summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2010-08-08 17:27:51 +0000
committerKrzysztof Kosiński <tweenk.pl@gmail.com>2010-08-08 17:27:51 +0000
commit60d3113d1f022a3de7cf04c7979d4751b3fe21f6 (patch)
treeca33e2a9a1af6b5911598fa1c6a1d77087b71dd2 /src/ui
parentMinor cleanups (diff)
parentAdd a constrained snap method that takes multiple constraints. This reduces t... (diff)
downloadinkscape-60d3113d1f022a3de7cf04c7979d4751b3fe21f6.tar.gz
inkscape-60d3113d1f022a3de7cf04c7979d4751b3fe21f6.zip
merge from trunk
(bzr r9508.1.52)
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/clipboard.cpp14
-rw-r--r--src/ui/dialog/align-and-distribute.cpp165
-rw-r--r--src/ui/dialog/align-and-distribute.h15
-rw-r--r--src/ui/dialog/dialog-manager.cpp6
-rw-r--r--src/ui/dialog/filter-effects-dialog.cpp25
-rw-r--r--src/ui/dialog/icon-preview.cpp134
-rw-r--r--src/ui/dialog/icon-preview.h3
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp9
-rw-r--r--src/ui/dialog/livepatheffect-editor.cpp4
-rw-r--r--src/ui/dialog/print-colors-preview-dialog.cpp3
-rw-r--r--src/ui/dialog/swatches.cpp199
-rw-r--r--src/ui/dialog/swatches.h3
-rw-r--r--src/ui/icon-names.h6
-rw-r--r--src/ui/tool/control-point-selection.cpp48
-rw-r--r--src/ui/tool/control-point-selection.h7
-rw-r--r--src/ui/tool/node.cpp112
-rw-r--r--src/ui/uxmanager.cpp2
17 files changed, 550 insertions, 205 deletions
diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp
index 9ce2ac5ba..0a64e7fa7 100644
--- a/src/ui/clipboard.cpp
+++ b/src/ui/clipboard.cpp
@@ -653,23 +653,23 @@ void ClipboardManagerImpl::_copySelection(Inkscape::Selection *selection)
void ClipboardManagerImpl::_copyUsedDefs(SPItem *item)
{
// copy fill and stroke styles (patterns and gradients)
- SPStyle *style = SP_OBJECT_STYLE(item);
+ SPStyle *style = item->style;
if (style && (style->fill.isPaintserver())) {
- SPObject *server = SP_OBJECT_STYLE_FILL_SERVER(item);
- if (SP_IS_LINEARGRADIENT(server) || SP_IS_RADIALGRADIENT(server)) {
+ SPPaintServer *server = item->style->getFillPaintServer();
+ if ( SP_IS_LINEARGRADIENT(server) || SP_IS_RADIALGRADIENT(server) ) {
_copyGradient(SP_GRADIENT(server));
}
- if (SP_IS_PATTERN(server)) {
+ if ( SP_IS_PATTERN(server) ) {
_copyPattern(SP_PATTERN(server));
}
}
if (style && (style->stroke.isPaintserver())) {
- SPObject *server = SP_OBJECT_STYLE_STROKE_SERVER(item);
- if (SP_IS_LINEARGRADIENT(server) || SP_IS_RADIALGRADIENT(server)) {
+ SPPaintServer *server = item->style->getStrokePaintServer();
+ if ( SP_IS_LINEARGRADIENT(server) || SP_IS_RADIALGRADIENT(server) ) {
_copyGradient(SP_GRADIENT(server));
}
- if (SP_IS_PATTERN(server)) {
+ if ( SP_IS_PATTERN(server) ) {
_copyPattern(SP_PATTERN(server));
}
}
diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp
index a75a8d68d..048c46a20 100644
--- a/src/ui/dialog/align-and-distribute.cpp
+++ b/src/ui/dialog/align-and-distribute.cpp
@@ -518,8 +518,8 @@ public:
guint row,
guint column,
AlignAndDistribute &dialog) :
- Action(id, tiptext, row, column + 4,
- dialog.graphLayout_table(), dialog.tooltips(), dialog)
+ Action(id, tiptext, row, column,
+ dialog.rearrange_table(), dialog.tooltips(), dialog)
{}
private :
@@ -542,6 +542,101 @@ private :
}
};
+class ActionExchangePositions : public Action {
+public:
+ enum SortOrder {
+ None,
+ ZOrder,
+ Clockwise
+ };
+
+ ActionExchangePositions(Glib::ustring const &id,
+ Glib::ustring const &tiptext,
+ guint row,
+ guint column,
+ AlignAndDistribute &dialog, SortOrder order = None) :
+ Action(id, tiptext, row, column,
+ dialog.rearrange_table(), dialog.tooltips(), dialog),
+ sortOrder(order)
+ {};
+
+
+private :
+ const SortOrder sortOrder;
+ static boost::optional<Geom::Point> center;
+
+ static bool sort_compare(const SPItem * a,const SPItem * b) {
+ if (a == NULL) return false;
+ if (b == NULL) return true;
+ if (center) {
+ Geom::Point point_a = a->getCenter() - (*center);
+ Geom::Point point_b = b->getCenter() - (*center);
+ // First criteria: Sort according to the angle to the center point
+ double angle_a = atan2(double(point_a[Geom::Y]), double(point_a[Geom::X]));
+ double angle_b = atan2(double(point_b[Geom::Y]), double(point_b[Geom::X]));
+ if (angle_a != angle_b) return (angle_a < angle_b);
+ // Second criteria: Sort according to the distance the center point
+ Geom::Coord length_a = point_a.length();
+ Geom::Coord length_b = point_b.length();
+ if (length_a != length_b) return (length_a > length_b);
+ }
+ // Last criteria: Sort according to the z-coordinate
+ return (a->isSiblingOf(b));
+ }
+
+ virtual void on_button_click()
+ {
+ SPDesktop *desktop = _dialog.getDesktop();
+ if (!desktop) return;
+
+ Inkscape::Selection *selection = sp_desktop_selection(desktop);
+ if (!selection) return;
+
+ using Inkscape::Util::GSListConstIterator;
+ std::list<SPItem *> selected;
+ selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
+ if (selected.empty()) return;
+
+ //Check 2 or more selected objects
+ if (selected.size() < 2) return;
+
+ // see comment in ActionAlign above
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
+ prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
+
+ // sort the list
+ if (sortOrder != None) {
+ if (sortOrder == Clockwise) {
+ center = selection->center();
+ } else { // sorting by ZOrder is outomatically done by not setting the center
+ center.reset();
+ }
+ selected.sort(ActionExchangePositions::sort_compare);
+ }
+ std::list<SPItem *>::iterator it(selected.begin());
+ Geom::Point p1 = (*it)->getCenter();
+ for (++it ;it != selected.end(); ++it)
+ {
+ Geom::Point p2 = (*it)->getCenter();
+ Geom::Point delta = p1 - p2;
+ sp_item_move_rel((*it),Geom::Translate(delta[Geom::X],delta[Geom::Y] ));
+ p1 = p2;
+ }
+ Geom::Point p2 = selected.front()->getCenter();
+ Geom::Point delta = p1 - p2;
+ sp_item_move_rel(selected.front(),Geom::Translate(delta[Geom::X],delta[Geom::Y] ));
+
+ // restore compensation setting
+ prefs->setInt("/options/clonecompensation/value", saved_compensation);
+
+ sp_document_done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
+ _("Exchange Positions"));
+ }
+};
+// instantiae the private static member
+boost::optional<Geom::Point> ActionExchangePositions::center;
+
class ActionUnclump : public Action {
public :
ActionUnclump(const Glib::ustring &id,
@@ -550,7 +645,7 @@ public :
guint column,
AlignAndDistribute &dialog):
Action(id, tiptext, row, column,
- dialog.distribute_table(), dialog.tooltips(), dialog)
+ dialog.rearrange_table(), dialog.tooltips(), dialog)
{}
private :
@@ -581,7 +676,7 @@ public :
guint column,
AlignAndDistribute &dialog):
Action(id, tiptext, row, column,
- dialog.distribute_table(), dialog.tooltips(), dialog)
+ dialog.rearrange_table(), dialog.tooltips(), dialog)
{}
private :
@@ -792,13 +887,13 @@ AlignAndDistribute::AlignAndDistribute()
randomize_bbox(),
_alignFrame(_("Align")),
_distributeFrame(_("Distribute")),
+ _rearrangeFrame(_("Rearrange")),
_removeOverlapFrame(_("Remove overlaps")),
- _graphLayoutFrame(_("Connector network layout")),
_nodesFrame(_("Nodes")),
_alignTable(2, 6, true),
- _distributeTable(3, 6, true),
+ _distributeTable(2, 6, true),
+ _rearrangeTable(1, 5, false),
_removeOverlapTable(1, 5, false),
- _graphLayoutTable(1, 5, false),
_nodesTable(1, 4, true),
_anchorLabel(_("Relative to: ")),
_selgrpLabel(_("Treat selection as group: "))
@@ -882,22 +977,33 @@ AlignAndDistribute::AlignAndDistribute()
_("Distribute baselines of texts vertically"),
1, 5, this->distribute_table(), Geom::Y, true);
+ // Rearrange
+ //Graph Layout
+ addGraphLayoutButton(INKSCAPE_ICON_DISTRIBUTE_GRAPH,
+ _("Nicely arrange selected connector network"),
+ 0, 0);
+ addExchangePositionsButton(INKSCAPE_ICON_EXCHANGE_POSITIONS,
+ _("Exchange positions of selected objects - selection order"),
+ 0, 1);
+ addExchangePositionsByZOrderButton(INKSCAPE_ICON_EXCHANGE_POSITIONS_ZORDER,
+ _("Exchange positions of selected objects - stacking order"),
+ 0, 2);
+ addExchangePositionsClockwiseButton(INKSCAPE_ICON_EXCHANGE_POSITIONS_CLOCKWISE,
+ _("Exchange positions of selected objects - clockwise rotate"),
+ 0, 3);
+
//Randomize & Unclump
addRandomizeButton(INKSCAPE_ICON_DISTRIBUTE_RANDOMIZE,
_("Randomize centers in both dimensions"),
- 2, 2);
+ 0, 4);
addUnclumpButton(INKSCAPE_ICON_DISTRIBUTE_UNCLUMP,
_("Unclump objects: try to equalize edge-to-edge distances"),
- 2, 4);
+ 0, 5);
//Remove overlaps
addRemoveOverlapsButton(INKSCAPE_ICON_DISTRIBUTE_REMOVE_OVERLAPS,
_("Move objects as little as possible so that their bounding boxes do not overlap"),
0, 0);
- //Graph Layout
- addGraphLayoutButton(INKSCAPE_ICON_DISTRIBUTE_GRAPH,
- _("Nicely arrange selected connector network"),
- 0, 0);
//Node Mode buttons
// NOTE: "align nodes vertically" means "move nodes vertically until they align on a common
@@ -943,8 +1049,8 @@ AlignAndDistribute::AlignAndDistribute()
_alignFrame.add(_alignBox);
_distributeFrame.add(_distributeTable);
+ _rearrangeFrame.add(_rearrangeTable);
_removeOverlapFrame.add(_removeOverlapTable);
- _graphLayoutFrame.add(_graphLayoutTable);
_nodesFrame.add(_nodesTable);
Gtk::Box *contents = _getContents();
@@ -954,8 +1060,8 @@ AlignAndDistribute::AlignAndDistribute()
contents->pack_start(_alignFrame, true, true);
contents->pack_start(_distributeFrame, true, true);
+ contents->pack_start(_rearrangeFrame, true, true);
contents->pack_start(_removeOverlapFrame, true, true);
- contents->pack_start(_graphLayoutFrame, true, true);
contents->pack_start(_nodesFrame, true, true);
//Connect to the global tool change signal
@@ -1010,8 +1116,8 @@ void AlignAndDistribute::setMode(bool nodeEdit)
((_alignFrame).*(mSel))();
((_distributeFrame).*(mSel))();
+ ((_rearrangeFrame).*(mSel))();
((_removeOverlapFrame).*(mSel))();
- ((_graphLayoutFrame).*(mSel))();
((_nodesFrame).*(mNode))();
}
@@ -1063,6 +1169,33 @@ void AlignAndDistribute::addGraphLayoutButton(const Glib::ustring &id, const Gli
);
}
+void AlignAndDistribute::addExchangePositionsButton(const Glib::ustring &id, const Glib::ustring tiptext,
+ guint row, guint col)
+{
+ _actionList.push_back(
+ new ActionExchangePositions(
+ id, tiptext, row, col, *this)
+ );
+}
+
+void AlignAndDistribute::addExchangePositionsByZOrderButton(const Glib::ustring &id, const Glib::ustring tiptext,
+ guint row, guint col)
+{
+ _actionList.push_back(
+ new ActionExchangePositions(
+ id, tiptext, row, col, *this, ActionExchangePositions::ZOrder)
+ );
+}
+
+void AlignAndDistribute::addExchangePositionsClockwiseButton(const Glib::ustring &id, const Glib::ustring tiptext,
+ guint row, guint col)
+{
+ _actionList.push_back(
+ new ActionExchangePositions(
+ id, tiptext, row, col, *this, ActionExchangePositions::Clockwise)
+ );
+}
+
void AlignAndDistribute::addUnclumpButton(const Glib::ustring &id, const Glib::ustring tiptext,
guint row, guint col)
{
diff --git a/src/ui/dialog/align-and-distribute.h b/src/ui/dialog/align-and-distribute.h
index 297b3d2a1..f55998385 100644
--- a/src/ui/dialog/align-and-distribute.h
+++ b/src/ui/dialog/align-and-distribute.h
@@ -55,8 +55,8 @@ public:
Gtk::Table &align_table(){return _alignTable;}
Gtk::Table &distribute_table(){return _distributeTable;}
+ Gtk::Table &rearrange_table(){return _rearrangeTable;}
Gtk::Table &removeOverlap_table(){return _removeOverlapTable;}
- Gtk::Table &graphLayout_table(){return _graphLayoutTable;}
Gtk::Table &nodes_table(){return _nodesTable;}
Gtk::Tooltips &tooltips(){return _tooltips;}
@@ -82,6 +82,15 @@ protected:
void addGraphLayoutButton(const Glib::ustring &id,
const Glib::ustring tiptext,
guint row, guint col);
+ void addExchangePositionsButton(const Glib::ustring &id,
+ const Glib::ustring tiptext,
+ guint row, guint col);
+ void addExchangePositionsByZOrderButton(const Glib::ustring &id,
+ const Glib::ustring tiptext,
+ guint row, guint col);
+ void addExchangePositionsClockwiseButton(const Glib::ustring &id,
+ const Glib::ustring tiptext,
+ guint row, guint col);
void addUnclumpButton(const Glib::ustring &id, const Glib::ustring tiptext,
guint row, guint col);
void addRandomizeButton(const Glib::ustring &id, const Glib::ustring tiptext,
@@ -90,8 +99,8 @@ protected:
guint row, guint col, Gtk::Table &table, Geom::Dim2 orientation, bool distribute);
std::list<Action *> _actionList;
- Gtk::Frame _alignFrame, _distributeFrame, _removeOverlapFrame, _graphLayoutFrame, _nodesFrame;
- Gtk::Table _alignTable, _distributeTable, _removeOverlapTable, _graphLayoutTable, _nodesTable;
+ Gtk::Frame _alignFrame, _distributeFrame, _rearrangeFrame, _removeOverlapFrame, _nodesFrame;
+ Gtk::Table _alignTable, _distributeTable, _rearrangeTable, _removeOverlapTable, _nodesTable;
Gtk::HBox _anchorBox;
Gtk::HBox _selgrpBox;
Gtk::VBox _alignBox;
diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp
index 6d3bc817e..aab9d89d7 100644
--- a/src/ui/dialog/dialog-manager.cpp
+++ b/src/ui/dialog/dialog-manager.cpp
@@ -41,7 +41,7 @@
#include "ui/dialog/icon-preview.h"
#include "ui/dialog/floating-behavior.h"
#include "ui/dialog/dock-behavior.h"
-#include "ui/dialog/print-colors-preview-dialog.h"
+//#include "ui/dialog/print-colors-preview-dialog.h"
#include "preferences.h"
#ifdef ENABLE_SVG_FONTS
@@ -104,7 +104,7 @@ DialogManager::DialogManager() {
registerFactory("LivePathEffect", &create<LivePathEffectEditor, FloatingBehavior>);
registerFactory("Memory", &create<Memory, FloatingBehavior>);
registerFactory("Messages", &create<Messages, FloatingBehavior>);
- registerFactory("PrintColorsPreviewDialog", &create<PrintColorsPreviewDialog, FloatingBehavior>);
+// registerFactory("PrintColorsPreviewDialog", &create<PrintColorsPreviewDialog, FloatingBehavior>);
registerFactory("Script", &create<ScriptDialog, FloatingBehavior>);
#ifdef ENABLE_SVG_FONTS
registerFactory("SvgFontsDialog", &create<SvgFontsDialog, FloatingBehavior>);
@@ -132,7 +132,7 @@ DialogManager::DialogManager() {
registerFactory("LivePathEffect", &create<LivePathEffectEditor, DockBehavior>);
registerFactory("Memory", &create<Memory, DockBehavior>);
registerFactory("Messages", &create<Messages, DockBehavior>);
- registerFactory("PrintColorsPreviewDialog", &create<PrintColorsPreviewDialog, DockBehavior>);
+// registerFactory("PrintColorsPreviewDialog", &create<PrintColorsPreviewDialog, DockBehavior>);
registerFactory("Script", &create<ScriptDialog, DockBehavior>);
#ifdef ENABLE_SVG_FONTS
registerFactory("SvgFontsDialog", &create<SvgFontsDialog, DockBehavior>);
diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp
index 4ec719bf4..dab42d897 100644
--- a/src/ui/dialog/filter-effects-dialog.cpp
+++ b/src/ui/dialog/filter-effects-dialog.cpp
@@ -176,7 +176,7 @@ public:
if (tip_text) {
_tt.set_tip(*this, tip_text);
}
- combo = new ComboBoxEnum<T>(default_value, c, a);
+ combo = new ComboBoxEnum<T>(default_value, c, a, false);
add(*combo);
show_all();
}
@@ -2177,13 +2177,14 @@ void FilterEffectsDialog::init_settings_widgets()
_settings->type(NR_FILTER_COMPONENTTRANSFER);
_settings->add_notimplemented();
+ /*
//TRANSLATORS: for info on "Slope" and "Intercept", see http://id.mind.net/~zona/mmts/functionInstitute/linearFunctions/lsif.html
- /*_settings->add_combo(COMPONENTTRANSFER_TYPE_IDENTITY, SP_ATTR_TYPE, _("Type"), ComponentTransferTypeConverter);
- _ct_slope = _settings->add_spinslider(SP_ATTR_SLOPE, _("Slope"), -100, 100, 1, 0.01, 1);
- _ct_intercept = _settings->add_spinslider(SP_ATTR_INTERCEPT, _("Intercept"), -100, 100, 1, 0.01, 1);
- _ct_amplitude = _settings->add_spinslider(SP_ATTR_AMPLITUDE, _("Amplitude"), 0, 100, 1, 0.01, 1);
- _ct_exponent = _settings->add_spinslider(SP_ATTR_EXPONENT, _("Exponent"), 0, 100, 1, 0.01, 1);
- _ct_offset = _settings->add_spinslider(SP_ATTR_OFFSET, _("Offset"), -100, 100, 1, 0.01, 1);*/
+ _settings->add_combo(COMPONENTTRANSFER_TYPE_IDENTITY, SP_ATTR_TYPE, _("Type"), ComponentTransferTypeConverter);
+ _ct_slope = _settings->add_spinslider(1, SP_ATTR_SLOPE, _("Slope"), -10, 10, 0.1, 0.01, 2);
+ _ct_intercept = _settings->add_spinslider(0, SP_ATTR_INTERCEPT, _("Intercept"), -10, 10, 0.1, 0.01, 2);
+ _ct_amplitude = _settings->add_spinslider(1, SP_ATTR_AMPLITUDE, _("Amplitude"), 0, 10, 0.1, 0.01, 2);
+ _ct_exponent = _settings->add_spinslider(1, SP_ATTR_EXPONENT, _("Exponent"), 0, 10, 0.1, 0.01, 2);
+ _ct_offset = _settings->add_spinslider(0, SP_ATTR_OFFSET, _("Offset"), -10, 10, 0.1, 0.01, 2);*/
_settings->type(NR_FILTER_COMPOSITE);
_settings->add_combo(COMPOSITE_OVER, SP_ATTR_OPERATOR, _("Operator:"), CompositeOperatorConverter);
@@ -2205,8 +2206,8 @@ void FilterEffectsDialog::init_settings_widgets()
_settings->type(NR_FILTER_DIFFUSELIGHTING);
_settings->add_color(/*default: white*/ 0xffffffff, SP_PROP_LIGHTING_COLOR, _("Diffuse Color:"), _("Defines the color of the light source"));
- _settings->add_spinslider(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -1000, 1000, 1, 0.01, 1, _("This value amplifies the heights of the bump map defined by the input alpha channel"));
- _settings->add_spinslider(1, SP_ATTR_DIFFUSECONSTANT, _("Constant:"), 0, 100, 0.1, 0.01, 2, _("This constant affects the Phong lighting model."));
+ _settings->add_spinslider(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -5, 5, 0.01, 0.001, 3, _("This value amplifies the heights of the bump map defined by the input alpha channel"));
+ _settings->add_spinslider(1, SP_ATTR_DIFFUSECONSTANT, _("Constant:"), 0, 5, 0.1, 0.01, 2, _("This constant affects the Phong lighting model."));
_settings->add_dualspinslider(SP_ATTR_KERNELUNITLENGTH, _("Kernel Unit Length:"), 0.01, 10, 1, 0.01, 1);
_settings->add_lightsource();
@@ -2238,9 +2239,9 @@ void FilterEffectsDialog::init_settings_widgets()
_settings->type(NR_FILTER_SPECULARLIGHTING);
_settings->add_color(/*default: white*/ 0xffffffff, SP_PROP_LIGHTING_COLOR, _("Specular Color:"), _("Defines the color of the light source"));
- _settings->add_spinslider(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -1000, 1000, 1, 0.01, 1, _("This value amplifies the heights of the bump map defined by the input alpha channel"));
- _settings->add_spinslider(1, SP_ATTR_SPECULARCONSTANT, _("Constant:"), 0, 100, 0.1, 0.01, 2, _("This constant affects the Phong lighting model."));
- _settings->add_spinslider(1, SP_ATTR_SPECULAREXPONENT, _("Exponent:"), 1, 128, 1, 0.01, 1, _("Exponent for specular term, larger is more \"shiny\"."));
+ _settings->add_spinslider(1, SP_ATTR_SURFACESCALE, _("Surface Scale:"), -5, 5, 0.1, 0.01, 2, _("This value amplifies the heights of the bump map defined by the input alpha channel"));
+ _settings->add_spinslider(1, SP_ATTR_SPECULARCONSTANT, _("Constant:"), 0, 5, 0.1, 0.01, 2, _("This constant affects the Phong lighting model."));
+ _settings->add_spinslider(1, SP_ATTR_SPECULAREXPONENT, _("Exponent:"), 1, 50, 1, 0.01, 1, _("Exponent for specular term, larger is more \"shiny\"."));
_settings->add_dualspinslider(SP_ATTR_KERNELUNITLENGTH, _("Kernel Unit Length:"), 0.01, 10, 1, 0.01, 1);
_settings->add_lightsource();
diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp
index c7ed9f92b..02e8cda9c 100644
--- a/src/ui/dialog/icon-preview.cpp
+++ b/src/ui/dialog/icon-preview.cpp
@@ -41,6 +41,8 @@ sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root,
const gchar *name, unsigned int psize, unsigned &stride);
}
+#define noICON_VERBOSE 1
+
namespace Inkscape {
namespace UI {
namespace Dialog {
@@ -85,7 +87,10 @@ IconPreviewPanel::IconPreviewPanel() :
desktop(0),
document(0),
timer(0),
+ renderTimer(0),
pending(false),
+ minDelay(0.1),
+ targetId(),
hot(1),
selectionButton(0),
desktopChangeConn(),
@@ -96,6 +101,8 @@ IconPreviewPanel::IconPreviewPanel() :
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
numEntries = 0;
+ bool pack = prefs->getBool("/iconpreview/pack", true);
+
std::vector<Glib::ustring> pref_sizes = prefs->getAllDirs("/iconpreview/sizes/default");
std::vector<int> rawSizes;
@@ -169,10 +176,14 @@ IconPreviewPanel::IconPreviewPanel() :
Glib::ustring label(*labels[i]);
buttons[i] = new Gtk::ToggleToolButton(label);
buttons[i]->set_active( i == hot );
- Gtk::Frame *frame = new Gtk::Frame();
- frame->set_shadow_type(Gtk::SHADOW_ETCHED_IN);
- frame->add(*images[i]);
- buttons[i]->set_icon_widget(*Gtk::manage(frame));
+ if ( prefs->getBool("/iconpreview/showFrames", true) ) {
+ Gtk::Frame *frame = new Gtk::Frame();
+ frame->set_shadow_type(Gtk::SHADOW_ETCHED_IN);
+ frame->add(*images[i]);
+ buttons[i]->set_icon_widget(*Gtk::manage(frame));
+ } else {
+ buttons[i]->set_icon_widget(*images[i]);
+ }
tips.set_tip((*buttons[i]), label);
@@ -183,7 +194,7 @@ IconPreviewPanel::IconPreviewPanel() :
align->add(*buttons[i]);
int pad = 12;
- if ((avail == 0) && (previous == 0)) {
+ if ( !pack || ( (avail == 0) && (previous == 0) ) ) {
verts->pack_end(*align, Gtk::PACK_SHRINK);
previous = sizes[i];
avail = sizes[i];
@@ -243,6 +254,11 @@ IconPreviewPanel::~IconPreviewPanel()
delete timer;
timer = 0;
}
+ if ( renderTimer ) {
+ renderTimer->stop();
+ delete renderTimer;
+ renderTimer = 0;
+ }
selChangedConn.disconnect();
docModConn.disconnect();
@@ -256,6 +272,22 @@ IconPreviewPanel::~IconPreviewPanel()
//#########################################################################
+#if ICON_VERBOSE
+static Glib::ustring getTimestr()
+{
+ Glib::ustring str;
+ GTimeVal now = {0, 0};
+ g_get_current_time(&now);
+ glong secs = now.tv_sec % 60;
+ glong mins = (now.tv_sec / 60) % 60;
+ gchar *ptr = g_strdup_printf(":%02ld:%02ld.%06ld", mins, secs, now.tv_usec);
+ str = ptr;
+ g_free(ptr);
+ ptr = 0;
+ return str;
+}
+#endif // ICON_VERBOSE
+
void IconPreviewPanel::setDesktop( SPDesktop* desktop )
{
Panel::setDesktop(desktop);
@@ -269,7 +301,7 @@ void IconPreviewPanel::setDesktop( SPDesktop* desktop )
this->desktop = Panel::getDesktop();
if ( this->desktop ) {
docReplacedConn = this->desktop->connectDocumentReplaced(sigc::hide<0>(sigc::mem_fun(this, &IconPreviewPanel::setDocument)));
- if (this->desktop->selection) {
+ if ( this->desktop->selection && Inkscape::Preferences::get()->getBool("/iconpreview/autoRefresh", true) ) {
selChangedConn = desktop->selection->connectChanged(sigc::hide(sigc::mem_fun(this, &IconPreviewPanel::queueRefresh)));
}
}
@@ -285,7 +317,9 @@ void IconPreviewPanel::setDocument( SPDocument *document )
this->document = document;
if (this->document) {
- docModConn = this->document->connectModified(sigc::hide(sigc::mem_fun(this, &IconPreviewPanel::queueRefresh)));
+ if ( Inkscape::Preferences::get()->getBool("/iconpreview/autoRefresh", true) ) {
+ docModConn = this->document->connectModified(sigc::hide(sigc::mem_fun(this, &IconPreviewPanel::queueRefresh)));
+ }
queueRefresh();
}
}
@@ -297,38 +331,50 @@ void IconPreviewPanel::refreshPreview()
if (!timer) {
timer = new Glib::Timer();
}
- if (timer->elapsed() < 0.1) {
+ if (timer->elapsed() < minDelay) {
+#if ICON_VERBOSE
+ g_message( "%s Deferring refresh as too soon. calling queueRefresh()", getTimestr().c_str() );
+#endif //ICON_VERBOSE
// Do not refresh too quickly
queueRefresh();
} else if ( desktop ) {
+#if ICON_VERBOSE
+ g_message( "%s Refreshing preview.", getTimestr().c_str() );
+#endif // ICON_VERBOSE
+ bool hold = Inkscape::Preferences::get()->getBool("/iconpreview/selectionHold", true);
+ SPObject *target = 0;
if ( selectionButton && selectionButton->get_active() )
{
- Inkscape::Selection * sel = sp_desktop_selection(desktop);
- if ( sel ) {
- //g_message("found a selection to play with");
-
- GSList const *items = sel->itemList();
- SPObject *target = 0;
- while ( items && !target ) {
- SPItem* item = SP_ITEM( items->data );
- SPObject * obj = SP_OBJECT(item);
- gchar const *id = obj->getId();
- if ( id ) {
- target = obj;
+ target = (hold && !targetId.empty()) ? desktop->doc()->getObjectById( targetId.c_str() ) : 0;
+ if ( !target ) {
+ targetId.clear();
+ Inkscape::Selection * sel = sp_desktop_selection(desktop);
+ if ( sel ) {
+ //g_message("found a selection to play with");
+
+ GSList const *items = sel->itemList();
+ while ( items && !target ) {
+ SPItem* item = SP_ITEM( items->data );
+ SPObject * obj = SP_OBJECT(item);
+ gchar const *id = obj->getId();
+ if ( id ) {
+ targetId = id;
+ target = obj;
+ }
+
+ items = g_slist_next(items);
}
-
- items = g_slist_next(items);
- }
- if ( target ) {
- renderPreview(target);
}
}
} else {
- SPObject *target = desktop->currentRoot();
- if ( target ) {
- renderPreview(target);
- }
+ target = desktop->currentRoot();
}
+ if ( target ) {
+ renderPreview(target);
+ }
+#if ICON_VERBOSE
+ g_message( "%s resetting timer", getTimestr().c_str() );
+#endif // ICON_VERBOSE
timer->reset();
}
}
@@ -339,9 +385,15 @@ bool IconPreviewPanel::refreshCB()
if (!timer) {
timer = new Glib::Timer();
}
- if ( timer->elapsed() > 0.1 ) {
+ if ( timer->elapsed() > minDelay ) {
+#if ICON_VERBOSE
+ g_message( "%s refreshCB() timer has progressed", getTimestr().c_str() );
+#endif // ICON_VERBOSE
callAgain = false;
refreshPreview();
+#if ICON_VERBOSE
+ g_message( "%s refreshCB() setting pending false", getTimestr().c_str() );
+#endif // ICON_VERBOSE
pending = false;
}
return callAgain;
@@ -351,6 +403,9 @@ void IconPreviewPanel::queueRefresh()
{
if (!pending) {
pending = true;
+#if ICON_VERBOSE
+ g_message( "%s queueRefresh() Setting pending true", getTimestr().c_str() );
+#endif // ICON_VERBOSE
if (!timer) {
timer = new Glib::Timer();
}
@@ -361,7 +416,11 @@ void IconPreviewPanel::queueRefresh()
void IconPreviewPanel::modeToggled()
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setBool("/iconpreview/selectionOnly", (selectionButton && selectionButton->get_active()));
+ bool selectionOnly = (selectionButton && selectionButton->get_active());
+ prefs->setBool("/iconpreview/selectionOnly", selectionOnly);
+ if ( !selectionOnly ) {
+ targetId.clear();
+ }
refreshPreview();
}
@@ -370,8 +429,14 @@ void IconPreviewPanel::renderPreview( SPObject* obj )
{
SPDocument * doc = SP_OBJECT_DOCUMENT(obj);
gchar const * id = obj->getId();
+ if ( !renderTimer ) {
+ renderTimer = new Glib::Timer();
+ }
+ renderTimer->reset();
-// g_message(" setting up to render '%s' as the icon", id );
+#if ICON_VERBOSE
+ g_message("%s setting up to render '%s' as the icon", getTimestr().c_str(), id );
+#endif // ICON_VERBOSE
NRArenaItem *root = NULL;
@@ -402,6 +467,11 @@ void IconPreviewPanel::renderPreview( SPObject* obj )
sp_item_invoke_hide(SP_ITEM(sp_document_root(doc)), visionkey);
nr_object_unref((NRObject *) arena);
+ renderTimer->stop();
+ minDelay = std::max( 0.1, renderTimer->elapsed() * 3.0 );
+#if ICON_VERBOSE
+ g_message(" render took %f seconds.", renderTimer->elapsed());
+#endif // ICON_VERBOSE
}
void IconPreviewPanel::updateMagnify()
diff --git a/src/ui/dialog/icon-preview.h b/src/ui/dialog/icon-preview.h
index 9de882569..f8957086a 100644
--- a/src/ui/dialog/icon-preview.h
+++ b/src/ui/dialog/icon-preview.h
@@ -61,13 +61,16 @@ private:
SPDesktop *desktop;
SPDocument *document;
Glib::Timer *timer;
+ Glib::Timer *renderTimer;
bool pending;
+ gdouble minDelay;
Gtk::Tooltips tips;
Gtk::VBox iconBox;
Gtk::HPaned splitter;
+ Glib::ustring targetId;
int hot;
int numEntries;
int* sizes;
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index 3c48a7972..8f5194eda 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -540,8 +540,9 @@ void InkscapePreferences::initPageTools()
this->AddNewObjectsStyle(_page_eraser, "/tools/eraser");
//LPETool
- this->AddPage(_page_lpetool, _("LPE Tool"), iter_tools, PREFS_PAGE_TOOLS_LPETOOL);
- this->AddNewObjectsStyle(_page_lpetool, "/tools/lpetool");
+ // commented out, because the LPETool is not finished yet.
+ //this->AddPage(_page_lpetool, _("LPE Tool"), iter_tools, PREFS_PAGE_TOOLS_LPETOOL);
+ //this->AddNewObjectsStyle(_page_lpetool, "/tools/lpetool");
//Text
this->AddPage(_page_text, _("Text"), iter_tools, PREFS_PAGE_TOOLS_TEXT);
@@ -1116,11 +1117,11 @@ void InkscapePreferences::initPageUI()
_("Mongolian (mn)"), _("Nepali (ne)"), _("Norwegian Bokmål (nb)"), _("Norwegian Nynorsk (nn)"), _("Panjabi (pa)"),
_("Polish (pl)"), _("Portuguese (pt)"), _("Portuguese/Brazil (pt_BR)"), _("Romanian (ro)"), _("Russian (ru)"),
_("Serbian (sr)"), _("Serbian in Latin script (sr@latin)"), _("Slovak (sk)"), _("Slovenian (sl)"), _("Spanish (es)"), _("Spanish/Mexico (es_MX)"),
- _("Swedish (sv)"), _("Thai (th)"), _("Turkish (tr)"), _("Ukrainian (uk)"), _("Vietnamese (vi)")};
+ _("Swedish (sv)"),_("Telugu (te_IN)"), _("Thai (th)"), _("Turkish (tr)"), _("Ukrainian (uk)"), _("Vietnamese (vi)")};
Glib::ustring langValues[] = {"", "sq", "am", "ar", "hy", "az", "eu", "be", "bg", "bn", "br", "ca", "ca@valencia", "zh_CN", "zh_TW", "hr", "cs", "da", "nl",
"dz", "de", "el", "en", "en_AU", "en_CA", "en_GB", "en_US@piglatin", "eo", "et", "fa", "fi", "fr", "ga",
"gl", "he", "hu", "id", "it", "ja", "km", "rw", "ko", "lt", "mk", "mn", "ne", "nb", "nn", "pa",
- "pl", "pt", "pt_BR", "ro", "ru", "sr", "sr@latin", "sk", "sl", "es", "es_MX", "sv", "th", "tr", "uk", "vi" };
+ "pl", "pt", "pt_BR", "ro", "ru", "sr", "sr@latin", "sk", "sl", "es", "es_MX", "sv", "te_IN", "th", "tr", "uk", "vi" };
_ui_languages.init( "/ui/language", languages, langValues, G_N_ELEMENTS(languages), languages[0]);
_page_ui.add_line( false, _("Language (requires restart):"), _ui_languages, "",
diff --git a/src/ui/dialog/livepatheffect-editor.cpp b/src/ui/dialog/livepatheffect-editor.cpp
index 62ed4e639..fb24d8e72 100644
--- a/src/ui/dialog/livepatheffect-editor.cpp
+++ b/src/ui/dialog/livepatheffect-editor.cpp
@@ -299,6 +299,10 @@ LivePathEffectEditor::effect_list_reload(SPLPEItem *lpeitem)
PathEffectList::iterator it;
for( it = effectlist.begin() ; it!=effectlist.end(); it++ )
{
+ if ( !(*it)->lpeobject ) {
+ continue;
+ }
+
if ((*it)->lpeobject->get_lpe()) {
Gtk::TreeModel::Row row = *(effectlist_store->append());
row[columns.col_name] = (*it)->lpeobject->get_lpe()->getName();
diff --git a/src/ui/dialog/print-colors-preview-dialog.cpp b/src/ui/dialog/print-colors-preview-dialog.cpp
index f4d83c271..1f999f692 100644
--- a/src/ui/dialog/print-colors-preview-dialog.cpp
+++ b/src/ui/dialog/print-colors-preview-dialog.cpp
@@ -7,7 +7,7 @@
* Copyright (C) 2009 Authors
* Released under GNU GPLv2 (or later). Read the file 'COPYING' for more information.
*/
-
+/*
#include "desktop.h"
#include "print-colors-preview-dialog.h"
#include "preferences.h"
@@ -98,3 +98,4 @@ PrintColorsPreviewDialog::~PrintColorsPreviewDialog(){}
} // namespace Dialog
} // namespace UI
} // namespace Inkscape
+*/
diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp
index 163b49867..96910821e 100644
--- a/src/ui/dialog/swatches.cpp
+++ b/src/ui/dialog/swatches.cpp
@@ -14,6 +14,7 @@
#include <errno.h>
#include <map>
+#include <algorithm>
#include <gtk/gtkdialog.h> //for GTK_RESPONSE* types
#include <gtk/gtkdnd.h>
@@ -44,11 +45,12 @@
#include "swatches.h"
#include "style.h"
#include "ui/previewholder.h"
+#include "widgets/desktop-widget.h"
#include "widgets/gradient-vector.h"
#include "widgets/eek-preview.h"
#include "display/cairo-utils.h"
#include "sp-gradient-reference.h"
-
+#include "dialog-manager.h"
namespace Inkscape {
namespace UI {
@@ -68,6 +70,12 @@ static std::vector<DocTrack*> docTrackings;
static std::map<SwatchesPanel*, SPDocument*> docPerPanel;
+class SwatchesPanelHook : public SwatchesPanel
+{
+public:
+ static void convertGradient( GtkMenuItem *menuitem, gpointer userData );
+ static void deleteGradient( GtkMenuItem *menuitem, gpointer userData );
+};
static void handleClick( GtkWidget* /*widget*/, gpointer callback_data ) {
ColorItem* item = reinterpret_cast<ColorItem*>(callback_data);
@@ -84,6 +92,9 @@ static void handleSecondaryClick( GtkWidget* /*widget*/, gint /*arg1*/, gpointer
}
static GtkWidget* popupMenu = 0;
+static GtkWidget *popupSubHolder = 0;
+static GtkWidget *popupSub = 0;
+static std::vector<Glib::ustring> popupItems;
static std::vector<GtkWidget*> popupExtras;
static ColorItem* bounceTarget = 0;
static SwatchesPanel* bouncePanel = 0;
@@ -102,11 +113,37 @@ static void redirSecondaryClick( GtkMenuItem *menuitem, gpointer /*user_data*/ )
}
}
-static void editGradientImpl( SPGradient* gr )
+static void editGradientImpl( SPDesktop* desktop, SPGradient* gr )
{
if ( gr ) {
- GtkWidget *dialog = sp_gradient_vector_editor_new( gr );
- gtk_widget_show( dialog );
+ bool shown = false;
+ if ( desktop && desktop->doc() ) {
+ Inkscape::Selection *selection = sp_desktop_selection( desktop );
+ GSList const *items = selection->itemList();
+ if (items) {
+ SPStyle *query = sp_style_new( desktop->doc() );
+ int result = objects_query_fillstroke(const_cast<GSList *>(items), query, true);
+ if ( (result == QUERY_STYLE_MULTIPLE_SAME) || (result == QUERY_STYLE_SINGLE) ) {
+ // could be pertinent
+ if (query->fill.isPaintserver()) {
+ SPPaintServer* server = query->getFillPaintServer();
+ if ( SP_IS_GRADIENT(server) ) {
+ SPGradient* grad = SP_GRADIENT(server);
+ if ( grad->isSwatch() && grad->getId() == gr->getId()) {
+ desktop->_dlg_mgr->showDialog("FillAndStroke");
+ shown = true;
+ }
+ }
+ }
+ }
+ sp_style_unref(query);
+ }
+ }
+
+ if (!shown) {
+ GtkWidget *dialog = sp_gradient_vector_editor_new( gr );
+ gtk_widget_show( dialog );
+ }
}
}
@@ -122,7 +159,7 @@ static void editGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ )
for (const GSList *item = gradients; item; item = item->next) {
SPGradient* grad = SP_GRADIENT(item->data);
if ( targetName == grad->getId() ) {
- editGradientImpl( grad );
+ editGradientImpl( desktop, grad );
break;
}
}
@@ -130,31 +167,48 @@ static void editGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ )
}
}
-static void addNewGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ )
+void SwatchesPanelHook::convertGradient( GtkMenuItem * /*menuitem*/, gpointer userData )
{
if ( bounceTarget ) {
SwatchesPanel* swp = bouncePanel;
SPDesktop* desktop = swp ? swp->getDesktop() : 0;
SPDocument *doc = desktop ? desktop->doc() : 0;
- if (doc) {
- Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
-
- Inkscape::XML::Node *repr = xml_doc->createElement("svg:linearGradient");
- repr->setAttribute("osb:paint", "solid");
- Inkscape::XML::Node *stop = xml_doc->createElement("svg:stop");
- stop->setAttribute("offset", "0");
- stop->setAttribute("style", "stop-color:#000;stop-opacity:1;");
- repr->appendChild(stop);
- Inkscape::GC::release(stop);
-
- SP_OBJECT_REPR( SP_DOCUMENT_DEFS(doc) )->addChild(repr, NULL);
-
- SPGradient * gr = static_cast<SPGradient *>(doc->getObjectByRepr(repr));
-
- Inkscape::GC::release(repr);
+ gint index = GPOINTER_TO_INT(userData);
+ if ( doc && (index >= 0) && (static_cast<guint>(index) < popupItems.size()) ) {
+ Glib::ustring targetName = popupItems[index];
+ const GSList *gradients = sp_document_get_resource_list(doc, "gradient");
+ for (const GSList *item = gradients; item; item = item->next) {
+ SPGradient* grad = SP_GRADIENT(item->data);
+ if ( targetName == grad->getId() ) {
+ grad->setSwatch();
+ sp_document_done(doc, SP_VERB_CONTEXT_GRADIENT,
+ _("Add gradient stop"));
+ break;
+ }
+ }
+ }
+ }
+}
- editGradientImpl( gr );
+void SwatchesPanelHook::deleteGradient( GtkMenuItem */*menuitem*/, gpointer /*userData*/ )
+{
+ if ( bounceTarget ) {
+ SwatchesPanel* swp = bouncePanel;
+ SPDesktop* desktop = swp ? swp->getDesktop() : 0;
+ SPDocument *doc = desktop ? desktop->doc() : 0;
+ if (doc) {
+ std::string targetName(bounceTarget->def.descr);
+ const GSList *gradients = sp_document_get_resource_list(doc, "gradient");
+ for (const GSList *item = gradients; item; item = item->next) {
+ SPGradient* grad = SP_GRADIENT(item->data);
+ if ( targetName == grad->getId() ) {
+ grad->setSwatch(false);
+ sp_document_done(doc, SP_VERB_CONTEXT_GRADIENT,
+ _("Delete"));
+ break;
+ }
+ }
}
}
}
@@ -177,7 +231,12 @@ static SwatchesPanel* findContainingPanel( GtkWidget *widget )
return swp;
}
-gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data)
+static void removeit( GtkWidget *widget, gpointer data )
+{
+ gtk_container_remove( GTK_CONTAINER(data), widget );
+}
+
+gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data )
{
gboolean handled = FALSE;
@@ -209,17 +268,13 @@ gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, g
gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
popupExtras.push_back(child);
- child = gtk_menu_item_new_with_label(_("Add"));
+ child = gtk_menu_item_new_with_label(_("Delete"));
g_signal_connect( G_OBJECT(child),
"activate",
- G_CALLBACK(addNewGradient),
+ G_CALLBACK(SwatchesPanelHook::deleteGradient),
user_data );
gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
popupExtras.push_back(child);
-
- child = gtk_menu_item_new_with_label(_("Delete"));
- gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
- //popupExtras.push_back(child);
gtk_widget_set_sensitive( child, FALSE );
child = gtk_menu_item_new_with_label(_("Edit..."));
@@ -237,7 +292,12 @@ gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, g
child = gtk_menu_item_new_with_label(_("Convert"));
gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child);
//popupExtras.push_back(child);
- gtk_widget_set_sensitive( child, FALSE );
+ //gtk_widget_set_sensitive( child, FALSE );
+ {
+ popupSubHolder = child;
+ popupSub = gtk_menu_new();
+ gtk_menu_item_set_submenu( GTK_MENU_ITEM(child), popupSub );
+ }
gtk_widget_show_all(popupMenu);
}
@@ -251,7 +311,39 @@ gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, g
bounceTarget = item;
bouncePanel = swp;
+ popupItems.clear();
if ( popupMenu ) {
+ gtk_container_foreach(GTK_CONTAINER(popupSub), removeit, popupSub);
+ bool processed = false;
+ GtkWidget *wdgt = gtk_widget_get_ancestor(widget, SP_TYPE_DESKTOP_WIDGET);
+ if ( wdgt ) {
+ SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(wdgt);
+ if ( dtw && dtw->desktop ) {
+ // Pick up all gradients with vectors
+ const GSList *gradients = sp_document_get_resource_list(dtw->desktop->doc(), "gradient");
+ gint index = 0;
+ for (const GSList *curr = gradients; curr; curr = curr->next) {
+ SPGradient* grad = SP_GRADIENT(curr->data);
+ if ( grad->hasStops() && !grad->isSwatch() ) {
+ //gl = g_slist_prepend(gl, curr->data);
+ processed = true;
+ GtkWidget *child = gtk_menu_item_new_with_label(grad->getId());
+ gtk_menu_shell_append(GTK_MENU_SHELL(popupSub), child);
+
+ popupItems.push_back(grad->getId());
+ g_signal_connect( G_OBJECT(child),
+ "activate",
+ G_CALLBACK(SwatchesPanelHook::convertGradient),
+ GINT_TO_POINTER(index) );
+ index++;
+ }
+ }
+
+ gtk_widget_show_all(popupSub);
+ }
+ }
+ gtk_widget_set_sensitive( popupSubHolder, processed );
+
gtk_menu_popup(GTK_MENU(popupMenu), NULL, NULL, NULL, NULL, event->button, event->time);
handled = TRUE;
}
@@ -728,9 +820,11 @@ static void recalcSwatchContents(SPDocument* doc,
}
if ( !newList.empty() ) {
+ std::reverse(newList.begin(), newList.end());
for ( std::vector<SPGradient*>::iterator it = newList.begin(); it != newList.end(); ++it )
{
SPGradient* grad = *it;
+
cairo_surface_t *preview = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
PREVIEW_PIXBUF_WIDTH, VBLOCK);
cairo_t *ct = cairo_create(preview);
@@ -807,21 +901,25 @@ void SwatchesPanel::handleDefsModified(SPDocument *document)
std::map<ColorItem*, SPGradient*> tmpGrads;
recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads);
- int cap = std::min(docPalette->_colors.size(), tmpColors.size());
- for (int i = 0; i < cap; i++) {
- ColorItem* newColor = tmpColors[i];
- ColorItem* oldColor = docPalette->_colors[i];
- if ( (newColor->def.getType() != oldColor->def.getType()) ||
- (newColor->def.getR() != oldColor->def.getR()) ||
- (newColor->def.getG() != oldColor->def.getG()) ||
- (newColor->def.getB() != oldColor->def.getB()) ) {
- oldColor->def.setRGB(newColor->def.getR(), newColor->def.getG(), newColor->def.getB());
- }
- if (tmpGrads.find(newColor) != tmpGrads.end()) {
- oldColor->setGradient(tmpGrads[newColor]);
- }
- if ( tmpPrevs.find(newColor) != tmpPrevs.end() ) {
- oldColor->setPattern(tmpPrevs[newColor]);
+ if ( tmpColors.size() != docPalette->_colors.size() ) {
+ handleGradientsChange(document);
+ } else {
+ int cap = std::min(docPalette->_colors.size(), tmpColors.size());
+ for (int i = 0; i < cap; i++) {
+ ColorItem* newColor = tmpColors[i];
+ ColorItem* oldColor = docPalette->_colors[i];
+ if ( (newColor->def.getType() != oldColor->def.getType()) ||
+ (newColor->def.getR() != oldColor->def.getR()) ||
+ (newColor->def.getG() != oldColor->def.getG()) ||
+ (newColor->def.getB() != oldColor->def.getB()) ) {
+ oldColor->def.setRGB(newColor->def.getR(), newColor->def.getG(), newColor->def.getB());
+ }
+ if (tmpGrads.find(newColor) != tmpGrads.end()) {
+ oldColor->setGradient(tmpGrads[newColor]);
+ }
+ if ( tmpPrevs.find(newColor) != tmpPrevs.end() ) {
+ oldColor->setPattern(tmpPrevs[newColor]);
+ }
}
}
@@ -865,11 +963,12 @@ void SwatchesPanel::_updateFromSelection()
if ( SP_IS_GRADIENT(server) ) {
SPGradient* target = 0;
SPGradient* grad = SP_GRADIENT(server);
- if (grad->repr->attribute("osb:paint")) {
+
+ if ( grad->isSwatch() ) {
target = grad;
} else if ( grad->ref ) {
SPGradient *tmp = grad->ref->getObject();
- if ( tmp && tmp->repr->attribute("osb:paint") ) {
+ if ( tmp && tmp->isSwatch() ) {
target = tmp;
}
}
@@ -896,11 +995,11 @@ void SwatchesPanel::_updateFromSelection()
if ( SP_IS_GRADIENT(server) ) {
SPGradient* target = 0;
SPGradient* grad = SP_GRADIENT(server);
- if (grad->repr->attribute("osb:paint")) {
+ if ( grad->isSwatch() ) {
target = grad;
} else if ( grad->ref ) {
SPGradient *tmp = grad->ref->getObject();
- if ( tmp && tmp->repr->attribute("osb:paint") ) {
+ if ( tmp && tmp->isSwatch() ) {
target = tmp;
}
}
diff --git a/src/ui/dialog/swatches.h b/src/ui/dialog/swatches.h
index b18fd6cad..93bbe81d8 100644
--- a/src/ui/dialog/swatches.h
+++ b/src/ui/dialog/swatches.h
@@ -43,6 +43,8 @@ public:
virtual int getSelectedIndex() {return _currentIndex;} // temporary
protected:
+ static void handleGradientsChange(SPDocument *document);
+
virtual void _updateFromSelection();
virtual void _handleAction( int setId, int itemId );
virtual void _setDocument( SPDocument *document );
@@ -55,7 +57,6 @@ private:
SwatchesPanel &operator=(SwatchesPanel const &); // no assign
static void _trackDocument( SwatchesPanel *panel, SPDocument *document );
- static void handleGradientsChange(SPDocument *document);
static void handleDefsModified(SPDocument *document);
PreviewHolder* _holder;
diff --git a/src/ui/icon-names.h b/src/ui/icon-names.h
index d36d4a41a..92fd86a48 100644
--- a/src/ui/icon-names.h
+++ b/src/ui/icon-names.h
@@ -206,6 +206,12 @@
"edit-select-original"
#define INKSCAPE_ICON_EDIT_UNDO_HISTORY \
"edit-undo-history"
+#define INKSCAPE_ICON_EXCHANGE_POSITIONS \
+ "exchange-positions"
+#define INKSCAPE_ICON_EXCHANGE_POSITIONS_ZORDER \
+ "exchange-positions-zorder"
+#define INKSCAPE_ICON_EXCHANGE_POSITIONS_CLOCKWISE \
+ "exchange-positions-clockwise"
#define INKSCAPE_ICON_FILL_RULE_EVEN_ODD \
"fill-rule-even-odd"
#define INKSCAPE_ICON_FILL_RULE_NONZERO \
diff --git a/src/ui/tool/control-point-selection.cpp b/src/ui/tool/control-point-selection.cpp
index f880d2ddf..615587eeb 100644
--- a/src/ui/tool/control-point-selection.cpp
+++ b/src/ui/tool/control-point-selection.cpp
@@ -273,8 +273,11 @@ void ControlPointSelection::_pointGrabbed(SelectableControlPoint *point)
_grabbed_point = point;
_farthest_point = point;
double maxdist = 0;
+ Geom::Matrix m;
+ m.setIdentity();
for (iterator i = _points.begin(); i != _points.end(); ++i) {
_original_positions.insert(std::make_pair(*i, (*i)->position()));
+ _last_trans.insert(std::make_pair(*i, m));
double dist = Geom::distance(*_grabbed_point, **i);
if (dist > maxdist) {
maxdist = dist;
@@ -288,12 +291,52 @@ void ControlPointSelection::_pointDragged(Geom::Point &new_pos, GdkEventMotion *
Geom::Point abs_delta = new_pos - _original_positions[_grabbed_point];
double fdist = Geom::distance(_original_positions[_grabbed_point], _original_positions[_farthest_point]);
if (held_alt(*event) && fdist > 0) {
- // sculpting
+ // Sculpting
for (iterator i = _points.begin(); i != _points.end(); ++i) {
SelectableControlPoint *cur = (*i);
+ Geom::Matrix trans;
+ trans.setIdentity();
double dist = Geom::distance(_original_positions[cur], _original_positions[_grabbed_point]);
double deltafrac = 0.5 + 0.5 * cos(M_PI * dist/fdist);
- cur->move(_original_positions[cur] + abs_delta * deltafrac);
+ if (dist != 0.0) {
+ // The sculpting transformation is not affine, but it can be
+ // locally approximated by one. Here we compute the local
+ // affine approximation of the sculpting transformation near
+ // the currently transformed point. We then transform the point
+ // by this approximation. This gives us sensible behavior for node handles.
+ // NOTE: probably it would be better to transform the node handles,
+ // but ControlPointSelection is supposed to work for any
+ // SelectableControlPoints, not only Nodes. We could create a specialized
+ // NodeSelection class that inherits from this one and move sculpting there.
+ Geom::Point origdx(Geom::EPSILON, 0);
+ Geom::Point origdy(0, Geom::EPSILON);
+ Geom::Point origp = _original_positions[cur];
+ Geom::Point origpx = _original_positions[cur] + origdx;
+ Geom::Point origpy = _original_positions[cur] + origdy;
+ double distdx = Geom::distance(origpx, _original_positions[_grabbed_point]);
+ double distdy = Geom::distance(origpy, _original_positions[_grabbed_point]);
+ double deltafracdx = 0.5 + 0.5 * cos(M_PI * distdx/fdist);
+ double deltafracdy = 0.5 + 0.5 * cos(M_PI * distdy/fdist);
+ Geom::Point newp = origp + abs_delta * deltafrac;
+ Geom::Point newpx = origpx + abs_delta * deltafracdx;
+ Geom::Point newpy = origpy + abs_delta * deltafracdy;
+ Geom::Point newdx = (newpx - newp) / Geom::EPSILON;
+ Geom::Point newdy = (newpy - newp) / Geom::EPSILON;
+
+ Geom::Matrix itrans(newdx[Geom::X], newdx[Geom::Y], newdy[Geom::X], newdy[Geom::Y], 0, 0);
+ if (itrans.isSingular())
+ itrans.setIdentity();
+
+ trans *= Geom::Translate(-cur->position());
+ trans *= _last_trans[cur].inverse();
+ trans *= itrans;
+ trans *= Geom::Translate(_original_positions[cur] + abs_delta * deltafrac);
+ _last_trans[cur] = itrans;
+ } else {
+ trans *= Geom::Translate(-cur->position() + _original_positions[cur] + abs_delta * deltafrac);
+ }
+ cur->transform(trans);
+ //cur->move(_original_positions[cur] + abs_delta * deltafrac);
}
} else {
Geom::Point delta = new_pos - _grabbed_point->position();
@@ -309,6 +352,7 @@ void ControlPointSelection::_pointDragged(Geom::Point &new_pos, GdkEventMotion *
void ControlPointSelection::_pointUngrabbed()
{
_original_positions.clear();
+ _last_trans.clear();
_dragging = false;
_grabbed_point = _farthest_point = NULL;
_updateBounds();
diff --git a/src/ui/tool/control-point-selection.h b/src/ui/tool/control-point-selection.h
index 514ecb2e3..8023c3e28 100644
--- a/src/ui/tool/control-point-selection.h
+++ b/src/ui/tool/control-point-selection.h
@@ -1,5 +1,5 @@
/** @file
- * Node selection - stores a set of nodes and applies transformations
+ * Control point selection - stores a set of control points and applies transformations
* to them
*/
/* Authors:
@@ -9,8 +9,8 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#ifndef SEEN_UI_TOOL_NODE_SELECTION_H
-#define SEEN_UI_TOOL_NODE_SELECTION_H
+#ifndef SEEN_UI_TOOL_CONTROL_POINT_SELECTION_H
+#define SEEN_UI_TOOL_CONTROL_POINT_SELECTION_H
#include <memory>
#include <boost/optional.hpp>
@@ -132,6 +132,7 @@ private:
set_type _points;
set_type _all_points;
INK_UNORDERED_MAP<SelectableControlPoint *, Geom::Point> _original_positions;
+ INK_UNORDERED_MAP<SelectableControlPoint *, Geom::Matrix> _last_trans;
boost::optional<double> _rot_radius;
boost::optional<double> _mouseover_rot_radius;
Geom::OptRect _bounds;
diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp
index 9c9c58ff1..a8582ccc5 100644
--- a/src/ui/tool/node.cpp
+++ b/src/ui/tool/node.cpp
@@ -266,13 +266,11 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event)
Node *node_away = (this == &_parent->_front ? _parent->_prev() : _parent->_next());
if (_parent->type() == NODE_SMOOTH && Node::_is_line_segment(_parent, node_away)) {
- Inkscape::Snapper::ConstraintLine cl(_parent->position(),
+ Inkscape::Snapper::SnapConstraint cl(_parent->position(),
_parent->position() - node_away->position());
Inkscape::SnappedPoint p;
p = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, SNAPSOURCE_NODE_HANDLE), cl);
- if (p.getSnapped()) {
- p.getPoint(new_pos);
- }
+ new_pos = p.getPoint();
} else {
sm.freeSnapReturnByRef(new_pos, SNAPSOURCE_NODE_HANDLE);
}
@@ -945,7 +943,7 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event)
// For a note on how snapping is implemented in Inkscape, see snap.h.
SnapManager &sm = _desktop->namedview->snap_manager;
bool snap = sm.someSnapperMightSnap();
- std::vector<Inkscape::SnapCandidatePoint> unselected;
+ Inkscape::SnappedPoint sp;
if (snap) {
/* setup
* TODO We are doing this every time a snap happens. It should once be done only once
@@ -955,6 +953,7 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event)
* TODO Snapping to unselected segments of selected paths doesn't work yet. */
// Build the list of unselected nodes.
+ std::vector<Inkscape::SnapCandidatePoint> unselected;
typedef ControlPointSelection::Set Set;
Set &nodes = _selection.allPoints();
for (Set::iterator i = nodes.begin(); i != nodes.end(); ++i) {
@@ -964,17 +963,22 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event)
unselected.push_back(p);
}
}
- sm.setupIgnoreSelection(_desktop, false, &unselected);
+ sm.setupIgnoreSelection(_desktop, true, &unselected);
}
if (held_control(*event)) {
Geom::Point origin = _last_drag_origin();
- Inkscape::SnappedPoint fp, bp;
+ std::vector<Inkscape::Snapper::SnapConstraint> constraints;
if (held_alt(*event)) {
// with Ctrl+Alt, constrain to handle lines
- // project the new position onto a handle line that is closer
- boost::optional<Geom::Point> front_point, back_point;
- boost::optional<Inkscape::Snapper::ConstraintLine> line_front, line_back;
+ // project the new position onto a handle line that is closer;
+ // also snap to perpendiculars of handle lines
+
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int snaps = prefs->getIntLimited("/options/rotationsnapsperpi/value", 12, 1, 1000);
+ double min_angle = M_PI / snaps;
+
+ boost::optional<Geom::Point> front_point, back_point, fperp_point, bperp_point;
if (_front.isDegenerate()) {
if (_is_line_segment(this, _next()))
front_point = _next()->position() - origin;
@@ -987,72 +991,40 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event)
} else {
back_point = _back.relativePos();
}
- if (front_point)
- line_front = Inkscape::Snapper::ConstraintLine(origin, *front_point);
- if (back_point)
- line_back = Inkscape::Snapper::ConstraintLine(origin, *back_point);
-
- // TODO: combine the snap and non-snap branches by modifying snap.h / snap.cpp
- if (snap) {
- if (line_front) {
- fp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos,
- _snapSourceType()), *line_front);
- }
- if (line_back) {
- bp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos,
- _snapSourceType()), *line_back);
- }
+ if (front_point) {
+ constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, *front_point));
+ fperp_point = Geom::rot90(*front_point);
}
- if (fp.getSnapped() || bp.getSnapped()) {
- if (fp.isOtherSnapBetter(bp, false)) {
- fp = bp;
- }
- fp.getPoint(new_pos);
- _desktop->snapindicator->set_new_snaptarget(fp);
- } else {
- boost::optional<Geom::Point> pos;
- if (line_front) {
- pos = line_front->projection(new_pos);
- }
- if (line_back) {
- Geom::Point pos2 = line_back->projection(new_pos);
- if (!pos || (pos && Geom::distance(new_pos, *pos) > Geom::distance(new_pos, pos2)))
- pos = pos2;
- }
- if (pos) {
- new_pos = *pos;
- } else {
- new_pos = origin;
- }
+ if (back_point) {
+ constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, *back_point));
+ bperp_point = Geom::rot90(*back_point);
}
- } else {
- // with Ctrl, constrain to axes
- // TODO combine the two branches
- if (snap) {
- Inkscape::Snapper::ConstraintLine line_x(origin, Geom::Point(1, 0));
- Inkscape::Snapper::ConstraintLine line_y(origin, Geom::Point(0, 1));
- fp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), line_x);
- bp = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), line_y);
+ // perpendiculars only snap when they are further than snap increment away
+ // from the second handle constraint
+ if (fperp_point && (!back_point ||
+ (fabs(Geom::angle_between(*fperp_point, *back_point)) > min_angle &&
+ fabs(Geom::angle_between(*fperp_point, *back_point)) < M_PI - min_angle)))
+ {
+ constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, *fperp_point));
}
- if (fp.getSnapped() || bp.getSnapped()) {
- if (fp.isOtherSnapBetter(bp, false)) {
- fp = bp;
- }
- fp.getPoint(new_pos);
- _desktop->snapindicator->set_new_snaptarget(fp);
- } else {
- Geom::Point origin = _last_drag_origin();
- Geom::Point delta = new_pos - origin;
- Geom::Dim2 d = (fabs(delta[Geom::X]) < fabs(delta[Geom::Y])) ? Geom::X : Geom::Y;
- new_pos[d] = origin[d];
+ if (bperp_point && (!front_point ||
+ (fabs(Geom::angle_between(*bperp_point, *front_point)) > min_angle &&
+ fabs(Geom::angle_between(*bperp_point, *front_point)) < M_PI - min_angle)))
+ {
+ constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, *bperp_point));
}
+
+ sp = sm.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), constraints);
+ } else {
+ // with Ctrl, constrain to axes
+ constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, Geom::Point(1, 0)));
+ constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, Geom::Point(0, 1)));
+ sp = sm.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()), constraints);
}
+ new_pos = sp.getPoint();
} else if (snap) {
- Inkscape::SnappedPoint p = sm.freeSnap(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()));
- if (p.getSnapped()) {
- p.getPoint(new_pos);
- _desktop->snapindicator->set_new_snaptarget(p);
- }
+ sp = sm.freeSnap(Inkscape::SnapCandidatePoint(new_pos, _snapSourceType()));
+ new_pos = sp.getPoint();
}
SelectableControlPoint::dragged(new_pos, event);
diff --git a/src/ui/uxmanager.cpp b/src/ui/uxmanager.cpp
index fbe000de9..a3ccb3471 100644
--- a/src/ui/uxmanager.cpp
+++ b/src/ui/uxmanager.cpp
@@ -131,7 +131,7 @@ UXManagerImpl::UXManagerImpl() :
int width = defaultScreen->get_width();
int height = defaultScreen->get_height();
gdouble aspect = static_cast<gdouble>(width) / static_cast<gdouble>(height);
- if (aspect > 1.4) {
+ if (aspect > 1.65) {
_widescreen = true;
}
}