From 1208e5f7938731244720438bff526c0b6e07c54f Mon Sep 17 00:00:00 2001 From: John Smith Date: Tue, 9 Oct 2012 15:26:18 +0900 Subject: Fix for 191020 : Lock/Unlock all layers (bzr r11764) --- src/desktop.cpp | 13 +++++++++++-- src/desktop.h | 3 ++- src/ui/dialog/layers.cpp | 17 +++++++++++++++++ src/verbs.cpp | 20 +++++++++++++++++--- src/verbs.h | 2 ++ 5 files changed, 49 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/desktop.cpp b/src/desktop.cpp index ca981a458..b01bf5d64 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -496,13 +496,22 @@ void SPDesktop::setCurrentLayer(SPObject *object) { _layer_hierarchy->setBottom(object); } -void SPDesktop::toggleAllLayers(bool hide) { +void SPDesktop::toggleHideAllLayers(bool hide) { - for ( SPObject* obj = currentRoot(); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) { + for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), currentRoot()); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) { SP_ITEM(obj)->setHidden(hide); } } +void SPDesktop::toggleLockAllLayers(bool lock) { + + for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), currentRoot()); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) { + SP_ITEM(obj)->setLocked(lock); + } +} + + + void SPDesktop::toggleLayerSolo(SPObject *object) { g_return_if_fail(SP_IS_GROUP(object)); g_return_if_fail( currentRoot() == object || (currentRoot() && currentRoot()->isAncestorOf(object)) ); diff --git a/src/desktop.h b/src/desktop.h index 919cd905e..3eb0294e7 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -280,7 +280,8 @@ public: void setCurrentLayer(SPObject *object); void toggleLayerSolo(SPObject *object); - void toggleAllLayers(bool hidden); + void toggleHideAllLayers(bool hide); + void toggleLockAllLayers(bool lock); SPObject *layerForObject(SPObject *object); bool isLayer(SPObject *object) const; bool isWithinViewport(SPItem *item) const; diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp index 70cf7075c..44eef89bb 100644 --- a/src/ui/dialog/layers.cpp +++ b/src/ui/dialog/layers.cpp @@ -69,6 +69,8 @@ enum { BUTTON_SOLO, BUTTON_SHOW_ALL, BUTTON_HIDE_ALL, + BUTTON_LOCK_ALL, + BUTTON_UNLOCK_ALL, DRAGNDROP }; @@ -263,6 +265,16 @@ bool LayersPanel::_executeAction() _fireAction( SP_VERB_LAYER_HIDE_ALL ); } break; + case BUTTON_LOCK_ALL: + { + _fireAction( SP_VERB_LAYER_LOCK_ALL ); + } + break; + case BUTTON_UNLOCK_ALL: + { + _fireAction( SP_VERB_LAYER_UNLOCK_ALL ); + } + break; case DRAGNDROP: { _doTreeMove( ); @@ -876,6 +888,11 @@ LayersPanel::LayersPanel() : _popupMenu.append(*manage(new Gtk::SeparatorMenuItem())); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOCK_ALL, 0, "Lock All", (int)BUTTON_LOCK_ALL ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_UNLOCK_ALL, 0, "Unlock All", (int)BUTTON_UNLOCK_ALL ) ); + + _popupMenu.append(*manage(new Gtk::SeparatorMenuItem())); + _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RAISE, GTK_STOCK_GO_UP, "Up", (int)BUTTON_UP ) ); _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOWER, GTK_STOCK_GO_DOWN, "Down", (int)BUTTON_DOWN ) ); diff --git a/src/verbs.cpp b/src/verbs.cpp index edfc45f8e..591280d47 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -1342,17 +1342,27 @@ void LayerVerb::perform(SPAction *action, void *data) break; } case SP_VERB_LAYER_SHOW_ALL: { - dt->toggleAllLayers( false ); + dt->toggleHideAllLayers( false ); DocumentUndo::maybeDone(sp_desktop_document(dt), "layer:showall", SP_VERB_LAYER_SHOW_ALL, _("Show all layers")); break; } - case SP_VERB_LAYER_HIDE_ALL: { - dt->toggleAllLayers( true ); + dt->toggleHideAllLayers( true ); DocumentUndo::maybeDone(sp_desktop_document(dt), "layer:hideall", SP_VERB_LAYER_HIDE_ALL, _("Hide all layers")); break; } + case SP_VERB_LAYER_LOCK_ALL: { + dt->toggleLockAllLayers( true ); + DocumentUndo::maybeDone(sp_desktop_document(dt), "layer:lockall", SP_VERB_LAYER_LOCK_ALL, _("Lock all layers")); + break; + } + + case SP_VERB_LAYER_UNLOCK_ALL: { + dt->toggleLockAllLayers( false ); + DocumentUndo::maybeDone(sp_desktop_document(dt), "layer:unlockall", SP_VERB_LAYER_UNLOCK_ALL, _("Unlock all layers")); + break; + } case SP_VERB_LAYER_TOGGLE_LOCK: case SP_VERB_LAYER_TOGGLE_HIDE: { if ( dt->currentLayer() == dt->currentRoot() ) { @@ -2489,6 +2499,10 @@ Verb *Verb::_base_verbs[] = { N_("Show all the layers"), NULL), new LayerVerb(SP_VERB_LAYER_HIDE_ALL, "LayerHideAll", N_("_Hide all layers"), N_("Hide all the layers"), NULL), + new LayerVerb(SP_VERB_LAYER_LOCK_ALL, "LayerLockAll", N_("_Lock all layers"), + N_("Lock all the layers"), NULL), + new LayerVerb(SP_VERB_LAYER_UNLOCK_ALL, "LayerUnlockAll", N_("_Unlock all layers"), + N_("Unlock all the layers"), NULL), new LayerVerb(SP_VERB_LAYER_TOGGLE_LOCK, "LayerToggleLock", N_("_Lock/Unlock Current Layer"), N_("Toggle lock on current layer"), NULL), new LayerVerb(SP_VERB_LAYER_TOGGLE_HIDE, "LayerToggleHide", N_("_Show/hide Current Layer"), diff --git a/src/verbs.h b/src/verbs.h index aa801803c..e8b271a18 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -149,6 +149,8 @@ enum { SP_VERB_LAYER_SOLO, SP_VERB_LAYER_SHOW_ALL, SP_VERB_LAYER_HIDE_ALL, + SP_VERB_LAYER_LOCK_ALL, + SP_VERB_LAYER_UNLOCK_ALL, SP_VERB_LAYER_TOGGLE_LOCK, SP_VERB_LAYER_TOGGLE_HIDE, /* Object */ -- cgit v1.2.3 From cc88abe36edd7dd478d4264742f61dd97ac5256b Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Tue, 9 Oct 2012 12:53:42 +0200 Subject: UI consistency fix (pointed Bug #955060, comment #24). (bzr r11768) --- src/live_effects/lpe-powerstroke.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index df94a761e..9fce832ab 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -209,7 +209,7 @@ LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) : interpolator_type(_("Interpolator type:"), _("Determines which kind of interpolator will be used to interpolate between stroke width along the path"), "interpolator_type", InterpolatorTypeConverter, &wr, this, Geom::Interpolate::INTERP_CUBICBEZIER_JOHAN), interpolator_beta(_("Smoothness:"), _("Sets the smoothness for the CubicBezierJohan interpolator; 0 = linear interpolation, 1 = smooth"), "interpolator_beta", &wr, this, 0.2), start_linecap_type(_("Start cap:"), _("Determines the shape of the path's start"), "start_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_ROUND), - linejoin_type(_("Join:"), _("Specifies the shape of the path's corners"), "linejoin_type", LineJoinTypeConverter, &wr, this, LINEJOIN_ROUND), + linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", LineJoinTypeConverter, &wr, this, LINEJOIN_ROUND), miter_limit(_("Miter limit:"), _("Maximum length of the miter (in units of stroke width)"), "miter_limit", &wr, this, 4.), end_linecap_type(_("End cap:"), _("Determines the shape of the path's end"), "end_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_ROUND) { -- cgit v1.2.3 From 66aa9095eba57e263fff225583c7cbfff121a09d Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Tue, 9 Oct 2012 13:36:06 +0200 Subject: Fix for Bug #1063831 (--export-text-to-path with SVG is undocumented) by Philipp Hagemeister. Greek and French man page translations updated. (bzr r11769) --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 578279929..844aded56 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -390,7 +390,7 @@ struct poptOption options[] = { {"export-text-to-path", 'T', POPT_ARG_NONE, &sp_export_text_to_path, SP_ARG_EXPORT_TEXT_TO_PATH, - N_("Convert text object to paths on export (PS, EPS, PDF)"), + N_("Convert text object to paths on export (PS, EPS, PDF, SVG)"), NULL}, {"export-ignore-filters", 0, -- cgit v1.2.3 From edf55384619442eed0ffee95e0eaa9b565477b86 Mon Sep 17 00:00:00 2001 From: Kris De Gussem Date: Tue, 9 Oct 2012 20:44:34 +0200 Subject: fix memory leak and access error in sp_repr_css_merge_from_decl (Bug #1061157) (bzr r11771) --- src/xml/repr-css.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/xml/repr-css.cpp b/src/xml/repr-css.cpp index 7fba4d7c6..f554d314d 100644 --- a/src/xml/repr-css.cpp +++ b/src/xml/repr-css.cpp @@ -351,7 +351,8 @@ static void sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *con guchar *const str_value_unsigned = cr_term_to_string(decl->value); gchar *const str_value = reinterpret_cast(str_value_unsigned); gchar *value_unquoted = attribute_unquote (str_value); // libcroco returns strings quoted in "" - gchar *units = NULL; + Glib::ustring value_unquoted2 = value_unquoted ? value_unquoted : Glib::ustring(); + Glib::ustring units; /* * Problem with parsing of units em and ex, like font-size "1.2em" and "3.4ex" @@ -360,18 +361,22 @@ static void sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *con * * HACK for now is to strip off em and ex units and add them back at the end */ - int l = strlen(value_unquoted); - if (!strncmp(&value_unquoted[l-2], "em", 2) || - !strncmp(&value_unquoted[l-2], "ex", 2)) { - units = g_strndup(&value_unquoted[l-2], 2); - value_unquoted = g_strndup(value_unquoted, l-2); + int le = value_unquoted2.length(); + if (le > 2) { + units = value_unquoted2.substr(le-2, 2); + if ((units == "em") || (units == "ex")) { + value_unquoted2 = value_unquoted2.substr(0, le-2); + } + else { + units.clear(); + } } // libcroco uses %.17f for formatting... leading to trailing zeros or small rounding errors. // CSSOStringStream is used here to write valid CSS (as in sp_style_write_string). This has // the additional benefit of respecting the numerical precission set in the SVG Output // preferences. We assume any numerical part comes first (if not, the whole string is copied). - std::stringstream ss( value_unquoted ); + std::stringstream ss( value_unquoted2 ); double number = 0; std::string characters; std::string temp; @@ -385,10 +390,9 @@ static void sp_repr_css_merge_from_decl(SPCSSAttr *css, CRDeclaration const *con Inkscape::CSSOStringStream os; if( number_valid ) os << number; os << characters; - if (units) { + if (!units.empty()) { os << units; //g_message("sp_repr_css_merge_from_decl looks like em or ex units %s --> %s", str_value, os.str().c_str()); - g_free(units); } ((Node *) css)->setAttribute(decl->property->stryng->str, os.str().c_str(), false); g_free(value_unquoted); -- cgit v1.2.3 From fab4c86f1347c48c3e87d645343faf0b167ea635 Mon Sep 17 00:00:00 2001 From: Kris De Gussem Date: Tue, 9 Oct 2012 21:26:18 +0200 Subject: Fix translation issue of rev 11759. (bzr r11772) --- src/inkscape.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/inkscape.cpp b/src/inkscape.cpp index 0a94d0742..fc9a9783f 100644 --- a/src/inkscape.cpp +++ b/src/inkscape.cpp @@ -312,8 +312,8 @@ static gint inkscape_autosave(gpointer) // Try to create the autosave directory if it doesn't exist if (g_mkdir(autosave_dir.c_str(), 0755)) { // the creation failed - Glib::ustring msg = Glib::ustring::format( - _("Autosave failed! Cannot create directory "), Glib::filename_to_utf8(autosave_dir)); + Glib::ustring msg = Glib::ustring::compose( + _("Autosave failed! Cannot create directory %1."), Glib::filename_to_utf8(autosave_dir)); g_warning("%s", msg.c_str()); SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, msg.c_str()); return TRUE; @@ -321,8 +321,8 @@ static gint inkscape_autosave(gpointer) // Try to read dir again autosave_dir_ptr = g_dir_open(autosave_dir.c_str(), 0, NULL); if( !autosave_dir_ptr ){ - Glib::ustring msg = Glib::ustring::format( - _("Autosave failed! Cannot open directory "), Glib::filename_to_utf8(autosave_dir)); + Glib::ustring msg = Glib::ustring::compose( + _("Autosave failed! Cannot open directory %1."), Glib::filename_to_utf8(autosave_dir)); g_warning("%s", msg.c_str()); SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, msg.c_str()); return TRUE; -- cgit v1.2.3 From 665bcd1dd1dce0b5a99725ab1bc9414b3760d044 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Wed, 10 Oct 2012 23:21:29 +0200 Subject: powerstroke: fix stuff! (apparently commit didn't work yesterday) (bzr r11774) --- src/live_effects/lpe-powerstroke.cpp | 129 +++++++++++++++++------------------ 1 file changed, 61 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index 9fce832ab..13fea76c5 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -153,6 +153,32 @@ static int circle_circle_intersection(Circle const &circle0, Circle const &circl return 2; } +/** + * Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t. + * Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt). + */ +Circle touching_circle( D2 const &curve, double t, double tol=0.01 ) +{ + //Piecewise k = curvature(curve, tol); + D2 dM=derivative(curve); + if ( are_near(L2sq(dM(t)),0.) ) { + dM=derivative(dM); + } + if ( are_near(L2sq(dM(t)),0.) ) { // try second time + dM=derivative(dM); + } + Piecewise > unitv = unitVector(dM,tol); + Piecewise dMlength = dot(Piecewise >(dM),unitv); + Piecewise k = cross(derivative(unitv),unitv); + k = divide(k,dMlength,tol,3); + double curv = k(t); // note that this value is signed + + Geom::Point normal = unitTangentAt(curve, t).cw(); + double radius = 1/curv; + Geom::Point center = curve(t) + radius*normal; + return Geom::Circle(center, fabs(radius)); +} + } // namespace Geom namespace Inkscape { @@ -381,76 +407,26 @@ static Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise derivs = reverse(B[prev_i]).valueAndDerivatives(0.,5); - for (unsigned deriv_n = 1, count = 0; deriv_n < derivs.size(); deriv_n++) { - Geom::Coord length = derivs[deriv_n].length(); - if ( ! Geom::are_near(length, 0) ) { - if (count == 0) { - tang0 = derivs[deriv_n] / length; - curv0 = length; // save the length of the tangent - count++; - } else { - // curv0 = need good way to calculate curvature - // calculate direction of normal - double angle = angle_between(tang0, derivs[deriv_n]); - if (angle >= 0 ) { - norm0 = tang0.ccw(); - } else { - norm0 = tang0.cw(); - } - break; // break out of for-loop - } - } - } - double r0 = curv0; - Geom::Point center0 = B[prev_i].at1() - r0*norm0; - circle0 = Geom::Circle(center0, r0); - } - Geom::Point tang1(0.,0.); - { - Geom::Point norm1(0.,0.); - Geom::Coord curv1 = 0; - std::vector derivs = B[i].valueAndDerivatives(0.,5); - for (unsigned deriv_n = 1, count = 0; deriv_n < derivs.size(); deriv_n++) { - Geom::Coord length = derivs[deriv_n].length(); - if ( ! Geom::are_near(length, 0) ) { - if (count == 0) { - tang1 = derivs[deriv_n] / length; - curv1 = length; // save the length of the tangent - count++; - } else { - //curv1 = length / curv1; // curvature = tangent' / tangent - // calculate direction of normal - double angle = angle_between(tang1, derivs[deriv_n]); - if (angle >= 0 ) { - norm1 = tang1.ccw(); - } else { - norm1 = tang1.cw(); - } - break; // break out of for-loop - } - } - } - double r1 = curv1; - Geom::Point center1 = B[i].at0() - r1*norm1; - circle1 = Geom::Circle(center1, r1); - } - + Geom::Circle circle1 = Geom::touching_circle(reverse(B[prev_i]),0.); + Geom::Circle circle2 = Geom::touching_circle(B[i],0.); Geom::Point points[2]; - int solutions = circle_circle_intersection(circle0, circle1, points[0], points[1]); + int solutions = circle_circle_intersection(circle1, circle2, points[0], points[1]); if (solutions == 2) { - Geom::Point sol = points[0]; - if ( dot(tang0,sol-B[prev_i].at1()) > 0 ) { + Geom::Point sol(0.,0.); + if ( dot(tang2,points[0]-B[i].at0()) > 0 ) { + // points[0] is bad, choose points[1] sol = points[1]; + } else if ( dot(tang2,points[1]-B[i].at0()) > 0 ) { // points[0] could be good, now check points[1] + // points[1] is bad, choose points[0] + sol = points[0]; + } else { + // both points are good, choose nearest + sol = ( distanceSq(B[i].at0(), points[0]) < distanceSq(B[i].at0(), points[1]) ) ? + points[0] : points[1]; } - Geom::EllipticalArc *arc0 = circle0.arc(B[prev_i].at1(), 0.5*(B[prev_i].at1()+sol), sol, true); - Geom::EllipticalArc *arc1 = circle1.arc(sol, 0.5*(sol+B[i].at0()), B[i].at0(), true); + + Geom::EllipticalArc *arc0 = circle1.arc(B[prev_i].at1(), 0.5*(B[prev_i].at1()+sol), sol, true); + Geom::EllipticalArc *arc1 = circle2.arc(sol, 0.5*(sol+B[i].at0()), B[i].at0(), true); if (arc0) { build_from_sbasis(pb,arc0->toSBasis(), tol, false); @@ -462,13 +438,30 @@ static Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise p = intersection_point( B[prev_i].at1(), tang1, + B[i].at0(), tang2 ); + if (p) { + // check size of miter + Geom::Point point_on_path = B[prev_i].at1() - rot90(tang1) * width; + Geom::Coord len = distance(*p, point_on_path); + if (len <= fabs(width) * miter_limit) { + // miter OK + pb.lineTo(*p); + } + } + pb.lineTo(B[i].at0()); + } + /*else if (solutions == 1) { // one circle is inside the other // don't know what to do: default to bevel pb.lineTo(B[i].at0()); } else { // no intersections // don't know what to do: default to bevel pb.lineTo(B[i].at0()); - } + } */ break; } -- cgit v1.2.3 From df6576d515c2618b9bc79226e6164e7d935a508b Mon Sep 17 00:00:00 2001 From: Alvin Penner Date: Wed, 10 Oct 2012 18:26:40 -0400 Subject: emf import. re-implement filtering of isolated control characters (Bug 217231) Fixed bugs: - https://launchpad.net/bugs/217231 (bzr r11775) --- src/extension/internal/emf-win32-inout.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/extension/internal/emf-win32-inout.cpp b/src/extension/internal/emf-win32-inout.cpp index 2097402c7..872de045a 100644 --- a/src/extension/internal/emf-win32-inout.cpp +++ b/src/extension/internal/emf-win32-inout.cpp @@ -1905,6 +1905,10 @@ myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD const * (gchar *) g_utf16_to_utf8( (gunichar2 *) wide_text, pEmr->emrtext.nChars, NULL, NULL, NULL ); if (ansi_text) { + if ((wide_text[0] < 32) && (strlen(ansi_text) == 1)) { + g_free(ansi_text); // filter out isolated control characters + ansi_text = g_strdup(""); + } // gchar *p = ansi_text; // while (*p) { // if (*p < 32 || *p >= 127) { -- cgit v1.2.3 From b79646b8d32b6f842f8dcc6ce5a0b7171f28a7bb Mon Sep 17 00:00:00 2001 From: John Smith Date: Thu, 11 Oct 2012 11:27:07 +0900 Subject: Fix for 246153 : Broken style indicator (bzr r11776) --- src/widgets/toolbox.cpp | 2 +- src/widgets/widget-sizes.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 49eb82de7..6e03c2606 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -1446,7 +1446,7 @@ void setup_aux_toolbox(GtkWidget *toolbox, SPDesktop *desktop) swatch->setClickVerb( aux_toolboxes[i].swatch_verb_id ); swatch->setWatchedTool( aux_toolboxes[i].swatch_tool, true ); GtkWidget *swatch_ = GTK_WIDGET( swatch->gobj() ); - gtk_table_attach( GTK_TABLE(holder), swatch_, 1, 2, 0, 1, (GtkAttachOptions)(GTK_SHRINK | GTK_FILL), (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), AUX_BETWEEN_BUTTON_GROUPS, 0 ); + gtk_table_attach( GTK_TABLE(holder), swatch_, 1, 2, 0, 1, (GtkAttachOptions)(GTK_SHRINK | GTK_FILL), (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), AUX_BETWEEN_BUTTON_GROUPS, AUX_SPACING ); } gtk_widget_show_all( holder ); diff --git a/src/widgets/widget-sizes.h b/src/widgets/widget-sizes.h index c3f9e1119..7de251ee6 100644 --- a/src/widgets/widget-sizes.h +++ b/src/widgets/widget-sizes.h @@ -31,7 +31,7 @@ #define SELECTED_STYLE_SB_WIDTH 48 #define SELECTED_STYLE_WIDTH 190 -#define STYLE_SWATCH_WIDTH 100 +#define STYLE_SWATCH_WIDTH 130 #define STATUS_LAYER_FONT_SIZE 7700 -- cgit v1.2.3 From 05c9f6824d14012a71528bd204bcdd4e6624db29 Mon Sep 17 00:00:00 2001 From: John Smith Date: Thu, 11 Oct 2012 12:34:08 +0900 Subject: Fix for 426763 : Cancelling import leads to error message (bzr r11777) --- src/extension/implementation/implementation.h | 1 + src/extension/input.cpp | 7 +++++-- src/extension/input.h | 4 ++++ src/extension/internal/pdfinput/pdf-input.cpp | 8 ++++++++ src/extension/internal/pdfinput/pdf-input.h | 4 +++- src/extension/system.cpp | 1 + src/file.cpp | 8 +++++++- 7 files changed, 29 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/extension/implementation/implementation.h b/src/extension/implementation/implementation.h index b0230b7c4..fb323cd78 100644 --- a/src/extension/implementation/implementation.h +++ b/src/extension/implementation/implementation.h @@ -104,6 +104,7 @@ public: virtual bool check(Inkscape::Extension::Extension * /*module*/) { return true; } virtual bool cancelProcessing () { return true; } + virtual bool wasCancelled () { return false; } virtual void commitDocument () {} // ----- Input functions ----- diff --git a/src/extension/input.cpp b/src/extension/input.cpp index 1662ef073..5cef38009 100644 --- a/src/extension/input.cpp +++ b/src/extension/input.cpp @@ -152,6 +152,10 @@ Input::open (const gchar *uri) SPDocument *const doc = imp->open(this, uri); + if (imp->wasCancelled()) { + throw Input::open_cancelled(); + } + return doc; } @@ -227,8 +231,7 @@ Input::prefs (const gchar *uri) delete dialog; - if (response == Gtk::RESPONSE_OK) return true; - return false; + return (response == Gtk::RESPONSE_OK); } } } /* namespace Inkscape, Extension */ diff --git a/src/extension/input.h b/src/extension/input.h index 8b198495e..b01ffeb86 100644 --- a/src/extension/input.h +++ b/src/extension/input.h @@ -39,6 +39,10 @@ public: virtual ~no_extension_found() throw() {} const char *what() const throw() { return "No suitable input extension found"; } }; + struct open_cancelled : public std::exception { + virtual ~open_cancelled() throw() {} + const char *what() const throw() { return "Open was cancelled"; } + }; Input (Inkscape::XML::Node * in_repr, Implementation::Implementation * in_imp); diff --git a/src/extension/internal/pdfinput/pdf-input.cpp b/src/extension/internal/pdfinput/pdf-input.cpp index 6b6107444..d2d594017 100644 --- a/src/extension/internal/pdfinput/pdf-input.cpp +++ b/src/extension/internal/pdfinput/pdf-input.cpp @@ -588,12 +588,19 @@ void PdfImportDialog::_setPreviewPage(int page) { //////////////////////////////////////////////////////////////////////////////// +bool +PdfInput::wasCancelled () { + return _cancelled; +} + /** * Parses the selected page of the given PDF document using PdfParser. */ SPDocument * PdfInput::open(::Inkscape::Extension::Input * /*mod*/, const gchar * uri) { + _cancelled = false; + // Initialize the globalParams variable for poppler if (!globalParams) { globalParams = new GlobalParams(); @@ -648,6 +655,7 @@ PdfInput::open(::Inkscape::Extension::Input * /*mod*/, const gchar * uri) { if (inkscape_use_gui()) { dlg = new PdfImportDialog(pdf_doc, uri); if (!dlg->showDialog()) { + _cancelled = true; delete dlg; delete pdf_doc; return NULL; diff --git a/src/extension/internal/pdfinput/pdf-input.h b/src/extension/internal/pdfinput/pdf-input.h index 75fcfa69a..e9da5b27c 100644 --- a/src/extension/internal/pdfinput/pdf-input.h +++ b/src/extension/internal/pdfinput/pdf-input.h @@ -135,7 +135,9 @@ public: SPDocument *open( Inkscape::Extension::Input *mod, const gchar *uri ); static void init( void ); - + virtual bool wasCancelled(); +private: + bool _cancelled; }; } // namespace Implementation diff --git a/src/extension/system.cpp b/src/extension/system.cpp index fc20095c5..7fb6e1591 100644 --- a/src/extension/system.cpp +++ b/src/extension/system.cpp @@ -144,6 +144,7 @@ SPDocument *open(Extension *key, gchar const *filename) } SPDocument *doc = imod->open(filename); + if (!doc) { throw Input::open_failed(); } diff --git a/src/file.cpp b/src/file.cpp index 778306d5d..a03c459da 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -235,12 +235,16 @@ bool sp_file_open(const Glib::ustring &uri, } SPDocument *doc = NULL; + bool cancelled = false; try { doc = Inkscape::Extension::open(key, uri.c_str()); } catch (Inkscape::Extension::Input::no_extension_found &e) { doc = NULL; } catch (Inkscape::Extension::Input::open_failed &e) { doc = NULL; + } catch (Inkscape::Extension::Input::open_cancelled &e) { + doc = NULL; + cancelled = true; } if (desktop) { @@ -287,7 +291,7 @@ bool sp_file_open(const Glib::ustring &uri, } return TRUE; - } else { + } else if (!cancelled) { gchar *safeUri = Inkscape::IO::sanitizeString(uri.c_str()); gchar *text = g_strdup_printf(_("Failed to load the requested file %s"), safeUri); sp_ui_error_dialog(text); @@ -295,6 +299,8 @@ bool sp_file_open(const Glib::ustring &uri, g_free(safeUri); return FALSE; } + + return FALSE; } /** -- cgit v1.2.3 From 3ca2c298a152f092b99d0c9978a47deec787ed8c Mon Sep 17 00:00:00 2001 From: John Smith Date: Thu, 11 Oct 2012 17:03:21 +0900 Subject: Fix for 171904 : toggleToolbox verb (bzr r11778) --- src/desktop.cpp | 13 ++++++++++++- src/desktop.h | 1 + src/interface.cpp | 39 ++++++++++++++++++--------------------- src/interface.h | 1 + src/verbs.cpp | 25 +++++++++++++++++++++++++ src/verbs.h | 7 +++++++ 6 files changed, 64 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/desktop.cpp b/src/desktop.cpp index b01bf5d64..bfec523db 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -55,6 +55,7 @@ #include "document.h" #include "event-log.h" #include "helper/units.h" +#include "interface.h" #include "inkscape-private.h" #include "layer-fns.h" #include "layer-manager.h" @@ -1318,6 +1319,17 @@ SPDesktop::toggleScrollbars() _widget->toggleScrollbars(); } + +void SPDesktop::toggleToolbar(gchar const *toolbar_name) +{ + Glib::ustring pref_path = getLayoutPrefPath(this) + toolbar_name + "/state"; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + gboolean visible = prefs->getBool(pref_path, true); + prefs->setBool(pref_path, !visible); + + layoutWidget(); +} + void SPDesktop::layoutWidget() { @@ -1474,7 +1486,6 @@ void SPDesktop::toggleSnapGlobal() namedview->setSnapGlobal(!v); } - //---------------------------------------------------------------------- // Callback implementations. The virtual ones are connected by the view. diff --git a/src/desktop.h b/src/desktop.h index 3eb0294e7..958e881ed 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -365,6 +365,7 @@ public: void toggleSnapGlobal(); bool gridsEnabled() const { return grids_visible; }; void showGrids(bool show, bool dirty_document = true); + void toggleToolbar(gchar const *toolbar_name); bool is_iconified(); bool is_maximized(); diff --git a/src/interface.cpp b/src/interface.cpp index 2ee188ef7..bad95adc6 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -527,7 +527,7 @@ static GtkWidget *sp_ui_menu_append_item_from_verb(GtkMenu *menu, Inkscape::Verb } // end of sp_ui_menu_append_item_from_verb -static Glib::ustring getLayoutPrefPath( Inkscape::UI::View::View *view ) +Glib::ustring getLayoutPrefPath( Inkscape::UI::View::View *view ) { Glib::ustring prefPath; @@ -554,7 +554,7 @@ checkitem_toggled(GtkCheckMenuItem *menuitem, gpointer user_data) sp_ui_menu_activate(menuitem, action); } else if (pref) { - // The Show/Hide menu items without actions + // All check menu items should have actions now, but just in case Glib::ustring pref_path = getLayoutPrefPath( view ); pref_path += pref; pref_path += "/state"; @@ -596,19 +596,16 @@ static gboolean checkitem_update(GtkWidget *widget, GdkEventExpose * /*event*/, if (!strcmp(action->id, "ToggleGrid")) { ison = dt->gridsEnabled(); } - if (!strcmp(action->id, "ToggleGuides")) { + else if (!strcmp(action->id, "ToggleGuides")) { ison = dt->namedview->getGuides(); } - if (!strcmp(action->id, "ToggleSnapGlobal")) { + else if (!strcmp(action->id, "ToggleSnapGlobal")) { ison = dt->namedview->getSnapGlobal(); } - if (!strcmp(action->id, "ViewCmsToggle")) { + else if (!strcmp(action->id, "ViewCmsToggle")) { ison = dt->colorProfAdjustEnabled(); } - if (!strcmp(action->id, "ToggleRulers")) { - ison = getViewStateFromPref(view, pref); - } - if (!strcmp(action->id, "ToggleScrollbars")) { + else { ison = getViewStateFromPref(view, pref); } } else if (pref) { @@ -896,22 +893,22 @@ sp_ui_checkboxes_menus(GtkMenu *m, Inkscape::UI::View::View *view) { //sp_ui_menu_append_check_item_from_verb(m, view, _("_Menu"), _("Show or hide the menu bar"), "menu", // checkitem_toggled, checkitem_update, 0); - sp_ui_menu_append_check_item_from_verb(m, view, _("_Commands Bar"), _("Show or hide the Commands bar (under the menu)"), "commands", - checkitem_toggled, checkitem_update, 0); - sp_ui_menu_append_check_item_from_verb(m, view, _("Sn_ap Controls Bar"), _("Show or hide the snapping controls"), "snaptoolbox", - checkitem_toggled, checkitem_update, 0); - sp_ui_menu_append_check_item_from_verb(m, view, _("T_ool Controls Bar"), _("Show or hide the Tool Controls bar"), "toppanel", - checkitem_toggled, checkitem_update, 0); - sp_ui_menu_append_check_item_from_verb(m, view, _("_Toolbox"), _("Show or hide the main toolbox (on the left)"), "toolbox", - checkitem_toggled, checkitem_update, 0); + sp_ui_menu_append_check_item_from_verb(m, view, NULL, NULL, "commands", + checkitem_toggled, checkitem_update, Inkscape::Verb::get(SP_VERB_TOGGLE_COMMANDS_TOOLBAR)); + sp_ui_menu_append_check_item_from_verb(m, view,NULL, NULL, "snaptoolbox", + checkitem_toggled, checkitem_update, Inkscape::Verb::get(SP_VERB_TOGGLE_SNAP_TOOLBAR)); + sp_ui_menu_append_check_item_from_verb(m, view, NULL, NULL, "toppanel", + checkitem_toggled, checkitem_update, Inkscape::Verb::get(SP_VERB_TOGGLE_TOOL_TOOLBAR)); + sp_ui_menu_append_check_item_from_verb(m, view, NULL, NULL, "toolbox", + checkitem_toggled, checkitem_update, Inkscape::Verb::get(SP_VERB_TOGGLE_TOOLBOX)); sp_ui_menu_append_check_item_from_verb(m, view, NULL, NULL, "rulers", checkitem_toggled, checkitem_update, Inkscape::Verb::get(SP_VERB_TOGGLE_RULERS)); sp_ui_menu_append_check_item_from_verb(m, view, NULL, NULL, "scrollbars", checkitem_toggled, checkitem_update, Inkscape::Verb::get(SP_VERB_TOGGLE_SCROLLBARS)); - sp_ui_menu_append_check_item_from_verb(m, view, _("_Palette"), _("Show or hide the color palette"), "panels", - checkitem_toggled, checkitem_update, 0); - sp_ui_menu_append_check_item_from_verb(m, view, _("_Statusbar"), _("Show or hide the statusbar (at the bottom of the window)"), "statusbar", - checkitem_toggled, checkitem_update, 0); + sp_ui_menu_append_check_item_from_verb(m, view, NULL, NULL, "panels", + checkitem_toggled, checkitem_update, Inkscape::Verb::get(SP_VERB_TOGGLE_PALETTE)); + sp_ui_menu_append_check_item_from_verb(m, view, NULL, NULL, "statusbar", + checkitem_toggled, checkitem_update, Inkscape::Verb::get(SP_VERB_TOGGLE_STATUSBAR)); } diff --git a/src/interface.h b/src/interface.h index 891e39957..2e9e7fc2e 100644 --- a/src/interface.h +++ b/src/interface.h @@ -81,6 +81,7 @@ GtkWidget *sp_ui_main_menubar (Inkscape::UI::View::View *view); void sp_menu_append_recent_documents (GtkWidget *menu); void sp_ui_dialog_title_string (Inkscape::Verb * verb, gchar* c); +Glib::ustring getLayoutPrefPath( Inkscape::UI::View::View *view ); /** * diff --git a/src/verbs.cpp b/src/verbs.cpp index 591280d47..55d114e9d 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -1785,6 +1785,24 @@ void ZoomVerb::perform(SPAction *action, void *data) case SP_VERB_TOGGLE_SCROLLBARS: dt->toggleScrollbars(); break; + case SP_VERB_TOGGLE_COMMANDS_TOOLBAR: + dt->toggleToolbar("commands"); + break; + case SP_VERB_TOGGLE_SNAP_TOOLBAR: + dt->toggleToolbar("snaptoolbox"); + break; + case SP_VERB_TOGGLE_TOOL_TOOLBAR: + dt->toggleToolbar("toppanel"); + break; + case SP_VERB_TOGGLE_TOOLBOX: + dt->toggleToolbar("toolbox"); + break; + case SP_VERB_TOGGLE_PALETTE: + dt->toggleToolbar("panels"); + break; + case SP_VERB_TOGGLE_STATUSBAR: + dt->toggleToolbar("statusbar"); + break; case SP_VERB_TOGGLE_GUIDES: sp_namedview_toggle_guides(doc, repr); break; @@ -1843,6 +1861,7 @@ void ZoomVerb::perform(SPAction *action, void *data) inkscape_dialogs_unhide(); dt->_dlg_mgr->showDialog("IconPreviewPanel"); break; + default: break; } @@ -2646,6 +2665,12 @@ Verb *Verb::_base_verbs[] = { new ZoomVerb(SP_VERB_TOGGLE_GRID, "ToggleGrid", N_("_Grid"), N_("Show or hide the grid"), INKSCAPE_ICON("show-grid")), new ZoomVerb(SP_VERB_TOGGLE_GUIDES, "ToggleGuides", N_("G_uides"), N_("Show or hide guides (drag from a ruler to create a guide)"), INKSCAPE_ICON("show-guides")), new ZoomVerb(SP_VERB_TOGGLE_SNAPPING, "ToggleSnapGlobal", N_("Snap"), N_("Enable snapping"), INKSCAPE_ICON("snap")), + new ZoomVerb(SP_VERB_TOGGLE_COMMANDS_TOOLBAR, "ToggleCommandsToolbar", N_("_Commands Bar"), N_("Show or hide the Commands bar (under the menu)"), NULL), + new ZoomVerb(SP_VERB_TOGGLE_SNAP_TOOLBAR, "ToggleSnapToolbar", N_("Sn_ap Controls Bar"), N_("Show or hide the snapping controls"), NULL), + new ZoomVerb(SP_VERB_TOGGLE_TOOL_TOOLBAR, "ToggleToolToolbar", N_("T_ool Controls Bar"), N_("Show or hide the Tool Controls bar"), NULL), + new ZoomVerb(SP_VERB_TOGGLE_TOOLBOX, "ToggleToolbox", N_("_Toolbox"), N_("Show or hide the main toolbox (on the left)"), NULL), + new ZoomVerb(SP_VERB_TOGGLE_PALETTE, "TogglePalette", N_("_Palette"), N_("Show or hide the color palette"), NULL), + new ZoomVerb(SP_VERB_TOGGLE_STATUSBAR, "ToggleStatusbar", N_("_Statusbar"), N_("Show or hide the statusbar (at the bottom of the window)"), NULL), new ZoomVerb(SP_VERB_ZOOM_NEXT, "ZoomNext", N_("Nex_t Zoom"), N_("Next zoom (from the history of zooms)"), INKSCAPE_ICON("zoom-next")), new ZoomVerb(SP_VERB_ZOOM_PREV, "ZoomPrev", N_("Pre_vious Zoom"), N_("Previous zoom (from the history of zooms)"), diff --git a/src/verbs.h b/src/verbs.h index e8b271a18..5a707ade3 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -224,6 +224,12 @@ enum { SP_VERB_TOGGLE_GRID, SP_VERB_TOGGLE_GUIDES, SP_VERB_TOGGLE_SNAPPING, + SP_VERB_TOGGLE_COMMANDS_TOOLBAR, + SP_VERB_TOGGLE_SNAP_TOOLBAR, + SP_VERB_TOGGLE_TOOL_TOOLBAR, + SP_VERB_TOGGLE_TOOLBOX, + SP_VERB_TOGGLE_PALETTE, + SP_VERB_TOGGLE_STATUSBAR, SP_VERB_ZOOM_NEXT, SP_VERB_ZOOM_PREV, SP_VERB_ZOOM_1_1, @@ -330,6 +336,7 @@ enum { SP_VERB_ALIGN_VERTICAL_BOTTOM, SP_VERB_ALIGN_VERTICAL_TOP_TO_ANCHOR, SP_VERB_ALIGN_VERTICAL_HORIZONTAL_CENTER, + /* Footer */ SP_VERB_LAST }; -- cgit v1.2.3 From c520388928f8cc85d91f24a2f01fa7549096fe83 Mon Sep 17 00:00:00 2001 From: John Smith Date: Thu, 11 Oct 2012 18:43:21 +0900 Subject: Fix for 191020 : Lock/Unlock all layers - Lock other layers (bzr r11779) --- src/desktop.cpp | 29 +++++++++++++++++++++++++++++ src/desktop.h | 1 + src/ui/dialog/layers.cpp | 7 +++++++ src/verbs.cpp | 13 +++++++++++-- src/verbs.h | 1 + 5 files changed, 49 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/desktop.cpp b/src/desktop.cpp index bfec523db..fa0c8647f 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -511,6 +511,35 @@ void SPDesktop::toggleLockAllLayers(bool lock) { } } +void SPDesktop::toggleLockOtherLayers(SPObject *object) { + g_return_if_fail(SP_IS_GROUP(object)); + g_return_if_fail( currentRoot() == object || (currentRoot() && currentRoot()->isAncestorOf(object)) ); + + bool othersLocked = false; + std::vector layers; + for ( SPObject* obj = Inkscape::next_layer(currentRoot(), object); obj; obj = Inkscape::next_layer(currentRoot(), obj) ) { + // Dont lock any ancestors, since that would in turn lock the layer as well + if (!obj->isAncestorOf(object)) { + layers.push_back(obj); + othersLocked |= !SP_ITEM(obj)->isLocked(); + } + } + for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), object); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) { + if (!obj->isAncestorOf(object)) { + layers.push_back(obj); + othersLocked |= !SP_ITEM(obj)->isLocked(); + } + } + + SPItem *item = SP_ITEM(object); + if ( item->isLocked() ) { + item->setLocked(false); + } + + for ( std::vector::iterator it = layers.begin(); it != layers.end(); ++it ) { + SP_ITEM(*it)->setLocked(othersLocked); + } +} void SPDesktop::toggleLayerSolo(SPObject *object) { diff --git a/src/desktop.h b/src/desktop.h index 958e881ed..529199692 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -282,6 +282,7 @@ public: void toggleLayerSolo(SPObject *object); void toggleHideAllLayers(bool hide); void toggleLockAllLayers(bool lock); + void toggleLockOtherLayers(SPObject *object); SPObject *layerForObject(SPObject *object); bool isLayer(SPObject *object) const; bool isWithinViewport(SPItem *item) const; diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp index 44eef89bb..457f7c147 100644 --- a/src/ui/dialog/layers.cpp +++ b/src/ui/dialog/layers.cpp @@ -69,6 +69,7 @@ enum { BUTTON_SOLO, BUTTON_SHOW_ALL, BUTTON_HIDE_ALL, + BUTTON_LOCK_OTHERS, BUTTON_LOCK_ALL, BUTTON_UNLOCK_ALL, DRAGNDROP @@ -265,6 +266,11 @@ bool LayersPanel::_executeAction() _fireAction( SP_VERB_LAYER_HIDE_ALL ); } break; + case BUTTON_LOCK_OTHERS: + { + _fireAction( SP_VERB_LAYER_LOCK_OTHERS ); + } + break; case BUTTON_LOCK_ALL: { _fireAction( SP_VERB_LAYER_LOCK_ALL ); @@ -888,6 +894,7 @@ LayersPanel::LayersPanel() : _popupMenu.append(*manage(new Gtk::SeparatorMenuItem())); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOCK_OTHERS, 0, "Lock Others", (int)BUTTON_LOCK_OTHERS ) ); _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOCK_ALL, 0, "Lock All", (int)BUTTON_LOCK_ALL ) ); _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_UNLOCK_ALL, 0, "Unlock All", (int)BUTTON_UNLOCK_ALL ) ); diff --git a/src/verbs.cpp b/src/verbs.cpp index 55d114e9d..450b800c1 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -1351,13 +1351,20 @@ void LayerVerb::perform(SPAction *action, void *data) DocumentUndo::maybeDone(sp_desktop_document(dt), "layer:hideall", SP_VERB_LAYER_HIDE_ALL, _("Hide all layers")); break; } - case SP_VERB_LAYER_LOCK_ALL: { dt->toggleLockAllLayers( true ); DocumentUndo::maybeDone(sp_desktop_document(dt), "layer:lockall", SP_VERB_LAYER_LOCK_ALL, _("Lock all layers")); break; } - + case SP_VERB_LAYER_LOCK_OTHERS: { + if ( dt->currentLayer() == dt->currentRoot() ) { + dt->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No current layer.")); + } else { + dt->toggleLockOtherLayers( dt->currentLayer() ); + DocumentUndo::maybeDone(sp_desktop_document(dt), "layer:lockothers", SP_VERB_LAYER_LOCK_OTHERS, _("Lock other layers")); + } + break; + } case SP_VERB_LAYER_UNLOCK_ALL: { dt->toggleLockAllLayers( false ); DocumentUndo::maybeDone(sp_desktop_document(dt), "layer:unlockall", SP_VERB_LAYER_UNLOCK_ALL, _("Unlock all layers")); @@ -2520,6 +2527,8 @@ Verb *Verb::_base_verbs[] = { N_("Hide all the layers"), NULL), new LayerVerb(SP_VERB_LAYER_LOCK_ALL, "LayerLockAll", N_("_Lock all layers"), N_("Lock all the layers"), NULL), + new LayerVerb(SP_VERB_LAYER_LOCK_OTHERS, "LayerLockOthers", N_("Lock/Unlock _other layers"), + N_("Lock all the other layers"), NULL), new LayerVerb(SP_VERB_LAYER_UNLOCK_ALL, "LayerUnlockAll", N_("_Unlock all layers"), N_("Unlock all the layers"), NULL), new LayerVerb(SP_VERB_LAYER_TOGGLE_LOCK, "LayerToggleLock", N_("_Lock/Unlock Current Layer"), diff --git a/src/verbs.h b/src/verbs.h index 5a707ade3..da2adb52e 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -150,6 +150,7 @@ enum { SP_VERB_LAYER_SHOW_ALL, SP_VERB_LAYER_HIDE_ALL, SP_VERB_LAYER_LOCK_ALL, + SP_VERB_LAYER_LOCK_OTHERS, SP_VERB_LAYER_UNLOCK_ALL, SP_VERB_LAYER_TOGGLE_LOCK, SP_VERB_LAYER_TOGGLE_HIDE, -- cgit v1.2.3 From 756e60863f9997fc95365a21937b9ac402709441 Mon Sep 17 00:00:00 2001 From: John Smith Date: Thu, 11 Oct 2012 23:23:48 +0900 Subject: Fix for 1058402 : Inconsistent opacity indication (bzr r11781) --- src/ui/widget/style-swatch.cpp | 7 ++----- src/widgets/widget-sizes.h | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ui/widget/style-swatch.cpp b/src/ui/widget/style-swatch.cpp index 857ae7019..60d5f6ecc 100644 --- a/src/ui/widget/style-swatch.cpp +++ b/src/ui/widget/style-swatch.cpp @@ -340,15 +340,12 @@ void StyleSwatch::setStyle(SPStyle *query) if (op != 1) { { gchar *str; - if (op == 0) - str = g_strdup_printf(_("O:%.3g"), op); - else - str = g_strdup_printf(_("O:.%d"), (int) (op*10)); + str = g_strdup_printf(_("O: %2.0f"), (op*100.0)); _opacity_value.set_markup (str); g_free (str); } { - gchar *str = g_strdup_printf(_("Opacity: %.3g"), op); + gchar *str = g_strdup_printf(_("Opacity: %2.1f %%"), (op*100.0)); _opacity_place.set_tooltip_text(str); g_free (str); } diff --git a/src/widgets/widget-sizes.h b/src/widgets/widget-sizes.h index 7de251ee6..fe89d4574 100644 --- a/src/widgets/widget-sizes.h +++ b/src/widgets/widget-sizes.h @@ -31,7 +31,7 @@ #define SELECTED_STYLE_SB_WIDTH 48 #define SELECTED_STYLE_WIDTH 190 -#define STYLE_SWATCH_WIDTH 130 +#define STYLE_SWATCH_WIDTH 135 #define STATUS_LAYER_FONT_SIZE 7700 -- cgit v1.2.3 From f304ab600788b02cb02a4413f68f466e35cf1539 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 11 Oct 2012 19:54:14 +0200 Subject: Add symbols dialog. See: http://wiki.inkscape.org/wiki/index.php/SymbolsDialog (bzr r11782) --- src/document.cpp | 35 ++- src/menus-skeleton.h | 5 + src/path-prefix.h | 4 + src/selection-chemistry.cpp | 158 +++++++++++ src/selection-chemistry.h | 5 +- src/selection-describer.cpp | 7 +- src/sp-object.cpp | 3 + src/sp-symbol.cpp | 5 + src/sp-use.cpp | 8 + src/ui/clipboard.cpp | 50 ++++ src/ui/clipboard.h | 2 + src/ui/dialog/Makefile_insert | 2 + src/ui/dialog/dialog-manager.cpp | 3 + src/ui/dialog/symbols.cpp | 574 +++++++++++++++++++++++++++++++++++++++ src/ui/dialog/symbols.h | 114 ++++++++ src/verbs.cpp | 16 ++ src/verbs.h | 3 + 17 files changed, 991 insertions(+), 3 deletions(-) create mode 100644 src/ui/dialog/symbols.cpp create mode 100644 src/ui/dialog/symbols.h (limited to 'src') diff --git a/src/document.cpp b/src/document.cpp index 9d8291db0..172037518 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -7,10 +7,12 @@ * bulia byak * Jon A. Cruz * Abhishek Sharma + * Tavmjong Bah * * Copyright (C) 2004-2005 MenTaLguY * Copyright (C) 1999-2002 Lauris Kaplinski * Copyright (C) 2000-2001 Ximian, Inc. + * Copyright (C) 2012 Tavmjong Bah * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -59,6 +61,7 @@ #include "sp-item-group.h" #include "sp-namedview.h" #include "sp-object-repr.h" +#include "sp-symbol.h" #include "transf_mat_3x4.h" #include "unit-constants.h" #include "xml/repr.h" @@ -1454,9 +1457,10 @@ void SPDocument::importDefs(SPDocument *source) for (Inkscape::XML::Node *def = defs->firstChild() ; def ; def = def->next()) { - // Prevent duplicates of solid swatches by checking if equivalent swatch already exists gboolean duplicate = false; SPObject *src = source->getObjectByRepr(def); + + // Prevent duplicates of solid swatches by checking if equivalent swatch already exists if (src && SP_IS_GRADIENT(src)) { SPGradient *gr = SP_GRADIENT(src); if (gr->isSolid() || gr->getVector()->isSolid()) { @@ -1473,6 +1477,35 @@ void SPDocument::importDefs(SPDocument *source) } } + // Prevent duplication of symbols... could be more clever. + // The tag "_inkscape_duplicate" is added to "id" by ClipboardManagerImpl::copySymbol(). + // We assume that symbols are in defs section (not required by SVG spec). + if (src && SP_IS_SYMBOL(src)) { + + Glib::ustring id = src->getRepr()->attribute("id"); + size_t pos = id.find( "_inkscape_duplicate" ); + if( pos != Glib::ustring::npos ) { + + // This is our symbol, now get rid of tag + id.erase( pos ); + + // Check that it really is a duplicate + for (SPObject *trg = this->getDefs()->firstChild() ; trg ; trg = trg->getNext()) { + if( trg && SP_IS_SYMBOL(trg) && src != trg ) { + std::string id2 = trg->getRepr()->attribute("id"); + + if( !id.compare( id2 ) ) { + duplicate = true; + break; + } + } + } + if ( !duplicate ) { + src->getRepr()->setAttribute("id", id.c_str() ); + } + } + } + if (!duplicate) { Inkscape::XML::Node * dup = def->duplicate(this->getReprDoc()); target_defs->appendChild(dup); diff --git a/src/menus-skeleton.h b/src/menus-skeleton.h index 09366a33f..fa39dbd3a 100644 --- a/src/menus-skeleton.h +++ b/src/menus-skeleton.h @@ -182,6 +182,7 @@ static char const menus_skeleton[] = " \n" " \n" " \n" +" \n" " \n" " \n" " \n" @@ -198,6 +199,10 @@ static char const menus_skeleton[] = " \n" " \n" " \n" +" \n" +" \n" +" \n" +" \n" " \n" " \n" " \n" diff --git a/src/path-prefix.h b/src/path-prefix.h index bdb6b35f7..be57ae354 100644 --- a/src/path-prefix.h +++ b/src/path-prefix.h @@ -34,6 +34,7 @@ extern "C" { # define INKSCAPE_PALETTESDIR BR_DATADIR( "/inkscape/palettes" ) # define INKSCAPE_PATTERNSDIR BR_DATADIR( "/inkscape/patterns" ) # define INKSCAPE_SCREENSDIR BR_DATADIR( "/inkscape/screens" ) +# define INKSCAPE_SYMBOLSDIR BR_DATADIR( "/inkscape/symbols" ) # define INKSCAPE_TUTORIALSDIR BR_DATADIR( "/inkscape/tutorials" ) # define INKSCAPE_TEMPLATESDIR BR_DATADIR( "/inkscape/templates" ) # define INKSCAPE_UIDIR BR_DATADIR( "/inkscape/ui" ) @@ -56,6 +57,7 @@ extern "C" { # define INKSCAPE_PALETTESDIR WIN32_DATADIR("share\\palettes") # define INKSCAPE_PATTERNSDIR WIN32_DATADIR("share\\patterns") # define INKSCAPE_SCREENSDIR WIN32_DATADIR("share\\screens") +# define INKSCAPE_SYMBOLSDIR WIN32_DATADIR("share\\symbols") # define INKSCAPE_TUTORIALSDIR WIN32_DATADIR("share\\tutorials") # define INKSCAPE_TEMPLATESDIR WIN32_DATADIR("share\\templates") # define INKSCAPE_UIDIR WIN32_DATADIR("share\\ui") @@ -77,6 +79,7 @@ extern "C" { # define INKSCAPE_PALETTESDIR "Contents/Resources/palettes" # define INKSCAPE_PATTERNSDIR "Contents/Resources/patterns" # define INKSCAPE_SCREENSDIR "Contents/Resources/screens" +# define INKSCAPE_SYMBOLSDIR "Contents/Resources/symbols" # define INKSCAPE_TUTORIALSDIR "Contents/Resources/tutorials" # define INKSCAPE_TEMPLATESDIR "Contents/Resources/templates" # define INKSCAPE_UIDIR "Contents/Resources/ui" @@ -98,6 +101,7 @@ extern "C" { # define INKSCAPE_PALETTESDIR INKSCAPE_DATADIR "/inkscape/palettes" # define INKSCAPE_PATTERNSDIR INKSCAPE_DATADIR "/inkscape/patterns" # define INKSCAPE_SCREENSDIR INKSCAPE_DATADIR "/inkscape/screens" +# define INKSCAPE_SYMBOLSDIR INKSCAPE_DATADIR "/inkscape/symbols" # define INKSCAPE_TUTORIALSDIR INKSCAPE_DATADIR "/inkscape/tutorials" # define INKSCAPE_TEMPLATESDIR INKSCAPE_DATADIR "/inkscape/templates" # define INKSCAPE_UIDIR INKSCAPE_DATADIR "/inkscape/ui" diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 332e9a34e..904e21960 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -11,6 +11,7 @@ * Martin Sucha * Abhishek Sharma * Kris De Gussem + * Tavmjong Bah (Symbol additions) * * Copyright (C) 1999-2010,2012 authors * Copyright (C) 2001-2002 Ximian, Inc. @@ -71,6 +72,7 @@ SPCycleType SP_CYCLING = SP_CYCLE_FOCUS; #include "sp-gradient-reference.h" #include "sp-linear-gradient-fns.h" #include "sp-pattern.h" +#include "sp-symbol.h" #include "sp-radial-gradient-fns.h" #include "gradient-context.h" #include "sp-namedview.h" @@ -2887,6 +2889,162 @@ void sp_selection_to_guides(SPDesktop *desktop) DocumentUndo::done(doc, SP_VERB_EDIT_SELECTION_2_GUIDES, _("Objects to guides")); } +/* + * Convert to , leaving all elements referencing group unchanged. + */ +void sp_selection_symbol(SPDesktop *desktop, bool apply ) +{ + + if (desktop == NULL) { + return; + } + + SPDocument *doc = sp_desktop_document(desktop); + Inkscape::XML::Document *xml_doc = doc->getReprDoc(); + + Inkscape::Selection *selection = sp_desktop_selection(desktop); + + // Check if something is selected. + if (selection->isEmpty()) { + desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select one group to convert to symbol.")); + return; + } + + SPObject* group = selection->single(); + + // Make sure we have only one object in selection. + if( group == NULL ) { + desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select only one group to convert to symbol.")); + return; + } + + // Make sure we convert the original. + if( SP_IS_USE( group ) ) { + desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select original (Shift+D) to convert to symbol.")); + return; + } + + // Require that we really have a group. + if( !SP_IS_GROUP( group ) ) { + desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Group selection first to convert to symbol.")); + return; + } + + doc->ensureUpToDate(); + + Inkscape::XML::Node *symbol = xml_doc->createElement("svg:symbol"); + symbol->setAttribute("style", group->getAttribute("style")); + symbol->setAttribute("title", group->getAttribute("title")); + symbol->setAttribute("transform", group->getAttribute("transform")); + + Glib::ustring id = group->getAttribute("id"); + + // Now we need to copy all children of group + GSList* children = group->childList(false); + children = g_slist_reverse(children); + for (GSList* i = children; i != NULL; i = i->next ) { + SPObject* child = SP_OBJECT(i->data); + Inkscape::XML::Node *dup = child->getRepr()->duplicate(xml_doc); + symbol->appendChild(dup); + child->deleteObject(true); + } + + // Need to delete ; all elements that referenced should + // auto-magically reference . + doc->getDefs()->getRepr()->appendChild(symbol); + symbol->setAttribute("id",id.c_str()); // After we delete group with same id. + // Mysterious, must set symbol ID before deleting group or all + // refering to symbol get turned into groups. (Linked to unlinking clones?) + group->deleteObject(true); + + Inkscape::GC::release(symbol); + selection->clear(); + // Group just disappears, nothing to select. + + // Need to signal Symbol dialog to update + + g_slist_free(children); + + DocumentUndo::done(doc, SP_VERB_EDIT_SYMBOL, _("Group to symbol")); +} + +/* + * Convert to . All elements referencing symbol remain unchanged. + */ +void sp_selection_unsymbol(SPDesktop *desktop) +{ + + if (desktop == NULL) { + return; + } + + SPDocument *doc = sp_desktop_document(desktop); + Inkscape::XML::Document *xml_doc = doc->getReprDoc(); + + Inkscape::Selection *selection = sp_desktop_selection(desktop); + + // Check if something is selected. + if (selection->isEmpty()) { + desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select a symbol to extract objects from.")); + return; + } + + SPObject* use = selection->single(); + + // Make sure we have only one object in selection. + if( use == NULL ) { + desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select only one symbol to convert to group.")); + return; + } + + // Require that we really have a that references a . + if( !SP_IS_USE( use ) && !SP_IS_SYMBOL( use->firstChild() ) ) { + desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select only one symbol to convert to group.")); + return; + } + + doc->ensureUpToDate(); + + SPObject* symbol = use->firstChild(); + + Inkscape::XML::Node *group = xml_doc->createElement("svg:g"); + group->setAttribute("style", symbol->getAttribute("style")); + group->setAttribute("title", symbol->getAttribute("title")); + group->setAttribute("transform", symbol->getAttribute("transform")); + + Glib::ustring id = symbol->getAttribute("id"); + + // Now we need to copy all children of symbol + GSList* children = symbol->childList(false); + children = g_slist_reverse(children); + for (GSList* i = children; i != NULL; i = i->next ) { + SPObject* child = SP_OBJECT(i->data); + Inkscape::XML::Node *dup = child->getRepr()->duplicate(xml_doc); + group->appendChild(dup); + child->deleteObject(true); + } + + SPObject* parent = use->parent; // So we insert next to (easier to find) + + // Need to delete ; all other elements that referenced should + // auto-magically reference . + symbol->deleteObject(true); + group->setAttribute("id",id.c_str()); // After we delete symbol with same id. + parent->getRepr()->appendChild(group); + //use->deleteObject(true); + + SPItem *group_item = static_cast(sp_desktop_document(desktop)->getObjectByRepr(group)); + Inkscape::GC::release(group); + selection->clear(); + selection->set(group_item); + + // Need to signal Symbol dialog to update + + g_slist_free(children); + + DocumentUndo::done(doc, SP_VERB_EDIT_UNSYMBOL, _("Group from symbol")); +} + void sp_selection_tile(SPDesktop *desktop, bool apply) { diff --git a/src/selection-chemistry.h b/src/selection-chemistry.h index 3c9c1aea9..5b35ded09 100644 --- a/src/selection-chemistry.h +++ b/src/selection-chemistry.h @@ -11,7 +11,7 @@ * Jon A. Cruz * Abhishek Sharma * - * Copyright (C) 1999-2010 authors + * Copyright (C) 1999-2012 authors * Copyright (C) 2001-2002 Ximian, Inc. * * Released under GNU GPL, read the file 'COPYING' for more information @@ -67,6 +67,9 @@ void sp_selection_clone_original_path_lpe(SPDesktop *desktop); void sp_selection_to_marker(SPDesktop *desktop, bool apply = true); void sp_selection_to_guides(SPDesktop *desktop); +void sp_selection_symbol(SPDesktop *desktop, bool apply = true); +void sp_selection_unsymbol(SPDesktop *desktop); + void sp_selection_tile(SPDesktop *desktop, bool apply = true); void sp_selection_untile(SPDesktop *desktop); diff --git a/src/selection-describer.cpp b/src/selection-describer.cpp index c141c3da5..391db8950 100644 --- a/src/selection-describer.cpp +++ b/src/selection-describer.cpp @@ -24,6 +24,7 @@ #include "sp-offset.h" #include "sp-flowtext.h" #include "sp-use.h" +#include "sp-symbol.h" #include "sp-rect.h" #include "box3d.h" #include "sp-ellipse.h" @@ -192,7 +193,11 @@ void SelectionDescriber::_updateMessageFromSelection(Inkscape::Selection *select if (!items->next) { // one item char *item_desc = item->description(); - if (SP_IS_USE(item) || (SP_IS_OFFSET(item) && SP_OFFSET (item)->sourceHref)) { + if (SP_IS_USE(item) && SP_IS_SYMBOL(item->firstChild())) { + _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.", + item_desc, in_phrase, + _("Convert symbol to group to edit"), _when_selected); + } else if (SP_IS_USE(item) || (SP_IS_OFFSET(item) && SP_OFFSET (item)->sourceHref)) { _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.", item_desc, in_phrase, _("Use Shift+D to look up original"), _when_selected); diff --git a/src/sp-object.cpp b/src/sp-object.cpp index c16dbaeef..3e18c0835 100644 --- a/src/sp-object.cpp +++ b/src/sp-object.cpp @@ -1409,6 +1409,9 @@ void SPObject::_requireSVGVersion(Inkscape::Version version) { be made. The same applies to 'desc' elements. Therefore, these functions ignore all but the first 'title' child element and first 'desc' child element, except when deleting a title or description. + + This will change in SVG 2, where multiple 'title' and 'desc' elements will + be allowed with different localized strings. */ gchar * SPObject::title() const diff --git a/src/sp-symbol.cpp b/src/sp-symbol.cpp index 87cd210e4..56f862bf3 100644 --- a/src/sp-symbol.cpp +++ b/src/sp-symbol.cpp @@ -405,6 +405,11 @@ static Geom::OptRect sp_symbol_bbox(SPItem const *item, Geom::Affine const &tran Geom::Affine const a( symbol->c2p * transform ); bbox = ((SPItemClass *) (parent_class))->bbox(item, a, type); } + } else { + // Need bounding box for Symbols dialog + + Geom::Affine const a; + bbox = ((SPItemClass *) (parent_class))->bbox(item, a, type); } return bbox; } diff --git a/src/sp-use.cpp b/src/sp-use.cpp index e39f560c3..0f45f5444 100644 --- a/src/sp-use.cpp +++ b/src/sp-use.cpp @@ -321,6 +321,14 @@ sp_use_description(SPItem *item) char *ret; if (use->child) { + + if( SP_IS_SYMBOL( use->child ) ) { + //char *symbol_desc = SP_ITEM(use->child)->description(); + //g_free(symbol_desc); + return g_strdup(_("Clone of Symbol")); + //return g_strdup_printf(_("Clone of Symbol: %s"), symbol_desc ); + } + static unsigned recursion_depth = 0; if (recursion_depth >= 4) { /* TRANSLATORS: Used for statusbar description for long chains: diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp index f1f6c4ab4..8cdb37f4f 100644 --- a/src/ui/clipboard.cpp +++ b/src/ui/clipboard.cpp @@ -7,9 +7,11 @@ * Jon A. Cruz * Incorporates some code from selection-chemistry.cpp, see that file for more credits. * Abhishek Sharma + * Tavmjong Bah * * Copyright (C) 2008 authors * Copyright (C) 2010 Jon A. Cruz + * Copyright (C) 2012 Tavmjong Bah (Symbol additions) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -66,6 +68,8 @@ #include "sp-mask.h" #include "sp-textpath.h" #include "sp-rect.h" +#include "sp-use.h" +#include "sp-symbol.h" #include "live_effects/lpeobject.h" #include "live_effects/lpeobject-reference.h" #include "live_effects/parameter/path.h" @@ -109,6 +113,7 @@ class ClipboardManagerImpl : public ClipboardManager { public: virtual void copy(SPDesktop *desktop); virtual void copyPathParameter(Inkscape::LivePathEffect::PathParam *); + virtual void copySymbol(Inkscape::XML::Node* symbol, gchar const* style); virtual bool paste(SPDesktop *desktop, bool in_place); virtual bool pasteStyle(SPDesktop *desktop); virtual bool pasteSize(SPDesktop *desktop, bool separately, bool apply_x, bool apply_y); @@ -294,6 +299,43 @@ void ClipboardManagerImpl::copyPathParameter(Inkscape::LivePathEffect::PathParam _setClipboardTargets(); } +/** + * Copy a symbol from the symbol dialog. + * @param symbol The Inkscape::XML::Node for the symbol. + */ +void ClipboardManagerImpl::copySymbol(Inkscape::XML::Node* symbol, gchar const* style) +{ + //std::cout << "ClipboardManagerImpl::copySymbol" << std::endl; + if ( symbol == NULL ) { + return; + } + + _discardInternalClipboard(); + _createInternalClipboard(); + + // We add "_duplicate" to have a well defined symbol name that + // bypasses the "prevent_id_classes" routine. We'll get rid of it + // when we paste. + Inkscape::XML::Node *repr = symbol->duplicate(_doc); + Glib::ustring symbol_name = repr->attribute("id"); + + symbol_name += "_inkscape_duplicate"; + repr->setAttribute("id", symbol_name.c_str()); + _defs->appendChild(repr); + + Glib::ustring id("#"); + id += symbol->attribute("id"); + + Inkscape::XML::Node *use = _doc->createElement("svg:use"); + use->setAttribute("xlink:href", id.c_str() ); + // Set a default style in rather than so it can be changed. + use->setAttribute("style", style ); + _root->appendChild(use); + + fit_canvas_to_drawing(_clipboardSPDoc); + _setClipboardTargets(); +} + /** * Paste from the system clipboard into the active desktop. * @param in_place Whether to put the contents where they were when copied. @@ -725,6 +767,14 @@ void ClipboardManagerImpl::_copyUsedDefs(SPItem *item) } } + // Copy symbols: We may want to be more clever... + // if (SP_IS_USE(item)) { + // SPObject *symbol = SP_USE(item)->child; + // if( symbol && SP_IS_SYMBOL(symbol) ) { + // _copyNode(symbol->getRepr(), _doc, _defs); + // } + // } + // recurse for (SPObject *o = item->children ; o != NULL ; o = o->next) { if (SP_IS_ITEM(o)) { diff --git a/src/ui/clipboard.h b/src/ui/clipboard.h index fb28bfc14..b565740c3 100644 --- a/src/ui/clipboard.h +++ b/src/ui/clipboard.h @@ -25,6 +25,7 @@ class SPDesktop; namespace Inkscape { class Selection; +namespace XML { class Node; } namespace LivePathEffect { class PathParam; } namespace UI { @@ -43,6 +44,7 @@ class ClipboardManager { public: virtual void copy(SPDesktop *desktop) = 0; virtual void copyPathParameter(Inkscape::LivePathEffect::PathParam *) = 0; + virtual void copySymbol(Inkscape::XML::Node* symbol, gchar const* style) = 0; virtual bool paste(SPDesktop *desktop, bool in_place = false) = 0; virtual bool pasteStyle(SPDesktop *desktop) = 0; virtual bool pasteSize(SPDesktop *desktop, bool separately, bool apply_x, bool apply_y) = 0; diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert index ba2f53a9e..580b47522 100644 --- a/src/ui/dialog/Makefile_insert +++ b/src/ui/dialog/Makefile_insert @@ -89,6 +89,8 @@ ink_common_sources += \ ui/dialog/svg-fonts-dialog.h \ ui/dialog/swatches.cpp \ ui/dialog/swatches.h \ + ui/dialog/symbols.cpp \ + ui/dialog/symbols.h \ ui/dialog/text-edit.cpp \ ui/dialog/text-edit.h \ ui/dialog/tile.cpp \ diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index 60011ca9d..faba47769 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -33,6 +33,7 @@ #include "ui/dialog/memory.h" #include "ui/dialog/messages.h" #include "ui/dialog/scriptdialog.h" +#include "ui/dialog/symbols.h" #include "ui/dialog/tile.h" #include "ui/dialog/tracedialog.h" #include "ui/dialog/transformation.h" @@ -121,6 +122,7 @@ DialogManager::DialogManager() { registerFactory("SvgFontsDialog", &create); #endif registerFactory("Swatches", &create); + registerFactory("Symbols", &create); registerFactory("TileDialog", &create); registerFactory("Trace", &create); registerFactory("Transformation", &create); @@ -156,6 +158,7 @@ DialogManager::DialogManager() { registerFactory("SvgFontsDialog", &create); #endif registerFactory("Swatches", &create); + registerFactory("Symbols", &create); registerFactory("TileDialog", &create); registerFactory("Trace", &create); registerFactory("Transformation", &create); diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp new file mode 100644 index 000000000..ea08c1cc8 --- /dev/null +++ b/src/ui/dialog/symbols.cpp @@ -0,0 +1,574 @@ +/** + * @file + * Symbols dialog. + */ +/* Authors: + * Copyright (C) 2012 Tavmjong Bah + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "path-prefix.h" +#include "io/sys.h" + +#include "ui/cache/svg_preview_cache.h" +#include "ui/clipboard.h" + +#include "symbols.h" + +#include "desktop.h" +#include "desktop-handles.h" +#include "document.h" +#include "inkscape.h" +#include "sp-root.h" +#include "sp-use.h" +#include "sp-symbol.h" + +#include "verbs.h" +#include "xml/repr.h" + +namespace Inkscape { +namespace UI { + +static Cache::SvgPreview svg_preview_cache; + +namespace Dialog { + + // See: http://developer.gnome.org/gtkmm/stable/classGtk_1_1TreeModelColumnRecord.html +class SymbolColumns : public Gtk::TreeModel::ColumnRecord +{ +public: + + Gtk::TreeModelColumn symbol_id; + Gtk::TreeModelColumn symbol_title; + Gtk::TreeModelColumn< Glib::RefPtr > symbol_image; + + SymbolColumns() { + add(symbol_id); + add(symbol_title); + add(symbol_image); + } +}; + +SymbolColumns* SymbolsDialog::getColumns() +{ + SymbolColumns* columns = new SymbolColumns(); + return columns; +} + +/** + * Constructor + */ +SymbolsDialog::SymbolsDialog( gchar const* prefsPath ) : + UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SYMBOLS), + store(Gtk::ListStore::create(*getColumns())), + iconView(0), + previewScale(0), + previewSize(0), + currentDesktop(0), + deskTrack(), + currentDocument(0), + previewDocument(0), + instanceConns() +{ + + /******************** Table *************************/ + // Replace by Grid for GTK 3.0 + Gtk::Table *table = new Gtk::Table(2, 4, false); + // panel is a cloked Gtk::VBox + _getContents()->pack_start(*Gtk::manage(table), Gtk::PACK_EXPAND_WIDGET); + guint row = 0; + + /******************** Symbol Sets *************************/ + Gtk::Label* labelSet = new Gtk::Label("Symbol set: "); + table->attach(*Gtk::manage(labelSet),0,1,row,row+1,Gtk::SHRINK,Gtk::SHRINK); + + symbolSet = new Gtk::ComboBoxText(); // Fill in later + symbolSet->append("Current Document"); + symbolSet->set_active_text("Current Document"); + table->attach(*Gtk::manage(symbolSet),1,2,row,row+1,Gtk::FILL|Gtk::EXPAND,Gtk::SHRINK); + + sigc::connection connSet = + symbolSet->signal_changed().connect(sigc::mem_fun(*this, &SymbolsDialog::rebuild)); + instanceConns.push_back(connSet); + + ++row; + + /********************* Icon View **************************/ + SymbolColumns* columns = getColumns(); + + iconView = new Gtk::IconView(static_cast >(store)); + //iconView->set_text_column( columns->symbol_id ); + iconView->set_tooltip_column( 1 ); + iconView->set_pixbuf_column( columns->symbol_image ); + + sigc::connection connIconChanged; + connIconChanged = + iconView->signal_selection_changed().connect(sigc::mem_fun(*this, &SymbolsDialog::iconChanged)); + instanceConns.push_back(connIconChanged); + + Gtk::ScrolledWindow *scroller = new Gtk::ScrolledWindow(); + scroller->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); + scroller->add(*Gtk::manage(iconView)); + table->attach(*Gtk::manage(scroller),0,2,row,row+1,Gtk::EXPAND|Gtk::FILL,Gtk::EXPAND|Gtk::FILL); + + ++row; + + /******************** Preview Scale ***********************/ + Gtk::Label* labelScale = new Gtk::Label("Preview scale: "); + table->attach(*Gtk::manage(labelScale),0,1,row,row+1,Gtk::SHRINK,Gtk::SHRINK); + + previewScale = new Gtk::ComboBoxText(); + const gchar *scales[] = + {"Fit", "Fit to width", "Fit to height", "0.1", "0.2", "0.5", "1.0", "2.0", "5.0", NULL}; + for( int i = 0; scales[i]; ++i ) { + previewScale->append(scales[i]); + } + previewScale->set_active_text(scales[0]); + table->attach(*Gtk::manage(previewScale),1,2,row,row+1,Gtk::FILL|Gtk::EXPAND,Gtk::SHRINK); + + sigc::connection connScale = + previewScale->signal_changed().connect(sigc::mem_fun(*this, &SymbolsDialog::rebuild)); + instanceConns.push_back(connScale); + + ++row; + + /******************** Preview Size ************************/ + Gtk::Label* labelSize = new Gtk::Label("Preview size: "); + table->attach(*Gtk::manage(labelSize),0,1,row,row+1,Gtk::SHRINK,Gtk::SHRINK); + + previewSize = new Gtk::ComboBoxText(); + const gchar *sizes[] = {"16", "24", "32", "48", "64", NULL}; + for( int i = 0; sizes[i]; ++i ) { + previewSize->append(sizes[i]); + } + previewSize->set_active_text(sizes[2]); + table->attach(*Gtk::manage(previewSize),1,2,row,row+1,Gtk::FILL|Gtk::EXPAND,Gtk::SHRINK); + + sigc::connection connSize = + previewSize->signal_changed().connect(sigc::mem_fun(*this, &SymbolsDialog::rebuild)); + instanceConns.push_back(connSize); + + ++row; + + /**********************************************************/ + currentDesktop = inkscape_active_desktop(); + currentDocument = sp_desktop_document(currentDesktop); + + previewDocument = symbols_preview_doc(); /* Template to render symbols in */ + previewDocument->ensureUpToDate(); /* Necessary? */ + + key = SPItem::display_key_new(1); + renderDrawing.setRoot(previewDocument->getRoot()->invoke_show(renderDrawing, key, SP_ITEM_SHOW_DISPLAY )); + + get_symbols(); + draw_symbols( currentDocument ); /* Defaults to current document */ + + desktopChangeConn = + deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &SymbolsDialog::setTargetDesktop) ); + instanceConns.push_back( desktopChangeConn ); + deskTrack.connect(GTK_WIDGET(gobj())); +} + +SymbolsDialog::~SymbolsDialog() +{ + for (std::vector::iterator it = instanceConns.begin(); it != instanceConns.end(); ++it) { + it->disconnect(); + } + instanceConns.clear(); + deskTrack.disconnect(); +} + +SymbolsDialog& SymbolsDialog::getInstance() +{ + return *new SymbolsDialog(); +} + +void SymbolsDialog::rebuild() { + + store->clear(); + Glib::ustring symbolSetString = symbolSet->get_active_text(); + + SPDocument* symbolDocument = symbolSets[symbolSetString]; + if( !symbolDocument ) { + // Symbol must be from Current Document (this method of + // checking should be language independent). + symbolDocument = currentDocument; + } + draw_symbols( symbolDocument ); +} + +void SymbolsDialog::iconChanged() { +#if WITH_GTKMM_3_0 + std::vector iconArray = iconView->get_selected_items(); +#else + Gtk::IconView::ArrayHandle_TreePaths iconArray = iconView->get_selected_items(); +#endif + + if( iconArray.empty() ) { + //std::cout << " iconArray empty: huh? " << std::endl; + } else { + Gtk::TreeModel::Path const & path = *iconArray.begin(); + Gtk::ListStore::iterator row = store->get_iter(path); + Glib::ustring symbol_id = (*row)[getColumns()->symbol_id]; + + /* OK, we know symbol name... now we need to copy it to clipboard, bon chance! */ + Glib::ustring symbolSetString = symbolSet->get_active_text(); + + SPDocument* symbolDocument = symbolSets[symbolSetString]; + if( !symbolDocument ) { + // Symbol must be from Current Document (this method of + // checking should be language independent). + symbolDocument = currentDocument; + } + + SPObject* symbol = symbolDocument->getObjectById(symbol_id); + if( symbol ) { + + // Find style for use in + // First look for default style stored in + gchar const* style = symbol->getAttribute("inkscape:symbol-style"); + if( !style ) { + // If no default style in , look in documents. + if( symbolDocument == currentDocument ) { + style = style_from_use( symbol_id.c_str(), currentDocument ); + } else { + style = symbolDocument->getReprRoot()->attribute("style"); + } + } + + ClipboardManager *cm = ClipboardManager::get(); + cm->copySymbol(symbol->getRepr(), style); + } + } +} + +/* Hunts preference directories for symbol files */ +void SymbolsDialog::get_symbols() { + + std::list directories; + + if( Inkscape::IO::file_test( INKSCAPE_SYMBOLSDIR, G_FILE_TEST_EXISTS ) && + Inkscape::IO::file_test( INKSCAPE_SYMBOLSDIR, G_FILE_TEST_IS_DIR ) ) { + directories.push_back( INKSCAPE_SYMBOLSDIR ); + } + if( Inkscape::IO::file_test( profile_path("symbols"), G_FILE_TEST_EXISTS ) && + Inkscape::IO::file_test( profile_path("symbols"), G_FILE_TEST_IS_DIR ) ) { + directories.push_back( profile_path("symbols") ); + } + + std::list::iterator it; + for( it = directories.begin(); it != directories.end(); ++it ) { + + GError *err = 0; + GDir *dir = g_dir_open( (*it).c_str(), 0, &err ); + if( dir ) { + + gchar *filename = 0; + while( (filename = (gchar *)g_dir_read_name( dir ) ) != NULL) { + + gchar *fullname = g_build_filename((*it).c_str(), filename, NULL); + + if ( !Inkscape::IO::file_test( fullname, G_FILE_TEST_IS_DIR ) ) { + + SPDocument* symbol_doc = SPDocument::createNewDoc( fullname, FALSE ); + if( symbol_doc ) { + symbolSets[Glib::ustring(filename)]= symbol_doc; + symbolSet->append(filename); + } + } + g_free( fullname ); + } + g_dir_close( dir ); + } + } +} + +GSList* SymbolsDialog::symbols_in_doc_recursive (SPObject *r, GSList *l) +{ + + // Stop multiple counting of same symbol + if( SP_IS_USE(r) ) { + return l; + } + + if( SP_IS_SYMBOL(r) ) { + l = g_slist_prepend (l, r); + } + + for (SPObject *child = r->firstChild(); child; child = child->getNext()) { + l = symbols_in_doc_recursive( child, l ); + } + + return l; +} + +GSList* SymbolsDialog::symbols_in_doc( SPDocument* symbolDocument ) { + + GSList *l = NULL; + l = symbols_in_doc_recursive (symbolDocument->getRoot(), l ); + return l; +} + +GSList* SymbolsDialog::use_in_doc_recursive (SPObject *r, GSList *l) +{ + + if( SP_IS_USE(r) ) { + l = g_slist_prepend (l, r); + } + + for (SPObject *child = r->firstChild(); child; child = child->getNext()) { + l = use_in_doc_recursive( child, l ); + } + + return l; +} + +GSList* SymbolsDialog::use_in_doc( SPDocument* useDocument ) { + + GSList *l = NULL; + l = use_in_doc_recursive (useDocument->getRoot(), l ); + return l; +} + +// Returns style from first element found that references id. +// This is a last ditch effort to find a style. +gchar const* SymbolsDialog::style_from_use( gchar const* id, SPDocument* document) { + + gchar const* style = 0; + GSList* l = use_in_doc( document ); + for( ; l != NULL; l = l->next ) { + SPObject* use = SP_OBJECT(l->data); + if( SP_IS_USE( use ) ) { + gchar const *href = use->getRepr()->attribute("xlink:href"); + if( href ) { + Glib::ustring href2(href); + Glib::ustring id2(id); + id2 = "#" + id2; + if( !href2.compare(id2) ) { + style = use->getRepr()->attribute("style"); + break; + } + } + } + } + return style; +} + +void SymbolsDialog::draw_symbols( SPDocument* symbolDocument ) { + + + SymbolColumns* columns = getColumns(); + + GSList* l = symbols_in_doc( symbolDocument ); + for( ; l != NULL; l = l->next ) { + + SPObject* symbol = SP_OBJECT(l->data); + if (!SP_IS_SYMBOL(symbol)) { + //std::cout << " Error: not symbol" << std::endl; + continue; + } + + gchar const *id = symbol->getRepr()->attribute("id"); + gchar const *title = symbol->title(); // From title element + if( !title ) { + title = id; + } + + Glib::RefPtr pixbuf = create_symbol_image(id, symbolDocument, &renderDrawing, key ); + if( pixbuf ) { + + Gtk::ListStore::iterator row = store->append(); + (*row)[columns->symbol_id] = Glib::ustring( id ); + (*row)[columns->symbol_title] = Glib::ustring( title ); + (*row)[columns->symbol_image] = pixbuf; + } + } +} + +/* + * Returns image of symbol. + * + * Symbols normally are not visible. They must be referenced by a + * element. A temporary document is created with a dummy + * element and a element that references the symbol + * element. Each real symbol is swapped in for the dummy symbol and + * the temporary document is rendered. + */ +Glib::RefPtr +SymbolsDialog::create_symbol_image(gchar const *symbol_id, + SPDocument *source, + Inkscape::Drawing* drawing, + unsigned /*visionkey*/) +{ + + // Retrieve the symbol named 'symbol_id' from the source SVG document + SPObject const* symbol = source->getObjectById(symbol_id); + if (symbol == NULL) { + //std::cout << " Failed to find symbol: " << symbol_id << std::endl; + //return 0; + } + + // Create a copy repr of the symbol with id="the_symbol" + Inkscape::XML::Document *xml_doc = previewDocument->getReprDoc(); + Inkscape::XML::Node *repr = symbol->getRepr()->duplicate(xml_doc); + repr->setAttribute("id", "the_symbol"); + + // Replace old "the_symbol" in previewDocument by new. + Inkscape::XML::Node *root = previewDocument->getReprRoot(); + SPObject *symbol_old = previewDocument->getObjectById("the_symbol"); + if (symbol_old) { + symbol_old->deleteObject(false); + } + + // First look for default style stored in + gchar const* style = repr->attribute("inkscape:symbol-style"); + if( !style ) { + // If no default style in , look in documents. + if( source == currentDocument ) { + style = style_from_use( symbol_id, source ); + } else { + style = source->getReprRoot()->attribute("style"); + } + } + + // This is for display in Symbols dialog only + if( style ) { + repr->setAttribute( "style", style ); + } + + // BUG: Symbols don't work if defined outside of . Causes Inkscape + // crash when trying to read in such a file. + root->appendChild(repr); + //defsrepr->appendChild(repr); + Inkscape::GC::release(repr); + + // Uncomment this to get the previewDocument documents saved (useful for debugging) + // FILE *fp = fopen (g_strconcat(symbol_id, ".svg", NULL), "w"); + // sp_repr_save_stream(previewDocument->getReprDoc(), fp); + // fclose (fp); + + // Make sure previewDocument is up-to-date. + previewDocument->getRoot()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + previewDocument->ensureUpToDate(); + + // Make sure we have symbol in previewDocument + SPObject *object_temp = previewDocument->getObjectById( "the_use" ); + previewDocument->getRoot()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + previewDocument->ensureUpToDate(); + + // if( object_temp == NULL || !SP_IS_ITEM(object_temp) ) { + // //std::cout << " previewDocument broken?" << std::endl; + // //return 0; + // } + + SPItem *item = SP_ITEM(object_temp); + + // Find object's bbox in document. + // Note symbols can have own viewport... ignore for now. + //Geom::OptRect dbox = item->geometricBounds(); + Geom::OptRect dbox = item->documentVisualBounds(); + // if (!dbox) { + // //std::cout << " No dbox" << std::endl; + // //return NULL; + // } + + Glib::ustring previewSizeString = previewSize->get_active_text(); + unsigned psize = atol( previewSizeString.c_str() ); + + Glib::ustring previewScaleString = previewScale->get_active_text(); + int previewScaleRow = previewScale->get_active_row_number(); + + /* Update to renderable state */ + Glib::ustring key = svg_preview_cache.cache_key(previewDocument->getURI(), symbol_id, psize); + //std::cout << " Key: " << key << std::endl; + // FIX ME + //Glib::RefPtr pixbuf = Glib::wrap(svg_preview_cache.get_preview_from_cache(key)); + Glib::RefPtr pixbuf = Glib::RefPtr(0); + + if (!pixbuf) { + + /* Scale symbols to fit */ + double scale = 1.0; + switch (previewScaleRow) { + case 0: + /* Fit */ + scale = psize/std::max(dbox->width(),dbox->height()); + break; + case 1: + /* Fit width */ + scale = psize/dbox->width(); + break; + case 2: + /* Fit height */ + scale = psize/dbox->height(); + break; + default: + scale = atof( previewScaleString.c_str() ); + } + + pixbuf = Glib::wrap(render_pixbuf(*drawing, scale, *dbox, psize)); + svg_preview_cache.set_preview_in_cache(key, pixbuf->gobj()); + } + + return pixbuf; +} + +/* + * Return empty doc to render symbols in. + * Symbols are by default not rendered so a element is + * provided. + */ +SPDocument* SymbolsDialog::symbols_preview_doc() +{ + // BUG: must be inside + gchar const *buffer = +"" +" " +" " +" " +" " +""; + + return SPDocument::createNewDocFromMem( buffer, strlen(buffer), FALSE ); +} + +void SymbolsDialog::setTargetDesktop(SPDesktop *desktop) +{ + if (this->currentDesktop != desktop) { + this->currentDesktop = desktop; + if( !symbolSets[symbolSet->get_active_text()] ) { + // Symbol set is from Current document, update + rebuild(); + } + } +} + + +} //namespace Dialogs +} //namespace UI +} //namespace Inkscape + + + diff --git a/src/ui/dialog/symbols.h b/src/ui/dialog/symbols.h new file mode 100644 index 000000000..c2bb4448e --- /dev/null +++ b/src/ui/dialog/symbols.h @@ -0,0 +1,114 @@ +/** @file + * @brief Symbols dialog + */ +/* Authors: + * Tavmjong Bah + * + * Copyright (C) 2012 Tavmjong Bah + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef INKSCAPE_UI_DIALOG_SYMBOLS_H +#define INKSCAPE_UI_DIALOG_SYMBOLS_H + +#include "ui/widget/panel.h" +#include "ui/widget/button.h" + +#include "ui/dialog/desktop-tracker.h" + +#include "display/drawing.h" + +#include +#include + +#include + +class SPObject; + +namespace Inkscape { +namespace UI { +namespace Dialog { + +class SymbolColumns; // For Gtk::ListStore + +/** + * A dialog that displays selectable symbols. + */ +class SymbolsDialog : public UI::Widget::Panel { + +public: + SymbolsDialog( gchar const* prefsPath = "/dialogs/symbols" ); + virtual ~SymbolsDialog(); + + static SymbolsDialog& getInstance(); + +protected: + + +private: + SymbolsDialog(SymbolsDialog const &); // no copy + SymbolsDialog &operator=(SymbolsDialog const &); // no assign + + static SymbolColumns *getColumns(); + + void rebuild(); + void iconChanged(); + + void get_symbols(); + void draw_symbols( SPDocument* symbol_document ); + SPDocument* symbols_preview_doc(); + + GSList* symbols_in_doc_recursive(SPObject *r, GSList *l); + GSList* symbols_in_doc( SPDocument* document ); + GSList* use_in_doc_recursive(SPObject *r, GSList *l); + GSList* use_in_doc( SPDocument* document ); + gchar const* style_from_use( gchar const* id, SPDocument* document); + + Glib::RefPtr + create_symbol_image(gchar const *symbol_name, + SPDocument *source, Inkscape::Drawing* drawing, + unsigned /*visionkey*/); + + /* Keep track of all symbol template documents */ + std::map symbolSets; + + + Glib::RefPtr store; + Gtk::ComboBoxText* symbolSet; + Gtk::IconView* iconView; + Gtk::ComboBoxText* previewScale; + Gtk::ComboBoxText* previewSize; + + void setTargetDesktop(SPDesktop *desktop); + SPDesktop* currentDesktop; + DesktopTracker deskTrack; + SPDocument* currentDocument; + SPDocument* previewDocument; /* Document to render single symbol */ + + /* For rendering the template drawing */ + unsigned key; + Inkscape::Drawing renderDrawing; + + std::vector instanceConns; + sigc::connection desktopChangeConn; + +}; + +} //namespace Dialogs +} //namespace UI +} //namespace Inkscape + + +#endif // INKSCAPE_UI_DIALOG_SYMBOLS_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/verbs.cpp b/src/verbs.cpp index 450b800c1..8c45ce665 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -78,6 +78,7 @@ #include "ui/dialog/layers.h" #include "ui/dialog/object-properties.h" #include "ui/dialog/swatches.h" +#include "ui/dialog/symbols.h" #include "ui/dialog/spellcheck.h" #include "ui/icon-names.h" #include "ui/tool/node-tool.h" @@ -957,6 +958,12 @@ void EditVerb::perform(SPAction *action, void *data) case SP_VERB_EDIT_UNTILE: sp_selection_untile(dt); break; + case SP_VERB_EDIT_SYMBOL: + sp_selection_symbol(dt); + break; + case SP_VERB_EDIT_UNSYMBOL: + sp_selection_unsymbol(dt); + break; case SP_VERB_EDIT_CLEAR_ALL: sp_edit_clear_all(dt); break; @@ -1912,6 +1919,9 @@ void DialogVerb::perform(SPAction *action, void *data) case SP_VERB_DIALOG_SWATCHES: dt->_dlg_mgr->showDialog("Swatches"); break; + case SP_VERB_DIALOG_SYMBOLS: + dt->_dlg_mgr->showDialog("Symbols"); + break; case SP_VERB_DIALOG_TRANSFORM: dt->_dlg_mgr->showDialog("Transformation"); break; @@ -2375,6 +2385,10 @@ Verb *Verb::_base_verbs[] = { N_("Convert selection to a rectangle with tiled pattern fill"), NULL), new EditVerb(SP_VERB_EDIT_UNTILE, "ObjectsFromPattern", N_("Pattern to _Objects"), N_("Extract objects from a tiled pattern fill"), NULL), + new EditVerb(SP_VERB_EDIT_SYMBOL, "ObjectsToSymbol", N_("Group to Symbol"), + N_("Convert group to a symbol"), NULL), + new EditVerb(SP_VERB_EDIT_UNSYMBOL, "ObjectsFromSymbol", N_("Symbol to Group"), + N_("Extract group from a symbol"), NULL), new EditVerb(SP_VERB_EDIT_CLEAR_ALL, "EditClearAll", N_("Clea_r All"), N_("Delete all objects from document"), NULL), new EditVerb(SP_VERB_EDIT_SELECT_ALL, "EditSelectAll", N_("Select Al_l"), @@ -2748,6 +2762,8 @@ Verb *Verb::_base_verbs[] = { // TRANSLATORS: "Swatches" means: color samples new DialogVerb(SP_VERB_DIALOG_SWATCHES, "DialogSwatches", N_("S_watches..."), N_("Select colors from a swatches palette"), GTK_STOCK_SELECT_COLOR), + new DialogVerb(SP_VERB_DIALOG_SYMBOLS, "DialogSymbols", N_("S_ymbols..."), + N_("Select symbol from a symbols palette"), GTK_STOCK_SELECT_COLOR), new DialogVerb(SP_VERB_DIALOG_TRANSFORM, "DialogTransform", N_("Transfor_m..."), N_("Precisely control objects' transformations"), INKSCAPE_ICON("dialog-transform")), new DialogVerb(SP_VERB_DIALOG_ALIGN_DISTRIBUTE, "DialogAlignDistribute", N_("_Align and Distribute..."), diff --git a/src/verbs.h b/src/verbs.h index da2adb52e..c47d3ae16 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -84,6 +84,8 @@ enum { SP_VERB_EDIT_SELECTION_2_GUIDES, SP_VERB_EDIT_TILE, SP_VERB_EDIT_UNTILE, + SP_VERB_EDIT_SYMBOL, + SP_VERB_EDIT_UNSYMBOL, SP_VERB_EDIT_CLEAR_ALL, SP_VERB_EDIT_SELECT_ALL, SP_VERB_EDIT_SELECT_ALL_IN_ALL_LAYERS, @@ -264,6 +266,7 @@ enum { SP_VERB_DIALOG_FILL_STROKE, SP_VERB_DIALOG_GLYPHS, SP_VERB_DIALOG_SWATCHES, + SP_VERB_DIALOG_SYMBOLS, SP_VERB_DIALOG_TRANSFORM, SP_VERB_DIALOG_ALIGN_DISTRIBUTE, SP_VERB_DIALOG_SPRAY_OPTION, -- cgit v1.2.3 From a67988fae58348562bcde83ea1c5fb8aa4eecb78 Mon Sep 17 00:00:00 2001 From: John Smith Date: Fri, 12 Oct 2012 13:15:19 +0900 Subject: Fix for 177931 : Shift click layer icons to trigger solo (bzr r11784) --- src/ui/dialog/layers.cpp | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp index 457f7c147..55a2f19a5 100644 --- a/src/ui/dialog/layers.cpp +++ b/src/ui/dialog/layers.cpp @@ -562,26 +562,36 @@ void LayersPanel::_handleButtonEvent(GdkEventButton* event) { static unsigned doubleclick = 0; - // TODO - fix to a better is-popup function if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) { + // TODO - fix to a better is-popup function + Gtk::TreeModel::Path path; + int x = static_cast(event->x); + int y = static_cast(event->y); + if ( _tree.get_path_at_pos( x, y, path ) ) { + _checkTreeSelection(); + _popupMenu.popup(event->button, event->time); + } + } - { - Gtk::TreeModel::Path path; - Gtk::TreeViewColumn* col = 0; - int x = static_cast(event->x); - int y = static_cast(event->y); - int x2 = 0; - int y2 = 0; - if ( _tree.get_path_at_pos( x, y, - path, col, - x2, y2 ) ) { - _checkTreeSelection(); - _popupMenu.popup(event->button, event->time); + if ( event->type == GDK_BUTTON_RELEASE && (event->button == 1) + && (event->state & GDK_SHIFT_MASK)) { + // Shift left click on the visible/lock columns toggles "solo" mode + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { + if (col == _tree.get_column(COL_VISIBLE-1)) { + _takeAction(BUTTON_SOLO); + } else if (col == _tree.get_column(COL_LOCKED-1)) { + _takeAction(BUTTON_LOCK_OTHERS); } } - } + if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { doubleclick = 1; } -- cgit v1.2.3 From c384a6116dd087856bd91806e9f8fb5e0eaa6dd8 Mon Sep 17 00:00:00 2001 From: John Smith Date: Fri, 12 Oct 2012 14:39:08 +0900 Subject: Fix for 1019974 : Default layer names are inconsistent (bzr r11785) --- src/layer-manager.cpp | 81 ++++++++++++++++++++++---------------- src/layer-manager.h | 1 + src/ui/dialog/layer-properties.cpp | 7 +++- 3 files changed, 53 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/layer-manager.cpp b/src/layer-manager.cpp index 894758a97..c02d75d16 100644 --- a/src/layer-manager.cpp +++ b/src/layer-manager.cpp @@ -159,53 +159,66 @@ void LayerManager::setCurrentLayer( SPObject* obj ) } } -void LayerManager::renameLayer( SPObject* obj, gchar const *label, bool uniquify ) +/* + * Return a unique layer name similar to param label + * A unique name is made by substituting or appending the label's number suffix with + * the next unique larger number suffix not already used for any layer name + */ +Glib::ustring LayerManager::getNextLayerName( SPObject* obj, gchar const *label) { - Glib::ustring incoming( label ? label : "" ); + Glib::ustring incoming( label ? label : "Layer 1" ); Glib::ustring result(incoming); Glib::ustring base(incoming); + Glib::ustring split(" "); guint startNum = 1; - if (uniquify) { + gint pos = base.length()-1; + while (pos >= 0 && g_ascii_isdigit(base[pos])) { + pos-- ; + } - Glib::ustring::size_type pos = base.rfind('#'); - if ( pos != Glib::ustring::npos ) { - gchar* numpart = g_strdup(base.substr(pos+1).c_str()); - if ( numpart ) { - gchar* endPtr = NULL; - guint64 val = g_ascii_strtoull( numpart, &endPtr, 10); - if ( ((val > 0) || (endPtr != numpart)) && (val < 65536) ) { - base.erase( pos ); - result = base; - startNum = static_cast(val); - } - g_free(numpart); - } + gchar* numpart = g_strdup(base.substr(pos+1).c_str()); + if ( numpart ) { + gchar* endPtr = NULL; + guint64 val = g_ascii_strtoull( numpart, &endPtr, 10); + if ( ((val > 0) || (endPtr != numpart)) && (val < 65536) ) { + base.erase( pos+1); + result = incoming; + startNum = static_cast(val); + split = ""; } + g_free(numpart); + } - std::set currentNames; - GSList const *layers=_document->getResourceList("layer"); - SPObject *root=_desktop->currentRoot(); - if ( root ) { - for ( GSList const *iter=layers ; iter ; iter = iter->next ) { - SPObject *layer=static_cast(iter->data); - if ( layer != obj ) { - currentNames.insert( layer->label() ? Glib::ustring(layer->label()) : Glib::ustring() ); - } + std::set currentNames; + GSList const *layers=_document->getResourceList("layer"); + SPObject *root=_desktop->currentRoot(); + if ( root ) { + for ( GSList const *iter=layers ; iter ; iter = iter->next ) { + SPObject *layer=static_cast(iter->data); + if ( layer != obj ) { + currentNames.insert( layer->label() ? Glib::ustring(layer->label()) : Glib::ustring() ); } } + } - // Not sure if we need to cap it, but we'll just be paranoid for the moment - // Intentionally unsigned - guint endNum = startNum + 3000; - for ( guint i = startNum; (i < endNum) && (currentNames.find(result) != currentNames.end()); i++ ) { - gchar* suffix = g_strdup_printf("#%d", i); - result = base; - result += suffix; + // Not sure if we need to cap it, but we'll just be paranoid for the moment + // Intentionally unsigned + guint endNum = startNum + 3000; + for ( guint i = startNum; (i < endNum) && (currentNames.find(result) != currentNames.end()); i++ ) { + result = Glib::ustring::format(base, split, i); + } - g_free(suffix); - } + return result; +} +void LayerManager::renameLayer( SPObject* obj, gchar const *label, bool uniquify ) +{ + Glib::ustring incoming( label ? label : "" ); + Glib::ustring result(incoming); + + if (uniquify) { + result = getNextLayerName(obj, label); } obj->setLabel( result.c_str() ); diff --git a/src/layer-manager.h b/src/layer-manager.h index fbb22d405..1b69324d5 100644 --- a/src/layer-manager.h +++ b/src/layer-manager.h @@ -30,6 +30,7 @@ public: void setCurrentLayer( SPObject* obj ); void renameLayer( SPObject* obj, gchar const *label, bool uniquify ); + Glib::ustring getNextLayerName( SPObject* obj, gchar const *label); sigc::connection connectCurrentLayerChanged(const sigc::slot & slot) { return _layer_changed_signal.connect(slot); diff --git a/src/ui/dialog/layer-properties.cpp b/src/ui/dialog/layer-properties.cpp index 35a235dbc..4f9edf774 100644 --- a/src/ui/dialog/layer-properties.cpp +++ b/src/ui/dialog/layer-properties.cpp @@ -331,8 +331,11 @@ void LayerPropertiesDialog::Rename::perform(LayerPropertiesDialog &dialog) { void LayerPropertiesDialog::Create::setup(LayerPropertiesDialog &dialog) { dialog.set_title(_("Add Layer")); - //TODO: find an unused layer number, forming name from _("Layer ") + "%d" - dialog._layer_name_entry.set_text(_("Layer")); + + // Set the initial name to the "next available" layer name + LayerManager *mgr = dialog._desktop->layer_manager; + Glib::ustring newName = mgr->getNextLayerName(NULL, dialog._desktop->currentLayer()->label()); + dialog._layer_name_entry.set_text(newName.c_str()); dialog._apply_button.set_label(_("_Add")); dialog._setup_position_controls(); } -- cgit v1.2.3 From 89f3de6cdd15aed516c23c07a0b02e7fb39b5ca1 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Fri, 12 Oct 2012 10:42:52 +0200 Subject: Fix for compiling with pre gtkmm 2.24 libraries. (bzr r11787) --- src/ui/dialog/symbols.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src') diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp index ea08c1cc8..21a178b57 100644 --- a/src/ui/dialog/symbols.cpp +++ b/src/ui/dialog/symbols.cpp @@ -101,7 +101,11 @@ SymbolsDialog::SymbolsDialog( gchar const* prefsPath ) : table->attach(*Gtk::manage(labelSet),0,1,row,row+1,Gtk::SHRINK,Gtk::SHRINK); symbolSet = new Gtk::ComboBoxText(); // Fill in later +#if WITH_GTKMM_2_24 symbolSet->append("Current Document"); +#else + symbolSet->append_text("Current Document"); +#endif symbolSet->set_active_text("Current Document"); table->attach(*Gtk::manage(symbolSet),1,2,row,row+1,Gtk::FILL|Gtk::EXPAND,Gtk::SHRINK); @@ -139,7 +143,11 @@ SymbolsDialog::SymbolsDialog( gchar const* prefsPath ) : const gchar *scales[] = {"Fit", "Fit to width", "Fit to height", "0.1", "0.2", "0.5", "1.0", "2.0", "5.0", NULL}; for( int i = 0; scales[i]; ++i ) { +#if WITH_GTKMM_2_24 previewScale->append(scales[i]); +#else + previewScale->append_text(scales[i]); +#endif } previewScale->set_active_text(scales[0]); table->attach(*Gtk::manage(previewScale),1,2,row,row+1,Gtk::FILL|Gtk::EXPAND,Gtk::SHRINK); @@ -157,7 +165,12 @@ SymbolsDialog::SymbolsDialog( gchar const* prefsPath ) : previewSize = new Gtk::ComboBoxText(); const gchar *sizes[] = {"16", "24", "32", "48", "64", NULL}; for( int i = 0; sizes[i]; ++i ) { +#if WITH_GTKMM_2_24 previewSize->append(sizes[i]); +#else + previewSize->append_text(sizes[i]); +#endif + } previewSize->set_active_text(sizes[2]); table->attach(*Gtk::manage(previewSize),1,2,row,row+1,Gtk::FILL|Gtk::EXPAND,Gtk::SHRINK); @@ -291,7 +304,11 @@ void SymbolsDialog::get_symbols() { SPDocument* symbol_doc = SPDocument::createNewDoc( fullname, FALSE ); if( symbol_doc ) { symbolSets[Glib::ustring(filename)]= symbol_doc; +#if WITH_GTKMM_2_24 symbolSet->append(filename); +#else + symbolSet->append_text(filename); +#endif } } g_free( fullname ); -- cgit v1.2.3