desktop.cpp revision acf6a9462fe97ec8c19cc905d164b1b437cb0b05
69879b63ae4fb3da90263808c133a39ed2b770f8glimmer * Editable view implementation
69879b63ae4fb3da90263808c133a39ed2b770f8glimmer * Lauris Kaplinski <lauris@kaplinski.com>
69879b63ae4fb3da90263808c133a39ed2b770f8glimmer * MenTaLguY <mental@rydia.net>
69879b63ae4fb3da90263808c133a39ed2b770f8glimmer * bulia byak <buliabyak@users.sf.net>
69879b63ae4fb3da90263808c133a39ed2b770f8glimmer * Ralf Stephan <ralf@ark.in-berlin.de>
69879b63ae4fb3da90263808c133a39ed2b770f8glimmer * John Bintz <jcoswell@coswellproductions.org>
69879b63ae4fb3da90263808c133a39ed2b770f8glimmer * Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
69879b63ae4fb3da90263808c133a39ed2b770f8glimmer * Copyright (C) 2006-2007 Johan Engelen
69879b63ae4fb3da90263808c133a39ed2b770f8glimmer * Copyright (C) 2006 John Bintz
69879b63ae4fb3da90263808c133a39ed2b770f8glimmer * Copyright (C) 2004 MenTaLguY
69879b63ae4fb3da90263808c133a39ed2b770f8glimmer * Copyright (C) 1999-2002 Lauris Kaplinski
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * Copyright (C) 2000-2001 Ximian, Inc.
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * Released under GNU GPL, read the file 'COPYING' for more information
c596be6d145df956e779f427dde5aabc8559dd6cglimmer/** \class SPDesktop
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * SPDesktop is a subclass of View, implementing an editable document
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * canvas. It is extensively used by many UI controls that need certain
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * visual representations of their own.
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * SPDesktop provides a certain set of SPCanvasItems, serving as GUI
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * layers of different control objects. The one containing the whole
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * document is the drawing layer. In addition to it, there are grid,
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * guide, sketch and control layers. The sketch layer is used for
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * temporary drawing objects, before the real objects in document are
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * created. The control layer contains editing knots, rubberband and
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * similar non-document UI objects.
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * Each SPDesktop is associated with a SPNamedView node of the document
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * tree. Currently, all desktops are created from a single main named
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * view, but in the future there may be support for different ones.
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * SPNamedView serves as an in-document container for desktop-related
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * data, like grid and guideline placement, snapping options and so on.
44a3b5d410b95b87a0c29ff7a0c9378e32c4fd38Eric Greveson * Associated with each SPDesktop are the two most important editing
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * related objects - SPSelection and SPEventContext.
40a3d45f2bcf7de02729811b4059e07abda134eaJohn Smith * Sodipodi keeps track of the active desktop and invokes notification
40a3d45f2bcf7de02729811b4059e07abda134eaJohn Smith * signals whenever it changes. UI elements can use these to update their
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * display to the selection of the currently active editing window.
c596be6d145df956e779f427dde5aabc8559dd6cglimmer * (Lauris Kaplinski)
40a3d45f2bcf7de02729811b4059e07abda134eaJohn Smithnamespace Inkscape { namespace XML { class Node; }}
40a3d45f2bcf7de02729811b4059e07abda134eaJohn Smith// Callback declarations
40a3d45f2bcf7de02729811b4059e07abda134eaJohn Smithstatic void _onSelectionChanged (Inkscape::Selection *selection, SPDesktop *desktop);
40a3d45f2bcf7de02729811b4059e07abda134eaJohn Smithstatic gint _arena_handler (SPCanvasArena *arena, NRArenaItem *ai, GdkEvent *event, SPDesktop *desktop);
40a3d45f2bcf7de02729811b4059e07abda134eaJohn Smithstatic void _layer_activated(SPObject *layer, SPDesktop *desktop);
40a3d45f2bcf7de02729811b4059e07abda134eaJohn Smithstatic void _layer_deactivated(SPObject *layer, SPDesktop *desktop);
40a3d45f2bcf7de02729811b4059e07abda134eaJohn Smithstatic void _layer_hierarchy_changed(SPObject *top, SPObject *bottom, SPDesktop *desktop);
40a3d45f2bcf7de02729811b4059e07abda134eaJohn Smithstatic void _reconstruction_start(SPDesktop * desktop);
40a3d45f2bcf7de02729811b4059e07abda134eaJohn Smithstatic void _reconstruction_finish(SPDesktop * desktop);
40a3d45f2bcf7de02729811b4059e07abda134eaJohn Smithstatic void _namedview_modified (SPObject *obj, guint flags, SPDesktop *desktop);
40a3d45f2bcf7de02729811b4059e07abda134eaJohn Smithstatic void _update_snap_distances (SPDesktop *desktop);
40a3d45f2bcf7de02729811b4059e07abda134eaJohn Smith * Return new desktop object.
40a3d45f2bcf7de02729811b4059e07abda134eaJohn Smith * \pre namedview != NULL.
40a3d45f2bcf7de02729811b4059e07abda134eaJohn Smith * \pre canvas != NULL.
c596be6d145df956e779f427dde5aabc8559dd6cglimmer selection = Inkscape::GC::release (new Inkscape::Selection (this));
c596be6d145df956e779f427dde5aabc8559dd6cglimmer _guides_message_context = new Inkscape::MessageContext(const_cast<Inkscape::MessageStack*>(messageStack()));
c596be6d145df956e779f427dde5aabc8559dd6cglimmer current = sp_repr_css_attr_inherited (inkscape_get_repr (INKSCAPE, "desktop"), "style");
c596be6d145df956e779f427dde5aabc8559dd6cglimmer SPDocument *document = SP_OBJECT_DOCUMENT (namedview);
f2614fa5142149207082d04e9b039c4520fa0856Eric Greveson /* Kill flicker */
c596be6d145df956e779f427dde5aabc8559dd6cglimmer /* Setup Dialog Manager */
c596be6d145df956e779f427dde5aabc8559dd6cglimmer _dlg_mgr = new Inkscape::UI::Dialog::DialogManager();
44a3b5d410b95b87a0c29ff7a0c9378e32c4fd38Eric Greveson /* Connect document */
c596be6d145df956e779f427dde5aabc8559dd6cglimmer /* Setup Canvas */
f2614fa5142149207082d04e9b039c4520fa0856Eric Greveson g_object_set_data (G_OBJECT (canvas), "SPDesktop", this);
f2614fa5142149207082d04e9b039c4520fa0856Eric Greveson SPCanvasGroup *root = sp_canvas_root (canvas);
9090603e08f72da58468db0e5b91f43ede35af26Eric Greveson /* Setup adminstrative layers */
9090603e08f72da58468db0e5b91f43ede35af26Eric Greveson acetate = sp_canvas_item_new (root, GNOME_TYPE_CANVAS_ACETATE, NULL);
9090603e08f72da58468db0e5b91f43ede35af26Eric Greveson g_signal_connect (G_OBJECT (acetate), "event", G_CALLBACK (sp_desktop_root_handler), this);
9090603e08f72da58468db0e5b91f43ede35af26Eric Greveson main = (SPCanvasGroup *) sp_canvas_item_new (root, SP_TYPE_CANVAS_GROUP, NULL);
9090603e08f72da58468db0e5b91f43ede35af26Eric Greveson g_signal_connect (G_OBJECT (main), "event", G_CALLBACK (sp_desktop_root_handler), this);
f2614fa5142149207082d04e9b039c4520fa0856Eric Greveson table = sp_canvas_item_new (main, SP_TYPE_CTRLRECT, NULL);
c596be6d145df956e779f427dde5aabc8559dd6cglimmer SP_CTRLRECT(table)->setRectangle(NR::Rect(NR::Point(-80000, -80000), NR::Point(80000, 80000)));
44a3b5d410b95b87a0c29ff7a0c9378e32c4fd38Eric Greveson SP_CTRLRECT(table)->setColor(0x00000000, true, 0x00000000);
c596be6d145df956e779f427dde5aabc8559dd6cglimmer page = sp_canvas_item_new (main, SP_TYPE_CTRLRECT, NULL);
c596be6d145df956e779f427dde5aabc8559dd6cglimmer ((CtrlRect *) page)->setColor(0x00000000, FALSE, 0x00000000);
c596be6d145df956e779f427dde5aabc8559dd6cglimmer page_border = sp_canvas_item_new (main, SP_TYPE_CTRLRECT, NULL);
c596be6d145df956e779f427dde5aabc8559dd6cglimmer drawing = sp_canvas_item_new (main, SP_TYPE_CANVAS_ARENA, NULL);
c596be6d145df956e779f427dde5aabc8559dd6cglimmer g_signal_connect (G_OBJECT (drawing), "arena_event", G_CALLBACK (_arena_handler), this);
c596be6d145df956e779f427dde5aabc8559dd6cglimmer SP_CANVAS_ARENA (drawing)->arena->delta = prefs_get_double_attribute ("options.cursortolerance", "value", 1.0); // default is 1 px
c596be6d145df956e779f427dde5aabc8559dd6cglimmer if (prefs_get_int_attribute("options.startmode", "outline", 0)) {
c596be6d145df956e779f427dde5aabc8559dd6cglimmer // Start in outline mode
9ba77856a8823f85b53c0a861d220cd0347f2754Liam P. White // Start in normal mode, default
c596be6d145df956e779f427dde5aabc8559dd6cglimmer grid = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL);
c596be6d145df956e779f427dde5aabc8559dd6cglimmer guides = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL);
c596be6d145df956e779f427dde5aabc8559dd6cglimmer sketch = (SPCanvasGroup *) sp_canvas_item_new (main, SP_TYPE_CANVAS_GROUP, NULL);
_modified_connection = namedview->connectModified(sigc::bind<2>(sigc::ptr_fun(&_namedview_modified), this));
dkey,
if (ai) {
activate_guides (true);
g_signal_handlers_disconnect_by_func(G_OBJECT (acetate), (gpointer) G_CALLBACK(sp_desktop_root_handler), this);
g_signal_handlers_disconnect_by_func(G_OBJECT (main), (gpointer) G_CALLBACK(sp_desktop_root_handler), this);
g_signal_handlers_disconnect_by_func(G_OBJECT (drawing), (gpointer) G_CALLBACK(_arena_handler), this);
while (event_context) {
if (_layer_hierarchy) {
delete _layer_hierarchy;
if (_inkscape) {
if (drawing) {
delete _guides_message_context;
g_return_if_fail( currentRoot() == object || (currentRoot() && currentRoot()->isAncestorOf(object)) );
return object;
if (bbox) {
if (new_active) {
while (event_context) {
SPItem *
SPItem *
SPItem *
if (log) {
double newscale;
if (fabs(expansion(_d2w) - zoom) < 0.0001*zoom && (fabs(SP_DESKTOP_ZOOM_MAX - zoom) < 0.01 || fabs(SP_DESKTOP_ZOOM_MIN - zoom) < 0.000001))
sp_canvas_scroll_to(canvas, viewbox.min()[NR::X] - dx, viewbox.min()[NR::Y] - dy, FALSE, is_scrolling);
gdouble autoscrolldistance = (gdouble) prefs_get_int_attribute_limited ("options.autoscrolldistance", "value", 0, -1000, 10000);
if (autoscrollspeed == 0)
autoscrollspeed = prefs_get_double_attribute_limited ("options.autoscrollspeed", "value", 1, 0, 10);
if (autoscrollspeed != 0)
inkscape_subselection_changed (this);
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
if (main) {
if (_layer_hierarchy) {
delete _layer_hierarchy;
if (drawing) {
_modified_connection = namedview->connectModified(sigc::bind<2>(sigc::ptr_fun(&_namedview_modified), this));
dkey,
if (ai) {
activate_guides (true);
if (_widget) {
if (item) {
static gint
if (ai) {
SPObject * newLayer = SP_OBJECT_DOCUMENT(desktop->namedview)->getObjectById(desktop->_reconstruction_old_layer_id);
SP_CANVAS_ARENA (desktop->drawing)->arena->outlinecolor = prefs_get_int_attribute("options.wireframecolors", "onlight", 0xff);
SP_CANVAS_ARENA (desktop->drawing)->arena->outlinecolor = prefs_get_int_attribute("options.wireframecolors", "ondark", 0xffffffff);
px));
px));
px));
px));
return _w2d;
return p * _w2d;
return p * _d2w;
return _doc2dt;
return p * _doc2dt;
return p / _doc2dt;