Code

First (very limited) version of the 3D box tool; allows for drawing of new boxes...
[inkscape.git] / src / verbs.cpp
index 25c805c3c30a62490d16c10183170dafbf77def0..04a49f37c4bd3a58d9ad03275d5e548d96a5f974 100644 (file)
 #include "sp-flowtext.h"
 #include "layer-fns.h"
 #include "node-context.h"
+#include "select-context.h"
+#include "seltrans.h"
 #include "gradient-context.h"
 #include "shape-editor.h"
+#include "draw-context.h"
 
 
 /**
@@ -129,12 +132,13 @@ static void show_panel( Inkscape::UI::Widget::Panel &panel, char const *prefs_pa
         Gtk::VBox *mainVBox = dia->get_vbox();
         mainVBox->pack_start(panel);
         dia->show_all_children();
-        dia->present();
         dia->read_geometry();
+        dia->present();
     } else {
-        Gtk::Dialog *dia = dynamic_cast<Gtk::Dialog*>(container);
+        PanelDialog *dia = dynamic_cast<PanelDialog*>(container);
         if ( dia ) {
             //g_message("Found an existing dialog");
+            dia->read_geometry();
             dia->present();
         } else {
             g_message("Failed to find an existing dialog");
@@ -1257,7 +1261,17 @@ ObjectVerb::perform( SPAction *action, void *data, void *pdata )
     if (sel->isEmpty())
         return;
 
-    NR::Point const center(sel->bounds().midpoint());
+    NR::Maybe<NR::Rect> bbox = sel->bounds();
+    if (!bbox) {
+        return;
+    }
+    // If the rotation center of the selection is visible, choose it as reference point
+    // for horizontal and vertical flips. Otherwise, take the center of the bounding box.
+    NR::Point center;
+    if (tools_isactive(dt, TOOLS_SELECT) && sel->center() && SP_SELECT_CONTEXT(ec)->_seltrans->centerIsVisible())
+        center = *sel->center();
+    else
+        center = bbox->midpoint();
 
     switch (reinterpret_cast<std::size_t>(data)) {
         case SP_VERB_OBJECT_ROTATE_90_CW:
@@ -1282,8 +1296,23 @@ ObjectVerb::perform( SPAction *action, void *data, void *pdata )
             flowtext_to_text();
             break;
         case SP_VERB_OBJECT_FLIP_HORIZONTAL:
+            // When working with the node tool ...
             if (tools_isactive(dt, TOOLS_NODES)) {
-                SP_NODE_CONTEXT(ec)->shape_editor->flip(NR::X);
+                Inkscape::NodePath::Node *active_node = Inkscape::NodePath::Path::active_node;
+
+                // ... and one of the nodes is currently mouseovered ...
+                if (active_node) {
+
+                    // ... flip the selected nodes about that node
+                    SP_NODE_CONTEXT(ec)->shape_editor->flip(NR::X, active_node->pos);
+               } else {
+
+                    // ... or else about the center of their bounding box.
+                    SP_NODE_CONTEXT(ec)->shape_editor->flip(NR::X);
+                }
+
+            // When working with the selector tool, flip the selection about its rotation center 
+            // (if it is visible) or about the center of the bounding box.
             } else {
                 sp_selection_scale_relative(sel, center, NR::scale(-1.0, 1.0));
             }
@@ -1291,8 +1320,14 @@ ObjectVerb::perform( SPAction *action, void *data, void *pdata )
                              _("Flip horizontally"));
             break;
         case SP_VERB_OBJECT_FLIP_VERTICAL:
+            // The behaviour is analogous to flipping horizontally
             if (tools_isactive(dt, TOOLS_NODES)) {
-                SP_NODE_CONTEXT(ec)->shape_editor->flip(NR::Y);
+                Inkscape::NodePath::Node *active_node = Inkscape::NodePath::Path::active_node;
+                if (active_node) {
+                    SP_NODE_CONTEXT(ec)->shape_editor->flip(NR::Y, active_node->pos);
+                } else {
+                    SP_NODE_CONTEXT(ec)->shape_editor->flip(NR::Y);
+                }
             } else {
                 sp_selection_scale_relative(sel, center, NR::scale(1.0, -1.0));
             }
@@ -1353,6 +1388,9 @@ ContextVerb::perform(SPAction *action, void *data, void *pdata)
         case SP_VERB_CONTEXT_RECT:
             tools_switch_current(TOOLS_SHAPES_RECT);
             break;
+        case SP_VERB_CONTEXT_3DBOX:
+            tools_switch_current(TOOLS_SHAPES_3DBOX);
+            break;
         case SP_VERB_CONTEXT_ARC:
             tools_switch_current(TOOLS_SHAPES_ARC);
             break;
@@ -1402,6 +1440,10 @@ ContextVerb::perform(SPAction *action, void *data, void *pdata)
             prefs_set_int_attribute("dialogs.preferences", "page", PREFS_PAGE_TOOLS_SHAPES_RECT);
             dt->_dlg_mgr->showDialog("InkscapePreferences");
             break;
+        case SP_VERB_CONTEXT_3DBOX_PREFS:
+            prefs_set_int_attribute("dialogs.preferences", "page", PREFS_PAGE_TOOLS_SHAPES_3DBOX);
+            dt->_dlg_mgr->showDialog("InkscapePreferences");
+            break;
         case SP_VERB_CONTEXT_ARC_PREFS:
             prefs_set_int_attribute("dialogs.preferences", "page", PREFS_PAGE_TOOLS_SHAPES_ELLIPSE);
             dt->_dlg_mgr->showDialog("InkscapePreferences");
@@ -1478,6 +1520,7 @@ ZoomVerb::perform(SPAction *action, void *data, void *pdata)
     SPDesktop *dt = static_cast<SPDesktop*>(sp_action_get_view(action));
     if (!dt)
         return;
+    SPEventContext *ec = dt->event_context;
 
     SPDocument *doc = sp_desktop_document(dt);
 
@@ -1490,12 +1533,32 @@ ZoomVerb::perform(SPAction *action, void *data, void *pdata)
     switch (GPOINTER_TO_INT(data)) {
         case SP_VERB_ZOOM_IN:
         {
+            // While drawing with the pen/pencil tool, zoom towards the end of the unfinished path
+            if (tools_isactive(dt, TOOLS_FREEHAND_PENCIL) || tools_isactive(dt, TOOLS_FREEHAND_PEN)) {
+                SPCurve *rc = SP_DRAW_CONTEXT(ec)->red_curve;
+                if (sp_curve_last_bpath(rc)) {
+                    NR::Point const zoom_to (sp_curve_last_point(rc));
+                    dt->zoom_relative_keep_point(zoom_to, zoom_inc);
+                    break;
+                }
+            }
+
             NR::Rect const d = dt->get_display_area();
             dt->zoom_relative( d.midpoint()[NR::X], d.midpoint()[NR::Y], zoom_inc);
             break;
         }
         case SP_VERB_ZOOM_OUT:
         {
+            // While drawing with the pen/pencil tool, zoom away from the end of the unfinished path
+            if (tools_isactive(dt, TOOLS_FREEHAND_PENCIL) || tools_isactive(dt, TOOLS_FREEHAND_PEN)) {
+                SPCurve *rc = SP_DRAW_CONTEXT(ec)->red_curve;
+                if (sp_curve_last_bpath(rc)) {
+                    NR::Point const zoom_to (sp_curve_last_point(rc));
+                    dt->zoom_relative_keep_point(zoom_to, 1 / zoom_inc);
+                    break;
+                }
+            }
+
             NR::Rect const d = dt->get_display_area();
             dt->zoom_relative( d.midpoint()[NR::X], d.midpoint()[NR::Y], 1 / zoom_inc );
             break;
@@ -1546,7 +1609,7 @@ ZoomVerb::perform(SPAction *action, void *data, void *pdata)
             sp_namedview_toggle_guides(doc, repr);
             break;
         case SP_VERB_TOGGLE_GRID:
-            sp_namedview_toggle_grid(doc, repr);
+            dt->toggleGrid();
             break;
 #ifdef HAVE_GTK_WINDOW_FULLSCREEN
         case SP_VERB_FULLSCREEN:
@@ -1606,6 +1669,7 @@ DialogVerb::perform(SPAction *action, void *data, void *pdata)
             break;
         case SP_VERB_DIALOG_FILL_STROKE:
             sp_object_properties_dialog();
+            // dt->_dlg_mgr->showDialog("FillAndStroke");
             break;
         case SP_VERB_DIALOG_SWATCHES:
             show_panel( Inkscape::UI::Dialogs::SwatchesPanel::getInstance(), "dialogs.swatches", SP_VERB_DIALOG_SWATCHES);
@@ -1962,8 +2026,80 @@ FitCanvasVerb::perform(SPAction *action, void *data, void *pdata)
 /* *********** End Fit Canvas ********** */
 
 
