summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2016-11-01 15:18:55 +0000
committerjabiertxof <info@marker.es>2016-11-01 15:18:55 +0000
commitefd3002943b5346bbaf961f3f02dc81c0ca0716d (patch)
treef92291c0ef59518938aa5db1abcc39e57ffdfbd0 /src
parentAdd fadding from temporary rotate draw to real ones (diff)
parent[Bug #1574561] Italian translation update. (diff)
downloadinkscape-efd3002943b5346bbaf961f3f02dc81c0ca0716d.tar.gz
inkscape-efd3002943b5346bbaf961f3f02dc81c0ca0716d.zip
Add some Vlava improvements from mailing list
(bzr r15142.1.28)
Diffstat (limited to 'src')
-rw-r--r--src/desktop-events.cpp4
-rw-r--r--src/display/sp-canvas.cpp18
-rw-r--r--src/display/sp-canvas.h2
-rw-r--r--src/file.cpp13
-rw-r--r--src/sp-namedview.cpp24
-rw-r--r--src/sp-namedview.h2
-rw-r--r--src/sp-object.cpp4
-rw-r--r--src/sp-object.h1
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp2
-rw-r--r--src/ui/tools/tool-base.cpp239
-rw-r--r--src/ui/tools/tool-base.h1
-rw-r--r--src/uri-references.cpp38
12 files changed, 227 insertions, 121 deletions
diff --git a/src/desktop-events.cpp b/src/desktop-events.cpp
index 5fef8cbfc..cb3e1f7c8 100644
--- a/src/desktop-events.cpp
+++ b/src/desktop-events.cpp
@@ -155,6 +155,10 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
}
}
+ SPNamedView *namedview = desktop->namedview;
+ if (namedview && namedview->document_rotation) {
+ normal *= Geom::Rotate(Geom::rad_from_deg(namedview->document_rotation * -1));
+ }
guide = sp_guideline_new(desktop->guides, NULL, event_dt, normal);
sp_guideline_set_color(SP_GUIDELINE(guide), desktop->namedview->guidehicolor);
diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp
index f168cffe6..e84303816 100644
--- a/src/display/sp-canvas.cpp
+++ b/src/display/sp-canvas.cpp
@@ -1927,7 +1927,7 @@ void SPCanvas::scrollTo(double cx, double cy, unsigned int clear, bool is_scroll
// Paint the background
cairo_translate(cr, -ix, -iy);
if (rotated) {
- cairo_translate(cr, dx, dy);
+ cairo_translate(cr, dx, dy);
rotated = false;
}
cairo_set_source(cr, _background);
@@ -1982,6 +1982,7 @@ void SPCanvas::startRotateTo(double angle)
int half_w = allocation.width/2;
int half_h = allocation.height/2;
int half_min = std::min(half_w,half_h);
+
cairo_surface_t *new_backing_store = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, allocation.width, allocation.height);
cairo_t *cr = cairo_create(new_backing_store);
cairo_arc(cr, half_w, half_h, half_min-15, 0, 2*M_PI);
@@ -2112,7 +2113,7 @@ void SPCanvas::clearRotateTo()
addIdle();
}
-void SPCanvas::rotateTo(SPCanvasItem * item, double angle)
+void SPCanvas::rotateTo(double angle)
{
if (!_backing_store || !started) {
return;
@@ -2203,19 +2204,26 @@ void SPCanvas::rotateTo(SPCanvasItem * item, double angle)
cairo_translate(cr, (-half_w +10) * -1 ,(-half_h + 25) * -1);
cairo_translate(cr, -half_w + 10 ,-half_h + 40);
s.str("");
- s << _("+CTRL, Fractional degrees");
+ s << _("+ALT, Fractional degrees");
cairo_text_path(cr, s.str().c_str());
cairo_fill(cr);
cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 40) * -1);
cairo_translate(cr, -half_w + 10 ,-half_h + 55);
s.str("");
- s << _("+SHIFT, 5º round step");
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ s << _("+CTRL, ") << prefs->getInt("/options/rotationsnapsperpi/value", 15) << _("º round step");
cairo_text_path(cr, s.str().c_str());
cairo_fill(cr);
cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 55) * -1);
cairo_translate(cr, -half_w + 10 ,-half_h + 70);
s.str("");
- s << _("+CTRL+SHIFT, Reset");
+ s << _("+SHIFT, Reset");
+ cairo_text_path(cr, s.str().c_str());
+ cairo_fill(cr);
+ cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 70) * -1);
+ cairo_translate(cr, -half_w + 10 ,-half_h + 85);
+ s.str("");
+ s << _("+CTRL+SHIFT, 0º");
cairo_text_path(cr, s.str().c_str());
cairo_fill(cr);
//cairo_translate(cr, (-half_w + 10) * -1 ,(-half_h + 60) * -1);
diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h
index 53b852140..21b6760f2 100644
--- a/src/display/sp-canvas.h
+++ b/src/display/sp-canvas.h
@@ -73,7 +73,7 @@ struct SPCanvas {
/// Scrolls canvas to specific position (cx and cy are measured in screen pixels).
void scrollTo(double cx, double cy, unsigned int clear, bool is_scrolling = false);
void startRotateTo(double angle);
- void rotateTo(SPCanvasItem * item, double angle);
+ void rotateTo(double angle);
bool endRotateTo();
void clearRotateTo();
/// Synchronously updates the canvas if necessary.
diff --git a/src/file.cpp b/src/file.cpp
index b29bee6b4..49d7fece5 100644
--- a/src/file.cpp
+++ b/src/file.cpp
@@ -1195,12 +1195,23 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri,
// Count the number of top-level items in the imported document.
guint items_count = 0;
+ SPObject *o = NULL;
for (auto& child: doc->getRoot()->children) {
if (SP_IS_ITEM(&child)) {
items_count++;
+ o = &child;
}
}
+ //ungroup if necessary
+ bool did_ungroup = false;
+ while(items_count==1 && o && SP_IS_GROUP(o) && o->children.size()==1){
+ std::vector<SPItem *>v;
+ sp_item_group_ungroup(SP_GROUP(o),v,false);
+ o = v.empty() ? NULL : v[0];
+ did_ungroup=true;
+ }
+
// Create a new group if necessary.
Inkscape::XML::Node *newgroup = NULL;
if ((style && style->attributeList()) || items_count > 1) {
@@ -1227,7 +1238,7 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri,
SPObject *new_obj = NULL;
for (auto& child: doc->getRoot()->children) {
if (SP_IS_ITEM(&child)) {
- Inkscape::XML::Node *newitem = child.getRepr()->duplicate(xml_in_doc);
+ Inkscape::XML::Node *newitem = did_ungroup ? o->getRepr()->duplicate(xml_in_doc) : child.getRepr()->duplicate(xml_in_doc);
// convert layers to groups, and make sure they are unlocked
// FIXME: add "preserve layers" mode where each layer from
diff --git a/src/sp-namedview.cpp b/src/sp-namedview.cpp
index df0778265..c9e71955f 100644
--- a/src/sp-namedview.cpp
+++ b/src/sp-namedview.cpp
@@ -958,6 +958,27 @@ static void sp_namedview_lock_guides(SPNamedView *nv)
}
}
+void sp_namedview_doc_rotate_guides(SPNamedView *nv)
+{
+ bool saved = DocumentUndo::getUndoSensitive(nv->document);
+ DocumentUndo::setUndoSensitive(nv->document, false);
+ SPRoot * root = nv->document->getRoot();
+ Geom::Point page_center = root->viewBox.midpoint() * root->vbt;
+ Geom::Affine rot = Geom::identity();
+ rot *= Geom::Translate(page_center).inverse();
+ rot *= Geom::Rotate(Geom::rad_from_deg((nv->document_rotation - root->get_rotation()) * -1));
+ rot *= Geom::Translate(page_center);
+ for(std::vector<SPGuide *>::iterator it=nv->guides.begin();it!=nv->guides.end();++it ) {
+ Geom::Point const on_line = (*it)->getPoint() * rot ;
+ (*it)->moveto(on_line, true);
+ Geom::Affine rot_normal_affine = Geom::Rotate(Geom::rad_from_deg((nv->document_rotation - root->get_rotation()) * -1));
+ Geom::Point const rot_normal = (*it)->getNormal() * rot_normal_affine;
+ (*it)->set_normal(rot_normal, true);
+ }
+ DocumentUndo::setUndoSensitive(nv->document, saved);
+ nv->document->setModifiedSinceSave();
+}
+
void sp_namedview_set_document_rotation(SPNamedView *nv)
{
if ( nv->document->getRoot()->get_rotation() == nv->document_rotation) return;
@@ -984,6 +1005,7 @@ void sp_namedview_set_document_rotation(SPNamedView *nv)
sp_canvas_item_affine_absolute(canvas_border, rot * root->vbt);
nv->page_border_rotated = desktop->add_temporary_canvasitem(canvas_border, 0);
}
+ sp_namedview_doc_rotate_guides(nv);
nv->document->getRoot()->set_rotation(nv->document_rotation);
c->unref();
}
@@ -1025,6 +1047,8 @@ static void sp_namedview_lock_single_guide(SPGuide* guide, bool locked)
guide->set_locked(locked, true);
}
+
+
void sp_namedview_toggle_guides(SPDocument *doc, Inkscape::XML::Node *repr)
{
unsigned int v;
diff --git a/src/sp-namedview.h b/src/sp-namedview.h
index 34f03e67e..9d11c13b7 100644
--- a/src/sp-namedview.h
+++ b/src/sp-namedview.h
@@ -42,7 +42,7 @@ enum {
SP_BORDER_LAYER_TOP
};
-class SPNamedView : public SPObjectGroup {
+class SPNamedView : public SPObjectGroup{
public:
SPNamedView();
virtual ~SPNamedView();
diff --git a/src/sp-object.cpp b/src/sp-object.cpp
index 21d8bcd93..8d4c4f0d1 100644
--- a/src/sp-object.cpp
+++ b/src/sp-object.cpp
@@ -119,7 +119,7 @@ static gchar *sp_object_get_unique_id(SPObject *object,
* Constructor, sets all attributes to default values.
*/
SPObject::SPObject()
- : cloned(0), uflags(0), mflags(0), hrefcount(0), _total_hrefcount(0),
+ : cloned(0), clone_original(NULL), uflags(0), mflags(0), hrefcount(0), _total_hrefcount(0),
document(NULL), parent(NULL), id(NULL), repr(NULL), refCount(1), hrefList(std::list<SPObject*>()),
_successor(NULL), _collection_policy(SPObject::COLLECT_WITH_PARENT),
_label(NULL), _default_label(NULL)
@@ -663,6 +663,8 @@ void SPObject::build(SPDocument *document, Inkscape::XML::Node *repr) {
object->readAttr("xml:space");
object->readAttr("inkscape:label");
object->readAttr("inkscape:collect");
+ if(object->cloned)
+ object->clone_original = document->getObjectById(repr->attribute("id"));
for (Inkscape::XML::Node *rchild = repr->firstChild() ; rchild != NULL; rchild = rchild->next()) {
const std::string typeString = NodeTraits::get_type_string(*rchild);
diff --git a/src/sp-object.h b/src/sp-object.h
index ac3d0c851..355f837b5 100644
--- a/src/sp-object.h
+++ b/src/sp-object.h
@@ -201,6 +201,7 @@ public:
virtual ~SPObject();
unsigned int cloned : 1;
+ SPObject *clone_original;
unsigned int uflags : 8;
unsigned int mflags : 8;
SPIXmlSpace xml_space;
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index 9a95c3d8c..f9540c989 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -631,7 +631,7 @@ void InkscapePreferences::initPageUI()
_page_ui.add_line( false, _("Maximum documents in Open _Recent:"), _misc_recent, "",
_("Set the maximum length of the Open Recent list in the File menu, or clear the list"), false, reset_recent);
- _ui_zoom_correction.init(300, 30, 1.00, 200.0, 1.0, 10.0, 1.0);
+ _ui_zoom_correction.init(300, 30, 1.00, 500.0, 1.0, 10.0, 1.0);
_page_ui.add_line( false, _("_Zoom correction factor (in %):"), _ui_zoom_correction, "",
_("Adjust the slider until the length of the ruler on your screen matches its real length. This information is used when zooming to 1:1, 1:2, etc., to display objects in their true sizes"), true);
diff --git a/src/ui/tools/tool-base.cpp b/src/ui/tools/tool-base.cpp
index 8d1034161..e1b2f97af 100644
--- a/src/ui/tools/tool-base.cpp
+++ b/src/ui/tools/tool-base.cpp
@@ -94,6 +94,7 @@ ToolBase::ToolBase(gchar const *const *cursor_shape, gint hot_x, gint hot_y, boo
, _grdrag(NULL)
, shape_editor(NULL)
, space_panning(false)
+ , rotating_mode(false)
, _delayed_snap_event(NULL)
, _dse_callback_in_process(false)
, desktop(NULL)
@@ -334,6 +335,7 @@ bool ToolBase::root_handler(GdkEvent* event) {
/// @todo REmove redundant /value in preference keys
tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
bool allow_panning = prefs->getBool("/options/spacebarpans/value");
+ int rotation_snap = prefs->getInt("/options/rotationsnapsperpi/value", 15);
gint ret = FALSE;
switch (event->type) {
@@ -374,42 +376,63 @@ bool ToolBase::root_handler(GdkEvent* event) {
break;
case 2:
- if (event->button.state & GDK_SHIFT_MASK) {
- zoom_rb = 2;
+ if (event->button.state & GDK_MOD1_MASK) {
+ sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), event->button.time);
+ desktop->canvas->startRotateTo(desktop->namedview->document_rotation);
+ this->rotating_mode = true;
+ this->message_context->set(Inkscape::INFORMATION_MESSAGE,
+ _("<b>Space+ALT+mouse move</b> to rotate canvas"));
} else {
- // When starting panning, make sure there are no snap events pending because these might disable the panning again
- if (_uses_snap) {
- sp_event_context_discard_delayed_snap_event(this);
+ if (event->button.state & GDK_SHIFT_MASK) {
+ zoom_rb = 2;
+ } else {
+ // When starting panning, make sure there are no snap events pending because these might disable the panning again
+ if (_uses_snap) {
+ sp_event_context_discard_delayed_snap_event(this);
+ }
+ panning = 2;
+
+ sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
+ GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK, NULL,
+ event->button.time - 1);
}
- panning = 2;
-
- sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
- GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK
- | GDK_POINTER_MOTION_HINT_MASK, NULL,
- event->button.time - 1);
-
+ desktop->canvas->clearRotateTo();
+ this->rotating_mode = false;
+ ret = TRUE;
+ desktop->canvas->endRotateTo();
}
-
ret = TRUE;
break;
case 3:
- // if ((event->button.state & GDK_SHIFT_MASK) || (event->button.state & GDK_CONTROL_MASK)) {
- // // When starting panning, make sure there are no snap events pending because these might disable the panning again
- // if (_uses_snap) {
- // sp_event_context_discard_delayed_snap_event(this);
- // }
- // panning = 3;
-
- // sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
- // GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK
- // | GDK_POINTER_MOTION_HINT_MASK, NULL,
- // event->button.time);
-
- // ret = TRUE;
- // } else
- if( !this->space_panning ) {
- sp_event_root_menu_popup(desktop, NULL, event);
+ if (event->button.state & GDK_MOD1_MASK) {
+ sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), event->button.time);
+ desktop->canvas->startRotateTo(desktop->namedview->document_rotation);
+ this->rotating_mode = true;
+ this->message_context->set(Inkscape::INFORMATION_MESSAGE,
+ _("<b>Space+ALT+mouse move</b> to rotate canvas"));
+ } else {
+ if ((event->button.state & GDK_SHIFT_MASK) || (event->button.state & GDK_CONTROL_MASK)) {
+ // When starting panning, make sure there are no snap events pending because these might disable the panning again
+ if (_uses_snap) {
+ sp_event_context_discard_delayed_snap_event(this);
+ }
+ panning = 3;
+
+ sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
+ GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK, NULL,
+ event->button.time);
+
+ ret = TRUE;
+ } else if( !this->space_panning) {
+ sp_event_root_menu_popup(desktop, NULL, event);
+ }
+ desktop->canvas->clearRotateTo();
+ this->rotating_mode = false;
+ ret = TRUE;
+ desktop->canvas->endRotateTo();
}
break;
@@ -419,39 +442,38 @@ bool ToolBase::root_handler(GdkEvent* event) {
break;
case GDK_MOTION_NOTIFY:
+ if (this->rotating_mode) {
+ button_w = Geom::Point(event->motion.x, event->motion.y);
+ Geom::Point const motion_dt(desktop->doc2dt(desktop->w2d(button_w)));
+ Geom::Rect view = desktop->get_display_area();
+ Geom::Point view_center = desktop->doc2dt(view.midpoint());
+ Geom::Ray center_ray(motion_dt, view_center);
+ angle = Geom::deg_from_rad(center_ray.angle()) - 90;
+ if (event->motion.state & GDK_SHIFT_MASK && event->motion.state & GDK_CONTROL_MASK) {
+ angle = 0;
+ } else if(event->motion.state & GDK_CONTROL_MASK) {
+ angle = floor(angle/rotation_snap) * rotation_snap;
+ } else if (event->motion.state & GDK_SHIFT_MASK) {
+ angle = desktop->namedview->document_rotation;
+ } else if (event->motion.state & GDK_MOD1_MASK) {
+ //Decimal raw angle
+ } else {
+ angle = floor(angle);
+ }
+ desktop->canvas->rotateTo(angle);
+ } else if (panning == 4 && !xp && !yp ) {
+ // <Space> + mouse panning started, save location and grab canvas
+ xp = event->motion.x;
+ yp = event->motion.y;
+ button_w = Geom::Point(event->motion.x, event->motion.y);
+
+ sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
+ GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK
+ | GDK_POINTER_MOTION_MASK
+ | GDK_POINTER_MOTION_HINT_MASK, NULL,
+ event->motion.time - 1);
+ }
if (panning) {
- if (panning == 4 && !xp && !yp ) {
- // <Space> + mouse panning started, save location and grab canvas
- xp = event->motion.x;
- yp = event->motion.y;
- button_w = Geom::Point(event->motion.x, event->motion.y);
-
- sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
- GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK
- | GDK_POINTER_MOTION_MASK
- | GDK_POINTER_MOTION_HINT_MASK, NULL,
- event->motion.time - 1);
- } else if (this->space_panning && event->motion.state & GDK_BUTTON3_MASK) {
- sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), event->button.time);
- desktop->canvas->startRotateTo(desktop->namedview->document_rotation);
- button_w = Geom::Point(event->motion.x, event->motion.y);
- Geom::Point const motion_dt(desktop->doc2dt(desktop->w2d(button_w)));
- Geom::Rect view = desktop->get_display_area();
- Geom::Point view_center = desktop->doc2dt(view.midpoint());
- Geom::Ray center_ray(motion_dt, view_center);
- desktop->canvas->startRotateTo(desktop->namedview->document_rotation);
- angle = Geom::deg_from_rad(center_ray.angle()) - 90;
- if (event->motion.state & GDK_SHIFT_MASK && event->motion.state & GDK_CONTROL_MASK) {
- angle = desktop->namedview->document_rotation;
- } else if (event->motion.state & GDK_SHIFT_MASK) {
- angle = floor(angle/5) * 5;
- } else if (event->motion.state & GDK_CONTROL_MASK) {
- //Decimal raw angle
- } else {
- angle = floor(angle);
- }
- desktop->canvas->rotateTo(desktop->getDrawing(), angle);
- }
if ((panning == 2 && !(event->motion.state & GDK_BUTTON2_MASK))
|| (panning == 1 && !(event->motion.state & GDK_BUTTON1_MASK))
|| (panning == 3 && !(event->motion.state & GDK_BUTTON3_MASK))) {
@@ -516,20 +538,9 @@ bool ToolBase::root_handler(GdkEvent* event) {
break;
case GDK_BUTTON_RELEASE:
- desktop->canvas->clearRotateTo();
- if (this->space_panning && event->button.button == 3) {
- xp = yp = 0;
- if (panning_cursor == 1) {
- panning_cursor = 0;
- GtkWidget *w = GTK_WIDGET(this->desktop->getCanvas());
- gdk_window_set_cursor(gtk_widget_get_window (w), this->cursor);
- }
- zoom_rb = 0;
- if (panning) {
- panning = 0;
- sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate),
- event->button.time);
- }
+ if (this->rotating_mode && event->button.button == 2) {
+ desktop->canvas->clearRotateTo();
+ this->rotating_mode = false;
ret = TRUE;
if (desktop->canvas->endRotateTo()) {
sp_repr_set_svg_double(desktop->namedview->getRepr(), "inkscape:document-rotation", angle);
@@ -589,6 +600,12 @@ bool ToolBase::root_handler(GdkEvent* event) {
ret = TRUE;
}
+ if (this->rotating_mode && event->button.button != 3) {
+ desktop->canvas->clearRotateTo();
+ this->rotating_mode = false;
+ ret = TRUE;
+ desktop->canvas->endRotateTo();
+ }
}
break;
@@ -598,6 +615,22 @@ bool ToolBase::root_handler(GdkEvent* event) {
int const key_scroll = prefs->getIntLimited("/options/keyscroll/value",
10, 0, 1000);
+ if (this->rotating_mode &&
+ get_group0_keyval(&event->key) != GDK_KEY_space &&
+ get_group0_keyval(&event->key) != GDK_KEY_Shift_L &&
+ get_group0_keyval(&event->key) != GDK_KEY_Shift_R &&
+ get_group0_keyval(&event->key) != GDK_KEY_Control_L &&
+ get_group0_keyval(&event->key) != GDK_KEY_Control_R &&
+ get_group0_keyval(&event->key) != GDK_KEY_Alt_L &&
+ get_group0_keyval(&event->key) != GDK_KEY_Alt_R )
+ {
+ desktop->canvas->clearRotateTo();
+ this->rotating_mode = false;
+ ret = TRUE;
+ desktop->canvas->endRotateTo();
+ break;
+ }
+
switch (get_group0_keyval(&event->key)) {
// GDK insists on stealing these keys (F1 for no idea what, tab for cycling widgets
// in the editing window). So we resteal them back and run our regular shortcut
@@ -709,14 +742,21 @@ bool ToolBase::root_handler(GdkEvent* event) {
break;
case GDK_KEY_space:
- within_tolerance = true;
- xp = yp = 0;
- if (!allow_panning) break;
- panning = 4;
- this->space_panning = true;
- this->message_context->set(Inkscape::INFORMATION_MESSAGE,
- _("<b>Space+mouse move</b> to pan canvas"));
-
+ if (event->key.state & GDK_MOD1_MASK) {
+ sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), event->button.time);
+ desktop->canvas->startRotateTo(desktop->namedview->document_rotation);
+ this->rotating_mode = true;
+ this->message_context->set(Inkscape::INFORMATION_MESSAGE,
+ _("<b>Space+ALT+mouse move</b> to rotate canvas"));
+ } else {
+ within_tolerance = true;
+ xp = yp = 0;
+ if (!allow_panning) break;
+ panning = 4;
+ this->space_panning = true;
+ this->message_context->set(Inkscape::INFORMATION_MESSAGE,
+ _("<b>Space+mouse move</b> to pan canvas"));
+ }
ret = TRUE;
break;
@@ -735,6 +775,22 @@ bool ToolBase::root_handler(GdkEvent* event) {
break;
case GDK_KEY_RELEASE:
+ if (this->rotating_mode &&
+ get_group0_keyval(&event->key) != GDK_KEY_space &&
+ get_group0_keyval(&event->key) != GDK_KEY_Shift_L &&
+ get_group0_keyval(&event->key) != GDK_KEY_Shift_R &&
+ get_group0_keyval(&event->key) != GDK_KEY_Control_L &&
+ get_group0_keyval(&event->key) != GDK_KEY_Control_R &&
+ get_group0_keyval(&event->key) != GDK_KEY_Alt_L &&
+ get_group0_keyval(&event->key) != GDK_KEY_Alt_R )
+ {
+ desktop->canvas->clearRotateTo();
+ this->rotating_mode = false;
+ ret = TRUE;
+ desktop->canvas->endRotateTo();
+ break;
+ }
+
// Stop panning on any key release
if (this->space_panning) {
this->space_panning = false;
@@ -759,7 +815,14 @@ bool ToolBase::root_handler(GdkEvent* event) {
switch (get_group0_keyval(&event->key)) {
case GDK_KEY_space:
- desktop->canvas->clearRotateTo();
+ if (this->rotating_mode) {
+ desktop->canvas->clearRotateTo();
+ this->rotating_mode = false;
+ ret = TRUE;
+ if (desktop->canvas->endRotateTo()) {
+ sp_repr_set_svg_double(desktop->namedview->getRepr(), "inkscape:document-rotation", angle);
+ }
+ }
if (within_tolerance) {
// Space was pressed, but not panned
sp_toggle_selector(desktop);
@@ -781,10 +844,16 @@ bool ToolBase::root_handler(GdkEvent* event) {
default:
break;
}
- desktop->canvas->clearRotateTo();
break;
case GDK_SCROLL: {
+ if (this->rotating_mode) {
+ desktop->canvas->clearRotateTo();
+ this->rotating_mode = false;
+ ret = TRUE;
+ desktop->canvas->endRotateTo();
+ break;
+ }
bool ctrl = (event->scroll.state & GDK_CONTROL_MASK);
bool wheelzooms = prefs->getBool("/options/wheelzooms/value");
diff --git a/src/ui/tools/tool-base.h b/src/ui/tools/tool-base.h
index 58eb6f88e..3d22fc66f 100644
--- a/src/ui/tools/tool-base.h
+++ b/src/ui/tools/tool-base.h
@@ -176,6 +176,7 @@ public:
ShapeEditor* shape_editor;
bool space_panning;
+ bool rotating_mode;
DelayedSnapEvent *_delayed_snap_event;
bool _dse_callback_in_process;
diff --git a/src/uri-references.cpp b/src/uri-references.cpp
index 07f2d168b..170c98beb 100644
--- a/src/uri-references.cpp
+++ b/src/uri-references.cpp
@@ -3,6 +3,7 @@
*
* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
+ * Marc Jeanmougin
*
* Copyright (C) 2001-2002 Lauris Kaplinski
* Copyright (C) 2001 Ximian, Inc.
@@ -48,13 +49,10 @@ URIReference::~URIReference() { detach(); }
* The main ideas here are:
* (1) "If we are inside a clone, then we can accept if and only if our "original thing" can accept the reference"
* (this caused problems when there are clones because a change in ids triggers signals for the object hrefing this id,
- *but also its cloned reprs
- * (descendants of <use> referencing an ancestor of the href'ing object)). The way it is done here is *atrocious*, but i
- *could not find a better way.
- * FIXME: find a better and safer way to find the "original object" of anyone with the flag ->cloned
+ * but also its cloned reprs(descendants of <use> referencing an ancestor of the href'ing object)).
*
* (2) Once we have an (potential owner) object, it can accept a href to obj, iff the graph of objects where directed
- *edges are
+ * edges are
* either parent->child relations , *** or href'ing to href'ed *** relations, stays acyclic.
* We can go either from owner and up in the tree, or from obj and down, in either case this will be in the worst case
*linear in the number of objects.
@@ -70,29 +68,17 @@ bool URIReference::_acceptObject(SPObject *obj) const
SPObject *owner = getOwner();
if (!owner)
return true;
+
while (owner->cloned) {
- std::vector<int> positions;
- while (owner->cloned) {
- int position = 0;
- for (auto &child: owner->parent->children) {
- if(&child == owner) {
- break;
- }
- position++;
- }
- positions.push_back(position);
+ if(!owner->clone_original)//happens when the clone is existing and linking to something, even before the original objects exists.
+ //for instance, it can happen when you paste a filtered object in a already cloned group: The construction of the
+ //clone representation of the filtered object will finish before the original object, so the cloned repr will
+ //have to _accept the filter even though the original does not exist yet. In that case, we'll accept iff the parent of the
+ //original can accept it: loops caused by other relations than parent-child would be prevented when created on their base object.
+ //Fixes bug 1636533.
owner = owner->parent;
- }
- if (dynamic_cast<SPUse *>(owner))
- owner = ((SPUse *)owner)->get_original();
- else if (dynamic_cast<SPTagUse *>(owner))
- owner = ((SPTagUse *)owner)->get_original();
- else {
- g_warning("cloned object with no known type\n");
- return false;
- }
- for (int i = (int) (positions.size() - 2); i >= 0; i--)
- owner = owner->childList(false)[positions[i]];
+ else
+ owner = owner->clone_original;
}
// once we have the "original" object (hopefully) we look at who is referencing it
if (obj == owner)