Code

Two variants of resizing 3D boxes (using three/four handles, respectively, demonstrat...
authorcilix42 <cilix42@users.sourceforge.net>
Wed, 4 Jul 2007 10:49:11 +0000 (10:49 +0000)
committercilix42 <cilix42@users.sourceforge.net>
Wed, 4 Jul 2007 10:49:11 +0000 (10:49 +0000)
share/icons/icons.svg
src/box3d-context.cpp
src/box3d-context.h
src/object-edit.cpp
src/widgets/toolbox.cpp

index a579af7194c15da18e60dabd73eac4fa8ee845c8..cf0b3cf3b78edb4a41e169914ef3c7a93434b085 100644 (file)
      inkscape:window-height="764"
      inkscape:window-width="1021"
      inkscape:cy="1119.1738"
-     inkscape:cx="696.90117"
+     inkscape:cx="821.60243"
      inkscape:zoom="4.050284"
      gridtolerance="6"
      snaptogrid="false"
@@ -15087,4 +15087,59 @@ http://www.inkscape.org/</dc:description>
        style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:3.83003211;stroke-linecap:butt;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
        id="path4995" />
   </g>
+  <g
+     id="3dbox_three_handles">
+    <rect
+       y="117.46199"
+       x="753.77429"
+       height="7.406888"
+       width="7.406888"
+       id="rect6683"
+       style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <rect
+       style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect7268"
+       width="7.406888"
+       height="7.406888"
+       x="759.77429"
+       y="131.46199" />
+    <rect
+       y="119.46199"
+       x="767.77429"
+       height="7.406888"
+       width="7.406888"
+       id="rect7270"
+       style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+  </g>
+  <g
+     id="3dbox_four_handles">
+    <rect
+       style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect7277"
+       width="7.406888"
+       height="7.406888"
+       x="793.77429"
+       y="117.46199" />
+    <rect
+       y="117.46199"
+       x="807.77429"
+       height="7.406888"
+       width="7.406888"
+       id="rect7279"
+       style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+    <rect
+       style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect7281"
+       width="7.406888"
+       height="7.406888"
+       x="807.77429"
+       y="131.46199" />
+    <rect
+       y="131.46199"
+       x="793.77429"
+       height="7.406888"
+       width="7.406888"
+       id="rect7283"
+       style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+  </g>
 </svg>
index 1ec86b827d51a7b6039ca995ca5b59ba5c7e44ee..a6a4319056549efbd6c5e0fe16626dd54415f31b 100644 (file)
@@ -91,6 +91,7 @@ static void sp_3dbox_context_class_init(SP3DBoxContextClass *klass)
 }
 
 Box3D::Perspective3D * SP3DBoxContext::current_perspective = NULL;