+/* *********** Lock'N'Hide ********** */
 
+/** \brief A class to represent the object unlocking and unhiding verbs */
+class LockAndHideVerb : public Verb {
+private:
+    static void perform(SPAction *action, void *mydata, void *otherdata);
+    static SPActionEventVector vector;
+protected:
+    virtual SPAction *make_action(Inkscape::UI::View::View *view);
+public:
+    /** \brief Use the Verb initializer with the same parameters. */
+    LockAndHideVerb(unsigned int const code,
+                   gchar const *id,
+                   gchar const *name,
+                   gchar const *tip,
+                   gchar const *image) :
+        Verb(code, id, name, tip, image)
+    {
+        set_default_sensitive(true);
+    }
+}; /* LockAndHideVerb class */
+
+/**
+ * The vector to attach in the lock'n'hide verb.
+ */
+SPActionEventVector LockAndHideVerb::vector =
+            {{NULL},LockAndHideVerb::perform, NULL, NULL, NULL, NULL};
+
+/** \brief  Create an action for a \c LockAndHideVerb
+    \param  view  Which view the action should be created for
+    \return The built action.
+
+    Calls \c make_action_helper with the \c vector.
+*/
+SPAction *
+LockAndHideVerb::make_action(Inkscape::UI::View::View *view)
+{
+    SPAction *action = make_action_helper(view, &vector);
+    return action;
+}
+
+/** \brief  Decode the verb code and take appropriate action */
+void
+LockAndHideVerb::perform(SPAction *action, void *data, void *pdata)
+{
+    SPDesktop *dt = static_cast<SPDesktop*>(sp_action_get_view(action));
+    if (!dt) return;
+    SPDocument *doc = sp_desktop_document(dt);
+    if (!doc) return;
+    
+    switch ((long) data) {
+        case SP_VERB_UNLOCK_ALL:
+            unlock_all(dt);
+            sp_document_done(doc, SP_VERB_UNLOCK_ALL, _("Unlock all objects in the current layer"));
+            break;
+        case SP_VERB_UNLOCK_ALL_IN_ALL_LAYERS:
+            unlock_all_in_all_layers(dt);
+            sp_document_done(doc, SP_VERB_UNLOCK_ALL_IN_ALL_LAYERS, _("Unlock all objects in all layers"));
+            break;
+        case SP_VERB_UNHIDE_ALL:
+            unhide_all(dt);
+            sp_document_done(doc, SP_VERB_UNHIDE_ALL, _("Unhide all objects in the current layer"));
+            break;
+        case SP_VERB_UNHIDE_ALL_IN_ALL_LAYERS:
+            unhide_all_in_all_layers(dt);
+            sp_document_done(doc, SP_VERB_UNHIDE_ALL_IN_ALL_LAYERS, _("Unhide all objects in all layers"));
+            break;
+        default:
+            return;
+    }
 
+    return;
+}
+/* *********** End Lock'N'Hide ********** */
 
 
 /* these must be in the same order as the SP_VERB_* enum in "verbs.h" */
