From 71c76fb077d04db40914542eb83a8025b1172dae Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Wed, 3 Nov 2021 06:29:28 -0400 Subject: [PATCH 1/6] Refactor layers, remove SPDesktop passthroughs Many problems with the layers can't be fixed until the code that manages layers is cleaned up. This is Part 1, which removes passthrough functions and signals from the SPDesktop object and moves them to the Layer Model or Layer Manager as needed. --- src/conn-avoid-ref.cpp | 7 ++- src/context-fns.cpp | 6 +- src/desktop.cpp | 74 ++----------------------- src/desktop.h | 15 ----- src/document.cpp | 2 +- src/extension/implementation/script.cpp | 2 +- src/extension/internal/grid.cpp | 26 ++++----- src/file.cpp | 10 ++-- src/layer-manager.cpp | 37 ++++++++++--- src/layer-manager.h | 7 ++- src/layer-model.cpp | 8 +-- src/layer-model.h | 6 +- src/object/sp-flowtext.cpp | 4 +- src/object/sp-item-group.cpp | 18 ------ src/object/sp-item-group.h | 14 +---- src/object/sp-item.cpp | 8 +++ src/object/sp-item.h | 3 + src/object/sp-namedview.cpp | 7 ++- src/object/sp-symbol.cpp | 2 +- src/object/sp-text.cpp | 22 +++----- src/selection-chemistry.cpp | 63 ++++++++++----------- src/ui/contextmenu.cpp | 40 +++++++------ src/ui/dialog/filter-effects-dialog.cpp | 5 +- src/ui/dialog/find.cpp | 11 ++-- src/ui/dialog/icon-preview.cpp | 2 +- src/ui/dialog/layer-properties.cpp | 16 +++--- src/ui/dialog/layers.cpp | 15 ++--- src/ui/dialog/objects.cpp | 15 ++--- src/ui/dialog/spellcheck.cpp | 11 ++-- src/ui/dialog/xml-tree.cpp | 5 +- src/ui/drag-and-drop.cpp | 3 +- src/ui/toolbar/connector-toolbar.cpp | 3 +- src/ui/tools/arc-tool.cpp | 5 +- src/ui/tools/box3d-tool.cpp | 2 +- src/ui/tools/calligraphic-tool.cpp | 5 +- src/ui/tools/connector-tool.cpp | 5 +- src/ui/tools/eraser-tool.cpp | 2 +- src/ui/tools/flood-tool.cpp | 6 +- src/ui/tools/freehand-base.cpp | 12 ++-- src/ui/tools/measure-tool.cpp | 31 ++++++----- src/ui/tools/pen-tool.cpp | 4 +- src/ui/tools/pencil-tool.cpp | 7 ++- src/ui/tools/rect-tool.cpp | 4 +- src/ui/tools/select-tool.cpp | 10 ++-- src/ui/tools/spiral-tool.cpp | 4 +- src/ui/tools/star-tool.cpp | 4 +- src/ui/tools/text-tool.cpp | 4 +- src/ui/tools/tool-base.cpp | 6 ++ src/ui/tools/tool-base.h | 2 + src/ui/widget/layer-selector.cpp | 72 ++++++++---------------- src/ui/widget/style-subject.cpp | 6 +- src/verbs.cpp | 63 ++++++++++----------- 52 files changed, 335 insertions(+), 386 deletions(-) diff --git a/src/conn-avoid-ref.cpp b/src/conn-avoid-ref.cpp index 34e87468c5..5ca5a8c86a 100644 --- a/src/conn-avoid-ref.cpp +++ b/src/conn-avoid-ref.cpp @@ -24,6 +24,7 @@ #include "document-undo.h" #include "document.h" #include "inkscape.h" +#include "layer-model.h" #include "verbs.h" #include "display/curve.h" @@ -338,7 +339,7 @@ std::vector get_avoided_items(std::vector &list, SPObject *f { for (auto& child: from->children) { if (SP_IS_ITEM(&child) && - !desktop->isLayer(SP_ITEM(&child)) && + !desktop->layers->isLayer(SP_ITEM(&child)) && !SP_ITEM(&child)->isLocked() && !desktop->itemIsHidden(SP_ITEM(&child)) && (!initialised || SP_ITEM(&child)->getAvoidRef().shapeRef) @@ -347,7 +348,7 @@ std::vector get_avoided_items(std::vector &list, SPObject *f list.push_back(SP_ITEM(&child)); } - if (SP_IS_ITEM(&child) && desktop->isLayer(SP_ITEM(&child))) { + if (SP_IS_ITEM(&child) && desktop->layers->isLayer(SP_ITEM(&child))) { list = get_avoided_items(list, &child, desktop, initialised); } } @@ -378,7 +379,7 @@ void init_avoided_shape_geometry(SPDesktop *desktop) bool initialised = false; std::vector tmp; - std::vector items = get_avoided_items(tmp, desktop->currentRoot(), desktop, + std::vector items = get_avoided_items(tmp, desktop->layers->currentRoot(), desktop, initialised); for (auto item : items) { diff --git a/src/context-fns.cpp b/src/context-fns.cpp index edfc62d258..28e36be17d 100644 --- a/src/context-fns.cpp +++ b/src/context-fns.cpp @@ -12,6 +12,7 @@ #include "context-fns.h" #include "desktop.h" +#include "layer-model.h" #include "message-context.h" #include "message-stack.h" #include "snap.h" @@ -19,6 +20,7 @@ #include "display/control/snap-indicator.h" #include "object/sp-namedview.h" +#include "object/sp-item-group.h" #include "ui/modifiers.h" #include "ui/tools/tool-base.h" @@ -39,7 +41,7 @@ static const double midpt_goldenratio_2 = (goldenratio + 2) / 2; bool Inkscape::have_viable_layer(SPDesktop *desktop, MessageContext *message) { - SPItem const *layer = SP_ITEM(desktop->currentLayer()); + auto layer = desktop->layers->currentLayer(); if ( !layer || desktop->itemIsHidden(layer) ) { message->flash(Inkscape::ERROR_MESSAGE, @@ -68,7 +70,7 @@ bool Inkscape::have_viable_layer(SPDesktop *desktop, MessageContext *message) bool Inkscape::have_viable_layer(SPDesktop *desktop, MessageStack *message) { - SPItem const *layer = SP_ITEM(desktop->currentLayer()); + auto layer = desktop->layers->currentLayer(); if ( !layer || desktop->itemIsHidden(layer) ) { message->flash(Inkscape::WARNING_MESSAGE, diff --git a/src/desktop.cpp b/src/desktop.cpp index 6bdce334d2..554a80cf93 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -38,6 +38,7 @@ #include "inkscape-window.h" #include "layer-fns.h" #include "layer-manager.h" +#include "layer-model.h" #include "message-context.h" #include "message-stack.h" @@ -80,9 +81,6 @@ namespace Inkscape { namespace XML { class Node; }} // Callback declarations static void _onSelectionChanged (Inkscape::Selection *selection, SPDesktop *desktop); static bool _drawing_handler (GdkEvent *event, Inkscape::DrawingItem *item, SPDesktop *desktop); -static void _layer_activated(SPObject *layer, SPDesktop *desktop); -static void _layer_deactivated(SPObject *layer, SPDesktop *desktop); -static void _layer_hierarchy_changed(SPObject *top, SPObject *bottom, SPDesktop *desktop); static void _reconstruction_start(SPDesktop * desktop); static void _reconstruction_finish(SPDesktop * desktop); static void _namedview_modified (SPObject *obj, guint flags, SPDesktop *desktop); @@ -137,9 +135,6 @@ SPDesktop::SPDesktop() , grids_visible(false) { layers = new Inkscape::LayerModel(); - layers->_layer_activated_signal.connect(sigc::bind(sigc::ptr_fun(_layer_activated), this)); - layers->_layer_deactivated_signal.connect(sigc::bind(sigc::ptr_fun(_layer_deactivated), this)); - layers->_layer_changed_signal.connect(sigc::bind(sigc::ptr_fun(_layer_hierarchy_changed), this)); selection = Inkscape::GC::release( new Inkscape::Selection(layers, this) ); } @@ -417,47 +412,6 @@ void SPDesktop::redrawDesktop() { canvas->set_affine(_current_affine.d2w()); // For CanvasItem's. } -// Pass-through LayerModel functions -SPObject *SPDesktop::currentRoot() const -{ - return layers->currentRoot(); -} - -SPObject *SPDesktop::currentLayer() const -{ - return layers->currentLayer(); -} - -void SPDesktop::setCurrentLayer(SPObject *object) -{ - layers->setCurrentLayer(object); -} - -void SPDesktop::toggleLayerSolo(SPObject *object) -{ - layers->toggleLayerSolo(object); -} - -void SPDesktop::toggleHideAllLayers(bool hide) -{ - layers->toggleHideAllLayers(hide); -} - -void SPDesktop::toggleLockAllLayers(bool lock) -{ - layers->toggleLockAllLayers(lock); -} - -void SPDesktop::toggleLockOtherLayers(SPObject *object) -{ - layers->toggleLockOtherLayers(object); -} - -bool SPDesktop::isLayer(SPObject *object) const -{ - return layers->isLayer(object); -} - /** * True if desktop viewport intersects \a item's bbox. */ @@ -1612,7 +1566,7 @@ _onSelectionChanged SPItem *item=selection->singleItem(); if (item) { SPObject *layer=desktop->layers->layerForObject(item); - if ( layer && layer != desktop->currentLayer() ) { + if ( layer && layer != desktop->layers->currentLayer() ) { desktop->layers->setCurrentLayer(layer); } } @@ -1638,31 +1592,11 @@ _drawing_handler (GdkEvent *event, Inkscape::DrawingItem *drawing_item, SPDeskto } } -static void -_layer_activated(SPObject *layer, SPDesktop *desktop) { - g_return_if_fail(SP_IS_GROUP(layer)); - SP_GROUP(layer)->setLayerDisplayMode(desktop->dkey, SPGroup::LAYER); -} - -/// Callback -static void -_layer_deactivated(SPObject *layer, SPDesktop *desktop) { - g_return_if_fail(SP_IS_GROUP(layer)); - SP_GROUP(layer)->setLayerDisplayMode(desktop->dkey, SPGroup::GROUP); -} - -/// Callback -static void -_layer_hierarchy_changed(SPObject */*top*/, SPObject *bottom, - SPDesktop *desktop) -{ - desktop->_layer_changed_signal.emit (bottom); -} - /// Called when document is starting to be rebuilt. static void _reconstruction_start(SPDesktop * desktop) { - desktop->_reconstruction_old_layer_id = desktop->currentLayer()->getId() ? desktop->currentLayer()->getId() : ""; + auto layer = desktop->layers->currentLayer(); + desktop->_reconstruction_old_layer_id = layer->getId() ? layer->getId() : ""; desktop->layers->reset(); desktop->selection->clear(); diff --git a/src/desktop.h b/src/desktop.h index 6f4f92c565..63c1f275e0 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -217,7 +217,6 @@ public: Glib::ustring _reconstruction_old_layer_id; sigc::signal _menu_update; - sigc::signal _layer_changed_signal; sigc::signal::accumulated _set_style_signal; sigc::signal::accumulated _query_style_signal; @@ -258,10 +257,6 @@ public: void emitToolSubselectionChanged(gpointer data); void emitToolSubselectionChangedEx(gpointer data, SPObject* object); - sigc::connection connectCurrentLayerChanged(const sigc::slot & slot) { - return _layer_changed_signal.connect(slot); - } - // there's an object selected and it has a gradient fill and/or stroke; one of the gradient stops has been selected // callback receives sender pointer and selected stop pointer sigc::connection connect_gradient_stop_selected(const sigc::slot& slot); @@ -341,16 +336,6 @@ public: Inkscape::UI::Dialog::DialogContainer *getContainer(); - // Could make all callers use this->layers instead of passing calls through? - SPObject *currentRoot() const; - SPObject *currentLayer() const; - void setCurrentLayer(SPObject *object); - void toggleLayerSolo(SPObject *object); - void toggleHideAllLayers(bool hide); - void toggleLockAllLayers(bool lock); - void toggleLockOtherLayers(SPObject *object); - bool isLayer(SPObject *object) const; - bool isWithinViewport(SPItem *item) const; bool itemIsHidden(SPItem const *item) const; diff --git a/src/document.cpp b/src/document.cpp index 412894332a..8239879be4 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1599,8 +1599,8 @@ std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vecto SPDesktop *desktop = SP_ACTIVE_DESKTOP; Inkscape::LayerModel *layer_model = nullptr; if(desktop){ - current_layer = desktop->currentLayer(); layer_model = desktop->layers; + current_layer = layer_model->currentLayer(); } size_t item_counter = 0; for(int i = points.size()-1;i>=0; i--) { diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp index 034f4542df..0e6acf80a0 100644 --- a/src/extension/implementation/script.cpp +++ b/src/extension/implementation/script.cpp @@ -681,7 +681,7 @@ void Script::effect(Inkscape::Extension::Effect *module, //If that layer exists, if (layer) { //set the current layer - desktop->setCurrentLayer(layer); + desktop->layers->setCurrentLayer(layer); } } mydoc->release(); diff --git a/src/extension/internal/grid.cpp b/src/extension/internal/grid.cpp index cc6615a16d..48aaa8ba04 100644 --- a/src/extension/internal/grid.cpp +++ b/src/extension/internal/grid.cpp @@ -19,6 +19,7 @@ #include "desktop.h" #include "document.h" +#include "layer-model.h" #include "selection.h" #include "2geom/geom.h" @@ -81,28 +82,27 @@ Glib::ustring build_lines(Geom::Rect bounding_area, \param document What should be edited. */ void -Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *document, Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/) +Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *view, Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/) { - Inkscape::Selection * selection = ((SPDesktop *)document)->selection; + auto desktop = dynamic_cast(view); + Inkscape::Selection *selection = desktop->selection; + SPDocument *doc = desktop->doc(); Geom::Rect bounding_area = Geom::Rect(Geom::Point(0,0), Geom::Point(100,100)); if (selection->isEmpty()) { /* get page size */ - SPDocument * doc = document->doc(); - bounding_area = Geom::Rect( Geom::Point(0,0), - Geom::Point(doc->getWidth().value("px"), doc->getHeight().value("px")) ); + if (auto bounds = doc->preferredBounds()) { + bounding_area = *bounds; + } } else { - Geom::OptRect bounds = selection->visualBounds(); - if (bounds) { + if (auto bounds = selection->visualBounds()) { bounding_area = *bounds; } - - Geom::Rect temprec = bounding_area * static_cast(document)->doc2dt(); - + Geom::Rect temprec = bounding_area * desktop->doc2dt(); bounding_area = temprec; } - double scale = document->doc()->getDocumentScale().inverse()[Geom::X]; + double scale = doc->getDocumentScale().inverse()[Geom::X]; bounding_area *= Geom::Scale(scale); Geom::Point spacings( scale * module->get_param_float("xspacing"), @@ -114,10 +114,10 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *doc Glib::ustring path_data(""); path_data = build_lines(bounding_area, offsets, spacings); - Inkscape::XML::Document * xml_doc = document->doc()->getReprDoc(); + Inkscape::XML::Document * xml_doc = doc->getReprDoc(); //XML Tree being used directly here while it shouldn't be. - Inkscape::XML::Node * current_layer = static_cast(document)->currentLayer()->getRepr(); + Inkscape::XML::Node * current_layer = desktop->layers->currentLayer()->getRepr(); Inkscape::XML::Node * path = xml_doc->createElement("svg:path"); path->setAttribute("d", path_data); diff --git a/src/file.cpp b/src/file.cpp index 2240eb1d22..9011a43782 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -43,6 +43,7 @@ #include "id-clash.h" #include "inkscape-version.h" #include "inkscape.h" +#include "layer-model.h" #include "message-stack.h" #include "path-prefix.h" #include "print.h" @@ -900,7 +901,7 @@ void sp_import_document(SPDesktop *desktop, SPDocument *clipdoc, bool in_place) SPDocument *target_document = desktop->getDocument(); Inkscape::XML::Node *root = clipdoc->getReprRoot(); - Inkscape::XML::Node *target_parent = desktop->currentLayer()->getRepr(); + Inkscape::XML::Node *target_parent = desktop->layers->currentLayer()->getRepr(); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -951,12 +952,13 @@ void sp_import_document(SPDesktop *desktop, SPDocument *clipdoc, bool in_place) } } + auto layer = desktop->layers->currentLayer(); std::vector pasted_objects_not; if(clipboard) //???? Removed dead code can cause any bug, need to reimplement undead for (Inkscape::XML::Node *obj = clipboard->firstChild() ; obj ; obj = obj->next()) { if(target_document->getObjectById(obj->attribute("id"))) continue; Inkscape::XML::Node *obj_copy = obj->duplicate(target_document->getReprDoc()); - SPObject * pasted = desktop->currentLayer()->appendChildRepr(obj_copy); + SPObject * pasted = layer->appendChildRepr(obj_copy); Inkscape::GC::release(obj_copy); SPLPEItem * pasted_lpe_item = dynamic_cast(pasted); if (pasted_lpe_item){ @@ -966,7 +968,7 @@ void sp_import_document(SPDesktop *desktop, SPDocument *clipdoc, bool in_place) } Inkscape::Selection *selection = desktop->getSelection(); selection->setReprList(pasted_objects_not); - Geom::Affine doc2parent = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + Geom::Affine doc2parent = layer->i2doc_affine().inverse(); selection->applyAffine(desktop->dt2doc() * doc2parent * desktop->doc2dt(), true, false, false); selection->deleteItems(); @@ -1085,7 +1087,7 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri, // For now, we just use the root in this case. SPObject *place_to_insert; if (desktop) { - place_to_insert = desktop->currentLayer(); + place_to_insert = desktop->layers->currentLayer(); } else { place_to_insert = in_doc->getRoot(); } diff --git a/src/layer-manager.cpp b/src/layer-manager.cpp index d6467c2480..348a9dc8fc 100644 --- a/src/layer-manager.cpp +++ b/src/layer-manager.cpp @@ -19,6 +19,7 @@ #include "document.h" #include "gc-finalized.h" #include "layer-manager.h" +#include "layer-model.h" #include "selection.h" #include "inkgc/gc-managed.h" @@ -138,7 +139,10 @@ public: LayerManager::LayerManager(SPDesktop *desktop) : _desktop(desktop), _document(nullptr) { - _layer_connection = desktop->connectCurrentLayerChanged( sigc::mem_fun(*this, &LayerManager::_selectedLayerChanged) ); + auto layers = desktop->layers; + _layer_connection = layers->_layer_changed_signal.connect(sigc::mem_fun(*this, &LayerManager::_selectedLayerChanged)); + _activate_connection = layers->_layer_activated_signal.connect(sigc::mem_fun(*this, &LayerManager::_layer_activated)); + _deactivate_connection = layers->_layer_deactivated_signal.connect(sigc::mem_fun(*this, &LayerManager::_layer_deactivated)); sigc::bound_mem_functor1 first = sigc::mem_fun(*this, &LayerManager::_setDocument); @@ -154,6 +158,8 @@ LayerManager::LayerManager(SPDesktop *desktop) LayerManager::~LayerManager() { _layer_connection.disconnect(); + _activate_connection.disconnect(); + _deactivate_connection.disconnect(); _document_connection.disconnect(); _resource_connection.disconnect(); _document = nullptr; @@ -161,9 +167,9 @@ LayerManager::~LayerManager() void LayerManager::setCurrentLayer( SPObject* obj ) { - //g_return_if_fail( _desktop->currentRoot() ); - if ( _desktop->currentRoot() ) { - _desktop->setCurrentLayer( obj ); + //g_return_if_fail( _desktop->layers->currentRoot() ); + if ( _desktop->layers->currentRoot() ) { + _desktop->layers->setCurrentLayer( obj ); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); if (prefs->getBool("/options/selection/layerdeselect", true)) { @@ -172,6 +178,21 @@ void LayerManager::setCurrentLayer( SPObject* obj ) } } +void LayerManager::_layer_activated(SPObject *layer) +{ + if (auto group = dynamic_cast(layer)) { + group->setLayerDisplayMode(_desktop->dkey, SPGroup::LAYER); + } +} + +void LayerManager::_layer_deactivated(SPObject *layer) +{ + if (auto group = dynamic_cast(layer)) { + group->setLayerDisplayMode(_desktop->dkey, SPGroup::GROUP); + } +} + + /* * Return a unique layer name similar to param label * A unique name is made by substituting or appending the label's number suffix with @@ -205,7 +226,7 @@ Glib::ustring LayerManager::getNextLayerName( SPObject* obj, gchar const *label) std::set currentNames; std::vector layers = _document->getResourceList("layer"); - SPObject *root=_desktop->currentRoot(); + SPObject *root = _desktop->layers->currentRoot(); if ( root ) { for (auto layer : layers) { if (layer != obj) @@ -265,7 +286,7 @@ void LayerManager::_rebuild() { std::vector layers = _document->getResourceList("layer"); - SPObject *root=_desktop->currentRoot(); + SPObject *root = _desktop->layers->currentRoot(); if ( root ) { _addOne(root); @@ -336,10 +357,10 @@ void LayerManager::_rebuild() { } // Connected to the desktop's CurrentLayerChanged signal -void LayerManager::_selectedLayerChanged(SPObject *layer) +void LayerManager::_selectedLayerChanged(SPObject *top, SPObject *bottom) { // notify anyone who's listening to this instead of directly to the desktop - _layer_changed_signal.emit(layer); + _layer_changed_signal.emit(bottom); } } diff --git a/src/layer-manager.h b/src/layer-manager.h index 94a2d26c10..2efe6fb2b2 100644 --- a/src/layer-manager.h +++ b/src/layer-manager.h @@ -50,9 +50,14 @@ private: void _objectModified( SPObject* obj, unsigned int flags ); void _setDocument(SPDocument *document); void _rebuild(); - void _selectedLayerChanged(SPObject *layer); + + void _selectedLayerChanged(SPObject *top, SPObject *bottom); + void _layer_activated(SPObject *layer); + void _layer_deactivated(SPObject *layer); sigc::connection _layer_connection; + sigc::connection _activate_connection; + sigc::connection _deactivate_connection; sigc::connection _document_connection; sigc::connection _resource_connection; diff --git a/src/layer-model.cpp b/src/layer-model.cpp index 56208af299..c7e22a666e 100644 --- a/src/layer-model.cpp +++ b/src/layer-model.cpp @@ -82,17 +82,17 @@ SPDocument *LayerModel::getDocument() /** * Returns current root (=bottom) layer. */ -SPObject *LayerModel::currentRoot() const +SPGroup *LayerModel::currentRoot() const { - return _layer_hierarchy ? _layer_hierarchy->top() : nullptr; + return _layer_hierarchy ? dynamic_cast(_layer_hierarchy->top()) : nullptr; } /** * Returns current top layer. */ -SPObject *LayerModel::currentLayer() const +SPGroup *LayerModel::currentLayer() const { - return _layer_hierarchy ? _layer_hierarchy->bottom() : nullptr; + return _layer_hierarchy ? dynamic_cast(_layer_hierarchy->bottom()) : nullptr; } /** diff --git a/src/layer-model.h b/src/layer-model.h index 8e7153875a..f42e5d6018 100644 --- a/src/layer-model.h +++ b/src/layer-model.h @@ -28,6 +28,7 @@ class SPDocument; class SPObject; +class SPGroup; namespace Inkscape { @@ -68,9 +69,8 @@ public: // 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; + SPGroup *currentRoot() const; + SPGroup *currentLayer() const; void reset(); void setCurrentLayer(SPObject *object); diff --git a/src/object/sp-flowtext.cpp b/src/object/sp-flowtext.cpp index 881857f9b0..ffaf46b213 100644 --- a/src/object/sp-flowtext.cpp +++ b/src/object/sp-flowtext.cpp @@ -646,7 +646,7 @@ bool SPFlowtext::has_internal_frame() const SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0, Geom::Point p1) { SPDocument *doc = desktop->getDocument(); - auto const parent = dynamic_cast(desktop->currentLayer()); + auto const parent = dynamic_cast(desktop->layers->currentLayer()); assert(parent); Inkscape::XML::Document *xml_doc = doc->getReprDoc(); @@ -657,7 +657,7 @@ SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0, /* Set style */ sp_desktop_apply_style_tool(desktop, root_repr, "/tools/text", true); - SPItem *ft_item = dynamic_cast(desktop->currentLayer()->appendChildRepr(root_repr)); + SPItem *ft_item = dynamic_cast(parent->appendChildRepr(root_repr)); g_assert(ft_item != nullptr); SPObject *root_object = doc->getObjectByRepr(root_repr); g_assert(dynamic_cast(root_object) != nullptr); diff --git a/src/object/sp-item-group.cpp b/src/object/sp-item-group.cpp index c42d59591d..571f394460 100644 --- a/src/object/sp-item-group.cpp +++ b/src/object/sp-item-group.cpp @@ -1050,24 +1050,6 @@ void set_default_highlight_colors(std::vector colors) { std::swap(default_highlights, colors); } -SPGroup* sp_item_get_layer(SPObject* item) { - if (auto group = dynamic_cast(item)) { - if (group->layerMode() == SPGroup::LAYER) { - return group; - } - } - return nullptr; -} - -SPGroup* sp_item_get_group(SPObject* item) { - if (auto group = dynamic_cast(item)) { - if (group->layerMode() == SPGroup::GROUP) { - return group; - } - } - return nullptr; -} - /* Local Variables: mode:c++ diff --git a/src/object/sp-item-group.h b/src/object/sp-item-group.h index e1a2879868..e4712694ea 100644 --- a/src/object/sp-item-group.h +++ b/src/object/sp-item-group.h @@ -31,6 +31,9 @@ public: enum LayerMode { GROUP, LAYER, MASK_HELPER }; + bool isGroup() const { return _layer_mode == GROUP; } + bool isLayer() const { return _layer_mode == LAYER; } + bool _insert_bottom; LayerMode _layer_mode; std::map _display_modes; @@ -115,17 +118,6 @@ inline bool SP_IS_LAYER(SPObject const *obj) return group && group->layerMode() == SPGroup::LAYER; } -/** - * return group object if it represents a layer or null otherwise - */ -SPGroup* sp_item_get_layer(SPObject* item); - -/** - * return group object if it represents a group that is not marked as layer or mask helper - */ -SPGroup* sp_item_get_group(SPObject* item); - - void set_default_highlight_colors(std::vector colors); #endif diff --git a/src/object/sp-item.cpp b/src/object/sp-item.cpp index db784c7307..5e8a0d6276 100644 --- a/src/object/sp-item.cpp +++ b/src/object/sp-item.cpp @@ -373,6 +373,14 @@ void SPItem::lowerToBottom() { } } +/** + * Return the parent, only if it's a group object. + */ +SPGroup *SPItem::getParentGroup() const +{ + return dynamic_cast(parent); +} + void SPItem::moveTo(SPItem *target, bool intoafter) { Inkscape::XML::Node *target_ref = ( target ? target->getRepr() : nullptr ); diff --git a/src/object/sp-item.h b/src/object/sp-item.h index c22b41e4fd..2d29f071ff 100644 --- a/src/object/sp-item.h +++ b/src/object/sp-item.h @@ -32,6 +32,7 @@ #include "xml/repr.h" +class SPGroup; class SPClipPath; class SPClipPathReference; class SPMask; @@ -227,6 +228,8 @@ public: void raiseToTop(); void lowerToBottom(); + SPGroup *getParentGroup() const; + /** * Move this SPItem into or after another SPItem in the doc. * diff --git a/src/object/sp-namedview.cpp b/src/object/sp-namedview.cpp index dca8716555..76958bf757 100644 --- a/src/object/sp-namedview.cpp +++ b/src/object/sp-namedview.cpp @@ -36,6 +36,7 @@ #include "sp-item-group.h" #include "sp-namedview.h" #include "preferences.h" +#include "layer-model.h" #include "desktop.h" #include "conn-avoid-ref.h" // for defaultConnSpacing. #include "sp-root.h" @@ -806,13 +807,13 @@ void sp_namedview_update_layers_from_document (SPDesktop *desktop) // if that didn't work out, look for the topmost layer if (!layer) { for (auto& iter: document->getRoot()->children) { - if (desktop->isLayer(&iter)) { + if (desktop->layers->isLayer(&iter)) { layer = &iter; } } } if (layer) { - desktop->setCurrentLayer(layer); + desktop->layers->setCurrentLayer(layer); } // FIXME: find a better place to do this @@ -850,7 +851,7 @@ void sp_namedview_document_from_window(SPDesktop *desktop) view->setAttributeInt("inkscape:window-maximized", desktop->is_maximized()); } - view->setAttribute("inkscape:current-layer", desktop->currentLayer()->getId()); + view->setAttribute("inkscape:current-layer", desktop->layers->currentLayer()->getId()); // restore undoability DocumentUndo::setUndoSensitive(desktop->getDocument(), saved); diff --git a/src/object/sp-symbol.cpp b/src/object/sp-symbol.cpp index 71c4f1137d..a9d45cfcd7 100644 --- a/src/object/sp-symbol.cpp +++ b/src/object/sp-symbol.cpp @@ -78,7 +78,7 @@ void SPSymbol::unSymbol() //TODO: Better handle if no desktop, currently go to defs without it SPDesktop *desktop = SP_ACTIVE_DESKTOP; if(desktop && desktop->doc() == doc) { - desktop->currentLayer()->getRepr()->appendChild(group); + desktop->layers->currentLayer()->getRepr()->appendChild(group); } else { parent->getRepr()->appendChild(group); } diff --git a/src/object/sp-text.cpp b/src/object/sp-text.cpp index 7aba3bf3f1..a1b69e7117 100644 --- a/src/object/sp-text.cpp +++ b/src/object/sp-text.cpp @@ -1198,7 +1198,10 @@ SPItem *create_text_with_inline_size (SPDesktop *desktop, Geom::Point p0, Geom:: Inkscape::XML::Node *text_repr = xml_doc->createElement("svg:text"); text_repr->setAttribute("xml:space", "preserve"); // we preserve spaces in the text objects we create - SPText *text_object = dynamic_cast(desktop->currentLayer()->appendChildRepr(text_repr)); + auto layer = desktop->layers->currentLayer(); + g_assert(layer != nullptr); + + SPText *text_object = dynamic_cast(layer->appendChildRepr(text_repr)); g_assert(text_object != nullptr); // Invert coordinate system? @@ -1206,8 +1209,8 @@ SPItem *create_text_with_inline_size (SPDesktop *desktop, Geom::Point p0, Geom:: p1 *= desktop->dt2doc(); // Pixels to user units - p0 *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); - p1 *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + p0 *= layer->i2doc_affine().inverse(); + p1 *= layer->i2doc_affine().inverse(); text_repr->setAttributeSvgDouble("x", p0[Geom::X]); text_repr->setAttributeSvgDouble("y", p0[Geom::Y]); @@ -1220,11 +1223,7 @@ SPItem *create_text_with_inline_size (SPDesktop *desktop, Geom::Point p0, Geom:: Inkscape::XML::Node *text_node = xml_doc->createTextNode(""); text_repr->appendChild(text_node); - SPItem *item = dynamic_cast(desktop->currentLayer()); - g_assert(item != nullptr); - - // text_object->transform = item->i2doc_affine().inverse(); - + //text_object->transform = layer->i2doc_affine().inverse(); text_object->updateRepr(); Inkscape::GC::release(text_repr); @@ -1236,7 +1235,7 @@ SPItem *create_text_with_inline_size (SPDesktop *desktop, Geom::Point p0, Geom:: SPItem *create_text_with_rectangle (SPDesktop *desktop, Geom::Point p0, Geom::Point p1) { SPDocument *doc = desktop->getDocument(); - auto const parent = dynamic_cast(desktop->currentLayer()); + auto const parent = desktop->layers->currentLayer(); assert(parent); Inkscape::XML::Document *xml_doc = doc->getReprDoc(); @@ -1244,7 +1243,7 @@ SPItem *create_text_with_rectangle (SPDesktop *desktop, Geom::Point p0, Geom::Po text_repr->setAttribute("xml:space", "preserve"); // we preserve spaces in the text objects we create text_repr->setAttributeOrRemoveIfEmpty("transform", sp_svg_transform_write(parent->i2doc_affine().inverse())); - SPText *text_object = dynamic_cast(desktop->currentLayer()->appendChildRepr(text_repr)); + SPText *text_object = dynamic_cast(parent->appendChildRepr(text_repr)); g_assert(text_object != nullptr); // Invert coordinate system? @@ -1290,9 +1289,6 @@ SPItem *create_text_with_rectangle (SPDesktop *desktop, Geom::Point p0, Geom::Po rtspan->appendChild(text_node); text_repr->appendChild(rtspan); - SPItem *item = dynamic_cast(desktop->currentLayer()); - g_assert(item != nullptr); - Inkscape::GC::release(rtspan); Inkscape::GC::release(text_repr); Inkscape::GC::release(text_node); diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 406f8733b7..7e1902a999 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -290,7 +290,7 @@ void SelectionHelper::fixSelection(SPDesktop *dt) for(auto i = boost::rbegin(selList); i != boost::rend(selList); ++i) { SPItem *item = *i; if( item && - !dt->isLayer(item) && + !dt->layers->isLayer(item) && (!item->isLocked())) { items.push_back(item); @@ -420,7 +420,7 @@ void ObjectSet::deleteItems() clear(); sp_selection_delete_impl(selected); if (SPDesktop *d = desktop()) { - d->currentLayer()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + d->layers->currentLayer()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); /* a tool may have set up private information in it's selection context * that depends on desktop items. I think the only sane way to deal with @@ -474,7 +474,7 @@ void ObjectSet::duplicate(bool suppressDone, bool duplicateLayer) if(duplicateLayer){ reprs.clear(); - reprs.push_back(desktop()->currentLayer()->getRepr()); + reprs.push_back(desktop()->layers->currentLayer()->getRepr()); } clear(); @@ -663,7 +663,7 @@ std::vector &get_all_items(std::vector &list, SPObject *from, for (auto& child: from->children) { SPItem *item = dynamic_cast(&child); if (item && - !desktop->isLayer(item) && + !desktop->layers->isLayer(item) && (!onlysensitive || !item->isLocked()) && (!onlyvisible || !desktop->itemIsHidden(item)) && (exclude.empty() || exclude.end() == std::find(exclude.begin(), exclude.end(), &child)) @@ -672,7 +672,7 @@ std::vector &get_all_items(std::vector &list, SPObject *from, list.insert(list.begin(),item); } - if (ingroups || (item && desktop->isLayer(item))) { + if (ingroups || (item && desktop->layers->isLayer(item))) { list = get_all_items(list, &child, desktop, onlyvisible, onlysensitive, ingroups, exclude); } } @@ -687,7 +687,7 @@ static void sp_edit_select_all_full(SPDesktop *dt, bool force_all_layers, bool i Inkscape::Selection *selection = dt->getSelection(); - auto layer = dynamic_cast(dt->currentLayer()); + auto layer = dt->layers->currentLayer(); g_return_if_fail(layer); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -717,7 +717,7 @@ static void sp_edit_select_all_full(SPDesktop *dt, bool force_all_layers, bool i if (item && (!onlysensitive || !item->isLocked())) { if (!onlyvisible || !dt->itemIsHidden(item)) { - if (!dt->isLayer(item)) { + if (!dt->layers->isLayer(item)) { if (!invert || exclude.end() == std::find(exclude.begin(),exclude.end(),item)) { items.push_back(item); // leave it in the list } @@ -730,12 +730,12 @@ static void sp_edit_select_all_full(SPDesktop *dt, bool force_all_layers, bool i } case PREFS_SELECTION_LAYER_RECURSIVE: { std::vector x; - items = get_all_items(x, dt->currentLayer(), dt, onlyvisible, onlysensitive, FALSE, exclude); + items = get_all_items(x, dt->layers->currentLayer(), dt, onlyvisible, onlysensitive, FALSE, exclude); break; } default: { std::vector x; - items = get_all_items(x, dt->currentRoot(), dt, onlyvisible, onlysensitive, FALSE, exclude); + items = get_all_items(x, dt->layers->currentRoot(), dt, onlyvisible, onlysensitive, FALSE, exclude); break; } } @@ -1449,23 +1449,23 @@ void ObjectSet::toNextLayer(bool skip_undo) std::vector items_copy(items().begin(), items().end()); bool no_more = false; // Set to true, if no more layers above - SPObject *next=Inkscape::next_layer(dt->currentRoot(), dt->currentLayer()); + SPObject *next=Inkscape::next_layer(dt->layers->currentRoot(), dt->layers->currentLayer()); if (next) { clear(); sp_selection_change_layer_maintain_clones(items_copy,next); std::vector temp_clip; sp_selection_copy_impl(items_copy, temp_clip, dt->doc()->getReprDoc()); sp_selection_delete_impl(items_copy, false, false); - next=Inkscape::next_layer(dt->currentRoot(), dt->currentLayer()); // Fixes bug 1482973: crash while moving layers + next=Inkscape::next_layer(dt->layers->currentRoot(), dt->layers->currentLayer()); // Fixes bug 1482973: crash while moving layers std::vector copied; if (next) { copied = sp_selection_paste_impl(dt->getDocument(), next, temp_clip); } else { - copied = sp_selection_paste_impl(dt->getDocument(), dt->currentLayer(), temp_clip); + copied = sp_selection_paste_impl(dt->getDocument(), dt->layers->currentLayer(), temp_clip); no_more = true; } setReprList(copied); - if (next) dt->setCurrentLayer(next); + if (next) dt->layers->setCurrentLayer(next); if ( !skip_undo ) { DocumentUndo::done(dt->getDocument(), _("Raise to next layer"), INKSCAPE_ICON("selection-move-to-layer-above")); } @@ -1494,23 +1494,23 @@ void ObjectSet::toPrevLayer(bool skip_undo) std::vector items_copy(items().begin(), items().end()); bool no_more = false; // Set to true, if no more layers below - SPObject *next=Inkscape::previous_layer(dt->currentRoot(), dt->currentLayer()); + SPObject *next=Inkscape::previous_layer(dt->layers->currentRoot(), dt->layers->currentLayer()); if (next) { clear(); sp_selection_change_layer_maintain_clones(items_copy,next); std::vector temp_clip; sp_selection_copy_impl(items_copy, temp_clip, dt->doc()->getReprDoc()); // we're in the same doc, so no need to copy defs sp_selection_delete_impl(items_copy, false, false); - next=Inkscape::previous_layer(dt->currentRoot(), dt->currentLayer()); // Fixes bug 1482973: crash while moving layers + next=Inkscape::previous_layer(dt->layers->currentRoot(), dt->layers->currentLayer()); // Fixes bug 1482973: crash while moving layers std::vector copied; if (next) { copied = sp_selection_paste_impl(dt->getDocument(), next, temp_clip); } else { - copied = sp_selection_paste_impl(dt->getDocument(), dt->currentLayer(), temp_clip); + copied = sp_selection_paste_impl(dt->getDocument(), dt->layers->currentLayer(), temp_clip); no_more = true; } setReprList( copied); - if (next) dt->setCurrentLayer(next); + if (next) dt->layers->setCurrentLayer(next); if ( !skip_undo ) { DocumentUndo::done(dt->getDocument(), _("Lower to previous layer"), INKSCAPE_ICON("selection-move-to-layer-below")); } @@ -1575,8 +1575,9 @@ void ObjectSet::toLayer(SPObject *moveto, bool skip_undo, Inkscape::XML::Node *a setReprList(copied); if (!temp_clip.empty()) temp_clip.clear(); if (moveto && dt) dt->setCurrentLayer(moveto); - if (!skip_undo) { - DocumentUndo::done(document(), _("Move selection to layer"), INKSCAPE_ICON("selection-move-to-layer")); + if ( !skip_undo ) { + DocumentUndo::done(document(), SP_VERB_LAYER_MOVE_TO, + _("Move selection to layer")); } } } @@ -1980,7 +1981,7 @@ void sp_select_same_fill_stroke_style(SPDesktop *desktop, gboolean fill, gboolea bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true); - SPObject *root = desktop->currentRoot(); + SPObject *root = desktop->layers->currentRoot(); bool ingroup = true; // Apply the same layer logic to select same as used for select all. @@ -2048,7 +2049,7 @@ void sp_select_same_object_type(SPDesktop *desktop) bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true); bool ingroups = TRUE; std::vector x,y; - std::vector all_list = get_all_items(x, desktop->currentRoot(), desktop, onlyvisible, onlysensitive, ingroups, y); + std::vector all_list = get_all_items(x, desktop->layers->currentRoot(), desktop, onlyvisible, onlysensitive, ingroups, y); std::vector matches = all_list; Inkscape::Selection *selection = desktop->getSelection(); @@ -2467,7 +2468,7 @@ SPItem *next_item(SPDesktop *desktop, std::vector &path, SPObject *r SPObject *object=path.back(); path.pop_back(); g_assert(object->parent == root); - if (desktop->isLayer(object)) { + if (desktop->layers->isLayer(object)) { found = next_item(desktop, path, object, only_in_viewport, inlayer, onlyvisible, onlysensitive); } iter = children = D::siblings_after(object); @@ -2477,7 +2478,7 @@ SPItem *next_item(SPDesktop *desktop, std::vector &path, SPObject *r while ( !D::isNull(iter) && !found ) { SPObject *object=D::object(iter); - if (desktop->isLayer(object)) { + if (desktop->layers->isLayer(object)) { if (PREFS_SELECTION_LAYER != inlayer) { // recurse into sublayers std::vector empt; found = next_item(desktop, empt, object, only_in_viewport, inlayer, onlyvisible, onlysensitive); @@ -2488,7 +2489,7 @@ SPItem *next_item(SPDesktop *desktop, std::vector &path, SPObject *r ( !only_in_viewport || desktop->isWithinViewport(item) ) && ( !onlyvisible || !desktop->itemIsHidden(item)) && ( !onlysensitive || !item->isLocked()) && - !desktop->isLayer(item) ) + !desktop->layers->isLayer(item) ) { found = item; } @@ -2549,7 +2550,7 @@ sp_selection_item_next(SPDesktop *desktop) if (PREFS_SELECTION_ALL != inlayer) { root = selection->activeContext(); } else { - root = desktop->currentRoot(); + root = desktop->layers->currentRoot(); } std::vector vec(selection->items().begin(), selection->items().end()); @@ -2580,7 +2581,7 @@ sp_selection_item_prev(SPDesktop *desktop) if (PREFS_SELECTION_ALL != inlayer) { root = selection->activeContext(); } else { - root = desktop->currentRoot(); + root = desktop->layers->currentRoot(); } std::vector vec(selection->items().begin(), selection->items().end()); @@ -3902,7 +3903,7 @@ void ObjectSet::setClipGroup() if (apply_to_layer) { // all selected items are used for mask, which is applied to a layer - apply_to_items.push_back(SP_ITEM(desktop()->currentLayer())); + apply_to_items.push_back(desktop()->layers->currentLayer()); } for (std::vector::const_iterator i=items_.begin();i!=items_.end();++i) { @@ -4379,14 +4380,14 @@ static void itemtree_map(void (*f)(SPItem *, SPDesktop *), SPObject *root, SPDes // don't operate on layers { SPItem *item = dynamic_cast(root); - if (item && !desktop->isLayer(item)) { + if (item && !desktop->layers->isLayer(item)) { f(item, desktop); } } for (auto& child: root->children) { //don't recurse into locked layers SPItem *item = dynamic_cast(&child); - if (!(item && desktop->isLayer(item) && item->isLocked())) { + if (!(item && desktop->layers->isLayer(item) && item->isLocked())) { itemtree_map(f, &child, desktop); } } @@ -4409,9 +4410,9 @@ static void process_all(void (*f)(SPItem *, SPDesktop *), SPDesktop *dt, bool la SPObject *root; if (layer_only) { - root = dt->currentLayer(); + root = dt->layers->currentLayer(); } else { - root = dt->currentRoot(); + root = dt->layers->currentRoot(); } itemtree_map(f, root, dt); diff --git a/src/ui/contextmenu.cpp b/src/ui/contextmenu.cpp index 0e9c0d4941..ce41f30ddc 100644 --- a/src/ui/contextmenu.cpp +++ b/src/ui/contextmenu.cpp @@ -80,7 +80,9 @@ ContextMenu::ContextMenu(SPDesktop *desktop, SPItem *item) : Inkscape::Preferences *prefs = Inkscape::Preferences::get(); _show_icons = prefs->getInt("/theme/menuIcons_canvas", true); - auto layer = sp_item_get_layer(_object); + + auto group = dynamic_cast(_object); + auto layer = group->isLayer() ? group : nullptr; AppendItemFromVerb(Inkscape::Verb::get(SP_VERB_EDIT_UNDO)); AppendItemFromVerb(Inkscape::Verb::get(SP_VERB_EDIT_REDO)); @@ -186,13 +188,13 @@ Gtk::SeparatorMenuItem* ContextMenu::AddSeparator() void ContextMenu::EnterGroup(Gtk::MenuItem* mi) { - _desktop->setCurrentLayer(_MIGroup_group); + _desktop->layers->setCurrentLayer(_MIGroup_group); _desktop->selection->clear(); } void ContextMenu::LeaveGroup() { - _desktop->setCurrentLayer(_desktop->currentLayer()->parent); + _desktop->layers->setCurrentLayer(_desktop->layers->currentLayer()->parent); } void ContextMenu::LockSelected() @@ -320,7 +322,7 @@ void ContextMenu::AppendItemFromVerb(Inkscape::Verb *verb) void ContextMenu::MakeObjectMenu() { if (SP_IS_ITEM(_object)) { - MakeItemMenu(sp_item_get_layer(_object)); + MakeItemMenu(dynamic_cast(_object)); } if (SP_IS_GROUP(_object)) { @@ -344,7 +346,7 @@ void ContextMenu::MakeObjectMenu() } } -void ContextMenu::MakeItemMenu(SPGroup* layer) +void ContextMenu::MakeItemMenu(SPGroup* group) { Gtk::MenuItem* mi; @@ -370,7 +372,7 @@ void ContextMenu::MakeItemMenu(SPGroup* layer) // several options are not applicable to layers; adding them makes context menu unwieldy, // so we need to be selective, or else it grows too much - if (!layer) { + if (!group || !group->isLayer()) { mi = Gtk::manage(new Gtk::MenuItem(_("Select Same"))); mi->show(); Gtk::Menu *select_same_submenu = Gtk::manage(new Gtk::Menu()); @@ -426,7 +428,7 @@ void ContextMenu::MakeItemMenu(SPGroup* layer) mi->show(); append(*mi); - if (!layer) { + if (!group || !group->isLayer()) { /* Create link */ mi = Gtk::manage(new Gtk::MenuItem(_("Create _Link"), true)); mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ItemCreateLink)); @@ -544,7 +546,7 @@ void ContextMenu::ItemSelectThis() void ContextMenu::ItemMoveTo() { - Inkscape::UI::Dialogs::LayerPropertiesDialog::showMove(_desktop, _desktop->currentLayer()); + Inkscape::UI::Dialogs::LayerPropertiesDialog::showMove(_desktop, _desktop->layers->currentLayer()); } @@ -628,7 +630,7 @@ void ContextMenu::fireAction(unsigned int code) { // group and layer menu void ContextMenu::MakeGroupMenu(SPGroup* item) { - if (auto layer = sp_item_get_layer(item)) { + if (item->isLayer()) { // layer-specific commands AppendItemFromVerb(Inkscape::Verb::get(SP_VERB_LAYER_NEW)); AppendItemFromVerb(Inkscape::Verb::get(SP_VERB_LAYER_RENAME)); @@ -643,28 +645,30 @@ void ContextMenu::MakeGroupMenu(SPGroup* item) AddSeparator(); // transform layer into group - append_item(_("Layer to group"), false).connect([=]() { sp_group_layer_transform(_desktop->doc(), layer, SPGroup::GROUP); }); + append_item(_("Layer to group"), false).connect([=]() { sp_group_layer_transform(_desktop->doc(), item, SPGroup::GROUP); }); } - else if (auto group = sp_item_get_group(item)) { + else if (item->isGroup()) { /* Ungroup */ append_item(_("_Ungroup"), true).connect(sigc::mem_fun(*this, &ContextMenu::ActivateUngroup)); - if (auto parent = sp_item_get_layer(group->parent)) { + if (item->getParentGroup()->isLayer()) { // transform group into layer - append_item(_("Group to layer"), false).connect([=](){ sp_group_layer_transform(_desktop->doc(), group, SPGroup::LAYER); }); + append_item(_("Group to layer"), false).connect([=](){ sp_group_layer_transform(_desktop->doc(), item, SPGroup::LAYER); }); } // enter group - if (group != _desktop->currentLayer()) { - MIGroup.set_label(Glib::ustring::compose(_("Enter group %1"), group->defaultLabel())); - _MIGroup_group = group; + auto layer = _desktop->layers->currentLayer(); + if (item != layer) { + MIGroup.set_label(Glib::ustring::compose(_("Enter group %1"), item->defaultLabel())); + _MIGroup_group = item; MIGroup.signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &ContextMenu::EnterGroup),&MIGroup)); MIGroup.show(); append(MIGroup); } - if (_desktop->currentLayer() != _desktop->currentRoot()) { - if (_desktop->currentLayer()->parent != _desktop->currentRoot()) { + auto root = _desktop->layers->currentRoot(); + if (layer != root) { + if (layer->parent != root) { MIParent.signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::LeaveGroup)); MIParent.show(); append(MIParent); diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp index ccad82d9e4..c8bd0a3c0f 100644 --- a/src/ui/dialog/filter-effects-dialog.cpp +++ b/src/ui/dialog/filter-effects-dialog.cpp @@ -41,6 +41,7 @@ #include "filter-effects-dialog.h" #include "filter-enums.h" #include "inkscape.h" +#include "layer-model.h" #include "selection-chemistry.h" #include "verbs.h" @@ -1588,7 +1589,7 @@ void FilterEffectsDialog::FilterModifier::remove_filter() // Delete all references to this filter std::vector x,y; - std::vector all = get_all_items(x, desktop->currentRoot(), desktop, false, false, true, y); + std::vector all = get_all_items(x, desktop->layers->currentRoot(), desktop, false, false, true, y); for(std::vector::const_iterator i=all.begin(); all.end() != i; ++i) { if (!SP_IS_ITEM(*i)) { continue; @@ -1647,7 +1648,7 @@ void FilterEffectsDialog::FilterModifier::select_filter_elements() std::vector x,y; std::vector items; - std::vector all = get_all_items(x, desktop->currentRoot(), desktop, false, false, true, y); + std::vector all = get_all_items(x, desktop->layers->currentRoot(), desktop, false, false, true, y); for(SPItem *item: all) { if (!item->style) { continue; diff --git a/src/ui/dialog/find.cpp b/src/ui/dialog/find.cpp index 15ced4c018..7885836fc2 100644 --- a/src/ui/dialog/find.cpp +++ b/src/ui/dialog/find.cpp @@ -21,6 +21,7 @@ #include "document-undo.h" #include "document.h" #include "inkscape.h" +#include "layer-model.h" #include "message-stack.h" #include "selection-chemistry.h" #include "text-editing.h" @@ -843,7 +844,7 @@ bool Find::item_type_match (SPItem *item) return (all || check_texts.get_active()); } else if (dynamic_cast(item) && - !getDesktop()->isLayer(item)) { // never select layers! + !getDesktop()->layers->isLayer(item)) { // never select layers! return (all || check_groups.get_active()); } else if (dynamic_cast(item)) { @@ -894,7 +895,7 @@ std::vector &Find::all_items (SPObject *r, std::vector &l, boo auto desktop = getDesktop(); for (auto& child: r->children) { SPItem *item = dynamic_cast(&child); - if (item && !child.cloned && !desktop->isLayer(item)) { + if (item && !child.cloned && !desktop->layers->isLayer(item)) { if ((hidden || !desktop->itemIsHidden(item)) && (locked || !item->isLocked())) { l.insert(l.begin(),(SPItem*)&child); } @@ -912,7 +913,7 @@ std::vector &Find::all_selection_items (Inkscape::Selection *s, std::ve SPObject *obj = *i; SPItem *item = dynamic_cast(obj); g_assert(item != nullptr); - if (item && !item->cloned && !desktop->isLayer(item)) { + if (item && !item->cloned && !desktop->layers->isLayer(item)) { if (!ancestor || ancestor->isAncestorOf(item)) { if ((hidden || !desktop->itemIsHidden(item)) && (locked || !item->isLocked())) { l.push_back(*i); @@ -966,13 +967,13 @@ void Find::onAction() std::vector l; if (check_scope_selection.get_active()) { if (check_scope_layer.get_active()) { - l = all_selection_items (desktop->selection, l, desktop->currentLayer(), hidden, locked); + l = all_selection_items (desktop->selection, l, desktop->layers->currentLayer(), hidden, locked); } else { l = all_selection_items (desktop->selection, l, nullptr, hidden, locked); } } else { if (check_scope_layer.get_active()) { - l = all_items (desktop->currentLayer(), l, hidden, locked); + l = all_items (desktop->layers->currentLayer(), l, hidden, locked); } else { l = all_items(desktop->getDocument()->getRoot(), l, hidden, locked); } diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp index 070284d9f4..da30e5e5c9 100644 --- a/src/ui/dialog/icon-preview.cpp +++ b/src/ui/dialog/icon-preview.cpp @@ -342,7 +342,7 @@ void IconPreviewPanel::refreshPreview() } } } else { - target = getDesktop()->currentRoot(); + target = getDesktop()->getDocument()->getRoot(); } if (target) { renderPreview(target); diff --git a/src/ui/dialog/layer-properties.cpp b/src/ui/dialog/layer-properties.cpp index 45c8e4cf38..93565f1b56 100644 --- a/src/ui/dialog/layer-properties.cpp +++ b/src/ui/dialog/layer-properties.cpp @@ -23,6 +23,7 @@ #include "document.h" #include "document-undo.h" #include "layer-manager.h" +#include "layer-model.h" #include "message-stack.h" #include "preferences.h" @@ -139,7 +140,7 @@ LayerPropertiesDialog::_close() void LayerPropertiesDialog::_setup_position_controls() { - if ( nullptr == _layer || _desktop->currentRoot() == _layer ) { + if ( nullptr == _layer || _desktop->getDocument()->getRoot() == _layer ) { // no layers yet, so option above/below/sublayer is useless return; } @@ -222,7 +223,7 @@ LayerPropertiesDialog::_setup_layers_controls() { SPDocument* document = _desktop->doc(); SPRoot* root = document->getRoot(); if ( root ) { - SPObject* target = _desktop->currentLayer(); + SPObject* target = _desktop->layers->currentLayer(); _store->clear(); _addLayer( document, root, nullptr, target, 0 ); } @@ -323,7 +324,7 @@ void LayerPropertiesDialog::_prepareLabelRenderer( void LayerPropertiesDialog::Rename::setup(LayerPropertiesDialog &dialog) { SPDesktop *desktop=dialog._desktop; dialog.set_title(_("Rename Layer")); - gchar const *name = desktop->currentLayer()->label(); + gchar const *name = desktop->layers->currentLayer()->label(); dialog._layer_name_entry.set_text(( name ? name : _("Layer") )); dialog._apply_button.set_label(_("_Rename")); } @@ -333,7 +334,7 @@ void LayerPropertiesDialog::Rename::perform(LayerPropertiesDialog &dialog) { Glib::ustring name(dialog._layer_name_entry.get_text()); if (name.empty()) return; - desktop->layer_manager->renameLayer( desktop->currentLayer(), + desktop->layer_manager->renameLayer( desktop->layers->currentLayer(), (gchar *)name.c_str(), FALSE ); @@ -347,7 +348,7 @@ void LayerPropertiesDialog::Create::setup(LayerPropertiesDialog &dialog) { // Set the initial name to the "next available" layer name LayerManager *mgr = dialog._desktop->layer_manager; - Glib::ustring newName = mgr->getNextLayerName(nullptr, dialog._desktop->currentLayer()->label()); + Glib::ustring newName = mgr->getNextLayerName(nullptr, dialog._desktop->layers->currentLayer()->label()); dialog._layer_name_entry.set_text(newName.c_str()); dialog._apply_button.set_label(_("_Add")); dialog._setup_position_controls(); @@ -367,13 +368,14 @@ void LayerPropertiesDialog::Create::perform(LayerPropertiesDialog &dialog) { if (name.empty()) return; - SPObject *new_layer=Inkscape::create_layer(desktop->currentRoot(), dialog._layer, position); + auto root = desktop->getDocument()->getRoot(); + SPObject *new_layer=Inkscape::create_layer(root, dialog._layer, position); if (!name.empty()) { desktop->layer_manager->renameLayer( new_layer, (gchar *)name.c_str(), TRUE ); } desktop->getSelection()->clear(); - desktop->setCurrentLayer(new_layer); + desktop->layers->setCurrentLayer(new_layer); DocumentUndo::done(desktop->getDocument(), SP_VERB_LAYER_NEW, _("Add layer")); desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("New layer created.")); } diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp index c32017c16e..230a43a075 100644 --- a/src/ui/dialog/layers.cpp +++ b/src/ui/dialog/layers.cpp @@ -24,6 +24,7 @@ #include "inkscape.h" #include "layer-fns.h" #include "layer-manager.h" +#include "layer-model.h" #include "selection-chemistry.h" #include "verbs.h" @@ -186,8 +187,8 @@ bool LayersPanel::_executeAction() if ( _pending && ( (_pending->_actionCode == BUTTON_NEW || _pending->_actionCode == DRAGNDROP) - || !( (desktop && desktop->currentLayer()) - && (desktop->currentLayer() != _pending->_target) + || !( (desktop && desktop->layers->currentLayer()) + && (desktop->layers->currentLayer() != _pending->_target) ) ) ) { @@ -364,7 +365,7 @@ void LayersPanel::_layersChanged() _selectedConnection.block(); auto desktop = getDesktop(); if (desktop->layer_manager && desktop->layer_manager->includes( root ) ) { - SPObject* target = desktop->currentLayer(); + SPObject* target = desktop->layers->currentLayer(); _store->clear(); #if DUMP_LAYERS @@ -427,10 +428,10 @@ SPObject* LayersPanel::_selectedLayer() void LayersPanel::_pushTreeSelectionToCurrent() { auto desktop = getDesktop(); - if (desktop && desktop->layer_manager && desktop->currentRoot() ) { + if (desktop && desktop->layer_manager && desktop->layers->currentRoot() ) { SPObject* inTree = _selectedLayer(); if ( inTree ) { - SPObject* curr = desktop->currentLayer(); + SPObject* curr = desktop->layers->currentLayer(); if (curr != inTree) { desktop->layer_manager->setCurrentLayer(inTree); } @@ -579,10 +580,10 @@ bool LayersPanel::_handleButtonEvent(GdkEventButton* event) Gtk::TreeModel::Row row = *iter; SPObject *obj = row[_model->_colObject]; if (col == _tree.get_column(COL_VISIBLE - 1)) { - desktop->toggleLayerSolo( obj ); + desktop->layers->toggleLayerSolo( obj ); DocumentUndo::maybeDone(document, "layer:solo", SP_VERB_LAYER_SOLO, _("Toggle layer solo")); } else if (col == _tree.get_column(COL_LOCKED - 1)) { - desktop->toggleLockOtherLayers(obj); + desktop->layers->toggleLockOtherLayers(obj); DocumentUndo::maybeDone(document, "layer:lockothers", SP_VERB_LAYER_LOCK_OTHERS, _("Lock other layers")); } } diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index 564b43bb41..daa12d37ca 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -31,6 +31,7 @@ #include "filter-chemistry.h" #include "inkscape.h" #include "layer-manager.h" +#include "layer-model.h" #include "verbs.h" #include "actions/actions-tools.h" @@ -852,7 +853,7 @@ void ObjectsPanel::desktopReplaced() layer_changed.disconnect(); if (auto desktop = getDesktop()) { - layer_changed = desktop->connectCurrentLayerChanged( sigc::mem_fun(*this, &ObjectsPanel::layerChanged)); + layer_changed = desktop->layer_manager->connectCurrentLayerChanged( sigc::mem_fun(*this, &ObjectsPanel::layerChanged)); } } @@ -872,7 +873,7 @@ void ObjectsPanel::setRootWatcher() Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool layers_only = prefs->getBool("/dialogs/objects/layers_only", true); root_watcher = new ObjectWatcher(this, document->getRoot(), nullptr, layers_only); - layerChanged(getDesktop()->currentLayer()); + layerChanged(getDesktop()->layers->currentLayer()); } } @@ -954,7 +955,7 @@ bool ObjectsPanel::toggleVisible(GdkEventButton* event, Gtk::TreeModel::Row row) if (event->state & GDK_SHIFT_MASK) { // Toggle Visible for layers (hide all other layers) if (auto desktop = getDesktop()) { - desktop->toggleLayerSolo(item); + desktop->layers->toggleLayerSolo(item); DocumentUndo::done(desktop->getDocument(), SP_VERB_LAYER_SOLO, _("Toggle layer solo")); } } else { @@ -975,7 +976,7 @@ bool ObjectsPanel::toggleLocked(GdkEventButton* event, Gtk::TreeModel::Row row) if (event->state & GDK_SHIFT_MASK) { // Toggle lock for layers (lock all other layers) if (auto desktop = getDesktop()) { - desktop->toggleLockOtherLayers(item); + desktop->layers->toggleLockOtherLayers(item); DocumentUndo::done(desktop->getDocument(), SP_VERB_LAYER_LOCK_OTHERS, _("Lock other layers")); } } else { @@ -1106,9 +1107,9 @@ bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event) } else if (group && group->layerMode() == SPGroup::LAYER) { // if right-clicking on a layer, make it current for context menu actions to work correctly if (context_menu) { - if (getDesktop()->currentLayer() != item) { + if (getDesktop()->layers->currentLayer() != item) { selection->clear(); - getDesktop()->setCurrentLayer(item); + getDesktop()->layers->setCurrentLayer(item); } } // Clicking on layers firstly switches to that layer. @@ -1116,7 +1117,7 @@ bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event) selection->clear(); } else if (_layer != item) { selection->clear(); - getDesktop()->setCurrentLayer(item); + getDesktop()->layers->setCurrentLayer(item); } else { selection->set(item); } diff --git a/src/ui/dialog/spellcheck.cpp b/src/ui/dialog/spellcheck.cpp index b2eebc0a59..acd9d0e789 100644 --- a/src/ui/dialog/spellcheck.cpp +++ b/src/ui/dialog/spellcheck.cpp @@ -24,6 +24,7 @@ #include "document.h" #include "inkscape.h" #include "message-stack.h" +#include "layer-model.h" #include "selection-chemistry.h" #include "text-editing.h" #include "verbs.h" @@ -239,11 +240,13 @@ void SpellCheck::allTextItems (SPObject *r, std::vector &l, bool hidde if (auto desktop = getDesktop()) { for (auto& child: r->children) { - if (SP_IS_ITEM (&child) && !child.cloned && !desktop->isLayer(SP_ITEM(&child))) { - if ((hidden || !desktop->itemIsHidden(SP_ITEM(&child))) && (locked || !SP_ITEM(&child)->isLocked())) { - if (SP_IS_TEXT(&child) || SP_IS_FLOWTEXT(&child)) - l.push_back(static_cast(&child)); + if (auto item = dynamic_cast(&child)) { + if (!child.cloned && !desktop->layers->isLayer(item)) { + if ((hidden || !desktop->itemIsHidden(item)) && (locked || !item->isLocked())) { + if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) + l.push_back(item); } + } } allTextItems (&child, l, hidden, locked); } diff --git a/src/ui/dialog/xml-tree.cpp b/src/ui/dialog/xml-tree.cpp index bbf9db89dc..b4a8ced43a 100644 --- a/src/ui/dialog/xml-tree.cpp +++ b/src/ui/dialog/xml-tree.cpp @@ -27,6 +27,7 @@ #include "document-undo.h" #include "document.h" #include "inkscape.h" +#include "layer-model.h" #include "message-context.h" #include "message-stack.h" #include "verbs.h" @@ -457,10 +458,10 @@ void XmlTree::set_dt_select(Inkscape::XML::Node *repr) if (!object || !in_dt_coordsys(*object)) { // object not on canvas } else if (isRealLayer(object)) { - getDesktop()->setCurrentLayer(object); + getDesktop()->layers->setCurrentLayer(object); } else { if (SP_IS_GROUP(object->parent)) { - getDesktop()->setCurrentLayer(object->parent); + getDesktop()->layers->setCurrentLayer(object->parent); } getSelection()->set(SP_ITEM(object)); diff --git a/src/ui/drag-and-drop.cpp b/src/ui/drag-and-drop.cpp index c99bd0f4f5..d0338b7fdd 100644 --- a/src/ui/drag-and-drop.cpp +++ b/src/ui/drag-and-drop.cpp @@ -24,6 +24,7 @@ #include "selection.h" #include "style.h" #include "verbs.h" +#include "layer-model.h" #include "extension/db.h" #include "extension/find_extension_by_mime.h" @@ -311,7 +312,7 @@ ink_drag_data_received(GtkWidget *widget, // Greg's edits to add intelligent positioning of svg drops SPObject *new_obj = nullptr; - new_obj = desktop->currentLayer()->appendChildRepr(newgroup); + new_obj = desktop->layers->currentLayer()->appendChildRepr(newgroup); Inkscape::Selection *selection = desktop->getSelection(); selection->set(SP_ITEM(new_obj)); diff --git a/src/ui/toolbar/connector-toolbar.cpp b/src/ui/toolbar/connector-toolbar.cpp index af7eaa13e1..bd21b3cbbf 100644 --- a/src/ui/toolbar/connector-toolbar.cpp +++ b/src/ui/toolbar/connector-toolbar.cpp @@ -39,6 +39,7 @@ #include "graphlayout.h" #include "selection.h" #include "verbs.h" +#include "layer-model.h" #include "object/sp-namedview.h" #include "object/sp-path.h" @@ -326,7 +327,7 @@ ConnectorToolbar::spacing_changed() bool modmade = false; std::vector items; - items = get_avoided_items(items, _desktop->currentRoot(), _desktop); + items = get_avoided_items(items, _desktop->layers->currentRoot(), _desktop); for (auto item : items) { Geom::Affine m = Geom::identity(); avoid_item_move(&m, item); diff --git a/src/ui/tools/arc-tool.cpp b/src/ui/tools/arc-tool.cpp index 92b247fd98..70f3f364c4 100644 --- a/src/ui/tools/arc-tool.cpp +++ b/src/ui/tools/arc-tool.cpp @@ -326,9 +326,10 @@ void ArcTool::drag(Geom::Point pt, guint state) { // Set style sp_desktop_apply_style_tool(desktop, repr, "/tools/shapes/arc", false); - this->arc = SP_GENERICELLIPSE(desktop->currentLayer()->appendChildRepr(repr)); + auto layer = currentLayer(); + this->arc = SP_GENERICELLIPSE(layer->appendChildRepr(repr)); Inkscape::GC::release(repr); - this->arc->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + this->arc->transform = layer->i2doc_affine().inverse(); this->arc->updateRepr(); forced_redraws_start(5); diff --git a/src/ui/tools/box3d-tool.cpp b/src/ui/tools/box3d-tool.cpp index c669d45605..171c521a67 100644 --- a/src/ui/tools/box3d-tool.cpp +++ b/src/ui/tools/box3d-tool.cpp @@ -481,7 +481,7 @@ void Box3dTool::drag(guint /*state*/) { } // Create object - SPBox3D *box3d = SPBox3D::createBox3D((SPItem*)desktop->currentLayer()); + SPBox3D *box3d = SPBox3D::createBox3D(currentLayer()); // Set style desktop->applyCurrentOrToolStyle(box3d, "/tools/shapes/3dbox", false); diff --git a/src/ui/tools/calligraphic-tool.cpp b/src/ui/tools/calligraphic-tool.cpp index 0b1a5724a7..23ab84ac70 100644 --- a/src/ui/tools/calligraphic-tool.cpp +++ b/src/ui/tools/calligraphic-tool.cpp @@ -927,9 +927,10 @@ void CalligraphicTool::set_to_accumulated(bool unionize, bool subtract) { this->repr = repr; - SPItem *item=SP_ITEM(desktop->currentLayer()->appendChildRepr(this->repr)); + auto layer = currentLayer(); + SPItem *item=SP_ITEM(layer->appendChildRepr(this->repr)); Inkscape::GC::release(this->repr); - item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + item->transform = layer->i2doc_affine().inverse(); item->updateRepr(); } diff --git a/src/ui/tools/connector-tool.cpp b/src/ui/tools/connector-tool.cpp index 6bfd96194e..069d989505 100644 --- a/src/ui/tools/connector-tool.cpp +++ b/src/ui/tools/connector-tool.cpp @@ -887,8 +887,9 @@ void ConnectorTool::_flushWhite(SPCurve *c) repr->setAttribute("d", sp_svg_write_path(c->get_pathvector())); /* Attach repr */ - this->newconn = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr)); - this->newconn->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + auto layer = currentLayer(); + this->newconn = SP_ITEM(layer->appendChildRepr(repr)); + this->newconn->transform = layer->i2doc_affine().inverse(); bool connection = false; this->newconn->setAttribute( "inkscape:connector-type", diff --git a/src/ui/tools/eraser-tool.cpp b/src/ui/tools/eraser-tool.cpp index 62b6e1ffdb..7fd0c7db57 100644 --- a/src/ui/tools/eraser-tool.cpp +++ b/src/ui/tools/eraser-tool.cpp @@ -644,7 +644,7 @@ void EraserTool::set_to_accumulated() { this->repr = repr; } - SPObject * top_layer = desktop->currentRoot(); + SPObject * top_layer = desktop->layers->currentRoot(); SPItem *item_repr = SP_ITEM(top_layer->appendChildRepr(this->repr)); Inkscape::GC::release(this->repr); item_repr->updateRepr(); diff --git a/src/ui/tools/flood-tool.cpp b/src/ui/tools/flood-tool.cpp index d0c4fa934e..d9b940957a 100644 --- a/src/ui/tools/flood-tool.cpp +++ b/src/ui/tools/flood-tool.cpp @@ -34,6 +34,7 @@ #include "desktop.h" #include "document-undo.h" #include "document.h" +#include "layer-model.h" #include "message-context.h" #include "message-stack.h" #include "rubberband.h" @@ -447,14 +448,15 @@ static void do_trace(bitmap_coords_info bci, guchar *trace_px, SPDesktop *deskto g_free(str); } - desktop->currentLayer()->addChild(pathRepr,nullptr); + auto layer = desktop->layers->currentLayer(); + layer->addChild(pathRepr, nullptr); SPObject *reprobj = document->getObjectByRepr(pathRepr); if (reprobj) { SP_ITEM(reprobj)->doWriteTransform(transform); // premultiply the item transform by the accumulated parent transform in the paste layer - Geom::Affine local (SP_GROUP(desktop->currentLayer())->i2doc_affine()); + Geom::Affine local (layer->i2doc_affine()); if (!local.isIdentity()) { gchar const *t_str = pathRepr->attribute("transform"); Geom::Affine item_t (Geom::identity()); diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp index e6b01b85f0..7d4fd3e47d 100644 --- a/src/ui/tools/freehand-base.cpp +++ b/src/ui/tools/freehand-base.cpp @@ -909,20 +909,21 @@ static void spdc_flush_white(FreehandBase *dc, SPCurve *gc) else repr->setAttribute("d", str); + auto layer = dc->currentLayer(); if (SP_IS_PENCIL_CONTEXT(dc) && dc->tablet_enabled) { if (!dc->white_item) { - dc->white_item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr)); + dc->white_item = SP_ITEM(layer->appendChildRepr(repr)); } spdc_check_for_and_apply_waiting_LPE(dc, dc->white_item, c.get(), false); } if (!dc->white_item) { // Attach repr - SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr)); + SPItem *item = SP_ITEM(layer->appendChildRepr(repr)); dc->white_item = item; //Bend needs the transforms applied after, Other effects best before spdc_check_for_and_apply_waiting_LPE(dc, item, c.get(), true); Inkscape::GC::release(repr); - item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + item->transform = layer->i2doc_affine().inverse(); item->updateRepr(); item->doWriteTransform(item->transform, nullptr, true); spdc_check_for_and_apply_waiting_LPE(dc, item, c.get(), false); @@ -1025,8 +1026,9 @@ void spdc_create_single_dot(ToolBase *ec, Geom::Point const &pt, char const *too Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); repr->setAttribute("sodipodi:type", "arc"); - SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr)); - item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + auto layer = ec->currentLayer(); + SPItem *item = SP_ITEM(layer->appendChildRepr(repr)); + item->transform = layer->i2doc_affine().inverse(); Inkscape::GC::release(repr); // apply the tool's current style diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp index cf2bfb4f81..a0083a310a 100644 --- a/src/ui/tools/measure-tool.cpp +++ b/src/ui/tools/measure-tool.cpp @@ -28,6 +28,7 @@ #include "desktop.h" #include "document-undo.h" #include "inkscape.h" +#include "layer-model.h" #include "path-chemistry.h" #include "rubberband.h" #include "text-editing.h" @@ -199,7 +200,8 @@ void setMeasureItem(Geom::PathVector pathv, bool is_curve, bool markers, guint32 repr = xml_doc->createElement("svg:path"); auto str = sp_svg_write_path(pathv); SPCSSAttr *css = sp_repr_css_attr_new(); - Geom::Coord strokewidth = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse().expansionX(); + auto layer = desktop->layers->currentLayer(); + Geom::Coord strokewidth = layer->i2doc_affine().inverse().expansionX(); std::stringstream stroke_width; stroke_width.imbue(std::locale::classic()); if(measure_repr) { @@ -239,7 +241,7 @@ void setMeasureItem(Geom::PathVector pathv, bool is_curve, bool markers, guint32 measure_repr->addChild(repr, nullptr); Inkscape::GC::release(repr); } else { - SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr)); + SPItem *item = SP_ITEM(layer->appendChildRepr(repr)); Inkscape::GC::release(repr); item->updateRepr(); desktop->getSelection()->clear(); @@ -349,7 +351,8 @@ void createAngleDisplayCurve(SPDesktop *desktop, path.start(desktop->doc2dt(p1)); path.appendNew(desktop->doc2dt(p2),desktop->doc2dt(p3),desktop->doc2dt(p4)); pathv.push_back(path); - pathv *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + auto layer = desktop->layers->currentLayer(); + pathv *= layer->i2doc_affine().inverse(); if(!pathv.empty()) { setMeasureItem(pathv, true, false, 0xff00007f, measure_repr); } @@ -765,7 +768,8 @@ void MeasureTool::toGuides() } setGuide(start,ray.angle(), _("Measure")); if(explicit_base) { - explicit_base = *explicit_base * SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + auto layer = desktop->layers->currentLayer(); + explicit_base = *explicit_base * layer->i2doc_affine().inverse(); ray.setPoints(start, *explicit_base); if(ray.angle() != 0) { setGuide(start,ray.angle(), _("Base")); @@ -816,7 +820,7 @@ void MeasureTool::toItem() Inkscape::XML::Node *rgroup = xml_doc->createElement("svg:g"); showCanvasItems(false, true, false, rgroup); setLine(start_p,end_p, false, line_color_primary, rgroup); - SPItem *measure_item = SP_ITEM(desktop->currentLayer()->appendChildRepr(rgroup)); + SPItem *measure_item = SP_ITEM(desktop->layers->currentLayer()->appendChildRepr(rgroup)); Inkscape::GC::release(rgroup); measure_item->updateRepr(); doc->ensureUpToDate(); @@ -919,7 +923,7 @@ void MeasureTool::setLine(Geom::Point start_point,Geom::Point end_point, bool ma path.start(desktop->doc2dt(start_point)); path.appendNew(desktop->doc2dt(end_point)); pathv.push_back(path); - pathv *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + pathv *= desktop->layers->currentLayer()->i2doc_affine().inverse(); if(!pathv.empty()) { setMeasureItem(pathv, false, markers, color, measure_repr); } @@ -939,7 +943,7 @@ void MeasureTool::setPoint(Geom::Point origin, Inkscape::XML::Node *measure_repr pathv *= scale; pathv *= Geom::Translate(Geom::Point() - (scale.vector() * 0.5)); pathv *= Geom::Translate(desktop->doc2dt(origin)); - pathv *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + pathv *= desktop->layers->currentLayer()->i2doc_affine().inverse(); if (!pathv.empty()) { guint32 line_color_secondary = 0xff0000ff; setMeasureItem(pathv, false, false, line_color_secondary, measure_repr); @@ -1004,7 +1008,8 @@ void MeasureTool::setLabelText(Glib::ustring const &value, Geom::Point pos, doub Inkscape::XML::Node *rstring = xml_doc->createTextNode(value.c_str()); rtspan->addChild(rstring, nullptr); Inkscape::GC::release(rstring); - SPItem *text_item = SP_ITEM(desktop->currentLayer()->appendChildRepr(rtext)); + auto layer = desktop->layers->currentLayer(); + SPItem *text_item = SP_ITEM(layer->appendChildRepr(rtext)); Inkscape::GC::release(rtext); text_item->updateRepr(); Geom::OptRect bbox = text_item->geometricBounds(); @@ -1040,7 +1045,7 @@ void MeasureTool::setLabelText(Glib::ustring const &value, Geom::Point pos, doub Inkscape::GC::release(rtextitem); rgroup->addChild(rrect, nullptr); Inkscape::GC::release(rrect); - SPItem *text_item_box = SP_ITEM(desktop->currentLayer()->appendChildRepr(rgroup)); + SPItem *text_item_box = SP_ITEM(layer->appendChildRepr(rgroup)); Geom::Scale scale = Geom::Scale(desktop->current_zoom()).inverse(); if(bbox && text_anchor == Inkscape::CANVAS_ITEM_TEXT_ANCHOR_CENTER) { text_item_box->transform *= Geom::Translate(bbox->midpoint() - Geom::Point(1.0,1.0)).inverse(); @@ -1048,7 +1053,7 @@ void MeasureTool::setLabelText(Glib::ustring const &value, Geom::Point pos, doub text_item_box->transform *= scale; text_item_box->transform *= Geom::Translate(Geom::Point() - (scale.vector() * 0.5)); text_item_box->transform *= Geom::Translate(pos); - text_item_box->transform *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + text_item_box->transform *= layer->i2doc_affine().inverse(); text_item_box->updateRepr(); text_item_box->doWriteTransform(text_item_box->transform, nullptr, true); Inkscape::XML::Node *rlabel = text_item_box->getRepr(); @@ -1058,7 +1063,7 @@ void MeasureTool::setLabelText(Glib::ustring const &value, Geom::Point pos, doub } else { text_item->transform *= Geom::Rotate(angle); text_item->transform *= Geom::Translate(pos); - text_item->transform *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + text_item->transform *= layer->i2doc_affine().inverse(); text_item->doWriteTransform(text_item->transform, nullptr, true); } } @@ -1326,10 +1331,10 @@ void MeasureTool::showCanvasItems(bool to_guides, bool to_item, bool to_phantom, Geom::Rect rect(start_p_doc, end_p_doc); items = doc->getItemsPartiallyInBox(desktop->dkey, rect, false, true, false, true); Inkscape::LayerModel *layer_model = nullptr; - SPObject *current_layer = nullptr; + SPGroup *current_layer = nullptr; if(desktop){ layer_model = desktop->layers; - current_layer = desktop->currentLayer(); + current_layer = desktop->layers->currentLayer(); } std::vector intersection_times; bool only_selected = prefs->getBool("/tools/measure/only_selected", false); diff --git a/src/ui/tools/pen-tool.cpp b/src/ui/tools/pen-tool.cpp index 87a4ddfd1a..23848a6588 100644 --- a/src/ui/tools/pen-tool.cpp +++ b/src/ui/tools/pen-tool.cpp @@ -1253,7 +1253,7 @@ void PenTool::_bsplineSpiroColor() this->red_color = 0xff000000; this->green_color = 0x00ff0000; } else if(this->bspline) { - this->highlight_color = SP_ITEM(this->desktop->currentLayer())->highlight_color(); + this->highlight_color = currentLayer()->highlight_color(); if((unsigned int)prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff) == this->highlight_color){ this->green_color = 0xff00007f; this->red_color = 0xff00007f; @@ -1262,7 +1262,7 @@ void PenTool::_bsplineSpiroColor() this->red_color = this->highlight_color; } } else { - this->highlight_color = SP_ITEM(this->desktop->currentLayer())->highlight_color(); + this->highlight_color = currentLayer()->highlight_color(); this->red_color = 0xff00007f; if((unsigned int)prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff) == this->highlight_color){ this->green_color = 0x00ff007f; diff --git a/src/ui/tools/pencil-tool.cpp b/src/ui/tools/pencil-tool.cpp index efedcbe0e7..7adcdd0b84 100644 --- a/src/ui/tools/pencil-tool.cpp +++ b/src/ui/tools/pencil-tool.cpp @@ -717,7 +717,7 @@ void PencilTool::addPowerStrokePencil() curvepressure->curveto(b[4 * c + 1], b[4 * c + 2], b[4 * c + 3]); } } - Geom::Affine transform_coordinate = SP_ITEM(desktop->currentLayer())->i2dt_affine().inverse(); + Geom::Affine transform_coordinate = currentLayer()->i2dt_affine().inverse(); curvepressure->transform(transform_coordinate); Geom::Path path = curvepressure->get_pathvector()[0]; @@ -729,7 +729,7 @@ void PencilTool::addPowerStrokePencil() pp->setAttribute("id", "power_stroke_preview"); Inkscape::GC::release(pp); - SPShape *powerpreview = SP_SHAPE(SP_ITEM(desktop->currentLayer())->appendChildRepr(pp)); + SPShape *powerpreview = SP_SHAPE(currentLayer()->appendChildRepr(pp)); SPLPEItem *lpeitem = dynamic_cast(powerpreview); if (!lpeitem) { return; @@ -1173,7 +1173,8 @@ void PencilTool::_fitAndSplit() { /// \todo fixme: - this->highlight_color = SP_ITEM(this->desktop->currentLayer())->highlight_color(); + auto layer = desktop->layers->currentLayer(); + this->highlight_color = layer->highlight_color(); if((unsigned int)prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff) == this->highlight_color){ this->green_color = 0x00ff007f; } else { diff --git a/src/ui/tools/rect-tool.cpp b/src/ui/tools/rect-tool.cpp index 3a976cac02..bace19df23 100644 --- a/src/ui/tools/rect-tool.cpp +++ b/src/ui/tools/rect-tool.cpp @@ -360,10 +360,10 @@ void RectTool::drag(Geom::Point const pt, guint state) { // Set style sp_desktop_apply_style_tool (desktop, repr, "/tools/shapes/rect", false); - this->rect = SP_RECT(desktop->currentLayer()->appendChildRepr(repr)); + this->rect = SP_RECT(currentLayer()->appendChildRepr(repr)); Inkscape::GC::release(repr); - this->rect->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + this->rect->transform = currentLayer()->i2doc_affine().inverse(); this->rect->updateRepr(); forced_redraws_start(5); diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp index 49a0221cd6..72656ecd2f 100644 --- a/src/ui/tools/select-tool.cpp +++ b/src/ui/tools/select-tool.cpp @@ -30,6 +30,7 @@ #include "document-undo.h" #include "document.h" #include "include/macros.h" +#include "layer-model.h" #include "message-stack.h" #include "rubberband.h" #include "selection-chemistry.h" @@ -231,8 +232,7 @@ sp_select_context_up_one_layer(SPDesktop *desktop) * document), we might consider further restricting the below to disallow * leaving a layer to go to a non-layer. */ - SPObject *const current_layer = desktop->currentLayer(); - if (current_layer) { + if (SPObject *const current_layer = desktop->layers->currentLayer()) { SPObject *const parent = current_layer->parent; SPGroup *current_group = dynamic_cast(current_layer); if ( parent @@ -240,7 +240,7 @@ sp_select_context_up_one_layer(SPDesktop *desktop) || !( current_group && ( SPGroup::LAYER == current_group->layerMode() ) ) ) ) { - desktop->setCurrentLayer(parent); + desktop->layers->setCurrentLayer(parent); if (current_group && (SPGroup::LAYER != current_group->layerMode())) { desktop->getSelection()->set(current_layer); } @@ -469,7 +469,7 @@ bool SelectTool::root_handler(GdkEvent* event) { SPItem *clicked_item = selection->items().front(); if (dynamic_cast(clicked_item) && !dynamic_cast(clicked_item)) { // enter group if it's not a 3D box - desktop->setCurrentLayer(clicked_item); + desktop->layers->setCurrentLayer(clicked_item); desktop->getSelection()->clear(); this->dragging = false; sp_event_context_discard_delayed_snap_event(this); @@ -1080,7 +1080,7 @@ bool SelectTool::root_handler(GdkEvent* event) { SPItem *clicked_item = selection->singleItem(); SPGroup *clickedGroup = dynamic_cast(clicked_item); if ( (clickedGroup && (clickedGroup->layerMode() != SPGroup::LAYER)) || dynamic_cast(clicked_item)) { // enter group or a 3D box - desktop->setCurrentLayer(clicked_item); + desktop->layers->setCurrentLayer(clicked_item); desktop->getSelection()->clear(); } else { this->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Selected object is not a group. Cannot enter.")); diff --git a/src/ui/tools/spiral-tool.cpp b/src/ui/tools/spiral-tool.cpp index 65fd2dee75..9294e89c16 100644 --- a/src/ui/tools/spiral-tool.cpp +++ b/src/ui/tools/spiral-tool.cpp @@ -331,9 +331,9 @@ void SpiralTool::drag(Geom::Point const &p, guint state) { // Set style sp_desktop_apply_style_tool(desktop, repr, "/tools/shapes/spiral", false); - this->spiral = SP_SPIRAL(desktop->currentLayer()->appendChildRepr(repr)); + this->spiral = SP_SPIRAL(currentLayer()->appendChildRepr(repr)); Inkscape::GC::release(repr); - this->spiral->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + this->spiral->transform = currentLayer()->i2doc_affine().inverse(); this->spiral->updateRepr(); forced_redraws_start(5); diff --git a/src/ui/tools/star-tool.cpp b/src/ui/tools/star-tool.cpp index e5b460a2a1..ed23ae3a82 100644 --- a/src/ui/tools/star-tool.cpp +++ b/src/ui/tools/star-tool.cpp @@ -346,10 +346,10 @@ void StarTool::drag(Geom::Point p, guint state) // Set style sp_desktop_apply_style_tool(desktop, repr, "/tools/shapes/star", false); - this->star = SP_STAR(desktop->currentLayer()->appendChildRepr(repr)); + this->star = SP_STAR(currentLayer()->appendChildRepr(repr)); Inkscape::GC::release(repr); - this->star->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + this->star->transform = currentLayer()->i2doc_affine().inverse(); this->star->updateRepr(); forced_redraws_start(5); diff --git a/src/ui/tools/text-tool.cpp b/src/ui/tools/text-tool.cpp index fe30282101..53b813b271 100644 --- a/src/ui/tools/text-tool.cpp +++ b/src/ui/tools/text-tool.cpp @@ -350,12 +350,12 @@ static void sp_text_context_setup_text(TextTool *tc) Inkscape::XML::Node *rstring = xml_doc->createTextNode(""); rtspan->addChild(rstring, nullptr); Inkscape::GC::release(rstring); - SPItem *text_item = SP_ITEM(desktop->currentLayer()->appendChildRepr(rtext)); + SPItem *text_item = SP_ITEM(tc->currentLayer()->appendChildRepr(rtext)); /* fixme: Is selection::changed really immediate? */ /* yes, it's immediate .. why does it matter? */ desktop->getSelection()->set(text_item); Inkscape::GC::release(rtext); - text_item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + text_item->transform = tc->currentLayer()->i2doc_affine().inverse(); text_item->updateRepr(); text_item->doWriteTransform(text_item->transform, nullptr, true); diff --git a/src/ui/tools/tool-base.cpp b/src/ui/tools/tool-base.cpp index e04d9bd266..9bde2ebf3a 100644 --- a/src/ui/tools/tool-base.cpp +++ b/src/ui/tools/tool-base.cpp @@ -24,6 +24,7 @@ #include "desktop.h" #include "file.h" #include "gradient-drag.h" +#include "layer-model.h" #include "message-context.h" #include "rubberband.h" #include "selcue.h" @@ -131,6 +132,11 @@ void ToolBase::set(const Inkscape::Preferences::Entry& /*val*/) { } +SPGroup *ToolBase::currentLayer() const +{ + return desktop->layers->currentLayer(); +} + /** * Recreates and draws cursor on desktop related to ToolBase. */ diff --git a/src/ui/tools/tool-base.h b/src/ui/tools/tool-base.h index 1c522de05b..ae19702e46 100644 --- a/src/ui/tools/tool-base.h +++ b/src/ui/tools/tool-base.h @@ -29,6 +29,7 @@ class GrDrag; class SPDesktop; class SPItem; +class SPGroup; class KnotHolder; namespace Inkscape { class MessageContext; @@ -165,6 +166,7 @@ public: void setDesktop(SPDesktop *desktop_in) { desktop = desktop_in; } SPDesktop *getDesktop() { return desktop; } + SPGroup *currentLayer() const; // Commonly used CanvasItemCatchall grab/ungrab. void grabCanvasEvents(Gdk::EventMask mask = diff --git a/src/ui/widget/layer-selector.cpp b/src/ui/widget/layer-selector.cpp index d505a1a49d..99b5040c01 100644 --- a/src/ui/widget/layer-selector.cpp +++ b/src/ui/widget/layer-selector.cpp @@ -23,6 +23,7 @@ #include "document-undo.h" #include "document.h" #include "layer-manager.h" +#include "layer-model.h" #include "verbs.h" #include "ui/dialog/layer-properties.h" @@ -31,6 +32,8 @@ #include "ui/util.h" #include "ui/widget/canvas.h" // Focus widget +#include "object/sp-item-group.h" + #include "xml/node-event-vector.h" namespace Inkscape { @@ -171,33 +174,18 @@ LayerSelector::~LayerSelector() { * Then it selects the current layer for the desktop. */ void LayerSelector::setDesktop(SPDesktop *desktop) { - if ( desktop == _desktop ) { + if ( desktop == _desktop ) return; - } + if (_current_layer_changed_connection) + _current_layer_changed_connection.disconnect(); - if (_desktop) { -// _desktop_shutdown_connection.disconnect(); - if (_current_layer_changed_connection) - _current_layer_changed_connection.disconnect(); - if (_layers_changed_connection) - _layers_changed_connection.disconnect(); -// g_signal_handlers_disconnect_by_func(_desktop, (gpointer)&detach, this); - } _desktop = desktop; + if (_desktop) { - // TODO we need a different signal for this, really..s -// _desktop_shutdown_connection = _desktop->connectShutdown( -// sigc::bind (sigc::ptr_fun (detach), this)); -// g_signal_connect_after(_desktop, "shutdown", GCallback(detach), this); - - LayerManager *mgr = _desktop->layer_manager; - if ( mgr ) { - _current_layer_changed_connection = mgr->connectCurrentLayerChanged( sigc::mem_fun(*this, &LayerSelector::_selectLayer) ); - //_layerUpdatedConnection = mgr->connectLayerDetailsChanged( sigc::mem_fun(*this, &LayerSelector::_updateLayer) ); - _layers_changed_connection = mgr->connectChanged( sigc::mem_fun(*this, &LayerSelector::_layersChanged) ); + if (auto manager = _desktop->layer_manager) { + _current_layer_changed_connection = manager->connectCurrentLayerChanged(sigc::mem_fun(*this, &LayerSelector::_selectLayer)); } - - _selectLayer(_desktop->currentLayer()); + _selectLayer(dynamic_cast(_desktop->layers->currentLayer())); } } @@ -207,7 +195,7 @@ class is_layer { public: is_layer(SPDesktop *desktop) : _desktop(desktop) {} bool operator()(SPObject &object) const { - return _desktop->isLayer(&object); + return _desktop->layers->isLayer(&object); } private: SPDesktop *_desktop; @@ -229,21 +217,10 @@ private: } -void LayerSelector::_layersChanged() -{ - if (_desktop) { - /* - * This code fixes #166691 but causes issues #1066543 and #1080378. - * Comment out until solution found. - */ - //_selectLayer(_desktop->currentLayer()); - } -} - /** Selects the given layer in the dropdown selector. */ -void LayerSelector::_selectLayer(SPObject *layer) { - +void LayerSelector::_selectLayer(SPObject *layer) +{ _selection_changed_connection.block(); _visibility_toggled_connection.block(); _lock_toggled_connection.block(); @@ -254,8 +231,7 @@ void LayerSelector::_selectLayer(SPObject *layer) { _layer_model->erase(first_row); } - SPObject *root=_desktop->currentRoot(); - + SPGroup *root = _desktop->layers->currentRoot(); if (_layer) { sp_object_unref(_layer, nullptr); _layer = nullptr; @@ -309,7 +285,7 @@ void LayerSelector::_selectLayer(SPObject *layer) { /** Sets the current desktop layer to the actively selected layer. */ void LayerSelector::_setDesktopLayer() { - SPObject *layer=_selector.get_active()->get_value(_model_columns.object); + SPObject *layer = _selector.get_active()->get_value(_model_columns.object); if ( _desktop && layer ) { _current_layer_changed_connection.block(); _layers_changed_connection.block(); @@ -319,7 +295,7 @@ void LayerSelector::_setDesktopLayer() { _current_layer_changed_connection.unblock(); _layers_changed_connection.unblock(); - _selectLayer(_desktop->currentLayer()); + _selectLayer(dynamic_cast(_desktop->layers->currentLayer())); } if (_desktop && _desktop->canvas) { _desktop->canvas->grab_focus(); @@ -422,7 +398,7 @@ void update_row_for_object(SPObject *object, void rebuild_all_rows(sigc::slot rebuild, SPDesktop *desktop) { - rebuild(desktop->currentLayer()); + rebuild(desktop->layers->currentLayer()); } } @@ -434,13 +410,13 @@ void LayerSelector::_protectUpdate(sigc::slot slot) { _lock_toggled_connection.block(true); slot(); - SPObject *layer = _desktop ? _desktop->currentLayer() : nullptr; - if ( layer ) { - bool wantedValue = ( SP_IS_ITEM(layer) ? SP_ITEM(layer)->isLocked() : false ); + auto layer = _desktop ? _desktop->layers->currentLayer() : nullptr; + if (layer) { + bool wantedValue = layer->isLocked(); if ( _lock_toggle.get_active() != wantedValue ) { _lock_toggle.set_active( wantedValue ); } - wantedValue = ( SP_IS_ITEM(layer) ? SP_ITEM(layer)->isHidden() : false ); + wantedValue = layer->isHidden(); if ( _visibility_toggle.get_active() != wantedValue ) { _visibility_toggle.set_active( wantedValue ); } @@ -464,7 +440,7 @@ void LayerSelector::_buildEntry(unsigned depth, SPObject &object) { ) ); - SPObject *layer=_desktop->currentLayer(); + auto layer = _desktop->layers->currentLayer(); if ( (&object == layer) || (&object == layer->parent) ) { callbacks->update_list = sigc::bind( sigc::mem_fun(*this, &LayerSelector::_protectUpdate), @@ -542,8 +518,8 @@ void LayerSelector::_prepareLabelRenderer( // "invent" an iterator with null data and try to render it; // where does it come from, and how can we avoid it? if ( object && object->getRepr() ) { - SPObject *layer=( _desktop ? _desktop->currentLayer() : nullptr ); - SPObject *root=( _desktop ? _desktop->currentRoot() : nullptr ); + auto layer = _desktop ? _desktop->layers->currentLayer() : nullptr; + auto root = _desktop ? _desktop->layers->currentRoot() : nullptr; bool isancestor = !( (layer && (object->parent == layer->parent)) || ((layer == root) && (object->parent == root))); diff --git a/src/ui/widget/style-subject.cpp b/src/ui/widget/style-subject.cpp index 44e45e6fab..4f3d8c1fac 100644 --- a/src/ui/widget/style-subject.cpp +++ b/src/ui/widget/style-subject.cpp @@ -10,6 +10,8 @@ #include "desktop.h" #include "desktop-style.h" +#include "layer-manager.h" +#include "layer-model.h" #include "selection.h" #include "xml/sp-css-attr.h" @@ -162,8 +164,8 @@ void StyleSubject::CurrentLayer::setCSS(SPCSSAttr *css) { void StyleSubject::CurrentLayer::_afterDesktopSwitch(SPDesktop *desktop) { _layer_switched.disconnect(); if (desktop) { - _layer_switched = desktop->connectCurrentLayerChanged(sigc::mem_fun(*this, &CurrentLayer::_setLayer)); - _setLayer(desktop->currentLayer()); + _layer_switched = desktop->layer_manager->connectCurrentLayerChanged(sigc::mem_fun(*this, &CurrentLayer::_setLayer)); + _setLayer(desktop->layers->currentLayer()); } else { _setLayer(nullptr); } diff --git a/src/verbs.cpp b/src/verbs.cpp index 3af537c9da..cf8cad5f63 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -42,6 +42,7 @@ #include "inkscape-version.h" #include "layer-fns.h" #include "layer-manager.h" +#include "layer-model.h" #include "message-stack.h" #include "path-chemistry.h" #include "selection-chemistry.h" @@ -1229,23 +1230,25 @@ void LayerVerb::perform(SPAction *action, void *data) SPDesktop *dt = sp_action_get_desktop(action); size_t verb = reinterpret_cast(data); - if ( !dt->currentLayer() ) { + auto layers = dt->layers; + auto layer = layers->currentLayer(); + auto root = layers->currentRoot(); + if (!layer) return; - } switch (verb) { case SP_VERB_LAYER_NEW: { - Inkscape::UI::Dialogs::LayerPropertiesDialog::showCreate(dt, dt->currentLayer()); + Inkscape::UI::Dialogs::LayerPropertiesDialog::showCreate(dt, layer); break; } case SP_VERB_LAYER_RENAME: { - Inkscape::UI::Dialogs::LayerPropertiesDialog::showRename(dt, dt->currentLayer()); + Inkscape::UI::Dialogs::LayerPropertiesDialog::showRename(dt, layer); break; } case SP_VERB_LAYER_NEXT: { - SPObject *next=Inkscape::next_layer(dt->currentRoot(), dt->currentLayer()); + SPObject *next=Inkscape::next_layer(root, layer); if (next) { - dt->setCurrentLayer(next); + layers->setCurrentLayer(next); DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_NEXT, _("Switch to next layer")); dt->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Switched to next layer.")); @@ -1255,9 +1258,9 @@ void LayerVerb::perform(SPAction *action, void *data) break; } case SP_VERB_LAYER_PREV: { - SPObject *prev=Inkscape::previous_layer(dt->currentRoot(), dt->currentLayer()); + SPObject *prev=Inkscape::previous_layer(root, layer); if (prev) { - dt->setCurrentLayer(prev); + layers->setCurrentLayer(prev); DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_PREV, _("Switch to previous layer")); dt->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Switched to previous layer.")); @@ -1275,21 +1278,19 @@ void LayerVerb::perform(SPAction *action, void *data) break; } case SP_VERB_LAYER_MOVE_TO: { - Inkscape::UI::Dialogs::LayerPropertiesDialog::showMove(dt, dt->currentLayer()); + Inkscape::UI::Dialogs::LayerPropertiesDialog::showMove(dt, layer); break; } case SP_VERB_LAYER_TO_TOP: case SP_VERB_LAYER_TO_BOTTOM: case SP_VERB_LAYER_RAISE: case SP_VERB_LAYER_LOWER: { - if ( dt->currentLayer() == dt->currentRoot() ) { + if ( layer == root ) { dt->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No current layer.")); return; } - SPItem *layer=SP_ITEM(dt->currentLayer()); g_return_if_fail(layer != nullptr); - SPObject *old_pos = layer->getNext(); switch (verb) { @@ -1340,7 +1341,7 @@ void LayerVerb::perform(SPAction *action, void *data) break; } case SP_VERB_LAYER_DUPLICATE: { - if ( dt->currentLayer() != dt->currentRoot() ) { + if ( layer != root ) { dt->selection->duplicate(true, true); @@ -1355,29 +1356,29 @@ void LayerVerb::perform(SPAction *action, void *data) break; } case SP_VERB_LAYER_DELETE: { - if ( dt->currentLayer() != dt->currentRoot() ) { + if ( layer != root ) { dt->getSelection()->clear(); - SPObject *old_layer = dt->currentLayer(); + auto old_layer = layer; SPObject *old_parent = old_layer->parent; SPObject *old_parent_parent = (old_parent != nullptr) ? old_parent->parent : nullptr; - SPObject *survivor = Inkscape::previous_layer(dt->currentRoot(), old_layer); + SPObject *survivor = Inkscape::previous_layer(root, old_layer); if (survivor != nullptr && survivor->parent == old_layer) { while (survivor != nullptr && survivor->parent != old_parent && survivor->parent != old_parent_parent) { - survivor = Inkscape::previous_layer(dt->currentRoot(), survivor); + survivor = Inkscape::previous_layer(root, survivor); } } if (survivor == nullptr || (survivor->parent != old_parent && survivor->parent != old_layer)) { - survivor = Inkscape::next_layer(dt->currentRoot(), old_layer); + survivor = Inkscape::next_layer(root, old_layer); while (survivor != nullptr && survivor != old_parent && survivor->parent != old_parent) { - survivor = Inkscape::next_layer(dt->currentRoot(), survivor); + survivor = Inkscape::next_layer(root, survivor); } } @@ -1389,7 +1390,7 @@ void LayerVerb::perform(SPAction *action, void *data) old_layer->deleteObject(); if (survivor) { - dt->setCurrentLayer(survivor); + layers->setCurrentLayer(survivor); } DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_DELETE, @@ -1403,52 +1404,52 @@ void LayerVerb::perform(SPAction *action, void *data) break; } case SP_VERB_LAYER_SOLO: { - if ( dt->currentLayer() == dt->currentRoot() ) { + if ( layer == root ) { dt->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No current layer.")); } else { - dt->toggleLayerSolo( dt->currentLayer() ); + layers->toggleLayerSolo( layer ); DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_SOLO, _("Toggle layer solo")); } break; } case SP_VERB_LAYER_SHOW_ALL: { - dt->toggleHideAllLayers( false ); + layers->toggleHideAllLayers( false ); DocumentUndo::maybeDone(dt->getDocument(), "layer:showall", SP_VERB_LAYER_SHOW_ALL, _("Show all layers")); break; } case SP_VERB_LAYER_HIDE_ALL: { - dt->toggleHideAllLayers( true ); + layers->toggleHideAllLayers( true ); DocumentUndo::maybeDone(dt->getDocument(), "layer:hideall", SP_VERB_LAYER_HIDE_ALL, _("Hide all layers")); break; } case SP_VERB_LAYER_LOCK_ALL: { - dt->toggleLockAllLayers( true ); + layers->toggleLockAllLayers( true ); DocumentUndo::maybeDone(dt->getDocument(), "layer:lockall", SP_VERB_LAYER_LOCK_ALL, _("Lock all layers")); break; } case SP_VERB_LAYER_LOCK_OTHERS: { - if ( dt->currentLayer() == dt->currentRoot() ) { + if ( layer == root ) { dt->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No current layer.")); } else { - dt->toggleLockOtherLayers( dt->currentLayer() ); + layers->toggleLockOtherLayers( layer ); DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_LOCK_OTHERS, _("Lock other layers")); } break; } case SP_VERB_LAYER_UNLOCK_ALL: { - dt->toggleLockAllLayers( false ); + layers->toggleLockAllLayers( false ); DocumentUndo::maybeDone(dt->getDocument(), "layer:unlockall", SP_VERB_LAYER_UNLOCK_ALL, _("Unlock all layers")); break; } case SP_VERB_LAYER_TOGGLE_LOCK: case SP_VERB_LAYER_TOGGLE_HIDE: { - if ( dt->currentLayer() == dt->currentRoot() ) { + if ( layer == root ) { dt->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No current layer.")); } else { if ( verb == SP_VERB_LAYER_TOGGLE_HIDE ){ - SP_ITEM(dt->currentLayer())->setHidden(!SP_ITEM(dt->currentLayer())->isHidden()); + layer->setHidden(!layer->isHidden()); } else { - SP_ITEM(dt->currentLayer())->setLocked(!SP_ITEM(dt->currentLayer())->isLocked()); + layer->setLocked(!layer->isLocked()); } } -- GitLab From a7855798866fe5ac1e9fd36bb935ad82a25acdae Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Thu, 4 Nov 2021 15:27:19 -0400 Subject: [PATCH 2/6] Consolidate layer Manager, Model and Fncs into one This refactoring unpicks many issues with the layer model and manager uses. We will now have a single LayerManager which will be a unique ptr from the desktop object. All layer functions should make their way to this file. --- src/CMakeLists.txt | 4 - src/conn-avoid-ref.cpp | 8 +- src/context-fns.cpp | 6 +- src/desktop.cpp | 59 +-- src/desktop.h | 8 +- src/document.cpp | 7 +- src/extension/dbus/document-interface.cpp | 40 +- src/extension/implementation/script.cpp | 3 +- src/extension/internal/grid.cpp | 4 +- src/file.cpp | 8 +- src/helper/action-context.cpp | 5 +- src/inkscape.h | 5 +- src/layer-fns.cpp | 207 --------- src/layer-fns.h | 44 -- src/layer-manager.cpp | 488 ++++++++++++++++------ src/layer-manager.h | 38 +- src/layer-model.cpp | 257 ------------ src/layer-model.h | 101 ----- src/object/sp-flowtext.cpp | 4 +- src/object/sp-namedview.cpp | 8 +- src/object/sp-symbol.cpp | 3 +- src/object/sp-text.cpp | 6 +- src/selection-chemistry.cpp | 74 ++-- src/selection-describer.cpp | 6 +- src/selection.cpp | 25 +- src/selection.h | 14 +- src/ui/contextmenu.cpp | 11 +- src/ui/dialog/filter-effects-dialog.cpp | 6 +- src/ui/dialog/find.cpp | 12 +- src/ui/dialog/layer-properties.cpp | 21 +- src/ui/dialog/layer-properties.h | 3 +- src/ui/dialog/layers.cpp | 43 +- src/ui/dialog/objects.cpp | 15 +- src/ui/dialog/spellcheck.cpp | 4 +- src/ui/dialog/xml-tree.cpp | 6 +- src/ui/drag-and-drop.cpp | 4 +- src/ui/toolbar/connector-toolbar.cpp | 4 +- src/ui/tools/eraser-tool.cpp | 3 +- src/ui/tools/flood-tool.cpp | 4 +- src/ui/tools/measure-tool.cpp | 22 +- src/ui/tools/pencil-tool.cpp | 3 +- src/ui/tools/select-tool.cpp | 10 +- src/ui/tools/tool-base.cpp | 4 +- src/ui/widget/layer-selector.cpp | 25 +- src/ui/widget/style-subject.cpp | 5 +- src/verbs.cpp | 25 +- 46 files changed, 624 insertions(+), 1038 deletions(-) delete mode 100644 src/layer-fns.cpp delete mode 100644 src/layer-fns.h delete mode 100644 src/layer-model.cpp delete mode 100644 src/layer-model.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 59e9035660..d9b6e4db28 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -42,9 +42,7 @@ set(inkscape_SRC id-clash.cpp inkscape.cpp inkscape-version-info.cpp - layer-fns.cpp layer-manager.cpp - layer-model.cpp line-geometry.cpp line-snapper.cpp media.cpp @@ -137,9 +135,7 @@ set(inkscape_SRC inkscape-version.h inkscape-version-info.h inkscape.h - layer-fns.h layer-manager.h - layer-model.h line-geometry.h line-snapper.h media.h diff --git a/src/conn-avoid-ref.cpp b/src/conn-avoid-ref.cpp index 5ca5a8c86a..1bf3934766 100644 --- a/src/conn-avoid-ref.cpp +++ b/src/conn-avoid-ref.cpp @@ -24,7 +24,7 @@ #include "document-undo.h" #include "document.h" #include "inkscape.h" -#include "layer-model.h" +#include "layer-manager.h" #include "verbs.h" #include "display/curve.h" @@ -339,7 +339,7 @@ std::vector get_avoided_items(std::vector &list, SPObject *f { for (auto& child: from->children) { if (SP_IS_ITEM(&child) && - !desktop->layers->isLayer(SP_ITEM(&child)) && + !desktop->layerManager().isLayer(SP_ITEM(&child)) && !SP_ITEM(&child)->isLocked() && !desktop->itemIsHidden(SP_ITEM(&child)) && (!initialised || SP_ITEM(&child)->getAvoidRef().shapeRef) @@ -348,7 +348,7 @@ std::vector get_avoided_items(std::vector &list, SPObject *f list.push_back(SP_ITEM(&child)); } - if (SP_IS_ITEM(&child) && desktop->layers->isLayer(SP_ITEM(&child))) { + if (SP_IS_ITEM(&child) && desktop->layerManager().isLayer(SP_ITEM(&child))) { list = get_avoided_items(list, &child, desktop, initialised); } } @@ -379,7 +379,7 @@ void init_avoided_shape_geometry(SPDesktop *desktop) bool initialised = false; std::vector tmp; - std::vector items = get_avoided_items(tmp, desktop->layers->currentRoot(), desktop, + std::vector items = get_avoided_items(tmp, desktop->layerManager().currentRoot(), desktop, initialised); for (auto item : items) { diff --git a/src/context-fns.cpp b/src/context-fns.cpp index 28e36be17d..05b1cafe33 100644 --- a/src/context-fns.cpp +++ b/src/context-fns.cpp @@ -12,7 +12,7 @@ #include "context-fns.h" #include "desktop.h" -#include "layer-model.h" +#include "layer-manager.h" #include "message-context.h" #include "message-stack.h" #include "snap.h" @@ -41,7 +41,7 @@ static const double midpt_goldenratio_2 = (goldenratio + 2) / 2; bool Inkscape::have_viable_layer(SPDesktop *desktop, MessageContext *message) { - auto layer = desktop->layers->currentLayer(); + auto layer = desktop->layerManager().currentLayer(); if ( !layer || desktop->itemIsHidden(layer) ) { message->flash(Inkscape::ERROR_MESSAGE, @@ -70,7 +70,7 @@ bool Inkscape::have_viable_layer(SPDesktop *desktop, MessageContext *message) bool Inkscape::have_viable_layer(SPDesktop *desktop, MessageStack *message) { - auto layer = desktop->layers->currentLayer(); + auto layer = desktop->layerManager().currentLayer(); if ( !layer || desktop->itemIsHidden(layer) ) { message->flash(Inkscape::WARNING_MESSAGE, diff --git a/src/desktop.cpp b/src/desktop.cpp index 554a80cf93..d4a0417430 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -36,9 +36,7 @@ #include "document-undo.h" #include "event-log.h" #include "inkscape-window.h" -#include "layer-fns.h" #include "layer-manager.h" -#include "layer-model.h" #include "message-context.h" #include "message-stack.h" @@ -79,7 +77,6 @@ namespace Inkscape { namespace XML { class Node; }} // Callback declarations -static void _onSelectionChanged (Inkscape::Selection *selection, SPDesktop *desktop); static bool _drawing_handler (GdkEvent *event, Inkscape::DrawingItem *item, SPDesktop *desktop); static void _reconstruction_start(SPDesktop * desktop); static void _reconstruction_finish(SPDesktop * desktop); @@ -107,10 +104,8 @@ static void _pinch_scale_changed_handler(GtkGesture *gesture, gdouble delta, SPD SPDesktop::SPDesktop() : namedview(nullptr) , canvas(nullptr) - , layers(nullptr) , selection(nullptr) , event_context(nullptr) - , layer_manager(nullptr) , temporary_item_list(nullptr) , snapindicator(nullptr) , current(nullptr) // current style @@ -134,8 +129,8 @@ SPDesktop::SPDesktop() , _image_render_observer(this, "/options/rendering/imageinoutlinemode") , grids_visible(false) { - layers = new Inkscape::LayerModel(); - selection = Inkscape::GC::release( new Inkscape::Selection(layers, this) ); + _layer_manager = std::make_unique(this); + selection = Inkscape::GC::release(new Inkscape::Selection(this)); } void @@ -174,9 +169,6 @@ SPDesktop::init (SPNamedView *nv, Inkscape::UI::Widget::Canvas *acanvas, SPDeskt dkey = SPItem::display_key_new(1); - /* Connect display key to layer model */ - layers->setDisplayKey(dkey); - /* Connect document */ setDocument (document); @@ -297,21 +289,6 @@ SPDesktop::init (SPNamedView *nv, Inkscape::UI::Widget::Canvas *acanvas, SPDeskt document->connectReconstructionFinish(sigc::bind(sigc::ptr_fun(_reconstruction_finish), this)); _reconstruction_old_layer_id.clear(); - // ? - // sp_active_desktop_set (desktop); - - _sel_changed_connection = selection->connectChanged( - sigc::bind( - sigc::ptr_fun(&_onSelectionChanged), - this - ) - ); - - - /* 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); } @@ -350,13 +327,6 @@ void SPDesktop::destroy() g_clear_object(&zoomgesture); } - delete layers; - - if (layer_manager) { - delete layer_manager; - layer_manager = nullptr; - } - if (canvas_drawing) { doc()->getRoot()->invoke_hide(dkey); delete canvas_drawing; // Why is canvas_drawing special? @@ -1488,7 +1458,6 @@ SPDesktop::setDocument (SPDocument *doc) this->doc()->getRoot()->invoke_hide(dkey); } - layers->setDocument(doc); selection->setDocument(doc); _commit_connection.disconnect(); @@ -1554,24 +1523,6 @@ SPDesktop::onDocumentResized (gdouble width, gdouble height) canvas_shadow->set_rect(a); } -static void -_onSelectionChanged -(Inkscape::Selection *selection, SPDesktop *desktop) -{ - /** \todo - * only change the layer for single selections, or what? - * This seems reasonable -- for multiple selections there can be many - * different layers involved. - */ - SPItem *item=selection->singleItem(); - if (item) { - SPObject *layer=desktop->layers->layerForObject(item); - if ( layer && layer != desktop->layers->currentLayer() ) { - desktop->layers->setCurrentLayer(layer); - } - } -} - /** * Calls event handler of current event context. */ @@ -1595,9 +1546,9 @@ _drawing_handler (GdkEvent *event, Inkscape::DrawingItem *drawing_item, SPDeskto /// Called when document is starting to be rebuilt. static void _reconstruction_start(SPDesktop * desktop) { - auto layer = desktop->layers->currentLayer(); + auto layer = desktop->layerManager().currentLayer(); desktop->_reconstruction_old_layer_id = layer->getId() ? layer->getId() : ""; - desktop->layers->reset(); + desktop->layerManager().reset(); desktop->selection->clear(); } @@ -1609,7 +1560,7 @@ static void _reconstruction_finish(SPDesktop * desktop) if ( !desktop->_reconstruction_old_layer_id.empty() ) { SPObject * newLayer = desktop->namedview->document->getObjectById(desktop->_reconstruction_old_layer_id); if (newLayer != nullptr) { - desktop->layers->setCurrentLayer(newLayer); + desktop->layerManager().setCurrentLayer(newLayer); } desktop->_reconstruction_old_layer_id.clear(); diff --git a/src/desktop.h b/src/desktop.h index 63c1f275e0..c1bbcde2fb 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -69,7 +69,6 @@ struct InkscapeApplication; namespace Inkscape { class LayerManager; - class LayerModel; class MessageContext; class Selection; @@ -141,11 +140,9 @@ class SPDesktop : public Inkscape::UI::View::View { public: SPNamedView *namedview; - Inkscape::LayerModel *layers; /// current selection; will never generally be NULL Inkscape::Selection *selection; Inkscape::UI::Tools::ToolBase *event_context; - Inkscape::LayerManager *layer_manager; DocumentInterface *dbus_document_interface; Inkscape::Display::TemporaryItemList *temporary_item_list; Inkscape::Display::SnapIndicator *snapindicator; @@ -282,6 +279,9 @@ public: ~SPDesktop() override; void destroy(); + Inkscape::LayerManager& layerManager() { return *_layer_manager; } + const Inkscape::LayerManager& layerManager() const { return *_layer_manager; } + Inkscape::MessageContext *guidesMessageContext() const { return _guides_message_context.get(); } @@ -605,6 +605,8 @@ private: bool grids_visible; /* don't set this variable directly, use the method below */ void set_grids_visible(bool visible); + std::unique_ptr _layer_manager; + sigc::signal _destroy_signal; sigc::signal _document_replaced_signal; sigc::signal _event_context_changed_signal; diff --git a/src/document.cpp b/src/document.cpp index 8239879be4..2e04b44a56 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -68,6 +68,7 @@ #include "3rdparty/libcroco/cr-selector.h" #include "io/dir-util.h" +#include "layer-manager.h" #include "live_effects/lpeobject.h" #include "object/persp3d.h" #include "object/sp-defs.h" @@ -1597,17 +1598,15 @@ std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vecto } SPObject *current_layer = nullptr; SPDesktop *desktop = SP_ACTIVE_DESKTOP; - Inkscape::LayerModel *layer_model = nullptr; if(desktop){ - layer_model = desktop->layers; - current_layer = layer_model->currentLayer(); + current_layer = desktop->layerManager().currentLayer(); } size_t item_counter = 0; for(int i = points.size()-1;i>=0; i--) { std::vector items = find_items_at_point(&_node_cache, key, points[i], topmost_only); for (SPItem *item : items) { if (item && result.end()==find(result.begin(), result.end(), item)) - if(all_layers || (layer_model && layer_model->layerForObject(item) == current_layer)){ + if(all_layers || (desktop && desktop->layerManager().layerForObject(item) == current_layer)){ result.push_back(item); item_counter++; //limit 0 = no limit diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index 9d35ed54fb..6b3b92045a 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -32,8 +32,7 @@ #include "document.h" // getReprDoc() #include "file.h" //IO #include "inkscape.h" //inkscape_find_desktop_by_dkey, activate desktops -#include "layer-fns.h" //LPOS_BELOW -#include "layer-model.h" +#include "layer-manager.h" #include "print.h" //IO #include "selection-chemistry.h"// lots of selection functions #include "selection.h" //selection struct @@ -186,7 +185,7 @@ selection_swap(Inkscape::Selection *sel, gchar *name, GError **error) { std::vector oldsel = std::vector(sel->objects().begin(), sel->objects().end()); - sel->set(get_object_by_name(sel->layers()->getDocument(), name, error)); + sel->set(get_object_by_name(sel->getDocument(), name, error)); return oldsel; } @@ -222,8 +221,9 @@ dbus_create_node (SPDocument *doc, const gchar *type) gchar *finish_create_shape (DocumentInterface *doc_interface, GError ** /*error*/, Inkscape::XML::Node *newNode, gchar *desc) { SPCSSAttr *style = NULL; - if (doc_interface->target.getDesktop()) { - style = sp_desktop_get_style(doc_interface->target.getDesktop(), TRUE); + auto desktop = doc_interface->target.getDesktop(); + if (desktop) { + style = sp_desktop_get_style(desktop, true); } if (style) { Glib::ustring str; @@ -234,8 +234,10 @@ gchar *finish_create_shape (DocumentInterface *doc_interface, GError ** /*error* newNode->setAttribute("style", "fill:#0000ff;fill-opacity:1;stroke:#c900b9;stroke-width:0;stroke-miterlimit:0;stroke-opacity:1;stroke-dasharray:none"); } - doc_interface->target.getSelection()->layers()->currentLayer()->appendChildRepr(newNode); - doc_interface->target.getSelection()->layers()->currentLayer()->updateRepr(); + if (desktop) { + desktop->layerManager().currentLayer()->appendChildRepr(newNode); + desktop->layerManager().currentLayer()->updateRepr(); + } if (doc_interface->updates) { Inkscape::DocumentUndo::done(doc_interface->target.getDocument(), 0, (gchar *)desc); @@ -508,8 +510,10 @@ document_interface_image (DocumentInterface *doc_interface, int x, int y, gchar newNode->setAttributeInt("y", y); newNode->setAttribute("xlink:href", uri); - doc_interface->target.getSelection()->layers()->currentLayer()->appendChildRepr(newNode); - doc_interface->target.getSelection()->layers()->currentLayer()->updateRepr(); + if (auto desktop = doc_interface->target.getDesktop()) { + desktop->layerManager().currentLayer()->appendChildRepr(newNode); + desktop->layerManager().currentLayer()->updateRepr(); + } if (doc_interface->updates) Inkscape::DocumentUndo::done(doc_interface->target.getDocument(), 0, "Imported bitmap."); @@ -525,8 +529,10 @@ gchar *document_interface_node(DocumentInterface *doc_interface, gchar *type, GE Inkscape::XML::Node *newNode = xml_doc->createElement(type); - doc_interface->target.getSelection()->layers()->currentLayer()->appendChildRepr(newNode); - doc_interface->target.getSelection()->layers()->currentLayer()->updateRepr(); + if (auto desktop = doc_interface->target.getDesktop()) { + desktop->layerManager().currentLayer()->appendChildRepr(newNode); + desktop->layerManager().currentLayer()->updateRepr(); + } if (doc_interface->updates) { Inkscape::DocumentUndo::done(doc, 0, (gchar *)"created empty node"); @@ -1279,7 +1285,9 @@ document_interface_selection_move_to_layer (DocumentInterface *doc_interface, dt->selection->cut(); - doc_interface->target.getSelection()->layers()->setCurrentLayer(next); + if (auto desktop = doc_interface->target.getDesktop()) { + desktop->layerManager().setCurrentLayer(next); + } sp_selection_paste(dt, TRUE); } @@ -1355,9 +1363,9 @@ document_interface_selection_change_level (DocumentInterface *doc_interface, gch gchar *document_interface_layer_new(DocumentInterface *doc_interface, GError ** /*error*/) { - Inkscape::LayerModel * layers = doc_interface->target.getSelection()->layers(); - SPObject *new_layer = Inkscape::create_layer(layers->currentRoot(), layers->currentLayer(), Inkscape::LPOS_BELOW); - layers->setCurrentLayer(new_layer); + auto desktop = doc_interface->target.getSelection()->desktop(); + SPObject *new_layer = Inkscape::create_layer(desktop->layerManager().currentRoot(), desktop->layerManager().currentLayer(), Inkscape::LPOS_BELOW); + desktop->layerManager().setCurrentLayer(new_layer); return g_strdup(get_name_from_object(new_layer)); } @@ -1370,7 +1378,7 @@ document_interface_layer_set (DocumentInterface *doc_interface, if (!obj) return FALSE; - doc_interface->target.getSelection()->layers()->setCurrentLayer (obj); + doc_interface->target.getDesktop()->layerManager().setCurrentLayer(obj); return TRUE; } diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp index 0e6acf80a0..e943d639ba 100644 --- a/src/extension/implementation/script.cpp +++ b/src/extension/implementation/script.cpp @@ -38,6 +38,7 @@ #include "extension/output.h" #include "extension/system.h" #include "io/resource.h" +#include "layer-manager.h" #include "object/sp-namedview.h" #include "object/sp-path.h" #include "ui/desktop/menubar.h" @@ -681,7 +682,7 @@ void Script::effect(Inkscape::Extension::Effect *module, //If that layer exists, if (layer) { //set the current layer - desktop->layers->setCurrentLayer(layer); + desktop->layerManager().setCurrentLayer(layer); } } mydoc->release(); diff --git a/src/extension/internal/grid.cpp b/src/extension/internal/grid.cpp index 48aaa8ba04..5517c2aa67 100644 --- a/src/extension/internal/grid.cpp +++ b/src/extension/internal/grid.cpp @@ -19,7 +19,7 @@ #include "desktop.h" #include "document.h" -#include "layer-model.h" +#include "layer-manager.h" #include "selection.h" #include "2geom/geom.h" @@ -117,7 +117,7 @@ Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *vie Inkscape::XML::Document * xml_doc = doc->getReprDoc(); //XML Tree being used directly here while it shouldn't be. - Inkscape::XML::Node * current_layer = desktop->layers->currentLayer()->getRepr(); + Inkscape::XML::Node * current_layer = desktop->layerManager().currentLayer()->getRepr(); Inkscape::XML::Node * path = xml_doc->createElement("svg:path"); path->setAttribute("d", path_data); diff --git a/src/file.cpp b/src/file.cpp index 9011a43782..4cf47b5d7f 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -43,7 +43,7 @@ #include "id-clash.h" #include "inkscape-version.h" #include "inkscape.h" -#include "layer-model.h" +#include "layer-manager.h" #include "message-stack.h" #include "path-prefix.h" #include "print.h" @@ -901,7 +901,7 @@ void sp_import_document(SPDesktop *desktop, SPDocument *clipdoc, bool in_place) SPDocument *target_document = desktop->getDocument(); Inkscape::XML::Node *root = clipdoc->getReprRoot(); - Inkscape::XML::Node *target_parent = desktop->layers->currentLayer()->getRepr(); + Inkscape::XML::Node *target_parent = desktop->layerManager().currentLayer()->getRepr(); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -952,7 +952,7 @@ void sp_import_document(SPDesktop *desktop, SPDocument *clipdoc, bool in_place) } } - auto layer = desktop->layers->currentLayer(); + auto layer = desktop->layerManager().currentLayer(); std::vector pasted_objects_not; if(clipboard) //???? Removed dead code can cause any bug, need to reimplement undead for (Inkscape::XML::Node *obj = clipboard->firstChild() ; obj ; obj = obj->next()) { @@ -1087,7 +1087,7 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri, // For now, we just use the root in this case. SPObject *place_to_insert; if (desktop) { - place_to_insert = desktop->layers->currentLayer(); + place_to_insert = desktop->layerManager().currentLayer(); } else { place_to_insert = in_doc->getRoot(); } diff --git a/src/helper/action-context.cpp b/src/helper/action-context.cpp index 36b6914d6f..5f229a6a86 100644 --- a/src/helper/action-context.cpp +++ b/src/helper/action-context.cpp @@ -12,7 +12,6 @@ #include "desktop.h" #include "document.h" -#include "layer-model.h" #include "selection.h" #include "helper/action-context.h" @@ -45,9 +44,7 @@ SPDocument *ActionContext::getDocument() const if (_selection == nullptr) { return nullptr; } - - // Should be the same as the view's document, if view is non-NULL - return _selection->layers()->getDocument(); + return getDesktop()->getDocument(); } Selection *ActionContext::getSelection() const diff --git a/src/inkscape.h b/src/inkscape.h index 2dac693177..2048332c41 100644 --- a/src/inkscape.h +++ b/src/inkscape.h @@ -14,7 +14,6 @@ * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ -#include "layer-model.h" #include "selection.h" #include #include @@ -56,16 +55,14 @@ void inkscape_unref(Inkscape::Application & in); #define SP_ACTIVE_DESKTOP (INKSCAPE.active_desktop()) class AppSelectionModel { - Inkscape::LayerModel _layer_model; Inkscape::Selection *_selection; public: AppSelectionModel(SPDocument *doc) { - _layer_model.setDocument(doc); // TODO: is this really how we should manage the lifetime of the selection? // I just copied this from the initialization of the Selection in SPDesktop. // When and how is it actually released? - _selection = Inkscape::GC::release(new Inkscape::Selection(&_layer_model, nullptr)); + _selection = Inkscape::GC::release(new Inkscape::Selection(nullptr)); _selection->setDocument(doc); } diff --git a/src/layer-fns.cpp b/src/layer-fns.cpp deleted file mode 100644 index 81c722ddc2..0000000000 --- a/src/layer-fns.cpp +++ /dev/null @@ -1,207 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Inkscape::SelectionDescriber - shows messages describing selection - * - * Authors: - * MenTaLguY - * Jon A. Cruz - * - * Copyright (C) 2004 MenTaLguY - * - * Released under GNU GPL v2+, read the file 'COPYING' for more information. - */ - -#include "document.h" -#include "layer-fns.h" - -#include "object/sp-item-group.h" - -#include "util/find-last-if.h" - -#include "xml/repr.h" - -// TODO move the documentation comments into the .h file - -namespace Inkscape { - -namespace { - -static bool is_layer(SPObject &object) { - return SP_IS_GROUP(&object) && - SP_GROUP(&object)->layerMode() == SPGroup::LAYER; -} - -/** Finds the next sibling layer for a \a layer - * - * @returns NULL if there are no further layers under a parent - */ -static SPObject *next_sibling_layer(SPObject *layer) { - if (layer->parent == nullptr) { - return nullptr; - } - SPObject::ChildrenList &list = layer->parent->children; - auto l = std::find_if(++list.iterator_to(*layer), list.end(), &is_layer); - return l != list.end() ? &*l : nullptr; -} - -/** Finds the previous sibling layer for a \a layer - * - * @returns NULL if there are no further layers under a parent - */ -static SPObject *previous_sibling_layer(SPObject *layer) { - using Inkscape::Algorithms::find_last_if; - - SPObject::ChildrenList &list = layer->parent->children; - auto l = find_last_if(list.begin(), list.iterator_to(*layer), &is_layer); - return l != list.iterator_to(*layer) ? &*(l) : nullptr; -} - -/** Finds the first child of a \a layer - * - * @returns the layer itself if layer has no sublayers - */ -static SPObject *first_descendant_layer(SPObject *layer) { - while (true) { - auto first_descendant = std::find_if(layer->children.begin(), layer->children.end(), &is_layer); - if (first_descendant == layer->children.end()) { - break; - } - layer = &*first_descendant; - } - - return layer; -} - -/** Finds the last (topmost) child of a \a layer - * - * @returns NULL if layer has no sublayers - */ -static SPObject *last_child_layer(SPObject *layer) { - using Inkscape::Algorithms::find_last_if; - - auto l = find_last_if(layer->children.begin(), layer->children.end(), &is_layer); - return l != layer->children.end() ? &*l : nullptr; -} - -static SPObject *last_elder_layer(SPObject *root, SPObject *layer) { - using Inkscape::Algorithms::find_last_if; - SPObject *result = nullptr; - - while ( layer != root ) { - SPObject *sibling(previous_sibling_layer(layer)); - if (sibling) { - result = sibling; - break; - } - layer = layer->parent; - } - - return result; -} - -} - -/** Finds the next layer under \a root, relative to \a layer in - * depth-first order. - * - * @returns NULL if there are no further layers under \a root - */ -SPObject *next_layer(SPObject *root, SPObject *layer) { - g_return_val_if_fail(layer != nullptr, NULL); - SPObject *result = nullptr; - - SPObject *sibling = next_sibling_layer(layer); - if (sibling) { - result = first_descendant_layer(sibling); - } else if ( layer->parent != root ) { - result = layer->parent; - } - - return result; -} - - -/** Finds the previous layer under \a root, relative to \a layer in - * depth-first order. - * - * @returns NULL if there are no prior layers under \a root. - */ -SPObject *previous_layer(SPObject *root, SPObject *layer) { - using Inkscape::Algorithms::find_last_if; - - g_return_val_if_fail(layer != nullptr, NULL); - SPObject *result = nullptr; - - SPObject *child = last_child_layer(layer); - if (child) { - result = child; - } else if ( layer != root ) { - SPObject *sibling = previous_sibling_layer(layer); - if (sibling) { - result = sibling; - } else { - result = last_elder_layer(root, layer->parent); - } - } - - return result; -} - -/** -* Creates a new layer. Advances to the next layer id indicated - * by the string "layerNN", then creates a new group object of - * that id with attribute inkscape:groupmode='layer', and finally - * appends the new group object to \a root after object \a layer. - * - * \pre \a root should be either \a layer or an ancestor of it - */ -SPObject *create_layer(SPObject *root, SPObject *layer, LayerRelativePosition position) { - SPDocument *document = root->document; - - static int layer_suffix=1; - gchar *id=nullptr; - do { - g_free(id); - id = g_strdup_printf("layer%d", layer_suffix++); - } while (document->getObjectById(id)); - - Inkscape::XML::Document *xml_doc = document->getReprDoc(); - Inkscape::XML::Node *repr = xml_doc->createElement("svg:g"); - repr->setAttribute("inkscape:groupmode", "layer"); - repr->setAttribute("id", id); - g_free(id); - - if ( LPOS_CHILD == position ) { - root = layer; - SPObject *child_layer = Inkscape::last_child_layer(layer); - if ( nullptr != child_layer ) { - layer = child_layer; - } - } - - if ( root == layer ) { - root->getRepr()->appendChild(repr); - } else { - Inkscape::XML::Node *layer_repr = layer->getRepr(); - layer_repr->parent()->addChild(repr, layer_repr); - - if ( LPOS_BELOW == position ) { - SP_ITEM(document->getObjectByRepr(repr))->lowerOne(); - } - } - - return document->getObjectByRepr(repr); -} - -} - -/* - 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-fns.h b/src/layer-fns.h deleted file mode 100644 index 1b9cd7e7a7..0000000000 --- a/src/layer-fns.h +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * assorted functions related to layers - * - * Authors: - * MenTaLguY - * - * Copyright (C) 2004 MenTaLguY - * - * Released under GNU GPL v2+, read the file 'COPYING' for more information. - */ - -#ifndef SEEN_INKSCAPE_LAYER_FNS_H -#define SEEN_INKSCAPE_LAYER_FNS_H - -class SPObject; - -namespace Inkscape { - -enum LayerRelativePosition { - LPOS_ABOVE, - LPOS_BELOW, - LPOS_CHILD, -}; - -SPObject *create_layer(SPObject *root, SPObject *layer, LayerRelativePosition position); - -SPObject *next_layer(SPObject *root, SPObject *layer); - -SPObject *previous_layer(SPObject *root, SPObject *layer); - -} - -#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-manager.cpp b/src/layer-manager.cpp index 348a9dc8fc..aa1f24d1af 100644 --- a/src/layer-manager.cpp +++ b/src/layer-manager.cpp @@ -1,10 +1,21 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Inkscape::LayerManager - a view of a document's layers, relative - * to a particular desktop + * Inkscape::LayerManager * - * Copyright 2006 MenTaLguY - * Abhishek Sharma + * Owned by the Desktop, this manager tracks layer objects as + * distinct entities from groups, providing a comprehensive set + * of utilities, signals and other Layer based organisation. + * + * Refactored from LayerManager and layer-fns in 2021. + * + * Copyright 2001 Ximian, Inc. + * 2002 Lauris Kaplinski + * 2006 John Bintz + * 2006 MenTaLguY + * 2007 Jon A. Cruz + * 2008 Johan Engelen + * 2010 Abhishek Sharma + * 2021 Martin Owens * * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ @@ -19,13 +30,16 @@ #include "document.h" #include "gc-finalized.h" #include "layer-manager.h" -#include "layer-model.h" #include "selection.h" #include "inkgc/gc-managed.h" +#include "object-hierarchy.h" +#include "object/sp-defs.h" +#include "object/sp-root.h" #include "object/sp-item-group.h" +#include "util/find-last-if.h" #include "xml/node-observer.h" namespace Inkscape { @@ -76,83 +90,16 @@ public: GQuark _labelAttr; }; -/* -namespace { - -Util::ptr_shared stringify_node(Node const &node); - -Util::ptr_shared stringify_obj(SPObject const &obj) { - gchar *string; - - if (obj.id) { - string = g_strdup_printf("SPObject(%p)=%s repr(%p)", &obj, obj.id, obj.repr); - } else { - string = g_strdup_printf("SPObject(%p) repr(%p)", &obj, obj.repr); - } - - Util::ptr_shared result=Util::share_string(string); - g_free(string); - return result; - -} - -typedef Debug::SimpleEvent DebugLayer; - -class DebugLayerNote : public DebugLayer { -public: - DebugLayerNote(Util::ptr_shared descr) - : DebugLayer(Util::share_static_string("layer-note")) - { - _addProperty("descr", descr); - } -}; - -class DebugLayerRebuild : public DebugLayer { -public: - DebugLayerRebuild() - : DebugLayer(Util::share_static_string("rebuild-layers")) - { - } -}; - -class DebugLayerObj : public DebugLayer { -public: - DebugLayerObj(SPObject const& obj, Util::ptr_shared name) - : DebugLayer(name) - { - _addProperty("layer", stringify_obj(obj)); - } -}; - -class DebugAddLayer : public DebugLayerObj { -public: - DebugAddLayer(SPObject const &obj) - : DebugLayerObj(obj, Util::share_static_string("add-layer")) - { - } -}; - - -} // end of namespace -*/ - LayerManager::LayerManager(SPDesktop *desktop) -: _desktop(desktop), _document(nullptr) + : _desktop(desktop) + , _document(nullptr) { - auto layers = desktop->layers; - _layer_connection = layers->_layer_changed_signal.connect(sigc::mem_fun(*this, &LayerManager::_selectedLayerChanged)); - _activate_connection = layers->_layer_activated_signal.connect(sigc::mem_fun(*this, &LayerManager::_layer_activated)); - _deactivate_connection = layers->_layer_deactivated_signal.connect(sigc::mem_fun(*this, &LayerManager::_layer_deactivated)); - - sigc::bound_mem_functor1 first = sigc::mem_fun(*this, &LayerManager::_setDocument); - - // This next line has problems on gcc 4.0.2 - sigc::slot base2 = first; - - sigc::slot slot2 = sigc::hide<0>( base2 ); - _document_connection = desktop->connectDocumentReplaced( slot2 ); - - _setDocument(desktop->doc()); + _layer_hierarchy = std::make_unique(nullptr); + _layer_hierarchy->connectAdded(sigc::mem_fun(*this, &LayerManager::_layer_activated)); + _layer_hierarchy->connectRemoved(sigc::mem_fun(*this, &LayerManager::_layer_deactivated)); + _layer_hierarchy->connectChanged(sigc::mem_fun(*this, &LayerManager::_selectedLayerChanged)); + _document_connection = desktop->connectDocumentReplaced(sigc::mem_fun(this, &LayerManager::_setDocument)); + _setDocument(desktop, desktop->doc()); } LayerManager::~LayerManager() @@ -165,17 +112,20 @@ LayerManager::~LayerManager() _document = nullptr; } -void LayerManager::setCurrentLayer( SPObject* obj ) -{ - //g_return_if_fail( _desktop->layers->currentRoot() ); - if ( _desktop->layers->currentRoot() ) { - _desktop->layers->setCurrentLayer( obj ); - - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - if (prefs->getBool("/options/selection/layerdeselect", true)) { - _desktop->getSelection()->clear(); - } +void LayerManager::_setDocument(SPDesktop *, SPDocument *document) { + _layer_hierarchy->clear(); + _resource_connection.disconnect(); + _document = document; + if (document) { + _resource_connection = document->connectResourcesChanged("layer", sigc::mem_fun(*this, &LayerManager::_rebuild)); + _layer_hierarchy->setTop(document->getRoot()); } + _rebuild(); +} + +void LayerManager::_objectModified( SPObject* obj, guint /*flags*/ ) +{ + _details_changed_signal.emit( obj ); } void LayerManager::_layer_activated(SPObject *layer) @@ -192,6 +142,29 @@ void LayerManager::_layer_deactivated(SPObject *layer) } } +/** + * Returns current root (=bottom) layer. + */ +SPGroup *LayerManager::currentRoot() const +{ + return dynamic_cast(_layer_hierarchy->top()); +} + +/** + * Returns current top layer. + */ +SPGroup *LayerManager::currentLayer() const +{ + return dynamic_cast(_layer_hierarchy->bottom()); +} + +/** + * Resets the bottom layer to the current root + */ +void LayerManager::reset() { + _layer_hierarchy->setBottom(currentRoot()); +} + /* * Return a unique layer name similar to param label @@ -226,11 +199,10 @@ Glib::ustring LayerManager::getNextLayerName( SPObject* obj, gchar const *label) std::set currentNames; std::vector layers = _document->getResourceList("layer"); - SPObject *root = _desktop->layers->currentRoot(); - if ( root ) { + if (currentRoot()) { for (auto layer : layers) { if (layer != obj) - currentNames.insert( layer->label() ? Glib::ustring(layer->label()) : Glib::ustring() ); + currentNames.insert(layer->label() ? Glib::ustring(layer->label()) : Glib::ustring()); } } @@ -256,63 +228,70 @@ void LayerManager::renameLayer( SPObject* obj, gchar const *label, bool uniquify obj->setLabel( result.c_str() ); } +/** + * Sets the current layer of the desktop. + * + * Make \a object the top layer. + */ +void LayerManager::setCurrentLayer(SPObject *object) { + if (currentRoot()) { + g_return_if_fail(SP_IS_GROUP(object)); + g_return_if_fail( currentRoot() == object || (currentRoot() && currentRoot()->isAncestorOf(object)) ); + _layer_hierarchy->setBottom(object); + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if (prefs->getBool("/options/selection/layerdeselect", true)) { + _desktop->getSelection()->clear(); + } + } +} -void LayerManager::_setDocument(SPDocument *document) { - if (_document) { - _resource_connection.disconnect(); +void LayerManager::toggleHideAllLayers(bool hide) { + for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), currentRoot()); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) { + SP_ITEM(obj)->setHidden(hide); } - _document = document; - if (document) { - _resource_connection = document->connectResourcesChanged("layer", sigc::mem_fun(*this, &LayerManager::_rebuild)); +} +void LayerManager::toggleLockAllLayers(bool lock) { + for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), currentRoot()); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) { + SP_ITEM(obj)->setLocked(lock); } - _rebuild(); } -void LayerManager::_objectModified( SPObject* obj, guint /*flags*/ ) -{ - _details_changed_signal.emit( obj ); -} void LayerManager::_rebuild() { // Debug::EventTracker tracker1(); _watchers.clear(); - _clear(); - if (!_document) // http://sourceforge.net/mailarchive/forum.php?thread_name=5747bce9a7ed077c1b4fc9f0f4f8a5e0%40localhost&forum_name=inkscape-devel + if (!_document || !_desktop) return; std::vector layers = _document->getResourceList("layer"); - SPObject *root = _desktop->layers->currentRoot(); - if ( root ) { + if (auto root = _desktop->layerManager().currentRoot()) { _addOne(root); + std::set layersToAdd; - std::set layersToAdd; - - for ( std::vector::const_iterator iter = layers.begin(); iter != layers.end(); ++iter ) { - SPObject *layer = *iter; + for (auto &layer : layers) { bool needsAdd = false; - std::set additional; + std::set additional; - if ( root->isAncestorOf(layer) ) { + if (root->isAncestorOf(layer)) { needsAdd = true; - for ( SPObject* curr = layer; curr && (curr != root) && needsAdd; curr = curr->parent ) { - if ( SP_IS_GROUP(curr) ) { - SPGroup* group = SP_GROUP(curr); - if ( group->layerMode() == SPGroup::LAYER ) { + for (SPObject* curr = layer; curr && (curr != root) && needsAdd; curr = curr->parent) { + if (auto group = dynamic_cast(curr)) { + if (group->isLayer()) { // If we have a layer-group as the one or a parent, ensure it is listed as a valid layer. needsAdd &= ( std::find(layers.begin(),layers.end(),curr) != layers.end() ); - // XML Tree being used here directly while it shouldn't be... + // XML Tree being used here directly while it shouldn't be... if ( (!(group->getRepr())) || (!(group->getRepr()->parent())) ) { needsAdd = false; } } else { // If a non-layer group is a parent of layer groups, then show it also as a layer. // TODO add the magic Inkscape group mode? - // XML Tree being used directly while it shouldn't be... + // XML Tree being used directly while it shouldn't be... if ( group->getRepr() && group->getRepr()->parent() ) { additional.insert(group); } else { @@ -322,12 +301,12 @@ void LayerManager::_rebuild() { } } } - if ( needsAdd ) { - if ( !includes(layer) ) { + if (needsAdd) { + if (!includes(layer)) { layersToAdd.insert(SP_GROUP(layer)); } for (auto it : additional) { - if ( !includes(it) ) { + if (!includes(it)) { layersToAdd.insert(it); } } @@ -346,16 +325,18 @@ void LayerManager::_rebuild() { } Node const* node = higher ? higher->getRepr() : nullptr; if ( node && node->parent() ) { -// Debug::EventTracker tracker(*layer); - _watchers.emplace_back(new LayerWatcher(this, layer)); - _addOne(layer); } } } } +static bool is_layer(SPObject &object) { + return SP_IS_GROUP(&object) && + SP_GROUP(&object)->layerMode() == SPGroup::LAYER; +} + // Connected to the desktop's CurrentLayerChanged signal void LayerManager::_selectedLayerChanged(SPObject *top, SPObject *bottom) { @@ -363,6 +344,261 @@ void LayerManager::_selectedLayerChanged(SPObject *top, SPObject *bottom) _layer_changed_signal.emit(bottom); } +/** Finds the next sibling layer for a \a layer + * + * @returns NULL if there are no further layers under a parent + */ +static SPObject *next_sibling_layer(SPObject *layer) { + if (layer->parent == nullptr) { + return nullptr; + } + SPObject::ChildrenList &list = layer->parent->children; + auto l = std::find_if(++list.iterator_to(*layer), list.end(), &is_layer); + return l != list.end() ? &*l : nullptr; +} + +/** Finds the previous sibling layer for a \a layer + * + * @returns NULL if there are no further layers under a parent + */ +static SPObject *previous_sibling_layer(SPObject *layer) { + using Inkscape::Algorithms::find_last_if; + + SPObject::ChildrenList &list = layer->parent->children; + auto l = find_last_if(list.begin(), list.iterator_to(*layer), &is_layer); + return l != list.iterator_to(*layer) ? &*(l) : nullptr; +} + +/** Finds the first child of a \a layer + * + * @returns the layer itself if layer has no sublayers + */ +static SPObject *first_descendant_layer(SPObject *layer) { + while (true) { + auto first_descendant = std::find_if(layer->children.begin(), layer->children.end(), &is_layer); + if (first_descendant == layer->children.end()) { + break; + } + layer = &*first_descendant; + } + + return layer; +} + +/** Finds the last (topmost) child of a \a layer + * + * @returns NULL if layer has no sublayers + */ +static SPObject *last_child_layer(SPObject *layer) { + using Inkscape::Algorithms::find_last_if; + + auto l = find_last_if(layer->children.begin(), layer->children.end(), &is_layer); + return l != layer->children.end() ? &*l : nullptr; +} + +static SPObject *last_elder_layer(SPObject *root, SPObject *layer) { + using Inkscape::Algorithms::find_last_if; + SPObject *result = nullptr; + + while ( layer != root ) { + SPObject *sibling(previous_sibling_layer(layer)); + if (sibling) { + result = sibling; + break; + } + layer = layer->parent; + } + + return result; +} + +/** Finds the next layer under \a root, relative to \a layer in + * depth-first order. + * + * @returns NULL if there are no further layers under \a root + */ +SPObject *next_layer(SPObject *root, SPObject *layer) { + g_return_val_if_fail(layer != nullptr, NULL); + SPObject *result = nullptr; + + SPObject *sibling = next_sibling_layer(layer); + if (sibling) { + result = first_descendant_layer(sibling); + } else if ( layer->parent != root ) { + result = layer->parent; + } + + return result; +} + + +/** Finds the previous layer under \a root, relative to \a layer in + * depth-first order. + * + * @returns NULL if there are no prior layers under \a root. + */ +SPObject *previous_layer(SPObject *root, SPObject *layer) { + using Inkscape::Algorithms::find_last_if; + + g_return_val_if_fail(layer != nullptr, NULL); + SPObject *result = nullptr; + + SPObject *child = last_child_layer(layer); + if (child) { + result = child; + } else if ( layer != root ) { + SPObject *sibling = previous_sibling_layer(layer); + if (sibling) { + result = sibling; + } else { + result = last_elder_layer(root, layer->parent); + } + } + + return result; +} + +/** +* Creates a new layer. Advances to the next layer id indicated + * by the string "layerNN", then creates a new group object of + * that id with attribute inkscape:groupmode='layer', and finally + * appends the new group object to \a root after object \a layer. + * + * \pre \a root should be either \a layer or an ancestor of it + */ +SPObject *create_layer(SPObject *root, SPObject *layer, LayerRelativePosition position) { + SPDocument *document = root->document; + + static int layer_suffix=1; + gchar *id=nullptr; + do { + g_free(id); + id = g_strdup_printf("layer%d", layer_suffix++); + } while (document->getObjectById(id)); + + Inkscape::XML::Document *xml_doc = document->getReprDoc(); + Inkscape::XML::Node *repr = xml_doc->createElement("svg:g"); + repr->setAttribute("inkscape:groupmode", "layer"); + repr->setAttribute("id", id); + g_free(id); + + if ( LPOS_CHILD == position ) { + root = layer; + SPObject *child_layer = Inkscape::last_child_layer(layer); + if ( nullptr != child_layer ) { + layer = child_layer; + } + } + + if ( root == layer ) { + root->getRepr()->appendChild(repr); + } else { + Inkscape::XML::Node *layer_repr = layer->getRepr(); + layer_repr->parent()->addChild(repr, layer_repr); + + if ( LPOS_BELOW == position ) { + SP_ITEM(document->getObjectByRepr(repr))->lowerOne(); + } + } + + return document->getObjectByRepr(repr); +} + +/** + * Toggle the sensitivity of every layer except the given layer. + */ +void LayerManager::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 layers; + for ( SPObject* obj = Inkscape::next_layer(currentRoot(), object); obj; obj = Inkscape::next_layer(currentRoot(), obj) ) { + // Don't 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 (auto & layer : layers) { + SP_ITEM(layer)->setLocked(othersLocked); + } +} + +/** + * Toggle the visibility of every layer except the given layer. + */ +void LayerManager::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) ) { + // 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 (auto & layer : layers) { + SP_ITEM(layer)->setHidden(othersShowing); + } +} + +/** + * Return layer that contains \a object. + */ +SPObject *LayerManager::layerForObject(SPObject *object) { + g_return_val_if_fail(object != nullptr, NULL); + if (isLayer(object)) { + return object; + } + + 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 nullptr; + object = object->parent; + } + return object; +} + +/** + * True if object is a layer. + */ +bool LayerManager::isLayer(SPObject *object) const { + if (auto group = dynamic_cast(object)) { + return group->effectiveLayerMode(_desktop->dkey) == SPGroup::LAYER; + } + return false; +} + } /* diff --git a/src/layer-manager.h b/src/layer-manager.h index 2efe6fb2b2..90426f5357 100644 --- a/src/layer-manager.h +++ b/src/layer-manager.h @@ -16,22 +16,21 @@ #include #include "document-subset.h" -#include "gc-finalized.h" #include "inkgc/gc-soft-ptr.h" class SPDesktop; class SPDocument; +class SPGroup; namespace Inkscape { + class ObjectHierarchy; -class LayerManager : public DocumentSubset, - public GC::Finalized +class LayerManager : public DocumentSubset { public: LayerManager(SPDesktop *desktop); ~LayerManager() override; - void setCurrentLayer( SPObject* obj ); void renameLayer( SPObject* obj, char const *label, bool uniquify ); Glib::ustring getNextLayerName( SPObject* obj, char const *label); @@ -43,12 +42,24 @@ public: return _details_changed_signal.connect(slot); } + SPGroup *currentRoot() const; + SPGroup *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; + private: friend class LayerWatcher; class LayerWatcher; void _objectModified( SPObject* obj, unsigned int flags ); - void _setDocument(SPDocument *document); + void _setDocument(SPDesktop *, SPDocument *document); void _rebuild(); void _selectedLayerChanged(SPObject *top, SPObject *bottom); @@ -61,14 +72,25 @@ private: sigc::connection _document_connection; sigc::connection _resource_connection; - GC::soft_ptr _desktop; + SPDesktop *_desktop; SPDocument *_document; std::vector> _watchers; + std::unique_ptr _layer_hierarchy; + + sigc::signal _layer_changed_signal; + sigc::signal _details_changed_signal; +}; - sigc::signal _layer_changed_signal; - sigc::signal _details_changed_signal; +enum LayerRelativePosition { + LPOS_ABOVE, + LPOS_BELOW, + LPOS_CHILD, }; + +SPObject *create_layer(SPObject *root, SPObject *layer, LayerRelativePosition position); +SPObject *next_layer(SPObject *root, SPObject *layer); +SPObject *previous_layer(SPObject *root, SPObject *layer); } diff --git a/src/layer-model.cpp b/src/layer-model.cpp deleted file mode 100644 index c7e22a666e..0000000000 --- a/src/layer-model.cpp +++ /dev/null @@ -1,257 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Editable view implementation - * - * Authors: - * Lauris Kaplinski - * MenTaLguY - * bulia byak - * Ralf Stephan - * John Bintz - * Johan Engelen - * Jon A. Cruz - * 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 v2+, read the file 'COPYING' for more information. - */ - -#include "layer-model.h" - -#include "document.h" -#include "layer-fns.h" -#include "object-hierarchy.h" - -#include "object/sp-defs.h" -#include "object/sp-item.h" -#include "object/sp-item-group.h" -#include "object/sp-root.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( nullptr ) - , _layer_hierarchy( nullptr ) - , _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(nullptr); - _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. - */ -SPGroup *LayerModel::currentRoot() const -{ - return _layer_hierarchy ? dynamic_cast(_layer_hierarchy->top()) : nullptr; -} - -/** - * Returns current top layer. - */ -SPGroup *LayerModel::currentLayer() const -{ - return _layer_hierarchy ? dynamic_cast(_layer_hierarchy->bottom()) : nullptr; -} - -/** - * 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 layers; - for ( SPObject* obj = Inkscape::next_layer(currentRoot(), object); obj; obj = Inkscape::next_layer(currentRoot(), obj) ) { - // Don't 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 (auto & layer : layers) { - SP_ITEM(layer)->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 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 (auto & layer : layers) { - SP_ITEM(layer)->setHidden(othersShowing); - } -} - -/** - * Return layer that contains \a object. - */ -SPObject *LayerModel::layerForObject(SPObject *object) { - g_return_val_if_fail(object != nullptr, NULL); - if (isLayer(object)) { - return object; - } - - 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 nullptr; - 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 deleted file mode 100644 index f42e5d6018..0000000000 --- a/src/layer-model.h +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -#ifndef SEEN_INKSCAPE_LAYER_MODEL_H -#define SEEN_INKSCAPE_LAYER_MODEL_H - -/* - * Authors: - * Lauris Kaplinski - * Frank Felfe - * bulia byak - * Ralf Stephan - * John Bintz - * Johan Engelen - * Jon A. Cruz get - * Abhishek Sharma - * Eric Greveson - * - * 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 v2+, read the file 'COPYING' for more information. - * - */ - -#include -#include - -class SPDocument; -class SPObject; -class SPGroup; - -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(); - - SPGroup *currentRoot() const; - SPGroup *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 _layer_activated_signal; - sigc::signal _layer_deactivated_signal; - sigc::signal _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 : diff --git a/src/object/sp-flowtext.cpp b/src/object/sp-flowtext.cpp index ffaf46b213..b6a0cb16f0 100644 --- a/src/object/sp-flowtext.cpp +++ b/src/object/sp-flowtext.cpp @@ -42,6 +42,8 @@ #include "display/curve.h" #include "display/drawing-text.h" +#include "layer-manager.h" + SPFlowtext::SPFlowtext() : SPItem(), par_indent(0), _optimizeScaledText(false) @@ -646,7 +648,7 @@ bool SPFlowtext::has_internal_frame() const SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0, Geom::Point p1) { SPDocument *doc = desktop->getDocument(); - auto const parent = dynamic_cast(desktop->layers->currentLayer()); + auto const parent = dynamic_cast(desktop->layerManager().currentLayer()); assert(parent); Inkscape::XML::Document *xml_doc = doc->getReprDoc(); diff --git a/src/object/sp-namedview.cpp b/src/object/sp-namedview.cpp index 76958bf757..4d0f5094e8 100644 --- a/src/object/sp-namedview.cpp +++ b/src/object/sp-namedview.cpp @@ -36,7 +36,7 @@ #include "sp-item-group.h" #include "sp-namedview.h" #include "preferences.h" -#include "layer-model.h" +#include "layer-manager.h" #include "desktop.h" #include "conn-avoid-ref.h" // for defaultConnSpacing. #include "sp-root.h" @@ -807,13 +807,13 @@ void sp_namedview_update_layers_from_document (SPDesktop *desktop) // if that didn't work out, look for the topmost layer if (!layer) { for (auto& iter: document->getRoot()->children) { - if (desktop->layers->isLayer(&iter)) { + if (desktop->layerManager().isLayer(&iter)) { layer = &iter; } } } if (layer) { - desktop->layers->setCurrentLayer(layer); + desktop->layerManager().setCurrentLayer(layer); } // FIXME: find a better place to do this @@ -851,7 +851,7 @@ void sp_namedview_document_from_window(SPDesktop *desktop) view->setAttributeInt("inkscape:window-maximized", desktop->is_maximized()); } - view->setAttribute("inkscape:current-layer", desktop->layers->currentLayer()->getId()); + view->setAttribute("inkscape:current-layer", desktop->layerManager().currentLayer()->getId()); // restore undoability DocumentUndo::setUndoSensitive(desktop->getDocument(), saved); diff --git a/src/object/sp-symbol.cpp b/src/object/sp-symbol.cpp index a9d45cfcd7..4c614ed74c 100644 --- a/src/object/sp-symbol.cpp +++ b/src/object/sp-symbol.cpp @@ -24,6 +24,7 @@ #include "document.h" #include "inkscape.h" #include "desktop.h" +#include "layer-manager.h" SPSymbol::SPSymbol() : SPGroup(), SPViewBox() { } @@ -78,7 +79,7 @@ void SPSymbol::unSymbol() //TODO: Better handle if no desktop, currently go to defs without it SPDesktop *desktop = SP_ACTIVE_DESKTOP; if(desktop && desktop->doc() == doc) { - desktop->layers->currentLayer()->getRepr()->appendChild(group); + desktop->layerManager().currentLayer()->getRepr()->appendChild(group); } else { parent->getRepr()->appendChild(group); } diff --git a/src/object/sp-text.cpp b/src/object/sp-text.cpp index a1b69e7117..996d59cdc2 100644 --- a/src/object/sp-text.cpp +++ b/src/object/sp-text.cpp @@ -61,6 +61,8 @@ #include "livarot/Shape.h" #include "display/curve.h" +#include "layer-manager.h" + /*##################################################### # SPTEXT #####################################################*/ @@ -1198,7 +1200,7 @@ SPItem *create_text_with_inline_size (SPDesktop *desktop, Geom::Point p0, Geom:: Inkscape::XML::Node *text_repr = xml_doc->createElement("svg:text"); text_repr->setAttribute("xml:space", "preserve"); // we preserve spaces in the text objects we create - auto layer = desktop->layers->currentLayer(); + auto layer = desktop->layerManager().currentLayer(); g_assert(layer != nullptr); SPText *text_object = dynamic_cast(layer->appendChildRepr(text_repr)); @@ -1235,7 +1237,7 @@ SPItem *create_text_with_inline_size (SPDesktop *desktop, Geom::Point p0, Geom:: SPItem *create_text_with_rectangle (SPDesktop *desktop, Geom::Point p0, Geom::Point p1) { SPDocument *doc = desktop->getDocument(); - auto const parent = desktop->layers->currentLayer(); + auto const parent = desktop->layerManager().currentLayer(); assert(parent); Inkscape::XML::Document *xml_doc = doc->getReprDoc(); diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 7e1902a999..ed2947f48e 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -39,9 +39,7 @@ #include "desktop.h" #include "document-undo.h" #include "gradient-drag.h" -#include "layer-fns.h" #include "layer-manager.h" -#include "layer-model.h" #include "message-stack.h" #include "path-chemistry.h" #include "selection.h" @@ -290,7 +288,7 @@ void SelectionHelper::fixSelection(SPDesktop *dt) for(auto i = boost::rbegin(selList); i != boost::rend(selList); ++i) { SPItem *item = *i; if( item && - !dt->layers->isLayer(item) && + !dt->layerManager().isLayer(item) && (!item->isLocked())) { items.push_back(item); @@ -420,7 +418,7 @@ void ObjectSet::deleteItems() clear(); sp_selection_delete_impl(selected); if (SPDesktop *d = desktop()) { - d->layers->currentLayer()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + d->layerManager().currentLayer()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); /* a tool may have set up private information in it's selection context * that depends on desktop items. I think the only sane way to deal with @@ -474,7 +472,7 @@ void ObjectSet::duplicate(bool suppressDone, bool duplicateLayer) if(duplicateLayer){ reprs.clear(); - reprs.push_back(desktop()->layers->currentLayer()->getRepr()); + reprs.push_back(desktop()->layerManager().currentLayer()->getRepr()); } clear(); @@ -624,7 +622,7 @@ void ObjectSet::duplicate(bool suppressDone, bool duplicateLayer) else{ SPObject* new_layer = doc->getObjectByRepr(copies[0]); gchar* name = g_strdup_printf(_("%s copy"), new_layer->label()); - desktop()->layer_manager->renameLayer( new_layer, name, TRUE ); + desktop()->layerManager().renameLayer( new_layer, name, TRUE ); g_free(name); } } @@ -634,10 +632,11 @@ void sp_edit_clear_all(Inkscape::Selection *selection) if (!selection) return; - SPDocument *doc = selection->layers()->getDocument(); + auto desktop = selection->desktop(); + SPDocument *doc = desktop->getDocument(); selection->clear(); - SPGroup *group = dynamic_cast(selection->layers()->currentLayer()); + SPGroup *group = dynamic_cast(desktop->layerManager().currentLayer()); g_return_if_fail(group != nullptr); std::vector items = sp_item_group_item_list(group); @@ -663,7 +662,7 @@ std::vector &get_all_items(std::vector &list, SPObject *from, for (auto& child: from->children) { SPItem *item = dynamic_cast(&child); if (item && - !desktop->layers->isLayer(item) && + !desktop->layerManager().isLayer(item) && (!onlysensitive || !item->isLocked()) && (!onlyvisible || !desktop->itemIsHidden(item)) && (exclude.empty() || exclude.end() == std::find(exclude.begin(), exclude.end(), &child)) @@ -672,7 +671,7 @@ std::vector &get_all_items(std::vector &list, SPObject *from, list.insert(list.begin(),item); } - if (ingroups || (item && desktop->layers->isLayer(item))) { + if (ingroups || (item && desktop->layerManager().isLayer(item))) { list = get_all_items(list, &child, desktop, onlyvisible, onlysensitive, ingroups, exclude); } } @@ -687,7 +686,7 @@ static void sp_edit_select_all_full(SPDesktop *dt, bool force_all_layers, bool i Inkscape::Selection *selection = dt->getSelection(); - auto layer = dt->layers->currentLayer(); + auto layer = dt->layerManager().currentLayer(); g_return_if_fail(layer); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -717,7 +716,7 @@ static void sp_edit_select_all_full(SPDesktop *dt, bool force_all_layers, bool i if (item && (!onlysensitive || !item->isLocked())) { if (!onlyvisible || !dt->itemIsHidden(item)) { - if (!dt->layers->isLayer(item)) { + if (!dt->layerManager().isLayer(item)) { if (!invert || exclude.end() == std::find(exclude.begin(),exclude.end(),item)) { items.push_back(item); // leave it in the list } @@ -730,12 +729,12 @@ static void sp_edit_select_all_full(SPDesktop *dt, bool force_all_layers, bool i } case PREFS_SELECTION_LAYER_RECURSIVE: { std::vector x; - items = get_all_items(x, dt->layers->currentLayer(), dt, onlyvisible, onlysensitive, FALSE, exclude); + items = get_all_items(x, dt->layerManager().currentLayer(), dt, onlyvisible, onlysensitive, FALSE, exclude); break; } default: { std::vector x; - items = get_all_items(x, dt->layers->currentRoot(), dt, onlyvisible, onlysensitive, FALSE, exclude); + items = get_all_items(x, dt->layerManager().currentRoot(), dt, onlyvisible, onlysensitive, FALSE, exclude); break; } } @@ -1449,23 +1448,23 @@ void ObjectSet::toNextLayer(bool skip_undo) std::vector items_copy(items().begin(), items().end()); bool no_more = false; // Set to true, if no more layers above - SPObject *next=Inkscape::next_layer(dt->layers->currentRoot(), dt->layers->currentLayer()); + SPObject *next=Inkscape::next_layer(dt->layerManager().currentRoot(), dt->layerManager().currentLayer()); if (next) { clear(); sp_selection_change_layer_maintain_clones(items_copy,next); std::vector temp_clip; sp_selection_copy_impl(items_copy, temp_clip, dt->doc()->getReprDoc()); sp_selection_delete_impl(items_copy, false, false); - next=Inkscape::next_layer(dt->layers->currentRoot(), dt->layers->currentLayer()); // Fixes bug 1482973: crash while moving layers + next=Inkscape::next_layer(dt->layerManager().currentRoot(), dt->layerManager().currentLayer()); // Fixes bug 1482973: crash while moving layers std::vector copied; if (next) { copied = sp_selection_paste_impl(dt->getDocument(), next, temp_clip); } else { - copied = sp_selection_paste_impl(dt->getDocument(), dt->layers->currentLayer(), temp_clip); + copied = sp_selection_paste_impl(dt->getDocument(), dt->layerManager().currentLayer(), temp_clip); no_more = true; } setReprList(copied); - if (next) dt->layers->setCurrentLayer(next); + if (next) dt->layerManager().setCurrentLayer(next); if ( !skip_undo ) { DocumentUndo::done(dt->getDocument(), _("Raise to next layer"), INKSCAPE_ICON("selection-move-to-layer-above")); } @@ -1494,23 +1493,23 @@ void ObjectSet::toPrevLayer(bool skip_undo) std::vector items_copy(items().begin(), items().end()); bool no_more = false; // Set to true, if no more layers below - SPObject *next=Inkscape::previous_layer(dt->layers->currentRoot(), dt->layers->currentLayer()); + SPObject *next=Inkscape::previous_layer(dt->layerManager().currentRoot(), dt->layerManager().currentLayer()); if (next) { clear(); sp_selection_change_layer_maintain_clones(items_copy,next); std::vector temp_clip; sp_selection_copy_impl(items_copy, temp_clip, dt->doc()->getReprDoc()); // we're in the same doc, so no need to copy defs sp_selection_delete_impl(items_copy, false, false); - next=Inkscape::previous_layer(dt->layers->currentRoot(), dt->layers->currentLayer()); // Fixes bug 1482973: crash while moving layers + next=Inkscape::previous_layer(dt->layerManager().currentRoot(), dt->layerManager().currentLayer()); // Fixes bug 1482973: crash while moving layers std::vector copied; if (next) { copied = sp_selection_paste_impl(dt->getDocument(), next, temp_clip); } else { - copied = sp_selection_paste_impl(dt->getDocument(), dt->layers->currentLayer(), temp_clip); + copied = sp_selection_paste_impl(dt->getDocument(), dt->layerManager().currentLayer(), temp_clip); no_more = true; } setReprList( copied); - if (next) dt->layers->setCurrentLayer(next); + if (next) dt->layerManager().setCurrentLayer(next); if ( !skip_undo ) { DocumentUndo::done(dt->getDocument(), _("Lower to previous layer"), INKSCAPE_ICON("selection-move-to-layer-below")); } @@ -1574,10 +1573,9 @@ void ObjectSet::toLayer(SPObject *moveto, bool skip_undo, Inkscape::XML::Node *a std::vector copied = sp_selection_paste_impl(document(), moveto, temp_clip, after); setReprList(copied); if (!temp_clip.empty()) temp_clip.clear(); - if (moveto && dt) dt->setCurrentLayer(moveto); - if ( !skip_undo ) { - DocumentUndo::done(document(), SP_VERB_LAYER_MOVE_TO, - _("Move selection to layer")); + if (moveto && dt) dt->layerManager().setCurrentLayer(moveto); + if (!skip_undo) { + DocumentUndo::done(document(), _("Move selection to layer"), INKSCAPE_ICON("selection-move-to-layer")); } } } @@ -1981,7 +1979,7 @@ void sp_select_same_fill_stroke_style(SPDesktop *desktop, gboolean fill, gboolea bool onlyvisible = prefs->getBool("/options/kbselection/onlyvisible", true); bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true); - SPObject *root = desktop->layers->currentRoot(); + SPObject *root = desktop->layerManager().currentRoot(); bool ingroup = true; // Apply the same layer logic to select same as used for select all. @@ -2049,7 +2047,7 @@ void sp_select_same_object_type(SPDesktop *desktop) bool onlysensitive = prefs->getBool("/options/kbselection/onlysensitive", true); bool ingroups = TRUE; std::vector x,y; - std::vector all_list = get_all_items(x, desktop->layers->currentRoot(), desktop, onlyvisible, onlysensitive, ingroups, y); + std::vector all_list = get_all_items(x, desktop->layerManager().currentRoot(), desktop, onlyvisible, onlysensitive, ingroups, y); std::vector matches = all_list; Inkscape::Selection *selection = desktop->getSelection(); @@ -2468,7 +2466,7 @@ SPItem *next_item(SPDesktop *desktop, std::vector &path, SPObject *r SPObject *object=path.back(); path.pop_back(); g_assert(object->parent == root); - if (desktop->layers->isLayer(object)) { + if (desktop->layerManager().isLayer(object)) { found = next_item(desktop, path, object, only_in_viewport, inlayer, onlyvisible, onlysensitive); } iter = children = D::siblings_after(object); @@ -2478,7 +2476,7 @@ SPItem *next_item(SPDesktop *desktop, std::vector &path, SPObject *r while ( !D::isNull(iter) && !found ) { SPObject *object=D::object(iter); - if (desktop->layers->isLayer(object)) { + if (desktop->layerManager().isLayer(object)) { if (PREFS_SELECTION_LAYER != inlayer) { // recurse into sublayers std::vector empt; found = next_item(desktop, empt, object, only_in_viewport, inlayer, onlyvisible, onlysensitive); @@ -2489,7 +2487,7 @@ SPItem *next_item(SPDesktop *desktop, std::vector &path, SPObject *r ( !only_in_viewport || desktop->isWithinViewport(item) ) && ( !onlyvisible || !desktop->itemIsHidden(item)) && ( !onlysensitive || !item->isLocked()) && - !desktop->layers->isLayer(item) ) + !desktop->layerManager().isLayer(item) ) { found = item; } @@ -2550,7 +2548,7 @@ sp_selection_item_next(SPDesktop *desktop) if (PREFS_SELECTION_ALL != inlayer) { root = selection->activeContext(); } else { - root = desktop->layers->currentRoot(); + root = desktop->layerManager().currentRoot(); } std::vector vec(selection->items().begin(), selection->items().end()); @@ -2581,7 +2579,7 @@ sp_selection_item_prev(SPDesktop *desktop) if (PREFS_SELECTION_ALL != inlayer) { root = selection->activeContext(); } else { - root = desktop->layers->currentRoot(); + root = desktop->layerManager().currentRoot(); } std::vector vec(selection->items().begin(), selection->items().end()); @@ -3903,7 +3901,7 @@ void ObjectSet::setClipGroup() if (apply_to_layer) { // all selected items are used for mask, which is applied to a layer - apply_to_items.push_back(desktop()->layers->currentLayer()); + apply_to_items.push_back(desktop()->layerManager().currentLayer()); } for (std::vector::const_iterator i=items_.begin();i!=items_.end();++i) { @@ -4380,14 +4378,14 @@ static void itemtree_map(void (*f)(SPItem *, SPDesktop *), SPObject *root, SPDes // don't operate on layers { SPItem *item = dynamic_cast(root); - if (item && !desktop->layers->isLayer(item)) { + if (item && !desktop->layerManager().isLayer(item)) { f(item, desktop); } } for (auto& child: root->children) { //don't recurse into locked layers SPItem *item = dynamic_cast(&child); - if (!(item && desktop->layers->isLayer(item) && item->isLocked())) { + if (!(item && desktop->layerManager().isLayer(item) && item->isLocked())) { itemtree_map(f, &child, desktop); } } @@ -4410,9 +4408,9 @@ static void process_all(void (*f)(SPItem *, SPDesktop *), SPDesktop *dt, bool la SPObject *root; if (layer_only) { - root = dt->layers->currentLayer(); + root = dt->layerManager().currentLayer(); } else { - root = dt->layers->currentRoot(); + root = dt->layerManager().currentRoot(); } itemtree_map(f, root, dt); diff --git a/src/selection-describer.cpp b/src/selection-describer.cpp index 526d5269ed..9e529d8b61 100644 --- a/src/selection-describer.cpp +++ b/src/selection-describer.cpp @@ -21,7 +21,7 @@ #include "selection-describer.h" -#include "layer-model.h" +#include "layer-manager.h" #include "selection.h" #include "desktop.h" @@ -110,8 +110,8 @@ void SelectionDescriber::_updateMessageFromSelection(Inkscape::Selection *select } else { SPItem *item = items[0]; g_assert(item != nullptr); - SPObject *layer = selection->layers()->layerForObject(item); - SPObject *root = selection->layers()->currentRoot(); + SPObject *layer = selection->desktop()->layerManager().layerForObject(item); + SPObject *root = selection->desktop()->layerManager().currentRoot(); // Layer name gchar *layer_name; diff --git a/src/selection.cpp b/src/selection.cpp index 1e3a69fa82..403c02a2fc 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -30,6 +30,7 @@ #include "ui/tool/multi-path-manipulator.h" #include "ui/tool/path-manipulator.h" #include "ui/tool/control-point-selection.h" +#include "layer-manager.h" #include "object/sp-path.h" #include "object/sp-defs.h" #include "object/sp-shape.h" @@ -39,9 +40,8 @@ namespace Inkscape { -Selection::Selection(LayerModel *layers, SPDesktop *desktop): +Selection::Selection(SPDesktop *desktop): ObjectSet(desktop), - _layers(layers), _selection_context(nullptr), _flags(0), _idle(0), @@ -51,7 +51,6 @@ Selection::Selection(LayerModel *layers, SPDesktop *desktop): } Selection::~Selection() { - _layers = nullptr; if (_idle) { g_source_remove(_idle); _idle = 0; @@ -95,7 +94,7 @@ void Selection::_emitModified(guint flags) { void Selection::_emitChanged(bool persist_selection_context/* = false */) { if (persist_selection_context) { if (nullptr == _selection_context) { - _selection_context = _layers->currentLayer(); + _selection_context = _desktop->layerManager().currentLayer(); sp_object_ref(_selection_context, nullptr); _context_release_connection = _selection_context->connectRelease(sigc::mem_fun(*this, &Selection::_releaseContext)); } @@ -105,6 +104,16 @@ void Selection::_emitChanged(bool persist_selection_context/* = false */) { INKSCAPE.selection_changed(this); _changed_signal.emit(this); + + /** Change the layer selection to the item selection + * TODO: Should it only change if there's a single object? + */ + if (auto item = singleItem()) { + auto layer = _desktop->layerManager().layerForObject(item); + if (layer && layer != _selection_context) { + _desktop->layerManager().setCurrentLayer(layer); + } + } } void Selection::_releaseContext(SPObject *obj) @@ -121,7 +130,7 @@ void Selection::_releaseContext(SPObject *obj) SPObject *Selection::activeContext() { if (nullptr != _selection_context) return _selection_context; - return _layers->currentLayer(); + return _desktop->layerManager().currentLayer(); } std::vector Selection::getSnapPoints(SnapPreferences const *snapprefs) const { @@ -148,8 +157,8 @@ std::vector Selection::getSnapPoints(SnapPreferenc SPObject *Selection::_objectForXMLNode(Inkscape::XML::Node *repr) const { g_return_val_if_fail(repr != nullptr, NULL); - SPObject *object = _layers->getDocument()->getObjectByRepr(repr); - assert(object == _layers->getDocument()->getObjectById(repr->attribute("id"))); + SPObject *object = _desktop->getDocument()->getObjectByRepr(repr); + assert(object == _desktop->getDocument()->getObjectById(repr->attribute("id"))); return object; } @@ -157,7 +166,7 @@ size_t Selection::numberOfLayers() { auto items = this->items(); std::set layers; for (auto iter = items.begin(); iter != items.end(); ++iter) { - SPObject *layer = _layers->layerForObject(*iter); + SPObject *layer = _desktop->layerManager().layerForObject(*iter); layers.insert(layer); } diff --git a/src/selection.h b/src/selection.h index 9b4eb2d50d..dbceb24f47 100644 --- a/src/selection.h +++ b/src/selection.h @@ -28,7 +28,6 @@ namespace Inkscape { -class LayerModel; namespace XML { class Node; } @@ -40,7 +39,7 @@ namespace Inkscape { * The set of selected SPObjects for a given document and layer model. * * This class represents the set of selected SPItems for a given - * document (referenced in LayerModel). + * document. * * An SPObject and its parent cannot be simultaneously selected; * selecting an SPObjects has the side-effect of unselecting any of @@ -67,7 +66,7 @@ public: * @param layers the layer model (for the SPDesktop, if GUI) * @param desktop the desktop associated with the layer model, or NULL if in console mode */ - Selection(LayerModel *layers, SPDesktop *desktop); + Selection(SPDesktop *desktop); ~Selection() override; /** no copy. */ @@ -75,14 +74,6 @@ public: /** no assign. */ void operator=(Selection const &) = delete; - /** - * Returns the layer model the selection is bound to (works in console or GUI mode) - * - * @return the layer model the selection is bound to, which is the same as the desktop - * layer model for GUI mode - */ - LayerModel *layers() { return _layers; } - /** * Returns active layer for selection (currentLayer or its parent). * @@ -242,7 +233,6 @@ private: /** Releases an active layer object that is being removed. */ void _releaseContext(SPObject *obj); - LayerModel *_layers; SPObject* _selection_context; unsigned int _flags; unsigned int _idle; diff --git a/src/ui/contextmenu.cpp b/src/ui/contextmenu.cpp index ce41f30ddc..73d25283bc 100644 --- a/src/ui/contextmenu.cpp +++ b/src/ui/contextmenu.cpp @@ -35,6 +35,7 @@ #include "document.h" #include "document-undo.h" #include "inkscape.h" +#include "layer-manager.h" #include "message-context.h" #include "message-stack.h" #include "selection.h" @@ -188,13 +189,13 @@ Gtk::SeparatorMenuItem* ContextMenu::AddSeparator() void ContextMenu::EnterGroup(Gtk::MenuItem* mi) { - _desktop->layers->setCurrentLayer(_MIGroup_group); + _desktop->layerManager().setCurrentLayer(_MIGroup_group); _desktop->selection->clear(); } void ContextMenu::LeaveGroup() { - _desktop->layers->setCurrentLayer(_desktop->layers->currentLayer()->parent); + _desktop->layerManager().setCurrentLayer(_desktop->layerManager().currentLayer()->parent); } void ContextMenu::LockSelected() @@ -546,7 +547,7 @@ void ContextMenu::ItemSelectThis() void ContextMenu::ItemMoveTo() { - Inkscape::UI::Dialogs::LayerPropertiesDialog::showMove(_desktop, _desktop->layers->currentLayer()); + Inkscape::UI::Dialogs::LayerPropertiesDialog::showMove(_desktop, _desktop->layerManager().currentLayer()); } @@ -657,7 +658,7 @@ void ContextMenu::MakeGroupMenu(SPGroup* item) } // enter group - auto layer = _desktop->layers->currentLayer(); + auto layer = _desktop->layerManager().currentLayer(); if (item != layer) { MIGroup.set_label(Glib::ustring::compose(_("Enter group %1"), item->defaultLabel())); _MIGroup_group = item; @@ -666,7 +667,7 @@ void ContextMenu::MakeGroupMenu(SPGroup* item) append(MIGroup); } - auto root = _desktop->layers->currentRoot(); + auto root = _desktop->layerManager().currentRoot(); if (layer != root) { if (layer->parent != root) { MIParent.signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::LeaveGroup)); diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp index c8bd0a3c0f..477f8a0fe3 100644 --- a/src/ui/dialog/filter-effects-dialog.cpp +++ b/src/ui/dialog/filter-effects-dialog.cpp @@ -41,7 +41,7 @@ #include "filter-effects-dialog.h" #include "filter-enums.h" #include "inkscape.h" -#include "layer-model.h" +#include "layer-manager.h" #include "selection-chemistry.h" #include "verbs.h" @@ -1589,7 +1589,7 @@ void FilterEffectsDialog::FilterModifier::remove_filter() // Delete all references to this filter std::vector x,y; - std::vector all = get_all_items(x, desktop->layers->currentRoot(), desktop, false, false, true, y); + std::vector all = get_all_items(x, desktop->layerManager().currentRoot(), desktop, false, false, true, y); for(std::vector::const_iterator i=all.begin(); all.end() != i; ++i) { if (!SP_IS_ITEM(*i)) { continue; @@ -1648,7 +1648,7 @@ void FilterEffectsDialog::FilterModifier::select_filter_elements() std::vector x,y; std::vector items; - std::vector all = get_all_items(x, desktop->layers->currentRoot(), desktop, false, false, true, y); + std::vector all = get_all_items(x, desktop->layerManager().currentRoot(), desktop, false, false, true, y); for(SPItem *item: all) { if (!item->style) { continue; diff --git a/src/ui/dialog/find.cpp b/src/ui/dialog/find.cpp index 7885836fc2..97a62b4bfe 100644 --- a/src/ui/dialog/find.cpp +++ b/src/ui/dialog/find.cpp @@ -21,7 +21,7 @@ #include "document-undo.h" #include "document.h" #include "inkscape.h" -#include "layer-model.h" +#include "layer-manager.h" #include "message-stack.h" #include "selection-chemistry.h" #include "text-editing.h" @@ -844,7 +844,7 @@ bool Find::item_type_match (SPItem *item) return (all || check_texts.get_active()); } else if (dynamic_cast(item) && - !getDesktop()->layers->isLayer(item)) { // never select layers! + !getDesktop()->layerManager().isLayer(item)) { // never select layers! return (all || check_groups.get_active()); } else if (dynamic_cast(item)) { @@ -895,7 +895,7 @@ std::vector &Find::all_items (SPObject *r, std::vector &l, boo auto desktop = getDesktop(); for (auto& child: r->children) { SPItem *item = dynamic_cast(&child); - if (item && !child.cloned && !desktop->layers->isLayer(item)) { + if (item && !child.cloned && !desktop->layerManager().isLayer(item)) { if ((hidden || !desktop->itemIsHidden(item)) && (locked || !item->isLocked())) { l.insert(l.begin(),(SPItem*)&child); } @@ -913,7 +913,7 @@ std::vector &Find::all_selection_items (Inkscape::Selection *s, std::ve SPObject *obj = *i; SPItem *item = dynamic_cast(obj); g_assert(item != nullptr); - if (item && !item->cloned && !desktop->layers->isLayer(item)) { + if (item && !item->cloned && !desktop->layerManager().isLayer(item)) { if (!ancestor || ancestor->isAncestorOf(item)) { if ((hidden || !desktop->itemIsHidden(item)) && (locked || !item->isLocked())) { l.push_back(*i); @@ -967,13 +967,13 @@ void Find::onAction() std::vector l; if (check_scope_selection.get_active()) { if (check_scope_layer.get_active()) { - l = all_selection_items (desktop->selection, l, desktop->layers->currentLayer(), hidden, locked); + l = all_selection_items (desktop->selection, l, desktop->layerManager().currentLayer(), hidden, locked); } else { l = all_selection_items (desktop->selection, l, nullptr, hidden, locked); } } else { if (check_scope_layer.get_active()) { - l = all_items (desktop->layers->currentLayer(), l, hidden, locked); + l = all_items (desktop->layerManager().currentLayer(), l, hidden, locked); } else { l = all_items(desktop->getDocument()->getRoot(), l, hidden, locked); } diff --git a/src/ui/dialog/layer-properties.cpp b/src/ui/dialog/layer-properties.cpp index 93565f1b56..49fe878310 100644 --- a/src/ui/dialog/layer-properties.cpp +++ b/src/ui/dialog/layer-properties.cpp @@ -23,7 +23,6 @@ #include "document.h" #include "document-undo.h" #include "layer-manager.h" -#include "layer-model.h" #include "message-stack.h" #include "preferences.h" @@ -223,7 +222,7 @@ LayerPropertiesDialog::_setup_layers_controls() { SPDocument* document = _desktop->doc(); SPRoot* root = document->getRoot(); if ( root ) { - SPObject* target = _desktop->layers->currentLayer(); + SPObject* target = _desktop->layerManager().currentLayer(); _store->clear(); _addLayer( document, root, nullptr, target, 0 ); } @@ -245,10 +244,10 @@ LayerPropertiesDialog::_setup_layers_controls() { void LayerPropertiesDialog::_addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level ) { int _maxNestDepth = 20; - if ( _desktop && _desktop->layer_manager && layer && (level < _maxNestDepth) ) { - unsigned int counter = _desktop->layer_manager->childCount(layer); + if ( _desktop && layer && (level < _maxNestDepth) ) { + unsigned int counter = _desktop->layerManager().childCount(layer); for ( unsigned int i = 0; i < counter; i++ ) { - SPObject *child = _desktop->layer_manager->nthChildOf(layer, i); + SPObject *child = _desktop->layerManager().nthChildOf(layer, i); if ( child ) { #if DUMP_LAYERS g_message(" %3d layer:%p {%s} [%s]", level, child, child->id, child->label() ); @@ -324,7 +323,7 @@ void LayerPropertiesDialog::_prepareLabelRenderer( void LayerPropertiesDialog::Rename::setup(LayerPropertiesDialog &dialog) { SPDesktop *desktop=dialog._desktop; dialog.set_title(_("Rename Layer")); - gchar const *name = desktop->layers->currentLayer()->label(); + gchar const *name = desktop->layerManager().currentLayer()->label(); dialog._layer_name_entry.set_text(( name ? name : _("Layer") )); dialog._apply_button.set_label(_("_Rename")); } @@ -334,7 +333,7 @@ void LayerPropertiesDialog::Rename::perform(LayerPropertiesDialog &dialog) { Glib::ustring name(dialog._layer_name_entry.get_text()); if (name.empty()) return; - desktop->layer_manager->renameLayer( desktop->layers->currentLayer(), + desktop->layerManager().renameLayer( desktop->layerManager().currentLayer(), (gchar *)name.c_str(), FALSE ); @@ -347,8 +346,8 @@ void LayerPropertiesDialog::Create::setup(LayerPropertiesDialog &dialog) { dialog.set_title(_("Add Layer")); // Set the initial name to the "next available" layer name - LayerManager *mgr = dialog._desktop->layer_manager; - Glib::ustring newName = mgr->getNextLayerName(nullptr, dialog._desktop->layers->currentLayer()->label()); + auto desktop = dialog._desktop; + Glib::ustring newName = desktop->layerManager().getNextLayerName(nullptr, desktop->layerManager().currentLayer()->label()); dialog._layer_name_entry.set_text(newName.c_str()); dialog._apply_button.set_label(_("_Add")); dialog._setup_position_controls(); @@ -372,10 +371,10 @@ void LayerPropertiesDialog::Create::perform(LayerPropertiesDialog &dialog) { SPObject *new_layer=Inkscape::create_layer(root, dialog._layer, position); if (!name.empty()) { - desktop->layer_manager->renameLayer( new_layer, (gchar *)name.c_str(), TRUE ); + desktop->layerManager().renameLayer(new_layer, name.c_str(), true); } desktop->getSelection()->clear(); - desktop->layers->setCurrentLayer(new_layer); + desktop->layerManager().setCurrentLayer(new_layer); DocumentUndo::done(desktop->getDocument(), SP_VERB_LAYER_NEW, _("Add layer")); desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("New layer created.")); } diff --git a/src/ui/dialog/layer-properties.h b/src/ui/dialog/layer-properties.h index 7cdd130bce..59de202600 100644 --- a/src/ui/dialog/layer-properties.h +++ b/src/ui/dialog/layer-properties.h @@ -24,7 +24,8 @@ #include #include -#include "layer-fns.h" +#include "layer-manager.h" + #include "ui/widget/layer-selector.h" class SPDesktop; diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp index 230a43a075..bd2570f8f6 100644 --- a/src/ui/dialog/layers.cpp +++ b/src/ui/dialog/layers.cpp @@ -22,9 +22,7 @@ #include "document-undo.h" #include "document.h" #include "inkscape.h" -#include "layer-fns.h" #include "layer-manager.h" -#include "layer-model.h" #include "selection-chemistry.h" #include "verbs.h" @@ -187,8 +185,8 @@ bool LayersPanel::_executeAction() if ( _pending && ( (_pending->_actionCode == BUTTON_NEW || _pending->_actionCode == DRAGNDROP) - || !( (desktop && desktop->layers->currentLayer()) - && (desktop->layers->currentLayer() != _pending->_target) + || !( (desktop && desktop->layerManager().currentLayer()) + && (desktop->layerManager().currentLayer() != _pending->_target) ) ) ) { @@ -364,8 +362,8 @@ void LayersPanel::_layersChanged() if (auto root = document->getRoot()) { _selectedConnection.block(); auto desktop = getDesktop(); - if (desktop->layer_manager && desktop->layer_manager->includes( root ) ) { - SPObject* target = desktop->layers->currentLayer(); + if (desktop->layerManager().includes( root ) ) { + SPObject* target = desktop->layerManager().currentLayer(); _store->clear(); #if DUMP_LAYERS @@ -381,11 +379,10 @@ void LayersPanel::_layersChanged() void LayersPanel::_addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level ) { auto desktop = getDesktop(); - if (desktop && desktop->layer_manager && layer && (level < _maxNestDepth) ) { - unsigned int counter = desktop->layer_manager->childCount(layer); + if (desktop && layer && (level < _maxNestDepth) ) { + unsigned int counter = desktop->layerManager().childCount(layer); for ( unsigned int i = 0; i < counter; i++ ) { - SPObject *child = desktop->layer_manager->nthChildOf(layer, i); - if ( child ) { + if (auto child = desktop->layerManager().nthChildOf(layer, i)) { #if DUMP_LAYERS g_message(" %3d layer:%p {%s} [%s]", level, child, child->getId(), child->label() ); #endif // DUMP_LAYERS @@ -428,15 +425,15 @@ SPObject* LayersPanel::_selectedLayer() void LayersPanel::_pushTreeSelectionToCurrent() { auto desktop = getDesktop(); - if (desktop && desktop->layer_manager && desktop->layers->currentRoot() ) { + if (desktop && desktop->layerManager().currentRoot() ) { SPObject* inTree = _selectedLayer(); if ( inTree ) { - SPObject* curr = desktop->layers->currentLayer(); + SPObject* curr = desktop->layerManager().currentLayer(); if (curr != inTree) { - desktop->layer_manager->setCurrentLayer(inTree); + desktop->layerManager().setCurrentLayer(inTree); } } else { - desktop->layer_manager->setCurrentLayer(getDocument()->getRoot()); + desktop->layerManager().setCurrentLayer(getDocument()->getRoot()); } } } @@ -580,10 +577,10 @@ bool LayersPanel::_handleButtonEvent(GdkEventButton* event) Gtk::TreeModel::Row row = *iter; SPObject *obj = row[_model->_colObject]; if (col == _tree.get_column(COL_VISIBLE - 1)) { - desktop->layers->toggleLayerSolo( obj ); + desktop->layerManager().toggleLayerSolo( obj ); DocumentUndo::maybeDone(document, "layer:solo", SP_VERB_LAYER_SOLO, _("Toggle layer solo")); } else if (col == _tree.get_column(COL_LOCKED - 1)) { - desktop->layers->toggleLockOtherLayers(obj); + desktop->layerManager().toggleLockOtherLayers(obj); DocumentUndo::maybeDone(document, "layer:lockothers", SP_VERB_LAYER_LOCK_OTHERS, _("Lock other layers")); } } @@ -685,12 +682,12 @@ void LayersPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& void LayersPanel::_renameLayer(Gtk::TreeModel::Row row, const Glib::ustring& name) { auto desktop = getDesktop(); - if (row && desktop && desktop->layer_manager) { + if (row && desktop) { SPObject* obj = row[_model->_colObject]; if (obj) { gchar const* oldLabel = obj->label(); if ( !name.empty() && (!oldLabel || name != oldLabel) ) { - desktop->layer_manager->renameLayer( obj, name.c_str(), FALSE ); + desktop->layerManager().renameLayer(obj, name.c_str(), false); DocumentUndo::done(getDocument(), SP_VERB_NONE, _("Rename layer")); } @@ -955,13 +952,9 @@ void LayersPanel::desktopReplaced() _changedConnection.disconnect(); _subject.setDesktop(getDesktop()); if (auto desktop = getDesktop()) { - //setLabel(document->name); - LayerManager *mgr = desktop->layer_manager; - if (mgr) { - _layerChangedConnection = mgr->connectCurrentLayerChanged( sigc::mem_fun(*this, &LayersPanel::_selectLayer) ); - _layerUpdatedConnection = mgr->connectLayerDetailsChanged( sigc::mem_fun(*this, &LayersPanel::_updateLayer) ); - _changedConnection = mgr->connectChanged( sigc::mem_fun(*this, &LayersPanel::_layersChanged) ); - } + _layerChangedConnection = desktop->layerManager().connectCurrentLayerChanged( sigc::mem_fun(*this, &LayersPanel::_selectLayer)); + _layerUpdatedConnection = desktop->layerManager().connectLayerDetailsChanged( sigc::mem_fun(*this, &LayersPanel::_updateLayer)); + _changedConnection = desktop->layerManager().connectChanged( sigc::mem_fun(*this, &LayersPanel::_layersChanged)); _layersChanged(); } } diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index daa12d37ca..cb5036df42 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -31,7 +31,6 @@ #include "filter-chemistry.h" #include "inkscape.h" #include "layer-manager.h" -#include "layer-model.h" #include "verbs.h" #include "actions/actions-tools.h" @@ -853,7 +852,7 @@ void ObjectsPanel::desktopReplaced() layer_changed.disconnect(); if (auto desktop = getDesktop()) { - layer_changed = desktop->layer_manager->connectCurrentLayerChanged( sigc::mem_fun(*this, &ObjectsPanel::layerChanged)); + layer_changed = desktop->layerManager().connectCurrentLayerChanged(sigc::mem_fun(*this, &ObjectsPanel::layerChanged)); } } @@ -873,7 +872,7 @@ void ObjectsPanel::setRootWatcher() Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool layers_only = prefs->getBool("/dialogs/objects/layers_only", true); root_watcher = new ObjectWatcher(this, document->getRoot(), nullptr, layers_only); - layerChanged(getDesktop()->layers->currentLayer()); + layerChanged(getDesktop()->layerManager().currentLayer()); } } @@ -955,7 +954,7 @@ bool ObjectsPanel::toggleVisible(GdkEventButton* event, Gtk::TreeModel::Row row) if (event->state & GDK_SHIFT_MASK) { // Toggle Visible for layers (hide all other layers) if (auto desktop = getDesktop()) { - desktop->layers->toggleLayerSolo(item); + desktop->layerManager().toggleLayerSolo(item); DocumentUndo::done(desktop->getDocument(), SP_VERB_LAYER_SOLO, _("Toggle layer solo")); } } else { @@ -976,7 +975,7 @@ bool ObjectsPanel::toggleLocked(GdkEventButton* event, Gtk::TreeModel::Row row) if (event->state & GDK_SHIFT_MASK) { // Toggle lock for layers (lock all other layers) if (auto desktop = getDesktop()) { - desktop->layers->toggleLockOtherLayers(item); + desktop->layerManager().toggleLockOtherLayers(item); DocumentUndo::done(desktop->getDocument(), SP_VERB_LAYER_LOCK_OTHERS, _("Lock other layers")); } } else { @@ -1107,9 +1106,9 @@ bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event) } else if (group && group->layerMode() == SPGroup::LAYER) { // if right-clicking on a layer, make it current for context menu actions to work correctly if (context_menu) { - if (getDesktop()->layers->currentLayer() != item) { + if (getDesktop()->layerManager().currentLayer() != item) { selection->clear(); - getDesktop()->layers->setCurrentLayer(item); + getDesktop()->layerManager().setCurrentLayer(item); } } // Clicking on layers firstly switches to that layer. @@ -1117,7 +1116,7 @@ bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event) selection->clear(); } else if (_layer != item) { selection->clear(); - getDesktop()->layers->setCurrentLayer(item); + getDesktop()->layerManager().setCurrentLayer(item); } else { selection->set(item); } diff --git a/src/ui/dialog/spellcheck.cpp b/src/ui/dialog/spellcheck.cpp index acd9d0e789..364c4e5180 100644 --- a/src/ui/dialog/spellcheck.cpp +++ b/src/ui/dialog/spellcheck.cpp @@ -24,7 +24,7 @@ #include "document.h" #include "inkscape.h" #include "message-stack.h" -#include "layer-model.h" +#include "layer-manager.h" #include "selection-chemistry.h" #include "text-editing.h" #include "verbs.h" @@ -241,7 +241,7 @@ void SpellCheck::allTextItems (SPObject *r, std::vector &l, bool hidde if (auto desktop = getDesktop()) { for (auto& child: r->children) { if (auto item = dynamic_cast(&child)) { - if (!child.cloned && !desktop->layers->isLayer(item)) { + if (!child.cloned && !desktop->layerManager().isLayer(item)) { if ((hidden || !desktop->itemIsHidden(item)) && (locked || !item->isLocked())) { if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) l.push_back(item); diff --git a/src/ui/dialog/xml-tree.cpp b/src/ui/dialog/xml-tree.cpp index b4a8ced43a..4c2638a71f 100644 --- a/src/ui/dialog/xml-tree.cpp +++ b/src/ui/dialog/xml-tree.cpp @@ -27,7 +27,7 @@ #include "document-undo.h" #include "document.h" #include "inkscape.h" -#include "layer-model.h" +#include "layer-manager.h" #include "message-context.h" #include "message-stack.h" #include "verbs.h" @@ -458,10 +458,10 @@ void XmlTree::set_dt_select(Inkscape::XML::Node *repr) if (!object || !in_dt_coordsys(*object)) { // object not on canvas } else if (isRealLayer(object)) { - getDesktop()->layers->setCurrentLayer(object); + getDesktop()->layerManager().setCurrentLayer(object); } else { if (SP_IS_GROUP(object->parent)) { - getDesktop()->layers->setCurrentLayer(object->parent); + getDesktop()->layerManager().setCurrentLayer(object->parent); } getSelection()->set(SP_ITEM(object)); diff --git a/src/ui/drag-and-drop.cpp b/src/ui/drag-and-drop.cpp index d0338b7fdd..c955243442 100644 --- a/src/ui/drag-and-drop.cpp +++ b/src/ui/drag-and-drop.cpp @@ -24,7 +24,7 @@ #include "selection.h" #include "style.h" #include "verbs.h" -#include "layer-model.h" +#include "layer-manager.h" #include "extension/db.h" #include "extension/find_extension_by_mime.h" @@ -312,7 +312,7 @@ ink_drag_data_received(GtkWidget *widget, // Greg's edits to add intelligent positioning of svg drops SPObject *new_obj = nullptr; - new_obj = desktop->layers->currentLayer()->appendChildRepr(newgroup); + new_obj = desktop->layerManager().currentLayer()->appendChildRepr(newgroup); Inkscape::Selection *selection = desktop->getSelection(); selection->set(SP_ITEM(new_obj)); diff --git a/src/ui/toolbar/connector-toolbar.cpp b/src/ui/toolbar/connector-toolbar.cpp index bd21b3cbbf..829acfd799 100644 --- a/src/ui/toolbar/connector-toolbar.cpp +++ b/src/ui/toolbar/connector-toolbar.cpp @@ -39,7 +39,7 @@ #include "graphlayout.h" #include "selection.h" #include "verbs.h" -#include "layer-model.h" +#include "layer-manager.h" #include "object/sp-namedview.h" #include "object/sp-path.h" @@ -327,7 +327,7 @@ ConnectorToolbar::spacing_changed() bool modmade = false; std::vector items; - items = get_avoided_items(items, _desktop->layers->currentRoot(), _desktop); + items = get_avoided_items(items, _desktop->layerManager().currentRoot(), _desktop); for (auto item : items) { Geom::Affine m = Geom::identity(); avoid_item_move(&m, item); diff --git a/src/ui/tools/eraser-tool.cpp b/src/ui/tools/eraser-tool.cpp index 7fd0c7db57..216ab244bb 100644 --- a/src/ui/tools/eraser-tool.cpp +++ b/src/ui/tools/eraser-tool.cpp @@ -43,7 +43,6 @@ #include "document-undo.h" #include "document.h" #include "layer-manager.h" -#include "layer-model.h" #include "message-context.h" #include "path-chemistry.h" #include "rubberband.h" @@ -644,7 +643,7 @@ void EraserTool::set_to_accumulated() { this->repr = repr; } - SPObject * top_layer = desktop->layers->currentRoot(); + SPObject * top_layer = desktop->layerManager().currentRoot(); SPItem *item_repr = SP_ITEM(top_layer->appendChildRepr(this->repr)); Inkscape::GC::release(this->repr); item_repr->updateRepr(); diff --git a/src/ui/tools/flood-tool.cpp b/src/ui/tools/flood-tool.cpp index d9b940957a..4624c8c16e 100644 --- a/src/ui/tools/flood-tool.cpp +++ b/src/ui/tools/flood-tool.cpp @@ -34,7 +34,7 @@ #include "desktop.h" #include "document-undo.h" #include "document.h" -#include "layer-model.h" +#include "layer-manager.h" #include "message-context.h" #include "message-stack.h" #include "rubberband.h" @@ -448,7 +448,7 @@ static void do_trace(bitmap_coords_info bci, guchar *trace_px, SPDesktop *deskto g_free(str); } - auto layer = desktop->layers->currentLayer(); + auto layer = desktop->layerManager().currentLayer(); layer->addChild(pathRepr, nullptr); SPObject *reprobj = document->getObjectByRepr(pathRepr); diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp index a0083a310a..04d9e8cc6a 100644 --- a/src/ui/tools/measure-tool.cpp +++ b/src/ui/tools/measure-tool.cpp @@ -28,7 +28,7 @@ #include "desktop.h" #include "document-undo.h" #include "inkscape.h" -#include "layer-model.h" +#include "layer-manager.h" #include "path-chemistry.h" #include "rubberband.h" #include "text-editing.h" @@ -200,7 +200,7 @@ void setMeasureItem(Geom::PathVector pathv, bool is_curve, bool markers, guint32 repr = xml_doc->createElement("svg:path"); auto str = sp_svg_write_path(pathv); SPCSSAttr *css = sp_repr_css_attr_new(); - auto layer = desktop->layers->currentLayer(); + auto layer = desktop->layerManager().currentLayer(); Geom::Coord strokewidth = layer->i2doc_affine().inverse().expansionX(); std::stringstream stroke_width; stroke_width.imbue(std::locale::classic()); @@ -351,7 +351,7 @@ void createAngleDisplayCurve(SPDesktop *desktop, path.start(desktop->doc2dt(p1)); path.appendNew(desktop->doc2dt(p2),desktop->doc2dt(p3),desktop->doc2dt(p4)); pathv.push_back(path); - auto layer = desktop->layers->currentLayer(); + auto layer = desktop->layerManager().currentLayer(); pathv *= layer->i2doc_affine().inverse(); if(!pathv.empty()) { setMeasureItem(pathv, true, false, 0xff00007f, measure_repr); @@ -768,7 +768,7 @@ void MeasureTool::toGuides() } setGuide(start,ray.angle(), _("Measure")); if(explicit_base) { - auto layer = desktop->layers->currentLayer(); + auto layer = desktop->layerManager().currentLayer(); explicit_base = *explicit_base * layer->i2doc_affine().inverse(); ray.setPoints(start, *explicit_base); if(ray.angle() != 0) { @@ -820,7 +820,7 @@ void MeasureTool::toItem() Inkscape::XML::Node *rgroup = xml_doc->createElement("svg:g"); showCanvasItems(false, true, false, rgroup); setLine(start_p,end_p, false, line_color_primary, rgroup); - SPItem *measure_item = SP_ITEM(desktop->layers->currentLayer()->appendChildRepr(rgroup)); + SPItem *measure_item = SP_ITEM(desktop->layerManager().currentLayer()->appendChildRepr(rgroup)); Inkscape::GC::release(rgroup); measure_item->updateRepr(); doc->ensureUpToDate(); @@ -923,7 +923,7 @@ void MeasureTool::setLine(Geom::Point start_point,Geom::Point end_point, bool ma path.start(desktop->doc2dt(start_point)); path.appendNew(desktop->doc2dt(end_point)); pathv.push_back(path); - pathv *= desktop->layers->currentLayer()->i2doc_affine().inverse(); + pathv *= desktop->layerManager().currentLayer()->i2doc_affine().inverse(); if(!pathv.empty()) { setMeasureItem(pathv, false, markers, color, measure_repr); } @@ -943,7 +943,7 @@ void MeasureTool::setPoint(Geom::Point origin, Inkscape::XML::Node *measure_repr pathv *= scale; pathv *= Geom::Translate(Geom::Point() - (scale.vector() * 0.5)); pathv *= Geom::Translate(desktop->doc2dt(origin)); - pathv *= desktop->layers->currentLayer()->i2doc_affine().inverse(); + pathv *= desktop->layerManager().currentLayer()->i2doc_affine().inverse(); if (!pathv.empty()) { guint32 line_color_secondary = 0xff0000ff; setMeasureItem(pathv, false, false, line_color_secondary, measure_repr); @@ -1008,7 +1008,7 @@ void MeasureTool::setLabelText(Glib::ustring const &value, Geom::Point pos, doub Inkscape::XML::Node *rstring = xml_doc->createTextNode(value.c_str()); rtspan->addChild(rstring, nullptr); Inkscape::GC::release(rstring); - auto layer = desktop->layers->currentLayer(); + auto layer = desktop->layerManager().currentLayer(); SPItem *text_item = SP_ITEM(layer->appendChildRepr(rtext)); Inkscape::GC::release(rtext); text_item->updateRepr(); @@ -1330,11 +1330,9 @@ void MeasureTool::showCanvasItems(bool to_guides, bool to_item, bool to_phantom, SPDocument *doc = desktop->getDocument(); Geom::Rect rect(start_p_doc, end_p_doc); items = doc->getItemsPartiallyInBox(desktop->dkey, rect, false, true, false, true); - Inkscape::LayerModel *layer_model = nullptr; SPGroup *current_layer = nullptr; if(desktop){ - layer_model = desktop->layers; - current_layer = desktop->layers->currentLayer(); + current_layer = desktop->layerManager().currentLayer(); } std::vector intersection_times; bool only_selected = prefs->getBool("/tools/measure/only_selected", false); @@ -1343,7 +1341,7 @@ void MeasureTool::showCanvasItems(bool to_guides, bool to_item, bool to_phantom, if (!desktop->getSelection()->includes(i) && only_selected) { continue; } - if(all_layers || (layer_model && layer_model->layerForObject(item) == current_layer)){ + if(all_layers || desktop->layerManager().layerForObject(item) == current_layer){ if (auto shape = dynamic_cast(item)) { calculate_intersections(desktop, item, lineseg, SPCurve::copy(shape->curve()), intersection_times); } else { diff --git a/src/ui/tools/pencil-tool.cpp b/src/ui/tools/pencil-tool.cpp index 7adcdd0b84..222539c1c9 100644 --- a/src/ui/tools/pencil-tool.cpp +++ b/src/ui/tools/pencil-tool.cpp @@ -29,6 +29,7 @@ #include "context-fns.h" #include "desktop.h" #include "desktop-style.h" +#include "layer-manager.h" #include "message-context.h" #include "message-stack.h" #include "selection-chemistry.h" @@ -1173,7 +1174,7 @@ void PencilTool::_fitAndSplit() { /// \todo fixme: - auto layer = desktop->layers->currentLayer(); + auto layer = desktop->layerManager().currentLayer(); this->highlight_color = layer->highlight_color(); if((unsigned int)prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff) == this->highlight_color){ this->green_color = 0x00ff007f; diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp index 72656ecd2f..5e6ab4be6a 100644 --- a/src/ui/tools/select-tool.cpp +++ b/src/ui/tools/select-tool.cpp @@ -30,7 +30,7 @@ #include "document-undo.h" #include "document.h" #include "include/macros.h" -#include "layer-model.h" +#include "layer-manager.h" #include "message-stack.h" #include "rubberband.h" #include "selection-chemistry.h" @@ -232,7 +232,7 @@ sp_select_context_up_one_layer(SPDesktop *desktop) * document), we might consider further restricting the below to disallow * leaving a layer to go to a non-layer. */ - if (SPObject *const current_layer = desktop->layers->currentLayer()) { + if (SPObject *const current_layer = desktop->layerManager().currentLayer()) { SPObject *const parent = current_layer->parent; SPGroup *current_group = dynamic_cast(current_layer); if ( parent @@ -240,7 +240,7 @@ sp_select_context_up_one_layer(SPDesktop *desktop) || !( current_group && ( SPGroup::LAYER == current_group->layerMode() ) ) ) ) { - desktop->layers->setCurrentLayer(parent); + desktop->layerManager().setCurrentLayer(parent); if (current_group && (SPGroup::LAYER != current_group->layerMode())) { desktop->getSelection()->set(current_layer); } @@ -469,7 +469,7 @@ bool SelectTool::root_handler(GdkEvent* event) { SPItem *clicked_item = selection->items().front(); if (dynamic_cast(clicked_item) && !dynamic_cast(clicked_item)) { // enter group if it's not a 3D box - desktop->layers->setCurrentLayer(clicked_item); + desktop->layerManager().setCurrentLayer(clicked_item); desktop->getSelection()->clear(); this->dragging = false; sp_event_context_discard_delayed_snap_event(this); @@ -1080,7 +1080,7 @@ bool SelectTool::root_handler(GdkEvent* event) { SPItem *clicked_item = selection->singleItem(); SPGroup *clickedGroup = dynamic_cast(clicked_item); if ( (clickedGroup && (clickedGroup->layerMode() != SPGroup::LAYER)) || dynamic_cast(clicked_item)) { // enter group or a 3D box - desktop->layers->setCurrentLayer(clicked_item); + desktop->layerManager().setCurrentLayer(clicked_item); desktop->getSelection()->clear(); } else { this->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Selected object is not a group. Cannot enter.")); diff --git a/src/ui/tools/tool-base.cpp b/src/ui/tools/tool-base.cpp index 9bde2ebf3a..5aeb5ca383 100644 --- a/src/ui/tools/tool-base.cpp +++ b/src/ui/tools/tool-base.cpp @@ -24,7 +24,7 @@ #include "desktop.h" #include "file.h" #include "gradient-drag.h" -#include "layer-model.h" +#include "layer-manager.h" #include "message-context.h" #include "rubberband.h" #include "selcue.h" @@ -134,7 +134,7 @@ void ToolBase::set(const Inkscape::Preferences::Entry& /*val*/) { SPGroup *ToolBase::currentLayer() const { - return desktop->layers->currentLayer(); + return desktop->layerManager().currentLayer(); } /** diff --git a/src/ui/widget/layer-selector.cpp b/src/ui/widget/layer-selector.cpp index 99b5040c01..cb437256af 100644 --- a/src/ui/widget/layer-selector.cpp +++ b/src/ui/widget/layer-selector.cpp @@ -23,7 +23,6 @@ #include "document-undo.h" #include "document.h" #include "layer-manager.h" -#include "layer-model.h" #include "verbs.h" #include "ui/dialog/layer-properties.h" @@ -182,10 +181,8 @@ void LayerSelector::setDesktop(SPDesktop *desktop) { _desktop = desktop; if (_desktop) { - if (auto manager = _desktop->layer_manager) { - _current_layer_changed_connection = manager->connectCurrentLayerChanged(sigc::mem_fun(*this, &LayerSelector::_selectLayer)); - } - _selectLayer(dynamic_cast(_desktop->layers->currentLayer())); + _current_layer_changed_connection = _desktop->layerManager().connectCurrentLayerChanged(sigc::mem_fun(*this, &LayerSelector::_selectLayer)); + _selectLayer(dynamic_cast(_desktop->layerManager().currentLayer())); } } @@ -195,7 +192,7 @@ class is_layer { public: is_layer(SPDesktop *desktop) : _desktop(desktop) {} bool operator()(SPObject &object) const { - return _desktop->layers->isLayer(&object); + return _desktop->layerManager().isLayer(&object); } private: SPDesktop *_desktop; @@ -231,7 +228,7 @@ void LayerSelector::_selectLayer(SPObject *layer) _layer_model->erase(first_row); } - SPGroup *root = _desktop->layers->currentRoot(); + SPGroup *root = _desktop->layerManager().currentRoot(); if (_layer) { sp_object_unref(_layer, nullptr); _layer = nullptr; @@ -290,12 +287,12 @@ void LayerSelector::_setDesktopLayer() { _current_layer_changed_connection.block(); _layers_changed_connection.block(); - _desktop->layer_manager->setCurrentLayer(layer); + _desktop->layerManager().setCurrentLayer(layer); _current_layer_changed_connection.unblock(); _layers_changed_connection.unblock(); - _selectLayer(dynamic_cast(_desktop->layers->currentLayer())); + _selectLayer(dynamic_cast(_desktop->layerManager().currentLayer())); } if (_desktop && _desktop->canvas) { _desktop->canvas->grab_focus(); @@ -398,7 +395,7 @@ void update_row_for_object(SPObject *object, void rebuild_all_rows(sigc::slot rebuild, SPDesktop *desktop) { - rebuild(desktop->layers->currentLayer()); + rebuild(desktop->layerManager().currentLayer()); } } @@ -410,7 +407,7 @@ void LayerSelector::_protectUpdate(sigc::slot slot) { _lock_toggled_connection.block(true); slot(); - auto layer = _desktop ? _desktop->layers->currentLayer() : nullptr; + auto layer = _desktop ? _desktop->layerManager().currentLayer() : nullptr; if (layer) { bool wantedValue = layer->isLocked(); if ( _lock_toggle.get_active() != wantedValue ) { @@ -440,7 +437,7 @@ void LayerSelector::_buildEntry(unsigned depth, SPObject &object) { ) ); - auto layer = _desktop->layers->currentLayer(); + auto layer = _desktop->layerManager().currentLayer(); if ( (&object == layer) || (&object == layer->parent) ) { callbacks->update_list = sigc::bind( sigc::mem_fun(*this, &LayerSelector::_protectUpdate), @@ -518,8 +515,8 @@ void LayerSelector::_prepareLabelRenderer( // "invent" an iterator with null data and try to render it; // where does it come from, and how can we avoid it? if ( object && object->getRepr() ) { - auto layer = _desktop ? _desktop->layers->currentLayer() : nullptr; - auto root = _desktop ? _desktop->layers->currentRoot() : nullptr; + auto layer = _desktop ? _desktop->layerManager().currentLayer() : nullptr; + auto root = _desktop ? _desktop->layerManager().currentRoot() : nullptr; bool isancestor = !( (layer && (object->parent == layer->parent)) || ((layer == root) && (object->parent == root))); diff --git a/src/ui/widget/style-subject.cpp b/src/ui/widget/style-subject.cpp index 4f3d8c1fac..310dbcfd68 100644 --- a/src/ui/widget/style-subject.cpp +++ b/src/ui/widget/style-subject.cpp @@ -11,7 +11,6 @@ #include "desktop.h" #include "desktop-style.h" #include "layer-manager.h" -#include "layer-model.h" #include "selection.h" #include "xml/sp-css-attr.h" @@ -164,8 +163,8 @@ void StyleSubject::CurrentLayer::setCSS(SPCSSAttr *css) { void StyleSubject::CurrentLayer::_afterDesktopSwitch(SPDesktop *desktop) { _layer_switched.disconnect(); if (desktop) { - _layer_switched = desktop->layer_manager->connectCurrentLayerChanged(sigc::mem_fun(*this, &CurrentLayer::_setLayer)); - _setLayer(desktop->layers->currentLayer()); + _layer_switched = desktop->layerManager().connectCurrentLayerChanged(sigc::mem_fun(*this, &CurrentLayer::_setLayer)); + _setLayer(desktop->layerManager().currentLayer()); } else { _setLayer(nullptr); } diff --git a/src/verbs.cpp b/src/verbs.cpp index cf8cad5f63..a13ec6ab4e 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -40,9 +40,7 @@ #include "gradient-drag.h" #include "inkscape.h" #include "inkscape-version.h" -#include "layer-fns.h" #include "layer-manager.h" -#include "layer-model.h" #include "message-stack.h" #include "path-chemistry.h" #include "selection-chemistry.h" @@ -1230,9 +1228,8 @@ void LayerVerb::perform(SPAction *action, void *data) SPDesktop *dt = sp_action_get_desktop(action); size_t verb = reinterpret_cast(data); - auto layers = dt->layers; - auto layer = layers->currentLayer(); - auto root = layers->currentRoot(); + auto layer = dt->layerManager().currentLayer(); + auto root = dt->layerManager().currentRoot(); if (!layer) return; @@ -1248,7 +1245,7 @@ void LayerVerb::perform(SPAction *action, void *data) case SP_VERB_LAYER_NEXT: { SPObject *next=Inkscape::next_layer(root, layer); if (next) { - layers->setCurrentLayer(next); + dt->layerManager().setCurrentLayer(next); DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_NEXT, _("Switch to next layer")); dt->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Switched to next layer.")); @@ -1260,7 +1257,7 @@ void LayerVerb::perform(SPAction *action, void *data) case SP_VERB_LAYER_PREV: { SPObject *prev=Inkscape::previous_layer(root, layer); if (prev) { - layers->setCurrentLayer(prev); + dt->layerManager().setCurrentLayer(prev); DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_PREV, _("Switch to previous layer")); dt->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Switched to previous layer.")); @@ -1390,7 +1387,7 @@ void LayerVerb::perform(SPAction *action, void *data) old_layer->deleteObject(); if (survivor) { - layers->setCurrentLayer(survivor); + dt->layerManager().setCurrentLayer(survivor); } DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_DELETE, @@ -1407,23 +1404,23 @@ void LayerVerb::perform(SPAction *action, void *data) if ( layer == root ) { dt->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No current layer.")); } else { - layers->toggleLayerSolo( layer ); + dt->layerManager().toggleLayerSolo( layer ); DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_SOLO, _("Toggle layer solo")); } break; } case SP_VERB_LAYER_SHOW_ALL: { - layers->toggleHideAllLayers( false ); + dt->layerManager().toggleHideAllLayers( false ); DocumentUndo::maybeDone(dt->getDocument(), "layer:showall", SP_VERB_LAYER_SHOW_ALL, _("Show all layers")); break; } case SP_VERB_LAYER_HIDE_ALL: { - layers->toggleHideAllLayers( true ); + dt->layerManager().toggleHideAllLayers( true ); DocumentUndo::maybeDone(dt->getDocument(), "layer:hideall", SP_VERB_LAYER_HIDE_ALL, _("Hide all layers")); break; } case SP_VERB_LAYER_LOCK_ALL: { - layers->toggleLockAllLayers( true ); + dt->layerManager().toggleLockAllLayers( true ); DocumentUndo::maybeDone(dt->getDocument(), "layer:lockall", SP_VERB_LAYER_LOCK_ALL, _("Lock all layers")); break; } @@ -1431,13 +1428,13 @@ void LayerVerb::perform(SPAction *action, void *data) if ( layer == root ) { dt->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No current layer.")); } else { - layers->toggleLockOtherLayers( layer ); + dt->layerManager().toggleLockOtherLayers( layer ); DocumentUndo::done(dt->getDocument(), SP_VERB_LAYER_LOCK_OTHERS, _("Lock other layers")); } break; } case SP_VERB_LAYER_UNLOCK_ALL: { - layers->toggleLockAllLayers( false ); + dt->layerManager().toggleLockAllLayers( false ); DocumentUndo::maybeDone(dt->getDocument(), "layer:unlockall", SP_VERB_LAYER_UNLOCK_ALL, _("Unlock all layers")); break; } -- GitLab From d674aead6ecca0f831a309f5cd488b0a52ef2cf4 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Thu, 4 Nov 2021 17:00:21 -0400 Subject: [PATCH 3/6] Replace asLayer function for contextmenu --- src/layer-manager.cpp | 14 +++++++++++++- src/layer-manager.h | 1 + src/ui/contextmenu.cpp | 13 ++++++------- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/layer-manager.cpp b/src/layer-manager.cpp index aa1f24d1af..bc985635b7 100644 --- a/src/layer-manager.cpp +++ b/src/layer-manager.cpp @@ -592,13 +592,25 @@ SPObject *LayerManager::layerForObject(SPObject *object) { /** * True if object is a layer. */ -bool LayerManager::isLayer(SPObject *object) const { +bool LayerManager::isLayer(SPObject *object) const +{ if (auto group = dynamic_cast(object)) { return group->effectiveLayerMode(_desktop->dkey) == SPGroup::LAYER; } return false; } +/** + * Return the SPGroup if we have a layer object. + */ +SPGroup *LayerManager::asLayer(SPObject *object) +{ + if (auto group = dynamic_cast(object)) { + return group->isLayer() ? group : nullptr; + } + return nullptr; +} + } /* diff --git a/src/layer-manager.h b/src/layer-manager.h index 90426f5357..cb54b67796 100644 --- a/src/layer-manager.h +++ b/src/layer-manager.h @@ -53,6 +53,7 @@ public: void toggleLockOtherLayers(SPObject *object); SPObject *layerForObject(SPObject *object); bool isLayer(SPObject *object) const; + static SPGroup *asLayer(SPObject *object); private: friend class LayerWatcher; diff --git a/src/ui/contextmenu.cpp b/src/ui/contextmenu.cpp index 73d25283bc..2db943d4a2 100644 --- a/src/ui/contextmenu.cpp +++ b/src/ui/contextmenu.cpp @@ -82,12 +82,11 @@ ContextMenu::ContextMenu(SPDesktop *desktop, SPItem *item) : Inkscape::Preferences *prefs = Inkscape::Preferences::get(); _show_icons = prefs->getInt("/theme/menuIcons_canvas", true); - auto group = dynamic_cast(_object); - auto layer = group->isLayer() ? group : nullptr; - AppendItemFromVerb(Inkscape::Verb::get(SP_VERB_EDIT_UNDO)); AppendItemFromVerb(Inkscape::Verb::get(SP_VERB_EDIT_REDO)); AddSeparator(); + + auto layer = Inkscape::LayerManager::asLayer(_object); if (!layer) { // don't bother adding copy/paste/cut when clicking on a layer; it won't work unless layer is *selected* AppendItemFromVerb(Inkscape::Verb::get(SP_VERB_EDIT_CUT)); @@ -323,7 +322,7 @@ void ContextMenu::AppendItemFromVerb(Inkscape::Verb *verb) void ContextMenu::MakeObjectMenu() { if (SP_IS_ITEM(_object)) { - MakeItemMenu(dynamic_cast(_object)); + MakeItemMenu(Inkscape::LayerManager::asLayer(_object)); } if (SP_IS_GROUP(_object)) { @@ -347,7 +346,7 @@ void ContextMenu::MakeObjectMenu() } } -void ContextMenu::MakeItemMenu(SPGroup* group) +void ContextMenu::MakeItemMenu(SPGroup* layer) { Gtk::MenuItem* mi; @@ -373,7 +372,7 @@ void ContextMenu::MakeItemMenu(SPGroup* group) // several options are not applicable to layers; adding them makes context menu unwieldy, // so we need to be selective, or else it grows too much - if (!group || !group->isLayer()) { + if (!layer) { mi = Gtk::manage(new Gtk::MenuItem(_("Select Same"))); mi->show(); Gtk::Menu *select_same_submenu = Gtk::manage(new Gtk::Menu()); @@ -429,7 +428,7 @@ void ContextMenu::MakeItemMenu(SPGroup* group) mi->show(); append(*mi); - if (!group || !group->isLayer()) { + if (!layer) { /* Create link */ mi = Gtk::manage(new Gtk::MenuItem(_("Create _Link"), true)); mi->signal_activate().connect(sigc::mem_fun(*this, &ContextMenu::ItemCreateLink)); -- GitLab From cb5083073fbb39129900304d09b71d5e8cdb4cd8 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Thu, 4 Nov 2021 23:34:37 -0400 Subject: [PATCH 4/6] Fix cli tests and selector clearing --- src/layer-manager.cpp | 4 ++-- src/layer-manager.h | 2 +- src/selection.cpp | 20 +++++++++++--------- src/ui/dialog/objects.cpp | 6 ++---- src/ui/widget/layer-selector.cpp | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/layer-manager.cpp b/src/layer-manager.cpp index bc985635b7..df1634bd5e 100644 --- a/src/layer-manager.cpp +++ b/src/layer-manager.cpp @@ -233,14 +233,14 @@ void LayerManager::renameLayer( SPObject* obj, gchar const *label, bool uniquify * * Make \a object the top layer. */ -void LayerManager::setCurrentLayer(SPObject *object) { +void LayerManager::setCurrentLayer(SPObject *object, bool clear) { if (currentRoot()) { g_return_if_fail(SP_IS_GROUP(object)); g_return_if_fail( currentRoot() == object || (currentRoot() && currentRoot()->isAncestorOf(object)) ); _layer_hierarchy->setBottom(object); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - if (prefs->getBool("/options/selection/layerdeselect", true)) { + if (clear && prefs->getBool("/options/selection/layerdeselect", true)) { _desktop->getSelection()->clear(); } } diff --git a/src/layer-manager.h b/src/layer-manager.h index cb54b67796..333a825c7d 100644 --- a/src/layer-manager.h +++ b/src/layer-manager.h @@ -46,7 +46,7 @@ public: SPGroup *currentLayer() const; void reset(); - void setCurrentLayer(SPObject *object); + void setCurrentLayer(SPObject *object, bool clear=false); void toggleLayerSolo(SPObject *object); void toggleHideAllLayers(bool hide); void toggleLockAllLayers(bool lock); diff --git a/src/selection.cpp b/src/selection.cpp index 403c02a2fc..c265d9b61c 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -102,18 +102,20 @@ void Selection::_emitChanged(bool persist_selection_context/* = false */) { _releaseContext(_selection_context); } - INKSCAPE.selection_changed(this); - _changed_signal.emit(this); - /** Change the layer selection to the item selection * TODO: Should it only change if there's a single object? */ - if (auto item = singleItem()) { - auto layer = _desktop->layerManager().layerForObject(item); - if (layer && layer != _selection_context) { - _desktop->layerManager().setCurrentLayer(layer); - } - } + if (_desktop) { + if (auto item = singleItem()) { + auto layer = _desktop->layerManager().layerForObject(item); + if (layer && layer != _selection_context) { + _desktop->layerManager().setCurrentLayer(layer); + } + } + } + + INKSCAPE.selection_changed(this); + _changed_signal.emit(this); } void Selection::_releaseContext(SPObject *obj) diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index cb5036df42..19fc1171e6 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -1107,16 +1107,14 @@ bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event) // if right-clicking on a layer, make it current for context menu actions to work correctly if (context_menu) { if (getDesktop()->layerManager().currentLayer() != item) { - selection->clear(); - getDesktop()->layerManager().setCurrentLayer(item); + getDesktop()->layerManager().setCurrentLayer(item, true); } } // Clicking on layers firstly switches to that layer. else if (selection->includes(item)) { selection->clear(); } else if (_layer != item) { - selection->clear(); - getDesktop()->layerManager().setCurrentLayer(item); + getDesktop()->layerManager().setCurrentLayer(item, true); } else { selection->set(item); } diff --git a/src/ui/widget/layer-selector.cpp b/src/ui/widget/layer-selector.cpp index cb437256af..d73472dc26 100644 --- a/src/ui/widget/layer-selector.cpp +++ b/src/ui/widget/layer-selector.cpp @@ -287,7 +287,7 @@ void LayerSelector::_setDesktopLayer() { _current_layer_changed_connection.block(); _layers_changed_connection.block(); - _desktop->layerManager().setCurrentLayer(layer); + _desktop->layerManager().setCurrentLayer(layer, true); _current_layer_changed_connection.unblock(); _layers_changed_connection.unblock(); -- GitLab From a4b7093041cf7ec5dc4a8a21286aeedc3b58422f Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Sun, 7 Nov 2021 12:36:08 -0500 Subject: [PATCH 5/6] Remove isGroup --- src/object/sp-item-group.h | 1 - src/ui/contextmenu.cpp | 7 +------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/object/sp-item-group.h b/src/object/sp-item-group.h index e4712694ea..388f3dee47 100644 --- a/src/object/sp-item-group.h +++ b/src/object/sp-item-group.h @@ -31,7 +31,6 @@ public: enum LayerMode { GROUP, LAYER, MASK_HELPER }; - bool isGroup() const { return _layer_mode == GROUP; } bool isLayer() const { return _layer_mode == LAYER; } bool _insert_bottom; diff --git a/src/ui/contextmenu.cpp b/src/ui/contextmenu.cpp index 2db943d4a2..ccd1060ac5 100644 --- a/src/ui/contextmenu.cpp +++ b/src/ui/contextmenu.cpp @@ -646,8 +646,7 @@ void ContextMenu::MakeGroupMenu(SPGroup* item) // transform layer into group append_item(_("Layer to group"), false).connect([=]() { sp_group_layer_transform(_desktop->doc(), item, SPGroup::GROUP); }); - } - else if (item->isGroup()) { + } else { /* Ungroup */ append_item(_("_Ungroup"), true).connect(sigc::mem_fun(*this, &ContextMenu::ActivateUngroup)); @@ -681,10 +680,6 @@ void ContextMenu::MakeGroupMenu(SPGroup* item) } } } - else { - // not a plain group and not a layer; a mask helper? - // no special operations here so far - } } void ContextMenu::ActivateGroup() -- GitLab From 9df1bea7cfda8a043930c28f7775fb2b0254ac71 Mon Sep 17 00:00:00 2001 From: Martin Owens Date: Sun, 7 Nov 2021 15:03:07 -0500 Subject: [PATCH 6/6] Repair layer refactoring from verbs refactoring merge --- src/actions/actions-layer.cpp | 57 ++++++++++++++++++----------------- src/layer-manager.h | 2 ++ 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/actions/actions-layer.cpp b/src/actions/actions-layer.cpp index 2d66918bd6..782d05b94c 100644 --- a/src/actions/actions-layer.cpp +++ b/src/actions/actions-layer.cpp @@ -29,7 +29,7 @@ layer_new(InkscapeWindow* win) SPDesktop* dt = win->get_desktop(); // New Layer - Inkscape::UI::Dialogs::LayerPropertiesDialog::showCreate(dt, dt->currentLayer()); + Inkscape::UI::Dialogs::LayerPropertiesDialog::showCreate(dt, dt->layerManager().currentLayer()); } void @@ -38,18 +38,19 @@ layer_rename(InkscapeWindow* win) SPDesktop* dt = win->get_desktop(); // Rename Layer - Inkscape::UI::Dialogs::LayerPropertiesDialog::showRename(dt, dt->currentLayer()); + Inkscape::UI::Dialogs::LayerPropertiesDialog::showRename(dt, dt->layerManager().currentLayer()); } void layer_toggle_hide (InkscapeWindow* win) { SPDesktop* dt = win->get_desktop(); + auto layer = dt->layerManager().currentLayer(); - if (dt->currentLayer() == dt->currentRoot()) { + if (!layer || dt->layerManager().isRoot()) { dt->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No current layer.")); } else { - SP_ITEM(dt->currentLayer())->setHidden(!SP_ITEM(dt->currentLayer())->isHidden()); + layer->setHidden(!layer->isHidden()); } } @@ -57,11 +58,12 @@ void layer_toggle_lock (InkscapeWindow* win) { SPDesktop* dt = win->get_desktop(); + auto layer = dt->layerManager().currentLayer(); - if (dt->currentLayer() == dt->currentRoot()) { + if (!layer || dt->layerManager().isRoot()) { dt->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No current layer.")); } else { - SP_ITEM(dt->currentLayer())->setLocked(!SP_ITEM(dt->currentLayer())->isLocked()); + layer->setLocked(!layer->isLocked()); } } @@ -70,9 +72,9 @@ layer_previous (InkscapeWindow* win) { SPDesktop* dt = win->get_desktop(); - SPObject *next=Inkscape::next_layer(dt->currentRoot(), dt->currentLayer()); + SPObject *next = Inkscape::next_layer(dt->layerManager().currentRoot(), dt->layerManager().currentLayer()); if (next) { - dt->setCurrentLayer(next); + dt->layerManager().setCurrentLayer(next); Inkscape::DocumentUndo::done(dt->getDocument(),_("Switch to next layer"),INKSCAPE_ICON("layer-previous")); dt->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Switched to next layer.")); } else { @@ -85,9 +87,9 @@ layer_next (InkscapeWindow* win) { SPDesktop* dt = win->get_desktop(); - SPObject *prev=Inkscape::previous_layer(dt->currentRoot(), dt->currentLayer()); + SPObject *prev=Inkscape::previous_layer(dt->layerManager().currentRoot(), dt->layerManager().currentLayer()); if (prev) { - dt->setCurrentLayer(prev); + dt->layerManager().setCurrentLayer(prev); Inkscape::DocumentUndo::done(dt->getDocument(), _("Switch to previous layer"),INKSCAPE_ICON("layer-next")); dt->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Switched to previous layer.")); } else { @@ -119,7 +121,7 @@ selection_move_to_layer (InkscapeWindow* win) SPDesktop* dt = win->get_desktop(); // Selection move to layer - Inkscape::UI::Dialogs::LayerPropertiesDialog::showMove(dt, dt->currentLayer()); + Inkscape::UI::Dialogs::LayerPropertiesDialog::showMove(dt, dt->layerManager().currentLayer()); } void @@ -127,12 +129,12 @@ layer_top (InkscapeWindow* win) { SPDesktop* dt = win->get_desktop(); - if (dt->currentLayer() == dt->currentRoot()) { + if (dt->layerManager().isRoot()) { dt->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No current layer.")); return; } - SPItem *layer=SP_ITEM(dt->currentLayer()); + SPItem *layer = dt->layerManager().currentLayer(); g_return_if_fail(layer != nullptr); SPObject *old_pos = layer->getNext(); layer->raiseToTop(); @@ -154,12 +156,12 @@ layer_raise (InkscapeWindow* win) { SPDesktop* dt = win->get_desktop(); - if (dt->currentLayer() == dt->currentRoot()) { + if (dt->layerManager().isRoot()) { dt->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No current layer.")); return; } - SPItem *layer=SP_ITEM(dt->currentLayer()); + SPItem *layer = dt->layerManager().currentLayer(); g_return_if_fail(layer != nullptr); SPObject *old_pos = layer->getNext(); @@ -185,12 +187,12 @@ layer_lower (InkscapeWindow* win) { SPDesktop* dt = win->get_desktop(); - if (dt->currentLayer() == dt->currentRoot()) { + if (dt->layerManager().isRoot()) { dt->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No current layer.")); return; } - SPItem *layer=SP_ITEM(dt->currentLayer()); + SPItem *layer = dt->layerManager().currentLayer(); g_return_if_fail(layer != nullptr); SPObject *old_pos = layer->getNext(); layer->lowerOne(); @@ -212,12 +214,12 @@ layer_bottom (InkscapeWindow* win) { SPDesktop* dt = win->get_desktop(); - if (dt->currentLayer() == dt->currentRoot()) { + if (dt->layerManager().isRoot()) { dt->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("No current layer.")); return; } - SPItem *layer=SP_ITEM(dt->currentLayer()); + SPItem *layer = dt->layerManager().currentLayer(); g_return_if_fail(layer != nullptr); SPObject *old_pos = layer->getNext(); layer->lowerToBottom(); @@ -239,7 +241,7 @@ layer_duplicate (InkscapeWindow* win) { SPDesktop* dt = win->get_desktop(); - if (dt->currentLayer() != dt->currentRoot()) { + if (!dt->layerManager().isRoot()) { dt->selection->duplicate(true, true); Inkscape::DocumentUndo::done(dt->getDocument(), _("Duplicate layer"), INKSCAPE_ICON("layer-duplicate")); @@ -254,31 +256,32 @@ void layer_delete (InkscapeWindow* win) { SPDesktop* dt = win->get_desktop(); + auto root = dt->layerManager().currentRoot(); - if (dt->currentLayer() != dt->currentRoot()) { + if (!dt->layerManager().isRoot()) { dt->getSelection()->clear(); - SPObject *old_layer = dt->currentLayer(); + SPObject *old_layer = dt->layerManager().currentLayer(); SPObject *old_parent = old_layer->parent; SPObject *old_parent_parent = (old_parent != nullptr) ? old_parent->parent : nullptr; - SPObject *survivor = Inkscape::previous_layer(dt->currentRoot(), old_layer); + SPObject *survivor = Inkscape::previous_layer(root, old_layer); if (survivor != nullptr && survivor->parent == old_layer) { while (survivor != nullptr && survivor->parent != old_parent && survivor->parent != old_parent_parent) { - survivor = Inkscape::previous_layer(dt->currentRoot(), survivor); + survivor = Inkscape::previous_layer(root, survivor); } } if (survivor == nullptr || (survivor->parent != old_parent && survivor->parent != old_layer)) { - survivor = Inkscape::next_layer(dt->currentRoot(), old_layer); + survivor = Inkscape::next_layer(root, old_layer); while (survivor != nullptr && survivor != old_parent && survivor->parent != old_parent) { - survivor = Inkscape::next_layer(dt->currentRoot(), survivor); + survivor = Inkscape::next_layer(root, survivor); } } @@ -286,7 +289,7 @@ layer_delete (InkscapeWindow* win) old_layer->deleteObject(); if (survivor) { - dt->setCurrentLayer(survivor); + dt->layerManager().setCurrentLayer(survivor); } Inkscape::DocumentUndo::done(dt->getDocument(), _("Delete layer"), INKSCAPE_ICON("layer-delete")); diff --git a/src/layer-manager.h b/src/layer-manager.h index 333a825c7d..b60c59df24 100644 --- a/src/layer-manager.h +++ b/src/layer-manager.h @@ -55,6 +55,8 @@ public: bool isLayer(SPObject *object) const; static SPGroup *asLayer(SPObject *object); + bool isRoot() const { return currentLayer() == currentRoot(); } + private: friend class LayerWatcher; class LayerWatcher; -- GitLab