X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fdesktop.cpp;h=8c070786e6a5d0e6530ad48426cb0abadd55cee7;hb=d1150228ea8064478ea50cd32e99d399b16455e3;hp=e16b030a44dfc9d2c2705502fcc61b661bcc172e;hpb=da83ec78b92d29793d7cd1d6526585cda47127f4;p=inkscape.git diff --git a/src/desktop.cpp b/src/desktop.cpp index e16b030a4..8c070786e 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -57,6 +57,7 @@ #include #include +#include <2geom/rect.h> #include "macros.h" #include "inkscape-private.h" #include "desktop.h" @@ -69,7 +70,7 @@ #include "sp-namedview.h" #include "color.h" #include "sp-item-group.h" -#include "prefs-utils.h" +#include "preferences.h" #include "object-hierarchy.h" #include "helper/units.h" #include "display/canvas-arena.h" @@ -79,8 +80,6 @@ #include "display/sp-canvas-util.h" #include "display/canvas-temporary-item-list.h" #include "display/snap-indicator.h" -#include "libnr/nr-matrix-div.h" -#include "libnr/nr-rect-ops.h" #include "ui/dialog/dialog-manager.h" #include "xml/repr.h" #include "message-context.h" @@ -105,7 +104,6 @@ static void _layer_hierarchy_changed(SPObject *top, SPObject *bottom, SPDesktop static void _reconstruction_start(SPDesktop * desktop); static void _reconstruction_finish(SPDesktop * desktop); static void _namedview_modified (SPObject *obj, guint flags, SPDesktop *desktop); -static void _update_snap_distances (SPDesktop *desktop); /** * Return new desktop object. @@ -134,6 +132,7 @@ SPDesktop::SPDesktop() : page( 0 ), page_border( 0 ), current( 0 ), + _focusMode(false), zooms_past( 0 ), zooms_future( 0 ), dkey( 0 ), @@ -156,11 +155,11 @@ SPDesktop::SPDesktop() : _active( false ), _w2d(), _d2w(), - _doc2dt( NR::Matrix(NR::scale(1, -1)) ), + _doc2dt( Geom::Scale(1, -1) ), grids_visible( false ) { - _d2w.set_identity(); - _w2d.set_identity(); + _d2w.setIdentity(); + _w2d.setIdentity(); selection = Inkscape::GC::release( new Inkscape::Selection(this) ); } @@ -170,10 +169,11 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) { // Temporary workaround for link order issues: Inkscape::DeviceManager::getManager().getDevices(); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); _guides_message_context = new Inkscape::MessageContext(const_cast(messageStack())); - current = sp_repr_css_attr_inherited (inkscape_get_repr (INKSCAPE, "desktop"), "style"); + current = prefs->getStyle("/desktop/style"); namedview = nv; canvas = aCanvas; @@ -205,7 +205,7 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) g_signal_connect (G_OBJECT (main), "event", G_CALLBACK (sp_desktop_root_handler), this); table = sp_canvas_item_new (main, SP_TYPE_CTRLRECT, NULL); - SP_CTRLRECT(table)->setRectangle(NR::Rect(NR::Point(-80000, -80000), NR::Point(80000, 80000))); + SP_CTRLRECT(table)->setRectangle(Geom::Rect(Geom::Point(-80000, -80000), Geom::Point(80000, 80000))); SP_CTRLRECT(table)->setColor(0x00000000, true, 0x00000000); sp_canvas_item_move_to_z (table, 0); @@ -216,9 +216,9 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) drawing = sp_canvas_item_new (main, SP_TYPE_CANVAS_ARENA, NULL); g_signal_connect (G_OBJECT (drawing), "arena_event", G_CALLBACK (_arena_handler), this); - SP_CANVAS_ARENA (drawing)->arena->delta = prefs_get_double_attribute ("options.cursortolerance", "value", 1.0); // default is 1 px + SP_CANVAS_ARENA (drawing)->arena->delta = prefs->getDouble("/options/cursortolerance/value", 1.0); // default is 1 px - if (prefs_get_int_attribute("options.startmode", "outline", 0)) { + if (prefs->getBool("/options/startmode/outline")) { // Start in outline mode setDisplayModeOutline(); } else { @@ -226,11 +226,18 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) setDisplayModeNormal(); } + // The order in which these canvas items are added determines the z-order. It's therefore + // important to add the tempgroup (which will contain the snapindicator) before adding the + // controls. Only this way one will be able to quickly (before the snap indicator has + // disappeared) reselect a node after snapping it. If the z-order is wrong however, this + // will not work (the snap indicator is on top of the node handler; is the snapindicator + // being selected? or does it intercept some of the events that should have gone to the + // node handler? see bug https://bugs.launchpad.net/inkscape/+bug/414142) gridgroup = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); guides = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); sketch = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); - controls = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); tempgroup = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); + controls = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); /* Push select tool to the bottom of stack */ /** \todo @@ -238,12 +245,12 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) * call "set" instead of "push". Can we assume that there is only one * context ever? */ - push_event_context (SP_TYPE_SELECT_CONTEXT, "tools.select", SP_EVENT_CONTEXT_STATIC); + push_event_context (SP_TYPE_SELECT_CONTEXT, "/tools/select", SP_EVENT_CONTEXT_STATIC); // display rect and zoom are now handled in sp_desktop_widget_realize() - NR::Rect const d(NR::Point(0.0, 0.0), - NR::Point(sp_document_width(document), sp_document_height(document))); + Geom::Rect const d(Geom::Point(0.0, 0.0), + Geom::Point(sp_document_width(document), sp_document_height(document))); SP_CTRLRECT(page)->setRectangle(d); SP_CTRLRECT(page_border)->setRectangle(d); @@ -271,7 +278,6 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) SP_ITEM_SHOW_DISPLAY); if (ai) { nr_arena_item_add_child (SP_CANVAS_ARENA (drawing)->root, ai, NULL); - nr_arena_item_unref (ai); } namedview->show(this); @@ -341,6 +347,11 @@ void SPDesktop::destroy() temporary_item_list = NULL; } + if (selection) { + delete selection; + selection = NULL; + } + namedview->hide(this); _activate_connection.disconnect(); @@ -395,11 +406,19 @@ SPDesktop::~SPDesktop() {} /* Public methods */ +/* These methods help for temporarily showing things on-canvas. + * The *only* valid use of the TemporaryItem* that you get from add_temporary_canvasitem + * is when you want to prematurely remove the item from the canvas, by calling + * desktop->remove_temporary_canvasitem(tempitem). + */ /** Note that lifetime is measured in milliseconds -* it is perfectly safe to ignore the returned pointer: the object is deleted by itself, so don't delete it elsewhere! -* The return value should only be used as argument for SPDesktop::remove_temporary_canvasitem, because the object might be deleted already. -* move_to_bottom = true by default so the item does not interfere with handling of other items on the canvas like nodes. -*/ + * One should *not* keep a reference to the SPCanvasItem, the temporary item code will + * delete the object for you and the reference will become invalid without you knowing it. + * It is perfectly safe to ignore the returned pointer: the object is deleted by itself, so don't delete it elsewhere! + * The *only* valid use of the returned TemporaryItem* is as argument for SPDesktop::remove_temporary_canvasitem, + * because the object might be deleted already without you knowing it. + * move_to_bottom = true by default so the item does not interfere with handling of other items on the canvas like nodes. + */ Inkscape::Display::TemporaryItem * SPDesktop::add_temporary_canvasitem (SPCanvasItem *item, guint lifetime, bool move_to_bottom) { @@ -521,8 +540,8 @@ bool SPDesktop::isLayer(SPObject *object) const { */ bool SPDesktop::isWithinViewport (SPItem *item) const { - NR::Rect const viewport = get_display_area(); - NR::Maybe const bbox = sp_item_bbox_desktop(item); + Geom::Rect const viewport = get_display_area(); + Geom::OptRect const bbox = sp_item_bbox_desktop(item); if (bbox) { return viewport.contains(*bbox); } else { @@ -601,8 +620,7 @@ SPDesktop::set_event_context (GtkType type, const gchar *config) g_object_unref (G_OBJECT (ec)); } - Inkscape::XML::Node *repr = (config) ? inkscape_get_repr (_inkscape, config) : NULL; - ec = sp_event_context_new (type, this, repr, SP_EVENT_CONTEXT_STATIC); + ec = sp_event_context_new (type, this, config, SP_EVENT_CONTEXT_STATIC); ec->next = event_context; event_context = ec; sp_event_context_activate (ec); @@ -616,7 +634,6 @@ void SPDesktop::push_event_context (GtkType type, const gchar *config, unsigned int key) { SPEventContext *ref, *ec; - Inkscape::XML::Node *repr; if (event_context && event_context->key == key) return; ref = event_context; @@ -629,8 +646,7 @@ SPDesktop::push_event_context (GtkType type, const gchar *config, unsigned int k } if (event_context) sp_event_context_deactivate (event_context); - repr = (config) ? inkscape_get_repr (INKSCAPE, config) : NULL; - ec = sp_event_context_new (type, this, repr, key); + ec = sp_event_context_new (type, this, config, key); ec->next = event_context; event_context = ec; sp_event_context_activate (ec); @@ -641,7 +657,7 @@ SPDesktop::push_event_context (GtkType type, const gchar *config, unsigned int k * Sets the coordinate status to a given point */ void -SPDesktop::set_coordinate_status (NR::Point p) { +SPDesktop::set_coordinate_status (Geom::Point p) { _widget->setCoordinateStatus(p); } @@ -649,7 +665,7 @@ SPDesktop::set_coordinate_status (NR::Point p) { * \see sp_document_item_from_list_at_point_bottom() */ SPItem * -SPDesktop::item_from_list_at_point_bottom (const GSList *list, NR::Point const p) const +SPDesktop::item_from_list_at_point_bottom (const GSList *list, Geom::Point const p) const { g_return_val_if_fail (doc() != NULL, NULL); return sp_document_item_from_list_at_point_bottom (dkey, SP_GROUP (doc()->root), list, p); @@ -659,7 +675,7 @@ SPDesktop::item_from_list_at_point_bottom (const GSList *list, NR::Point const p * \see sp_document_item_at_point() */ SPItem * -SPDesktop::item_at_point (NR::Point const p, bool into_groups, SPItem *upto) const +SPDesktop::item_at_point (Geom::Point const p, bool into_groups, SPItem *upto) const { g_return_val_if_fail (doc() != NULL, NULL); return sp_document_item_at_point (doc(), dkey, p, into_groups, upto); @@ -669,7 +685,7 @@ SPDesktop::item_at_point (NR::Point const p, bool into_groups, SPItem *upto) con * \see sp_document_group_at_point() */ SPItem * -SPDesktop::group_at_point (NR::Point const p) const +SPDesktop::group_at_point (Geom::Point const p) const { g_return_val_if_fail (doc() != NULL, NULL); return sp_document_group_at_point (doc(), dkey, p); @@ -679,22 +695,22 @@ SPDesktop::group_at_point (NR::Point const p) const * \brief Returns the mouse point in document coordinates; if mouse is * outside the canvas, returns the center of canvas viewpoint */ -NR::Point +Geom::Point SPDesktop::point() const { - NR::Point p = _widget->getPointer(); - NR::Point pw = sp_canvas_window_to_world (canvas, p); + Geom::Point p = _widget->getPointer(); + Geom::Point pw = sp_canvas_window_to_world (canvas, p); p = w2d(pw); - NR::Rect const r = canvas->getViewbox(); + Geom::Rect const r = canvas->getViewbox(); - NR::Point r0 = w2d(r.min()); - NR::Point r1 = w2d(r.max()); + Geom::Point r0 = w2d(r.min()); + Geom::Point r1 = w2d(r.max()); - if (p[NR::X] >= r0[NR::X] && - p[NR::X] <= r1[NR::X] && - p[NR::Y] >= r1[NR::Y] && - p[NR::Y] <= r0[NR::Y]) + if (p[Geom::X] >= r0[Geom::X] && + p[Geom::X] <= r1[Geom::X] && + p[Geom::Y] >= r1[Geom::Y] && + p[Geom::Y] <= r0[Geom::Y]) { return p; } else { @@ -708,13 +724,13 @@ SPDesktop::point() const void SPDesktop::push_current_zoom (GList **history) { - NR::Rect const area = get_display_area(); + Geom::Rect const area = get_display_area(); NRRect *old_zoom = g_new(NRRect, 1); - old_zoom->x0 = area.min()[NR::X]; - old_zoom->x1 = area.max()[NR::X]; - old_zoom->y0 = area.min()[NR::Y]; - old_zoom->y1 = area.max()[NR::Y]; + old_zoom->x0 = area.min()[Geom::X]; + old_zoom->x1 = area.max()[Geom::X]; + old_zoom->y0 = area.min()[Geom::Y]; + old_zoom->y1 = area.max()[Geom::Y]; if ( *history == NULL || !( ( ((NRRect *) ((*history)->data))->x0 == old_zoom->x0 ) && ( ((NRRect *) ((*history)->data))->x1 == old_zoom->x1 ) && @@ -744,14 +760,16 @@ SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double double const cx = 0.5 * (x0 + x1); double const cy = 0.5 * (y0 + y1); - NR::Rect const viewbox = NR::expand(canvas->getViewbox(), border); + // FIXME: This 2geom idiom doesn't allow us to declare dbox const + Geom::Rect viewbox = canvas->getViewbox(); + viewbox.expandBy(-border); - double scale = expansion(_d2w); + double scale = _d2w.descrim(); double newscale; - if (((x1 - x0) * viewbox.dimensions()[NR::Y]) > ((y1 - y0) * viewbox.dimensions()[NR::X])) { - newscale = viewbox.dimensions()[NR::X] / (x1 - x0); + if (((x1 - x0) * viewbox.dimensions()[Geom::Y]) > ((y1 - y0) * viewbox.dimensions()[Geom::X])) { + newscale = viewbox.dimensions()[Geom::X] / (x1 - x0); } else { - newscale = viewbox.dimensions()[NR::Y] / (y1 - y0); + newscale = viewbox.dimensions()[Geom::Y] / (y1 - y0); } newscale = CLAMP(newscale, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX); // unit: 'screen pixels' per 'document pixels' @@ -759,15 +777,15 @@ SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double int clear = FALSE; if (!NR_DF_TEST_CLOSE (newscale, scale, 1e-4 * scale)) { /* Set zoom factors */ - _d2w = NR::Matrix(NR::scale(newscale, -newscale)); - _w2d = NR::Matrix(NR::scale(1/newscale, 1/-newscale)); + _d2w = Geom::Scale(newscale, -newscale); + _w2d = Geom::Scale(1/newscale, 1/-newscale); sp_canvas_item_affine_absolute(SP_CANVAS_ITEM(main), _d2w); clear = TRUE; } /* Calculate top left corner (in document pixels) */ - x0 = cx - 0.5 * viewbox.dimensions()[NR::X] / newscale; - y1 = cy + 0.5 * viewbox.dimensions()[NR::Y] / newscale; + x0 = cx - 0.5 * viewbox.dimensions()[Geom::X] / newscale; + y1 = cy + 0.5 * viewbox.dimensions()[Geom::Y] / newscale; /* Scroll */ sp_canvas_scroll_to (canvas, x0 * newscale - border, y1 * -newscale - border, clear); @@ -776,26 +794,26 @@ SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double sp_box3d_context_update_lines(event_context); _widget->updateRulers(); - _widget->updateScrollbars(expansion(_d2w)); + _widget->updateScrollbars(_d2w.descrim()); _widget->updateZoom(); } -void SPDesktop::set_display_area(NR::Rect const &a, NR::Coord b, bool log) +void SPDesktop::set_display_area(Geom::Rect const &a, Geom::Coord b, bool log) { - set_display_area(a.min()[NR::X], a.min()[NR::Y], a.max()[NR::X], a.max()[NR::Y], b, log); + set_display_area(a.min()[Geom::X], a.min()[Geom::Y], a.max()[Geom::X], a.max()[Geom::Y], b, log); } /** * Return viewbox dimensions. */ -NR::Rect SPDesktop::get_display_area() const +Geom::Rect SPDesktop::get_display_area() const { - NR::Rect const viewbox = canvas->getViewbox(); + Geom::Rect const viewbox = canvas->getViewbox(); double const scale = _d2w[0]; - return NR::Rect(NR::Point(viewbox.min()[NR::X] / scale, viewbox.max()[NR::Y] / -scale), - NR::Point(viewbox.max()[NR::X] / scale, viewbox.min()[NR::Y] / -scale)); + return Geom::Rect(Geom::Point(viewbox.min()[Geom::X] / scale, viewbox.max()[Geom::Y] / -scale), + Geom::Point(viewbox.max()[Geom::X] / scale, viewbox.min()[Geom::Y] / -scale)); } /** @@ -848,6 +866,103 @@ SPDesktop::next_zoom() zooms_future = g_list_remove (zooms_future, ((NRRect *) zooms_future->data)); } +#include "tools-switch.h" +#include "node-context.h" +#include "shape-editor.h" +#include "nodepath.h" + +/** \brief Performs a quick zoom into what the user is working on + \param enable Whether we're going in or out of quick zoom + +*/ +void +SPDesktop::zoom_quick (bool enable) +{ + if (enable == _quick_zoom_enabled) { + return; + } + + if (enable == true) { + _quick_zoom_stored_area = get_display_area(); + bool zoomed = false; + + if (!zoomed) { + SPItem * singleItem = selection->singleItem(); + if (singleItem != NULL && tools_isactive(this, TOOLS_NODES)) { + + Inkscape::NodePath::Path * nodepath = event_context->shape_editor->get_nodepath(); + // printf("I've got a nodepath, crazy\n"); + + if (nodepath) { + Geom::Rect nodes; + bool firstnode = true; + + if (nodepath->selected) { + for (GList *spl = nodepath->subpaths; spl != NULL; spl = spl->next) { + Inkscape::NodePath::SubPath *subpath = (Inkscape::NodePath::SubPath *) spl->data; + for (GList *nl = subpath->nodes; nl != NULL; nl = nl->next) { + Inkscape::NodePath::Node *node = (Inkscape::NodePath::Node *) nl->data; + if (node->selected) { + // printf("\tSelected node\n"); + if (firstnode) { + nodes = Geom::Rect(node->pos, node->pos); + firstnode = false; + } else { + nodes.expandTo(node->pos); + } + + if (node->p.other != NULL) { + /* Include previous node pos */ + nodes.expandTo(node->p.other->pos); + + /* Include previous handle */ + if (!sp_node_side_is_line(node, &node->p)) { + nodes.expandTo(node->p.pos); + } + } + + if (node->n.other != NULL) { + /* Include previous node pos */ + nodes.expandTo(node->n.other->pos); + + /* Include previous handle */ + if (!sp_node_side_is_line(node, &node->n)) { + nodes.expandTo(node->n.pos); + } + } + } + } + } + + if (!firstnode && nodes.area() * 2.0 < _quick_zoom_stored_area.area()) { + set_display_area(nodes, 10); + zoomed = true; + } + } + } + } + } + + if (!zoomed) { + Geom::OptRect const d = selection->bounds(); + if (d && d->area() * 2.0 < _quick_zoom_stored_area.area()) { + set_display_area(*d, 10); + zoomed = true; + } + } + + if (!zoomed) { + zoom_relative(_quick_zoom_stored_area.midpoint()[Geom::X], _quick_zoom_stored_area.midpoint()[Geom::Y], 2.0); + zoomed = true; + } + } else { + set_display_area(_quick_zoom_stored_area, 0); + } + + _quick_zoom_enabled = enable; + return; +} + /** * Zoom to point with absolute zoom factor. */ @@ -859,13 +974,13 @@ SPDesktop::zoom_absolute_keep_point (double cx, double cy, double px, double py, // maximum or minimum zoom reached, but there's no exact equality because of rounding errors; // this check prevents "sliding" when trying to zoom in at maximum zoom; /// \todo someone please fix calculations properly and remove this hack - if (fabs(expansion(_d2w) - zoom) < 0.0001*zoom && (fabs(SP_DESKTOP_ZOOM_MAX - zoom) < 0.01 || fabs(SP_DESKTOP_ZOOM_MIN - zoom) < 0.000001)) + if (fabs(_d2w.descrim() - zoom) < 0.0001*zoom && (fabs(SP_DESKTOP_ZOOM_MAX - zoom) < 0.01 || fabs(SP_DESKTOP_ZOOM_MIN - zoom) < 0.000001)) return; - NR::Rect const viewbox = canvas->getViewbox(); + Geom::Rect const viewbox = canvas->getViewbox(); - double const width2 = viewbox.dimensions()[NR::X] / zoom; - double const height2 = viewbox.dimensions()[NR::Y] / zoom; + double const width2 = viewbox.dimensions()[Geom::X] / zoom; + double const height2 = viewbox.dimensions()[Geom::Y] / zoom; set_display_area(cx - px * width2, cy - py * height2, @@ -889,24 +1004,24 @@ SPDesktop::zoom_absolute (double cx, double cy, double zoom) void SPDesktop::zoom_relative_keep_point (double cx, double cy, double zoom) { - NR::Rect const area = get_display_area(); + Geom::Rect const area = get_display_area(); - if (cx < area.min()[NR::X]) { - cx = area.min()[NR::X]; + if (cx < area.min()[Geom::X]) { + cx = area.min()[Geom::X]; } - if (cx > area.max()[NR::X]) { - cx = area.max()[NR::X]; + if (cx > area.max()[Geom::X]) { + cx = area.max()[Geom::X]; } - if (cy < area.min()[NR::Y]) { - cy = area.min()[NR::Y]; + if (cy < area.min()[Geom::Y]) { + cy = area.min()[Geom::Y]; } - if (cy > area.max()[NR::Y]) { - cy = area.max()[NR::Y]; + if (cy > area.max()[Geom::Y]) { + cy = area.max()[Geom::Y]; } - gdouble const scale = expansion(_d2w) * zoom; - double const px = (cx - area.min()[NR::X]) / area.dimensions()[NR::X]; - double const py = (cy - area.min()[NR::Y]) / area.dimensions()[NR::Y]; + gdouble const scale = _d2w.descrim() * zoom; + double const px = (cx - area.min()[Geom::X]) / area.dimensions()[Geom::X]; + double const py = (cy - area.min()[Geom::Y]) / area.dimensions()[Geom::Y]; zoom_absolute_keep_point(cx, cy, px, py, scale); } @@ -917,7 +1032,7 @@ SPDesktop::zoom_relative_keep_point (double cx, double cy, double zoom) void SPDesktop::zoom_relative (double cx, double cy, double zoom) { - gdouble scale = expansion(_d2w) * zoom; + gdouble scale = _d2w.descrim() * zoom; zoom_absolute (cx, cy, scale); } @@ -927,10 +1042,10 @@ SPDesktop::zoom_relative (double cx, double cy, double zoom) void SPDesktop::zoom_page() { - NR::Rect d(NR::Point(0, 0), - NR::Point(sp_document_width(doc()), sp_document_height(doc()))); + Geom::Rect d(Geom::Point(0, 0), + Geom::Point(sp_document_width(doc()), sp_document_height(doc()))); - if (d.isEmpty(1.0)) { + if (d.minExtent() < 1.0) { return; } @@ -943,14 +1058,14 @@ SPDesktop::zoom_page() void SPDesktop::zoom_page_width() { - NR::Rect const a = get_display_area(); + Geom::Rect const a = get_display_area(); if (sp_document_width(doc()) < 1.0) { return; } - NR::Rect d(NR::Point(0, a.midpoint()[NR::Y]), - NR::Point(sp_document_width(doc()), a.midpoint()[NR::Y])); + Geom::Rect d(Geom::Point(0, a.midpoint()[Geom::Y]), + Geom::Point(sp_document_width(doc()), a.midpoint()[Geom::Y])); set_display_area(d, 10); } @@ -961,9 +1076,9 @@ SPDesktop::zoom_page_width() void SPDesktop::zoom_selection() { - NR::Maybe const d = selection->bounds(); + Geom::OptRect const d = selection->bounds(); - if ( !d || d->isEmpty(0.1) ) { + if ( !d || d->minExtent() < 0.1 ) { return; } @@ -989,12 +1104,12 @@ SPDesktop::zoom_drawing() SPItem *docitem = SP_ITEM (sp_document_root (doc())); g_return_if_fail (docitem != NULL); - NR::Maybe d = sp_item_bbox_desktop(docitem); + Geom::OptRect d = sp_item_bbox_desktop(docitem); /* Note that the second condition here indicates that ** there are no items in the drawing. */ - if ( !d || d->isEmpty(1.0) ) { + if ( !d || d->minExtent() < 0.1 ) { return; } @@ -1007,7 +1122,7 @@ SPDesktop::zoom_drawing() void SPDesktop::scroll_world_in_svg_coords (double dx, double dy, bool is_scrolling) { - double scale = expansion(_d2w); + double scale = _d2w.descrim(); scroll_world(dx*scale, dy*scale, is_scrolling); } @@ -1019,53 +1134,59 @@ SPDesktop::scroll_world (double dx, double dy, bool is_scrolling) { g_assert(_widget); - NR::Rect const viewbox = canvas->getViewbox(); + Geom::Rect const viewbox = canvas->getViewbox(); - sp_canvas_scroll_to(canvas, viewbox.min()[NR::X] - dx, viewbox.min()[NR::Y] - dy, FALSE, is_scrolling); + sp_canvas_scroll_to(canvas, viewbox.min()[Geom::X] - dx, viewbox.min()[Geom::Y] - dy, FALSE, is_scrolling); /* update perspective lines if we are in the 3D box tool (so that infinite ones are shown correctly) */ sp_box3d_context_update_lines(event_context); _widget->updateRulers(); - _widget->updateScrollbars(expansion(_d2w)); + _widget->updateScrollbars(_d2w.descrim()); } bool -SPDesktop::scroll_to_point (NR::Point const *p, gdouble autoscrollspeed) +SPDesktop::scroll_to_point (Geom::Point const &p, gdouble autoscrollspeed) { - gdouble autoscrolldistance = (gdouble) prefs_get_int_attribute_limited ("options.autoscrolldistance", "value", 0, -1000, 10000); + using Geom::X; + using Geom::Y; + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + gdouble autoscrolldistance = (gdouble) prefs->getIntLimited("/options/autoscrolldistance/value", 0, -1000, 10000); // autoscrolldistance is in screen pixels, but the display area is in document units - autoscrolldistance /= expansion(_d2w); - NR::Rect const dbox = NR::expand(get_display_area(), -autoscrolldistance); + autoscrolldistance /= _d2w.descrim(); + // FIXME: This 2geom idiom doesn't allow us to declare dbox const + Geom::Rect dbox = get_display_area(); + dbox.expandBy(-autoscrolldistance); - if (!((*p)[NR::X] > dbox.min()[NR::X] && (*p)[NR::X] < dbox.max()[NR::X]) || - !((*p)[NR::Y] > dbox.min()[NR::Y] && (*p)[NR::Y] < dbox.max()[NR::Y]) ) { + if (!(p[X] > dbox.min()[X] && p[X] < dbox.max()[X]) || + !(p[Y] > dbox.min()[Y] && p[Y] < dbox.max()[Y]) ) { - NR::Point const s_w( (*p) * _d2w ); + Geom::Point const s_w( p * (Geom::Matrix)_d2w ); gdouble x_to; - if ((*p)[NR::X] < dbox.min()[NR::X]) - x_to = dbox.min()[NR::X]; - else if ((*p)[NR::X] > dbox.max()[NR::X]) - x_to = dbox.max()[NR::X]; + if (p[X] < dbox.min()[X]) + x_to = dbox.min()[X]; + else if (p[X] > dbox.max()[X]) + x_to = dbox.max()[X]; else - x_to = (*p)[NR::X]; + x_to = p[X]; gdouble y_to; - if ((*p)[NR::Y] < dbox.min()[NR::Y]) - y_to = dbox.min()[NR::Y]; - else if ((*p)[NR::Y] > dbox.max()[NR::Y]) - y_to = dbox.max()[NR::Y]; + if (p[Y] < dbox.min()[Y]) + y_to = dbox.min()[Y]; + else if (p[Y] > dbox.max()[Y]) + y_to = dbox.max()[Y]; else - y_to = (*p)[NR::Y]; + y_to = p[Y]; - NR::Point const d_dt(x_to, y_to); - NR::Point const d_w( d_dt * _d2w ); - NR::Point const moved_w( d_w - s_w ); + Geom::Point const d_dt(x_to, y_to); + Geom::Point const d_w( d_dt * _d2w ); + Geom::Point const moved_w( d_w - s_w ); if (autoscrollspeed == 0) - autoscrollspeed = prefs_get_double_attribute_limited ("options.autoscrollspeed", "value", 1, 0, 10); + autoscrollspeed = prefs->getDoubleLimited("/options/autoscrollspeed/value", 1, 0, 10); if (autoscrollspeed != 0) scroll_world (autoscrollspeed * moved_w); @@ -1111,6 +1232,33 @@ SPDesktop::fullscreen() _widget->setFullscreen(); } +/** \brief Checks to see if the user is working in focused mode + + Returns the value of \c _focusMode +*/ +bool +SPDesktop::is_focusMode() +{ + return _focusMode; +} + +/** \brief Changes whether the user is in focus mode or not + \param mode Which mode the view should be in + +*/ +void +SPDesktop::focusMode (bool mode) +{ + if (mode == _focusMode) { return; } + + _focusMode = mode; + + layoutWidget(); + //sp_desktop_widget_layout(SPDesktopWidget); + + return; +} + void SPDesktop::getWindowGeometry (gint &x, gint &y, gint &w, gint &h) { @@ -1118,7 +1266,7 @@ SPDesktop::getWindowGeometry (gint &x, gint &y, gint &w, gint &h) } void -SPDesktop::setWindowPosition (NR::Point p) +SPDesktop::setWindowPosition (Geom::Point p) { _widget->setPosition (p); } @@ -1185,7 +1333,7 @@ SPDesktop::shutdown() bool SPDesktop::onDeleteUI (GdkEventAny*) { - if(shutdown()) + if(shutdown()) return true; destroyWidget(); @@ -1202,7 +1350,7 @@ bool SPDesktop::onDeleteUI (GdkEventAny*) bool SPDesktop::onWindowStateEvent (GdkEventWindowState* event) { - // Record the desktop window's state + // Record the desktop window's state window_state = event->new_window_state; // Layout may differ depending on full-screen mode or not @@ -1211,7 +1359,7 @@ SPDesktop::onWindowStateEvent (GdkEventWindowState* event) layoutWidget(); } - return false; + return false; } void @@ -1241,8 +1389,8 @@ SPDesktop::isToolboxButtonActive (gchar const *id) void SPDesktop::emitToolSubselectionChanged(gpointer data) { - _tool_subselection_changed.emit(data); - inkscape_subselection_changed (this); + _tool_subselection_changed.emit(data); + inkscape_subselection_changed (this); } void @@ -1267,14 +1415,9 @@ void SPDesktop::setWaitingCursor() GdkCursor *waiting = gdk_cursor_new(GDK_WATCH); gdk_window_set_cursor(GTK_WIDGET(sp_desktop_canvas(this))->window, waiting); gdk_cursor_unref(waiting); + // GDK needs the flush for the cursor change to take effect + gdk_flush(); waiting_cursor = true; - - // Stupidly broken GDK cannot just set the new cursor right now - it needs some main loop iterations for that - // Since setting waiting_cursor is usually immediately followed by some Real Work, we must run the iterations here - // CAUTION: iterations may redraw, and redraw may be interrupted, so you cannot assume that anything is the same - // after the call to setWaitingCursor as it was before - while( Gtk::Main::events_pending() ) - Gtk::Main::iteration(); } void SPDesktop::clearWaitingCursor() @@ -1313,9 +1456,9 @@ void SPDesktop::showGrids(bool show, bool dirty_document) } } -void SPDesktop::toggleSnapping() +void SPDesktop::toggleSnapGlobal() { - bool v = namedview->snap_manager.getSnapEnabledGlobally(); + bool v = namedview->snap_manager.snapprefs.getSnapEnabledGlobally(); Inkscape::XML::Node *repr = SP_OBJECT_REPR(namedview); sp_repr_set_boolean(repr, "inkscape:snap-global", !v); } @@ -1326,7 +1469,7 @@ void SPDesktop::toggleSnapping() void SPDesktop::onPositionSet (double x, double y) { - _widget->viewSetPosition (NR::Point(x,y)); + _widget->viewSetPosition (Geom::Point(x,y)); } void @@ -1397,7 +1540,6 @@ SPDesktop::setDocument (SPDocument *doc) SP_ITEM_SHOW_DISPLAY); if (ai) { nr_arena_item_add_child (SP_CANVAS_ARENA (drawing)->root, ai, NULL); - nr_arena_item_unref (ai); } namedview->show(this); /* Ugly hack */ @@ -1434,7 +1576,7 @@ SPDesktop::onDocumentResized (gdouble width, gdouble height) { _doc2dt[5] = height; sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (drawing), _doc2dt); - NR::Rect const a(NR::Point(0, 0), NR::Point(width, height)); + Geom::Rect const a(Geom::Point(0, 0), Geom::Point(width, height)); SP_CTRLRECT(page)->setRectangle(a); SP_CTRLRECT(page_border)->setRectangle(a); } @@ -1459,7 +1601,7 @@ SPDesktop::_onSelectionModified (Inkscape::Selection */*selection*/, guint /*flags*/, SPDesktop *dt) { if (!dt->_widget) return; - dt->_widget->updateScrollbars (expansion(dt->_d2w)); + dt->_widget->updateScrollbars (dt->_d2w.descrim()); } static void @@ -1564,12 +1706,6 @@ _namedview_modified (SPObject *obj, guint flags, SPDesktop *desktop) if (flags & SP_OBJECT_MODIFIED_FLAG) { - /* Recalculate snap distances */ - /* FIXME: why is the desktop getting involved in setting up something - ** that is entirely to do with the namedview? - */ - _update_snap_distances (desktop); - /* Show/hide page background */ if (nv->pagecolor & 0xff) { sp_canvas_item_show (desktop->table); @@ -1595,7 +1731,7 @@ _namedview_modified (SPObject *obj, guint flags, SPDesktop *desktop) int order = sp_canvas_item_order (desktop->page_border); int morder = sp_canvas_item_order (desktop->drawing); if (morder > order) sp_canvas_item_raise (desktop->page_border, - morder - order); + morder - order); } } else { sp_canvas_item_hide (desktop->page_border); @@ -1611,73 +1747,53 @@ _namedview_modified (SPObject *obj, guint flags, SPDesktop *desktop) ((CtrlRect *) desktop->page_border)->setShadow(0, 0x00000000); } + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (SP_RGBA32_A_U(nv->pagecolor) < 128 || (SP_RGBA32_R_U(nv->pagecolor) + SP_RGBA32_G_U(nv->pagecolor) + SP_RGBA32_B_U(nv->pagecolor)) >= 384) { // the background color is light or transparent, use black outline - SP_CANVAS_ARENA (desktop->drawing)->arena->outlinecolor = prefs_get_int_attribute("options.wireframecolors", "onlight", 0xff); + SP_CANVAS_ARENA (desktop->drawing)->arena->outlinecolor = prefs->getInt("/options/wireframecolors/onlight", 0xff); } else { // use white outline - SP_CANVAS_ARENA (desktop->drawing)->arena->outlinecolor = prefs_get_int_attribute("options.wireframecolors", "ondark", 0xffffffff); + SP_CANVAS_ARENA (desktop->drawing)->arena->outlinecolor = prefs->getInt("/options/wireframecolors/ondark", 0xffffffff); } } } -/** - * Callback to reset snapper's distances. - */ -static void -_update_snap_distances (SPDesktop *desktop) -{ - SPUnit const &px = sp_unit_get_by_id(SP_UNIT_PX); - - SPNamedView &nv = *desktop->namedview; - - //tell all grid snappers - for ( GSList const *l = nv.grids; l != NULL; l = l->next) { - Inkscape::CanvasGrid *grid = (Inkscape::CanvasGrid*) l->data; - grid->snapper->setSnapperTolerance(sp_convert_distance_full(nv.gridtolerance, - *nv.gridtoleranceunit, - px)); - } - - nv.snap_manager.guide.setSnapperTolerance(sp_convert_distance_full(nv.guidetolerance, - *nv.guidetoleranceunit, - px)); - nv.snap_manager.object.setSnapperTolerance(sp_convert_distance_full(nv.objecttolerance, - *nv.objecttoleranceunit, - px)); -} - - -NR::Matrix SPDesktop::w2d() const +Geom::Matrix SPDesktop::w2d() const { return _w2d; } -NR::Point SPDesktop::w2d(NR::Point const &p) const +Geom::Point SPDesktop::w2d(Geom::Point const &p) const { return p * _w2d; } -NR::Point SPDesktop::d2w(NR::Point const &p) const +Geom::Point SPDesktop::d2w(Geom::Point const &p) const { return p * _d2w; } -NR::Matrix SPDesktop::doc2dt() const +Geom::Matrix SPDesktop::doc2dt() const +{ + return _doc2dt; +} + +Geom::Matrix SPDesktop::dt2doc() const { + // doc2dt is its own inverse return _doc2dt; } -NR::Point SPDesktop::doc2dt(NR::Point const &p) const +Geom::Point SPDesktop::doc2dt(Geom::Point const &p) const { return p * _doc2dt; } -NR::Point SPDesktop::dt2doc(NR::Point const &p) const +Geom::Point SPDesktop::dt2doc(Geom::Point const &p) const { - return p / _doc2dt; + return p * dt2doc(); }