diff options
| author | Krzysztof Kosi??ski <tweenk.pl@gmail.com> | 2010-08-08 17:27:51 +0000 |
|---|---|---|
| committer | Krzysztof Kosiński <tweenk.pl@gmail.com> | 2010-08-08 17:27:51 +0000 |
| commit | 60d3113d1f022a3de7cf04c7979d4751b3fe21f6 (patch) | |
| tree | ca33e2a9a1af6b5911598fa1c6a1d77087b71dd2 /src/ui | |
| parent | Minor cleanups (diff) | |
| parent | Add a constrained snap method that takes multiple constraints. This reduces t... (diff) | |
| download | inkscape-60d3113d1f022a3de7cf04c7979d4751b3fe21f6.tar.gz inkscape-60d3113d1f022a3de7cf04c7979d4751b3fe21f6.zip | |
merge from trunk
(bzr r9508.1.52)
Diffstat (limited to 'src/ui')
| -rw-r--r-- | src/ui/clipboard.cpp | 14 | ||||
| -rw-r--r-- | src/ui/dialog/align-and-distribute.cpp | 165 | ||||
| -rw-r--r-- | src/ui/dialog/align-and-distribute.h | 15 | ||||
| -rw-r--r-- | src/ui/dialog/dialog-manager.cpp | 6 | ||||
| -rw-r--r-- | src/ui/dialog/filter-effects-dialog.cpp | 25 | ||||
| -rw-r--r-- | src/ui/dialog/icon-preview.cpp | 134 | ||||
| -rw-r--r-- | src/ui/dialog/icon-preview.h | 3 | ||||
| -rw-r--r-- | src/ui/dialog/inkscape-preferences.cpp | 9 | ||||
| -rw-r--r-- | src/ui/dialog/livepatheffect-editor.cpp | 4 | ||||
| -rw-r--r-- | src/ui/dialog/print-colors-preview-dialog.cpp | 3 | ||||
| -rw-r--r-- | src/ui/dialog/swatches.cpp | 199 | ||||
| -rw-r--r-- | src/ui/dialog/swatches.h | 3 | ||||
| -rw-r--r-- | src/ui/icon-names.h | 6 | ||||
| -rw-r--r-- | src/ui/tool/control-point-selection.cpp | 48 | ||||
| -rw-r--r-- | src/ui/tool/control-point-selection.h | 7 | ||||
| -rw-r--r-- | src/ui/tool/node.cpp | 112 | ||||
| -rw-r--r-- | src/ui/uxmanager.cpp | 2 |
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; } } |
