Code

Split SPCanvasItem and SPCanvasGroup to individual .h files. Removed forward header.
[inkscape.git] / src / desktop.cpp
index 0e4d4caf3d1f4b7904a47c7196bf73f179794294..bfde0ee9239314b859659f94579c7ab655dae924 100644 (file)
@@ -1,5 +1,3 @@
-#define __SP_DESKTOP_C__
-
 /** \file
  * Editable view implementation
  *
@@ -10,6 +8,8 @@
  *   Ralf Stephan <ralf@ark.in-berlin.de>
  *   John Bintz <jcoswell@coswellproductions.org>
  *   Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
+ *   Jon A. Cruz <jon@joncruz.org>
+ *   Abhishek Sharma
  *
  * Copyright (C) 2007 Jon A. Cruz
  * Copyright (C) 2006-2008 Johan Engelen
@@ -80,6 +80,7 @@
 #include "display/sp-canvas-util.h"
 #include "display/canvas-temporary-item-list.h"
 #include "display/snap-indicator.h"
+#include "display/sp-canvas-group.h"
 #include "ui/dialog/dialog-manager.h"
 #include "xml/repr.h"
 #include "message-context.h"
 #include "display/canvas-grid.h"
 #include "widgets/desktop-widget.h"
 #include "box3d-context.h"
+#include "desktop-style.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"
 
@@ -181,12 +187,12 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWid
 
     SPDocument *document = SP_OBJECT_DOCUMENT (namedview);
     /* Kill flicker */
-    sp_document_ensure_up_to_date (document);
+    document->ensureUpToDate();
 
     /* Setup Dialog Manager */
     _dlg_mgr = &Inkscape::UI::Dialog::DialogManager::getInstance();
 
-    dkey = sp_item_display_key_new (1);
+    dkey = SPItem::display_key_new(1);
 
     /* Connect document */
     setDocument (document);
@@ -251,7 +257,7 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWid
     // display rect and zoom are now handled in sp_desktop_widget_realize()
 
     Geom::Rect const d(Geom::Point(0.0, 0.0),
-                       Geom::Point(sp_document_width(document), sp_document_height(document)));
+                       Geom::Point(document->getWidth(), document->getHeight()));
 
     SP_CTRLRECT(page)->setRectangle(d);
     SP_CTRLRECT(page_border)->setRectangle(d);
@@ -268,12 +274,12 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWid
 
 
     /* Connect event for page resize */
-    _doc2dt[5] = sp_document_height (document);
+    _doc2dt[5] = document->getHeight();
     sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (drawing), _doc2dt);
 
     _modified_connection = namedview->connectModified(sigc::bind<2>(sigc::ptr_fun(&_namedview_modified), this));
 
-    NRArenaItem *ai = sp_item_invoke_show (SP_ITEM (sp_document_root (document)),
+    NRArenaItem *ai = SP_ITEM(document->getRoot())->invoke_show(
             SP_CANVAS_ARENA (drawing)->arena,
             dkey,
             SP_ITEM_SHOW_DISPLAY);
@@ -390,7 +396,7 @@ void SPDesktop::destroy()
     }
 
     if (drawing) {
-        sp_item_invoke_hide (SP_ITEM (sp_document_root (doc())), dkey);
+        SP_ITEM(doc()->getRoot())->invoke_hide(dkey);
         drawing = NULL;
     }
 
