summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: bf2a326)
raw | patch | inline | side by side (parent: bf2a326)
author | buliabyak <buliabyak@users.sourceforge.net> | |
Thu, 26 Jan 2006 05:16:27 +0000 (05:16 +0000) | ||
committer | buliabyak <buliabyak@users.sourceforge.net> | |
Thu, 26 Jan 2006 05:16:27 +0000 (05:16 +0000) |
src/attributes.cpp | patch | blob | history | |
src/attributes.h | patch | blob | history | |
src/seltrans.cpp | patch | blob | history | |
src/seltrans.h | patch | blob | history | |
src/sp-item.cpp | patch | blob | history | |
src/sp-item.h | patch | blob | history |
diff --git a/src/attributes.cpp b/src/attributes.cpp
index ce9c0e105230021bd845b4c194058f5008316b17..10b33e178c19f1780e96c9e7b9201522bda2d895 100644 (file)
--- a/src/attributes.cpp
+++ b/src/attributes.cpp
{SP_ATTR_SODIPODI_NONPRINTABLE, "sodipodi:nonprintable"},
{SP_ATTR_CONNECTOR_AVOID, "inkscape:connector-avoid"},
{SP_ATTR_STYLE, "style"},
+ {SP_ATTR_TRANSFORM_CENTER_X, "inkscape:transform-center-x"},
+ {SP_ATTR_TRANSFORM_CENTER_Y, "inkscape:transform-center-y"},
/* SPAnchor */
{SP_ATTR_XLINK_HREF, "xlink:href"},
{SP_ATTR_XLINK_TYPE, "xlink:type"},
diff --git a/src/attributes.h b/src/attributes.h
index 2b4a68f34d520c2a8820a7bd3c12d215cd4b1623..b36cf255717234adaab53aa030403f726f262512 100644 (file)
--- a/src/attributes.h
+++ b/src/attributes.h
SP_ATTR_SODIPODI_NONPRINTABLE,
SP_ATTR_CONNECTOR_AVOID,
SP_ATTR_STYLE,
+ SP_ATTR_TRANSFORM_CENTER_X,
+ SP_ATTR_TRANSFORM_CENTER_Y,
/* SPAnchor */
SP_ATTR_XLINK_HREF,
SP_ATTR_XLINK_TYPE,
diff --git a/src/seltrans.cpp b/src/seltrans.cpp
index ca65b5d761a7cd28e223686f71f8cd71456fd7b5..f83c646b7bc6da5dd61614079524175cd06e62d8 100644 (file)
--- a/src/seltrans.cpp
+++ b/src/seltrans.cpp
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);
static void sp_sel_trans_handle_new_event(SPKnot *knot, NR::Point *position, guint32 state, gpointer data);
static gboolean sp_sel_trans_handle_request(SPKnot *knot, NR::Point *p, guint state, gboolean *data);
_updateVolatileState();
- _center = _box.midpoint();
-
_updateHandles();
_selection = SP_DT_SELECTION(desktop);
void Inkscape::SelTrans::setCenter(NR::Point const &p)
{
_center = p;
+
+ // Write the new center position into all selected items
+ for (GSList const *l = _desktop->selection->itemList(); l; l = l->next) {
+ SPItem *it = (SPItem*)sp_object_ref(SP_OBJECT(l->data), NULL);
+ it->setCenter(p);
+ SP_OBJECT(it)->updateRepr();
+ }
+ sp_document_maybe_done (SP_DT_DOCUMENT(_desktop), "center::move");
+
_updateHandles();
}
@@ -301,44 +309,30 @@ void Inkscape::SelTrans::transform(NR::Matrix const &rel_affine, NR::Point const
_updateHandles();
}
-void Inkscape::SelTrans::_centreTrans(Inkscape::XML::Node *current) const
-{
- for ( Inkscape::XML::Node *child = sp_repr_children(current) ; child ; child = sp_repr_next(child) ) {
- _centreTrans(child);
- }
- double const cx = sp_repr_get_double_attribute(current, "inkscape:c_rx", 9999999);
- double const cy = sp_repr_get_double_attribute(current, "inkscape:c_ry", 9999999);
- if (cx != 9999999) {
- NR::Point object_centre = NR::Point(cx, cy) * _current;
- sp_repr_set_svg_double(current, "inkscape:c_rx", object_centre[NR::X]);
- sp_repr_set_svg_double(current, "inkscape:c_ry", object_centre[NR::Y]);
- }
- }
-
-
-
-
void Inkscape::SelTrans::ungrab()
{
g_return_if_fail(_grabbed);
Inkscape::Selection *selection = SP_DT_SELECTION(_desktop);
-
bool updh = true;
if (!_empty && _changed) {
sp_selection_apply_affine(selection, _current, (_show == SHOW_OUTLINE)? true : false);
_center *= _current;
+
+ // Transform may have changed the objects' bboxes, so we need to write the _center into them again
+ for (unsigned i = 0; i < _items.size(); i++) {
+ SPItem *currentItem = _items[i].first;
+ if (currentItem->isCenterSet() || _current[1] != 0 || _current[2] != 0) { // only if it's already set, or if it's a rotation/skew
+ currentItem->setCenter (_center);
+ SP_OBJECT(currentItem)->updateRepr();
+ }
+ }
+
sp_document_done(SP_DT_DOCUMENT(_desktop));
updh = false;
}
- for (unsigned i = 0; i < _items.size(); i++)
- {
- Inkscape::XML::Node *current = SP_OBJECT_REPR(_items[i].first);
- if (current != NULL) {
- _centreTrans(current);
- }
-
+ for (unsigned i = 0; i < _items.size(); i++) {
sp_object_unref(SP_OBJECT(_items[i].first), NULL);
}
_items.clear();
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);
}
sp_remove_handles(&_chandle, 1);
_("<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"));
}
+
+ // Extract the position of the center from the first selected object
+ GSList *items = (GSList *) _desktop->selection->itemList();
+ if (items) {
+ SPItem *first = reinterpret_cast<SPItem*>(g_slist_last(items)->data); // from the first item in selection
+ if (first->isCenterSet()) { // only if set explicitly
+ _center = first->getCenter();
+ } else {
+ _center = _box.midpoint();
+ }
+ } else {
+ _center = _box.midpoint();
+ }
+
if ( _state == STATE_SCALE ) {
sp_knot_hide(_chandle);
} else {
- Inkscape::Selection *selection = _desktop->selection;
- Inkscape::XML::Node *current = selection->singleRepr();
- if (current != NULL && sp_repr_get_double_attribute(current, "inkscape:c_rx", 99999999) != 99999999) {
- double cx = sp_repr_get_double_attribute(current, "inkscape:c_rx", _center[NR::X]);
- double cy = sp_repr_get_double_attribute(current, "inkscape:c_ry", _center[NR::Y]);
- _center = NR::Point(cx, cy);
- }
sp_knot_show(_chandle);
sp_knot_moveto(_chandle, &_center);
}
@@ -581,6 +584,32 @@ static gboolean sp_sel_trans_handle_request(SPKnot *knot, NR::Point *position, g
);
}
+static void sp_sel_trans_handle_click(SPKnot *knot, guint state, gpointer data)
+{
+ SP_SELECT_CONTEXT(knot->desktop->event_context)->_seltrans->handleClick(
+ knot, state, *(SPSelTransHandle const *) data
+ );
+}
+
+void Inkscape::SelTrans::handleClick(SPKnot *knot, guint state, SPSelTransHandle const &handle)
+{
+ switch (handle.anchor) {
+ case GTK_ANCHOR_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) {
+ SPItem *it = (SPItem*)sp_object_ref(SP_OBJECT(l->data), NULL);
+ it->unsetCenter();
+ SP_OBJECT(it)->updateRepr();
+ }
+ sp_document_maybe_done (SP_DT_DOCUMENT(_desktop), "center::unset");
+ }
+ break;
+ default:
+ break;
+ }
+}
+
void Inkscape::SelTrans::handleGrab(SPKnot *knot, guint state, SPSelTransHandle const &handle)
{
switch (handle.anchor) {
{
if (!_grabbed) {
_updateVolatileState();
- _center = _box.midpoint();
_updateHandles();
}
}
@@ -667,17 +695,6 @@ void Inkscape::SelTrans::_selModified(Inkscape::Selection *selection, guint flag
if (!_grabbed) {
_updateVolatileState();
- if (
- (flags != (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG)) &&
- (flags != SP_OBJECT_PARENT_MODIFIED_FLAG) &&
- (flags != SP_OBJECT_CHILD_MODIFIED_FLAG) &&
- !_changed) {
- // Only reset center if object itself is modified (not style, parent or child),
- // and this is not a local change by seltrans
- // (still annoyingly recenters on keyboard transforms, fixme)
- _center = _box.midpoint();
- }
-
// reset internal flag
_changed = false;
}
}
- Inkscape::Selection *selection = _desktop->selection;
- Inkscape::XML::Node *current = selection->singleRepr();
- if (current != NULL){
- sp_repr_set_svg_double(current, "inkscape:c_rx", pt[X]);
- sp_repr_set_svg_double(current, "inkscape:c_ry", pt[Y]);
-
- }
-
if (!(state & GDK_SHIFT_MASK)) {
// screen pixels to snap center to bbox
#define SNAP_DIST 5
diff --git a/src/seltrans.h b/src/seltrans.h
index 30be58eeb98ba4d16773328cb7b9845403672858..8ac56766e6ea6151e1d8c780f5f7f9e0bd549f48 100644 (file)
--- a/src/seltrans.h
+++ b/src/seltrans.h
gboolean handleRequest(SPKnot *knot, NR::Point *position, guint state, SPSelTransHandle const &handle);
void handleGrab(SPKnot *knot, guint state, SPSelTransHandle const &handle);
+ void handleClick(SPKnot *knot, guint state, SPSelTransHandle const &handle);
void handleNewEvent(SPKnot *knot, NR::Point *position, guint state, SPSelTransHandle const &handle);
enum Show
void _selModified(Inkscape::Selection *selection, guint flags);
void _showHandles(SPKnot *knot[], SPSelTransHandle const handle[], gint num,
gchar const *even_tip, gchar const *odd_tip);
- void _centreTrans(Inkscape::XML::Node *current) const;
-
+
enum State {
STATE_SCALE,
STATE_ROTATE
diff --git a/src/sp-item.cpp b/src/sp-item.cpp
index 97aeb187720916a0403d1baf4377ef6a9a2d3d90..7339160c7cb0351cb4a3f12e1cce9240257fb556 100644 (file)
--- a/src/sp-item.cpp
+++ b/src/sp-item.cpp
item->sensitive = TRUE;
- item->r_cx = 0;
- item->r_cx = 0;
+ item->transform_center_x = 0;
+ item->transform_center_y = 0;
item->transform = NR::identity();
this->updateRepr();
}
+/**
+ * Sets the transform_center_x and transform_center_y properties to retain the rotation centre
+ */
+void
+SPItem::setCenter(NR::Point object_centre) {
+ NR::Rect bbox = invokeBbox(sp_item_i2d_affine(this));
+ if (!bbox.isEmpty()) {
+ transform_center_x = object_centre[NR::X] - bbox.midpoint()[NR::X];
+ if (fabs(transform_center_x) < 1e-5) // rounding error
+ transform_center_x = 0;
+ transform_center_y = object_centre[NR::Y] - bbox.midpoint()[NR::Y];
+ if (fabs(transform_center_y) < 1e-5) // rounding error
+ transform_center_y = 0;
+ }
+}
+
+void
+SPItem::unsetCenter() {
+ transform_center_x = 0;
+ transform_center_y = 0;
+}
+
+bool SPItem::isCenterSet() {
+ return (transform_center_x != 0 || transform_center_y != 0);
+}
+
+NR::Point SPItem::getCenter() {
+ NR::Rect bbox = invokeBbox(sp_item_i2d_affine(this));
+ if (!bbox.isEmpty()) {
+ return bbox.midpoint() + NR::Point (this->transform_center_x, this->transform_center_y);
+ } else {
+ return NR::Point (0, 0); // something's wrong!
+ }
+}
+
+
namespace {
bool is_item(SPObject const &object) {
@@ -313,8 +349,8 @@ sp_item_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
sp_object_read_attr(object, "mask");
sp_object_read_attr(object, "sodipodi:insensitive");
sp_object_read_attr(object, "sodipodi:nonprintable");
- sp_object_read_attr(object, "inkscape:r_cx");
- sp_object_read_attr(object, "inkscape:r_cy");
+ sp_object_read_attr(object, "inkscape:transform-center-x");
+ sp_object_read_attr(object, "inkscape:transform-center-y");
sp_object_read_attr(object, "inkscape:connector-avoid");
if (((SPObjectClass *) (parent_class))->build) {
case SP_ATTR_CONNECTOR_AVOID:
item->avoidRef->setAvoid(value);
break;
+ case SP_ATTR_TRANSFORM_CENTER_X:
+ if (value) {
+ item->transform_center_x = g_strtod(value, NULL);
+ }
+ break;
+ case SP_ATTR_TRANSFORM_CENTER_Y:
+ if (value) {
+ item->transform_center_y = g_strtod(value, NULL);
+ }
+ break;
default:
if (SP_ATTRIBUTE_IS_CSS(key)) {
sp_style_read_from_object(object->style, object);
if (flags & SP_OBJECT_WRITE_EXT) {
repr->setAttribute("sodipodi:insensitive", ( item->sensitive ? NULL : "true" ));
- repr->setAttribute("inkscape:r_cx", ( item->r_cx ? NULL : "true" ));
- repr->setAttribute("inkscape:r_cy", ( item->r_cy ? NULL : "true" ));
+ if (item->transform_center_x != 0)
+ sp_repr_set_svg_double (repr, "inkscape:transform-center-x", item->transform_center_x);
+ else
+ repr->setAttribute ("inkscape:transform-center-x", NULL);
+ if (item->transform_center_y != 0)
+ sp_repr_set_svg_double (repr, "inkscape:transform-center-y", item->transform_center_y);
+ else
+ repr->setAttribute ("inkscape:transform-center-y", NULL);
}
if (((SPObjectClass *) (parent_class))->write) {
diff --git a/src/sp-item.h b/src/sp-item.h
index 252821f362b060ead5c1eebc2a4366dee9dcae5b..141d3f88119d0dd5e774243adf615e28036f5529 100644 (file)
--- a/src/sp-item.h
+++ b/src/sp-item.h
struct SPItem : public SPObject {
unsigned int sensitive : 1;
unsigned int stop_paint: 1;
- double r_cx;
- double r_cy;
-
+ double transform_center_x;
+ double transform_center_y;
+
NR::Matrix transform;
SPClipPathReference *clip_ref;
bool isExplicitlyHidden() const;
void setExplicitlyHidden(bool val);
-
+
+ void setCenter(NR::Point object_centre);
+ void unsetCenter();
+ bool isCenterSet();
+ NR::Point getCenter();
+
bool isVisibleAndUnlocked() const;
bool isVisibleAndUnlocked(unsigned display_key) const;