@@ -2176,9 +2312,13 @@ Verb *Verb::_base_verbs[] = {
 
     /* Object */
     new ObjectVerb(SP_VERB_OBJECT_ROTATE_90_CW, "ObjectRotate90", N_("Rotate _90&#176; CW"),
-                   N_("Rotate selection 90&#176; clockwise"), "object_rotate_90_CW"),
+                   // This is shared between tooltips and statusbar, so they
+                   // must use UTF-8, not HTML entities for special characters.
+                   N_("Rotate selection 90\xc2\xb0 clockwise"), "object_rotate_90_CW"),
     new ObjectVerb(SP_VERB_OBJECT_ROTATE_90_CCW, "ObjectRotate90CCW", N_("Rotate 9_0&#176; CCW"),
-                   N_("Rotate selection 90&#176; counter-clockwise"), "object_rotate_90_CCW"),
+                   // This is shared between tooltips and statusbar, so they
+                   // must use UTF-8, not HTML entities for special characters.
+                   N_("Rotate selection 90\xc2\xb0 counter-clockwise"), "object_rotate_90_CCW"),
     new ObjectVerb(SP_VERB_OBJECT_FLATTEN, "ObjectRemoveTransform", N_("Remove _Transformations"),
                    N_("Remove transformations from object"), "object_reset"),
     new ObjectVerb(SP_VERB_OBJECT_TO_CURVE, "ObjectToPath", N_("_Object to Path"),
@@ -2211,6 +2351,8 @@ Verb *Verb::_base_verbs[] = {
                     N_("Edit path nodes or control handles"), "draw_node"),
     new ContextVerb(SP_VERB_CONTEXT_RECT, "ToolRect", N_("Rectangle"),
                     N_("Create rectangles and squares"), "draw_rect"),
+    new ContextVerb(SP_VERB_CONTEXT_3DBOX, "Tool3DBox", N_("3D Box"),
+                    N_("Create 3D boxes"), "draw_3dbox"),
     new ContextVerb(SP_VERB_CONTEXT_ARC, "ToolArc", N_("Ellipse"),
                     N_("Create circles, ellipses, and arcs"), "draw_arc"),
     new ContextVerb(SP_VERB_CONTEXT_STAR, "ToolStar", N_("Star"),
@@ -2221,7 +2363,7 @@ Verb *Verb::_base_verbs[] = {
                     N_("Draw freehand lines"), "draw_freehand"),
     new ContextVerb(SP_VERB_CONTEXT_PEN, "ToolPen", N_("Pen"),
                     N_("Draw Bezier curves and straight lines"), "draw_pen"),
-    new ContextVerb(SP_VERB_CONTEXT_CALLIGRAPHIC, "ToolCalligrphic", N_("Calligraphy"),
+    new ContextVerb(SP_VERB_CONTEXT_CALLIGRAPHIC, "ToolCalligraphic", N_("Calligraphy"),
                     N_("Draw calligraphic lines"), "draw_calligraphic"),
     new ContextVerb(SP_VERB_CONTEXT_TEXT, "ToolText", N_("Text"),
                     N_("Create and edit text objects"), "draw_text"),
@@ -2243,6 +2385,8 @@ Verb *Verb::_base_verbs[] = {
                     N_("Open Preferences for the Node tool"), NULL),
     new ContextVerb(SP_VERB_CONTEXT_RECT_PREFS, "RectPrefs", N_("Rectangle Preferences"),
                     N_("Open Preferences for the Rectangle tool"), NULL),
+    new ContextVerb(SP_VERB_CONTEXT_3DBOX_PREFS, "3DBoxPrefs", N_("3D Box Preferences"),
+                    N_("Open Preferences for the 3D Box tool"), NULL),
     new ContextVerb(SP_VERB_CONTEXT_ARC_PREFS, "ArcPrefs", N_("Ellipse Preferences"),
                     N_("Open Preferences for the Ellipse tool"), NULL),
     new ContextVerb(SP_VERB_CONTEXT_STAR_PREFS, "StarPrefs", N_("Star Preferences"),
@@ -2399,6 +2543,15 @@ Verb *Verb::_base_verbs[] = {
                        N_("Fit the page to the drawing"), NULL),
     new FitCanvasVerb(SP_VERB_FIT_CANVAS_TO_SELECTION_OR_DRAWING, "FitCanvasToSelectionOrDrawing", N_("Fit Page to Selection or Drawing"),
                        N_("Fit the page to the current selection or the drawing if there is no selection"), NULL),
+    /* LockAndHide */
+    new LockAndHideVerb(SP_VERB_UNLOCK_ALL, "UnlockAll", N_("Unlock All"),
+                       N_("Unlock all objects in the current layer"), NULL),
+    new LockAndHideVerb(SP_VERB_UNLOCK_ALL_IN_ALL_LAYERS, "UnlockAllInAllLayers", N_("Unlock All in All Layers"),
+                       N_("Unlock all objects in all layers"), NULL),
+    new LockAndHideVerb(SP_VERB_UNHIDE_ALL, "UnhideAll", N_("Unhide All"),
+                       N_("Unhide all objects in the current layer"), NULL),
+    new LockAndHideVerb(SP_VERB_UNHIDE_ALL_IN_ALL_LAYERS, "UnhideAllInAllLayers", N_("Unhide All in All Layers"),
+                       N_("Unhide all objects in all layers"), NULL),
     /* Footer */
     new Verb(SP_VERB_LAST, " '\"invalid id", NULL, NULL, NULL)
 };