@@ -446,7 +452,7 @@ void SPDesktop::_setDisplayMode(Inkscape::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)));
+    _widget->setTitle( sp_desktop_document(this)->getName() );
 }
 
 void SPDesktop::displayModeToggle() {
@@ -458,9 +464,9 @@ void SPDesktop::displayModeToggle() {
         _setDisplayMode(Inkscape::RENDERMODE_OUTLINE);
         break;
     case Inkscape::RENDERMODE_OUTLINE:
-        _setDisplayMode(Inkscape::RENDERMODE_PRINT_COLORS_PREVIEW);
+        _setDisplayMode(Inkscape::RENDERMODE_NORMAL);
         break;
-    case Inkscape::RENDERMODE_PRINT_COLORS_PREVIEW:
+//    case Inkscape::RENDERMODE_PRINT_COLORS_PREVIEW:
     default:
         _setDisplayMode(Inkscape::RENDERMODE_NORMAL);
     }
@@ -490,7 +496,7 @@ SPObject *SPDesktop::currentLayer() const
 void SPDesktop::setCurrentLayer(SPObject *object) {
     g_return_if_fail(SP_IS_GROUP(object));
     g_return_if_fail( currentRoot() == object || (currentRoot() && currentRoot()->isAncestorOf(object)) );
-    // printf("Set Layer to ID: %s\n", SP_OBJECT_ID(object));
+    // printf("Set Layer to ID: %s\n", object->getId());
     _layer_hierarchy->setBottom(object);
 }
 
@@ -548,7 +554,7 @@ bool SPDesktop::isLayer(SPObject *object) const {
 bool SPDesktop::isWithinViewport (SPItem *item) const
 {
     Geom::Rect const viewport = get_display_area();
-    Geom::OptRect const bbox = sp_item_bbox_desktop(item);
+    Geom::OptRect const bbox = item->getBboxDesktop();
     if (bbox) {
         return viewport.contains(*bbox);
     } else {
@@ -605,8 +611,10 @@ SPDesktop::change_document (SPDocument *theDocument)
     Gtk::Window *parent = this->getToplevel();
     g_assert(parent != NULL);
     SPDesktopWidget *dtw = (SPDesktopWidget *) parent->get_data("desktopwidget");
-    if (dtw) dtw->desktop = this;
-    sp_desktop_widget_update_namedview(dtw);
+    if (dtw) {
+        dtw->desktop = this;
+    }
+    dtw->updateNamedview();
 
     _namedview_modified (namedview, SP_OBJECT_MODIFIED_FLAG, this);
     _document_replaced_signal.emit (this, theDocument);
@@ -622,14 +630,23 @@ 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;
     }
 
+    // The event_context will be null. This means that it will be impossible
+    // to process any event invoked by the lines below. See for example bug
+    // LP #622350. Cutting and undoing again in the node tool resets the event
+    // context to the node tool. In this bug the line bellow invokes GDK_LEAVE_NOTIFY
+    // events which cannot be handled and must be discarded.
     ec = sp_event_context_new (type, this, config, SP_EVENT_CONTEXT_STATIC);
     ec->next = event_context;
     event_context = ec;
+    // Now the event_context has been set again and we can process all events again
     sp_event_context_activate (ec);
     _event_context_changed_signal.emit (this, ec);
 }
@@ -669,33 +686,30 @@ SPDesktop::set_coordinate_status (Geom::Point p) {
 }
 
 /**
- * \see sp_document_item_from_list_at_point_bottom()
+ * \see SPDocument::getItemFromListAtPointBottom()
  */
-SPItem *
-SPDesktop::item_from_list_at_point_bottom (const GSList *list, Geom::Point const p) const
+SPItem *SPDesktop::getItemFromListAtPointBottom(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);
+    return SPDocument::getItemFromListAtPointBottom(dkey, SP_GROUP (doc()->root), list, p);
 }
 
 /**
- * \see sp_document_item_at_point()
+ * \see SPDocument::getItemAtPoint()
  */
-SPItem *
-SPDesktop::item_at_point (Geom::Point const p, bool into_groups, SPItem *upto) const
+SPItem *SPDesktop::getItemAtPoint(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);
+    return doc()->getItemAtPoint( dkey, p, into_groups, upto);
 }
 
 /**
- * \see sp_document_group_at_point()
+ * \see SPDocument::getGroupAtPoint()
  */
-SPItem *
-SPDesktop::group_at_point (Geom::Point const p) const
+SPItem *SPDesktop::getGroupAtPoint(Geom::Point const p) const
 {
     g_return_val_if_fail (doc() != NULL, NULL);
-    return sp_document_group_at_point (doc(), dkey, p);
+    return doc()->getGroupAtPoint(dkey, p);
 }
 
 /**
@@ -783,11 +797,12 @@ 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 */
+        // zoom changed - set new zoom factors
         _d2w = Geom::Scale(newscale, -newscale);
         _w2d = Geom::Scale(1/newscale, 1/-newscale);
         sp_canvas_item_affine_absolute(SP_CANVAS_ITEM(main), _d2w);
         clear = TRUE;
+        signal_zoom_changed.emit(_d2w.descrim());
     }
 
     /* Calculate top left corner (in document pixels) */
@@ -873,11 +888,6 @@ 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
 
@@ -893,67 +903,26 @@ SPDesktop::zoom_quick (bool enable)
         _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;
-                                               }
-                                       }
-                               }
+        // 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<InkNodeTool*>(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, 10);
+                set_display_area(*d, true);
                 zoomed = true;
             }
         }
@@ -963,7 +932,7 @@ SPDesktop::zoom_quick (bool enable)
             zoomed = true;
         }
     } else {
-        set_display_area(_quick_zoom_stored_area, 0);
+        set_display_area(_quick_zoom_stored_area, false);
     }
 
     _quick_zoom_enabled = enable;
@@ -996,6 +965,26 @@ SPDesktop::zoom_absolute_keep_point (double cx, double cy, double px, double py,
                      0.0);
 }
 
