diff options
41 files changed, 384 insertions, 362 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 49f32fdea..fa54940db 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -239,6 +239,7 @@ set(inkscape_SRC knotholder.cpp layer-fns.cpp layer-manager.cpp + layer-model.cpp line-geometry.cpp line-snapper.cpp lpe-tool-context.cpp @@ -398,6 +399,7 @@ set(inkscape_SRC knotholder.h layer-fns.h layer-manager.h + layer-model.h line-geometry.h line-snapper.h lpe-tool-context.h diff --git a/src/Makefile_insert b/src/Makefile_insert index 87b2545c8..023d640ca 100644 --- a/src/Makefile_insert +++ b/src/Makefile_insert @@ -92,6 +92,7 @@ ink_common_sources += \ knot-holder-entity.h knot-holder-entity.cpp \ layer-fns.cpp layer-fns.h \ layer-manager.cpp layer-manager.h \ + layer-model.cpp layer-model.h \ line-geometry.cpp line-geometry.h \ line-snapper.cpp line-snapper.h \ lpe-tool-context.cpp lpe-tool-context.h \ diff --git a/src/desktop.cpp b/src/desktop.cpp index 17548ee56..485fcfcc4 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -53,15 +53,16 @@ #include "display/sp-canvas-util.h" #include "document.h" #include "event-log.h" +#include "helper/action-context.h" #include "helper/units.h" #include "interface.h" #include "inkscape-private.h" #include "layer-fns.h" #include "layer-manager.h" +#include "layer-model.h" #include "macros.h" #include "message-context.h" #include "message-stack.h" -#include "object-hierarchy.h" #include "preferences.h" #include "resource-manager.h" #include "select-context.h" @@ -95,6 +96,7 @@ SPDesktop::SPDesktop() : _dlg_mgr( 0 ), namedview( 0 ), canvas( 0 ), + layer_model( 0 ), selection( 0 ), event_context( 0 ), layer_manager( 0 ), @@ -125,7 +127,6 @@ SPDesktop::SPDesktop() : gr_point_type( POINT_LG_BEGIN ), gr_point_i( 0 ), gr_fill_or_stroke( Inkscape::FOR_FILL ), - _layer_hierarchy( 0 ), _reconstruction_old_layer_id(), // an id attribute is not allowed to be the empty string _display_mode(Inkscape::RENDERMODE_NORMAL), _display_color_mode(Inkscape::COLORMODE_NORMAL), @@ -140,8 +141,12 @@ SPDesktop::SPDesktop() : { _d2w.setIdentity(); _w2d.setIdentity(); - - selection = Inkscape::GC::release( new Inkscape::Selection(this) ); + + layer_model = new Inkscape::LayerModel(); + layer_model->_layer_activated_signal.connect(sigc::bind(sigc::ptr_fun(_layer_activated), this)); + layer_model->_layer_deactivated_signal.connect(sigc::bind(sigc::ptr_fun(_layer_deactivated), this)); + layer_model->_layer_changed_signal.connect(sigc::bind(sigc::ptr_fun(_layer_hierarchy_changed), this)); + selection = Inkscape::GC::release( new Inkscape::Selection(layer_model, this) ); } void @@ -170,6 +175,9 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWid dkey = SPItem::display_key_new(1); + /* Connect display key to layer model */ + layer_model->setDisplayKey(dkey); + /* Connect document */ setDocument (document); @@ -359,10 +367,7 @@ void SPDesktop::destroy() g_object_unref (G_OBJECT (ec)); } - if (_layer_hierarchy) { - delete _layer_hierarchy; -// _layer_hierarchy = NULL; //this should be here, but commented to find other bug somewhere else. - } + delete layer_model; if (layer_manager) { delete layer_manager; @@ -483,134 +488,45 @@ void SPDesktop::displayColorModeToggle() { } } -/** - * Returns current root (=bottom) layer. - */ +// Pass-through LayerModel functions SPObject *SPDesktop::currentRoot() const { - return _layer_hierarchy ? _layer_hierarchy->top() : NULL; + return layer_model->currentRoot(); } -/** - * Returns current top layer. - */ SPObject *SPDesktop::currentLayer() const { - return _layer_hierarchy ? _layer_hierarchy->bottom() : NULL; -} - -/** - * Sets the current layer of the desktop. - * - * Make \a object the top layer. - */ -void SPDesktop::setCurrentLayer(SPObject *object) { - g_return_if_fail(SP_IS_GROUP(object)); - g_return_if_fail( currentRoot() == object || (currentRoot() && currentRoot()->isAncestorOf(object)) ); - // printf("Set Layer to ID: %s\n", object->getId()); - _layer_hierarchy->setBottom(object); + return layer_model->currentLayer(); } -void SPDesktop::toggleHideAllLayers(bool hide) { - - for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), currentRoot()); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) { - SP_ITEM(obj)->setHidden(hide); - } +void SPDesktop::setCurrentLayer(SPObject *object) +{ + layer_model->setCurrentLayer(object); } -void SPDesktop::toggleLockAllLayers(bool lock) { - - for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), currentRoot()); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) { - SP_ITEM(obj)->setLocked(lock); - } +void SPDesktop::toggleLayerSolo(SPObject *object) +{ + layer_model->toggleLayerSolo(object); } -void SPDesktop::toggleLockOtherLayers(SPObject *object) { - g_return_if_fail(SP_IS_GROUP(object)); - g_return_if_fail( currentRoot() == object || (currentRoot() && currentRoot()->isAncestorOf(object)) ); - - bool othersLocked = false; - std::vector<SPObject*> layers; - for ( SPObject* obj = Inkscape::next_layer(currentRoot(), object); obj; obj = Inkscape::next_layer(currentRoot(), obj) ) { - // Dont lock any ancestors, since that would in turn lock the layer as well - if (!obj->isAncestorOf(object)) { - layers.push_back(obj); - othersLocked |= !SP_ITEM(obj)->isLocked(); - } - } - for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), object); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) { - if (!obj->isAncestorOf(object)) { - layers.push_back(obj); - othersLocked |= !SP_ITEM(obj)->isLocked(); - } - } - - SPItem *item = SP_ITEM(object); - if ( item->isLocked() ) { - item->setLocked(false); - } - - for ( std::vector<SPObject*>::iterator it = layers.begin(); it != layers.end(); ++it ) { - SP_ITEM(*it)->setLocked(othersLocked); - } +void SPDesktop::toggleHideAllLayers(bool hide) +{ + layer_model->toggleHideAllLayers(hide); } - -void SPDesktop::toggleLayerSolo(SPObject *object) { - g_return_if_fail(SP_IS_GROUP(object)); - g_return_if_fail( currentRoot() == object || (currentRoot() && currentRoot()->isAncestorOf(object)) ); - - bool othersShowing = false; - std::vector<SPObject*> layers; - for ( SPObject* obj = Inkscape::next_layer(currentRoot(), object); obj; obj = Inkscape::next_layer(currentRoot(), obj) ) { - // Don't hide ancestors, since that would in turn hide the layer as well - if (!obj->isAncestorOf(object)) { - layers.push_back(obj); - othersShowing |= !SP_ITEM(obj)->isHidden(); - } - } - for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), object); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) { - if (!obj->isAncestorOf(object)) { - layers.push_back(obj); - othersShowing |= !SP_ITEM(obj)->isHidden(); - } - } - - - SPItem *item = SP_ITEM(object); - if ( item->isHidden() ) { - item->setHidden(false); - } - - for ( std::vector<SPObject*>::iterator it = layers.begin(); it != layers.end(); ++it ) { - SP_ITEM(*it)->setHidden(othersShowing); - } +void SPDesktop::toggleLockAllLayers(bool lock) +{ + layer_model->toggleLockAllLayers(lock); } -/** - * Return layer that contains \a object. - */ -SPObject *SPDesktop::layerForObject(SPObject *object) { - g_return_val_if_fail(object != NULL, NULL); - - SPObject *root=currentRoot(); - object = object->parent; - while ( object && object != root && !isLayer(object) ) { - // Objects in defs have no layer and are NOT in the root layer - if(SP_IS_DEFS(object)) - return NULL; - object = object->parent; - } - return object; +void SPDesktop::toggleLockOtherLayers(SPObject *object) +{ + layer_model->toggleLockOtherLayers(object); } -/** - * True if object is a layer. - */ -bool SPDesktop::isLayer(SPObject *object) const { - return ( SP_IS_GROUP(object) - && ( SP_GROUP(object)->effectiveLayerMode(this->dkey) - == SPGroup::LAYER ) ); +bool SPDesktop::isLayer(SPObject *object) const +{ + return layer_model->isLayer(object); } /** @@ -1575,15 +1491,7 @@ SPDesktop::setDocument (SPDocument *doc) this->doc()->getRoot()->invoke_hide(dkey); } - if (_layer_hierarchy) { - _layer_hierarchy->clear(); - delete _layer_hierarchy; - } - _layer_hierarchy = new Inkscape::ObjectHierarchy(NULL); - _layer_hierarchy->connectAdded(sigc::bind(sigc::ptr_fun(_layer_activated), this)); - _layer_hierarchy->connectRemoved(sigc::bind(sigc::ptr_fun(_layer_deactivated), this)); - _layer_hierarchy->connectChanged(sigc::bind(sigc::ptr_fun(_layer_hierarchy_changed), this)); - _layer_hierarchy->setTop(doc->getRoot()); + layer_model->setDocument(doc); // remove old EventLog if it exists (see also: bug #1071082) if (event_log) { @@ -1691,9 +1599,9 @@ _onSelectionChanged */ SPItem *item=selection->singleItem(); if (item) { - SPObject *layer=desktop->layerForObject(item); + SPObject *layer=desktop->layer_model->layerForObject(item); if ( layer && layer != desktop->currentLayer() ) { - desktop->setCurrentLayer(layer); + desktop->layer_model->setCurrentLayer(layer); } } } @@ -1740,7 +1648,7 @@ static void _reconstruction_start(SPDesktop * desktop) { // printf("Desktop, starting reconstruction\n"); desktop->_reconstruction_old_layer_id = desktop->currentLayer()->getId() ? desktop->currentLayer()->getId() : ""; - desktop->_layer_hierarchy->setBottom(desktop->currentRoot()); + desktop->layer_model->reset(); /* GSList const * selection_objs = desktop->selection->list(); @@ -1760,7 +1668,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 != NULL) { - desktop->setCurrentLayer(newLayer); + desktop->layer_model->setCurrentLayer(newLayer); } desktop->_reconstruction_old_layer_id.clear(); @@ -1931,7 +1839,7 @@ SPDesktop::show_dialogs() if (visible) { Inkscape::Verb *verb = Inkscape::Verb::get(verbId); if (verb) { - SPAction *action = verb->get_action(this); + SPAction *action = verb->get_action(Inkscape::ActionContext(this)); if (action) { sp_action_perform(action, NULL); } diff --git a/src/desktop.h b/src/desktop.h index 56de56c65..661470ded 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -62,9 +62,9 @@ typedef struct _GdkEventWindowState GdkEventWindowState; namespace Inkscape { struct Application; + class LayerModel; class MessageContext; class Selection; - class ObjectHierarchy; class LayerManager; class EventLog; namespace UI { @@ -125,6 +125,7 @@ public: Inkscape::UI::Dialog::DialogManager *_dlg_mgr; SPNamedView *namedview; SPCanvas *canvas; + Inkscape::LayerModel *layer_model; /// current selection; will never generally be NULL Inkscape::Selection *selection; SPEventContext *event_context; @@ -170,8 +171,6 @@ public: guint gr_point_i; Inkscape::PaintTarget gr_fill_or_stroke; - - Inkscape::ObjectHierarchy *_layer_hierarchy; Glib::ustring _reconstruction_old_layer_id; sigc::signal<void, sp_verb_t> _tool_changed; @@ -264,17 +263,16 @@ public: void set_active (bool new_active); - // TODO look into making these return a more specific subclass: + // Could make all callers use layer_model 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); - SPObject *layerForObject(SPObject *object); bool isLayer(SPObject *object) const; + bool isWithinViewport(SPItem *item) const; bool itemIsHidden(SPItem const *item) const; diff --git a/src/dyna-draw-context.cpp b/src/dyna-draw-context.cpp index 605e487ab..c37f9cb4b 100644 --- a/src/dyna-draw-context.cpp +++ b/src/dyna-draw-context.cpp @@ -999,10 +999,10 @@ set_to_accumulated(SPDynaDrawContext *dc, bool unionize, bool subtract) if (unionize) { sp_desktop_selection(desktop)->add(dc->repr); - sp_selected_path_union_skip_undo(desktop); + sp_selected_path_union_skip_undo(sp_desktop_selection(desktop), desktop); } else if (subtract) { sp_desktop_selection(desktop)->add(dc->repr); - sp_selected_path_diff_skip_undo(desktop); + sp_selected_path_diff_skip_undo(sp_desktop_selection(desktop), desktop); } else { if (dc->keep_selected) { sp_desktop_selection(desktop)->set(dc->repr); diff --git a/src/eraser-context.cpp b/src/eraser-context.cpp index b34e3352c..a337f941b 100644 --- a/src/eraser-context.cpp +++ b/src/eraser-context.cpp @@ -751,7 +751,7 @@ set_to_accumulated(SPEraserContext *dc) selection->set(item); selection->add(dup); - sp_selected_path_diff_skip_undo(desktop); + sp_selected_path_diff_skip_undo(selection, desktop); workDone = true; // TODO set this only if something was cut. if ( !selection->isEmpty() ) { // If the item was not completely erased, track the new remainder. diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index 56d1dfdbd..bdf1fa98c 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -30,6 +30,7 @@ #include "extension/system.h" //IO #include "file.h" //IO #include "helper/action.h" //sp_action_perform +#include "helper/action-context.h" #include "inkscape.h" //inkscape_find_desktop_by_dkey, activate desktops #include "layer-fns.h" //LPOS_BELOW #include "live_effects/parameter/text.h" //text @@ -263,7 +264,7 @@ dbus_call_verb (DocumentInterface *object, int verbid, GError **error) if ( desk2 ) { Inkscape::Verb *verb = Inkscape::Verb::get( verbid ); if ( verb ) { - SPAction *action = verb->get_action(desk2); + SPAction *action = verb->get_action(Inkscape::ActionContext(desk2)); if ( action ) { //if (!object->updates) //document_interface_pause_updates (object, error); @@ -342,7 +343,7 @@ document_interface_call_verb (DocumentInterface *object, gchar *verbid, GError * if ( desk2 ) { Inkscape::Verb *verb = Inkscape::Verb::getbyid( verbid ); if ( verb ) { - SPAction *action = verb->get_action(desk2); + SPAction *action = verb->get_action(Inkscape::ActionContext(desk2)); if ( action ) { sp_action_perform( action, NULL ); if (object->updates) { diff --git a/src/extension/effect.cpp b/src/extension/effect.cpp index 1df8002ad..22c5e4989 100644 --- a/src/extension/effect.cpp +++ b/src/extension/effect.cpp @@ -359,9 +359,9 @@ Effect::set_pref_dialog (PrefDialog * prefdialog) } SPAction * -Effect::EffectVerb::make_action (Inkscape::UI::View::View * view) +Effect::EffectVerb::make_action (Inkscape::ActionContext const & context) { - return make_action_helper(view, &perform, static_cast<void *>(this)); + return make_action_helper(context, &perform, static_cast<void *>(this)); } /** \brief Decode the verb code and take appropriate action */ diff --git a/src/extension/effect.h b/src/extension/effect.h index 193b90a97..a14cc6e7d 100644 --- a/src/extension/effect.h +++ b/src/extension/effect.h @@ -58,7 +58,7 @@ class Effect : public Extension { /** \brief Name with elipses if that makes sense */ gchar * _elip_name; protected: - virtual SPAction * make_action (Inkscape::UI::View::View * view); + virtual SPAction * make_action (Inkscape::ActionContext const & context); public: /** \brief Use the Verb initializer with the same parameters. */ EffectVerb(gchar const * id, diff --git a/src/extension/internal/bluredge.cpp b/src/extension/internal/bluredge.cpp index 8f1e07211..a3d2fd6e5 100644 --- a/src/extension/internal/bluredge.cpp +++ b/src/extension/internal/bluredge.cpp @@ -17,6 +17,7 @@ #include "document.h" #include "selection.h" #include "helper/action.h" +#include "helper/action-context.h" #include "preferences.h" #include "path-chemistry.h" #include "sp-item.h" @@ -99,10 +100,10 @@ BlurEdge::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View /* Doing an inset here folks */ offset *= -1.0; prefs->setDoubleUnit("/options/defaultoffsetwidth/value", offset, "px"); - sp_action_perform(Inkscape::Verb::get(SP_VERB_SELECTION_INSET)->get_action(desktop), NULL); + sp_action_perform(Inkscape::Verb::get(SP_VERB_SELECTION_INSET)->get_action(Inkscape::ActionContext(desktop)), NULL); } else if (offset > 0.0) { prefs->setDoubleUnit("/options/defaultoffsetwidth/value", offset, "px"); - sp_action_perform(Inkscape::Verb::get(SP_VERB_SELECTION_OFFSET)->get_action(desktop), NULL); + sp_action_perform(Inkscape::Verb::get(SP_VERB_SELECTION_OFFSET)->get_action(Inkscape::ActionContext(desktop)), NULL); } selection->clear(); diff --git a/src/extension/internal/filter/filter-all.cpp b/src/extension/internal/filter/filter-all.cpp index 0273d1669..0273d1669 100755..100644 --- a/src/extension/internal/filter/filter-all.cpp +++ b/src/extension/internal/filter/filter-all.cpp diff --git a/src/flood-context.cpp b/src/flood-context.cpp index bb6864f7e..8fde11f88 100644 --- a/src/flood-context.cpp +++ b/src/flood-context.cpp @@ -511,7 +511,7 @@ static void do_trace(bitmap_coords_info bci, guchar *trace_px, SPDesktop *deskto ngettext("Area filled, path with <b>%d</b> node created and unioned with selection.","Area filled, path with <b>%d</b> nodes created and unioned with selection.", SP_PATH(reprobj)->nodesInPath()), SP_PATH(reprobj)->nodesInPath() ); selection->add(reprobj); - sp_selected_path_union_skip_undo(desktop); + sp_selected_path_union_skip_undo(sp_desktop_selection(desktop), desktop); } else { desktop->messageStack()->flashF( Inkscape::WARNING_MESSAGE, ngettext("Area filled, path with <b>%d</b> node created.","Area filled, path with <b>%d</b> nodes created.", diff --git a/src/helper/CMakeLists.txt b/src/helper/CMakeLists.txt index f709c7386..2e1e724f5 100644 --- a/src/helper/CMakeLists.txt +++ b/src/helper/CMakeLists.txt @@ -10,6 +10,7 @@ set(sp_marshal_SRC set(helper_SRC action.cpp + action-context.cpp geom.cpp geom-nodetype.cpp gnome-utils.cpp @@ -29,6 +30,7 @@ set(helper_SRC # ------- # Headers action.h + action-context.h geom-curves.h geom-nodetype.h geom.h diff --git a/src/helper/Makefile_insert b/src/helper/Makefile_insert index 2be40e0e0..790d87b14 100644 --- a/src/helper/Makefile_insert +++ b/src/helper/Makefile_insert @@ -5,6 +5,8 @@ helper/unit-menu.$(OBJEXT): helper/sp-marshal.h ink_common_sources += \ helper/action.cpp \ helper/action.h \ + helper/action-context.cpp \ + helper/action-context.h \ helper/geom.cpp \ helper/geom.h \ helper/geom-curves.h \ diff --git a/src/helper/action.cpp b/src/helper/action.cpp index 0e9957ca3..107d0179b 100644 --- a/src/helper/action.cpp +++ b/src/helper/action.cpp @@ -41,7 +41,7 @@ sp_action_init (SPAction *action) { action->sensitive = 0; action->active = 0; - action->view = NULL; + action->context = Inkscape::ActionContext(); action->id = action->name = action->tip = NULL; action->image = NULL; @@ -76,7 +76,7 @@ sp_action_finalize (GObject *object) * Create new SPAction object and set its properties. */ SPAction * -sp_action_new(Inkscape::UI::View::View *view, +sp_action_new(Inkscape::ActionContext const &context, const gchar *id, const gchar *name, const gchar *tip, @@ -85,7 +85,7 @@ sp_action_new(Inkscape::UI::View::View *view, { SPAction *action = (SPAction *)g_object_new(SP_TYPE_ACTION, NULL); - action->view = view; + action->context = context; action->sensitive = TRUE; action->id = g_strdup (id); action->name = g_strdup (name); @@ -111,11 +111,9 @@ public: : ActionEventBase(share_static_string("action")) { _addProperty(share_static_string("timestamp"), timestamp()); - if (action->view) { - SPDocument *document = action->view->doc(); - if (document) { - _addProperty(share_static_string("document"), document->serial()); - } + SPDocument *document = action->context.getDocument(); + if (document) { + _addProperty(share_static_string("document"), document->serial()); } _addProperty(share_static_string("verb"), action->id); } @@ -170,13 +168,33 @@ sp_action_set_name (SPAction *action, Glib::ustring const &name) } /** + * Return Document associated with the action. + */ +SPDocument * +sp_action_get_document (SPAction *action) +{ + g_return_val_if_fail (SP_IS_ACTION (action), NULL); + return action->context.getDocument(); +} + +/** + * Return Selection associated with the action + */ +Inkscape::Selection * +sp_action_get_selection (SPAction *action) +{ + g_return_val_if_fail (SP_IS_ACTION (action), NULL); + return action->context.getSelection(); +} + +/** * Return View associated with the action. */ Inkscape::UI::View::View * sp_action_get_view (SPAction *action) { g_return_val_if_fail (SP_IS_ACTION (action), NULL); - return action->view; + return action->context.getView(); } /* diff --git a/src/helper/action.h b/src/helper/action.h index 0cd010b34..49816e3c9 100644 --- a/src/helper/action.h +++ b/src/helper/action.h @@ -12,6 +12,7 @@ #ifndef SEEN_INKSCAPE_SP_ACTION_H #define SEEN_INKSCAPE_SP_ACTION_H +#include "helper/action-context.h" #include <sigc++/sigc++.h> #include <glibmm/ustring.h> #include <glib-object.h> @@ -24,8 +25,12 @@ struct SPActionClass; #define SP_ACTION_CLASS(o) (G_TYPE_CHECK_CLASS_CAST((o), SP_TYPE_ACTION, SPActionClass)) #define SP_IS_ACTION(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), SP_TYPE_ACTION)) +class SPDocument; namespace Inkscape { + +class Selection; class Verb; + namespace UI { namespace View { class View; @@ -39,7 +44,7 @@ class View; struct SPAction : public GObject { unsigned sensitive : 1; /**< Value to track whether the action is sensitive */ unsigned active : 1; /**< Value to track whether the action is active */ - Inkscape::UI::View::View *view; /**< The View to which this action is attached */ + Inkscape::ActionContext context; /**< The context (doc/view) to which this action is attached */ gchar *id; /**< The identifier for the action */ gchar *name; /**< Full text name of the action */ gchar *tip; /**< A tooltip to describe the action */ @@ -59,7 +64,7 @@ struct SPActionClass { GType sp_action_get_type(); -SPAction *sp_action_new(Inkscape::UI::View::View *view, +SPAction *sp_action_new(Inkscape::ActionContext const &context, gchar const *id, gchar const *name, gchar const *tip, @@ -70,6 +75,8 @@ void sp_action_perform(SPAction *action, void *data); void sp_action_set_active(SPAction *action, unsigned active); void sp_action_set_sensitive(SPAction *action, unsigned sensitive); void sp_action_set_name(SPAction *action, Glib::ustring const &name); +SPDocument *sp_action_get_document(SPAction *action); +Inkscape::Selection *sp_action_get_selection(SPAction *action); Inkscape::UI::View::View *sp_action_get_view(SPAction *action); #endif diff --git a/src/inkscape.cpp b/src/inkscape.cpp index 7e570deb7..125a7176a 100644 --- a/src/inkscape.cpp +++ b/src/inkscape.cpp @@ -87,7 +87,7 @@ enum { LAST_SIGNAL }; -#define DESKTOP_IS_ACTIVE(d) ((d) == inkscape->desktops->data) +#define DESKTOP_IS_ACTIVE(d) (inkscape->desktops && ((d) == inkscape->desktops->data)) /*################################ diff --git a/src/interface.cpp b/src/interface.cpp index 986d3107f..e3036afdd 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -53,6 +53,7 @@ #include "sp-namedview.h" #include "ui/view/view.h" #include "helper/action.h" +#include "helper/action-context.h" #include "helper/gnome-utils.h" #include "helper/window.h" #include "io/sys.h" @@ -370,13 +371,13 @@ sp_ui_menu_activate(void */*object*/, SPAction *action) static void sp_ui_menu_select_action(void */*object*/, SPAction *action) { - action->view->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, action->tip); + sp_action_get_view(action)->tipsMessageContext()->set(Inkscape::NORMAL_MESSAGE, action->tip); } static void sp_ui_menu_deselect_action(void */*object*/, SPAction *action) { - action->view->tipsMessageContext()->clear(); + sp_action_get_view(action)->tipsMessageContext()->clear(); } static void @@ -419,7 +420,7 @@ sp_ui_dialog_title_string(Inkscape::Verb *verb, gchar *c) gchar *s; gchar *atitle; - action = verb->get_action(NULL); + action = verb->get_action(Inkscape::ActionContext()); if (!action) return; @@ -456,7 +457,7 @@ static GtkWidget *sp_ui_menu_append_item_from_verb(GtkMenu *menu, Inkscape::Verb } else { - action = verb->get_action(view); + action = verb->get_action(Inkscape::ActionContext(view)); if (!action) return NULL; if (radio) { @@ -670,7 +671,7 @@ sp_ui_menu_append_check_item_from_verb(GtkMenu *menu, Inkscape::UI::View::View * Inkscape::Verb *verb) { unsigned int shortcut = (verb) ? sp_shortcut_get_primary(verb) : 0; - SPAction *action = (verb) ? verb->get_action(view) : 0; + SPAction *action = (verb) ? verb->get_action(Inkscape::ActionContext(view)) : 0; GtkWidget *item = gtk_check_menu_item_new_with_mnemonic(action ? action->name : label); #if 0 @@ -955,7 +956,7 @@ static void sp_ui_build_dyn_menus(Inkscape::XML::Node *menus, GtkWidget *menu, I gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), TRUE); } if (verb->get_code() != SP_VERB_NONE) { - SPAction *action = verb->get_action(view); + SPAction *action = verb->get_action(Inkscape::ActionContext(view)); #if GTK_CHECK_VERSION(3,0,0) g_signal_connect( G_OBJECT(item), "draw", (GCallback) update_view_menu, (void *) action); #else @@ -965,7 +966,7 @@ static void sp_ui_build_dyn_menus(Inkscape::XML::Node *menus, GtkWidget *menu, I } else if (menu_pntr->attribute("check") != NULL) { SPAction *action = NULL; if (verb->get_code() != SP_VERB_NONE) { - action = verb->get_action(view); + action = verb->get_action(Inkscape::ActionContext(view)); } sp_ui_menu_append_check_item_from_verb(GTK_MENU(menu), view, action->name, action->tip, NULL, checkitem_toggled, checkitem_update, verb); @@ -1671,7 +1672,7 @@ void ContextMenu::AppendItemFromVerb(Inkscape::Verb *verb)//, SPDesktop *view)// item->show(); append(*item); } else { - action = verb->get_action(view); + action = verb->get_action(Inkscape::ActionContext(view)); if (!action) { return; } @@ -2035,7 +2036,7 @@ void ContextMenu::AnchorLinkFollow(void) // Opening the selected links with a python extension Inkscape::Verb *verb = Inkscape::Verb::getbyid( "org.inkscape.followlink" ); if (verb) { - SPAction *action = verb->get_action(_desktop); + SPAction *action = verb->get_action(Inkscape::ActionContext(_desktop)); if (action) { sp_action_perform(action, NULL); } @@ -2205,7 +2206,7 @@ void ContextMenu::ImageEmbed(void) Inkscape::Verb *verb = Inkscape::Verb::getbyid( "org.ekips.filter.embedselectedimages" ); if (verb) { - SPAction *action = verb->get_action(_desktop); + SPAction *action = verb->get_action(Inkscape::ActionContext(_desktop)); if (action) { sp_action_perform(action, NULL); } @@ -2220,7 +2221,7 @@ void ContextMenu::ImageExtract(void) Inkscape::Verb *verb = Inkscape::Verb::getbyid( "org.ekips.filter.extractimage" ); if (verb) { - SPAction *action = verb->get_action(_desktop); + SPAction *action = verb->get_action(Inkscape::ActionContext(_desktop)); if (action) { sp_action_perform(action, NULL); } diff --git a/src/main-cmdlineact.cpp b/src/main-cmdlineact.cpp index 9f700292e..6af616e34 100644 --- a/src/main-cmdlineact.cpp +++ b/src/main-cmdlineact.cpp @@ -11,6 +11,7 @@ #include <desktop.h> #include <desktop-handles.h> #include <helper/action.h> +#include <helper/action-context.h> #include <selection.h> #include <verbs.h> #include <inkscape.h> @@ -41,7 +42,7 @@ CmdLineAction::~CmdLineAction () { } void -CmdLineAction::doIt (Inkscape::UI::View::View * view) { +CmdLineAction::doIt (ActionContext const & context) { //printf("Doing: %s\n", _arg); if (_isVerb) { Inkscape::Verb * verb = Inkscape::Verb::getbyid(_arg); @@ -49,32 +50,33 @@ CmdLineAction::doIt (Inkscape::UI::View::View * view) { printf(_("Unable to find verb ID '%s' specified on the command line.\n"), _arg); return; } - SPAction * action = verb->get_action(view); + SPAction * action = verb->get_action(context); sp_action_perform(action, NULL); } else { - SPDesktop * desktop = dynamic_cast<SPDesktop *>(view); - if (desktop == NULL) { return; } + if (context.getDocument() == NULL || context.getSelection() == NULL) { return; } - SPDocument * doc = view->doc(); + SPDocument * doc = context.getDocument(); SPObject * obj = doc->getObjectById(_arg); if (obj == NULL) { printf(_("Unable to find node ID: '%s'\n"), _arg); return; } - Inkscape::Selection * selection = sp_desktop_selection(desktop); + Inkscape::Selection * selection = context.getSelection(); selection->add(obj, false); } return; } -void -CmdLineAction::doList (Inkscape::UI::View::View * view) { +bool +CmdLineAction::doList (ActionContext const & context) { + bool hasActions = !_list.empty(); for (std::list<CmdLineAction *>::iterator i = _list.begin(); i != _list.end(); ++i) { CmdLineAction * entry = *i; - entry->doIt(view); + entry->doIt(context); } + return hasActions; } bool @@ -87,8 +89,8 @@ CmdLineAction::idle (void) { for (std::list<SPDesktop *>::iterator i = desktops.begin(); i != desktops.end(); ++i) { SPDesktop * desktop = *i; - //Inkscape::UI::View::View * view = dynamic_cast<Inkscape::UI::View::View *>(desktop); - doList(desktop); + //Inkscape::UI::View::View * view = dynamic_cast<Inkscape::UI::View::View *>(desktop); + doList(ActionContext(desktop)); } return false; } diff --git a/src/main-cmdlineact.h b/src/main-cmdlineact.h index 03f0eb0fc..fe11357fa 100644 --- a/src/main-cmdlineact.h +++ b/src/main-cmdlineact.h @@ -19,6 +19,8 @@ namespace Inkscape { +class ActionContext; + class CmdLineAction { bool _isVerb; gchar * _arg; @@ -29,8 +31,9 @@ public: CmdLineAction (bool isVerb, gchar const * arg); virtual ~CmdLineAction (); - void doIt (Inkscape::UI::View::View * view); - static void doList (Inkscape::UI::View::View * view); + void doIt (ActionContext const & context); + /** Return true if any actions were performed */ + static bool doList (ActionContext const & context); static bool idle (void); }; diff --git a/src/main.cpp b/src/main.cpp index 19ea3f181..49ef33fc9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -60,6 +60,8 @@ #include "macros.h" #include "file.h" #include "document.h" +#include "layer-model.h" +#include "selection.h" #include "sp-object.h" #include "interface.h" #include "print.h" @@ -85,6 +87,7 @@ #include "debug/logger.h" #include "debug/log-display-config.h" +#include "helper/action-context.h" #include "helper/png-write.h" #include "helper/geom.h" @@ -1066,7 +1069,20 @@ static int sp_process_file_list(GSList *fl) if (sp_vacuum_defs) { doc->vacuumDocument(); } - if (sp_vacuum_defs && !sp_export_svg) { + + bool has_performed_actions = false; + { + // Create layer model and selection model so we can run some verbs without a GUI + Inkscape::LayerModel layer_model; + layer_model.setDocument(doc); + Inkscape::Selection *selection = Inkscape::GC::release(new Inkscape::Selection(&layer_model, NULL)); + + // Execute command-line actions (selections and verbs) using our local models + Inkscape::ActionContext context(selection); + has_performed_actions = Inkscape::CmdLineAction::doList(context); + } + + if (!sp_export_svg && (sp_vacuum_defs || has_performed_actions)) { // save under the name given in the command line sp_repr_save_file(doc->rdoc, filename, SP_SVG_NS_URI); } diff --git a/src/selection-describer.cpp b/src/selection-describer.cpp index 72467c187..ce2d1c90b 100644 --- a/src/selection-describer.cpp +++ b/src/selection-describer.cpp @@ -17,6 +17,7 @@ #include <glibmm/i18n.h> #include "xml/quote.h" +#include "layer-model.h" #include "selection.h" #include "selection-describer.h" #include "desktop.h" @@ -144,8 +145,8 @@ void SelectionDescriber::_updateMessageFromSelection(Inkscape::Selection *select _context.set(Inkscape::NORMAL_MESSAGE, _when_nothing); } else { SPItem *item = SP_ITEM(items->data); - SPObject *layer = selection->desktop()->layerForObject(item); - SPObject *root = selection->desktop()->currentRoot(); + SPObject *layer = selection->layerModel()->layerForObject(item); + SPObject *root = selection->layerModel()->currentRoot(); // Layer name gchar *layer_name; diff --git a/src/selection.cpp b/src/selection.cpp index 564f1fdd3..76f49f544 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -21,9 +21,8 @@ #endif #include "macros.h" #include "inkscape-private.h" -#include "desktop.h" -#include "desktop-handles.h" #include "document.h" +#include "layer-model.h" #include "selection.h" #include <2geom/rect.h> #include "xml/repr.h" @@ -42,10 +41,11 @@ namespace Inkscape { -Selection::Selection(SPDesktop *desktop) : +Selection::Selection(LayerModel *layer_model, SPDesktop *desktop) : _objs(NULL), _reprs(NULL), _items(NULL), + _layer_model(layer_model), _desktop(desktop), _selection_context(NULL), _flags(0), @@ -55,7 +55,7 @@ Selection::Selection(SPDesktop *desktop) : Selection::~Selection() { _clear(); - _desktop = NULL; + _layer_model = NULL; if (_idle) { g_source_remove(_idle); _idle = 0; @@ -96,7 +96,7 @@ void Selection::_emitModified(guint flags) { void Selection::_emitChanged(bool persist_selection_context/* = false */) { if (persist_selection_context) { if (NULL == _selection_context) { - _selection_context = desktop()->currentLayer(); + _selection_context = _layer_model->currentLayer(); sp_object_ref(_selection_context, NULL); _context_release_connection = _selection_context->connectRelease(sigc::mem_fun(*this, &Selection::_releaseContext)); } @@ -139,7 +139,7 @@ void Selection::_clear() { SPObject *Selection::activeContext() { if (NULL != _selection_context) return _selection_context; - return desktop()->currentLayer(); + return _layer_model->currentLayer(); } bool Selection::includes(SPObject *obj) const { @@ -487,7 +487,7 @@ SPObject *Selection::_objectForXMLNode(Inkscape::XML::Node *repr) const { g_return_val_if_fail(repr != NULL, NULL); gchar const *id = repr->attribute("id"); g_return_val_if_fail(id != NULL, NULL); - SPObject *object=sp_desktop_document(_desktop)->getObjectById(id); + SPObject *object=_layer_model->getDocument()->getObjectById(id); g_return_val_if_fail(object != NULL, NULL); return object; } @@ -496,7 +496,7 @@ guint Selection::numberOfLayers() { GSList const *items = const_cast<Selection *>(this)->itemList(); GSList *layers = NULL; for (GSList const *iter = items; iter != NULL; iter = iter->next) { - SPObject *layer = desktop()->layerForObject(SP_OBJECT(iter->data)); + SPObject *layer = _layer_model->layerForObject(SP_OBJECT(iter->data)); if (g_slist_find (layers, layer) == NULL) { layers = g_slist_prepend (layers, layer); } diff --git a/src/selection.h b/src/selection.h index 10775dcb5..65a6c5140 100644 --- a/src/selection.h +++ b/src/selection.h @@ -33,6 +33,7 @@ class SPBox3D; struct Persp3D; namespace Inkscape { +class LayerModel; namespace XML { class Node; } @@ -41,10 +42,10 @@ class Node; namespace Inkscape { /** - * The set of selected SPObjects for a given desktop. + * The set of selected SPObjects for a given document and layer model. * * This class represents the set of selected SPItems for a given - * SPDesktop. + * document (referenced in LayerModel). * * An SPObject and its parent cannot be simultaneously selected; * selecting an SPObjects has the side-effect of unselecting any of @@ -64,17 +65,26 @@ class Selection : public Inkscape::GC::Managed<>, public: /** * Constructs an selection object, bound to a particular - * SPDesktop + * layer model * - * @param desktop the desktop in question + * @param layer_model the layer model (for the SPDesktop, if GUI) + * @param desktop the desktop associated with the layer model, or NULL if in console mode */ - Selection(SPDesktop *desktop); + Selection(LayerModel *layer_model, SPDesktop *desktop); ~Selection(); /** + * 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 *layerModel() { return _layer_model; } + + /** * Returns the desktop the selection is bound to * - * @return the desktop the selection is bound to + * @return the desktop the selection is bound to, or NULL if in console mode */ SPDesktop *desktop() { return _desktop; } @@ -342,6 +352,7 @@ private: std::list<SPBox3D *> _3dboxes; + LayerModel *_layer_model; GC::soft_ptr<SPDesktop> _desktop; SPObject* _selection_context; guint _flags; diff --git a/src/shortcuts.cpp b/src/shortcuts.cpp index 2af04929e..231e33e4a 100644 --- a/src/shortcuts.cpp +++ b/src/shortcuts.cpp @@ -35,6 +35,7 @@ #include <glibmm/miscutils.h> #include "helper/action.h" +#include "helper/action-context.h" #include "io/sys.h" #include "io/resource.h" #include "verbs.h" @@ -68,7 +69,7 @@ sp_shortcut_invoke(unsigned int shortcut, Inkscape::UI::View::View *view) { Inkscape::Verb *verb = sp_shortcut_get_verb(shortcut); if (verb) { - SPAction *action = verb->get_action(view); + SPAction *action = verb->get_action(Inkscape::ActionContext(view)); if (action) { sp_action_perform(action, NULL); return true; diff --git a/src/splivarot.cpp b/src/splivarot.cpp index e45712134..0ec9da2a7 100644 --- a/src/splivarot.cpp +++ b/src/splivarot.cpp @@ -34,6 +34,7 @@ #include "style.h" #include "document.h" #include "document-undo.h" +#include "layer-model.h" #include "message-stack.h" #include "selection.h" #include "desktop-handles.h" @@ -58,79 +59,89 @@ using Inkscape::DocumentUndo; bool Ancetre(Inkscape::XML::Node *a, Inkscape::XML::Node *who); -void sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb=SP_VERB_NONE, const Glib::ustring description=""); +void sp_selected_path_boolop(Inkscape::Selection *selection, SPDesktop *desktop, bool_op bop, const unsigned int verb=SP_VERB_NONE, const Glib::ustring description=""); void sp_selected_path_do_offset(SPDesktop *desktop, bool expand, double prefOffset); void sp_selected_path_create_offset_object(SPDesktop *desktop, int expand, bool updating); void -sp_selected_path_union(SPDesktop *desktop) +sp_selected_path_union(Inkscape::Selection *selection, SPDesktop *desktop) { - sp_selected_path_boolop(desktop, bool_op_union, SP_VERB_SELECTION_UNION, _("Union")); + sp_selected_path_boolop(selection, desktop, bool_op_union, SP_VERB_SELECTION_UNION, _("Union")); } void -sp_selected_path_union_skip_undo(SPDesktop *desktop) +sp_selected_path_union_skip_undo(Inkscape::Selection *selection, SPDesktop *desktop) { - sp_selected_path_boolop(desktop, bool_op_union, SP_VERB_NONE, _("Union")); + sp_selected_path_boolop(selection, desktop, bool_op_union, SP_VERB_NONE, _("Union")); } void -sp_selected_path_intersect(SPDesktop *desktop) +sp_selected_path_intersect(Inkscape::Selection *selection, SPDesktop *desktop) { - sp_selected_path_boolop(desktop, bool_op_inters, SP_VERB_SELECTION_INTERSECT, _("Intersection")); + sp_selected_path_boolop(selection, desktop, bool_op_inters, SP_VERB_SELECTION_INTERSECT, _("Intersection")); } void -sp_selected_path_diff(SPDesktop *desktop) +sp_selected_path_diff(Inkscape::Selection *selection, SPDesktop *desktop) { - sp_selected_path_boolop(desktop, bool_op_diff, SP_VERB_SELECTION_DIFF, _("Difference")); + sp_selected_path_boolop(selection, desktop, bool_op_diff, SP_VERB_SELECTION_DIFF, _("Difference")); } void -sp_selected_path_diff_skip_undo(SPDesktop *desktop) +sp_selected_path_diff_skip_undo(Inkscape::Selection *selection, SPDesktop *desktop) { - sp_selected_path_boolop(desktop, bool_op_diff, SP_VERB_NONE, _("Difference")); + sp_selected_path_boolop(selection, desktop, bool_op_diff, SP_VERB_NONE, _("Difference")); } void -sp_selected_path_symdiff(SPDesktop *desktop) +sp_selected_path_symdiff(Inkscape::Selection *selection, SPDesktop *desktop) { - sp_selected_path_boolop(desktop, bool_op_symdiff, SP_VERB_SELECTION_SYMDIFF, _("Exclusion")); + sp_selected_path_boolop(selection, desktop, bool_op_symdiff, SP_VERB_SELECTION_SYMDIFF, _("Exclusion")); } void -sp_selected_path_cut(SPDesktop *desktop) +sp_selected_path_cut(Inkscape::Selection *selection, SPDesktop *desktop) { - sp_selected_path_boolop(desktop, bool_op_cut, SP_VERB_SELECTION_CUT, _("Division")); + sp_selected_path_boolop(selection, desktop, bool_op_cut, SP_VERB_SELECTION_CUT, _("Division")); } void -sp_selected_path_slice(SPDesktop *desktop) +sp_selected_path_slice(Inkscape::Selection *selection, SPDesktop *desktop) { - sp_selected_path_boolop(desktop, bool_op_slice, SP_VERB_SELECTION_SLICE, _("Cut path")); + sp_selected_path_boolop(selection, desktop, bool_op_slice, SP_VERB_SELECTION_SLICE, _("Cut path")); } +// helper for printing error messages, regardless of whether we have a GUI or not +// If desktop == NULL, errors will be shown on stderr +static void +boolop_display_error_message(SPDesktop *desktop, Glib::ustring const &msg) +{ + if (desktop) { + desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, msg); + } else { + g_printerr("%s\n", msg.c_str()); + } +} // boolean operations // take the source paths from the file, do the operation, delete the originals and add the results void -sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb, const Glib::ustring description) +sp_selected_path_boolop(Inkscape::Selection *selection, SPDesktop *desktop, bool_op bop, const unsigned int verb, const Glib::ustring description) { - Inkscape::Selection *selection = sp_desktop_selection(desktop); - + SPDocument *doc = selection->layerModel()->getDocument(); GSList *il = (GSList *) selection->itemList(); // allow union on a single object for the purpose of removing self overlapse (svn log, revision 13334) if ( (g_slist_length(il) < 2) && (bop != bool_op_union)) { - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Select <b>at least 2 paths</b> to perform a boolean operation.")); + boolop_display_error_message(desktop, _("Select <b>at least 2 paths</b> to perform a boolean operation.")); return; } else if ( g_slist_length(il) < 1 ) { - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Select <b>at least 1 path</b> to perform a boolean union.")); + boolop_display_error_message(desktop, _("Select <b>at least 1 path</b> to perform a boolean union.")); return; } if (g_slist_length(il) > 2) { if (bop == bool_op_diff || bop == bool_op_cut || bop == bool_op_slice ) { - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Select <b>exactly 2 paths</b> to perform difference, division, or path cut.")); + boolop_display_error_message(desktop, _("Select <b>exactly 2 paths</b> to perform difference, division, or path cut.")); return; } } @@ -146,7 +157,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb Inkscape::XML::Node *b = reinterpret_cast<SPObject *>(il->next->data)->getRepr(); if (a == NULL || b == NULL) { - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Unable to determine the <b>z-order</b> of the objects selected for difference, XOR, division, or path cut.")); + boolop_display_error_message(desktop, _("Unable to determine the <b>z-order</b> of the objects selected for difference, XOR, division, or path cut.")); return; } @@ -161,7 +172,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb // find their lowest common ancestor Inkscape::XML::Node *dad = LCA(a, b); if (dad == NULL) { - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Unable to determine the <b>z-order</b> of the objects selected for difference, XOR, division, or path cut.")); + boolop_display_error_message(desktop, _("Unable to determine the <b>z-order</b> of the objects selected for difference, XOR, division, or path cut.")); return; } @@ -191,7 +202,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb SPItem *item = SP_ITEM(l->data); if (!SP_IS_SHAPE(item) && !SP_IS_TEXT(item) && !SP_IS_FLOWTEXT(item)) { - desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("One of the objects is <b>not a path</b>, cannot perform boolean operation.")); + boolop_display_error_message(desktop, _("One of the objects is <b>not a path</b>, cannot perform boolean operation.")); g_slist_free(il); return; } @@ -432,8 +443,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb { SP_OBJECT(l->data)->deleteObject(); } - DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_NONE, - description); + DocumentUndo::done(doc, SP_VERB_NONE, description); selection->clear(); delete res; @@ -455,8 +465,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb sorted = g_slist_sort(sorted, (GCompareFunc) sp_repr_compare_position); - source = sp_desktop_document(desktop)-> - getObjectByRepr((Inkscape::XML::Node *)sorted->data); + source = doc->getObjectByRepr((Inkscape::XML::Node *)sorted->data); g_slist_free(sorted); } @@ -496,7 +505,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb g_slist_free(il); // premultiply by the inverse of parent's repr - SPItem *parent_item = SP_ITEM(sp_desktop_document(desktop)->getObjectByRepr(parent)); + SPItem *parent_item = SP_ITEM(doc->getObjectByRepr(parent)); Geom::Affine local (parent_item->i2doc_affine()); gchar *transform = sp_svg_transform_write(local.inverse()); @@ -526,7 +535,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb for (int i=0;i<nbRP;i++) { gchar *d = resPath[i]->svg_dump_path(); - Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); + Inkscape::XML::Document *xml_doc = doc->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); repr->setAttribute("style", style); if (mask) @@ -572,7 +581,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb } else { gchar *d = res->svg_dump_path(); - Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); + Inkscape::XML::Document *xml_doc = doc->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); repr->setAttribute("style", style); @@ -590,10 +599,10 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb repr->setAttribute("id", id); parent->appendChild(repr); if (title) { - sp_desktop_document(desktop)->getObjectByRepr(repr)->setTitle(title); + doc->getObjectByRepr(repr)->setTitle(title); } if (desc) { - sp_desktop_document(desktop)->getObjectByRepr(repr)->setDesc(desc); + doc->getObjectByRepr(repr)->setDesc(desc); } repr->setPosition(pos > 0 ? pos : 0); @@ -606,7 +615,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb if (desc) g_free(desc); if (verb != SP_VERB_NONE) { - DocumentUndo::done(sp_desktop_document(desktop), verb, description); + DocumentUndo::done(doc, verb, description); } delete res; diff --git a/src/splivarot.h b/src/splivarot.h index 3d2a1ee58..0cefed3c2 100644 --- a/src/splivarot.h +++ b/src/splivarot.h @@ -11,19 +11,28 @@ #include <2geom/forward.h> #include <2geom/path.h> class SPCurve; +class SPDesktop; class SPItem; +namespace Inkscape { + class Selection; +} + // boolean operations // work on the current selection // selection has 2 contain exactly 2 items -void sp_selected_path_union (SPDesktop *desktop); -void sp_selected_path_union_skip_undo (SPDesktop *desktop); -void sp_selected_path_intersect (SPDesktop *desktop); -void sp_selected_path_diff (SPDesktop *desktop); -void sp_selected_path_diff_skip_undo (SPDesktop *desktop); -void sp_selected_path_symdiff (SPDesktop *desktop); -void sp_selected_path_cut (SPDesktop *desktop); -void sp_selected_path_slice (SPDesktop *desktop); + +// UPDATE: these signatures have been modified so they may work in +// command-line mode, i.e. without a desktop. If a desktop is not +// provided (desktop == NULL), error messages will be shown on stderr. +void sp_selected_path_union (Inkscape::Selection *selection, SPDesktop *desktop); +void sp_selected_path_union_skip_undo (Inkscape::Selection *selection, SPDesktop *desktop); +void sp_selected_path_intersect (Inkscape::Selection *selection, SPDesktop *desktop); +void sp_selected_path_diff (Inkscape::Selection *selection, SPDesktop *desktop); +void sp_selected_path_diff_skip_undo (Inkscape::Selection *selection, SPDesktop *desktop); +void sp_selected_path_symdiff (Inkscape::Selection *selection, SPDesktop *desktop); +void sp_selected_path_cut (Inkscape::Selection *selection, SPDesktop *desktop); +void sp_selected_path_slice (Inkscape::Selection *selection, SPDesktop *desktop); // offset/inset of a curve // takes the fill-rule in consideration diff --git a/src/spray-context.cpp b/src/spray-context.cpp index b8172fa4c..7690d0373 100644 --- a/src/spray-context.cpp +++ b/src/spray-context.cpp @@ -505,7 +505,7 @@ static bool sp_spray_recursive(SPDesktop *desktop, selection->clear(); selection->add(item_copied); selection->add(unionResult); - sp_selected_path_union_skip_undo(selection->desktop()); + sp_selected_path_union_skip_undo(selection, selection->desktop()); selection->add(father); Inkscape::GC::release(copy2); did = true; diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp index 5cc9578f1..32d85574d 100644 --- a/src/ui/dialog/layers.cpp +++ b/src/ui/dialog/layers.cpp @@ -27,6 +27,7 @@ #include "document.h" #include "document-undo.h" #include "helper/action.h" +#include "helper/action-context.h" #include "inkscape.h" #include "layer-fns.h" #include "layer-manager.h" @@ -99,7 +100,7 @@ void LayersPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned i if ( desktop ) { Verb *verb = Verb::get( code ); if ( verb ) { - SPAction *action = verb->get_action(desktop); + SPAction *action = verb->get_action(Inkscape::ActionContext(desktop)); if ( !set && action && action->image ) { GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image ); gtk_widget_show( child ); @@ -131,7 +132,7 @@ Gtk::MenuItem& LayersPanel::_addPopupItem( SPDesktop *desktop, unsigned int code if ( desktop ) { Verb *verb = Verb::get( code ); if ( verb ) { - SPAction *action = verb->get_action(desktop); + SPAction *action = verb->get_action(Inkscape::ActionContext(desktop)); if ( !iconWidget && action && action->image ) { iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image ); } @@ -172,7 +173,7 @@ void LayersPanel::_fireAction( unsigned int code ) if ( _desktop ) { Verb *verb = Verb::get( code ); if ( verb ) { - SPAction *action = verb->get_action(_desktop); + SPAction *action = verb->get_action(Inkscape::ActionContext(_desktop)); if ( action ) { sp_action_perform( action, NULL ); // } else { diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 90cb1cdc9..094a6fa6a 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -57,6 +57,7 @@ #include "verbs.h" #include "gradient-chemistry.h" #include "helper/action.h" +#include "helper/action-context.h" namespace Inkscape { namespace UI { @@ -154,7 +155,7 @@ static void editGradientImpl( SPDesktop* desktop, SPGradient* gr ) // Invoke the gradient tool Inkscape::Verb *verb = Inkscape::Verb::get( SP_VERB_CONTEXT_GRADIENT ); if ( verb ) { - SPAction *action = verb->get_action( ( Inkscape::UI::View::View * ) SP_ACTIVE_DESKTOP); + SPAction *action = verb->get_action( Inkscape::ActionContext( ( Inkscape::UI::View::View * ) SP_ACTIVE_DESKTOP ) ); if ( action ) { sp_action_perform( action, NULL ); } diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp index 5eb7084d6..09bf1a863 100644 --- a/src/ui/dialog/symbols.cpp +++ b/src/ui/dialog/symbols.cpp @@ -66,6 +66,7 @@ #include "verbs.h" #include "helper/action.h" +#include "helper/action-context.h" #include "xml/repr.h" namespace Inkscape { @@ -328,13 +329,13 @@ void SymbolsDialog::rebuild() { void SymbolsDialog::insertSymbol() { Inkscape::Verb *verb = Inkscape::Verb::get( SP_VERB_EDIT_SYMBOL ); - SPAction *action = verb->get_action((Inkscape::UI::View::View *) this->currentDesktop); + SPAction *action = verb->get_action(Inkscape::ActionContext( (Inkscape::UI::View::View *) this->currentDesktop) ); sp_action_perform (action, NULL); } void SymbolsDialog::revertSymbol() { Inkscape::Verb *verb = Inkscape::Verb::get( SP_VERB_EDIT_UNSYMBOL ); - SPAction *action = verb->get_action((Inkscape::UI::View::View *) this->currentDesktop); + SPAction *action = verb->get_action(Inkscape::ActionContext( (Inkscape::UI::View::View *) this->currentDesktop ) ); sp_action_perform (action, NULL); } diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp index fa3f8e3a1..988c4e5de 100644 --- a/src/ui/widget/page-sizer.cpp +++ b/src/ui/widget/page-sizer.cpp @@ -36,6 +36,7 @@ #include "document.h" #include "desktop.h" #include "helper/action.h" +#include "helper/action-context.h" #include "helper/units.h" #include "inkscape.h" #include "sp-namedview.h" @@ -619,7 +620,7 @@ PageSizer::fire_fit_canvas_to_selection_or_drawing() Verb *verb = Verb::get( SP_VERB_FIT_CANVAS_TO_SELECTION_OR_DRAWING ); if (verb) { - SPAction *action = verb->get_action(dt); + SPAction *action = verb->get_action(Inkscape::ActionContext(dt)); if (action) { sp_action_perform(action, NULL); } diff --git a/src/ui/widget/style-swatch.cpp b/src/ui/widget/style-swatch.cpp index a89f42575..aedab3fa5 100644 --- a/src/ui/widget/style-swatch.cpp +++ b/src/ui/widget/style-swatch.cpp @@ -28,6 +28,7 @@ #include "widgets/widget-sizes.h" #include "helper/units.h" #include "helper/action.h" +#include "helper/action-context.h" #include "preferences.h" #include "inkscape.h" #include "verbs.h" @@ -200,7 +201,7 @@ StyleSwatch::on_click(GdkEventButton */*event*/) { if (this->_desktop && this->_verb_t != SP_VERB_NONE) { Inkscape::Verb *verb = Inkscape::Verb::get(this->_verb_t); - SPAction *action = verb->get_action((Inkscape::UI::View::View *) this->_desktop); + SPAction *action = verb->get_action(Inkscape::ActionContext((Inkscape::UI::View::View *) this->_desktop)); sp_action_perform (action, NULL); return true; } diff --git a/src/verbs.cpp b/src/verbs.cpp index 6f83b3dfb..4bbd3f9df 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -50,6 +50,7 @@ #include "file.h" #include "gradient-drag.h" #include "helper/action.h" +#include "helper/action-context.h" #include "help.h" #include "inkscape-private.h" #include "interface.h" @@ -124,7 +125,7 @@ class FileVerb : public Verb { private: static void perform(SPAction *action, void *mydata); protected: - virtual SPAction *make_action(Inkscape::UI::View::View *view); + virtual SPAction *make_action(Inkscape::ActionContext const & context); public: /** Use the Verb initializer with the same parameters. */ FileVerb(unsigned int const code, @@ -143,7 +144,7 @@ class EditVerb : public Verb { private: static void perform(SPAction *action, void *mydata); protected: - virtual SPAction *make_action(Inkscape::UI::View::View *view); + virtual SPAction *make_action(Inkscape::ActionContext const & context); public: /** Use the Verb initializer with the same parameters. */ EditVerb(unsigned int const code, @@ -162,7 +163,7 @@ class SelectionVerb : public Verb { private: static void perform(SPAction *action, void *mydata); protected: - virtual SPAction *make_action(Inkscape::UI::View::View *view); + virtual SPAction *make_action(Inkscape::ActionContext const & context); public: /** Use the Verb initializer with the same parameters. */ SelectionVerb(unsigned int const code, @@ -181,7 +182,7 @@ class LayerVerb : public Verb { private: static void perform(SPAction *action, void *mydata); protected: - virtual SPAction *make_action(Inkscape::UI::View::View *view); + virtual SPAction *make_action(Inkscape::ActionContext const & context); public: /** Use the Verb initializer with the same parameters. */ LayerVerb(unsigned int const code, @@ -200,7 +201,7 @@ class ObjectVerb : public Verb { private: static void perform(SPAction *action, void *mydata); protected: - virtual SPAction *make_action(Inkscape::UI::View::View *view); + virtual SPAction *make_action(Inkscape::ActionContext const & context); public: /** Use the Verb initializer with the same parameters. */ ObjectVerb(unsigned int const code, @@ -219,7 +220,7 @@ class ContextVerb : public Verb { private: static void perform(SPAction *action, void *mydata); protected: - virtual SPAction *make_action(Inkscape::UI::View::View *view); + virtual SPAction *make_action(Inkscape::ActionContext const & context); public: /** Use the Verb initializer with the same parameters. */ ContextVerb(unsigned int const code, @@ -238,7 +239,7 @@ class ZoomVerb : public Verb { private: static void perform(SPAction *action, void *mydata); protected: - virtual SPAction *make_action(Inkscape::UI::View::View *view); + virtual SPAction *make_action(Inkscape::ActionContext const & context); public: /** Use the Verb initializer with the same parameters. */ ZoomVerb(unsigned int const code, @@ -258,7 +259,7 @@ class DialogVerb : public Verb { private: static void perform(SPAction *action, void *mydata); protected: - virtual SPAction *make_action(Inkscape::UI::View::View *view); + virtual SPAction *make_action(Inkscape::ActionContext const & context); public: /** Use the Verb initializer with the same parameters. */ DialogVerb(unsigned int const code, @@ -277,7 +278,7 @@ class HelpVerb : public Verb { private: static void perform(SPAction *action, void *mydata); protected: - virtual SPAction *make_action(Inkscape::UI::View::View *view); + virtual SPAction *make_action(Inkscape::ActionContext const & context); public: /** Use the Verb initializer with the same parameters. */ HelpVerb(unsigned int const code, @@ -296,7 +297,7 @@ class TutorialVerb : public Verb { private: static void perform(SPAction *action, void *mydata); protected: - virtual SPAction *make_action(Inkscape::UI::View::View *view); + virtual SPAction *make_action(Inkscape::ActionContext const & context); public: /** Use the Verb initializer with the same parameters. */ TutorialVerb(unsigned int const code, @@ -315,7 +316,7 @@ class TextVerb : public Verb { private: static void perform(SPAction *action, void *mydata); protected: - virtual SPAction *make_action(Inkscape::UI::View::View *view); + virtual SPAction *make_action(Inkscape::ActionContext const & context); public: /** Use the Verb initializer with the same parameters. */ TextVerb(unsigned int const code, @@ -382,10 +383,10 @@ Verb::~Verb(void) * for a function that every subclass should write. Most * can be written using \c make_action_helper. * - * @param view Which view the action should be created for. + * @param context Which context the action should be created for. * @return NULL to represent error (this function shouldn't ever be called) */ -SPAction *Verb::make_action(Inkscape::UI::View::View */*view*/) +SPAction *Verb::make_action(Inkscape::ActionContext const & /*context*/) { //std::cout << "make_action" << std::endl; return NULL; @@ -395,13 +396,13 @@ SPAction *Verb::make_action(Inkscape::UI::View::View */*view*/) * Create an action for a \c FileVerb. * Calls \c make_action_helper with the \c vector. * - * @param view Which view the action should be created for. + * @param context Which context the action should be created for. * @return The built action. */ -SPAction *FileVerb::make_action(Inkscape::UI::View::View *view) +SPAction *FileVerb::make_action(Inkscape::ActionContext const & context) { //std::cout << "fileverb: make_action: " << &perform << std::endl; - return make_action_helper(view, &perform); + return make_action_helper(context, &perform); } /** @@ -409,13 +410,13 @@ SPAction *FileVerb::make_action(Inkscape::UI::View::View *view) * * Calls \c make_action_helper with the \c vector. * - * @param view Which view the action should be created for. + * @param context Which context the action should be created for. * @return The built action. */ -SPAction *EditVerb::make_action(Inkscape::UI::View::View *view) +SPAction *EditVerb::make_action(Inkscape::ActionContext const & context) { //std::cout << "editverb: make_action: " << &perform << std::endl; - return make_action_helper(view, &perform); + return make_action_helper(context, &perform); } /** @@ -423,12 +424,12 @@ SPAction *EditVerb::make_action(Inkscape::UI::View::View *view) * * Calls \c make_action_helper with the \c vector. * - * @param view Which view the action should be created for. + * @param context Which context the action should be created for. * @return The built action. */ -SPAction *SelectionVerb::make_action(Inkscape::UI::View::View *view) +SPAction *SelectionVerb::make_action(Inkscape::ActionContext const & context) { - return make_action_helper(view, &perform); + return make_action_helper(context, &perform); } /** @@ -436,12 +437,12 @@ SPAction *SelectionVerb::make_action(Inkscape::UI::View::View *view) * * Calls \c make_action_helper with the \c vector. * - * @param view Which view the action should be created for. + * @param context Which context the action should be created for. * @return The built action. */ -SPAction *LayerVerb::make_action(Inkscape::UI::View::View *view) +SPAction *LayerVerb::make_action(Inkscape::ActionContext const & context) { - return make_action_helper(view, &perform); + return make_action_helper(context, &perform); } /** @@ -449,12 +450,12 @@ SPAction *LayerVerb::make_action(Inkscape::UI::View::View *view) * * Calls \c make_action_helper with the \c vector. * - * @param view Which view the action should be created for. + * @param context Which context the action should be created for. * @return The built action. */ -SPAction *ObjectVerb::make_action(Inkscape::UI::View::View *view) +SPAction *ObjectVerb::make_action(Inkscape::ActionContext const & context) { - return make_action_helper(view, &perform); + return make_action_helper(context, &perform); } /** @@ -462,12 +463,12 @@ SPAction *ObjectVerb::make_action(Inkscape::UI::View::View *view) * * Calls \c make_action_helper with the \c vector. * - * @param view Which view the action should be created for. + * @param context Which context the action should be created for. * @return The built action. */ -SPAction *ContextVerb::make_action(Inkscape::UI::View::View *view) +SPAction *ContextVerb::make_action(Inkscape::ActionContext const & context) { - return make_action_helper(view, &perform); + return make_action_helper(context, &perform); } /** @@ -475,12 +476,12 @@ SPAction *ContextVerb::make_action(Inkscape::UI::View::View *view) * * Calls \c make_action_helper with the \c vector. * - * @param view Which view the action should be created for. + * @param context Which context the action should be created for. * @return The built action. */ -SPAction *ZoomVerb::make_action(Inkscape::UI::View::View *view) +SPAction *ZoomVerb::make_action(Inkscape::ActionContext const & context) { - return make_action_helper(view, &perform); + return make_action_helper(context, &perform); } /** @@ -488,12 +489,12 @@ SPAction *ZoomVerb::make_action(Inkscape::UI::View::View *view) * * Calls \c make_action_helper with the \c vector. * - * @param view Which view the action should be created for. + * @param context Which context the action should be created for. * @return The built action. */ -SPAction *DialogVerb::make_action(Inkscape::UI::View::View *view) +SPAction *DialogVerb::make_action(Inkscape::ActionContext const & context) { - return make_action_helper(view, &perform); + return make_action_helper(context, &perform); } /** @@ -501,12 +502,12 @@ SPAction *DialogVerb::make_action(Inkscape::UI::View::View *view) * * Calls \c make_action_helper with the \c vector. * - * @param view Which view the action should be created for. + * @param context Which context the action should be created for. * @return The built action. */ -SPAction *HelpVerb::make_action(Inkscape::UI::View::View *view) +SPAction *HelpVerb::make_action(Inkscape::ActionContext const & context) { - return make_action_helper(view, &perform); + return make_action_helper(context, &perform); } /** @@ -514,12 +515,12 @@ SPAction *HelpVerb::make_action(Inkscape::UI::View::View *view) * * Calls \c make_action_helper with the \c vector. * - * @param view Which view the action should be created for. + * @param context Which context the action should be created for. * @return The built action. */ -SPAction *TutorialVerb::make_action(Inkscape::UI::View::View *view) +SPAction *TutorialVerb::make_action(Inkscape::ActionContext const & context) { - return make_action_helper(view, &perform); + return make_action_helper(context, &perform); } /** @@ -527,12 +528,12 @@ SPAction *TutorialVerb::make_action(Inkscape::UI::View::View *view) * * Calls \c make_action_helper with the \c vector. * - * @param view Which view the action should be created for. + * @param context Which context the action should be created for. * @return The built action. */ -SPAction *TextVerb::make_action(Inkscape::UI::View::View *view) +SPAction *TextVerb::make_action(Inkscape::ActionContext const & context) { - return make_action_helper(view, &perform); + return make_action_helper(context, &perform); } /** @@ -546,16 +547,16 @@ SPAction *TextVerb::make_action(Inkscape::UI::View::View *view) * if the action gets crated, a listener is added to the action with * the vector that is passed in. * - * @param view Which view the action should be created for. + * @param context Which context the action should be created for. * @param vector The function vector for the verb. * @return The created action. */ -SPAction *Verb::make_action_helper(Inkscape::UI::View::View *view, void (*perform_fun)(SPAction *, void *), void *in_pntr) +SPAction *Verb::make_action_helper(Inkscape::ActionContext const & context, void (*perform_fun)(SPAction *, void *), void *in_pntr) { SPAction *action; //std::cout << "Adding action: " << _code << std::endl; - action = sp_action_new(view, _id, _(_name), + action = sp_action_new(context, _id, _(_name), _(_tip), _image, this); if (action == NULL) return NULL; @@ -587,22 +588,22 @@ SPAction *Verb::make_action_helper(Inkscape::UI::View::View *view, void (*perfor * looked for, and the sensitivity is matched. Unfortunately, this is * currently a linear search. * - * @param view The view which this action would relate to. + * @param context The action context which this action relates to. * @return The action, or NULL if there is an error. */ -SPAction *Verb::get_action(Inkscape::UI::View::View *view) +SPAction *Verb::get_action(Inkscape::ActionContext const & context) { SPAction *action = NULL; if ( _actions == NULL ) { _actions = new ActionTable; } - ActionTable::iterator action_found = _actions->find(view); + ActionTable::iterator action_found = _actions->find(context.getView()); if (action_found != _actions->end()) { action = action_found->second; } else { - action = this->make_action(view); + action = this->make_action(context); // if (action == NULL) printf("Hmm, NULL in %s\n", _name); if (action == NULL) printf("Hmm, NULL in %s\n", _name); @@ -610,16 +611,16 @@ SPAction *Verb::get_action(Inkscape::UI::View::View *view) sp_action_set_sensitive(action, 0); } else { for (ActionTable::iterator cur_action = _actions->begin(); - cur_action != _actions->end() && view != NULL; + cur_action != _actions->end() && context.getView() != NULL; ++cur_action) { - if (cur_action->first != NULL && cur_action->first->doc() == view->doc()) { + if (cur_action->first != NULL && cur_action->first->doc() == context.getDocument()) { sp_action_set_sensitive(action, cur_action->second->sensitive); break; } } } - _actions->insert(ActionTable::value_type(view, action)); + _actions->insert(ActionTable::value_type(context.getView(), action)); } return action; @@ -802,8 +803,7 @@ void FileVerb::perform(SPAction *action, void *data) #if 0 // These aren't used, but are here to remind people not to use // the CURRENT_DOCUMENT macros unless they really have to. - Inkscape::UI::View::View *current_view = sp_action_get_view(action); - SPDocument *current_document = current_view->doc(); + SPDocument *current_document = sp_action_get_document(action); #endif SPDesktop *desktop = dynamic_cast<SPDesktop*>(sp_action_get_view(action)); @@ -1028,8 +1028,39 @@ void EditVerb::perform(SPAction *action, void *data) */ void SelectionVerb::perform(SPAction *action, void *data) { + Inkscape::Selection *selection = sp_action_get_selection(action); SPDesktop *dt = static_cast<SPDesktop*>(sp_action_get_view(action)); + // Some of these operations have been modified so they work in command-line mode! + // In this case, all we need is a selection + if (!selection) { + return; + } + + switch (reinterpret_cast<std::size_t>(data)) { + case SP_VERB_SELECTION_UNION: + sp_selected_path_union(selection, dt); + break; + case SP_VERB_SELECTION_INTERSECT: + sp_selected_path_intersect(selection, dt); + break; + case SP_VERB_SELECTION_DIFF: + sp_selected_path_diff(selection, dt); + break; + case SP_VERB_SELECTION_SYMDIFF: + sp_selected_path_symdiff(selection, dt); + break; + case SP_VERB_SELECTION_CUT: + sp_selected_path_cut(selection, dt); + break; + case SP_VERB_SELECTION_SLICE: + sp_selected_path_slice(selection, dt); + break; + default: + break; + } + + // The remaining operations require a desktop if (!dt) return; @@ -1065,26 +1096,6 @@ void SelectionVerb::perform(SPAction *action, void *data) text_remove_all_kerns(); break; - case SP_VERB_SELECTION_UNION: - sp_selected_path_union(dt); - break; - case SP_VERB_SELECTION_INTERSECT: - sp_selected_path_intersect(dt); - break; - case SP_VERB_SELECTION_DIFF: - sp_selected_path_diff(dt); - break; - case SP_VERB_SELECTION_SYMDIFF: - sp_selected_path_symdiff(dt); - break; - - case SP_VERB_SELECTION_CUT: - sp_selected_path_cut(dt); - break; - case SP_VERB_SELECTION_SLICE: - sp_selected_path_slice(dt); - break; - case SP_VERB_SELECTION_OFFSET: sp_selected_path_offset(dt); break; @@ -1500,7 +1511,7 @@ void ContextVerb::perform(SPAction *action, void *data) */ for (vidx = SP_VERB_CONTEXT_SELECT; vidx <= SP_VERB_CONTEXT_PAINTBUCKET_PREFS; vidx++) { - SPAction *tool_action= get((sp_verb_t)vidx)->get_action(dt); + SPAction *tool_action= get((sp_verb_t)vidx)->get_action(action->context); if (tool_action) { sp_action_set_active(tool_action, vidx == (int)verb); } @@ -2090,7 +2101,7 @@ class EffectLastVerb : public Verb { private: static void perform(SPAction *action, void *mydata); protected: - virtual SPAction *make_action(Inkscape::UI::View::View *view); + virtual SPAction *make_action(Inkscape::ActionContext const & context); public: /** Use the Verb initializer with the same parameters. */ EffectLastVerb(unsigned int const code, @@ -2109,12 +2120,12 @@ public: * * Calls \c make_action_helper with the \c vector. * - * @param view Which view the action should be created for. + * @param context Which context the action should be created for. * @return The built action. */ -SPAction *EffectLastVerb::make_action(Inkscape::UI::View::View *view) +SPAction *EffectLastVerb::make_action(Inkscape::ActionContext const & context) { - return make_action_helper(view, &perform); + return make_action_helper(context, &perform); } /** @@ -2155,7 +2166,7 @@ class FitCanvasVerb : public Verb { private: static void perform(SPAction *action, void *mydata); protected: - virtual SPAction *make_action(Inkscape::UI::View::View *view); + virtual SPAction *make_action(Inkscape::ActionContext const & context); public: /** Use the Verb initializer with the same parameters. */ FitCanvasVerb(unsigned int const code, @@ -2174,12 +2185,12 @@ public: * * Calls \c make_action_helper with the \c vector. * - * @param view Which view the action should be created for. + * @param context Which context the action should be created for. * @return The built action. */ -SPAction *FitCanvasVerb::make_action(Inkscape::UI::View::View *view) +SPAction *FitCanvasVerb::make_action(Inkscape::ActionContext const & context) { - SPAction *action = make_action_helper(view, &perform); + SPAction *action = make_action_helper(context, &perform); return action; } @@ -2221,7 +2232,7 @@ class LockAndHideVerb : public Verb { private: static void perform(SPAction *action, void *mydata); protected: - virtual SPAction *make_action(Inkscape::UI::View::View *view); + virtual SPAction *make_action(Inkscape::ActionContext const & context); public: /** Use the Verb initializer with the same parameters. */ LockAndHideVerb(unsigned int const code, @@ -2240,12 +2251,12 @@ public: * * Calls \c make_action_helper with the \c vector. * - * @param view Which view the action should be created for. + * @param context Which context the action should be created for. * @return The built action. */ -SPAction *LockAndHideVerb::make_action(Inkscape::UI::View::View *view) +SPAction *LockAndHideVerb::make_action(Inkscape::ActionContext const & context) { - SPAction *action = make_action_helper(view, &perform); + SPAction *action = make_action_helper(context, &perform); return action; } diff --git a/src/verbs.h b/src/verbs.h index dab524d7a..35165822a 100644 --- a/src/verbs.h +++ b/src/verbs.h @@ -23,6 +23,9 @@ struct SPAction; class SPDocument; namespace Inkscape { + +class ActionContext; + namespace UI { namespace View { class View; @@ -472,8 +475,8 @@ public: protected: - SPAction *make_action_helper (Inkscape::UI::View::View *view, void (*perform_fun)(SPAction *, void *), void *in_pntr = NULL); - virtual SPAction *make_action (Inkscape::UI::View::View *view); + SPAction *make_action_helper (Inkscape::ActionContext const & context, void (*perform_fun)(SPAction *, void *), void *in_pntr = NULL); + virtual SPAction *make_action (Inkscape::ActionContext const & context); public: @@ -521,7 +524,7 @@ public: Verb (gchar const * id, gchar const * name, gchar const * tip, gchar const * image, gchar const * group); virtual ~Verb (void); - SPAction * get_action(Inkscape::UI::View::View * view); + SPAction * get_action(Inkscape::ActionContext const & context); private: static Verb * get_search (unsigned int code); diff --git a/src/widgets/button.cpp b/src/widgets/button.cpp index 467f0d70e..a1bd9b792 100644 --- a/src/widgets/button.cpp +++ b/src/widgets/button.cpp @@ -20,6 +20,7 @@ #include "icon.h" #include "shortcuts.h" #include "interface.h" +#include "helper/action-context.h" #include <gdk/gdkkeysyms.h> @@ -309,7 +310,7 @@ sp_button_new_from_data( Inkscape::IconSize size, const gchar *tip ) { GtkWidget *button; - SPAction *action=sp_action_new(view, name, name, tip, name, 0); + SPAction *action=sp_action_new(Inkscape::ActionContext(view), name, name, tip, name, 0); button = sp_button_new (size, type, action, NULL); g_object_unref(action); return button; diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index 814298041..c1214c1a4 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -41,6 +41,8 @@ #include "ege-select-one-action.h" #include <extension/db.h> #include "file.h" +#include "helper/action.h" +#include "helper/action-context.h" #include "helper/units.h" #include "helper/unit-tracker.h" #include "inkscape-private.h" @@ -485,7 +487,7 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) gchar const* tip = ""; Inkscape::Verb* verb = Inkscape::Verb::get( SP_VERB_VIEW_CMS_TOGGLE ); if ( verb ) { - SPAction *act = verb->get_action( dtw->viewwidget.view ); + SPAction *act = verb->get_action( Inkscape::ActionContext( dtw->viewwidget.view ) ); if ( act && act->tip ) { tip = act->tip; } @@ -1060,7 +1062,7 @@ void cms_adjust_set_sensitive( SPDesktopWidget *dtw, bool enabled ) { Inkscape::Verb* verb = Inkscape::Verb::get( SP_VERB_VIEW_CMS_TOGGLE ); if ( verb ) { - SPAction *act = verb->get_action( dtw->viewwidget.view ); + SPAction *act = verb->get_action( Inkscape::ActionContext( dtw->viewwidget.view ) ); if ( act ) { sp_action_set_sensitive( act, enabled ); } diff --git a/src/widgets/gradient-selector.cpp b/src/widgets/gradient-selector.cpp index 7a7f0d8ff..5ac994509 100644 --- a/src/widgets/gradient-selector.cpp +++ b/src/widgets/gradient-selector.cpp @@ -26,6 +26,7 @@ #include "inkscape.h" #include "verbs.h" #include "helper/action.h" +#include "helper/action-context.h" #include "preferences.h" #include <glibmm/i18n.h> @@ -535,7 +536,7 @@ sp_gradient_selector_edit_vector_clicked (GtkWidget */*w*/, SPGradientSelector * // Invoke the gradient tool Inkscape::Verb *verb = Inkscape::Verb::get( SP_VERB_CONTEXT_GRADIENT ); if ( verb ) { - SPAction *action = verb->get_action( ( Inkscape::UI::View::View * ) SP_ACTIVE_DESKTOP); + SPAction *action = verb->get_action( Inkscape::ActionContext( ( Inkscape::UI::View::View * ) SP_ACTIVE_DESKTOP ) ); if ( action ) { sp_action_perform( action, NULL ); } diff --git a/src/widgets/lpe-toolbar.cpp b/src/widgets/lpe-toolbar.cpp index 3126175b3..c7659ab42 100644 --- a/src/widgets/lpe-toolbar.cpp +++ b/src/widgets/lpe-toolbar.cpp @@ -55,6 +55,8 @@ #include "../xml/repr.h" #include "ui/uxmanager.h" #include "../ui/icon-names.h" +#include "../helper/action.h" +#include "../helper/action-context.h" #include "../helper/unit-menu.h" #include "../helper/units.h" #include "../helper/unit-tracker.h" @@ -286,7 +288,7 @@ static void lpetool_open_lpe_dialog(GtkToggleAction *act, gpointer data) SPDesktop *desktop = static_cast<SPDesktop *>(data); if (tools_isactive(desktop, TOOLS_LPETOOL)) { - sp_action_perform(Inkscape::Verb::get(SP_VERB_DIALOG_LIVE_PATH_EFFECT)->get_action(desktop), NULL); + sp_action_perform(Inkscape::Verb::get(SP_VERB_DIALOG_LIVE_PATH_EFFECT)->get_action(Inkscape::ActionContext(desktop)), NULL); } gtk_toggle_action_set_active(act, false); } diff --git a/src/widgets/select-toolbar.cpp b/src/widgets/select-toolbar.cpp index 549581610..1bfc841e3 100644 --- a/src/widgets/select-toolbar.cpp +++ b/src/widgets/select-toolbar.cpp @@ -37,6 +37,8 @@ #include "sp-namedview.h" #include "toolbox.h" #include <glibmm/i18n.h> +#include "helper/action.h" +#include "helper/action-context.h" #include "helper/unit-menu.h" #include "helper/units.h" #include "inkscape.h" @@ -413,7 +415,7 @@ static GtkAction* create_action_for_verb( Inkscape::Verb* verb, Inkscape::UI::Vi { GtkAction* act = 0; - SPAction* targetAction = verb->get_action(view); + SPAction* targetAction = verb->get_action(Inkscape::ActionContext(view)); InkAction* inky = ink_action_new( verb->get_id(), verb->get_name(), verb->get_tip(), verb->get_image(), size ); act = GTK_ACTION(inky); diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 0fdf36d5f..ca593976f 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -47,6 +47,8 @@ #include "../ege-output-action.h" #include "../ege-select-one-action.h" #include "../graphlayout.h" +#include "../helper/action.h" +#include "../helper/action-context.h" #include "../helper/unit-menu.h" #include "../helper/units.h" #include "../helper/unit-tracker.h" @@ -591,9 +593,9 @@ private: Glib::RefPtr<VerbAction> VerbAction::create(Inkscape::Verb* verb, Inkscape::Verb* verb2, Inkscape::UI::View::View *view) { Glib::RefPtr<VerbAction> result; - SPAction *action = verb->get_action(view); + SPAction *action = verb->get_action(Inkscape::ActionContext(view)); if ( action ) { - //SPAction* action2 = verb2 ? verb2->get_action(view) : 0; + //SPAction* action2 = verb2 ? verb2->get_action(Inkscape::ActionContext(view)) : 0; result = Glib::RefPtr<VerbAction>(new VerbAction(verb, verb2, view)); } @@ -680,7 +682,7 @@ void VerbAction::set_active(bool active) void VerbAction::on_activate() { if ( verb ) { - SPAction *action = verb->get_action(view); + SPAction *action = verb->get_action(Inkscape::ActionContext(view)); if ( action ) { sp_action_perform(action, 0); } @@ -770,14 +772,14 @@ GtkToolItem * sp_toolbox_button_item_new_from_verb_with_doubleclick(GtkWidget *t Inkscape::Verb *verb, Inkscape::Verb *doubleclick_verb, Inkscape::UI::View::View *view) { - SPAction *action = verb->get_action(view); + SPAction *action = verb->get_action(Inkscape::ActionContext(view)); if (!action) { return NULL; } SPAction *doubleclick_action; if (doubleclick_verb) { - doubleclick_action = doubleclick_verb->get_action(view); + doubleclick_action = doubleclick_verb->get_action(Inkscape::ActionContext(view)); } else { doubleclick_action = NULL; } @@ -822,7 +824,7 @@ static GtkAction* create_action_for_verb( Inkscape::Verb* verb, Inkscape::UI::Vi { GtkAction* act = 0; - SPAction* targetAction = verb->get_action(view); + SPAction* targetAction = verb->get_action(Inkscape::ActionContext(view)); InkAction* inky = ink_action_new( verb->get_id(), _(verb->get_name()), verb->get_tip(), verb->get_image(), size ); act = GTK_ACTION(inky); gtk_action_set_sensitive( act, targetAction->sensitive ); |
