summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEric Greveson <eric@greveson.co.uk>2013-07-01 20:09:53 +0000
committerEric Greveson <eric@greveson.co.uk>2013-07-01 20:09:53 +0000
commit6fe6a37589cbd6e53bf763879503ace16260e7a2 (patch)
treeab3d7fa48e6ca4af582a54cf4c042de0fac2bef2 /src
parentFactored layer model out into new Inkscape::LayerModel class. This allows (diff)
downloadinkscape-6fe6a37589cbd6e53bf763879503ace16260e7a2.tar.gz
inkscape-6fe6a37589cbd6e53bf763879503ace16260e7a2.zip
Added new files referenced in previous commit message (forgot to add!)
(bzr r12387.1.2)
Diffstat (limited to 'src')
-rw-r--r--src/helper/action-context.cpp74
-rw-r--r--src/helper/action-context.h78
-rw-r--r--src/layer-model.cpp259
-rw-r--r--src/layer-model.h104
4 files changed, 515 insertions, 0 deletions
diff --git a/src/helper/action-context.cpp b/src/helper/action-context.cpp
new file mode 100644
index 000000000..c88086f7f
--- /dev/null
+++ b/src/helper/action-context.cpp
@@ -0,0 +1,74 @@
+/*
+ * ActionContext implementation.
+ *
+ * Author:
+ * Eric Greveson <eric@greveson.co.uk>
+ *
+ * Copyright (C) 2013 Eric Greveson
+ *
+ * This code is in public domain
+ */
+
+#include "desktop.h"
+#include "document.h"
+#include "layer-model.h"
+#include "selection.h"
+#include "helper/action-context.h"
+#include "ui/view/view.h"
+
+namespace Inkscape {
+
+ActionContext::ActionContext()
+ : _selection(NULL)
+ , _view(NULL)
+{
+}
+
+ActionContext::ActionContext(Selection *selection)
+ : _selection(selection)
+ , _view(NULL)
+{
+}
+
+ActionContext::ActionContext(UI::View::View *view)
+ : _selection(NULL)
+ , _view(view)
+{
+ SPDesktop *desktop = static_cast<SPDesktop *>(view);
+ if (desktop) {
+ _selection = desktop->selection;
+ }
+}
+
+SPDocument *ActionContext::getDocument() const
+{
+ if (_selection == NULL) {
+ return NULL;
+ }
+
+ // Should be the same as the view's document, if view is non-NULL
+ return _selection->layerModel()->getDocument();
+}
+
+Selection *ActionContext::getSelection() const
+{
+ return _selection;
+}
+
+UI::View::View *ActionContext::getView() const
+{
+ return _view;
+}
+
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/helper/action-context.h b/src/helper/action-context.h
new file mode 100644
index 000000000..de09f94f4
--- /dev/null
+++ b/src/helper/action-context.h
@@ -0,0 +1,78 @@
+/** \file
+ * Inkscape UI action context implementation
+ *//*
+ * Author:
+ * Eric Greveson <eric@greveson.co.uk>
+ *
+ * Copyright (C) 2013 Eric Greveson
+ *
+ * This code is in public domain
+ */
+
+#ifndef SEEN_INKSCAPE_ACTION_CONTEXT_H
+#define SEEN_INKSCAPE_ACTION_CONTEXT_H
+
+class SPDocument;
+
+namespace Inkscape {
+
+class Selection;
+
+namespace UI {
+namespace View {
+class View;
+} // namespace View
+} // namespace UI
+
+/** This structure contains all the document/view context required
+ for an action. Some actions may be executed on a document without
+ requiring a GUI, hence not providing the info directly through
+ Inkscape::UI::View::View. Actions that do require GUI objects should
+ check to see if the relevant pointers are NULL before attempting to
+ use them.
+
+ ActionContext is designed to be copyable, so it may be used with stack
+ storage if required. */
+class ActionContext {
+ // NB: Only one of these is typically set - selection model if in console mode, view if in GUI mode
+ Selection *_selection; /**< The selection model to which this action applies, if running in console mode. May be NULL. */
+ UI::View::View *_view; /**< The view to which this action applies. May be NULL (e.g. if running in console mode). */
+
+public:
+ /** Construct without any document or GUI */
+ ActionContext();
+
+ /** Construct an action context for when the app is being run without
+ any GUI, i.e. in console mode */
+ ActionContext(Selection *selection);
+
+ /** Construct an action context for when the app is being run in GUI mode */
+ ActionContext(UI::View::View *view);
+
+ /** Get the document for the action context. May be NULL. Prefer this
+ function to getView()->doc() if the action doesn't require a GUI. */
+ SPDocument *getDocument() const;
+
+ /** Get the selection for the action context. May be NULL. Should be
+ non-NULL if getDocument() is non-NULL. */
+ Selection *getSelection() const;
+
+ /** Get the view for the action context. May be NULL. Guaranteed to be
+ NULL if running in console mode. */
+ UI::View::View *getView() const;
+};
+
+} // namespace Inkscape
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/layer-model.cpp b/src/layer-model.cpp
new file mode 100644
index 000000000..6833852ad
--- /dev/null
+++ b/src/layer-model.cpp
@@ -0,0 +1,259 @@
+/*
+ * Editable view implementation
+ *
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * MenTaLguY <mental@rydia.net>
+ * bulia byak <buliabyak@users.sf.net>
+ * 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
+ * Copyright (C) 2006 John Bintz
+ * Copyright (C) 2004 MenTaLguY
+ * Copyright (C) 1999-2002 Lauris Kaplinski
+ * Copyright (C) 2000-2001 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "document.h"
+#include "layer-fns.h"
+#include "layer-model.h"
+#include "object-hierarchy.h"
+#include "sp-defs.h"
+#include "sp-item.h"
+#include "sp-item-group.h"
+#include "sp-object.h"
+#include "sp-root.h"
+#include <glib.h>
+#include <glibmm/i18n.h>
+#include <sigc++/functors/ptr_fun.h>
+
+// Callbacks
+static void _layer_activated(SPObject *layer, Inkscape::LayerModel *layer_model);
+static void _layer_deactivated(SPObject *layer, Inkscape::LayerModel *layer_model);
+static void _layer_changed(SPObject *top, SPObject *bottom, Inkscape::LayerModel *layer_model);
+
+namespace Inkscape {
+
+LayerModel::LayerModel()
+ : _doc( 0 )
+ , _layer_hierarchy( 0 )
+ , _display_key( 0 )
+{
+}
+
+LayerModel::~LayerModel()
+{
+ if (_layer_hierarchy) {
+ delete _layer_hierarchy;
+// _layer_hierarchy = NULL; //this should be here, but commented to find other bug somewhere else.
+ }
+}
+
+void LayerModel::setDocument(SPDocument *doc)
+{
+ _doc = doc;
+ if (_layer_hierarchy) {
+ _layer_hierarchy->clear();
+ delete _layer_hierarchy;
+ }
+ _layer_hierarchy = new Inkscape::ObjectHierarchy(NULL);
+ _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_changed), this));
+ _layer_hierarchy->setTop(doc->getRoot());
+}
+
+void LayerModel::setDisplayKey(unsigned int display_key)
+{
+ _display_key = display_key;
+}
+
+SPDocument *LayerModel::getDocument()
+{
+ return _doc;
+}
+
+/**
+ * Returns current root (=bottom) layer.
+ */
+SPObject *LayerModel::currentRoot() const
+{
+ return _layer_hierarchy ? _layer_hierarchy->top() : NULL;
+}
+
+/**
+ * Returns current top layer.
+ */
+SPObject *LayerModel::currentLayer() const
+{
+ return _layer_hierarchy ? _layer_hierarchy->bottom() : NULL;
+}
+
+/**
+ * Resets the bottom layer to the current root
+ */
+void LayerModel::reset() {
+ if (_layer_hierarchy) {
+ _layer_hierarchy->setBottom(currentRoot());
+ }
+}
+
+/**
+ * Sets the current layer of the desktop.
+ *
+ * Make \a object the top layer.
+ */
+void LayerModel::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", object->getId());
+ _layer_hierarchy->setBottom(object);
+}
+
+void LayerModel::toggleHideAllLayers(bool hide) {
+
+ for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), currentRoot()); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) {
+ SP_ITEM(obj)->setHidden(hide);
+ }
+}
+
+void LayerModel::toggleLockAllLayers(bool lock) {
+
+ for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), currentRoot()); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) {
+ SP_ITEM(obj)->setLocked(lock);
+ }
+}
+
+void LayerModel::toggleLockOtherLayers(SPObject *object) {
+ g_return_if_fail(SP_IS_GROUP(object));
+ g_return_if_fail( currentRoot() == object || (currentRoot() && currentRoot()->isAncestorOf(object)) );
+
+ bool othersLocked = false;
+ std::vector<SPObject*> layers;
+ for ( SPObject* obj = Inkscape::next_layer(currentRoot(), object); obj; obj = Inkscape::next_layer(currentRoot(), obj) ) {
+ // Dont lock any ancestors, since that would in turn lock the layer as well
+ if (!obj->isAncestorOf(object)) {
+ layers.push_back(obj);
+ othersLocked |= !SP_ITEM(obj)->isLocked();
+ }
+ }
+ for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), object); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) {
+ if (!obj->isAncestorOf(object)) {
+ layers.push_back(obj);
+ othersLocked |= !SP_ITEM(obj)->isLocked();
+ }
+ }
+
+ SPItem *item = SP_ITEM(object);
+ if ( item->isLocked() ) {
+ item->setLocked(false);
+ }
+
+ for ( std::vector<SPObject*>::iterator it = layers.begin(); it != layers.end(); ++it ) {
+ SP_ITEM(*it)->setLocked(othersLocked);
+ }
+}
+
+
+void LayerModel::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<SPObject*> layers;
+ for ( SPObject* obj = Inkscape::next_layer(currentRoot(), object); obj; obj = Inkscape::next_layer(currentRoot(), obj) ) {
+ // Don't hide ancestors, since that would in turn hide the layer as well
+ if (!obj->isAncestorOf(object)) {
+ layers.push_back(obj);
+ othersShowing |= !SP_ITEM(obj)->isHidden();
+ }
+ }
+ for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), object); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) {
+ if (!obj->isAncestorOf(object)) {
+ layers.push_back(obj);
+ othersShowing |= !SP_ITEM(obj)->isHidden();
+ }
+ }
+
+
+ SPItem *item = SP_ITEM(object);
+ if ( item->isHidden() ) {
+ item->setHidden(false);
+ }
+
+ for ( std::vector<SPObject*>::iterator it = layers.begin(); it != layers.end(); ++it ) {
+ SP_ITEM(*it)->setHidden(othersShowing);
+ }
+}
+
+/**
+ * Return layer that contains \a object.
+ */
+SPObject *LayerModel::layerForObject(SPObject *object) {
+ g_return_val_if_fail(object != NULL, NULL);
+
+ SPObject *root=currentRoot();
+ object = object->parent;
+ while ( object && object != root && !isLayer(object) ) {
+ // Objects in defs have no layer and are NOT in the root layer
+ if(SP_IS_DEFS(object))
+ return NULL;
+ object = object->parent;
+ }
+ return object;
+}
+
+/**
+ * True if object is a layer.
+ */
+bool LayerModel::isLayer(SPObject *object) const {
+ return ( SP_IS_GROUP(object)
+ && ( SP_GROUP(object)->effectiveLayerMode(_display_key)
+ == SPGroup::LAYER ) );
+}
+
+} // namespace Inkscape
+
+
+/// Callback
+static void
+_layer_activated(SPObject *layer, Inkscape::LayerModel *layer_model) {
+ g_return_if_fail(SP_IS_GROUP(layer));
+ layer_model->_layer_activated_signal.emit(layer);
+}
+
+/// Callback
+static void
+_layer_deactivated(SPObject *layer, Inkscape::LayerModel *layer_model) {
+ g_return_if_fail(SP_IS_GROUP(layer));
+ layer_model->_layer_deactivated_signal.emit(layer);
+}
+
+/// Callback
+static void
+_layer_changed(SPObject *top, SPObject *bottom, Inkscape::LayerModel *layer_model)
+{
+ layer_model->_layer_changed_signal.emit (top, bottom);
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/layer-model.h b/src/layer-model.h
new file mode 100644
index 000000000..79b7fbe44
--- /dev/null
+++ b/src/layer-model.h
@@ -0,0 +1,104 @@
+#ifndef SEEN_INKSCAPE_LAYER_MODEL_H
+#define SEEN_INKSCAPE_LAYER_MODEL_H
+
+/*
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Frank Felfe <innerspace@iname.com>
+ * bulia byak <buliabyak@users.sf.net>
+ * 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>get
+ * Abhishek Sharma
+ * Eric Greveson <eric@greveson.co.uk>
+ *
+ * Copyright (C) 2007 Johan Engelen
+ * Copyright (C) 2006 John Bintz
+ * Copyright (C) 1999-2013 authors
+ * Copyright (C) 2000-2001 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stddef.h>
+#include <sigc++/sigc++.h>
+
+class SPDocument;
+class SPObject;
+
+namespace Inkscape {
+
+class ObjectHierarchy;
+
+namespace XML {
+ class Node;
+}
+
+/**
+ * The layer model for a document.
+ *
+ * This class represents the layer model for a document, typically (but
+ * not necessarily) displayed in an SPDesktop.
+ *
+ * It also implements its own asynchronous notification signals that
+ * UI elements can listen to.
+ */
+class LayerModel
+{
+ SPDocument *_doc;
+ Inkscape::ObjectHierarchy *_layer_hierarchy;
+ unsigned int _display_key;
+
+public:
+ /** Construct a layer model */
+ LayerModel();
+
+ /** Destructor */
+ ~LayerModel();
+
+ // Set document
+ void setDocument(SPDocument *doc);
+
+ // Set display key. For GUI apps.
+ void setDisplayKey(unsigned int display_key);
+
+ // Get the document that this layer model refers to. May be NULL.
+ SPDocument *getDocument();
+
+ // TODO look into making these return a more specific subclass:
+ SPObject *currentRoot() const;
+ SPObject *currentLayer() const;
+
+ void reset();
+ void setCurrentLayer(SPObject *object);
+ void toggleLayerSolo(SPObject *object);
+ void toggleHideAllLayers(bool hide);
+ void toggleLockAllLayers(bool lock);
+ void toggleLockOtherLayers(SPObject *object);
+ SPObject *layerForObject(SPObject *object);
+ bool isLayer(SPObject *object) const;
+
+ sigc::signal<void, SPObject *> _layer_activated_signal;
+ sigc::signal<void, SPObject *> _layer_deactivated_signal;
+ sigc::signal<void, SPObject *, SPObject *> _layer_changed_signal;
+};
+
+} // namespace Inkscape
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :