X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fdesktop.cpp;h=1953ae2a6e8db730bfff77ff61f52a8f398ba6dd;hb=62dad53172661dfa1ef8dd3ed07e06d2ea2523a4;hp=903a6bd7c90c46e3ea7980fc54b6d4e2f7f43b54;hpb=0f600b9add1b1d2f508a52959e809f0d216457cb;p=inkscape.git diff --git a/src/desktop.cpp b/src/desktop.cpp index 903a6bd7c..1953ae2a6 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -9,8 +9,10 @@ * bulia byak * Ralf Stephan * John Bintz + * Johan Engelen * - * Copyright (C) 2006 Johan Engelen + * Copyright (C) 2007 Jon A. Cruz + * Copyright (C) 2006-2008 Johan Engelen * Copyright (C) 2006 John Bintz * Copyright (C) 2004 MenTaLguY * Copyright (C) 1999-2002 Lauris Kaplinski @@ -53,7 +55,9 @@ #include #include +#include +#include <2geom/rect.h> #include "macros.h" #include "inkscape-private.h" #include "desktop.h" @@ -66,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" @@ -74,13 +78,24 @@ #include "display/gnome-canvas-acetate.h" #include "display/sodipodi-ctrlrect.h" #include "display/sp-canvas-util.h" -#include "libnr/nr-matrix-div.h" -#include "libnr/nr-rect-ops.h" +#include "display/canvas-temporary-item-list.h" +#include "display/snap-indicator.h" #include "ui/dialog/dialog-manager.h" #include "xml/repr.h" #include "message-context.h" +#include "device-manager.h" +#include "layer-fns.h" #include "layer-manager.h" #include "event-log.h" +#include "display/canvas-grid.h" +#include "widgets/desktop-widget.h" +#include "box3d-context.h" + +// TODO those includes are only for node tool quick zoom. Remove them after fixing it. +#include "ui/tool/node-tool.h" +#include "ui/tool/control-point-selection.h" + +#include "display/sp-canvas.h" namespace Inkscape { namespace XML { class Node; }} @@ -93,58 +108,77 @@ 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. * \pre namedview != NULL. * \pre canvas != NULL. */ -SPDesktop::SPDesktop() -{ - _dlg_mgr = NULL; - _widget = 0; - namedview = NULL; - selection = NULL; - acetate = NULL; - main = NULL; - grid = NULL; - guides = NULL; - drawing = NULL; - sketch = NULL; - controls = NULL; - event_context = 0; - layer_manager = 0; - - _d2w.set_identity(); - _w2d.set_identity(); - _doc2dt = NR::Matrix(NR::scale(1, -1)); - - guides_active = false; - - zooms_past = NULL; - zooms_future = NULL; - - is_fullscreen = false; - - gr_item = NULL; - gr_point_type = 0; - gr_point_i = 0; - gr_fill_or_stroke = true; - - _layer_hierarchy = NULL; - _active = false; - - selection = Inkscape::GC::release (new Inkscape::Selection (this)); +SPDesktop::SPDesktop() : + _dlg_mgr( 0 ), + namedview( 0 ), + canvas( 0 ), + selection( 0 ), + event_context( 0 ), + layer_manager( 0 ), + event_log( 0 ), + temporary_item_list( 0 ), + snapindicator( 0 ), + acetate( 0 ), + main( 0 ), + gridgroup( 0 ), + guides( 0 ), + drawing( 0 ), + sketch( 0 ), + controls( 0 ), + tempgroup ( 0 ), + table( 0 ), + page( 0 ), + page_border( 0 ), + current( 0 ), + _focusMode(false), + zooms_past( 0 ), + zooms_future( 0 ), + dkey( 0 ), + number( 0 ), + window_state(0), + interaction_disabled_counter( 0 ), + waiting_cursor( false ), + guides_active( false ), + gr_item( 0 ), + gr_point_type( 0 ), + gr_point_i( 0 ), + gr_fill_or_stroke( true ), + _layer_hierarchy( 0 ), + _reconstruction_old_layer_id( 0 ), + _display_mode(Inkscape::RENDERMODE_NORMAL), + _widget( 0 ), + _inkscape( 0 ), + _guides_message_context( 0 ), + _active( false ), + _w2d(), + _d2w(), + _doc2dt( Geom::identity() ), + grids_visible( false ) +{ + _d2w.setIdentity(); + _w2d.setIdentity(); + + selection = Inkscape::GC::release( new Inkscape::Selection(this) ); } void -SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) - +SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWidgetInterface *widget) { + _widget = widget; + + // 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; @@ -154,7 +188,7 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) sp_document_ensure_up_to_date (document); /* Setup Dialog Manager */ - _dlg_mgr = new Inkscape::UI::Dialog::DialogManager(); + _dlg_mgr = &Inkscape::UI::Dialog::DialogManager::getInstance(); dkey = sp_item_display_key_new (1); @@ -176,7 +210,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); @@ -187,9 +221,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 { @@ -197,9 +231,17 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) setDisplayModeNormal(); } - grid = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL); + // 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); + 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 */ @@ -208,12 +250,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); @@ -230,7 +272,6 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) /* Connect event for page resize */ - _doc2dt[5] = sp_document_height (document); sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (drawing), _doc2dt); _modified_connection = namedview->connectModified(sigc::bind<2>(sigc::ptr_fun(&_namedview_modified), this)); @@ -241,7 +282,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); @@ -257,9 +297,7 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) _reconstruction_finish_connection = document->connectReconstructionFinish(sigc::bind(sigc::ptr_fun(_reconstruction_finish), this)); _reconstruction_old_layer_id = NULL; - - _commit_connection = document->connectCommit(sigc::mem_fun(*this, &SPDesktop::updateNow)); - + // ? // sp_active_desktop_set (desktop); _inkscape = INKSCAPE; @@ -294,11 +332,32 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas) /* setup LayerManager */ // (Setting up after the connections are all in place, as it may use some of them) layer_manager = new Inkscape::LayerManager( this ); + + showGrids(namedview->grids_visible, false); + + temporary_item_list = new Inkscape::Display::TemporaryItemList( this ); + snapindicator = new Inkscape::Display::SnapIndicator ( this ); } void SPDesktop::destroy() { + if (snapindicator) { + delete snapindicator; + snapindicator = NULL; + } + if (temporary_item_list) { + delete temporary_item_list; + temporary_item_list = NULL; + } + + if (selection) { + delete selection; + selection = NULL; + } + + namedview->hide(this); + _activate_connection.disconnect(); _deactivate_connection.disconnect(); _sel_modified_connection.disconnect(); @@ -321,6 +380,12 @@ void SPDesktop::destroy() if (_layer_hierarchy) { delete _layer_hierarchy; +// _layer_hierarchy = NULL; //this should be here, but commented to find other bug somewhere else. + } + + if (layer_manager) { + delete layer_manager; + layer_manager = NULL; } if (_inkscape) { @@ -344,32 +409,64 @@ SPDesktop::~SPDesktop() {} //-------------------------------------------------------------------- /* Public methods */ -void SPDesktop::setDisplayModeNormal() + +/* 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 + * 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) { - prefs_set_int_attribute("options.outlinemode", "value", 0); - SP_CANVAS_ARENA (drawing)->arena->rendermode = RENDERMODE_NORMAL; - canvas->rendermode = RENDERMODE_NORMAL; // canvas needs that for choosing the best buffer size - displayMode = RENDERMODE_NORMAL; - sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (main), _d2w); // redraw - _widget->setTitle(SP_DOCUMENT_NAME(sp_desktop_document(this))); + if (move_to_bottom) { + sp_canvas_item_move_to_z(item, 0); + } + + return temporary_item_list->add_item(item, lifetime); } -void SPDesktop::setDisplayModeOutline() +/** It is perfectly safe to call this function while the object has already been deleted due to a timeout. +*/ +void +SPDesktop::remove_temporary_canvasitem (Inkscape::Display::TemporaryItem * tempitem) { - prefs_set_int_attribute("options.outlinemode", "value", 1); - SP_CANVAS_ARENA (drawing)->arena->rendermode = RENDERMODE_OUTLINE; - canvas->rendermode = RENDERMODE_OUTLINE; // canvas needs that for choosing the best buffer size - displayMode = RENDERMODE_OUTLINE; + // check for non-null temporary_item_list, because during destruction of desktop, some destructor might try to access this list! + if (tempitem && temporary_item_list) { + temporary_item_list->delete_item(tempitem); + } +} + +void SPDesktop::_setDisplayMode(Inkscape::RenderMode mode) { + SP_CANVAS_ARENA (drawing)->arena->rendermode = mode; + canvas->rendermode = mode; + _display_mode = mode; sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (main), _d2w); // redraw _widget->setTitle(SP_DOCUMENT_NAME(sp_desktop_document(this))); } -void SPDesktop::displayModeToggle() -{ - if (prefs_get_int_attribute("options.outlinemode", "value", prefs_get_int_attribute("options.startmode", "outline", 0))) - setDisplayModeNormal(); - else - setDisplayModeOutline(); +void SPDesktop::displayModeToggle() { + switch (_display_mode) { + case Inkscape::RENDERMODE_NORMAL: + _setDisplayMode(Inkscape::RENDERMODE_NO_FILTERS); + break; + case Inkscape::RENDERMODE_NO_FILTERS: + _setDisplayMode(Inkscape::RENDERMODE_OUTLINE); + break; + case Inkscape::RENDERMODE_OUTLINE: + _setDisplayMode(Inkscape::RENDERMODE_PRINT_COLORS_PREVIEW); + break; + case Inkscape::RENDERMODE_PRINT_COLORS_PREVIEW: + default: + _setDisplayMode(Inkscape::RENDERMODE_NORMAL); + } } /** @@ -390,7 +487,7 @@ SPObject *SPDesktop::currentLayer() const /** * Sets the current layer of the desktop. - * + * * Make \a object the top layer. */ void SPDesktop::setCurrentLayer(SPObject *object) { @@ -400,6 +497,31 @@ void SPDesktop::setCurrentLayer(SPObject *object) { _layer_hierarchy->setBottom(object); } +void SPDesktop::toggleLayerSolo(SPObject *object) { + g_return_if_fail(SP_IS_GROUP(object)); + g_return_if_fail( currentRoot() == object || (currentRoot() && currentRoot()->isAncestorOf(object)) ); + + bool othersShowing = false; + std::vector layers; + for ( SPObject* obj = Inkscape::next_layer(currentRoot(), object); obj; obj = Inkscape::next_layer(currentRoot(), obj) ) { + layers.push_back(obj); + othersShowing |= !SP_ITEM(obj)->isHidden(); + } + for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), object); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) { + layers.push_back(obj); + othersShowing |= !SP_ITEM(obj)->isHidden(); + } + + + if ( SP_ITEM(object)->isHidden() ) { + SP_ITEM(object)->setHidden(false); + } + + for ( std::vector::iterator it = layers.begin(); it != layers.end(); ++it ) { + SP_ITEM(*it)->setHidden(othersShowing); + } +} + /** * Return layer that contains \a object. */ @@ -428,9 +550,13 @@ bool SPDesktop::isLayer(SPObject *object) const { */ bool SPDesktop::isWithinViewport (SPItem *item) const { - NR::Rect const viewport = get_display_area(); - NR::Rect const bbox = sp_item_bbox_desktop(item); - return viewport.contains(bbox); + Geom::Rect const viewport = get_display_area(); + Geom::OptRect const bbox = sp_item_bbox_desktop(item); + if (bbox) { + return viewport.contains(*bbox); + } else { + return true; + } } /// @@ -476,6 +602,17 @@ SPDesktop::change_document (SPDocument *theDocument) selection->clear(); setDocument (theDocument); + + /* update the rulers, connect the desktop widget's signal to the new namedview etc. + (this can probably be done in a better way) */ + Gtk::Window *parent = this->getToplevel(); + g_assert(parent != NULL); + SPDesktopWidget *dtw = (SPDesktopWidget *) parent->get_data("desktopwidget"); + if (dtw) { + dtw->desktop = this; + } + dtw->updateNamedview(); + _namedview_modified (namedview, SP_OBJECT_MODIFIED_FLAG, this); _document_replaced_signal.emit (this, theDocument); } @@ -490,13 +627,15 @@ SPDesktop::set_event_context (GtkType type, const gchar *config) while (event_context) { ec = event_context; sp_event_context_deactivate (ec); - event_context = ec->next; + // we have to keep event_context valid during destruction - otherwise writing + // destructors is next to impossible + SPEventContext *next = ec->next; sp_event_context_finish (ec); g_object_unref (G_OBJECT (ec)); + event_context = next; } - 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); @@ -510,7 +649,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; @@ -523,8 +661,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); @@ -535,7 +672,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); } @@ -543,7 +680,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); @@ -553,7 +690,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); @@ -563,7 +700,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); @@ -573,22 +710,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 { @@ -602,13 +739,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 ) && @@ -620,7 +757,7 @@ SPDesktop::push_current_zoom (GList **history) } /** - * Set viewbox. + * Set viewbox (x0, x1, y0 and y1 are in document pixels. Border is in screen pixels). */ void SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double border, bool log) @@ -638,55 +775,60 @@ 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); + newscale = CLAMP(newscale, SP_DESKTOP_ZOOM_MIN, SP_DESKTOP_ZOOM_MAX); // unit: 'screen pixels' per 'document pixels' 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)); + // zoom changed - set new zoom factors + _d2w = Geom::Scale(newscale); + _w2d = Geom::Scale(1/newscale); sp_canvas_item_affine_absolute(SP_CANVAS_ITEM(main), _d2w); clear = TRUE; + signal_zoom_changed.emit(_d2w.descrim()); } - /* Calculate top left corner */ - x0 = cx - 0.5 * viewbox.dimensions()[NR::X] / newscale; - y1 = cy + 0.5 * viewbox.dimensions()[NR::Y] / newscale; + /* Calculate top left corner (in document pixels) */ + x0 = cx - 0.5 * viewbox.dimensions()[Geom::X] / newscale; + y0 = cy - 0.5 * viewbox.dimensions()[Geom::Y] / newscale; /* Scroll */ - sp_canvas_scroll_to (canvas, x0 * newscale - border, y1 * -newscale - border, clear); + sp_canvas_scroll_to (canvas, x0 * newscale - border, y0 * newscale - border, clear); + + /* 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()); _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 viewbox * (1./scale); } /** @@ -739,6 +881,57 @@ SPDesktop::next_zoom() zooms_future = g_list_remove (zooms_future, ((NRRect *) zooms_future->data)); } +/** \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; + + // TODO This needs to migrate into the node tool, but currently the design + // of this method is sufficiently wrong to prevent this. + if (!zoomed && INK_IS_NODE_TOOL(event_context)) { + InkNodeTool *nt = static_cast(event_context); + if (!nt->_selected_nodes->empty()) { + Geom::Rect nodes = *nt->_selected_nodes->bounds(); + double area = nodes.area(); + // do not zoom if a single cusp node is selected aand the bounds + // have zero area. + if (!Geom::are_near(area, 0) && area * 2.0 < _quick_zoom_stored_area.area()) { + set_display_area(nodes, true); + 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, true); + 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, false); + } + + _quick_zoom_enabled = enable; + return; +} + /** * Zoom to point with absolute zoom factor. */ @@ -750,13 +943,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, @@ -780,24 +973,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); } @@ -808,7 +1001,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); } @@ -818,10 +1011,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.dimensions()[NR::X] < 1.0 || d.dimensions()[NR::Y] < 1.0) { + if (d.minExtent() < 1.0) { return; } @@ -834,14 +1027,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); } @@ -852,13 +1045,13 @@ SPDesktop::zoom_page_width() void SPDesktop::zoom_selection() { - NR::Rect const d = selection->bounds(); + Geom::OptRect const d = selection->bounds(); - if (d.dimensions()[NR::X] < 0.1 || d.dimensions()[NR::Y] < 0.1) { + if ( !d || d->minExtent() < 0.1 ) { return; } - set_display_area(d, 10); + set_display_area(*d, 10); } /** @@ -880,70 +1073,89 @@ SPDesktop::zoom_drawing() SPItem *docitem = SP_ITEM (sp_document_root (doc())); g_return_if_fail (docitem != NULL); - NR::Rect 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.dimensions()[NR::X] < 1.0 || d.dimensions()[NR::Y] < 1.0 ) { + if ( !d || d->minExtent() < 0.1 ) { return; } - set_display_area(d, 10); + set_display_area(*d, 10); +} + +/** + * Scroll canvas by specific coordinate amount in svg coordinates. + */ +void +SPDesktop::scroll_world_in_svg_coords (double dx, double dy, bool is_scrolling) +{ + double scale = _d2w.descrim(); + scroll_world(dx*scale, dy*scale, is_scrolling); } /** * Scroll canvas by specific coordinate amount. */ void -SPDesktop::scroll_world (double dx, double dy) +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); + 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); @@ -953,12 +1165,69 @@ SPDesktop::scroll_to_point (NR::Point const *p, gdouble autoscrollspeed) return false; } +bool +SPDesktop::is_iconified() +{ + return 0!=(window_state & GDK_WINDOW_STATE_ICONIFIED); +} + +void +SPDesktop::iconify() +{ + _widget->setIconified(); +} + +bool +SPDesktop::is_maximized() +{ + return 0!=(window_state & GDK_WINDOW_STATE_MAXIMIZED); +} + +void +SPDesktop::maximize() +{ + _widget->setMaximized(); +} + +bool +SPDesktop::is_fullscreen() +{ + return 0!=(window_state & GDK_WINDOW_STATE_FULLSCREEN); +} + void 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) { @@ -966,7 +1235,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); } @@ -983,6 +1252,12 @@ SPDesktop::setWindowTransient (void *p, int transient_policy) _widget->setTransient (p, transient_policy); } +Gtk::Window* +SPDesktop::getToplevel( ) +{ + return _widget->getWindow(); +} + void SPDesktop::presentWindow() { @@ -1025,6 +1300,37 @@ SPDesktop::shutdown() return _widget->shutdown(); } +bool SPDesktop::onDeleteUI (GdkEventAny*) +{ + if(shutdown()) + return true; + + destroyWidget(); + return false; +} + +/** + * onWindowStateEvent + * + * Called when the window changes its maximize/fullscreen/iconify/pinned state. + * Since GTK doesn't have a way to query this state information directly, we + * record it for the desktop here, and also possibly trigger a layout. + */ +bool +SPDesktop::onWindowStateEvent (GdkEventWindowState* event) +{ + // Record the desktop window's state + window_state = event->new_window_state; + + // Layout may differ depending on full-screen mode or not + GdkWindowState changed = event->changed_mask; + if (changed & (GDK_WINDOW_STATE_FULLSCREEN|GDK_WINDOW_STATE_MAXIMIZED)) { + layoutWidget(); + } + + return false; +} + void SPDesktop::setToolboxFocusTo (gchar const *label) { @@ -1037,6 +1343,12 @@ SPDesktop::setToolboxAdjustmentValue (gchar const* id, double val) _widget->setToolboxAdjustmentValue (id, val); } +void +SPDesktop::setToolboxSelectOneValue (gchar const* id, gint val) +{ + _widget->setToolboxSelectOneValue (id, val); +} + bool SPDesktop::isToolboxButtonActive (gchar const *id) { @@ -1046,8 +1358,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 @@ -1067,17 +1379,70 @@ void SPDesktop::disableInteraction() _widget->disableInteraction(); } +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; +} + +void SPDesktop::clearWaitingCursor() +{ + if (waiting_cursor) + sp_event_context_update_cursor(sp_desktop_event_context(this)); +} + +void SPDesktop::toggleColorProfAdjust() +{ + _widget->toggleColorProfAdjust(); +} + +void SPDesktop::toggleGrids() +{ + if (namedview->grids) { + if(gridgroup) { + showGrids(!grids_visible); + } + } else { + //there is no grid present at the moment. add a rectangular grid and make it visible + Inkscape::XML::Node *repr = SP_OBJECT_REPR(namedview); + Inkscape::CanvasGrid::writeNewGridToRepr(repr, sp_desktop_document(this), Inkscape::GRID_RECTANGULAR); + showGrids(true); + } +} + +void SPDesktop::showGrids(bool show, bool dirty_document) +{ + grids_visible = show; + sp_namedview_show_grids(namedview, grids_visible, dirty_document); + if (show) { + sp_canvas_item_show(SP_CANVAS_ITEM(gridgroup)); + } else { + sp_canvas_item_hide(SP_CANVAS_ITEM(gridgroup)); + } +} + +void SPDesktop::toggleSnapGlobal() +{ + bool v = namedview->snap_manager.snapprefs.getSnapEnabledGlobally(); + Inkscape::XML::Node *repr = SP_OBJECT_REPR(namedview); + sp_repr_set_boolean(repr, "inkscape:snap-global", !v); +} + //---------------------------------------------------------------------- // Callback implementations. The virtual ones are connected by the view. void SPDesktop::onPositionSet (double x, double y) { - _widget->viewSetPosition (NR::Point(x,y)); + _widget->viewSetPosition (Geom::Point(x,y)); } void -SPDesktop::onResized (double x, double y) +SPDesktop::onResized (double /*x*/, double /*y*/) { // Nothing called here } @@ -1102,7 +1467,6 @@ SPDesktop::updateCanvasNow() /** * Associate document with desktop. */ -/// \todo fixme: refactor SPDesktop::init to use setDocument void SPDesktop::setDocument (SPDocument *doc) { @@ -1129,10 +1493,11 @@ SPDesktop::setDocument (SPDocument *doc) _commit_connection = doc->connectCommit(sigc::mem_fun(*this, &SPDesktop::updateNow)); /// \todo fixme: This condition exists to make sure the code - /// inside is called only once on initialization. But there + /// inside is NOT called on initialization, only on replacement. But there /// are surely more safe methods to accomplish this. + // TODO since the comment had reversed logic, check the intent of this block of code: if (drawing) { - NRArenaItem *ai; + NRArenaItem *ai = 0; namedview = sp_document_namedview (doc, NULL); _modified_connection = namedview->connectModified(sigc::bind<2>(sigc::ptr_fun(&_namedview_modified), this)); @@ -1144,7 +1509,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 */ @@ -1179,9 +1543,8 @@ SPDesktop::onDocumentURISet (gchar const* uri) void 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); } @@ -1203,10 +1566,10 @@ SPDesktop::_onDeactivate (SPDesktop* dt) void SPDesktop::_onSelectionModified -(Inkscape::Selection *selection, guint flags, SPDesktop *dt) +(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 @@ -1233,7 +1596,7 @@ _onSelectionChanged * \todo fixme */ static gint -_arena_handler (SPCanvasArena *arena, NRArenaItem *ai, GdkEvent *event, SPDesktop *desktop) +_arena_handler (SPCanvasArena */*arena*/, NRArenaItem *ai, GdkEvent *event, SPDesktop *desktop) { if (ai) { SPItem *spi = (SPItem*)NR_ARENA_ITEM_GET_DATA (ai); @@ -1258,7 +1621,7 @@ _layer_deactivated(SPObject *layer, SPDesktop *desktop) { /// Callback static void -_layer_hierarchy_changed(SPObject *top, SPObject *bottom, +_layer_hierarchy_changed(SPObject */*top*/, SPObject *bottom, SPDesktop *desktop) { desktop->_layer_changed_signal.emit (bottom); @@ -1269,7 +1632,7 @@ static void _reconstruction_start (SPDesktop * desktop) { // printf("Desktop, starting reconstruction\n"); - desktop->_reconstruction_old_layer_id = g_strdup(SP_OBJECT_ID(desktop->currentLayer())); + desktop->_reconstruction_old_layer_id = g_strdup(desktop->currentLayer()->getId()); desktop->_layer_hierarchy->setBottom(desktop->currentRoot()); /* @@ -1311,12 +1674,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); @@ -1342,7 +1699,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); @@ -1350,7 +1707,7 @@ _namedview_modified (SPObject *obj, guint flags, SPDesktop *desktop) ((CtrlRect *) desktop->page)->setShadow(0, 0x00000000); } } - + /* Show/hide page shadow */ if (nv->showpageshadow && nv->pageshadow) { ((CtrlRect *) desktop->page_border)->setShadow(nv->pageshadow, nv->bordercolor); @@ -1358,75 +1715,57 @@ _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; - - nv.snap_manager.grid.setDistance(sp_convert_distance_full(nv.gridtolerance, - *nv.gridtoleranceunit, - px)); - nv.snap_manager.axonomgrid.setDistance(sp_convert_distance_full(nv.gridtolerance, - *nv.gridtoleranceunit, - px)); - nv.snap_manager.guide.setDistance(sp_convert_distance_full(nv.guidetolerance, - *nv.guidetoleranceunit, - px)); - nv.snap_manager.object.setDistance(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; } -NR::Point SPDesktop::doc2dt(NR::Point const &p) const +Geom::Matrix SPDesktop::dt2doc() const +{ + // doc2dt is its own inverse + return _doc2dt; +} + +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(); } -/** +/* * Pop event context from desktop's context stack. Never used. */ // void @@ -1468,4 +1807,4 @@ NR::Point SPDesktop::dt2doc(NR::Point const &p) const fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :