diff options
| author | Jabier Arraiza Cenoz <jabier.arraiza@marker.es> | 2016-11-01 15:18:55 +0000 |
|---|---|---|
| committer | jabiertxof <info@marker.es> | 2016-11-01 15:18:55 +0000 |
| commit | efd3002943b5346bbaf961f3f02dc81c0ca0716d (patch) | |
| tree | f92291c0ef59518938aa5db1abcc39e57ffdfbd0 /src | |
| parent | Add fadding from temporary rotate draw to real ones (diff) | |
| parent | [Bug #1574561] Italian translation update. (diff) | |
| download | inkscape-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.cpp | 4 | ||||
| -rw-r--r-- | src/display/sp-canvas.cpp | 18 | ||||
| -rw-r--r-- | src/display/sp-canvas.h | 2 | ||||
| -rw-r--r-- | src/file.cpp | 13 | ||||
| -rw-r--r-- | src/sp-namedview.cpp | 24 | ||||
| -rw-r--r-- | src/sp-namedview.h | 2 | ||||
| -rw-r--r-- | src/sp-object.cpp | 4 | ||||
| -rw-r--r-- | src/sp-object.h | 1 | ||||
| -rw-r--r-- | src/ui/dialog/inkscape-preferences.cpp | 2 | ||||
| -rw-r--r-- | src/ui/tools/tool-base.cpp | 239 | ||||
| -rw-r--r-- | src/ui/tools/tool-base.h | 1 | ||||
| -rw-r--r-- | src/uri-references.cpp | 38 |
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) |