+guint SP3DBoxContext::number_of_handles = 3;
 
 static void sp_3dbox_context_init(SP3DBoxContext *box3d_context)
 {
index bf1d0e5ab156fe783511d934ee3bac92b4df391e..c244699b440ce283a214b4cc1b955c3274767927 100644 (file)
@@ -51,6 +51,9 @@ struct SP3DBoxContext : public SPEventContext {
     bool ctrl_dragged; /* whether we are ctrl-dragging */
     bool extruded; /* whether shift-dragging already occured (i.e. the box is already extruded) */
 
+    /* temporary member until the precise behaviour is sorted out */
+    static guint number_of_handles;
+
     static Box3D::Perspective3D *current_perspective;
 
        sigc::connection sel_changed_connection;
index 684c4404f3bd51193682885d34f158ea78d64690..563e7daa6838ce2872df9b11b90b04ee74d73a7f 100644 (file)
@@ -49,7 +49,8 @@
 #define sp_round(v,m) (((v) < 0.0) ? ((ceil((v) / (m) - 0.5)) * (m)) : ((floor((v) / (m) + 0.5)) * (m)))
 
 static SPKnotHolder *sp_rect_knot_holder(SPItem *item, SPDesktop *desktop);
-static SPKnotHolder *sp_3dbox_knot_holder(SPItem *item, SPDesktop *desktop);
+//static 
+SPKnotHolder *sp_3dbox_knot_holder(SPItem *item, SPDesktop *desktop, guint number_of_handles);
 static SPKnotHolder *sp_arc_knot_holder(SPItem *item, SPDesktop *desktop);
 static SPKnotHolder *sp_star_knot_holder(SPItem *item, SPDesktop *desktop);
 static SPKnotHolder *sp_spiral_knot_holder(SPItem *item, SPDesktop *desktop);
@@ -64,7 +65,7 @@ sp_item_knot_holder(SPItem *item, SPDesktop *desktop)
     if (SP_IS_RECT(item)) {
         return sp_rect_knot_holder(item, desktop);
     } else if (SP_IS_3DBOX(item)) {
-        return sp_3dbox_knot_holder(item, desktop);
+        return sp_3dbox_knot_holder(item, desktop, SP3DBoxContext::number_of_handles);
     } else if (SP_IS_ARC(item)) {
         return sp_arc_knot_holder(item, desktop);
     } else if (SP_IS_STAR(item)) {
@@ -529,7 +530,7 @@ static SPKnotHolder *sp_rect_knot_holder(SPItem *item, SPDesktop *desktop)
 /* 3D Box */
 
 static void sp_3dbox_knot_set(SPItem *item, guint knot_id, Box3D::Axis direction,
-                               NR::Point const &new_pos, NR::Point const &origin, guint state)
+                              NR::Point const &new_pos, NR::Point const &origin, guint state)
 {
     g_assert(item != NULL);
     SP3DBox *box = SP_3DBOX(item);
@@ -538,11 +539,13 @@ static void sp_3dbox_knot_set(SPItem *item, guint knot_id, Box3D::Axis direction
     SPDocument *doc = SP_OBJECT_DOCUMENT(box);
     gdouble height = sp_document_height(doc);
 
-    if (direction == Box3D::Z) {
-        sp_3dbox_move_corner_in_Z_direction (box, knot_id, NR::Point (new_pos[NR::X], height - new_pos[NR::Y]));
-    } else {
-        sp_3dbox_move_corner_in_XY_plane (box, knot_id, NR::Point (new_pos[NR::X], height - new_pos[NR::Y]));
-    }
+      if (direction == Box3D::Z) {
+         sp_3dbox_move_corner_in_Z_direction (box, knot_id, NR::Point (new_pos[NR::X], height - new_pos[NR::Y]),
+                                              !(state & GDK_SHIFT_MASK));
+      } else {
+         sp_3dbox_move_corner_in_XY_plane (box, knot_id, NR::Point (new_pos[NR::X], height - new_pos[NR::Y]),
+                                           (state & GDK_SHIFT_MASK) ? direction : Box3D::XY);
+      }
     sp_3dbox_update_curves (box);
 }
 
@@ -560,7 +563,12 @@ static NR::Point sp_3dbox_knot_get(SPItem *item, guint knot_id)
 
 static void sp_3dbox_knot1_set(SPItem *item, NR::Point const &new_pos, NR::Point const &origin, guint state)
 {
-    sp_3dbox_knot_set (item, 1, Box3D::XY, new_pos, origin, state);
+    sp_3dbox_knot_set (item, 1, Box3D::Y, new_pos, origin, state);
+}
+
+static void sp_3dbox_knot1_set_constrained(SPItem *item, NR::Point const &new_pos, NR::Point const &origin, guint state)
+{
+    sp_3dbox_knot_set (item, 1, Box3D::Y, new_pos, origin, state ^ GDK_SHIFT_MASK);
 }
 
 static NR::Point sp_3dbox_knot1_get(SPItem *item)
@@ -570,7 +578,12 @@ static NR::Point sp_3dbox_knot1_get(SPItem *item)
 
 static void sp_3dbox_knot2_set(SPItem *item, NR::Point const &new_pos, NR::Point const &origin, guint state)
 {
-    sp_3dbox_knot_set (item, 2, Box3D::XY, new_pos, origin, state);
+    sp_3dbox_knot_set (item, 2, Box3D::X, new_pos, origin, state);
+}
+
+static void sp_3dbox_knot2_set_constrained(SPItem *item, NR::Point const &new_pos, NR::Point const &origin, guint state)
+{
+    sp_3dbox_knot_set (item, 2, Box3D::X, new_pos, origin, state ^ GDK_SHIFT_MASK);
 }
 
 static NR::Point sp_3dbox_knot2_get(SPItem *item)
@@ -578,6 +591,20 @@ static NR::Point sp_3dbox_knot2_get(SPItem *item)
     return sp_3dbox_knot_get(item, 2);
 }
 
+static void sp_3dbox_knot3_set(SPItem *item, NR::Point const &new_pos, NR::Point const &origin, guint state)
+{
+    if (!(state & GDK_SHIFT_MASK)) {
+        sp_3dbox_knot_set (item, 3, Box3D::Y, new_pos, origin, state);
+    } else {
+        sp_3dbox_knot_set (item, 3, Box3D::Z, new_pos, origin, state ^ GDK_SHIFT_MASK);
+    }
+}
+
+static NR::Point sp_3dbox_knot3_get(SPItem *item)
+{
+    return sp_3dbox_knot_get(item, 3);
+}
+
 static void sp_3dbox_knot5_set(SPItem *item, NR::Point const &new_pos, NR::Point const &origin, guint state)
 {
     sp_3dbox_knot_set (item, 5, Box3D::Z, new_pos, origin, state);
@@ -588,16 +615,42 @@ static NR::Point sp_3dbox_knot5_get(SPItem *item)
     return sp_3dbox_knot_get(item, 5);
 }
 
-static SPKnotHolder *
-sp_3dbox_knot_holder(SPItem *item, SPDesktop *desktop)
+static void sp_3dbox_knot7_set(SPItem *item, NR::Point const &new_pos, NR::Point const &origin, guint state)
+{
+    sp_3dbox_knot_set (item, 7, Box3D::Z, new_pos, origin, state);
+}
+
+static NR::Point sp_3dbox_knot7_get(SPItem *item)
+{
+    return sp_3dbox_knot_get(item, 7);
+}
+
+//static
+SPKnotHolder *
+sp_3dbox_knot_holder(SPItem *item, SPDesktop *desktop, guint number_of_handles)
 {
     g_assert(item != NULL);
     SPKnotHolder *knot_holder = sp_knot_holder_new(desktop, item, NULL);
 
-    sp_knot_holder_add(knot_holder, sp_3dbox_knot1_set, sp_3dbox_knot1_get, NULL,_("Resize box in X/Y direction"));
-    sp_knot_holder_add(knot_holder, sp_3dbox_knot2_set, sp_3dbox_knot2_get, NULL,_("Resize box in X/Y direction"));
-    sp_knot_holder_add(knot_holder, sp_3dbox_knot5_set, sp_3dbox_knot5_get, NULL,_("Resize box in Z direction"));
-    sp_pat_knot_holder(item, knot_holder);
+    switch (number_of_handles) {
+    case 3:
+        sp_knot_holder_add(knot_holder, sp_3dbox_knot1_set, sp_3dbox_knot1_get, NULL,_("Resize box in X/Y direction"));
+        sp_knot_holder_add(knot_holder, sp_3dbox_knot2_set, sp_3dbox_knot2_get, NULL,_("Resize box in X/Y direction"));
+        sp_knot_holder_add(knot_holder, sp_3dbox_knot5_set, sp_3dbox_knot5_get, NULL,_("Resize box in Z direction"));
+        sp_pat_knot_holder(item, knot_holder);
+        break;
+    case 4:
+        sp_knot_holder_add(knot_holder, sp_3dbox_knot1_set_constrained, sp_3dbox_knot1_get, NULL,_("Resize box in X/Y direction"));
+        sp_knot_holder_add(knot_holder, sp_3dbox_knot2_set_constrained, sp_3dbox_knot2_get, NULL,_("Resize box in X/Y direction"));
+        sp_knot_holder_add_full(knot_holder, sp_3dbox_knot3_set, sp_3dbox_knot3_get, NULL,
+                                SP_KNOT_SHAPE_CIRCLE,  SP_KNOT_MODE_XOR, _("Resize box in Y direction"));
+        sp_knot_holder_add(knot_holder, sp_3dbox_knot7_set, sp_3dbox_knot7_get, NULL,_("Resize box in Z direction"));
+        sp_pat_knot_holder(item, knot_holder);
+        break;
+    default:
+        g_print ("Wrong number of handles (%d): Not implemented yet.\n", number_of_handles);
+        break;
+    }
 
     return knot_holder;
 }
index 26798bce4c06a43e23d216233b3fdf25bc13b174..cd2506bef111eb568589657810dc3aa21aadacec 100644 (file)
@@ -64,6 +64,7 @@
 #include "node-context.h"
 #include "shape-editor.h"
 #include "sp-rect.h"
+#include "box3d.h"
 #include "box3d-context.h"
 #include "sp-star.h"
 #include "sp-spiral.h"
 #include "ege-select-one-action.h"
 #include "helper/unit-tracker.h"
 
+// FIXME: The next two lines are only temporarily added until
+//        the final resizing behaviour of 3D boxes is sorted out.
+#include "knotholder.h"
+SPKnotHolder *sp_3dbox_knot_holder(SPItem *item, SPDesktop *desktop, guint number_of_handles);
+
 using Inkscape::UnitTracker;
 
 typedef void (*SetupFunction)(GtkWidget *toolbox, SPDesktop *desktop);
@@ -281,6 +287,9 @@ static gchar const * ui_descr =
         "    <toolitem action='3DBoxVPXAction' />"
         "    <toolitem action='3DBoxVPYAction' />"
         "    <toolitem action='3DBoxVPZAction' />"
+        "    <separator />"
+        "    <toolitem action='3DBoxHandlesAction' />"
+        "    <separator />"
         "  </toolbar>"
 
         "  <toolbar name='SpiralToolbar'>"
@@ -2130,6 +2139,60 @@ static void sp_3dbox_toggle_vp_changed( GtkToggleAction *act, gpointer data )
     
 }
 
+static void sp_3dboxtb_handles_state_changed( EgeSelectOneAction *act, GObject *tbl )
+{
+    SPDesktop *desktop = (SPDesktop *) g_object_get_data( tbl, "desktop" );
+    if (sp_document_get_undo_sensitive(sp_desktop_document(desktop))) {
+        if ( ege_select_one_action_get_active( act ) != 0 ) {
+            prefs_set_string_attribute("tools.shapes.3dbox", "constrainedXYmoving", "true");
+        } else {
+            prefs_set_string_attribute("tools.shapes.3dbox", "constrainedXYmoving", NULL);
+        }
+    }
+
+    // quit if run by the attr_changed listener
+    if (g_object_get_data( tbl, "freeze" )) {
+        return;
+    }
+
+    // in turn, prevent listener from responding
+    g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
+
+    bool modmade = false;
+
+    SPEventContext *ec = SP_EVENT_CONTEXT(inkscape_active_event_context());
+    if (!SP_IS_3DBOX_CONTEXT(ec)) return;
+    SP3DBoxContext *bc = SP_3DBOX_CONTEXT(ec);
+    for (GSList const *items = sp_desktop_selection(desktop)->itemList();
+         items != NULL;
+         items = items->next)
+    {
+        if (SP_IS_3DBOX((SPItem *) items->data)) {
+            if (ec->shape_knot_holder) {
+                sp_knot_holder_destroy(ec->shape_knot_holder);
+                if ( ege_select_one_action_get_active(act) != 0 ) {
+                    bc->number_of_handles = 4;
+                    ec->shape_knot_holder = sp_3dbox_knot_holder((SPItem *) items->data, SP_ACTIVE_DESKTOP, 4);;
+                } else {
+                    bc->number_of_handles = 3;
+                    ec->shape_knot_holder = sp_3dbox_knot_holder((SPItem *) items->data, SP_ACTIVE_DESKTOP, 3);;
+                }
+            } else {
+                g_print ("Warning: No KnotHolder detected!!!\n");
+            }
+            modmade = true;
+        }
+    }
+
+    if (modmade) {
+        sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_3DBOX,
+                                   _("3D Box: Change number of handles"));
+    }
+
+    g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
+}
+
+
 static void sp_3dbox_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
 {
     bool toggled = false;
@@ -2177,6 +2240,42 @@ static void sp_3dbox_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainAction
     }
     gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), toggled );
     }
