diff options
| author | Eric Greveson <eric@greveson.co.uk> | 2013-07-01 20:09:53 +0000 |
|---|---|---|
| committer | Eric Greveson <eric@greveson.co.uk> | 2013-07-01 20:09:53 +0000 |
| commit | 6fe6a37589cbd6e53bf763879503ace16260e7a2 (patch) | |
| tree | ab3d7fa48e6ca4af582a54cf4c042de0fac2bef2 /src | |
| parent | Factored layer model out into new Inkscape::LayerModel class. This allows (diff) | |
| download | inkscape-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.cpp | 74 | ||||
| -rw-r--r-- | src/helper/action-context.h | 78 | ||||
| -rw-r--r-- | src/layer-model.cpp | 259 | ||||
| -rw-r--r-- | src/layer-model.h | 104 |
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 : |