+/**
+  * Apply the desktop's current style or the tool style to the object.
+  */
+void SPDesktop::applyCurrentOrToolStyle(SPObject *obj, Glib::ustring const &tool_path, bool with_text)
+{
+    SPCSSAttr *css_current = sp_desktop_get_style(this, with_text);
+    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+    if (prefs->getBool(tool_path + "/usecurrent") && css_current) {
+        obj->setCSS(css_current,"style");
+    } else {
+        SPCSSAttr *css = prefs->getInheritedStyle(tool_path + "/style");
+        obj->setCSS(css,"style");
+        sp_repr_css_attr_unref(css);
+    }
+    if (css_current) {
+        sp_repr_css_attr_unref(css_current);
+    }
+}
+
 /**
  * Zoom to center with absolute zoom factor.
  */
@@ -1050,7 +1039,7 @@ void
 SPDesktop::zoom_page()
 {
     Geom::Rect d(Geom::Point(0, 0),
-                 Geom::Point(sp_document_width(doc()), sp_document_height(doc())));
+                 Geom::Point(doc()->getWidth(), doc()->getHeight()));
 
     if (d.minExtent() < 1.0) {
         return;
@@ -1067,12 +1056,12 @@ SPDesktop::zoom_page_width()
 {
     Geom::Rect const a = get_display_area();
 
-    if (sp_document_width(doc()) < 1.0) {
+    if (doc()->getWidth() < 1.0) {
         return;
     }
 
     Geom::Rect d(Geom::Point(0, a.midpoint()[Geom::Y]),
-                 Geom::Point(sp_document_width(doc()), a.midpoint()[Geom::Y]));
+                 Geom::Point(doc()->getWidth(), a.midpoint()[Geom::Y]));
 
     set_display_area(d, 10);
 }
@@ -1108,10 +1097,10 @@ void
 SPDesktop::zoom_drawing()
 {
     g_return_if_fail (doc() != NULL);
-    SPItem *docitem = SP_ITEM (sp_document_root (doc()));
+    SPItem *docitem = SP_ITEM(doc()->getRoot());
     g_return_if_fail (docitem != NULL);
 
-    Geom::OptRect d = sp_item_bbox_desktop(docitem);
+    Geom::OptRect d = docitem->getBboxDesktop();
 
     /* Note that the second condition here indicates that
     ** there are no items in the drawing.
@@ -1403,7 +1392,7 @@ SPDesktop::emitToolSubselectionChanged(gpointer data)
 void
 SPDesktop::updateNow()
 {
-  sp_canvas_update_now(canvas);
+    sp_canvas_update_now(canvas);
 }
 
 void
@@ -1446,8 +1435,7 @@ void SPDesktop::toggleGrids()
         }
     } 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);
+        namedview->writeNewGrid(sp_desktop_document(this), Inkscape::GRID_RECTANGULAR);
         showGrids(true);
     }
 }
@@ -1465,9 +1453,8 @@ void SPDesktop::showGrids(bool show, bool dirty_document)
 
 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);
+    bool v = namedview->getSnapGlobal();
+    namedview->setSnapGlobal(!v);
 }
 
 //----------------------------------------------------------------------
@@ -1510,7 +1497,7 @@ SPDesktop::setDocument (SPDocument *doc)
 {
     if (this->doc() && doc) {
         namedview->hide(this);
-        sp_item_invoke_hide (SP_ITEM (sp_document_root (this->doc())), dkey);
+        SP_ITEM(this->doc()->getRoot())->invoke_hide(dkey);
     }
 
     if (_layer_hierarchy) {
@@ -1521,7 +1508,7 @@ SPDesktop::setDocument (SPDocument *doc)
     _layer_hierarchy->connectAdded(sigc::bind(sigc::ptr_fun(_layer_activated), this));
     _layer_hierarchy->connectRemoved(sigc::bind(sigc::ptr_fun(_layer_deactivated), this));
     _layer_hierarchy->connectChanged(sigc::bind(sigc::ptr_fun(_layer_hierarchy_changed), this));
-    _layer_hierarchy->setTop(SP_DOCUMENT_ROOT(doc));
+    _layer_hierarchy->setTop(doc->getRoot());
 
     /* setup EventLog */
     event_log = new Inkscape::EventLog(doc);
@@ -1541,7 +1528,7 @@ SPDesktop::setDocument (SPDocument *doc)
         _modified_connection = namedview->connectModified(sigc::bind<2>(sigc::ptr_fun(&_namedview_modified), this));
         number = namedview->getViewCount();
 
-        ai = sp_item_invoke_show (SP_ITEM (sp_document_root (doc)),
+        ai = SP_ITEM(doc->getRoot())->invoke_show(
                 SP_CANVAS_ARENA (drawing)->arena,
                 dkey,
                 SP_ITEM_SHOW_DISPLAY);
@@ -1671,7 +1658,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());
 
     /*
@@ -1804,7 +1791,7 @@ Geom::Point SPDesktop::dt2doc(Geom::Point const &p) const
 }
 
 
-/**
+/*
  * Pop event context from desktop's context stack. Never used.
  */
 // void
@@ -1846,4 +1833,4 @@ Geom::Point SPDesktop::dt2doc(Geom::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:fileencoding=utf-8:textwidth=99 :