+
+
+    /* Number of handles and resizing behaviour */
+    {
+        GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
+
+        GtkTreeIter iter;
+        gtk_list_store_append( model, &iter );
+        gtk_list_store_set( model, &iter,
+                            0, _("Three Handles"),
+                            1, _("Switch to three handles (arbitrary resizing in XY-direction)"),
+                            2, "3dbox_three_handles",
+                            -1 );
+
+        gtk_list_store_append( model, &iter );
+        gtk_list_store_set( model, &iter,
+                            0, _("Four Handles"),
+                            1, _("Switch to four handles (constrained resizing in XY-direction)"),
+                            2, "3dbox_four_handles",
+                            -1 );
+
+        EgeSelectOneAction* act = ege_select_one_action_new( "3DBoxHandlesAction", _(""), _(""), NULL, GTK_TREE_MODEL(model) );
+        gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
+        g_object_set_data( holder, "handles_action", act );
+
+        ege_select_one_action_set_appearance( act, "full" );
+        ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE );
+        g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL );
+        ege_select_one_action_set_icon_column( act, 2 );
+        ege_select_one_action_set_tooltip_column( act, 1  );
+
+        gchar const *handlestr = prefs_get_string_attribute("tools.shapes.3dbox", "constrainedXYmoving");
+        bool isConstrained = (!handlestr || (handlestr && !strcmp(handlestr, "true")));
+        ege_select_one_action_set_active( act, isConstrained ? 0 : 1 );
+        g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_3dboxtb_handles_state_changed), holder );
+    }
 }
 
 //########################