summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Owens <doctormo@gmail.com>2013-07-02 02:23:13 +0000
committerMartin Owens <doctormo@gmail.com>2013-07-02 02:23:13 +0000
commit4d9cb756267d624666ae792d621a255f4b209657 (patch)
treed63f071411ce9a89b641da6cf3bfb20eab091c94 /src
parentShape calculations. do not quantize the coordinates. (Bug 168158) (diff)
downloadinkscape-4d9cb756267d624666ae792d621a255f4b209657.tar.gz
inkscape-4d9cb756267d624666ae792d621a255f4b209657.zip
Refactor resize, rotate, skew handle code
(bzr r12400)
Diffstat (limited to 'src')
-rw-r--r--src/seltrans-handles.cpp52
-rw-r--r--src/seltrans-handles.h42
-rw-r--r--src/seltrans.cpp287
-rw-r--r--src/seltrans.h13
4 files changed, 157 insertions, 237 deletions
diff --git a/src/seltrans-handles.cpp b/src/seltrans-handles.cpp
index fc03789d6..cc11125f6 100644
--- a/src/seltrans-handles.cpp
+++ b/src/seltrans-handles.cpp
@@ -1,33 +1,39 @@
#include "seltrans-handles.h"
+#ifdef __cplusplus
+#undef N_
+#define N_(x) x
+#endif
-SPSelTransHandle const handles_scale[] = {
-//anchor cursor control action request x y
- {SP_ANCHOR_SE, GDK_TOP_LEFT_CORNER, 0, sp_sel_trans_scale, sp_sel_trans_scale_request, 0, 1},
- {SP_ANCHOR_S, GDK_TOP_SIDE, 3, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 0.5, 1},
- {SP_ANCHOR_SW, GDK_TOP_RIGHT_CORNER, 1, sp_sel_trans_scale, sp_sel_trans_scale_request, 1, 1},
- {SP_ANCHOR_W, GDK_RIGHT_SIDE, 2, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 1, 0.5},
- {SP_ANCHOR_NW, GDK_BOTTOM_RIGHT_CORNER, 0, sp_sel_trans_scale, sp_sel_trans_scale_request, 1, 0},
- {SP_ANCHOR_N, GDK_BOTTOM_SIDE, 3, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 0.5, 0},
- {SP_ANCHOR_NE, GDK_BOTTOM_LEFT_CORNER, 1, sp_sel_trans_scale, sp_sel_trans_scale_request, 0, 0},
- {SP_ANCHOR_E, GDK_LEFT_SIDE, 2, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 0, 0.5}
+SPSelTransTypeInfo const handtypes[] = {
+ {N_("<b>Squeeze or stretch</b> selection; with <b>Ctrl</b> to scale uniformly; with <b>Shift</b> to scale around rotation center") },
+ {N_("<b>Scale</b> selection; with <b>Ctrl</b> to scale uniformly; with <b>Shift</b> to scale around rotation center") },
+ {N_("<b>Skew</b> selection; with <b>Ctrl</b> to snap angle; with <b>Shift</b> to skew around the opposite side") },
+ {N_("<b>Rotate</b> selection; with <b>Ctrl</b> to snap angle; with <b>Shift</b> to rotate around the opposite corner") },
+ {N_("<b>Center</b> of rotation and skewing: drag to reposition; scaling with Shift also uses this center") }
};
-SPSelTransHandle const handles_rotate[] = {
- {SP_ANCHOR_SE, GDK_EXCHANGE, 4, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 0, 1},
- {SP_ANCHOR_S, GDK_SB_H_DOUBLE_ARROW, 5, sp_sel_trans_skew, sp_sel_trans_skew_request, 0.5, 1},
- {SP_ANCHOR_SW, GDK_EXCHANGE, 6, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 1, 1},
- {SP_ANCHOR_W, GDK_SB_V_DOUBLE_ARROW, 7, sp_sel_trans_skew, sp_sel_trans_skew_request, 1, 0.5},
- {SP_ANCHOR_NW, GDK_EXCHANGE, 8, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 1, 0},
- {SP_ANCHOR_N, GDK_SB_H_DOUBLE_ARROW, 9, sp_sel_trans_skew, sp_sel_trans_skew_request, 0.5, 0},
- {SP_ANCHOR_NE, GDK_EXCHANGE, 10, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 0, 0},
- {SP_ANCHOR_E, GDK_SB_V_DOUBLE_ARROW, 11, sp_sel_trans_skew, sp_sel_trans_skew_request, 0, 0.5}
+SPSelTransHandle const hands[] = {
+//handle-type anchor cursor control x y
+ {HANDLE_STRETCH, SP_ANCHOR_S, GDK_TOP_SIDE, 3, 0.5, 1},
+ {HANDLE_STRETCH, SP_ANCHOR_W, GDK_RIGHT_SIDE, 2, 1, 0.5},
+ {HANDLE_STRETCH, SP_ANCHOR_N, GDK_BOTTOM_SIDE, 3, 0.5, 0},
+ {HANDLE_STRETCH, SP_ANCHOR_E, GDK_LEFT_SIDE, 2, 0, 0.5},
+ {HANDLE_SCALE, SP_ANCHOR_SE, GDK_TOP_LEFT_CORNER, 0, 0, 1},
+ {HANDLE_SCALE, SP_ANCHOR_SW, GDK_TOP_RIGHT_CORNER, 1, 1, 1},
+ {HANDLE_SCALE, SP_ANCHOR_NW, GDK_BOTTOM_RIGHT_CORNER, 0, 1, 0},
+ {HANDLE_SCALE, SP_ANCHOR_NE, GDK_BOTTOM_LEFT_CORNER, 1, 0, 0},
+ {HANDLE_SKEW, SP_ANCHOR_S, GDK_SB_H_DOUBLE_ARROW, 5, 0.5, 1},
+ {HANDLE_SKEW, SP_ANCHOR_W, GDK_SB_V_DOUBLE_ARROW, 7, 1, 0.5},
+ {HANDLE_SKEW, SP_ANCHOR_N, GDK_SB_H_DOUBLE_ARROW, 9, 0.5, 0},
+ {HANDLE_SKEW, SP_ANCHOR_E, GDK_SB_V_DOUBLE_ARROW, 11, 0, 0.5},
+ {HANDLE_ROTATE, SP_ANCHOR_SE, GDK_EXCHANGE, 4, 0, 1},
+ {HANDLE_ROTATE, SP_ANCHOR_SW, GDK_EXCHANGE, 6, 1, 1},
+ {HANDLE_ROTATE, SP_ANCHOR_NW, GDK_EXCHANGE, 8, 1, 0},
+ {HANDLE_ROTATE, SP_ANCHOR_NE, GDK_EXCHANGE, 10, 0, 0},
+ {HANDLE_CENTER, SP_ANCHOR_CENTER, GDK_CROSSHAIR, 12, 0.5, 0.5}
};
-SPSelTransHandle const handle_center =
- {SP_ANCHOR_CENTER, GDK_CROSSHAIR, 12, sp_sel_trans_center, sp_sel_trans_center_request, 0.5, 0.5};
-
-
/*
Local Variables:
mode:c++
diff --git a/src/seltrans-handles.h b/src/seltrans-handles.h
index 14f50d784..ef285392b 100644
--- a/src/seltrans-handles.h
+++ b/src/seltrans-handles.h
@@ -21,40 +21,32 @@ namespace Inkscape
class SelTrans;
}
-struct SPSelTransHandle;
+enum SPSelTransType {
+ HANDLE_STRETCH,
+ HANDLE_SCALE,
+ HANDLE_SKEW,
+ HANDLE_ROTATE,
+ HANDLE_CENTER
+};
-// request handlers
-gboolean sp_sel_trans_scale_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &handle, Geom::Point &p, guint state);
-gboolean sp_sel_trans_stretch_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &handle, Geom::Point &p, guint state);
-gboolean sp_sel_trans_skew_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &handle, Geom::Point &p, guint state);
-gboolean sp_sel_trans_rotate_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &handle, Geom::Point &p, guint state);
-gboolean sp_sel_trans_center_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &handle, Geom::Point &p, guint state);
+struct SPSelTransTypeInfo {
+ gchar const *tip;
+};
+// One per handle type in order
+extern SPSelTransTypeInfo const handtypes[5];
-// action handlers
-void sp_sel_trans_scale(Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &p, guint state);
-void sp_sel_trans_stretch(Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &p, guint state);
-void sp_sel_trans_skew(Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &p, guint state);
-void sp_sel_trans_rotate(Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &p, guint state);
-void sp_sel_trans_center(Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &p, guint state);
+struct SPSelTransHandle;
struct SPSelTransHandle {
+ SPSelTransType type;
SPAnchorType anchor;
GdkCursorType cursor;
guint control;
- void (* action) (Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &p, guint state);
- gboolean (* request) (Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &p, guint state);
gdouble x, y;
};
-
-// TODO these must be purged:
-extern SPSelTransHandle const handles_scale[8];
-extern SPSelTransHandle const handles_rotate[8];
-extern SPSelTransHandle const handle_center;
+// These are 4 * each handle type + 1 for center
+int const NUMHANDS = 17;
+extern SPSelTransHandle const hands[17];
#endif // SEEN_SP_SELTRANS_HANDLES_H
diff --git a/src/seltrans.cpp b/src/seltrans.cpp
index 84c73e452..016eba816 100644
--- a/src/seltrans.cpp
+++ b/src/seltrans.cpp
@@ -48,12 +48,11 @@
#include <2geom/angle.h>
#include "display/snap-indicator.h"
#include "ui/control-manager.h"
+#include "seltrans-handles.h"
using Inkscape::ControlManager;
using Inkscape::DocumentUndo;
-static void sp_remove_handles(SPKnot *knot[], gint num);
-
static void sp_sel_trans_handle_grab(SPKnot *knot, guint state, gpointer data);
static void sp_sel_trans_handle_ungrab(SPKnot *knot, guint state, gpointer data);
static void sp_sel_trans_handle_click(SPKnot *knot, guint state, gpointer data);
@@ -62,7 +61,7 @@ static gboolean sp_sel_trans_handle_request(SPKnot *knot, Geom::Point *p, guint
extern GdkPixbuf *handles[];
-static gboolean sp_seltrans_handle_event(SPKnot *knot, GdkEvent *event, gpointer)
+static gboolean sp_sel_trans_handle_event(SPKnot *knot, GdkEvent *event, gpointer)
{
switch (event->type) {
case GDK_MOTION_NOTIFY:
@@ -112,7 +111,6 @@ Inkscape::SelTrans::SelTrans(SPDesktop *desktop) :
_opposite_for_bboxpoints(Geom::Point(0,0)),
_origin_for_specpoints(Geom::Point(0,0)),
_origin_for_bboxpoints(Geom::Point(0,0)),
- _chandle(NULL),
_stamp_cache(NULL),
_message_context(desktop->messageStack()),
_bounding_box_prefs_observer(*this)
@@ -124,16 +122,12 @@ Inkscape::SelTrans::SelTrans(SPDesktop *desktop) :
g_return_if_fail(desktop != NULL);
- for (int i = 0; i < 8; i++) {
- _shandle[i] = NULL;
- _rhandle[i] = NULL;
- }
-
_updateVolatileState();
_current_relative_affine.setIdentity();
_center_is_set = false; // reread _center from items, or set to bbox midpoint
+ _makeHandles();
_updateHandles();
_selection = sp_desktop_selection(desktop);
@@ -190,19 +184,9 @@ Inkscape::SelTrans::~SelTrans()
_sel_changed_connection.disconnect();
_sel_modified_connection.disconnect();
- for (unsigned int i = 0; i < 8; i++) {
- if (_shandle[i]) {
- g_object_unref(G_OBJECT(_shandle[i]));
- _shandle[i] = NULL;
- }
- if (_rhandle[i]) {
- g_object_unref(G_OBJECT(_rhandle[i]));
- _rhandle[i] = NULL;
- }
- }
- if (_chandle) {
- g_object_unref(G_OBJECT(_chandle));
- _chandle = NULL;
+ for (int i = 0; i < NUMHANDS; i++) {
+ g_object_unref(G_OBJECT(knots[i]));
+ knots[i] = NULL;
}
if (_norm) {
@@ -584,13 +568,11 @@ void Inkscape::SelTrans::stamp()
void Inkscape::SelTrans::_updateHandles()
{
+ for (int i = 0; i < NUMHANDS; i++)
+ sp_knot_hide(knots[i]);
+
if ( !_show_handles || _empty )
- {
- sp_remove_handles(_shandle, 8);
- sp_remove_handles(_rhandle, 8);
- sp_remove_handles(&_chandle, 1);
return;
- }
if (!_center_is_set) {
_center = _desktop->selection->center();
@@ -598,57 +580,12 @@ void Inkscape::SelTrans::_updateHandles()
}
if ( _state == STATE_SCALE ) {
- sp_remove_handles(_rhandle, 8);
- sp_remove_handles(&_chandle, 1);
- _showHandles(_shandle, handles_scale, 8,
- _("<b>Squeeze or stretch</b> selection; with <b>Ctrl</b> to scale uniformly; with <b>Shift</b> to scale around rotation center"),
- _("<b>Scale</b> selection; with <b>Ctrl</b> to scale uniformly; with <b>Shift</b> to scale around rotation center"));
+ _showHandles(HANDLE_STRETCH);
+ _showHandles(HANDLE_SCALE);
} else {
- sp_remove_handles(_shandle, 8);
- _showHandles(_rhandle, handles_rotate, 8,
- _("<b>Skew</b> selection; with <b>Ctrl</b> to snap angle; with <b>Shift</b> to skew around the opposite side"),
- _("<b>Rotate</b> selection; with <b>Ctrl</b> to snap angle; with <b>Shift</b> to rotate around the opposite corner"));
- // center handle
- /* Assuming that the center handle is in its default position, ie. in the center:
- * Multiple handles will be shown, for rotating, skewing and the center handle. For straight lines, the bounding box of the center handle will be
- * fully overlapped by bounding boxes of two of the skew handles. Due to the internals of sp_canvas_group_point, the center handle must be the
- * last handle in the SPCanvasGroup if it is to be selectable in such a case. So we have made sure here that the center handle is added to the
- * group after the rotation handles (determined by the chronological order of sp_knot_new() calls)
- * Now when the center handle is in still in the center, the skew handles can be selected because because the bounding box of the
- * center handle does not fully overlap the bounding box of either of the skew handles. However, if the center handle has been moved such that it
- * covers one of the other eight handles, then either the opposite handle has to be used (in case of rotating), or the center handle has to be moved.
- * Although this is annoying, this is still better than not being able to select the center handle at all
- */
- if ( _chandle == NULL ) {
- _chandle = sp_knot_new(_desktop, _("<b>Center</b> of rotation and skewing: drag to reposition; scaling with Shift also uses this center"));
-
- _chandle->setShape (SP_CTRL_SHAPE_BITMAP);
- _chandle->setSize (13);
- _chandle->setAnchor (handle_center.anchor);
- _chandle->setMode (SP_CTRL_MODE_XOR);
- _chandle->setFill(0x00000000, 0x00000000, 0x00000000);
- _chandle->setStroke(0x000000ff, 0xff0000b0, 0xff0000b0);
- _chandle->setPixbuf(handles[handle_center.control]);
- sp_knot_update_ctrl(_chandle);
-
- g_signal_connect(G_OBJECT(_chandle), "request",
- G_CALLBACK(sp_sel_trans_handle_request), (gpointer) &handle_center);
- g_signal_connect(G_OBJECT(_chandle), "moved",
- G_CALLBACK(sp_sel_trans_handle_new_event), (gpointer) &handle_center);
- g_signal_connect(G_OBJECT(_chandle), "grabbed",
- G_CALLBACK(sp_sel_trans_handle_grab), (gpointer) &handle_center);
- g_signal_connect(G_OBJECT(_chandle), "ungrabbed",
- G_CALLBACK(sp_sel_trans_handle_ungrab), (gpointer) &handle_center);
- g_signal_connect(G_OBJECT(_chandle), "clicked",
- G_CALLBACK(sp_sel_trans_handle_click), (gpointer) &handle_center);
- }
-
- if ( _center ) {
- sp_knot_show(_chandle);
- sp_knot_moveto(_chandle, *_center);
- } else {
- sp_remove_handles(&_chandle, 1);
- }
+ _showHandles(HANDLE_SKEW);
+ _showHandles(HANDLE_ROTATE);
+ _showHandles(HANDLE_CENTER);
}
}
@@ -673,53 +610,60 @@ void Inkscape::SelTrans::_updateVolatileState()
_strokewidth = stroke_average_width (selection->itemList());
}
-static void sp_remove_handles(SPKnot *knot[], gint num)
+void Inkscape::SelTrans::_showHandles(SPSelTransType type)
{
- for (int i = 0; i < num; i++) {
- if (knot[i] != NULL) {
- sp_knot_hide(knot[i]);
- }
+ // shouldn't have nullary bbox, but knots
+ g_assert(_bbox);
+
+ for (int i = 0; i < NUMHANDS; i++) {
+ if (hands[i].type != type)
+ continue;
+
+ // Position knots to scale the selection bbox
+ Geom::Point const bpos(hands[i].x, hands[i].y);
+ Geom::Point p(_bbox->min() + (_bbox->dimensions() * Geom::Scale(bpos)));
+ sp_knot_moveto(knots[i], p);
+ sp_knot_show(knots[i]);
+
+ // This controls the center handle's position, because the default can
+ // be moved and needs to be remembered.
+ if( type == HANDLE_CENTER && _center )
+ sp_knot_moveto(knots[i], *_center);
}
}
-void Inkscape::SelTrans::_showHandles(SPKnot *knot[], SPSelTransHandle const handle[], gint num,
- gchar const *even_tip, gchar const *odd_tip)
+void Inkscape::SelTrans::_makeHandles()
{
- g_return_if_fail( !_empty );
-
- for (int i = 0; i < num; i++) {
- if (knot[i] == NULL) {
- knot[i] = sp_knot_new(_desktop, i % 2 ? even_tip : odd_tip);
-
- knot[i]->setShape (SP_CTRL_SHAPE_BITMAP);
- knot[i]->setSize (13);
- knot[i]->setAnchor (handle[i].anchor);
- knot[i]->setMode (SP_CTRL_MODE_XOR);
- knot[i]->setFill(0x000000ff, 0x00ff6600, 0x00ff6600); // inversion, green, green
- knot[i]->setStroke(0x000000ff, 0x000000ff, 0x000000ff); // inversion
- knot[i]->setPixbuf(handles[handle[i].control]);
- sp_knot_update_ctrl(knot[i]);
-
- g_signal_connect(G_OBJECT(knot[i]), "request",
- G_CALLBACK(sp_sel_trans_handle_request), (gpointer) &handle[i]);
- g_signal_connect(G_OBJECT(knot[i]), "moved",
- G_CALLBACK(sp_sel_trans_handle_new_event), (gpointer) &handle[i]);
- g_signal_connect(G_OBJECT(knot[i]), "grabbed",
- G_CALLBACK(sp_sel_trans_handle_grab), (gpointer) &handle[i]);
- g_signal_connect(G_OBJECT(knot[i]), "ungrabbed",
- G_CALLBACK(sp_sel_trans_handle_ungrab), (gpointer) &handle[i]);
- g_signal_connect(G_OBJECT(knot[i]), "event", G_CALLBACK(sp_seltrans_handle_event), (gpointer) &handle[i]);
+ for (int i = 0; i < NUMHANDS; i++) {
+ knots[i] = sp_knot_new(_desktop, handtypes[hands[i].type].tip);
+
+ knots[i]->setShape(SP_CTRL_SHAPE_BITMAP);
+ knots[i]->setSize(13);
+ knots[i]->setAnchor(hands[i].anchor);
+ knots[i]->setMode(SP_CTRL_MODE_XOR);
+ knots[i]->setFill(0x000000ff, 0x00ff6600, 0x00ff6600); // invert+2*green
+ knots[i]->setStroke(0x000000ff, 0x000000ff, 0x000000ff); // 3*invert
+ knots[i]->setPixbuf(handles[hands[i].control]);
+ sp_knot_update_ctrl(knots[i]);
+
+ if( hands[i].type == HANDLE_CENTER ) {
+ _center_handle = i;
+ knots[i]->setFill(0x00000000, 0x00000000, 0x00000000);
+ knots[i]->setStroke(0x000000ff, 0xff0000b0, 0xff0000b0);
}
- sp_knot_show(knot[i]);
-
- Geom::Point const handle_pt(handle[i].x, handle[i].y);
- // shouldn't have nullary bbox, but knots
- g_assert(_bbox);
- Geom::Point p( _bbox->min()
- + ( _bbox->dimensions()
- * Geom::Scale(handle_pt) ) );
- sp_knot_moveto(knot[i], p);
+ g_signal_connect(G_OBJECT(knots[i]), "request",
+ G_CALLBACK(sp_sel_trans_handle_request), (gpointer) &hands[i]);
+ g_signal_connect(G_OBJECT(knots[i]), "moved",
+ G_CALLBACK(sp_sel_trans_handle_new_event), (gpointer) &hands[i]);
+ g_signal_connect(G_OBJECT(knots[i]), "grabbed",
+ G_CALLBACK(sp_sel_trans_handle_grab), (gpointer) &hands[i]);
+ g_signal_connect(G_OBJECT(knots[i]), "ungrabbed",
+ G_CALLBACK(sp_sel_trans_handle_ungrab), (gpointer) &hands[i]);
+ g_signal_connect(G_OBJECT(knots[i]), "clicked",
+ G_CALLBACK(sp_sel_trans_handle_click), (gpointer) &hands[i]);
+ g_signal_connect(G_OBJECT(knots[i]), "event",
+ G_CALLBACK(sp_sel_trans_handle_event), (gpointer) &hands[i]);
}
}
@@ -758,8 +702,8 @@ static void sp_sel_trans_handle_click(SPKnot *knot, guint state, gpointer data)
void Inkscape::SelTrans::handleClick(SPKnot */*knot*/, guint state, SPSelTransHandle const &handle)
{
- switch (handle.anchor) {
- case SP_ANCHOR_CENTER:
+ switch (handle.type) {
+ case HANDLE_CENTER:
if (state & GDK_SHIFT_MASK) {
// Unset the center position for all selected items
for (GSList const *l = _desktop->selection->itemList(); l; l = l->next) {
@@ -780,8 +724,8 @@ void Inkscape::SelTrans::handleClick(SPKnot */*knot*/, guint state, SPSelTransHa
void Inkscape::SelTrans::handleGrab(SPKnot *knot, guint /*state*/, SPSelTransHandle const &handle)
{
- switch (handle.anchor) {
- case SP_ANCHOR_CENTER:
+ switch (handle.type) {
+ case HANDLE_CENTER:
g_object_set(G_OBJECT(_grip),
"shape", SP_CTRL_SHAPE_BITMAP,
"size", 13.0,
@@ -795,7 +739,6 @@ void Inkscape::SelTrans::handleGrab(SPKnot *knot, guint /*state*/, SPSelTransHan
NULL);
sp_canvas_item_show(_norm);
sp_canvas_item_show(_grip);
-
break;
}
@@ -816,21 +759,35 @@ void Inkscape::SelTrans::handleNewEvent(SPKnot *knot, Geom::Point *position, gui
return;
}
}
-
- handle.action(this, handle, *position, state);
+ switch (handle.type) {
+ case HANDLE_SCALE:
+ scale(*position, state);
+ break;
+ case HANDLE_STRETCH:
+ stretch(handle, *position, state);
+ break;
+ case HANDLE_SKEW:
+ skew(handle, *position, state);
+ break;
+ case HANDLE_ROTATE:
+ rotate(*position, state);
+ break;
+ case HANDLE_CENTER:
+ setCenter(*position);
+ break;
+ }
}
gboolean Inkscape::SelTrans::handleRequest(SPKnot *knot, Geom::Point *position, guint state, SPSelTransHandle const &handle)
{
- if (!SP_KNOT_IS_GRABBED(knot)) {
+ if (!SP_KNOT_IS_GRABBED(knot))
return TRUE;
- }
// When holding shift while rotating or skewing, the transformation will be
// relative to the point opposite of the handle; otherwise it will be relative
// to the center as set for the selection
- if ((!(state & GDK_SHIFT_MASK) == !(_state == STATE_ROTATE)) && (&handle != &handle_center)) {
+ if ((!(state & GDK_SHIFT_MASK) == !(_state == STATE_ROTATE)) && (handle.type != HANDLE_CENTER)) {
_origin = _opposite;
_origin_for_bboxpoints = _opposite_for_bboxpoints;
_origin_for_specpoints = _opposite_for_specpoints;
@@ -842,10 +799,10 @@ gboolean Inkscape::SelTrans::handleRequest(SPKnot *knot, Geom::Point *position,
// FIXME
return TRUE;
}
- if (handle.request(this, handle, *position, state)) {
+ if (request(handle, *position, state)) {
sp_knot_set_position(knot, *position, state);
SP_CTRL(_grip)->moveto(*position);
- if (&handle == &handle_center) {
+ if (handle.type == HANDLE_CENTER) {
SP_CTRL(_norm)->moveto(*position);
} else {
SP_CTRL(_norm)->moveto(_origin);
@@ -908,36 +865,6 @@ static double sign(double const x)
: 1 );
}
-gboolean sp_sel_trans_scale_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &, Geom::Point &pt, guint state)
-{
- return seltrans->scaleRequest(pt, state);
-}
-
-gboolean sp_sel_trans_stretch_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &handle, Geom::Point &pt, guint state)
-{
- return seltrans->stretchRequest(handle, pt, state);
-}
-
-gboolean sp_sel_trans_skew_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &handle, Geom::Point &pt, guint state)
-{
- return seltrans->skewRequest(handle, pt, state);
-}
-
-gboolean sp_sel_trans_rotate_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &, Geom::Point &pt, guint state)
-{
- return seltrans->rotateRequest(pt, state);
-}
-
-gboolean sp_sel_trans_center_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &, Geom::Point &pt, guint state)
-{
- return seltrans->centerRequest(pt, state);
-}
-
gboolean Inkscape::SelTrans::scaleRequest(Geom::Point &pt, guint state)
{
@@ -1117,6 +1044,24 @@ gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, Geom
return TRUE;
}
+gboolean Inkscape::SelTrans::request(SPSelTransHandle const &handle, Geom::Point &pt, guint state)
+{
+ // These _should_ be in the handstype somewhere instead
+ switch (handle.type) {
+ case HANDLE_SCALE:
+ return scaleRequest(pt, state);
+ case HANDLE_STRETCH:
+ return stretchRequest(handle, pt, state);
+ case HANDLE_SKEW:
+ return skewRequest(handle, pt, state);
+ case HANDLE_ROTATE:
+ return rotateRequest(pt, state);
+ case HANDLE_CENTER:
+ return centerRequest(pt, state);
+ }
+ return FALSE;
+}
+
gboolean Inkscape::SelTrans::skewRequest(SPSelTransHandle const &handle, Geom::Point &pt, guint state)
{
/* When skewing (or rotating):
@@ -1347,25 +1292,7 @@ gboolean Inkscape::SelTrans::centerRequest(Geom::Point &pt, guint state)
*
*/
-void sp_sel_trans_stretch(Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &pt, guint state)
-{
- seltrans->stretch(handle, pt, state);
-}
-
-void sp_sel_trans_scale(Inkscape::SelTrans *seltrans, SPSelTransHandle const &, Geom::Point &pt, guint state)
-{
- seltrans->scale(pt, state);
-}
-void sp_sel_trans_skew(Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &pt, guint state)
-{
- seltrans->skew(handle, pt, state);
-}
-
-void sp_sel_trans_rotate(Inkscape::SelTrans *seltrans, SPSelTransHandle const &, Geom::Point &pt, guint state)
-{
- seltrans->rotate(pt, state);
-}
void Inkscape::SelTrans::stretch(SPSelTransHandle const &/*handle*/, Geom::Point &/*pt*/, guint /*state*/)
{
@@ -1387,12 +1314,6 @@ void Inkscape::SelTrans::rotate(Geom::Point &/*pt*/, guint /*state*/)
transform(_relative_affine, _origin);
}
-void sp_sel_trans_center(Inkscape::SelTrans *seltrans, SPSelTransHandle const &, Geom::Point &pt, guint /*state*/)
-{
- seltrans->setCenter(pt);
-}
-
-
void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state)
{
SnapManager &m = _desktop->namedview->snap_manager;
diff --git a/src/seltrans.h b/src/seltrans.h
index 10860f58f..9cf4a7aaf 100644
--- a/src/seltrans.h
+++ b/src/seltrans.h
@@ -25,6 +25,7 @@
#include "message-context.h"
#include <vector>
#include "sp-item.h"
+#include "seltrans-handles.h"
struct SPKnot;
class SPDesktop;
@@ -64,6 +65,7 @@ public:
void scale(Geom::Point &pt, guint state);
void skew(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
void rotate(Geom::Point &pt, guint state);
+ gboolean request(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
gboolean scaleRequest(Geom::Point &pt, guint state);
gboolean stretchRequest(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
gboolean skewRequest(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
@@ -91,7 +93,7 @@ public:
return _grabbed;
}
bool centerIsVisible() {
- return ( _chandle && SP_KNOT_IS_VISIBLE (_chandle) );
+ return ( _center_handle && SP_KNOT_IS_VISIBLE (knots[_center_handle]) );
}
void getNextClosestPoint(bool reverse);
@@ -115,8 +117,8 @@ private:
void _selChanged(Inkscape::Selection *selection);
void _selModified(Inkscape::Selection *selection, guint flags);
void _boundingBoxPrefsChanged(int prefs_bbox);
- void _showHandles(SPKnot *knot[], SPSelTransHandle const handle[], gint num,
- gchar const *even_tip, gchar const *odd_tip);
+ void _makeHandles();
+ void _showHandles(SPSelTransType type);
Geom::Point _getGeomHandlePos(Geom::Point const &visual_handle_pos);
Geom::Point _calcAbsAffineDefault(Geom::Scale const default_scale);
Geom::Point _calcAbsAffineGeom(Geom::Scale const geom_scale);
@@ -176,10 +178,9 @@ private:
boost::optional<Geom::Point> _center;
bool _center_is_set; ///< we've already set _center, no need to reread it from items
+ int _center_handle;
- SPKnot *_shandle[8];
- SPKnot *_rhandle[8];
- SPKnot *_chandle;
+ SPKnot *knots[27]; // Only some as shown at any time
SPCanvasItem *_norm;
SPCanvasItem *_grip;
SPCtrlLine *_l[4];