summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/Makefile_insert2
-rw-r--r--src/desktop.cpp180
-rw-r--r--src/desktop.h10
-rw-r--r--src/document.cpp5
-rw-r--r--src/document.h1
-rw-r--r--src/dyna-draw-context.cpp4
-rw-r--r--src/eraser-context.cpp2
-rw-r--r--src/extension/dbus/application-interface.cpp59
-rw-r--r--src/extension/dbus/application-interface.h22
-rw-r--r--src/extension/dbus/application-interface.xml23
-rw-r--r--src/extension/dbus/dbus-init.cpp118
-rw-r--r--src/extension/dbus/dbus-init.h15
-rw-r--r--src/extension/dbus/document-interface.cpp663
-rw-r--r--src/extension/dbus/document-interface.h180
-rw-r--r--src/extension/dbus/document-interface.xml32
-rw-r--r--src/extension/dbus/wrapper/inkscape-dbus-wrapper.c18
-rw-r--r--src/extension/dbus/wrapper/inkscape-dbus-wrapper.h8
-rw-r--r--src/extension/effect.cpp8
-rw-r--r--src/extension/effect.h2
-rw-r--r--src/extension/internal/bluredge.cpp5
-rw-r--r--[-rwxr-xr-x]src/extension/internal/filter/filter-all.cpp0
-rw-r--r--src/file.cpp33
-rw-r--r--src/file.h2
-rw-r--r--src/flood-context.cpp2
-rw-r--r--src/helper/CMakeLists.txt2
-rw-r--r--src/helper/Makefile_insert2
-rw-r--r--src/helper/action-context.cpp84
-rw-r--r--src/helper/action-context.h89
-rw-r--r--src/helper/action.cpp53
-rw-r--r--src/helper/action.h13
-rw-r--r--src/inkscape-private.h2
-rw-r--r--src/inkscape.cpp71
-rw-r--r--src/inkscape.h21
-rw-r--r--src/interface.cpp25
-rw-r--r--src/layer-model.cpp259
-rw-r--r--src/layer-model.h104
-rw-r--r--src/livarot/Shape.cpp8
-rw-r--r--src/livarot/Shape.h12
-rw-r--r--src/livarot/ShapeMisc.cpp12
-rw-r--r--src/livarot/ShapeSweep.cpp8
-rw-r--r--src/main-cmdlineact.cpp24
-rw-r--r--src/main-cmdlineact.h7
-rw-r--r--src/main.cpp75
-rw-r--r--src/pixmaps/handles.xpm178
-rw-r--r--src/select-context.cpp60
-rw-r--r--src/selection-chemistry.cpp131
-rw-r--r--src/selection-chemistry.h18
-rw-r--r--src/selection-describer.cpp5
-rw-r--r--src/selection.cpp45
-rw-r--r--src/selection.h36
-rw-r--r--src/seltrans-handles.cpp53
-rw-r--r--src/seltrans-handles.h46
-rw-r--r--src/seltrans.cpp286
-rw-r--r--src/seltrans.h13
-rw-r--r--src/shortcuts.cpp3
-rw-r--r--src/splivarot.cpp81
-rw-r--r--src/splivarot.h25
-rw-r--r--src/spray-context.cpp2
-rw-r--r--src/ui/dialog/align-and-distribute.cpp190
-rw-r--r--src/ui/dialog/align-and-distribute.h10
-rw-r--r--src/ui/dialog/layers.cpp7
-rw-r--r--src/ui/dialog/swatches.cpp3
-rw-r--r--src/ui/dialog/symbols.cpp5
-rw-r--r--src/ui/tool/transform-handle-set.cpp12
-rw-r--r--src/ui/widget/dock.cpp20
-rw-r--r--src/ui/widget/dock.h10
-rw-r--r--src/ui/widget/page-sizer.cpp3
-rw-r--r--src/ui/widget/style-swatch.cpp3
-rw-r--r--src/util/units.cpp262
-rw-r--r--src/util/units.h55
-rw-r--r--src/verbs.cpp348
-rw-r--r--src/verbs.h14
-rw-r--r--src/widgets/button.cpp3
-rw-r--r--src/widgets/desktop-widget.cpp6
-rw-r--r--src/widgets/gradient-selector.cpp3
-rw-r--r--src/widgets/lpe-toolbar.cpp4
-rw-r--r--src/widgets/select-toolbar.cpp4
-rw-r--r--src/widgets/toolbox.cpp14
79 files changed, 2422 insertions, 1803 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..88f809b52 100644
--- a/src/Makefile_insert
+++ b/src/Makefile_insert
@@ -21,6 +21,7 @@ ink_common_sources += \
color-profile.cpp color-profile.h \
color-profile-cms-fns.h \
color-rgba.h \
+ colorspace.h \
common-context.cpp common-context.h \
composite-undo-stack-observer.cpp \
composite-undo-stack-observer.h \
@@ -92,6 +93,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..ce740f76f 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 ),
+ layers( 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) );
+
+ 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) );
}
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 */
+ layers->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 layers;
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 layers->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 layers->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)
+{
+ layers->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)
+{
+ layers->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)
+{
+ layers->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)
+{
+ layers->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)
+{
+ layers->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 layers->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());
+ layers->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->layers->layerForObject(item);
if ( layer && layer != desktop->currentLayer() ) {
- desktop->setCurrentLayer(layer);
+ desktop->layers->setCurrentLayer(layer);
}
}
}
@@ -1738,9 +1646,9 @@ _layer_hierarchy_changed(SPObject */*top*/, SPObject *bottom,
/// Called when document is starting to be rebuilt.
static void _reconstruction_start(SPDesktop * desktop)
{
- // printf("Desktop, starting reconstruction\n");
+ g_debug("Desktop, starting reconstruction\n");
desktop->_reconstruction_old_layer_id = desktop->currentLayer()->getId() ? desktop->currentLayer()->getId() : "";
- desktop->_layer_hierarchy->setBottom(desktop->currentRoot());
+ desktop->layers->reset();
/*
GSList const * selection_objs = desktop->selection->list();
@@ -1750,22 +1658,22 @@ static void _reconstruction_start(SPDesktop * desktop)
*/
desktop->selection->clear();
- // printf("Desktop, starting reconstruction end\n");
+ g_debug("Desktop, starting reconstruction end\n");
}
/// Called when document rebuild is finished.
static void _reconstruction_finish(SPDesktop * desktop)
{
- // printf("Desktop, finishing reconstruction\n");
+ g_debug("Desktop, finishing reconstruction\n");
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->layers->setCurrentLayer(newLayer);
}
desktop->_reconstruction_old_layer_id.clear();
- // printf("Desktop, finishing reconstruction end\n");
}
+ g_debug("Desktop, finishing reconstruction end\n");
}
/**
@@ -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..9a3c609d0 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 *layers;
/// 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 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);
- SPObject *layerForObject(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 ed3d8e21b..78d7018bb 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -616,6 +616,11 @@ Geom::Point SPDocument::getDimensions() const
return Geom::Point(getWidth(), getHeight());
}
+Geom::OptRect SPDocument::preferredBounds() const
+{
+ return Geom::OptRect( Geom::Point(0, 0), getDimensions() );
+}
+
/**
* Given a Geom::Rect that may, for example, correspond to the bbox of an object,
* this function fits the canvas to that rect by resizing the canvas
diff --git a/src/document.h b/src/document.h
index c584c3beb..6782c6206 100644
--- a/src/document.h
+++ b/src/document.h
@@ -230,6 +230,7 @@ public:
gdouble getWidth() const;
gdouble getHeight() const;
Geom::Point getDimensions() const;
+ Geom::OptRect preferredBounds() const;
void setWidth(const Inkscape::Util::Quantity &width);
void setHeight(const Inkscape::Util::Quantity &height);
void requestModified();
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/application-interface.cpp b/src/extension/dbus/application-interface.cpp
index 8ee7bd12f..c0bc19d90 100644
--- a/src/extension/dbus/application-interface.cpp
+++ b/src/extension/dbus/application-interface.cpp
@@ -18,6 +18,8 @@
#include "application-interface.h"
#include <string.h>
#include "dbus-init.h"
+#include "file.h"
+#include "inkscape.h"
G_DEFINE_TYPE(ApplicationInterface, application_interface, G_TYPE_OBJECT)
@@ -37,13 +39,32 @@ application_interface_class_init (ApplicationInterfaceClass *klass)
}
static void
-application_interface_init (ApplicationInterface *object)
+application_interface_init (ApplicationInterface *app_interface)
{
dbus_g_error_domain_register (INKSCAPE_ERROR,
NULL,
INKSCAPE_TYPE_ERROR);
}
+static bool
+ensure_desktop_valid(GError **error)
+{
+ if (!inkscape_use_gui()) {
+ g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OTHER, "Application interface action requires a GUI");
+ return false;
+ }
+ return true;
+}
+
+static bool
+ensure_desktop_not_present(GError **error)
+{
+ if (inkscape_use_gui()) {
+ g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OTHER, "Application interface action requires non-GUI (command line) mode");
+ return false;
+ }
+ return true;
+}
ApplicationInterface *
application_interface_new (void)
@@ -94,27 +115,28 @@ GType inkscape_error_get_type(void)
****************************************************************************/
gchar*
-application_interface_desktop_new (ApplicationInterface *object,
+application_interface_desktop_new (ApplicationInterface *app_interface,
GError **error)
{
- return (gchar*)Inkscape::Extension::Dbus::init_desktop();
+ g_return_val_if_fail(ensure_desktop_valid(error), NULL);
+ return (gchar*)Inkscape::Extension::Dbus::init_desktop();
}
gchar**
-application_interface_get_desktop_list (ApplicationInterface *object)
+application_interface_get_desktop_list (ApplicationInterface *app_interface)
{
return NULL;
}
gchar*
-application_interface_get_active_desktop (ApplicationInterface *object,
+application_interface_get_active_desktop (ApplicationInterface *app_interface,
GError **error)
{
return NULL;
}
gboolean
-application_interface_set_active_desktop (ApplicationInterface *object,
+application_interface_set_active_desktop (ApplicationInterface *app_interface,
gchar* document_name,
GError **error)
{
@@ -122,15 +144,16 @@ application_interface_set_active_desktop (ApplicationInterface *object,
}
gboolean
-application_interface_desktop_close_all (ApplicationInterface *object,
+application_interface_desktop_close_all (ApplicationInterface *app_interface,
GError **error)
{
return TRUE;
}
gboolean
-application_interface_exit (ApplicationInterface *object, GError **error)
+application_interface_exit (ApplicationInterface *app_interface, GError **error)
{
+ sp_file_exit();
return TRUE;
}
@@ -138,20 +161,32 @@ application_interface_exit (ApplicationInterface *object, GError **error)
DOCUMENT FUNCTIONS
****************************************************************************/
-gchar* application_interface_document_new (ApplicationInterface *object,
+gchar* application_interface_document_new (ApplicationInterface *app_interface,
GError **error)
{
- return (gchar*)Inkscape::Extension::Dbus::init_document();
+ g_return_val_if_fail(ensure_desktop_not_present(error), NULL);
+ return (gchar*)Inkscape::Extension::Dbus::init_document();
+}
+
+gchar*
+application_interface_get_active_document(ApplicationInterface *app_interface,
+ GError **error)
+{
+ gchar *result = (gchar*)Inkscape::Extension::Dbus::init_active_document();
+ if (!result) {
+ g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OTHER, "No active document");
+ }
+ return result;
}
gchar**
-application_interface_get_document_list (ApplicationInterface *object)
+application_interface_get_document_list (ApplicationInterface *app_interface)
{
return NULL;
}
gboolean
-application_interface_document_close_all (ApplicationInterface *object,
+application_interface_document_close_all (ApplicationInterface *app_interface,
GError **error)
{
return TRUE;
diff --git a/src/extension/dbus/application-interface.h b/src/extension/dbus/application-interface.h
index 88219a6b0..c108402cb 100644
--- a/src/extension/dbus/application-interface.h
+++ b/src/extension/dbus/application-interface.h
@@ -67,41 +67,45 @@ GType inkscape_error_get_type (void);
****************************************************************************/
gchar*
-application_interface_desktop_new (ApplicationInterface *object,
+application_interface_desktop_new (ApplicationInterface *app_interface,
GError **error);
gchar**
-application_interface_get_desktop_list (ApplicationInterface *object);
+application_interface_get_desktop_list (ApplicationInterface *app_interface);
gchar*
-application_interface_get_active_desktop (ApplicationInterface *object,
+application_interface_get_active_desktop (ApplicationInterface *app_interface,
GError **error);
gboolean
-application_interface_set_active_desktop (ApplicationInterface *object,
+application_interface_set_active_desktop (ApplicationInterface *app_interface,
gchar* document_name,
GError **error);
gboolean
-application_interface_desktop_close_all (ApplicationInterface *object,
+application_interface_desktop_close_all (ApplicationInterface *app_interface,
GError **error);
gboolean
-application_interface_exit (ApplicationInterface *object, GError **error);
+application_interface_exit (ApplicationInterface *app_interface, GError **error);
/****************************************************************************
DOCUMENT FUNCTIONS
****************************************************************************/
gchar*
-application_interface_document_new (ApplicationInterface *object,
+application_interface_document_new (ApplicationInterface *app_interface,
GError **error);
+gchar*
+application_interface_get_active_document(ApplicationInterface *app_interface,
+ GError **error);
+
gchar**
-application_interface_get_document_list (ApplicationInterface *object);
+application_interface_get_document_list (ApplicationInterface *app_interface);
gboolean
-application_interface_document_close_all (ApplicationInterface *object,
+application_interface_document_close_all (ApplicationInterface *app_interface,
GError **error);
diff --git a/src/extension/dbus/application-interface.xml b/src/extension/dbus/application-interface.xml
index ee2c4837b..1553971cc 100644
--- a/src/extension/dbus/application-interface.xml
+++ b/src/extension/dbus/application-interface.xml
@@ -32,7 +32,7 @@
</arg>
<doc:doc>
<doc:description>
- <doc:para>Create a new document interface and return it's location.</doc:para>
+ <doc:para>Create a new document interface and return its location. Only call this when Inkscape is running in GUI mode.</doc:para>
</doc:description>
</doc:doc>
</method>
@@ -45,21 +45,21 @@
</arg>
<doc:doc>
<doc:description>
- <doc:para>List all the interfaces that it is possible to connect to.</doc:para>
+ <doc:para>List all the interfaces that it is possible to connect to. TODO: not implemented.</doc:para>
</doc:description>
</doc:doc>
</method>
<method name="desktop_close_all">
<doc:doc>
<doc:description>
- <doc:para>Close all document interfaces without saving.</doc:para>
+ <doc:para>Close all document interfaces without saving. TODO: not implemented.</doc:para>
</doc:description>
</doc:doc>
</method>
<method name="exit">
<doc:doc>
<doc:description>
- <doc:para>Exit Inkscape without saving. Fairly straightforward. </doc:para>
+ <doc:para>Exit Inkscape without saving. Fairly straightforward.</doc:para>
</doc:description>
</doc:doc>
</method>
@@ -76,6 +76,21 @@
<doc:description>
<doc:para>Originally, there were going to be two interfaces. A desktop and a document. Desktops would be used when the user wanted to see the result of their code and documents would be used when less overhead was desired. Unfortunately as more and more of the code can to rely on the desktop and it's associated support code (including selections and verbs) the document interface was looking more and more limited. Ultimately I decided to just go with the desktop interface since I didn't have a compelling reason for keeping the other one and having two similar interfaces could be very confusing. The desktop interface inherited the document name because I believe it's more familiar to people.</doc:para>
<doc:para>Perhaps it would be best to have an option as to whether or not to create a window and fail with a good error message when they call a function that requires one. Or have a second interface for different use cases but have it be completely different, rather than a subset of the first if there are use cases that support it.</doc:para>
+ <doc:para>UPDATE: 3rd July 2013, Eric Greveson: After having done some initial work to attempt to decouple Inkscape "verbs" from desktops, it is now possible to run a limited subset of actions in command-line mode (with a selection model and document, but no desktop). I believe that the "single document interface" approach, with some functions that may require a GUI, is the better path, and so document interfaces without a desktop are now possible. Most functions still require the desktop to work, though, with the notable exception of selection methods and Boolean operations.</doc:para>
+ <doc:para>As a result, this function should ONLY be called when using Inkscape in command-line mode. Use "desktop_new" instead if running in GUI mode.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+ <method name="get_active_document">
+ <arg type="s" name="document_name" direction="out" >
+ <annotation name="org.freedesktop.DBus.GLib.ReturnVal" value="error"/>
+ <doc:doc>
+ <doc:summary>This string can be used to connect to the current active document.</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Get the location of the current active document (e.g. when running in console mode, when desktops are not available).</doc:para>
</doc:description>
</doc:doc>
</method>
diff --git a/src/extension/dbus/dbus-init.cpp b/src/extension/dbus/dbus-init.cpp
index 9ff6897e5..19b48e10d 100644
--- a/src/extension/dbus/dbus-init.cpp
+++ b/src/extension/dbus/dbus-init.cpp
@@ -36,7 +36,14 @@
#include <sstream>
-
+namespace
+{
+ // This stores the bus name to use for this app instance. By default, it
+ // will be set to org.inkscape. However, users may provide other names by
+ // setting command-line parameters when starting Inkscape, so that more
+ // than one instance of Inkscape may be used by external scripts.
+ gchar *instance_bus_name = NULL;
+}
namespace Inkscape {
namespace Extension {
@@ -78,10 +85,53 @@ dbus_register_object (DBusGConnection *connection,
return object;
}
+/*
+ * PRIVATE register a document interface for the document in the given ActionContext, if none exists.
+ * Return the DBus path to the interface (something like /org/inkscape/document_0).
+ * Note that while a DocumentInterface could be used either for a document with no desktop, or a
+ * document with a desktop, this function is only used for creating interfaces in the former case.
+ * Desktop-associated DocumentInterfaces are named /org/inkscape/desktop_0, etc.
+ * FIXME: This state of affairs probably needs tidying up at some point in the future.
+ */
+static gchar *
+dbus_register_document(Inkscape::ActionContext const & target)
+{
+ SPDocument *doc = target.getDocument();
+ g_assert(doc != NULL);
+
+ // Document name is not suitable for DBus name, as it might contain invalid chars
+ std::string name("/org/inkscape/document_");
+ std::stringstream ss;
+ ss << doc->serial();
+ name.append(ss.str());
+
+ DBusGConnection *connection = dbus_get_connection();
+ DBusGProxy *proxy = dbus_get_proxy(connection);
+
+ // Has the document already been registered?
+ if (!dbus_g_connection_lookup_g_object(connection, name.c_str())) {
+ // No - register it
+ DocumentInterface *doc_interface = (DocumentInterface*) dbus_register_object (connection,
+ proxy,
+ TYPE_DOCUMENT_INTERFACE,
+ &dbus_glib_document_interface_object_info,
+ name.c_str());
+
+ // Set the document info for this interface
+ doc_interface->target = target;
+ }
+ return strdup(name.c_str());
+}
+
/* Initialize a Dbus service */
void
init (void)
{
+ if (instance_bus_name == NULL) {
+ // Set the bus name to the default
+ instance_bus_name = strdup("org.inkscape");
+ }
+
guint result;
GError *error = NULL;
DBusGConnection *connection;
@@ -89,7 +139,7 @@ init (void)
connection = dbus_get_connection();
proxy = dbus_get_proxy(connection);
org_freedesktop_DBus_request_name (proxy,
- "org.inkscape",
+ instance_bus_name,
DBUS_NAME_FLAG_DO_NOT_QUEUE, &result, &error);
//create interface for application
dbus_register_object (connection,
@@ -97,37 +147,36 @@ init (void)
TYPE_APPLICATION_INTERFACE,
&dbus_glib_application_interface_object_info,
DBUS_APPLICATION_INTERFACE_PATH);
-} //init
+}
gchar *
-init_document (void) {
- DBusGConnection *connection;
- DBusGProxy *proxy;
- SPDocument *doc;
-
- doc = SPDocument::createNewDoc(NULL, 1, TRUE);
-
- std::string name("/org/inkscape/");
- name.append(doc->getName());
- std::replace(name.begin(), name.end(), ' ', '_');
+init_document (void)
+{
+ // This is for command-line use only
+ g_assert(!inkscape_use_gui());
- connection = dbus_get_connection();
- proxy = dbus_get_proxy(connection);
+ // Create a blank document and get its selection model etc in an ActionContext
+ SPDocument *doc = SPDocument::createNewDoc(NULL, 1, TRUE);
+ inkscape_add_document(doc);
+ return dbus_register_document(inkscape_action_context_for_document(doc));
+}
- dbus_register_object (connection,
- proxy,
- TYPE_DOCUMENT_INTERFACE,
- &dbus_glib_document_interface_object_info,
- name.c_str());
- return strdup(name.c_str());
-} //init_document
+gchar *
+init_active_document()
+{
+ SPDocument *doc = inkscape_active_document();
+ if (!doc) {
+ return NULL;
+ }
+
+ return dbus_register_document(inkscape_active_action_context());
+}
gchar *
dbus_init_desktop_interface (SPDesktop * dt)
{
DBusGConnection *connection;
DBusGProxy *proxy;
- DocumentInterface *obj;
std::string name("/org/inkscape/desktop_");
std::stringstream out;
@@ -139,12 +188,12 @@ dbus_init_desktop_interface (SPDesktop * dt)
connection = dbus_get_connection();
proxy = dbus_get_proxy(connection);
- obj = (DocumentInterface*) dbus_register_object (connection,
+ DocumentInterface *doc_interface = (DocumentInterface*) dbus_register_object (connection,
proxy, TYPE_DOCUMENT_INTERFACE,
&dbus_glib_document_interface_object_info, name.c_str());
- obj->desk = dt;
- obj->updates = TRUE;
- dt->dbus_document_interface=obj;
+ doc_interface->target = Inkscape::ActionContext(dt);
+ doc_interface->updates = TRUE;
+ dt->dbus_document_interface=doc_interface;
return strdup(name.c_str());
}
@@ -159,8 +208,21 @@ init_desktop (void) {
out << dt->dkey;
name.append(out.str());
return strdup(name.c_str());
-} //init_desktop
+}
+void
+dbus_set_bus_name(gchar * bus_name)
+{
+ g_assert(bus_name != NULL);
+ g_assert(instance_bus_name == NULL);
+ instance_bus_name = strdup(bus_name);
+}
+gchar *
+dbus_get_bus_name()
+{
+ g_assert(instance_bus_name != NULL);
+ return instance_bus_name;
+}
} } } /* namespace Inkscape::Extension::Dbus */
diff --git a/src/extension/dbus/dbus-init.h b/src/extension/dbus/dbus-init.h
index 025011f28..7862ad3c3 100644
--- a/src/extension/dbus/dbus-init.h
+++ b/src/extension/dbus/dbus-init.h
@@ -10,8 +10,7 @@
#ifndef INKSCAPE_EXTENSION_DBUS_INIT_H__
#define INKSCAPE_EXTENSION_DBUS_INIT_H__
-#include "desktop.h"
-
+class SPDesktop;
namespace Inkscape {
namespace Extension {
@@ -23,10 +22,22 @@ void init (void);
gchar * init_document (void);
+gchar * init_active_document ();
+
gchar * init_desktop (void);
gchar * dbus_init_desktop_interface (SPDesktop * dt);
+/** Set the bus name to use. Default is "org.inkscape".
+ This function should only be called once, before init(), if a non-default
+ bus name is required. */
+void dbus_set_bus_name(gchar * bus_name);
+
+/** Get the bus name for this instance. Default is "org.inkscape".
+ This function should only be called after init().
+ The returned gchar * is owned by this module and should not be freed. */
+gchar * dbus_get_bus_name();
+
} } } /* namespace Dbus, Extension, Inkscape */
#endif /* INKSCAPE_EXTENSION_DBUS_INIT_H__ */
diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp
index 56d1dfdbd..3cb03646a 100644
--- a/src/extension/dbus/document-interface.cpp
+++ b/src/extension/dbus/document-interface.cpp
@@ -20,6 +20,7 @@
#include "application-interface.h"
#include <string.h>
#include <dbus/dbus-glib.h>
+#include "desktop.h"
#include "desktop-handles.h" //sp_desktop_document()
#include "desktop-style.h" //sp_desktop_get_style
#include "display/canvas-text.h" //text
@@ -30,8 +31,10 @@
#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 "layer-model.h"
#include "live_effects/parameter/text.h" //text
#include "print.h" //IO
#include "selection-chemistry.h"// lots of selection functions
@@ -91,12 +94,12 @@
* place to adjust things.
*/
Inkscape::XML::Node *
-get_repr_by_name (SPDesktop *desk, gchar *name, GError **error)
+get_repr_by_name (SPDocument *doc, gchar *name, GError **error)
{
/* ALTERNATIVE (is this faster if only repr is needed?)
Inkscape::XML::Node *node = sp_repr_lookup_name((doc->root)->repr, name);
*/
- SPObject * obj = sp_desktop_document(desk)->getObjectById(name);
+ SPObject * obj = doc->getObjectById(name);
if (!obj)
{
g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OBJECT, "Object '%s' not found in document.", name);
@@ -109,9 +112,9 @@ get_repr_by_name (SPDesktop *desk, gchar *name, GError **error)
* See comment for get_repr_by_name, above.
*/
SPObject *
-get_object_by_name (SPDesktop *desk, gchar *name, GError **error)
+get_object_by_name (SPDocument *doc, gchar *name, GError **error)
{
- SPObject * obj = sp_desktop_document(desk)->getObjectById(name);
+ SPObject * obj = doc->getObjectById(name);
if (!obj)
{
g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OBJECT, "Object '%s' not found in document.", name);
@@ -183,12 +186,11 @@ selection_get_center_y (Inkscape::Selection *sel){
* they might see the selection box flicker if used in a loop.
*/
const GSList *
-selection_swap(SPDesktop *desk, gchar *name, GError **error)
+selection_swap(Inkscape::Selection *sel, gchar *name, GError **error)
{
- Inkscape::Selection *sel = sp_desktop_selection(desk);
const GSList *oldsel = g_slist_copy((GSList *)sel->list());
- sel->set(get_object_by_name(desk, name, error));
+ sel->set(get_object_by_name(sel->layers()->getDocument(), name, error));
return oldsel;
}
@@ -196,9 +198,8 @@ selection_swap(SPDesktop *desk, gchar *name, GError **error)
* See selection_swap, above
*/
void
-selection_restore(SPDesktop *desk, const GSList * oldsel)
+selection_restore(Inkscape::Selection *sel, const GSList * oldsel)
{
- Inkscape::Selection *sel = sp_desktop_selection(desk);
sel->setList(oldsel);
}
@@ -206,9 +207,8 @@ selection_restore(SPDesktop *desk, const GSList * oldsel)
* Shortcut for creating a Node.
*/
Inkscape::XML::Node *
-dbus_create_node (SPDesktop *desk, const gchar *type)
+dbus_create_node (SPDocument *doc, const gchar *type)
{
- SPDocument * doc = sp_desktop_document (desk);
Inkscape::XML::Document *xml_doc = doc->getReprDoc();
return xml_doc->createElement(type);
@@ -221,10 +221,12 @@ dbus_create_node (SPDesktop *desk, const gchar *type)
* There is probably a better way to do this (use the shape tools default styles)
* but I'm not sure how.
*/
-gchar *finish_create_shape (DocumentInterface *object, GError ** /*error*/, Inkscape::XML::Node *newNode, gchar *desc)
+gchar *finish_create_shape (DocumentInterface *doc_interface, GError ** /*error*/, Inkscape::XML::Node *newNode, gchar *desc)
{
- SPCSSAttr *style = sp_desktop_get_style(object->desk, TRUE);
-
+ SPCSSAttr *style = NULL;
+ if (doc_interface->target.getDesktop()) {
+ style = sp_desktop_get_style(doc_interface->target.getDesktop(), TRUE);
+ }
if (style) {
Glib::ustring str;
sp_repr_css_write_string(style, str);
@@ -234,13 +236,11 @@ gchar *finish_create_shape (DocumentInterface *object, GError ** /*error*/, Inks
newNode->setAttribute("style", "fill:#0000ff;fill-opacity:1;stroke:#c900b9;stroke-width:0;stroke-miterlimit:0;stroke-opacity:1;stroke-dasharray:none", TRUE);
}
- object->desk->currentLayer()->appendChildRepr(newNode);
- object->desk->currentLayer()->updateRepr();
+ doc_interface->target.getSelection()->layers()->currentLayer()->appendChildRepr(newNode);
+ doc_interface->target.getSelection()->layers()->currentLayer()->updateRepr();
- if (object->updates) {
- Inkscape::DocumentUndo::done(sp_desktop_document(object->desk), 0, (gchar *)desc);
- //} else {
- //document_interface_pause_updates(object, error);
+ if (doc_interface->updates) {
+ Inkscape::DocumentUndo::done(doc_interface->target.getDocument(), 0, (gchar *)desc);
}
return strdup(newNode->attribute("id"));
@@ -255,31 +255,40 @@ gchar *finish_create_shape (DocumentInterface *object, GError ** /*error*/, Inks
* document_interface_call_verb is similar but is called by the user.
*/
gboolean
-dbus_call_verb (DocumentInterface *object, int verbid, GError **error)
+dbus_call_verb (DocumentInterface *doc_interface, int verbid, GError **error)
{
- SPDesktop *desk2 = object->desk;
- desktop_ensure_active (desk2);
-
- if ( desk2 ) {
- Inkscape::Verb *verb = Inkscape::Verb::get( verbid );
- if ( verb ) {
- SPAction *action = verb->get_action(desk2);
- if ( action ) {
- //if (!object->updates)
- //document_interface_pause_updates (object, error);
- sp_action_perform( action, NULL );
- if (object->updates)
- Inkscape::DocumentUndo::done(sp_desktop_document(desk2), verb->get_code(), g_strdup(verb->get_tip()));
- //if (!object->updates)
- //document_interface_pause_updates (object, error);
- return TRUE;
- }
+ SPDesktop *desk = doc_interface->target.getDesktop();
+ if ( desk ) {
+ desktop_ensure_active (desk);
+ }
+ Inkscape::Verb *verb = Inkscape::Verb::get( verbid );
+ if ( verb ) {
+ SPAction *action = verb->get_action(doc_interface->target);
+ if ( action ) {
+ sp_action_perform( action, NULL );
+ if (doc_interface->updates)
+ Inkscape::DocumentUndo::done(doc_interface->target.getDocument(), verb->get_code(), g_strdup(verb->get_tip()));
+ return TRUE;
}
}
g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_VERB, "Verb failed to execute");
return FALSE;
}
+/*
+ * Check that the desktop is not NULL. If it is NULL, set the error to a useful message.
+ */
+bool
+ensure_desktop_valid(SPDesktop* desk, GError **error)
+{
+ if (desk) {
+ return true;
+ }
+
+ g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OTHER, "Document interface action requires a GUI");
+ return false;
+}
+
/****************************************************************************
DOCUMENT INTERFACE CLASS STUFF
****************************************************************************/
@@ -310,9 +319,9 @@ document_interface_class_init (DocumentInterfaceClass *klass)
}
static void
-document_interface_init (DocumentInterface *object)
+document_interface_init (DocumentInterface *doc_interface)
{
- object->desk = NULL;
+ doc_interface->target = Inkscape::ActionContext();
}
@@ -328,28 +337,28 @@ document_interface_new (void)
MISC FUNCTIONS
****************************************************************************/
-gboolean document_interface_delete_all(DocumentInterface *object, GError ** /*error*/)
+gboolean document_interface_delete_all(DocumentInterface *doc_interface, GError ** /*error*/)
{
- sp_edit_clear_all(object->desk);
+ sp_edit_clear_all(doc_interface->target.getSelection());
return TRUE;
}
gboolean
-document_interface_call_verb (DocumentInterface *object, gchar *verbid, GError **error)
-{
- SPDesktop *desk2 = object->desk;
- desktop_ensure_active (object->desk);
- if ( desk2 ) {
- Inkscape::Verb *verb = Inkscape::Verb::getbyid( verbid );
- if ( verb ) {
- SPAction *action = verb->get_action(desk2);
- if ( action ) {
- sp_action_perform( action, NULL );
- if (object->updates) {
- Inkscape::DocumentUndo::done(sp_desktop_document(desk2), verb->get_code(), g_strdup(verb->get_tip()));
- }
- return TRUE;
+document_interface_call_verb (DocumentInterface *doc_interface, gchar *verbid, GError **error)
+{
+ SPDesktop *desk = doc_interface->target.getDesktop();
+ if ( desk ) {
+ desktop_ensure_active (desk);
+ }
+ Inkscape::Verb *verb = Inkscape::Verb::getbyid( verbid );
+ if ( verb ) {
+ SPAction *action = verb->get_action(doc_interface->target);
+ if ( action ) {
+ sp_action_perform( action, NULL );
+ if (doc_interface->updates) {
+ Inkscape::DocumentUndo::done(doc_interface->target.getDocument(), verb->get_code(), g_strdup(verb->get_tip()));
}
+ return TRUE;
}
}
g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_VERB, "Verb '%s' failed to execute or was not found.", verbid);
@@ -362,39 +371,39 @@ document_interface_call_verb (DocumentInterface *object, gchar *verbid, GError *
****************************************************************************/
gchar*
-document_interface_rectangle (DocumentInterface *object, int x, int y,
+document_interface_rectangle (DocumentInterface *doc_interface, int x, int y,
int width, int height, GError **error)
{
- Inkscape::XML::Node *newNode = dbus_create_node(object->desk, "svg:rect");
+ Inkscape::XML::Node *newNode = dbus_create_node(doc_interface->target.getDocument(), "svg:rect");
sp_repr_set_int(newNode, "x", x); //could also use newNode->setAttribute()
sp_repr_set_int(newNode, "y", y);
sp_repr_set_int(newNode, "width", width);
sp_repr_set_int(newNode, "height", height);
- return finish_create_shape (object, error, newNode, (gchar *)"create rectangle");
+ return finish_create_shape (doc_interface, error, newNode, (gchar *)"create rectangle");
}
gchar*
-document_interface_ellipse_center (DocumentInterface *object, int cx, int cy,
+document_interface_ellipse_center (DocumentInterface *doc_interface, int cx, int cy,
int rx, int ry, GError **error)
{
- Inkscape::XML::Node *newNode = dbus_create_node(object->desk, "svg:path");
+ Inkscape::XML::Node *newNode = dbus_create_node(doc_interface->target.getDocument(), "svg:path");
newNode->setAttribute("sodipodi:type", "arc");
sp_repr_set_int(newNode, "sodipodi:cx", cx);
sp_repr_set_int(newNode, "sodipodi:cy", cy);
sp_repr_set_int(newNode, "sodipodi:rx", rx);
sp_repr_set_int(newNode, "sodipodi:ry", ry);
- return finish_create_shape (object, error, newNode, (gchar *)"create circle");
+ return finish_create_shape (doc_interface, error, newNode, (gchar *)"create circle");
}
gchar*
-document_interface_polygon (DocumentInterface *object, int cx, int cy,
+document_interface_polygon (DocumentInterface *doc_interface, int cx, int cy,
int radius, int rotation, int sides,
GError **error)
{
gdouble rot = ((rotation / 180.0) * 3.14159265) - ( 3.14159265 / 2.0);
- Inkscape::XML::Node *newNode = dbus_create_node(object->desk, "svg:path");
+ Inkscape::XML::Node *newNode = dbus_create_node(doc_interface->target.getDocument(), "svg:path");
newNode->setAttribute("inkscape:flatsided", "true");
newNode->setAttribute("sodipodi:type", "star");
sp_repr_set_int(newNode, "sodipodi:cx", cx);
@@ -407,15 +416,15 @@ document_interface_polygon (DocumentInterface *object, int cx, int cy,
sp_repr_set_svg_double(newNode, "sodipodi:arg2", rot);
sp_repr_set_svg_double(newNode, "inkscape:rounded", 0);
- return finish_create_shape (object, error, newNode, (gchar *)"create polygon");
+ return finish_create_shape (doc_interface, error, newNode, (gchar *)"create polygon");
}
gchar*
-document_interface_star (DocumentInterface *object, int cx, int cy,
+document_interface_star (DocumentInterface *doc_interface, int cx, int cy,
int r1, int r2, int sides, gdouble rounded,
gdouble arg1, gdouble arg2, GError **error)
{
- Inkscape::XML::Node *newNode = dbus_create_node(object->desk, "svg:path");
+ Inkscape::XML::Node *newNode = dbus_create_node(doc_interface->target.getDocument(), "svg:path");
newNode->setAttribute("inkscape:flatsided", "false");
newNode->setAttribute("sodipodi:type", "star");
sp_repr_set_int(newNode, "sodipodi:cx", cx);
@@ -428,35 +437,35 @@ document_interface_star (DocumentInterface *object, int cx, int cy,
sp_repr_set_svg_double(newNode, "sodipodi:arg2", arg2);
sp_repr_set_svg_double(newNode, "inkscape:rounded", rounded);
- return finish_create_shape (object, error, newNode, (gchar *)"create star");
+ return finish_create_shape (doc_interface, error, newNode, (gchar *)"create star");
}
gchar*
-document_interface_ellipse (DocumentInterface *object, int x, int y,
+document_interface_ellipse (DocumentInterface *doc_interface, int x, int y,
int width, int height, GError **error)
{
int rx = width/2;
int ry = height/2;
- return document_interface_ellipse_center (object, x+rx, y+ry, rx, ry, error);
+ return document_interface_ellipse_center (doc_interface, x+rx, y+ry, rx, ry, error);
}
gchar*
-document_interface_line (DocumentInterface *object, int x, int y,
+document_interface_line (DocumentInterface *doc_interface, int x, int y,
int x2, int y2, GError **error)
{
- Inkscape::XML::Node *newNode = dbus_create_node(object->desk, "svg:path");
+ Inkscape::XML::Node *newNode = dbus_create_node(doc_interface->target.getDocument(), "svg:path");
std::stringstream out;
// Not sure why this works.
out << "m " << x << "," << y << " " << x2 - x << "," << y2 - y;
newNode->setAttribute("d", out.str().c_str());
- return finish_create_shape (object, error, newNode, (gchar *)"create line");
+ return finish_create_shape (doc_interface, error, newNode, (gchar *)"create line");
}
gchar*
-document_interface_spiral (DocumentInterface *object, int cx, int cy,
+document_interface_spiral (DocumentInterface *doc_interface, int cx, int cy,
int r, int revolutions, GError **error)
{
- Inkscape::XML::Node *newNode = dbus_create_node(object->desk, "svg:path");
+ Inkscape::XML::Node *newNode = dbus_create_node(doc_interface->target.getDocument(), "svg:path");
newNode->setAttribute("sodipodi:type", "spiral");
sp_repr_set_int(newNode, "sodipodi:cx", cx);
sp_repr_set_int(newNode, "sodipodi:cy", cy);
@@ -465,7 +474,7 @@ document_interface_spiral (DocumentInterface *object, int cx, int cy,
sp_repr_set_int(newNode, "sodipodi:t0", 0);
sp_repr_set_int(newNode, "sodipodi:argument", 0);
sp_repr_set_int(newNode, "sodipodi:expansion", 1);
- gchar * retval = finish_create_shape (object, error, newNode, (gchar *)"create spiral");
+ gchar * retval = finish_create_shape (doc_interface, error, newNode, (gchar *)"create spiral");
//Makes sure there is no fill for spirals by default.
gchar* newString = g_strconcat(newNode->attribute("style"), ";fill:none", NULL);
newNode->setAttribute("style", newString);
@@ -474,57 +483,55 @@ document_interface_spiral (DocumentInterface *object, int cx, int cy,
}
gchar*
-document_interface_text (DocumentInterface *object, int x, int y, gchar *text, GError **error)
+document_interface_text (DocumentInterface *doc_interface, int x, int y, gchar *text, GError **error)
{
- Inkscape::XML::Node *text_node = dbus_create_node(object->desk, "svg:text");
+ Inkscape::XML::Node *text_node = dbus_create_node(doc_interface->target.getDocument(), "svg:text");
sp_repr_set_int(text_node, "x", x);
sp_repr_set_int(text_node, "y", y);
//just a workaround so i can get an spitem from the name
- gchar *name = finish_create_shape (object, error, text_node, (gchar *)"create text");
+ gchar *name = finish_create_shape (doc_interface, error, text_node, (gchar *)"create text");
- SPItem* text_obj=(SPItem* )get_object_by_name(object->desk, name, error);
+ SPItem* text_obj=(SPItem* )get_object_by_name(doc_interface->target.getDocument(), name, error);
sp_te_set_repr_text_multiline(text_obj, text);
return name;
}
gchar *
-document_interface_image (DocumentInterface *object, int x, int y, gchar *filename, GError **error)
+document_interface_image (DocumentInterface *doc_interface, int x, int y, gchar *filename, GError **error)
{
gchar * uri = g_filename_to_uri (filename, FALSE, error);
if (!uri)
return FALSE;
- Inkscape::XML::Node *newNode = dbus_create_node(object->desk, "svg:image");
+ Inkscape::XML::Node *newNode = dbus_create_node(doc_interface->target.getDocument(), "svg:image");
sp_repr_set_int(newNode, "x", x);
sp_repr_set_int(newNode, "y", y);
newNode->setAttribute("xlink:href", uri);
- object->desk->currentLayer()->appendChildRepr(newNode);
- object->desk->currentLayer()->updateRepr();
+ doc_interface->target.getSelection()->layers()->currentLayer()->appendChildRepr(newNode);
+ doc_interface->target.getSelection()->layers()->currentLayer()->updateRepr();
- if (object->updates)
- Inkscape::DocumentUndo::done(sp_desktop_document(object->desk), 0, "Imported bitmap.");
+ if (doc_interface->updates)
+ Inkscape::DocumentUndo::done(doc_interface->target.getDocument(), 0, "Imported bitmap.");
//g_free(uri);
return strdup(newNode->attribute("id"));
}
-gchar *document_interface_node(DocumentInterface *object, gchar *type, GError ** /*error*/)
+gchar *document_interface_node(DocumentInterface *doc_interface, gchar *type, GError ** /*error*/)
{
- SPDocument * doc = sp_desktop_document (object->desk);
+ SPDocument * doc = doc_interface->target.getDocument();
Inkscape::XML::Document *xml_doc = doc->getReprDoc();
Inkscape::XML::Node *newNode = xml_doc->createElement(type);
- object->desk->currentLayer()->appendChildRepr(newNode);
- object->desk->currentLayer()->updateRepr();
+ doc_interface->target.getSelection()->layers()->currentLayer()->appendChildRepr(newNode);
+ doc_interface->target.getSelection()->layers()->currentLayer()->updateRepr();
- if (object->updates) {
- Inkscape::DocumentUndo::done(sp_desktop_document(object->desk), 0, (gchar *)"created empty node");
- //} else {
- //document_interface_pause_updates(object, error);
+ if (doc_interface->updates) {
+ Inkscape::DocumentUndo::done(doc, 0, (gchar *)"created empty node");
}
return strdup(newNode->attribute("id"));
@@ -534,53 +541,59 @@ gchar *document_interface_node(DocumentInterface *object, gchar *type, GError **
ENVIRONMENT FUNCTIONS
****************************************************************************/
gdouble
-document_interface_document_get_width (DocumentInterface *object)
+document_interface_document_get_width (DocumentInterface *doc_interface)
{
- return sp_desktop_document(object->desk)->getWidth();
+ return doc_interface->target.getDocument()->getWidth();
}
gdouble
-document_interface_document_get_height (DocumentInterface *object)
+document_interface_document_get_height (DocumentInterface *doc_interface)
{
- return sp_desktop_document(object->desk)->getHeight();
+ return doc_interface->target.getDocument()->getHeight();
}
-gchar *document_interface_document_get_css(DocumentInterface *object, GError ** /*error*/)
+gchar *document_interface_document_get_css(DocumentInterface *doc_interface, GError ** error)
{
- SPCSSAttr *current = (object->desk)->current;
+ SPDesktop *desk = doc_interface->target.getDesktop();
+ g_return_val_if_fail(ensure_desktop_valid(desk, error), NULL);
+ SPCSSAttr *current = desk->current;
Glib::ustring str;
sp_repr_css_write_string(current, str);
return (str.empty() ? NULL : g_strdup (str.c_str()));
}
-gboolean document_interface_document_merge_css(DocumentInterface *object,
- gchar *stylestring, GError ** /*error*/)
+gboolean document_interface_document_merge_css(DocumentInterface *doc_interface,
+ gchar *stylestring, GError ** error)
{
+ SPDesktop *desk = doc_interface->target.getDesktop();
+ g_return_val_if_fail(ensure_desktop_valid(desk, error), FALSE);
SPCSSAttr * style = sp_repr_css_attr_new();
sp_repr_css_attr_add_from_string(style, stylestring);
- sp_desktop_set_style(object->desk, style);
+ sp_desktop_set_style(desk, style);
return TRUE;
}
-gboolean document_interface_document_set_css(DocumentInterface *object,
- gchar *stylestring, GError ** /*error*/)
+gboolean document_interface_document_set_css(DocumentInterface *doc_interface,
+ gchar *stylestring, GError ** error)
{
+ SPDesktop *desk = doc_interface->target.getDesktop();
+ g_return_val_if_fail(ensure_desktop_valid(desk, error), FALSE);
SPCSSAttr * style = sp_repr_css_attr_new();
sp_repr_css_attr_add_from_string (style, stylestring);
//Memory leak?
- object->desk->current = style;
+ desk->current = style;
return TRUE;
}
gboolean
-document_interface_document_resize_to_fit_selection (DocumentInterface *object,
+document_interface_document_resize_to_fit_selection (DocumentInterface *doc_interface,
GError **error)
{
- return dbus_call_verb (object, SP_VERB_FIT_CANVAS_TO_SELECTION, error);
+ return dbus_call_verb (doc_interface, SP_VERB_FIT_CANVAS_TO_SELECTION, error);
}
gboolean
-document_interface_document_set_display_area (DocumentInterface *object,
+document_interface_document_set_display_area (DocumentInterface *doc_interface,
double x0,
double y0,
double x1,
@@ -588,19 +601,25 @@ document_interface_document_set_display_area (DocumentInterface *object,
double border,
GError **error)
{
- object->desk->set_display_area (x0,
+ SPDesktop *desk = doc_interface->target.getDesktop();
+ g_return_val_if_fail(ensure_desktop_valid(desk, error), FALSE);
+ desk->set_display_area (x0,
y0,
x1,
y1,
border, false);
- return TRUE;
+ return TRUE;
}
GArray *
-document_interface_document_get_display_area (DocumentInterface *object)
+document_interface_document_get_display_area (DocumentInterface *doc_interface)
{
- Geom::Rect const d = object->desk->get_display_area();
+ SPDesktop *desk = doc_interface->target.getDesktop();
+ if (!desk) {
+ return NULL;
+ }
+ Geom::Rect const d = desk->get_display_area();
GArray * dArr = g_array_new (TRUE, TRUE, sizeof(double));
@@ -622,10 +641,10 @@ document_interface_document_get_display_area (DocumentInterface *object)
****************************************************************************/
gboolean
-document_interface_set_attribute (DocumentInterface *object, char *shape,
+document_interface_set_attribute (DocumentInterface *doc_interface, char *shape,
char *attribute, char *newval, GError **error)
{
- Inkscape::XML::Node *newNode = get_repr_by_name(object->desk, shape, error);
+ Inkscape::XML::Node *newNode = get_repr_by_name(doc_interface->target.getDocument(), shape, error);
/* ALTERNATIVE (is this faster?)
Inkscape::XML::Node *newnode = sp_repr_lookup_name((doc->root)->repr, name);
@@ -641,11 +660,11 @@ document_interface_set_attribute (DocumentInterface *object, char *shape,
}
gboolean
-document_interface_set_int_attribute (DocumentInterface *object,
+document_interface_set_int_attribute (DocumentInterface *doc_interface,
char *shape, char *attribute,
int newval, GError **error)
{
- Inkscape::XML::Node *newNode = get_repr_by_name (object->desk, shape, error);
+ Inkscape::XML::Node *newNode = get_repr_by_name (doc_interface->target.getDocument(), shape, error);
if (!newNode)
return FALSE;
@@ -655,11 +674,11 @@ document_interface_set_int_attribute (DocumentInterface *object,
gboolean
-document_interface_set_double_attribute (DocumentInterface *object,
+document_interface_set_double_attribute (DocumentInterface *doc_interface,
char *shape, char *attribute,
double newval, GError **error)
{
- Inkscape::XML::Node *newNode = get_repr_by_name (object->desk, shape, error);
+ Inkscape::XML::Node *newNode = get_repr_by_name (doc_interface->target.getDocument(), shape, error);
if (!dbus_check_string (attribute, error, "New value string was empty."))
return FALSE;
@@ -671,10 +690,10 @@ document_interface_set_double_attribute (DocumentInterface *object,
}
gchar *
-document_interface_get_attribute (DocumentInterface *object, char *shape,
+document_interface_get_attribute (DocumentInterface *doc_interface, char *shape,
char *attribute, GError **error)
{
- Inkscape::XML::Node *newNode = get_repr_by_name(object->desk, shape, error);
+ Inkscape::XML::Node *newNode = get_repr_by_name(doc_interface->target.getDocument(), shape, error);
if (!dbus_check_string (attribute, error, "Attribute name empty."))
return NULL;
@@ -685,47 +704,47 @@ document_interface_get_attribute (DocumentInterface *object, char *shape,
}
gboolean
-document_interface_move (DocumentInterface *object, gchar *name, gdouble x,
+document_interface_move (DocumentInterface *doc_interface, gchar *name, gdouble x,
gdouble y, GError **error)
{
- const GSList *oldsel = selection_swap(object->desk, name, error);
+ const GSList *oldsel = selection_swap(doc_interface->target.getSelection(), name, error);
if (!oldsel)
return FALSE;
- sp_selection_move (object->desk, x, 0 - y);
- selection_restore(object->desk, oldsel);
+ sp_selection_move (doc_interface->target.getSelection(), x, 0 - y);
+ selection_restore(doc_interface->target.getSelection(), oldsel);
return TRUE;
}
gboolean
-document_interface_move_to (DocumentInterface *object, gchar *name, gdouble x,
+document_interface_move_to (DocumentInterface *doc_interface, gchar *name, gdouble x,
gdouble y, GError **error)
{
- const GSList *oldsel = selection_swap(object->desk, name, error);
+ const GSList *oldsel = selection_swap(doc_interface->target.getSelection(), name, error);
if (!oldsel)
return FALSE;
- Inkscape::Selection * sel = sp_desktop_selection(object->desk);
- sp_selection_move (object->desk, x - selection_get_center_x(sel),
+ Inkscape::Selection * sel = doc_interface->target.getSelection();
+ sp_selection_move (doc_interface->target.getSelection(), x - selection_get_center_x(sel),
0 - (y - selection_get_center_y(sel)));
- selection_restore(object->desk, oldsel);
+ selection_restore(doc_interface->target.getSelection(), oldsel);
return TRUE;
}
gboolean
-document_interface_object_to_path (DocumentInterface *object,
+document_interface_object_to_path (DocumentInterface *doc_interface,
char *shape, GError **error)
{
- const GSList *oldsel = selection_swap(object->desk, shape, error);
+ const GSList *oldsel = selection_swap(doc_interface->target.getSelection(), shape, error);
if (!oldsel)
return FALSE;
- dbus_call_verb (object, SP_VERB_OBJECT_TO_CURVE, error);
- selection_restore(object->desk, oldsel);
+ dbus_call_verb (doc_interface, SP_VERB_OBJECT_TO_CURVE, error);
+ selection_restore(doc_interface->target.getSelection(), oldsel);
return TRUE;
}
gchar *
-document_interface_get_path (DocumentInterface *object, char *pathname, GError **error)
+document_interface_get_path (DocumentInterface *doc_interface, char *pathname, GError **error)
{
- Inkscape::XML::Node *node = get_repr_by_name(object->desk, pathname, error);
+ Inkscape::XML::Node *node = get_repr_by_name(doc_interface->target.getDocument(), pathname, error);
if (!node)
return NULL;
@@ -739,30 +758,30 @@ document_interface_get_path (DocumentInterface *object, char *pathname, GError *
}
gboolean
-document_interface_transform (DocumentInterface *object, gchar *shape,
+document_interface_transform (DocumentInterface *doc_interface, gchar *shape,
gchar *transformstr, GError **error)
{
//FIXME: This should merge transformations.
gchar trans[] = "transform";
- document_interface_set_attribute (object, shape, trans, transformstr, error);
+ document_interface_set_attribute (doc_interface, shape, trans, transformstr, error);
return TRUE;
}
gchar *
-document_interface_get_css (DocumentInterface *object, gchar *shape,
+document_interface_get_css (DocumentInterface *doc_interface, gchar *shape,
GError **error)
{
gchar style[] = "style";
- return document_interface_get_attribute (object, shape, style, error);
+ return document_interface_get_attribute (doc_interface, shape, style, error);
}
gboolean
-document_interface_modify_css (DocumentInterface *object, gchar *shape,
+document_interface_modify_css (DocumentInterface *doc_interface, gchar *shape,
gchar *cssattrb, gchar *newval, GError **error)
{
// Doesn't like non-variable strings for some reason.
gchar style[] = "style";
- Inkscape::XML::Node *node = get_repr_by_name(object->desk, shape, error);
+ Inkscape::XML::Node *node = get_repr_by_name(doc_interface->target.getDocument(), shape, error);
if (!dbus_check_string (cssattrb, error, "Attribute string empty."))
return FALSE;
@@ -778,12 +797,12 @@ document_interface_modify_css (DocumentInterface *object, gchar *shape,
}
gboolean
-document_interface_merge_css (DocumentInterface *object, gchar *shape,
+document_interface_merge_css (DocumentInterface *doc_interface, gchar *shape,
gchar *stylestring, GError **error)
{
gchar style[] = "style";
- Inkscape::XML::Node *node = get_repr_by_name(object->desk, shape, error);
+ Inkscape::XML::Node *node = get_repr_by_name(doc_interface->target.getDocument(), shape, error);
if (!dbus_check_string (stylestring, error, "Style string empty."))
return FALSE;
@@ -804,7 +823,7 @@ document_interface_merge_css (DocumentInterface *object, gchar *shape,
}
gboolean
-document_interface_set_color (DocumentInterface *object, gchar *shape,
+document_interface_set_color (DocumentInterface *doc_interface, gchar *shape,
int r, int g, int b, gboolean fill, GError **error)
{
gchar style[15];
@@ -820,29 +839,29 @@ document_interface_set_color (DocumentInterface *object, gchar *shape,
snprintf(style, 15, "stroke:#%.2x%.2x%.2x", r, g, b);
if (strcmp(shape, "document") == 0)
- return document_interface_document_merge_css (object, style, error);
+ return document_interface_document_merge_css (doc_interface, style, error);
- return document_interface_merge_css (object, shape, style, error);
+ return document_interface_merge_css (doc_interface, shape, style, error);
}
gboolean
-document_interface_move_to_layer (DocumentInterface *object, gchar *shape,
+document_interface_move_to_layer (DocumentInterface *doc_interface, gchar *shape,
gchar *layerstr, GError **error)
{
- const GSList *oldsel = selection_swap(object->desk, shape, error);
+ const GSList *oldsel = selection_swap(doc_interface->target.getSelection(), shape, error);
if (!oldsel)
return FALSE;
- document_interface_selection_move_to_layer(object, layerstr, error);
- selection_restore(object->desk, oldsel);
+ document_interface_selection_move_to_layer(doc_interface, layerstr, error);
+ selection_restore(doc_interface->target.getSelection(), oldsel);
return TRUE;
}
-GArray *document_interface_get_node_coordinates(DocumentInterface * /*object*/, gchar * /*shape*/)
+GArray *document_interface_get_node_coordinates(DocumentInterface * /*doc_interface*/, gchar * /*shape*/)
{
//FIXME: Needs lot's of work.
/*
- Inkscape::XML::Node *shapenode = get_repr_by_name (object->desk, shape, error);
+ Inkscape::XML::Node *shapenode = get_repr_by_name (doc_interface->target.getDocument(), shape, error);
if (shapenode == NULL || shapenode->attribute("d") == NULL) {
return FALSE;
}
@@ -857,10 +876,10 @@ GArray *document_interface_get_node_coordinates(DocumentInterface * /*object*/,
gboolean
-document_interface_set_text (DocumentInterface *object, gchar *name, gchar *text, GError **error)
+document_interface_set_text (DocumentInterface *doc_interface, gchar *name, gchar *text, GError **error)
{
- SPItem* text_obj=(SPItem* )get_object_by_name(object->desk, name, error);
+ SPItem* text_obj=(SPItem* )get_object_by_name(doc_interface->target.getDocument(), name, error);
//TODO verify object type
if (!text_obj)
return FALSE;
@@ -872,12 +891,12 @@ document_interface_set_text (DocumentInterface *object, gchar *name, gchar *text
gboolean
-document_interface_text_apply_style (DocumentInterface *object, gchar *name,
+document_interface_text_apply_style (DocumentInterface *doc_interface, gchar *name,
int start_pos, int end_pos, gchar *style, gchar *styleval,
GError **error)
{
- SPItem* text_obj=(SPItem* )get_object_by_name(object->desk, name, error);
+ SPItem* text_obj=(SPItem* )get_object_by_name(doc_interface->target.getDocument(), name, error);
//void sp_te_apply_style(SPItem *text, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, SPCSSAttr const *css)
//TODO verify object type
@@ -904,34 +923,40 @@ document_interface_text_apply_style (DocumentInterface *object, gchar *name,
****************************************************************************/
gboolean
-document_interface_save (DocumentInterface *object, GError **error)
+document_interface_save (DocumentInterface *doc_interface, GError **error)
{
- SPDocument * doc = sp_desktop_document(object->desk);
+ SPDocument * doc = doc_interface->target.getDocument();
printf("1: %s\n2: %s\n3: %s\n", doc->getURI(), doc->getBase(), doc->getName());
if (doc->getURI())
- return document_interface_save_as (object, doc->getURI(), error);
+ return document_interface_save_as (doc_interface, doc->getURI(), error);
return FALSE;
}
-gboolean document_interface_load(DocumentInterface *object,
+gboolean document_interface_load(DocumentInterface *doc_interface,
gchar *filename, GError ** /*error*/)
{
- desktop_ensure_active(object->desk);
+ SPDesktop *desk = doc_interface->target.getDesktop();
+ if (desk) {
+ desktop_ensure_active(desk);
+ }
const Glib::ustring file(filename);
sp_file_open(file, NULL, TRUE, TRUE);
- if (object->updates) {
- Inkscape::DocumentUndo::done(sp_desktop_document(object->desk), SP_VERB_FILE_OPEN, "Opened File");
+ if (doc_interface->updates) {
+ Inkscape::DocumentUndo::done(doc_interface->target.getDocument(), SP_VERB_FILE_OPEN, "Opened File");
}
return TRUE;
}
gchar *
-document_interface_import (DocumentInterface *object,
+document_interface_import (DocumentInterface *doc_interface,
gchar *filename, GError **error)
{
- desktop_ensure_active (object->desk);
+ SPDesktop *desk = doc_interface->target.getDesktop();
+ if (desk) {
+ desktop_ensure_active(desk);
+ }
const Glib::ustring file(filename);
- SPDocument * doc = sp_desktop_document(object->desk);
+ SPDocument * doc = doc_interface->target.getDocument();
SPObject *new_obj = NULL;
new_obj = file_import(doc, file, NULL);
@@ -939,10 +964,11 @@ document_interface_import (DocumentInterface *object,
}
gboolean
-document_interface_save_as (DocumentInterface *object,
+document_interface_save_as (DocumentInterface *doc_interface,
const gchar *filename, GError **error)
{
- SPDocument * doc = sp_desktop_document(object->desk);
+ // FIXME: Isn't there a verb we can use for this instead?
+ SPDocument * doc = doc_interface->target.getDocument();
#ifdef WITH_GNOME_VFS
const Glib::ustring file(filename);
return file_save_remote(doc, file, NULL, TRUE, TRUE);
@@ -955,18 +981,16 @@ document_interface_save_as (DocumentInterface *object,
Inkscape::Extension::save(NULL, doc, filename,
false, false, true, Inkscape::Extension::FILE_SAVE_METHOD_SAVE_AS);
} catch (...) {
- //SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("Document not saved."));
+ // FIXME: catch ... is not usually a great idea, why is it needed here?
return false;
}
- //SP_ACTIVE_DESKTOP->event_log->rememberFileSave();
- //SP_ACTIVE_DESKTOP->messageStack()->flash(Inkscape::NORMAL_MESSAGE, "Document saved.");
return true;
}
-gboolean document_interface_mark_as_unmodified(DocumentInterface *object, GError ** /*error*/)
+gboolean document_interface_mark_as_unmodified(DocumentInterface *doc_interface, GError ** /*error*/)
{
- SPDocument * doc = sp_desktop_document(object->desk);
+ SPDocument * doc = doc_interface->target.getDocument();
if (doc) {
doc->modified_since_save = FALSE;
}
@@ -975,9 +999,9 @@ gboolean document_interface_mark_as_unmodified(DocumentInterface *object, GError
/*
gboolean
-document_interface_print_to_file (DocumentInterface *object, GError **error)
+document_interface_print_to_file (DocumentInterface *doc_interface, GError **error)
{
- SPDocument * doc = sp_desktop_document(object->desk);
+ SPDocument * doc = doc_interface->target.getDocument();
sp_print_document_to_file (doc, g_strdup("/home/soren/test.pdf"));
return TRUE;
@@ -988,27 +1012,27 @@ document_interface_print_to_file (DocumentInterface *object, GError **error)
****************************************************************************/
gboolean
-document_interface_close (DocumentInterface *object, GError **error)
+document_interface_close (DocumentInterface *doc_interface, GError **error)
{
- return dbus_call_verb (object, SP_VERB_FILE_CLOSE_VIEW, error);
+ return dbus_call_verb (doc_interface, SP_VERB_FILE_CLOSE_VIEW, error);
}
gboolean
-document_interface_exit (DocumentInterface *object, GError **error)
+document_interface_exit (DocumentInterface *doc_interface, GError **error)
{
- return dbus_call_verb (object, SP_VERB_FILE_QUIT, error);
+ return dbus_call_verb (doc_interface, SP_VERB_FILE_QUIT, error);
}
gboolean
-document_interface_undo (DocumentInterface *object, GError **error)
+document_interface_undo (DocumentInterface *doc_interface, GError **error)
{
- return dbus_call_verb (object, SP_VERB_EDIT_UNDO, error);
+ return dbus_call_verb (doc_interface, SP_VERB_EDIT_UNDO, error);
}
gboolean
-document_interface_redo (DocumentInterface *object, GError **error)
+document_interface_redo (DocumentInterface *doc_interface, GError **error)
{
- return dbus_call_verb (object, SP_VERB_EDIT_REDO, error);
+ return dbus_call_verb (doc_interface, SP_VERB_EDIT_REDO, error);
}
@@ -1020,48 +1044,46 @@ document_interface_redo (DocumentInterface *object, GError **error)
Need to make sure it plays well with verbs because they are used so much.
****************************************************************************/
-void document_interface_pause_updates(DocumentInterface *object, GError ** /*error*/)
+void document_interface_pause_updates(DocumentInterface *doc_interface, GError ** error)
{
- object->updates = FALSE;
- object->desk->canvas->drawing_disabled = 1;
- //object->desk->canvas->need_redraw = 0;
- //object->desk->canvas->need_repick = 0;
- //sp_desktop_document(object->desk)->root->uflags = FALSE;
- //sp_desktop_document(object->desk)->root->mflags = FALSE;
+ SPDesktop *desk = doc_interface->target.getDesktop();
+ g_return_if_fail(ensure_desktop_valid(desk, error));
+ doc_interface->updates = FALSE;
+ desk->canvas->drawing_disabled = 1;
}
-void document_interface_resume_updates(DocumentInterface *object, GError ** /*error*/)
+void document_interface_resume_updates(DocumentInterface *doc_interface, GError ** error)
{
- object->updates = TRUE;
- object->desk->canvas->drawing_disabled = 0;
- //object->desk->canvas->need_redraw = 1;
- //object->desk->canvas->need_repick = 1;
- //sp_desktop_document(object->desk)->root->uflags = TRUE;
- //sp_desktop_document(object->desk)->root->mflags = TRUE;
- //sp_desktop_document(object->desk)->_updateDocument();
+ SPDesktop *desk = doc_interface->target.getDesktop();
+ g_return_if_fail(ensure_desktop_valid(desk, error));
+ doc_interface->updates = TRUE;
+ desk->canvas->drawing_disabled = 0;
//FIXME: use better verb than rect.
- Inkscape::DocumentUndo::done(sp_desktop_document(object->desk), SP_VERB_CONTEXT_RECT, "Multiple actions");
+ Inkscape::DocumentUndo::done(doc_interface->target.getDocument(), SP_VERB_CONTEXT_RECT, "Multiple actions");
}
-void document_interface_update(DocumentInterface *object, GError ** /*error*/)
+void document_interface_update(DocumentInterface *doc_interface, GError ** error)
{
- sp_desktop_document(object->desk)->getRoot()->uflags = TRUE;
- sp_desktop_document(object->desk)->getRoot()->mflags = TRUE;
- object->desk->enableInteraction();
- sp_desktop_document(object->desk)->_updateDocument();
- object->desk->disableInteraction();
- sp_desktop_document(object->desk)->getRoot()->uflags = FALSE;
- sp_desktop_document(object->desk)->getRoot()->mflags = FALSE;
- //Inkscape::DocumentUndo::done(sp_desktop_document(object->desk), SP_VERB_CONTEXT_RECT, "Multiple actions");
+ SPDesktop *desk = doc_interface->target.getDesktop();
+ g_return_if_fail(ensure_desktop_valid(desk, error));
+ SPDocument *doc = doc_interface->target.getDocument();
+ doc->getRoot()->uflags = TRUE;
+ doc->getRoot()->mflags = TRUE;
+ desk->enableInteraction();
+ doc->_updateDocument();
+ desk->disableInteraction();
+ doc->getRoot()->uflags = FALSE;
+ doc->getRoot()->mflags = FALSE;
+ //Inkscape::DocumentUndo::done(doc, SP_VERB_CONTEXT_RECT, "Multiple actions");
}
/****************************************************************************
SELECTION FUNCTIONS FIXME: use call_verb where appropriate (once update system is tested.)
****************************************************************************/
-gboolean document_interface_selection_get(DocumentInterface *object, char ***out, GError ** /*error*/)
+gboolean document_interface_selection_get(DocumentInterface *doc_interface, char ***out, GError ** /*error*/)
{
- Inkscape::Selection * sel = sp_desktop_selection(object->desk);
+ Inkscape::Selection * sel = doc_interface->target.getSelection();
GSList const *oldsel = sel->list();
int size = g_slist_length((GSList *) oldsel);
@@ -1079,85 +1101,82 @@ gboolean document_interface_selection_get(DocumentInterface *object, char ***out
}
gboolean
-document_interface_selection_add (DocumentInterface *object, char *name, GError **error)
+document_interface_selection_add (DocumentInterface *doc_interface, char *name, GError **error)
{
- SPObject * obj = get_object_by_name(object->desk, name, error);
+ SPObject * obj = get_object_by_name(doc_interface->target.getDocument(), name, error);
if (!obj)
return FALSE;
- Inkscape::Selection *selection = sp_desktop_selection(object->desk);
+ Inkscape::Selection *selection = doc_interface->target.getSelection();
selection->add(obj);
return TRUE;
}
gboolean
-document_interface_selection_add_list (DocumentInterface *object,
+document_interface_selection_add_list (DocumentInterface *doc_interface,
char **names, GError **error)
{
int i;
for (i=0;names[i] != NULL;i++) {
- document_interface_selection_add(object, names[i], error);
+ document_interface_selection_add(doc_interface, names[i], error);
}
return TRUE;
}
-gboolean document_interface_selection_set(DocumentInterface *object, char *name, GError ** /*error*/)
+gboolean document_interface_selection_set(DocumentInterface *doc_interface, char *name, GError ** /*error*/)
{
- SPDocument * doc = sp_desktop_document(object->desk);
- Inkscape::Selection *selection = sp_desktop_selection(object->desk);
+ SPDocument * doc = doc_interface->target.getDocument();
+ Inkscape::Selection *selection = doc_interface->target.getSelection();
selection->set(doc->getObjectById(name));
return TRUE;
}
gboolean
-document_interface_selection_set_list (DocumentInterface *object,
+document_interface_selection_set_list (DocumentInterface *doc_interface,
gchar **names, GError **error)
{
- sp_desktop_selection(object->desk)->clear();
+ doc_interface->target.getSelection()->clear();
int i;
for (i=0;names[i] != NULL;i++) {
- document_interface_selection_add(object, names[i], error);
+ document_interface_selection_add(doc_interface, names[i], error);
}
return TRUE;
}
-gboolean document_interface_selection_rotate(DocumentInterface *object, int angle, GError ** /*error*/)
+gboolean document_interface_selection_rotate(DocumentInterface *doc_interface, int angle, GError ** /*error*/)
{
- Inkscape::Selection *selection = sp_desktop_selection(object->desk);
+ Inkscape::Selection *selection = doc_interface->target.getSelection();
sp_selection_rotate(selection, angle);
return TRUE;
}
gboolean
-document_interface_selection_delete (DocumentInterface *object, GError **error)
+document_interface_selection_delete (DocumentInterface *doc_interface, GError **error)
{
- //sp_selection_delete (object->desk);
- return dbus_call_verb (object, SP_VERB_EDIT_DELETE, error);
+ return dbus_call_verb (doc_interface, SP_VERB_EDIT_DELETE, error);
}
-gboolean document_interface_selection_clear(DocumentInterface *object, GError ** /*error*/)
+gboolean document_interface_selection_clear(DocumentInterface *doc_interface, GError ** /*error*/)
{
- sp_desktop_selection(object->desk)->clear();
+ doc_interface->target.getSelection()->clear();
return TRUE;
}
gboolean
-document_interface_select_all (DocumentInterface *object, GError **error)
+document_interface_select_all (DocumentInterface *doc_interface, GError **error)
{
- //sp_edit_select_all (object->desk);
- return dbus_call_verb (object, SP_VERB_EDIT_SELECT_ALL, error);
+ return dbus_call_verb (doc_interface, SP_VERB_EDIT_SELECT_ALL, error);
}
gboolean
-document_interface_select_all_in_all_layers(DocumentInterface *object,
+document_interface_select_all_in_all_layers(DocumentInterface *doc_interface,
GError **error)
{
- //sp_edit_select_all_in_all_layers (object->desk);
- return dbus_call_verb (object, SP_VERB_EDIT_SELECT_ALL_IN_ALL_LAYERS, error);
+ return dbus_call_verb (doc_interface, SP_VERB_EDIT_SELECT_ALL_IN_ALL_LAYERS, error);
}
-gboolean document_interface_selection_box(DocumentInterface * /*object*/, int /*x*/, int /*y*/,
+gboolean document_interface_selection_box(DocumentInterface * /*doc_interface*/, int /*x*/, int /*y*/,
int /*x2*/, int /*y2*/, gboolean /*replace*/,
GError ** /*error*/)
{
@@ -1166,63 +1185,49 @@ gboolean document_interface_selection_box(DocumentInterface * /*object*/, int /*
}
gboolean
-document_interface_selection_invert (DocumentInterface *object, GError **error)
+document_interface_selection_invert (DocumentInterface *doc_interface, GError **error)
{
- //sp_edit_invert (object->desk);
- return dbus_call_verb (object, SP_VERB_EDIT_INVERT, error);
+ return dbus_call_verb (doc_interface, SP_VERB_EDIT_INVERT, error);
}
gboolean
-document_interface_selection_group (DocumentInterface *object, GError **error)
+document_interface_selection_group (DocumentInterface *doc_interface, GError **error)
{
- //sp_selection_group (object->desk);
- return dbus_call_verb (object, SP_VERB_SELECTION_GROUP, error);
+ return dbus_call_verb (doc_interface, SP_VERB_SELECTION_GROUP, error);
}
gboolean
-document_interface_selection_ungroup (DocumentInterface *object, GError **error)
+document_interface_selection_ungroup (DocumentInterface *doc_interface, GError **error)
{
- //sp_selection_ungroup (object->desk);
- return dbus_call_verb (object, SP_VERB_SELECTION_UNGROUP, error);
+ return dbus_call_verb (doc_interface, SP_VERB_SELECTION_UNGROUP, error);
}
gboolean
-document_interface_selection_cut (DocumentInterface *object, GError **error)
+document_interface_selection_cut (DocumentInterface *doc_interface, GError **error)
{
- //desktop_ensure_active (object->desk);
- //sp_selection_cut (object->desk);
- return dbus_call_verb (object, SP_VERB_EDIT_CUT, error);
+ SPDesktop *desk = doc_interface->target.getDesktop();
+ g_return_val_if_fail(ensure_desktop_valid(desk, error), FALSE);
+ return dbus_call_verb (doc_interface, SP_VERB_EDIT_CUT, error);
}
gboolean
-document_interface_selection_copy (DocumentInterface *object, GError **error)
+document_interface_selection_copy (DocumentInterface *doc_interface, GError **error)
{
- //desktop_ensure_active (object->desk);
- //sp_selection_copy ();
- return dbus_call_verb (object, SP_VERB_EDIT_COPY, error);
-}
-/*
-gboolean
-document_interface_selection_paste (DocumentInterface *object, GError **error)
-{
- desktop_ensure_active (object->desk);
- if (!object->updates)
- document_interface_pause_updates (object, error);
- sp_selection_paste (object->desk, TRUE);
- if (!object->updates)
- document_interface_pause_updates (object, error);
- return TRUE;
- //return dbus_call_verb (object, SP_VERB_EDIT_PASTE, error);
+ SPDesktop *desk = doc_interface->target.getDesktop();
+ g_return_val_if_fail(ensure_desktop_valid(desk, error), FALSE);
+ return dbus_call_verb (doc_interface, SP_VERB_EDIT_COPY, error);
}
-*/
+
gboolean
-document_interface_selection_paste (DocumentInterface *object, GError **error)
+document_interface_selection_paste (DocumentInterface *doc_interface, GError **error)
{
- return dbus_call_verb (object, SP_VERB_EDIT_PASTE, error);
+ SPDesktop *desk = doc_interface->target.getDesktop();
+ g_return_val_if_fail(ensure_desktop_valid(desk, error), FALSE);
+ return dbus_call_verb (doc_interface, SP_VERB_EDIT_PASTE, error);
}
-gboolean document_interface_selection_scale(DocumentInterface *object, gdouble grow, GError ** /*error*/)
+gboolean document_interface_selection_scale(DocumentInterface *doc_interface, gdouble grow, GError ** /*error*/)
{
- Inkscape::Selection *selection = sp_desktop_selection(object->desk);
+ Inkscape::Selection *selection = doc_interface->target.getSelection();
if (!selection)
{
return FALSE;
@@ -1231,15 +1236,15 @@ gboolean document_interface_selection_scale(DocumentInterface *object, gdouble g
return TRUE;
}
-gboolean document_interface_selection_move(DocumentInterface *object, gdouble x, gdouble y, GError ** /*error*/)
+gboolean document_interface_selection_move(DocumentInterface *doc_interface, gdouble x, gdouble y, GError ** /*error*/)
{
- sp_selection_move(object->desk, x, 0 - y); //switching coordinate systems.
+ sp_selection_move(doc_interface->target.getSelection(), x, 0 - y); //switching coordinate systems.
return TRUE;
}
-gboolean document_interface_selection_move_to(DocumentInterface *object, gdouble x, gdouble y, GError ** /*error*/)
+gboolean document_interface_selection_move_to(DocumentInterface *doc_interface, gdouble x, gdouble y, GError ** /*error*/)
{
- Inkscape::Selection * sel = sp_desktop_selection(object->desk);
+ Inkscape::Selection * sel = doc_interface->target.getSelection();
Geom::OptRect sel_bbox = sel->visualBounds();
if (sel_bbox) {
@@ -1253,18 +1258,19 @@ gboolean document_interface_selection_move_to(DocumentInterface *object, gdouble
// This needs to use lower level cut_impl and paste_impl (messy)
// See the built-in sp_selection_to_next_layer and duplicate.
gboolean
-document_interface_selection_move_to_layer (DocumentInterface *object,
+document_interface_selection_move_to_layer (DocumentInterface *doc_interface,
gchar *layerstr, GError **error)
{
- SPDesktop * dt = object->desk;
+ SPDesktop *dt = doc_interface->target.getDesktop();
+ g_return_val_if_fail(ensure_desktop_valid(dt, error), FALSE);
- Inkscape::Selection *selection = sp_desktop_selection(dt);
+ Inkscape::Selection *selection = doc_interface->target.getSelection();
// check if something is selected
if (selection->isEmpty())
return FALSE;
- SPObject *next = get_object_by_name(object->desk, layerstr, error);
+ SPObject *next = get_object_by_name(doc_interface->target.getDocument(), layerstr, error);
if (!next)
return FALSE;
@@ -1273,7 +1279,7 @@ document_interface_selection_move_to_layer (DocumentInterface *object,
sp_selection_cut(dt);
- dt->setCurrentLayer(next);
+ doc_interface->target.getSelection()->layers()->setCurrentLayer(next);
sp_selection_paste(dt, TRUE);
}
@@ -1281,9 +1287,9 @@ document_interface_selection_move_to_layer (DocumentInterface *object,
}
GArray *
-document_interface_selection_get_center (DocumentInterface *object)
+document_interface_selection_get_center (DocumentInterface *doc_interface)
{
- Inkscape::Selection * sel = sp_desktop_selection(object->desk);
+ Inkscape::Selection * sel = doc_interface->target.getSelection();
if (sel)
{
@@ -1300,52 +1306,46 @@ document_interface_selection_get_center (DocumentInterface *object)
}
gboolean
-document_interface_selection_to_path (DocumentInterface *object, GError **error)
+document_interface_selection_to_path (DocumentInterface *doc_interface, GError **error)
{
- return dbus_call_verb (object, SP_VERB_OBJECT_TO_CURVE, error);
+ return dbus_call_verb (doc_interface, SP_VERB_OBJECT_TO_CURVE, error);
}
-gchar *
-document_interface_selection_combine (DocumentInterface *object, gchar *cmd,
+gboolean
+document_interface_selection_combine (DocumentInterface *doc_interface, gchar *cmd, char ***newpaths,
GError **error)
{
if (strcmp(cmd, "union") == 0)
- dbus_call_verb (object, SP_VERB_SELECTION_UNION, error);
+ dbus_call_verb (doc_interface, SP_VERB_SELECTION_UNION, error);
else if (strcmp(cmd, "intersection") == 0)
- dbus_call_verb (object, SP_VERB_SELECTION_INTERSECT, error);
+ dbus_call_verb (doc_interface, SP_VERB_SELECTION_INTERSECT, error);
else if (strcmp(cmd, "difference") == 0)
- dbus_call_verb (object, SP_VERB_SELECTION_DIFF, error);
+ dbus_call_verb (doc_interface, SP_VERB_SELECTION_DIFF, error);
else if (strcmp(cmd, "exclusion") == 0)
- dbus_call_verb (object, SP_VERB_SELECTION_SYMDIFF, error);
- else
- return NULL;
-
- if (sp_desktop_selection(object->desk)->singleRepr() != NULL)
- return g_strdup((sp_desktop_selection(object->desk)->singleRepr())->attribute("id"));
- return NULL;
-}
-
-gboolean
-document_interface_selection_divide (DocumentInterface *object, char ***out, GError **error)
-{
- dbus_call_verb (object, SP_VERB_SELECTION_CUT, error);
+ dbus_call_verb (doc_interface, SP_VERB_SELECTION_SYMDIFF, error);
+ else if (strcmp(cmd, "division") == 0)
+ dbus_call_verb (doc_interface, SP_VERB_SELECTION_CUT, error);
+ else {
+ g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OTHER, "Operation command not recognised");
+ return FALSE;
+ }
- return document_interface_selection_get (object, out, error);
+ return document_interface_selection_get (doc_interface, newpaths, error);
}
gboolean
-document_interface_selection_change_level (DocumentInterface *object, gchar *cmd,
+document_interface_selection_change_level (DocumentInterface *doc_interface, gchar *cmd,
GError **error)
{
if (strcmp(cmd, "raise") == 0)
- return dbus_call_verb (object, SP_VERB_SELECTION_RAISE, error);
+ return dbus_call_verb (doc_interface, SP_VERB_SELECTION_RAISE, error);
if (strcmp(cmd, "lower") == 0)
- return dbus_call_verb (object, SP_VERB_SELECTION_LOWER, error);
+ return dbus_call_verb (doc_interface, SP_VERB_SELECTION_LOWER, error);
if ((strcmp(cmd, "to_top") == 0) || (strcmp(cmd, "to_front") == 0))
- return dbus_call_verb (object, SP_VERB_SELECTION_TO_FRONT, error);
+ return dbus_call_verb (doc_interface, SP_VERB_SELECTION_TO_FRONT, error);
if ((strcmp(cmd, "to_bottom") == 0) || (strcmp(cmd, "to_back") == 0))
- return dbus_call_verb (object, SP_VERB_SELECTION_TO_BACK, error);
+ return dbus_call_verb (doc_interface, SP_VERB_SELECTION_TO_BACK, error);
return TRUE;
}
@@ -1353,58 +1353,58 @@ document_interface_selection_change_level (DocumentInterface *object, gchar *cmd
LAYER FUNCTIONS
****************************************************************************/
-gchar *document_interface_layer_new(DocumentInterface *object, GError ** /*error*/)
+gchar *document_interface_layer_new(DocumentInterface *doc_interface, GError ** /*error*/)
{
- SPDesktop * dt = object->desk;
- SPObject *new_layer = Inkscape::create_layer(dt->currentRoot(), dt->currentLayer(), Inkscape::LPOS_BELOW);
- dt->setCurrentLayer(new_layer);
+ 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);
return g_strdup(get_name_from_object(new_layer));
}
gboolean
-document_interface_layer_set (DocumentInterface *object,
+document_interface_layer_set (DocumentInterface *doc_interface,
gchar *layerstr, GError **error)
{
- SPObject * obj = get_object_by_name (object->desk, layerstr, error);
+ SPObject * obj = get_object_by_name (doc_interface->target.getDocument(), layerstr, error);
if (!obj)
return FALSE;
- object->desk->setCurrentLayer (obj);
+ doc_interface->target.getSelection()->layers()->setCurrentLayer (obj);
return TRUE;
}
-gchar **document_interface_layer_get_all(DocumentInterface * /*object*/)
+gchar **document_interface_layer_get_all(DocumentInterface * /*doc_interface*/)
{
//FIXME: implement.
return NULL;
}
gboolean
-document_interface_layer_change_level (DocumentInterface *object,
+document_interface_layer_change_level (DocumentInterface *doc_interface,
gchar *cmd, GError **error)
{
if (strcmp(cmd, "raise") == 0)
- return dbus_call_verb (object, SP_VERB_LAYER_RAISE, error);
+ return dbus_call_verb (doc_interface, SP_VERB_LAYER_RAISE, error);
if (strcmp(cmd, "lower") == 0)
- return dbus_call_verb (object, SP_VERB_LAYER_LOWER, error);
+ return dbus_call_verb (doc_interface, SP_VERB_LAYER_LOWER, error);
if ((strcmp(cmd, "to_top") == 0) || (strcmp(cmd, "to_front") == 0))
- return dbus_call_verb (object, SP_VERB_LAYER_TO_TOP, error);
+ return dbus_call_verb (doc_interface, SP_VERB_LAYER_TO_TOP, error);
if ((strcmp(cmd, "to_bottom") == 0) || (strcmp(cmd, "to_back") == 0))
- return dbus_call_verb (object, SP_VERB_LAYER_TO_BOTTOM, error);
+ return dbus_call_verb (doc_interface, SP_VERB_LAYER_TO_BOTTOM, error);
return TRUE;
}
gboolean
-document_interface_layer_next (DocumentInterface *object, GError **error)
+document_interface_layer_next (DocumentInterface *doc_interface, GError **error)
{
- return dbus_call_verb (object, SP_VERB_LAYER_NEXT, error);
+ return dbus_call_verb (doc_interface, SP_VERB_LAYER_NEXT, error);
}
gboolean
-document_interface_layer_previous (DocumentInterface *object, GError **error)
+document_interface_layer_previous (DocumentInterface *doc_interface, GError **error)
{
- return dbus_call_verb (object, SP_VERB_LAYER_PREV, error);
+ return dbus_call_verb (doc_interface, SP_VERB_LAYER_PREV, error);
}
@@ -1414,7 +1414,6 @@ document_interface_layer_previous (DocumentInterface *object, GError **error)
DocumentInterface *fugly;
gboolean dbus_send_ping (SPDesktop* desk, SPItem *item)
{
- //DocumentInterface *obj;
if (!item) return TRUE;
g_signal_emit (desk->dbus_document_interface, signals[OBJECT_MOVED_SIGNAL], 0, item->getId());
return TRUE;
@@ -1424,9 +1423,9 @@ gboolean dbus_send_ping (SPDesktop* desk, SPItem *item)
gboolean
-document_interface_get_children (DocumentInterface *object, char *name, char ***out, GError **error)
+document_interface_get_children (DocumentInterface *doc_interface, char *name, char ***out, GError **error)
{
- SPItem* parent=(SPItem* )get_object_by_name(object->desk, name, error);
+ SPItem* parent=(SPItem* )get_object_by_name(doc_interface->target.getDocument(), name, error);
GSList const *children = parent->childList(false);
@@ -1447,9 +1446,9 @@ document_interface_get_children (DocumentInterface *object, char *name, char **
gchar*
-document_interface_get_parent (DocumentInterface *object, char *name, GError **error)
+document_interface_get_parent (DocumentInterface *doc_interface, char *name, GError **error)
{
- SPItem* node=(SPItem* )get_object_by_name(object->desk, name, error);
+ SPItem* node=(SPItem* )get_object_by_name(doc_interface->target.getDocument(), name, error);
SPObject* parent=node->parent;
@@ -1460,8 +1459,8 @@ document_interface_get_parent (DocumentInterface *object, char *name, GError **
#if 0
//just pseudo code
gboolean
-document_interface_get_xpath (DocumentInterface *object, char *xpath_expression, char ***out, GError **error){
- SPDocument * doc = sp_desktop_document (object->desk);
+document_interface_get_xpath (DocumentInterface *doc_interface, char *xpath_expression, char ***out, GError **error){
+ SPDocument * doc = doc_interface->target.getDocument();
Inkscape::XML::Document *repr = doc->getReprDoc();
xmlXPathObjectPtr xpathObj;
diff --git a/src/extension/dbus/document-interface.h b/src/extension/dbus/document-interface.h
index 5fcbb919b..27460de52 100644
--- a/src/extension/dbus/document-interface.h
+++ b/src/extension/dbus/document-interface.h
@@ -30,9 +30,10 @@
#undef DBUS_MESSAGE_TYPE_ERROR
#undef DBUS_MESSAGE_TYPE_SIGNAL
-#include "desktop.h"
+#include "helper/action-context.h"
-#define DBUS_DOCUMENT_INTERFACE_PATH "/org/inkscape/document"
+class SPDesktop;
+class SPItem;
#define TYPE_DOCUMENT_INTERFACE (document_interface_get_type ())
#define DOCUMENT_INTERFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TYPE_DOCUMENT_INTERFACE, DocumentInterface))
@@ -47,8 +48,8 @@ typedef struct _DocumentInterface DocumentInterface;
typedef struct _DocumentInterfaceClass DocumentInterfaceClass;
struct _DocumentInterface {
- GObject parent;
- SPDesktop *desk;
+ GObject parent;
+ Inkscape::ActionContext target; ///< stores information about which document, selection, desktop etc this interface is linked to
gboolean updates;
};
@@ -67,10 +68,10 @@ struct DBUSPoint {
****************************************************************************/
gboolean
-document_interface_delete_all (DocumentInterface *object, GError **error);
+document_interface_delete_all (DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_call_verb (DocumentInterface *object,
+document_interface_call_verb (DocumentInterface *doc_interface,
gchar *verbid, GError **error);
/****************************************************************************
@@ -78,48 +79,48 @@ document_interface_call_verb (DocumentInterface *object,
****************************************************************************/
gchar*
-document_interface_rectangle (DocumentInterface *object, int x, int y,
+document_interface_rectangle (DocumentInterface *doc_interface, int x, int y,
int width, int height, GError **error);
gchar*
-document_interface_ellipse (DocumentInterface *object, int x, int y,
+document_interface_ellipse (DocumentInterface *doc_interface, int x, int y,
int width, int height, GError **error);
gchar*
-document_interface_polygon (DocumentInterface *object, int cx, int cy,
+document_interface_polygon (DocumentInterface *doc_interface, int cx, int cy,
int radius, int rotation, int sides,
GError **error);
gchar*
-document_interface_star (DocumentInterface *object, int cx, int cy,
+document_interface_star (DocumentInterface *doc_interface, int cx, int cy,
int r1, int r2, int sides, gdouble rounded,
gdouble arg1, gdouble arg2, GError **error);
gchar*
-document_interface_spiral (DocumentInterface *object, int cx, int cy,
+document_interface_spiral (DocumentInterface *doc_interface, int cx, int cy,
int r, int revolutions, GError **error);
gchar*
-document_interface_line (DocumentInterface *object, int x, int y,
+document_interface_line (DocumentInterface *doc_interface, int x, int y,
int x2, int y2, GError **error);
gchar*
-document_interface_text (DocumentInterface *object, int x, int y,
+document_interface_text (DocumentInterface *doc_interface, int x, int y,
gchar *text, GError **error);
gboolean
-document_interface_set_text (DocumentInterface *object, gchar *name,
+document_interface_set_text (DocumentInterface *doc_interface, gchar *name,
gchar *text, GError **error);
gboolean
-document_interface_text_apply_style (DocumentInterface *object, gchar *name,
+document_interface_text_apply_style (DocumentInterface *doc_interface, gchar *name,
int start_pos, int end_pos, gchar *style, gchar *styleval,
GError **error);
gchar *
-document_interface_image (DocumentInterface *object, int x, int y,
+document_interface_image (DocumentInterface *doc_interface, int x, int y,
gchar *filename, GError **error);
gchar*
-document_interface_node (DocumentInterface *object, gchar *svgtype,
+document_interface_node (DocumentInterface *doc_interface, gchar *svgtype,
GError **error);
@@ -127,27 +128,27 @@ document_interface_node (DocumentInterface *object, gchar *svgtype,
ENVIORNMENT FUNCTIONS
****************************************************************************/
gdouble
-document_interface_document_get_width (DocumentInterface *object);
+document_interface_document_get_width (DocumentInterface *doc_interface);
gdouble
-document_interface_document_get_height (DocumentInterface *object);
+document_interface_document_get_height (DocumentInterface *doc_interface);
gchar *
-document_interface_document_get_css (DocumentInterface *object, GError **error);
+document_interface_document_get_css (DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_document_merge_css (DocumentInterface *object,
+document_interface_document_merge_css (DocumentInterface *doc_interface,
gchar *stylestring, GError **error);
gboolean
-document_interface_document_set_css (DocumentInterface *object,
+document_interface_document_set_css (DocumentInterface *doc_interface,
gchar *stylestring, GError **error);
gboolean
-document_interface_document_resize_to_fit_selection (DocumentInterface *object,
+document_interface_document_resize_to_fit_selection (DocumentInterface *doc_interface,
GError **error);
gboolean
-document_interface_document_set_display_area (DocumentInterface *object,
+document_interface_document_set_display_area (DocumentInterface *doc_interface,
double x0,
double y0,
double x1,
@@ -155,95 +156,95 @@ document_interface_document_set_display_area (DocumentInterface *object,
double border,
GError **error);
GArray *
-document_interface_document_get_display_area (DocumentInterface *object);
+document_interface_document_get_display_area (DocumentInterface *doc_interface);
/****************************************************************************
OBJECT FUNCTIONS
****************************************************************************/
gboolean
-document_interface_set_attribute (DocumentInterface *object,
+document_interface_set_attribute (DocumentInterface *doc_interface,
char *shape, char *attribute,
char *newval, GError **error);
gboolean
-document_interface_set_int_attribute (DocumentInterface *object,
+document_interface_set_int_attribute (DocumentInterface *doc_interface,
char *shape, char *attribute,
int newval, GError **error);
gboolean
-document_interface_set_double_attribute (DocumentInterface *object,
+document_interface_set_double_attribute (DocumentInterface *doc_interface,
char *shape, char *attribute,
double newval, GError **error);
gchar *
-document_interface_get_attribute (DocumentInterface *object,
+document_interface_get_attribute (DocumentInterface *doc_interface,
char *shape, char *attribute, GError **error);
gboolean
-document_interface_move (DocumentInterface *object, gchar *name,
+document_interface_move (DocumentInterface *doc_interface, gchar *name,
gdouble x, gdouble y, GError **error);
gboolean
-document_interface_move_to (DocumentInterface *object, gchar *name,
+document_interface_move_to (DocumentInterface *doc_interface, gchar *name,
gdouble x, gdouble y, GError **error);
gboolean
-document_interface_object_to_path (DocumentInterface *object,
+document_interface_object_to_path (DocumentInterface *doc_interface,
char *shape, GError **error);
gchar *
-document_interface_get_path (DocumentInterface *object,
+document_interface_get_path (DocumentInterface *doc_interface,
char *pathname, GError **error);
gboolean
-document_interface_transform (DocumentInterface *object, gchar *shape,
+document_interface_transform (DocumentInterface *doc_interface, gchar *shape,
gchar *transformstr, GError **error);
gchar *
-document_interface_get_css (DocumentInterface *object, gchar *shape,
+document_interface_get_css (DocumentInterface *doc_interface, gchar *shape,
GError **error);
gboolean
-document_interface_modify_css (DocumentInterface *object, gchar *shape,
+document_interface_modify_css (DocumentInterface *doc_interface, gchar *shape,
gchar *cssattrb, gchar *newval, GError **error);
gboolean
-document_interface_merge_css (DocumentInterface *object, gchar *shape,
+document_interface_merge_css (DocumentInterface *doc_interface, gchar *shape,
gchar *stylestring, GError **error);
gboolean
-document_interface_set_color (DocumentInterface *object, gchar *shape,
+document_interface_set_color (DocumentInterface *doc_interface, gchar *shape,
int r, int g, int b, gboolean fill, GError **error);
gboolean
-document_interface_move_to_layer (DocumentInterface *object, gchar *shape,
+document_interface_move_to_layer (DocumentInterface *doc_interface, gchar *shape,
gchar *layerstr, GError **error);
GArray *
-document_interface_get_node_coordinates (DocumentInterface *object, gchar *shape);
+document_interface_get_node_coordinates (DocumentInterface *doc_interface, gchar *shape);
/****************************************************************************
FILE I/O FUNCTIONS
****************************************************************************/
gboolean
-document_interface_save (DocumentInterface *object, GError **error);
+document_interface_save (DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_load (DocumentInterface *object,
+document_interface_load (DocumentInterface *doc_interface,
gchar *filename, GError **error);
gboolean
-document_interface_save_as (DocumentInterface *object,
+document_interface_save_as (DocumentInterface *doc_interface,
const gchar *filename, GError **error);
gboolean
-document_interface_mark_as_unmodified (DocumentInterface *object, GError **error);
+document_interface_mark_as_unmodified (DocumentInterface *doc_interface, GError **error);
/*
gboolean
-document_interface_print_to_file (DocumentInterface *object, GError **error);
+document_interface_print_to_file (DocumentInterface *doc_interface, GError **error);
*/
/****************************************************************************
@@ -251,125 +252,120 @@ document_interface_print_to_file (DocumentInterface *object, GError **error);
****************************************************************************/
gboolean
-document_interface_close (DocumentInterface *object, GError **error);
+document_interface_close (DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_exit (DocumentInterface *object, GError **error);
+document_interface_exit (DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_undo (DocumentInterface *object, GError **error);
+document_interface_undo (DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_redo (DocumentInterface *object, GError **error);
+document_interface_redo (DocumentInterface *doc_interface, GError **error);
/****************************************************************************
UPDATE FUNCTIONS
****************************************************************************/
void
-document_interface_pause_updates (DocumentInterface *object, GError **error);
+document_interface_pause_updates (DocumentInterface *doc_interface, GError **error);
void
-document_interface_resume_updates (DocumentInterface *object, GError **error);
+document_interface_resume_updates (DocumentInterface *doc_interface, GError **error);
void
-document_interface_update (DocumentInterface *object, GError **error);
+document_interface_update (DocumentInterface *doc_interface, GError **error);
/****************************************************************************
SELECTION FUNCTIONS
****************************************************************************/
gboolean
-document_interface_selection_get (DocumentInterface *object, char ***out, GError **error);
+document_interface_selection_get (DocumentInterface *doc_interface, char ***out, GError **error);
gboolean
-document_interface_selection_add (DocumentInterface *object,
+document_interface_selection_add (DocumentInterface *doc_interface,
char *name, GError **error);
gboolean
-document_interface_selection_add_list (DocumentInterface *object,
+document_interface_selection_add_list (DocumentInterface *doc_interface,
char **names, GError **error);
gboolean
-document_interface_selection_set (DocumentInterface *object,
+document_interface_selection_set (DocumentInterface *doc_interface,
char *name, GError **error);
gboolean
-document_interface_selection_set_list (DocumentInterface *object,
+document_interface_selection_set_list (DocumentInterface *doc_interface,
gchar **names, GError **error);
gboolean
-document_interface_selection_rotate (DocumentInterface *object,
+document_interface_selection_rotate (DocumentInterface *doc_interface,
int angle, GError **error);
gboolean
-document_interface_selection_delete(DocumentInterface *object, GError **error);
+document_interface_selection_delete(DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_selection_clear(DocumentInterface *object, GError **error);
+document_interface_selection_clear(DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_select_all(DocumentInterface *object, GError **error);
+document_interface_select_all(DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_select_all_in_all_layers(DocumentInterface *object,
+document_interface_select_all_in_all_layers(DocumentInterface *doc_interface,
GError **error);
gboolean
-document_interface_selection_box (DocumentInterface *object, int x, int y,
+document_interface_selection_box (DocumentInterface *doc_interface, int x, int y,
int x2, int y2, gboolean replace,
GError **error);
gboolean
-document_interface_selection_invert (DocumentInterface *object, GError **error);
+document_interface_selection_invert (DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_selection_group(DocumentInterface *object, GError **error);
+document_interface_selection_group(DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_selection_ungroup(DocumentInterface *object, GError **error);
+document_interface_selection_ungroup(DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_selection_cut(DocumentInterface *object, GError **error);
+document_interface_selection_cut(DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_selection_copy(DocumentInterface *object, GError **error);
+document_interface_selection_copy(DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_selection_paste(DocumentInterface *object, GError **error);
+document_interface_selection_paste(DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_selection_scale (DocumentInterface *object,
+document_interface_selection_scale (DocumentInterface *doc_interface,
gdouble grow, GError **error);
gboolean
-document_interface_selection_move (DocumentInterface *object, gdouble x,
+document_interface_selection_move (DocumentInterface *doc_interface, gdouble x,
gdouble y, GError **error);
gboolean
-document_interface_selection_move_to (DocumentInterface *object, gdouble x,
+document_interface_selection_move_to (DocumentInterface *doc_interface, gdouble x,
gdouble y, GError **error);
gboolean
-document_interface_selection_move_to_layer (DocumentInterface *object,
+document_interface_selection_move_to_layer (DocumentInterface *doc_interface,
gchar *layerstr, GError **error);
GArray *
-document_interface_selection_get_center (DocumentInterface *object);
+document_interface_selection_get_center (DocumentInterface *doc_interface);
gboolean
-document_interface_selection_to_path (DocumentInterface *object, GError **error);
-
-gchar *
-document_interface_selection_combine (DocumentInterface *object, gchar *cmd,
- GError **error);
+document_interface_selection_to_path (DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_selection_divide (DocumentInterface *object,
- char ***out, GError **error);
-
+document_interface_selection_combine (DocumentInterface *doc_interface, gchar *cmd, char ***newpaths,
+ GError **error);
gboolean
-document_interface_selection_change_level (DocumentInterface *object, gchar *cmd,
+document_interface_selection_change_level (DocumentInterface *doc_interface, gchar *cmd,
GError **error);
/****************************************************************************
@@ -377,24 +373,24 @@ document_interface_selection_change_level (DocumentInterface *object, gchar *cmd
****************************************************************************/
gchar *
-document_interface_layer_new (DocumentInterface *object, GError **error);
+document_interface_layer_new (DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_layer_set (DocumentInterface *object,
+document_interface_layer_set (DocumentInterface *doc_interface,
gchar *layerstr, GError **error);
gchar **
-document_interface_layer_get_all (DocumentInterface *object);
+document_interface_layer_get_all (DocumentInterface *doc_interface);
gboolean
-document_interface_layer_change_level (DocumentInterface *object,
+document_interface_layer_change_level (DocumentInterface *doc_interface,
gchar *cmd, GError **error);
gboolean
-document_interface_layer_next (DocumentInterface *object, GError **error);
+document_interface_layer_next (DocumentInterface *doc_interface, GError **error);
gboolean
-document_interface_layer_previous (DocumentInterface *object, GError **error);
+document_interface_layer_previous (DocumentInterface *doc_interface, GError **error);
@@ -410,13 +406,13 @@ extern DocumentInterface *fugly;
gboolean dbus_send_ping (SPDesktop* desk, SPItem *item);
gboolean
-document_interface_get_children (DocumentInterface *object, char *name, char ***out, GError **error);
+document_interface_get_children (DocumentInterface *doc_interface, char *name, char ***out, GError **error);
gchar*
-document_interface_get_parent (DocumentInterface *object, char *name, GError **error);
+document_interface_get_parent (DocumentInterface *doc_interface, char *name, GError **error);
gchar*
-document_interface_import (DocumentInterface *object,
+document_interface_import (DocumentInterface *doc_interface,
gchar *filename, GError **error);
G_END_DECLS
diff --git a/src/extension/dbus/document-interface.xml b/src/extension/dbus/document-interface.xml
index aeacfae44..7481c0893 100644
--- a/src/extension/dbus/document-interface.xml
+++ b/src/extension/dbus/document-interface.xml
@@ -21,7 +21,7 @@
<node name="/org/inkscape/document"
xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd"
>
-
+c
<interface name="org.inkscape.document">
<!-- MISC FUNCTIONS -->
@@ -1348,36 +1348,20 @@
<doc:summary>Type of combination.</doc:summary>
</doc:doc>
</arg>
- <arg type="s" name="newpath" direction="out" >
- <annotation name="org.freedesktop.DBus.GLib.ReturnVal" value="error"/>
+ <arg type="as" name="newpaths" direction="out" >
<doc:doc>
- <doc:summary>The new path created, if there is one. NULL otherwise.</doc:summary>
+ <doc:summary>List of the ids of resulting paths after applying the operation.</doc:summary>
</doc:doc>
</arg>
<doc:doc>
<doc:description>
<doc:para>Will erase all objects in the selection and replace with a single aggregate path.</doc:para>
<doc:para>There are 5 types that can be passed in:</doc:para>
- <doc:para>Union: The new shape is all of the other shapes put together, even if they don't overlap (paths can have multiple non-contiguous areas.)</doc:para>
- <doc:para>Intersection: The new shape is composed of the area where ALL the objects in the selection overlap. If there is no area where all shapes overlap the new shape will be empty.</doc:para>
- <doc:para>Difference: The area of the second shape is subtracted from the first, only works with two objects.</doc:para>
- <doc:para>Exclusion: The new shape is the area(s) where none of the objects in the selection overlaped. Only works with two objects.</doc:para>
- <doc:para>Division: the first object is split into multiple segments by the second object. Only works with two objects and if multiple paths result they are grouped and the group id is returned.</doc:para>
- </doc:description>
- </doc:doc>
- </method>
-
- <method name="selection_divide">
- <arg type="as" name="pieces" direction="out" >
- <!-- <annotation name="org.freedesktop.DBus.GLib.ReturnVal" value=""/> -->
- <doc:doc>
- <doc:summary>List of the ids of resulting paths.</doc:summary>
- </doc:doc>
- </arg>
- <doc:doc>
- <doc:description>
- <doc:para>Returns the result of cutting the bottom object by all other intersecting paths.</doc:para>
- <doc:para>This may make many seperate layers.</doc:para>
+ <doc:para>'union': The new shape is all of the other shapes put together, even if they don't overlap (paths can have multiple non-contiguous areas.)</doc:para>
+ <doc:para>'intersection': The new shape is composed of the area where ALL the objects in the selection overlap. If there is no area where all shapes overlap the new shape will be empty.</doc:para>
+ <doc:para>'difference': The area of the second shape is subtracted from the first, only works with two objects.</doc:para>
+ <doc:para>'exclusion': The new shape is the area(s) where none of the objects in the selection overlaped. Only works with two objects.</doc:para>
+ <doc:para>'division': the first object is split into multiple segments by the second object. Only works with two objects.</doc:para>
</doc:description>
</doc:doc>
</method>
diff --git a/src/extension/dbus/wrapper/inkscape-dbus-wrapper.c b/src/extension/dbus/wrapper/inkscape-dbus-wrapper.c
index 0be1be42e..c7e453593 100644
--- a/src/extension/dbus/wrapper/inkscape-dbus-wrapper.c
+++ b/src/extension/dbus/wrapper/inkscape-dbus-wrapper.c
@@ -688,23 +688,13 @@ inkscape_selection_to_path (DocumentInterface *doc, GError **error)
}
//static
-char *
-inkscape_selection_combine (DocumentInterface *doc, const char * IN_type, GError **error)
-{
- char * OUT_newpath;
- DBusGProxy *proxy = doc->proxy;
- org_inkscape_document_selection_combine (proxy, IN_type, &OUT_newpath, error);
- return OUT_newpath;
-}
-
-//static
char **
-inkscape_selection_divide (DocumentInterface *doc, GError **error)
+inkscape_selection_combine (DocumentInterface *doc, const char * IN_type, GError **error)
{
- char ** OUT_pieces;
+ char ** OUT_newpaths;
DBusGProxy *proxy = doc->proxy;
- org_inkscape_document_selection_divide (proxy, &OUT_pieces, error);
- return OUT_pieces;
+ org_inkscape_document_selection_combine (proxy, IN_type, &OUT_newpaths, error);
+ return OUT_newpaths;
}
//static
diff --git a/src/extension/dbus/wrapper/inkscape-dbus-wrapper.h b/src/extension/dbus/wrapper/inkscape-dbus-wrapper.h
index 684f1b142..20830bd65 100644
--- a/src/extension/dbus/wrapper/inkscape-dbus-wrapper.h
+++ b/src/extension/dbus/wrapper/inkscape-dbus-wrapper.h
@@ -8,8 +8,6 @@
//#include <dbus/dbus-glib-bindings.h>
//#include <dbus/dbus-glib-lowlevel.h>
-
-#define DBUS_DOCUMENT_INTERFACE_PATH "/org/inkscape/document"
#define TYPE_DOCUMENT_INTERFACE (document_interface_get_type ())
#define DOCUMENT_INTERFACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TYPE_DOCUMENT_INTERFACE, DocumentInterface))
@@ -304,12 +302,8 @@ gboolean
inkscape_selection_to_path (DocumentInterface *doc, GError **error);
//static
-char *
-inkscape_selection_combine (DocumentInterface *doc, const char * IN_type, GError **error);
-
-//static
char **
-inkscape_selection_divide (DocumentInterface *doc, GError **error);
+inkscape_selection_combine (DocumentInterface *doc, const char * IN_type, GError **error);
//static
gboolean
diff --git a/src/extension/effect.cpp b/src/extension/effect.cpp
index 1df8002ad..dcccf3d7d 100644
--- a/src/extension/effect.cpp
+++ b/src/extension/effect.cpp
@@ -359,22 +359,22 @@ 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 */
void
Effect::EffectVerb::perform( SPAction *action, void * data )
{
+ g_return_if_fail(ensure_desktop_valid(action));
Inkscape::UI::View::View * current_view = sp_action_get_view(action);
-// SPDocument * current_document = current_view->doc;
+
Effect::EffectVerb * ev = reinterpret_cast<Effect::EffectVerb *>(data);
Effect * effect = ev->_effect;
if (effect == NULL) return;
- if (current_view == NULL) return;
if (ev->_showPrefs) {
effect->prefs(current_view);
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/file.cpp b/src/file.cpp
index 5b4110253..5007cd901 100644
--- a/src/file.cpp
+++ b/src/file.cpp
@@ -68,6 +68,7 @@
#include "ui/dialog/font-substitution.h"
#include <gtk/gtk.h>
+#include <gtkmm/main.h>
#include <glibmm/convert.h>
#include <glibmm/i18n.h>
@@ -209,8 +210,13 @@ SPDesktop* sp_file_new_default()
void
sp_file_exit()
{
- sp_ui_close_all();
- // no need to call inkscape_exit here; last document being closed will take care of that
+ if (SP_ACTIVE_DESKTOP == NULL) {
+ // We must be in console mode
+ Gtk::Main::quit();
+ } else {
+ sp_ui_close_all();
+ // no need to call inkscape_exit here; last document being closed will take care of that
+ }
}
@@ -582,24 +588,25 @@ sp_file_open_dialog(Gtk::Window &parentWindow, gpointer /*object*/, gpointer /*d
/**
* Remove unreferenced defs from the defs section of the document.
*/
-void sp_file_vacuum()
+void sp_file_vacuum(SPDocument *doc)
{
- SPDocument *doc = SP_ACTIVE_DOCUMENT;
-
unsigned int diff = doc->vacuumDocument();
DocumentUndo::done(doc, SP_VERB_FILE_VACUUM,
_("Clean up document"));
SPDesktop *dt = SP_ACTIVE_DESKTOP;
- if (diff > 0) {
- dt->messageStack()->flashF(Inkscape::NORMAL_MESSAGE,
- ngettext("Removed <b>%i</b> unused definition in &lt;defs&gt;.",
- "Removed <b>%i</b> unused definitions in &lt;defs&gt;.",
- diff),
- diff);
- } else {
- dt->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("No unused definitions in &lt;defs&gt;."));
+ if (dt != NULL) {
+ // Show status messages when in GUI mode
+ if (diff > 0) {
+ dt->messageStack()->flashF(Inkscape::NORMAL_MESSAGE,
+ ngettext("Removed <b>%i</b> unused definition in &lt;defs&gt;.",
+ "Removed <b>%i</b> unused definitions in &lt;defs&gt;.",
+ diff),
+ diff);
+ } else {
+ dt->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("No unused definitions in &lt;defs&gt;."));
+ }
}
}
diff --git a/src/file.h b/src/file.h
index fe8ad9af3..eeb4c6fc5 100644
--- a/src/file.h
+++ b/src/file.h
@@ -200,7 +200,7 @@ void sp_file_print (Gtk::Window& parentWindow);
/**
* clean unused defs out of file
*/
-void sp_file_vacuum ();
+void sp_file_vacuum (SPDocument *doc);
#endif // SEEN_SP_FILE_H
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-context.cpp b/src/helper/action-context.cpp
new file mode 100644
index 000000000..d52e43d96
--- /dev/null
+++ b/src/helper/action-context.cpp
@@ -0,0 +1,84 @@
+/*
+ * ActionContext implementation.
+ *
+ * Author:
+ * Eric Greveson <eric@greveson.co.uk>
+ *
+ * Copyright (C) 2013 Eric Greveson
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "desktop.h"
+#include "document.h"
+#include "layer-model.h"
+#include "selection.h"
+#include "helper/action-context.h"
+#include "ui/view/view.h"
+
+namespace Inkscape {
+
+ActionContext::ActionContext()
+ : _selection(NULL)
+ , _view(NULL)
+{
+}
+
+ActionContext::ActionContext(Selection *selection)
+ : _selection(selection)
+ , _view(NULL)
+{
+}
+
+ActionContext::ActionContext(UI::View::View *view)
+ : _selection(NULL)
+ , _view(view)
+{
+ SPDesktop *desktop = static_cast<SPDesktop *>(view);
+ if (desktop) {
+ _selection = desktop->selection;
+ }
+}
+
+SPDocument *ActionContext::getDocument() const
+{
+ if (_selection == NULL) {
+ return NULL;
+ }
+
+ // Should be the same as the view's document, if view is non-NULL
+ return _selection->layers()->getDocument();
+}
+
+Selection *ActionContext::getSelection() const
+{
+ return _selection;
+}
+
+UI::View::View *ActionContext::getView() const
+{
+ return _view;
+}
+
+SPDesktop *ActionContext::getDesktop() const
+{
+ // TODO: this slightly horrible storage of a UI::View::View*, and
+ // casting to an SPDesktop*, is only done because that's what was
+ // already the norm in the Inkscape codebase. This seems wrong. Surely
+ // we should store an SPDesktop* in the first place? Is there a case
+ // of actions being carried out on a View that is not an SPDesktop?
+ return static_cast<SPDesktop *>(_view);
+}
+
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/helper/action-context.h b/src/helper/action-context.h
new file mode 100644
index 000000000..bb538f413
--- /dev/null
+++ b/src/helper/action-context.h
@@ -0,0 +1,89 @@
+/** \file
+ * Inkscape UI action context implementation
+ *//*
+ * Author:
+ * Eric Greveson <eric@greveson.co.uk>
+ *
+ * Copyright (C) 2013 Eric Greveson
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_ACTION_CONTEXT_H
+#define SEEN_INKSCAPE_ACTION_CONTEXT_H
+
+class SPDesktop;
+class SPDocument;
+
+namespace Inkscape {
+
+class Selection;
+
+namespace UI {
+namespace View {
+class View;
+} // namespace View
+} // namespace UI
+
+/** This structure contains all the document/view context required
+ for an action. Some actions may be executed on a document without
+ requiring a GUI, hence not providing the info directly through
+ Inkscape::UI::View::View. Actions that do require GUI objects should
+ check to see if the relevant pointers are NULL before attempting to
+ use them.
+
+ TODO: we store a UI::View::View* because that's what the actions and verbs
+ used to take as parameters in their methods. Why is this? They almost
+ always seemed to cast straight to an SPDesktop* - so shouldn't we actually
+ be storing an SPDesktop*? Is there a case where a non-SPDesktop
+ UI::View::View is used by the actions?
+
+ ActionContext is designed to be copyable, so it may be used with stack
+ storage if required. */
+class ActionContext {
+ // NB: Only one of these is typically set - selection model if in console mode, view if in GUI mode
+ Selection *_selection; /**< The selection model to which this action applies, if running in console mode. May be NULL. */
+ UI::View::View *_view; /**< The view to which this action applies. May be NULL (e.g. if running in console mode). */
+
+public:
+ /** Construct without any document or GUI */
+ ActionContext();
+
+ /** Construct an action context for when the app is being run without
+ any GUI, i.e. in console mode */
+ ActionContext(Selection *selection);
+
+ /** Construct an action context for when the app is being run in GUI mode */
+ ActionContext(UI::View::View *view);
+
+ /** Get the document for the action context. May be NULL. Prefer this
+ function to getView()->doc() if the action doesn't require a GUI. */
+ SPDocument *getDocument() const;
+
+ /** Get the selection for the action context. May be NULL. Should be
+ non-NULL if getDocument() is non-NULL. */
+ Selection *getSelection() const;
+
+ /** Get the view for the action context. May be NULL. Guaranteed to be
+ NULL if running in console mode. */
+ UI::View::View *getView() const;
+
+ /** Get the desktop for the action context. May be NULL. Guaranteed to be
+ NULL if running in console mode. */
+ SPDesktop *getDesktop() const;
+};
+
+} // namespace Inkscape
+
+#endif
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/helper/action.cpp b/src/helper/action.cpp
index 0e9957ca3..28cb40334 100644
--- a/src/helper/action.cpp
+++ b/src/helper/action.cpp
@@ -16,6 +16,7 @@
#include "debug/simple-event.h"
#include "debug/event-tracker.h"
#include "ui/view/view.h"
+#include "desktop.h"
#include "document.h"
#include "helper/action.h"
@@ -41,7 +42,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 +77,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 +86,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 +112,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 +169,47 @@ sp_action_set_name (SPAction *action, Glib::ustring const &name)
}
/**
- * Return View associated with the action.
+ * 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, if any.
*/
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();
+}
+
+/**
+ * Return Desktop associated with the action, if any.
+ */
+SPDesktop *
+sp_action_get_desktop (SPAction *action)
+{
+ // TODO: this slightly horrible storage of a UI::View::View*, and
+ // casting to an SPDesktop*, is only done because that's what was
+ // already the norm in the Inkscape codebase. This seems wrong. Surely
+ // we should store an SPDesktop* in the first place? Is there a case
+ // of actions being carried out on a View that is not an SPDesktop?
+ return static_cast<SPDesktop *>(sp_action_get_view(action));
}
/*
diff --git a/src/helper/action.h b/src/helper/action.h
index 0cd010b34..1f2de87b4 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,13 @@ 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 SPDesktop;
+class SPDocument;
namespace Inkscape {
+
+class Selection;
class Verb;
+
namespace UI {
namespace View {
class View;
@@ -39,7 +45,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 +65,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,7 +76,10 @@ 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);
+SPDesktop *sp_action_get_desktop(SPAction *action);
#endif
diff --git a/src/inkscape-private.h b/src/inkscape-private.h
index 09bcef12b..364e3dab6 100644
--- a/src/inkscape-private.h
+++ b/src/inkscape-private.h
@@ -48,8 +48,6 @@ void inkscape_add_desktop (SPDesktop * desktop);
void inkscape_remove_desktop (SPDesktop * desktop);
void inkscape_activate_desktop (SPDesktop * desktop);
void inkscape_reactivate_desktop (SPDesktop * desktop);
-void inkscape_add_document (SPDocument *document);
-bool inkscape_remove_document (SPDocument *document);
void inkscape_set_color (SPColor *color, float opacity);
diff --git a/src/inkscape.cpp b/src/inkscape.cpp
index 7e570deb7..a24bd2b8a 100644
--- a/src/inkscape.cpp
+++ b/src/inkscape.cpp
@@ -58,12 +58,14 @@
#include "extension/system.h"
#include "inkscape-private.h"
#include "io/sys.h"
+#include "layer-model.h"
#include "message-stack.h"
#include "preferences.h"
#include "resource-manager.h"
#include "selection.h"
#include "ui/dialog/debug.h"
#include "xml/repr.h"
+#include "helper/action-context.h"
#include "helper/sp-marshal.h"
static Inkscape::Application *inkscape = NULL;
@@ -87,7 +89,7 @@ enum {
LAST_SIGNAL
};
-#define DESKTOP_IS_ACTIVE(d) ((d) == inkscape->desktops->data)
+#define DESKTOP_IS_ACTIVE(d) (inkscape->desktops && ((d) == inkscape->desktops->data))
/*################################
@@ -105,10 +107,27 @@ static void inkscape_dispose (GObject *object);
static void inkscape_activate_desktop_private (Inkscape::Application *inkscape, SPDesktop *desktop);
static void inkscape_deactivate_desktop_private (Inkscape::Application *inkscape, SPDesktop *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, NULL));
+ }
+
+ Inkscape::Selection *getSelection() const { return _selection; }
+};
+
struct Inkscape::Application {
GObject object;
Inkscape::XML::Document *menus;
std::map<SPDocument *, int> document_set;
+ std::map<SPDocument *, AppSelectionModel *> selection_models;
GSList *desktops;
gchar *argv0;
gboolean dialogs_toggle;
@@ -481,6 +500,7 @@ inkscape_init (SPObject * object)
}
new (&inkscape->document_set) std::map<SPDocument *, int>();
+ new (&inkscape->selection_models) std::map<SPDocument *, AppSelectionModel *>();
inkscape->menus = sp_repr_read_mem (_(menus_skeleton), MENUS_SKELETON_SIZE, NULL);
inkscape->desktops = NULL;
@@ -504,6 +524,7 @@ inkscape_dispose (GObject *object)
inkscape->menus = NULL;
}
+ inkscape->selection_models.~map();
inkscape->document_set.~map();
G_OBJECT_CLASS (parent_class)->dispose (object);
@@ -1234,6 +1255,14 @@ inkscape_add_document (SPDocument *document)
iter->second ++;
}
}
+ } else {
+ // insert succeeded, this document is new. Do we need to create a
+ // selection model for it, i.e. are we running without a desktop?
+ if (!inkscape->use_gui) {
+ // Create layer model and selection model so we can run some verbs without a GUI
+ g_assert(inkscape->selection_models.find(document) == inkscape->selection_models.end());
+ inkscape->selection_models[document] = new AppSelectionModel(document);
+ }
}
}
@@ -1253,6 +1282,13 @@ inkscape_remove_document (SPDocument *document)
if (iter->second < 1) {
// this was the last one, remove the pair from list
inkscape->document_set.erase (iter);
+
+ // also remove the selection model
+ std::map<SPDocument *, AppSelectionModel *>::iterator sel_iter = inkscape->selection_models.find(document);
+ if (sel_iter != inkscape->selection_models.end()) {
+ inkscape->selection_models.erase(sel_iter);
+ }
+
return true;
} else {
return false;
@@ -1312,6 +1348,39 @@ inkscape_active_event_context (void)
return NULL;
}
+Inkscape::ActionContext
+inkscape_active_action_context()
+{
+ if (SP_ACTIVE_DESKTOP) {
+ return Inkscape::ActionContext(SP_ACTIVE_DESKTOP);
+ }
+
+ SPDocument *doc = inkscape_active_document();
+ if (!doc) {
+ return Inkscape::ActionContext();
+ }
+
+ return inkscape_action_context_for_document(doc);
+}
+
+Inkscape::ActionContext
+inkscape_action_context_for_document(SPDocument *doc)
+{
+ // If there are desktops, check them first to see if the document is bound to one of them
+ for (GSList *iter = inkscape->desktops ; iter ; iter = iter->next) {
+ SPDesktop *desktop=static_cast<SPDesktop *>(iter->data);
+ if (desktop->doc() == doc) {
+ return Inkscape::ActionContext(desktop);
+ }
+ }
+
+ // Document is not associated with any desktops - maybe we're in command-line mode
+ std::map<SPDocument *, AppSelectionModel *>::iterator sel_iter = inkscape->selection_models.find(doc);
+ if (sel_iter == inkscape->selection_models.end()) {
+ return Inkscape::ActionContext();
+ }
+ return Inkscape::ActionContext(sel_iter->second->getSelection());
+}
/*#####################
diff --git a/src/inkscape.h b/src/inkscape.h
index 368c7fa60..234b98d2c 100644
--- a/src/inkscape.h
+++ b/src/inkscape.h
@@ -20,6 +20,7 @@ class SPDocument;
struct SPEventContext;
namespace Inkscape {
+ class ActionContext;
struct Application;
namespace XML {
class Node;
@@ -56,6 +57,21 @@ SPDocument * inkscape_active_document (void);
#define SP_ACTIVE_DESKTOP inkscape_active_desktop ()
SPDesktop * inkscape_active_desktop (void);
+// Use this function to get selection model etc for a document, if possible!
+// The "active" alternative below has all the horrible static cling of a singleton.
+Inkscape::ActionContext
+inkscape_action_context_for_document(SPDocument *doc);
+
+// More horrible static cling... sorry about this. Should really replace all of
+// the static stuff with a single instance of some kind of engine class holding
+// all the document / non-GUI stuff, and an optional GUI class that behaves a
+// bit like SPDesktop does currently. Then it will be easier to write good code
+// that doesn't just expect a GUI all the time (like lots of the app currently
+// does).
+// Also, while the "active" document / desktop concepts are convenient, they
+// appear to have been abused somewhat, further increasing static cling.
+Inkscape::ActionContext inkscape_active_action_context();
+
bool inkscape_is_sole_desktop_for_document(SPDesktop const &desktop);
gchar *homedir_path(const char *filename);
@@ -74,6 +90,11 @@ void inkscape_dialogs_toggle ();
void inkscape_external_change ();
void inkscape_subselection_changed (SPDesktop *desktop);
+/* Moved document add/remove functions into public inkscape.h as they are used
+ (rightly or wrongly) by console-mode functions */
+void inkscape_add_document (SPDocument *document);
+bool inkscape_remove_document (SPDocument *document);
+
/*
* fixme: This has to be rethought
*/
diff --git a/src/interface.cpp b/src/interface.cpp
index 986d3107f..98c30bf3c 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;
}
@@ -1986,7 +1987,7 @@ void ContextMenu::MakeGroupMenu(void)
void ContextMenu::ActivateGroup(void)
{
- sp_selection_group(_desktop);
+ sp_selection_group(_desktop->selection, _desktop);
}
void ContextMenu::ActivateUngroup(void)
@@ -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/layer-model.cpp b/src/layer-model.cpp
new file mode 100644
index 000000000..6833852ad
--- /dev/null
+++ b/src/layer-model.cpp
@@ -0,0 +1,259 @@
+/*
+ * Editable view implementation
+ *
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * MenTaLguY <mental@rydia.net>
+ * bulia byak <buliabyak@users.sf.net>
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ * John Bintz <jcoswell@coswellproductions.org>
+ * Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
+ * Jon A. Cruz <jon@joncruz.org>
+ * Abhishek Sharma
+ *
+ * Copyright (C) 2007 Jon A. Cruz
+ * Copyright (C) 2006-2008 Johan Engelen
+ * Copyright (C) 2006 John Bintz
+ * Copyright (C) 2004 MenTaLguY
+ * Copyright (C) 1999-2002 Lauris Kaplinski
+ * Copyright (C) 2000-2001 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "document.h"
+#include "layer-fns.h"
+#include "layer-model.h"
+#include "object-hierarchy.h"
+#include "sp-defs.h"
+#include "sp-item.h"
+#include "sp-item-group.h"
+#include "sp-object.h"
+#include "sp-root.h"
+#include <glib.h>
+#include <glibmm/i18n.h>
+#include <sigc++/functors/ptr_fun.h>
+
+// Callbacks
+static void _layer_activated(SPObject *layer, Inkscape::LayerModel *layer_model);
+static void _layer_deactivated(SPObject *layer, Inkscape::LayerModel *layer_model);
+static void _layer_changed(SPObject *top, SPObject *bottom, Inkscape::LayerModel *layer_model);
+
+namespace Inkscape {
+
+LayerModel::LayerModel()
+ : _doc( 0 )
+ , _layer_hierarchy( 0 )
+ , _display_key( 0 )
+{
+}
+
+LayerModel::~LayerModel()
+{
+ if (_layer_hierarchy) {
+ delete _layer_hierarchy;
+// _layer_hierarchy = NULL; //this should be here, but commented to find other bug somewhere else.
+ }
+}
+
+void LayerModel::setDocument(SPDocument *doc)
+{
+ _doc = doc;
+ if (_layer_hierarchy) {
+ _layer_hierarchy->clear();
+ delete _layer_hierarchy;
+ }
+ _layer_hierarchy = new Inkscape::ObjectHierarchy(NULL);
+ _layer_hierarchy->connectAdded(sigc::bind(sigc::ptr_fun(_layer_activated), this));
+ _layer_hierarchy->connectRemoved(sigc::bind(sigc::ptr_fun(_layer_deactivated), this));
+ _layer_hierarchy->connectChanged(sigc::bind(sigc::ptr_fun(_layer_changed), this));
+ _layer_hierarchy->setTop(doc->getRoot());
+}
+
+void LayerModel::setDisplayKey(unsigned int display_key)
+{
+ _display_key = display_key;
+}
+
+SPDocument *LayerModel::getDocument()
+{
+ return _doc;
+}
+
+/**
+ * Returns current root (=bottom) layer.
+ */
+SPObject *LayerModel::currentRoot() const
+{
+ return _layer_hierarchy ? _layer_hierarchy->top() : NULL;
+}
+
+/**
+ * Returns current top layer.
+ */
+SPObject *LayerModel::currentLayer() const
+{
+ return _layer_hierarchy ? _layer_hierarchy->bottom() : NULL;
+}
+
+/**
+ * Resets the bottom layer to the current root
+ */
+void LayerModel::reset() {
+ if (_layer_hierarchy) {
+ _layer_hierarchy->setBottom(currentRoot());
+ }
+}
+
+/**
+ * Sets the current layer of the desktop.
+ *
+ * Make \a object the top layer.
+ */
+void LayerModel::setCurrentLayer(SPObject *object) {
+ g_return_if_fail(SP_IS_GROUP(object));
+ g_return_if_fail( currentRoot() == object || (currentRoot() && currentRoot()->isAncestorOf(object)) );
+ // printf("Set Layer to ID: %s\n", object->getId());
+ _layer_hierarchy->setBottom(object);
+}
+
+void LayerModel::toggleHideAllLayers(bool hide) {
+
+ for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), currentRoot()); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) {
+ SP_ITEM(obj)->setHidden(hide);
+ }
+}
+
+void LayerModel::toggleLockAllLayers(bool lock) {
+
+ for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), currentRoot()); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) {
+ SP_ITEM(obj)->setLocked(lock);
+ }
+}
+
+void LayerModel::toggleLockOtherLayers(SPObject *object) {
+ g_return_if_fail(SP_IS_GROUP(object));
+ g_return_if_fail( currentRoot() == object || (currentRoot() && currentRoot()->isAncestorOf(object)) );
+
+ bool othersLocked = false;
+ std::vector<SPObject*> layers;
+ for ( SPObject* obj = Inkscape::next_layer(currentRoot(), object); obj; obj = Inkscape::next_layer(currentRoot(), obj) ) {
+ // Dont lock any ancestors, since that would in turn lock the layer as well
+ if (!obj->isAncestorOf(object)) {
+ layers.push_back(obj);
+ othersLocked |= !SP_ITEM(obj)->isLocked();
+ }
+ }
+ for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), object); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) {
+ if (!obj->isAncestorOf(object)) {
+ layers.push_back(obj);
+ othersLocked |= !SP_ITEM(obj)->isLocked();
+ }
+ }
+
+ SPItem *item = SP_ITEM(object);
+ if ( item->isLocked() ) {
+ item->setLocked(false);
+ }
+
+ for ( std::vector<SPObject*>::iterator it = layers.begin(); it != layers.end(); ++it ) {
+ SP_ITEM(*it)->setLocked(othersLocked);
+ }
+}
+
+
+void LayerModel::toggleLayerSolo(SPObject *object) {
+ g_return_if_fail(SP_IS_GROUP(object));
+ g_return_if_fail( currentRoot() == object || (currentRoot() && currentRoot()->isAncestorOf(object)) );
+
+ bool othersShowing = false;
+ std::vector<SPObject*> layers;
+ for ( SPObject* obj = Inkscape::next_layer(currentRoot(), object); obj; obj = Inkscape::next_layer(currentRoot(), obj) ) {
+ // Don't hide ancestors, since that would in turn hide the layer as well
+ if (!obj->isAncestorOf(object)) {
+ layers.push_back(obj);
+ othersShowing |= !SP_ITEM(obj)->isHidden();
+ }
+ }
+ for ( SPObject* obj = Inkscape::previous_layer(currentRoot(), object); obj; obj = Inkscape::previous_layer(currentRoot(), obj) ) {
+ if (!obj->isAncestorOf(object)) {
+ layers.push_back(obj);
+ othersShowing |= !SP_ITEM(obj)->isHidden();
+ }
+ }
+
+
+ SPItem *item = SP_ITEM(object);
+ if ( item->isHidden() ) {
+ item->setHidden(false);
+ }
+
+ for ( std::vector<SPObject*>::iterator it = layers.begin(); it != layers.end(); ++it ) {
+ SP_ITEM(*it)->setHidden(othersShowing);
+ }
+}
+
+/**
+ * Return layer that contains \a object.
+ */
+SPObject *LayerModel::layerForObject(SPObject *object) {
+ g_return_val_if_fail(object != NULL, NULL);
+
+ SPObject *root=currentRoot();
+ object = object->parent;
+ while ( object && object != root && !isLayer(object) ) {
+ // Objects in defs have no layer and are NOT in the root layer
+ if(SP_IS_DEFS(object))
+ return NULL;
+ object = object->parent;
+ }
+ return object;
+}
+
+/**
+ * True if object is a layer.
+ */
+bool LayerModel::isLayer(SPObject *object) const {
+ return ( SP_IS_GROUP(object)
+ && ( SP_GROUP(object)->effectiveLayerMode(_display_key)
+ == SPGroup::LAYER ) );
+}
+
+} // namespace Inkscape
+
+
+/// Callback
+static void
+_layer_activated(SPObject *layer, Inkscape::LayerModel *layer_model) {
+ g_return_if_fail(SP_IS_GROUP(layer));
+ layer_model->_layer_activated_signal.emit(layer);
+}
+
+/// Callback
+static void
+_layer_deactivated(SPObject *layer, Inkscape::LayerModel *layer_model) {
+ g_return_if_fail(SP_IS_GROUP(layer));
+ layer_model->_layer_deactivated_signal.emit(layer);
+}
+
+/// Callback
+static void
+_layer_changed(SPObject *top, SPObject *bottom, Inkscape::LayerModel *layer_model)
+{
+ layer_model->_layer_changed_signal.emit (top, bottom);
+}
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/layer-model.h b/src/layer-model.h
new file mode 100644
index 000000000..79b7fbe44
--- /dev/null
+++ b/src/layer-model.h
@@ -0,0 +1,104 @@
+#ifndef SEEN_INKSCAPE_LAYER_MODEL_H
+#define SEEN_INKSCAPE_LAYER_MODEL_H
+
+/*
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Frank Felfe <innerspace@iname.com>
+ * bulia byak <buliabyak@users.sf.net>
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ * John Bintz <jcoswell@coswellproductions.org>
+ * Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
+ * Jon A. Cruz <jon@joncruz.org>get
+ * Abhishek Sharma
+ * Eric Greveson <eric@greveson.co.uk>
+ *
+ * Copyright (C) 2007 Johan Engelen
+ * Copyright (C) 2006 John Bintz
+ * Copyright (C) 1999-2013 authors
+ * Copyright (C) 2000-2001 Ximian, Inc.
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stddef.h>
+#include <sigc++/sigc++.h>
+
+class SPDocument;
+class SPObject;
+
+namespace Inkscape {
+
+class ObjectHierarchy;
+
+namespace XML {
+ class Node;
+}
+
+/**
+ * The layer model for a document.
+ *
+ * This class represents the layer model for a document, typically (but
+ * not necessarily) displayed in an SPDesktop.
+ *
+ * It also implements its own asynchronous notification signals that
+ * UI elements can listen to.
+ */
+class LayerModel
+{
+ SPDocument *_doc;
+ Inkscape::ObjectHierarchy *_layer_hierarchy;
+ unsigned int _display_key;
+
+public:
+ /** Construct a layer model */
+ LayerModel();
+
+ /** Destructor */
+ ~LayerModel();
+
+ // Set document
+ void setDocument(SPDocument *doc);
+
+ // Set display key. For GUI apps.
+ void setDisplayKey(unsigned int display_key);
+
+ // Get the document that this layer model refers to. May be NULL.
+ SPDocument *getDocument();
+
+ // TODO look into making these return a more specific subclass:
+ SPObject *currentRoot() const;
+ SPObject *currentLayer() const;
+
+ void reset();
+ void setCurrentLayer(SPObject *object);
+ void toggleLayerSolo(SPObject *object);
+ void toggleHideAllLayers(bool hide);
+ void toggleLockAllLayers(bool lock);
+ void toggleLockOtherLayers(SPObject *object);
+ SPObject *layerForObject(SPObject *object);
+ bool isLayer(SPObject *object) const;
+
+ sigc::signal<void, SPObject *> _layer_activated_signal;
+ sigc::signal<void, SPObject *> _layer_deactivated_signal;
+ sigc::signal<void, SPObject *, SPObject *> _layer_changed_signal;
+};
+
+} // namespace Inkscape
+
+#endif
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/livarot/Shape.cpp b/src/livarot/Shape.cpp
index 130b1b03a..c29444a33 100644
--- a/src/livarot/Shape.cpp
+++ b/src/livarot/Shape.cpp
@@ -334,8 +334,8 @@ Shape::AddPoint (const Geom::Point x)
pData[n].nextLinkedPoint = -1;
pData[n].askForWindingS = NULL;
pData[n].askForWindingB = -1;
- pData[n].rx[0] = /*Round*/ (p.x[0]);
- pData[n].rx[1] = /*Round*/ (p.x[1]);
+ pData[n].rx[0] = Round(p.x[0]);
+ pData[n].rx[1] = Round(p.x[1]);
}
if (_has_voronoi_data)
{
@@ -2116,8 +2116,8 @@ void Shape::initialisePointData()
pData[i].pending = 0;
pData[i].edgeOnLeft = -1;
pData[i].nextLinkedPoint = -1;
- pData[i].rx[0] = /*Round*/ (getPoint(i).x[0]);
- pData[i].rx[1] = /*Round*/ (getPoint(i).x[1]);
+ pData[i].rx[0] = Round(getPoint(i).x[0]);
+ pData[i].rx[1] = Round(getPoint(i).x[1]);
}
_point_data_initialised = true;
diff --git a/src/livarot/Shape.h b/src/livarot/Shape.h
index b999b9dca..98fc2d7bf 100644
--- a/src/livarot/Shape.h
+++ b/src/livarot/Shape.h
@@ -266,20 +266,20 @@ public:
// be careful when using this function
// the coordinate rounding function
-// inline static double Round(double x)
-// {
-// return ldexp(rint(ldexp(x, 5)), -5);
-// }
+ inline static double Round(double x)
+ {
+ return ldexp(rint(ldexp(x, 9)), -9);
+ }
// 2 miscannellous variations on it, to scale to and back the rounding grid
inline static double HalfRound(double x)
{
- return ldexp(x, -5);
+ return ldexp(x, -9);
}
inline static double IHalfRound(double x)
{
- return ldexp(x, 5);
+ return ldexp(x, 9);
}
// boolean operations on polygons (requests intersection-free poylygons)
diff --git a/src/livarot/ShapeMisc.cpp b/src/livarot/ShapeMisc.cpp
index 5bb8a25ef..6fd40790f 100644
--- a/src/livarot/ShapeMisc.cpp
+++ b/src/livarot/ShapeMisc.cpp
@@ -49,8 +49,8 @@ Shape::ConvertToForme (Path * dest)
for (int i = 0; i < numberOfPoints(); i++)
{
- pData[i].rx[0] = /*Round*/ (getPoint(i).x[0]);
- pData[i].rx[1] = /*Round*/ (getPoint(i).x[1]);
+ pData[i].rx[0] = Round (getPoint(i).x[0]);
+ pData[i].rx[1] = Round (getPoint(i).x[1]);
}
for (int i = 0; i < numberOfEdges(); i++)
{
@@ -199,8 +199,8 @@ Shape::ConvertToForme (Path * dest, int nbP, Path * *orig, bool splitWhenForced)
for (int i = 0; i < numberOfPoints(); i++)
{
- pData[i].rx[0] = /*Round*/ (getPoint(i).x[0]);
- pData[i].rx[1] = /*Round*/ (getPoint(i).x[1]);
+ pData[i].rx[0] = Round (getPoint(i).x[0]);
+ pData[i].rx[1] = Round (getPoint(i).x[1]);
}
for (int i = 0; i < numberOfEdges(); i++)
{
@@ -352,8 +352,8 @@ Shape::ConvertToFormeNested (Path * dest, int nbP, Path * *orig, int wildPath,in
for (int i = 0; i < numberOfPoints(); i++)
{
- pData[i].rx[0] = /*Round*/ (getPoint(i).x[0]);
- pData[i].rx[1] = /*Round*/ (getPoint(i).x[1]);
+ pData[i].rx[0] = Round (getPoint(i).x[0]);
+ pData[i].rx[1] = Round (getPoint(i).x[1]);
}
for (int i = 0; i < numberOfEdges(); i++)
{
diff --git a/src/livarot/ShapeSweep.cpp b/src/livarot/ShapeSweep.cpp
index ffe5a9d73..c2fd83e31 100644
--- a/src/livarot/ShapeSweep.cpp
+++ b/src/livarot/ShapeSweep.cpp
@@ -250,8 +250,8 @@ Shape::ConvertToShape (Shape * a, FillRule directed, bool invert)
}
Geom::Point rPtX;
- rPtX[0]= /*Round*/ (ptX[0]);
- rPtX[1]= /*Round*/ (ptX[1]);
+ rPtX[0]= Round (ptX[0]);
+ rPtX[1]= Round (ptX[1]);
int lastPointNo = -1;
lastPointNo = AddPoint (rPtX);
pData[lastPointNo].rx = rPtX;
@@ -1051,8 +1051,8 @@ Shape::Booleen (Shape * a, Shape * b, BooleanOp mod,int cutPathID)
}
Geom::Point rPtX;
- rPtX[0]= /*Round*/ (ptX[0]);
- rPtX[1]= /*Round*/ (ptX[1]);
+ rPtX[0]= Round (ptX[0]);
+ rPtX[1]= Round (ptX[1]);
int lastPointNo = -1;
lastPointNo = AddPoint (rPtX);
pData[lastPointNo].rx = rPtX;
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..4e2f2fd2b 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"
@@ -100,6 +103,11 @@
#endif // WIN32
#include "extension/init.h"
+// Not ideal, but there doesn't appear to be a nicer system in place for
+// passing command-line parameters to extensions before initialization...
+#ifdef WITH_DBUS
+#include "extension/dbus/dbus-init.h"
+#endif // WITH_DBUS
#include <glibmm/i18n.h>
#include <glibmm/main.h>
@@ -166,6 +174,10 @@ enum {
SP_ARG_SHELL,
SP_ARG_VERSION,
SP_ARG_VACUUM_DEFS,
+#ifdef WITH_DBUS
+ SP_ARG_DBUS_LISTEN,
+ SP_ARG_DBUS_NAME,
+#endif // WITH_DBUS
SP_ARG_VERB_LIST,
SP_ARG_VERB,
SP_ARG_SELECT,
@@ -219,7 +231,10 @@ static gboolean sp_query_all = FALSE;
static gchar *sp_query_id = NULL;
static gboolean sp_shell = FALSE;
static gboolean sp_vacuum_defs = FALSE;
-
+#ifdef WITH_DBUS
+static gboolean sp_dbus_listen = FALSE;
+static gchar *sp_dbus_name = NULL;
+#endif // WITH_DBUS
static gchar *sp_export_png_utf8 = NULL;
static gchar *sp_export_svg_utf8 = NULL;
static gchar *sp_global_printer_utf8 = NULL;
@@ -264,6 +279,10 @@ static void resetCommandlineGlobals() {
sp_query_all = FALSE;
sp_query_id = NULL;
sp_vacuum_defs = FALSE;
+#ifdef WITH_DBUS
+ sp_dbus_listen = FALSE;
+ sp_dbus_name = NULL;
+#endif // WITH_DBUS
sp_export_png_utf8 = NULL;
sp_export_svg_utf8 = NULL;
@@ -470,6 +489,18 @@ struct poptOption options[] = {
POPT_ARG_NONE, &sp_vacuum_defs, SP_ARG_VACUUM_DEFS,
N_("Remove unused definitions from the defs section(s) of the document"),
NULL},
+
+#ifdef WITH_DBUS
+ {"dbus-listen", 0,
+ POPT_ARG_NONE, &sp_dbus_listen, SP_ARG_DBUS_LISTEN,
+ N_("Enter a listening loop for D-Bus messages in console mode"),
+ NULL},
+
+ {"dbus-name", 0,
+ POPT_ARG_STRING, &sp_dbus_name, SP_ARG_DBUS_NAME,
+ N_("Specify the D-Bus bus name to listen for messages on (default is org.inkscape)"),
+ N_("BUS-NAME")},
+#endif // WITH_DBUS
{"verb-list", 0,
POPT_ARG_NONE, NULL, SP_ARG_VERB_LIST,
@@ -728,6 +759,9 @@ main(int argc, char **argv)
|| !strcmp(argv[i], "-Y")
|| !strncmp(argv[i], "--query-y", 9)
|| !strcmp(argv[i], "--vacuum-defs")
+#ifdef WITH_DBUS
+ || !strcmp(argv[i], "--dbus-listen")
+#endif // WITH_DBUS
|| !strcmp(argv[i], "--shell")
)
{
@@ -864,6 +898,13 @@ static int sp_common_main( int argc, char const **argv, GSList **flDest )
if ( sp_global_printer )
sp_global_printer_utf8 = g_strdup( sp_global_printer );
}
+
+#ifdef WITH_DBUS
+ // Before initializing extensions, we must set the DBus bus name if required
+ if (sp_dbus_name != NULL) {
+ Inkscape::Extension::Dbus::dbus_set_bus_name(sp_dbus_name);
+ }
+#endif
// Return the list if wanted, else free it up.
if ( flDest ) {
@@ -1035,6 +1076,17 @@ sp_main_gui(int argc, char const **argv)
static int sp_process_file_list(GSList *fl)
{
int retVal = 0;
+#ifdef WITH_DBUS
+ if (!fl) {
+ // If we've been asked to listen for D-Bus messages, enter a main loop here
+ // The main loop may be exited by calling "exit" on the D-Bus application interface.
+ if (sp_dbus_listen) {
+ Gtk::Main main_dbus_loop(0, NULL);
+ main_dbus_loop.run();
+ }
+ }
+#endif // WITH_DBUS
+
while (fl) {
const gchar *filename = (gchar *)fl->data;
@@ -1066,7 +1118,20 @@ static int sp_process_file_list(GSList *fl)
if (sp_vacuum_defs) {
doc->vacuumDocument();
}
- if (sp_vacuum_defs && !sp_export_svg) {
+
+ // Execute command-line actions (selections and verbs) using our local models
+ bool has_performed_actions = Inkscape::CmdLineAction::doList(inkscape_active_action_context());
+
+#ifdef WITH_DBUS
+ // If we've been asked to listen for D-Bus messages, enter a main loop here
+ // The main loop may be exited by calling "exit" on the D-Bus application interface.
+ if (sp_dbus_listen) {
+ Gtk::Main main_dbus_loop(0, NULL);
+ main_dbus_loop.run();
+ }
+#endif // WITH_DBUS
+
+ 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);
}
@@ -1232,7 +1297,11 @@ int sp_main_console(int argc, char const **argv)
int retVal = sp_common_main( argc, argv, &fl );
g_return_val_if_fail(retVal == 0, 1);
- if (fl == NULL && !sp_shell) {
+ if (fl == NULL && !sp_shell
+#ifdef WITH_DBUS
+ && !sp_dbus_listen
+#endif // WITH_DBUS
+ ) {
g_print("Nothing to do!\n");
exit(0);
}
diff --git a/src/pixmaps/handles.xpm b/src/pixmaps/handles.xpm
index f2afa026b..b61ad377c 100644
--- a/src/pixmaps/handles.xpm
+++ b/src/pixmaps/handles.xpm
@@ -1,5 +1,5 @@
-/* XPM */
-static char const *handle_scale_nw_xpm[] = {
+/* XPM North-West */
+static char const *handle_scale_xpm[] = {
"13 13 3 1",
" c None",
". c #000000",
@@ -18,28 +18,8 @@ static char const *handle_scale_nw_xpm[] = {
" ....... ",
" "};
-/* XPM */
-static char const *handle_scale_ne_xpm[] = {
-"13 13 3 1",
-" c None",
-". c #000000",
-"+ c #FFFFFF",
-" ",
-" ....... ",
-" ..+++. ",
-" .++++. ",
-" .+++++. ",
-" . .+++++.. ",
-" ...+++++... ",
-" ..+++++. . ",
-" .+++++. ",
-" .++++. ",
-" .+++.. ",
-" ....... ",
-" "};
-
-/* XPM */
-static char const *handle_scale_h_xpm[] = {
+/* XPM Vertical */
+static char const *handle_stretch_xpm[] = {
"13 13 3 1",
" c None",
". c #000000",
@@ -58,28 +38,8 @@ static char const *handle_scale_h_xpm[] = {
" ",
" "};
-/* XPM */
-static char const *handle_scale_v_xpm[] = {
-"13 13 3 1",
-" c None",
-". c #000000",
-"+ c #FFFFFF",
-" . ",
-" ... ",
-" ..+.. ",
-" ..+++.. ",
-" ..+++++.. ",
-" .+++. ",
-" .+++. ",
-" .+++. ",
-" ..+++++.. ",
-" ..+++.. ",
-" ..+.. ",
-" ... ",
-" . "};
-
-/* XPM */
-static char const *handle_rotate_nw_xpm[] = {
+/* XPM North-West */
+static char const *handle_rotate_xpm[] = {
"13 13 3 1",
" c None",
". c #000000",
@@ -98,8 +58,8 @@ static char const *handle_rotate_nw_xpm[] = {
" ... ",
" . "};
-/* XPM */
-static char const *handle_rotate_n_xpm[] = {
+/* XPM North */
+static char const *handle_skew_xpm[] = {
"13 13 3 1",
" c None",
". c #000000",
@@ -119,127 +79,6 @@ static char const *handle_rotate_n_xpm[] = {
" "};
/* XPM */
-static char const *handle_rotate_ne_xpm[] = {
-"13 13 3 1",
-" c None",
-". c #000000",
-"+ c #FFFFFF",
-" . ",
-" .. ",
-" .... ",
-" ..++... ",
-"..++++++. ",
-" .+++++++. ",
-" .+..++++. ",
-" . .+++. ",
-" .+++...",
-" .++++.. ",
-" .++.. ",
-" ... ",
-" . "};
-
-/* XPM */
-static char const *handle_rotate_e_xpm[] = {
-"13 13 3 1",
-" c None",
-". c #000000",
-"+ c #FFFFFF",
-" . ",
-" ... ",
-" ..+.. ",
-" ..+++.. ",
-" ...+++...",
-" .+++. ",
-" .+++. ",
-" .+++. ",
-" ...+++...",
-" ..+++.. ",
-" ..+.. ",
-" ... ",
-" . "};
-
-/* XPM */
-static char const *handle_rotate_se_xpm[] = {
-"13 13 3 1",
-" c None",
-". c #000000",
-"+ c #FFFFFF",
-" . ",
-" ... ",
-" .++.. ",
-" .++++.. ",
-" .+++...",
-" . .+++. ",
-" .+..++++. ",
-" .+++++++. ",
-"..++++++. ",
-" ..++... ",
-" .... ",
-" .. ",
-" . "};
-
-
-/* XPM */
-static char const *handle_rotate_s_xpm[] = {
-"13 13 3 1",
-" c None",
-". c #000000",
-"+ c #FFFFFF",
-" ",
-" ",
-" ",
-" ",
-" . . ",
-" .. .. ",
-" ......... ",
-" ..+++++++.. ",
-"..+++++++++..",
-" ..+++++++.. ",
-" ......... ",
-" .. .. ",
-" . . "};
-
-/* XPM */
-static char const *handle_rotate_sw_xpm[] = {
-"13 13 3 1",
-" c None",
-". c #000000",
-"+ c #FFFFFF",
-" . ",
-" ... ",
-" ..++. ",
-" ..++++. ",
-"...+++. ",
-" .+++. . ",
-" .++++..+. ",
-" .+++++++. ",
-" .++++++..",
-" ...++.. ",
-" .... ",
-" .. ",
-" . "};
-
-/* XPM */
-static char const *handle_rotate_w_xpm[] = {
-"13 13 3 1",
-" c None",
-". c #000000",
-"+ c #FFFFFF",
-" . ",
-" ... ",
-" ..+.. ",
-" ..+++.. ",
-"...+++... ",
-" .+++. ",
-" .+++. ",
-" .+++. ",
-"...+++. . ",
-" ..+++.. ",
-" ..+.. ",
-" ... ",
-" . "};
-
-/* XPM */
static char const *handle_center_xpm[] = {
"13 13 3 1",
" c None",
@@ -258,3 +97,4 @@ static char const *handle_center_xpm[] = {
" . ",
" . ",
" "};
+
diff --git a/src/select-context.cpp b/src/select-context.cpp
index 1dd3b08d7..b4b01bf15 100644
--- a/src/select-context.cpp
+++ b/src/select-context.cpp
@@ -91,6 +91,16 @@ sp_select_context_class_init(SPSelectContextClass *klass)
event_context_class->item_handler = sp_select_context_item_handler;
}
+//Creates rotated variations for handles
+static void
+sp_load_handles(int start, int count, char const **xpm) {
+ handles[start] = gdk_pixbuf_new_from_xpm_data((gchar const **)xpm);
+ for(int i = start + 1; i < start + count; i++) {
+ // We use either the original at *start or previous loop item to rotate
+ handles[i] = gdk_pixbuf_rotate_simple(handles[i-1], GDK_PIXBUF_ROTATE_CLOCKWISE);
+ }
+}
+
static void
sp_select_context_init(SPSelectContext *sc)
{
@@ -111,19 +121,11 @@ sp_select_context_init(SPSelectContext *sc)
CursorSelectMouseover = sp_cursor_new_from_xpm(cursor_select_m_xpm , 1, 1);
CursorSelectDragging = sp_cursor_new_from_xpm(cursor_select_d_xpm , 1, 1);
// selection handles
- handles[0] = gdk_pixbuf_new_from_xpm_data((gchar const **)handle_scale_nw_xpm);
- handles[1] = gdk_pixbuf_new_from_xpm_data((gchar const **)handle_scale_ne_xpm);
- handles[2] = gdk_pixbuf_new_from_xpm_data((gchar const **)handle_scale_h_xpm);
- handles[3] = gdk_pixbuf_new_from_xpm_data((gchar const **)handle_scale_v_xpm);
- handles[4] = gdk_pixbuf_new_from_xpm_data((gchar const **)handle_rotate_nw_xpm);
- handles[5] = gdk_pixbuf_new_from_xpm_data((gchar const **)handle_rotate_n_xpm);
- handles[6] = gdk_pixbuf_new_from_xpm_data((gchar const **)handle_rotate_ne_xpm);
- handles[7] = gdk_pixbuf_new_from_xpm_data((gchar const **)handle_rotate_e_xpm);
- handles[8] = gdk_pixbuf_new_from_xpm_data((gchar const **)handle_rotate_se_xpm);
- handles[9] = gdk_pixbuf_new_from_xpm_data((gchar const **)handle_rotate_s_xpm);
- handles[10] = gdk_pixbuf_new_from_xpm_data((gchar const **)handle_rotate_sw_xpm);
- handles[11] = gdk_pixbuf_new_from_xpm_data((gchar const **)handle_rotate_w_xpm);
- handles[12] = gdk_pixbuf_new_from_xpm_data((gchar const **)handle_center_xpm);
+ sp_load_handles(0, 2, handle_scale_xpm);
+ sp_load_handles(2, 2, handle_stretch_xpm);
+ sp_load_handles(4, 4, handle_rotate_xpm);
+ sp_load_handles(8, 4, handle_skew_xpm);
+ sp_load_handles(12, 1, handle_center_xpm);
}
static void
@@ -921,12 +923,12 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event)
gint mul = 1 + gobble_key_events(
get_group0_keyval(&event->key), 0); // with any mask
if (MOD__ALT(event)) { // alt
- if (MOD__SHIFT(event)) sp_selection_move_screen(desktop, mul*-10, 0); // shift
- else sp_selection_move_screen(desktop, mul*-1, 0); // no shift
+ if (MOD__SHIFT(event)) sp_selection_move_screen(sp_desktop_selection(desktop), mul*-10, 0); // shift
+ else sp_selection_move_screen(sp_desktop_selection(desktop), mul*-1, 0); // no shift
}
else { // no alt
- if (MOD__SHIFT(event)) sp_selection_move(desktop, mul*-10*nudge, 0); // shift
- else sp_selection_move(desktop, mul*-nudge, 0); // no shift
+ if (MOD__SHIFT(event)) sp_selection_move(sp_desktop_selection(desktop), mul*-10*nudge, 0); // shift
+ else sp_selection_move(sp_desktop_selection(desktop), mul*-nudge, 0); // no shift
}
ret = TRUE;
}
@@ -937,12 +939,12 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event)
gint mul = 1 + gobble_key_events(
get_group0_keyval(&event->key), 0); // with any mask
if (MOD__ALT(event)) { // alt
- if (MOD__SHIFT(event)) sp_selection_move_screen(desktop, 0, mul*10); // shift
- else sp_selection_move_screen(desktop, 0, mul*1); // no shift
+ if (MOD__SHIFT(event)) sp_selection_move_screen(sp_desktop_selection(desktop), 0, mul*10); // shift
+ else sp_selection_move_screen(sp_desktop_selection(desktop), 0, mul*1); // no shift
}
else { // no alt
- if (MOD__SHIFT(event)) sp_selection_move(desktop, 0, mul*10*nudge); // shift
- else sp_selection_move(desktop, 0, mul*nudge); // no shift
+ if (MOD__SHIFT(event)) sp_selection_move(sp_desktop_selection(desktop), 0, mul*10*nudge); // shift
+ else sp_selection_move(sp_desktop_selection(desktop), 0, mul*nudge); // no shift
}
ret = TRUE;
}
@@ -953,12 +955,12 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event)
gint mul = 1 + gobble_key_events(
get_group0_keyval(&event->key), 0); // with any mask
if (MOD__ALT(event)) { // alt
- if (MOD__SHIFT(event)) sp_selection_move_screen(desktop, mul*10, 0); // shift
- else sp_selection_move_screen(desktop, mul*1, 0); // no shift
+ if (MOD__SHIFT(event)) sp_selection_move_screen(sp_desktop_selection(desktop), mul*10, 0); // shift
+ else sp_selection_move_screen(sp_desktop_selection(desktop), mul*1, 0); // no shift
}
else { // no alt
- if (MOD__SHIFT(event)) sp_selection_move(desktop, mul*10*nudge, 0); // shift
- else sp_selection_move(desktop, mul*nudge, 0); // no shift
+ if (MOD__SHIFT(event)) sp_selection_move(sp_desktop_selection(desktop), mul*10*nudge, 0); // shift
+ else sp_selection_move(sp_desktop_selection(desktop), mul*nudge, 0); // no shift
}
ret = TRUE;
}
@@ -969,12 +971,12 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event)
gint mul = 1 + gobble_key_events(
get_group0_keyval(&event->key), 0); // with any mask
if (MOD__ALT(event)) { // alt
- if (MOD__SHIFT(event)) sp_selection_move_screen(desktop, 0, mul*-10); // shift
- else sp_selection_move_screen(desktop, 0, mul*-1); // no shift
+ if (MOD__SHIFT(event)) sp_selection_move_screen(sp_desktop_selection(desktop), 0, mul*-10); // shift
+ else sp_selection_move_screen(sp_desktop_selection(desktop), 0, mul*-1); // no shift
}
else { // no alt
- if (MOD__SHIFT(event)) sp_selection_move(desktop, 0, mul*-10*nudge); // shift
- else sp_selection_move(desktop, 0, mul*-nudge); // no shift
+ if (MOD__SHIFT(event)) sp_selection_move(sp_desktop_selection(desktop), 0, mul*-10*nudge); // shift
+ else sp_selection_move(sp_desktop_selection(desktop), 0, mul*-nudge); // no shift
}
ret = TRUE;
}
diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp
index 56923859b..29cb208d9 100644
--- a/src/selection-chemistry.cpp
+++ b/src/selection-chemistry.cpp
@@ -35,6 +35,7 @@ SPCycleType SP_CYCLING = SP_CYCLE_FOCUS;
#include "desktop.h"
#include "desktop-style.h"
#include "dir-util.h"
+#include "layer-model.h"
#include "selection.h"
#include "tools-switch.h"
#include "desktop-handles.h"
@@ -124,6 +125,21 @@ because the layer manipulation code uses them. It should be rewritten specifical
for that purpose. */
+// 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
+selection_display_message(SPDesktop *desktop, Inkscape::MessageType msgType, Glib::ustring const &msg)
+{
+ if (desktop) {
+ desktop->messageStack()->flash(msgType, msg);
+ } else {
+ if (msgType == Inkscape::IMMEDIATE_MESSAGE ||
+ msgType == Inkscape::WARNING_MESSAGE ||
+ msgType == Inkscape::ERROR_MESSAGE) {
+ g_printerr("%s\n", msg.c_str());
+ }
+ }
+}
namespace Inkscape {
@@ -521,16 +537,16 @@ void sp_selection_duplicate(SPDesktop *desktop, bool suppressDone)
g_slist_free(newsel);
}
-void sp_edit_clear_all(SPDesktop *dt)
+void sp_edit_clear_all(Inkscape::Selection *selection)
{
- if (!dt)
+ if (!selection)
return;
- SPDocument *doc = sp_desktop_document(dt);
- sp_desktop_selection(dt)->clear();
+ SPDocument *doc = selection->layers()->getDocument();
+ selection->clear();
- g_return_if_fail(SP_IS_GROUP(dt->currentLayer()));
- GSList *items = sp_item_group_item_list(SP_GROUP(dt->currentLayer()));
+ g_return_if_fail(SP_IS_GROUP(selection->layers()->currentLayer()));
+ GSList *items = sp_item_group_item_list(SP_GROUP(selection->layers()->currentLayer()));
while (items) {
reinterpret_cast<SPObject*>(items->data)->deleteObject();
@@ -721,20 +737,14 @@ static void sp_selection_group_impl(GSList *p, Inkscape::XML::Node *group, Inksc
group->setPosition(topmost + 1);
}
-void sp_selection_group(SPDesktop *desktop)
+void sp_selection_group(Inkscape::Selection *selection, SPDesktop *desktop)
{
- if (desktop == NULL) {
- return;
- }
-
- SPDocument *doc = sp_desktop_document(desktop);
+ SPDocument *doc = selection->layers()->getDocument();
Inkscape::XML::Document *xml_doc = doc->getReprDoc();
- Inkscape::Selection *selection = sp_desktop_selection(desktop);
-
// Check if something is selected.
if (selection->isEmpty()) {
- desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>some objects</b> to group."));
+ selection_display_message(desktop, Inkscape::WARNING_MESSAGE, _("Select <b>some objects</b> to group."));
return;
}
@@ -748,22 +758,17 @@ void sp_selection_group(SPDesktop *desktop)
sp_selection_group_impl(p, group, xml_doc, doc);
- DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_SELECTION_GROUP,
+ DocumentUndo::done(doc, SP_VERB_SELECTION_GROUP,
_("Group"));
selection->set(group);
Inkscape::GC::release(group);
}
-void sp_selection_ungroup(SPDesktop *desktop)
+void sp_selection_ungroup(Inkscape::Selection *selection, SPDesktop *desktop)
{
- if (desktop == NULL)
- return;
-
- Inkscape::Selection *selection = sp_desktop_selection(desktop);
-
if (selection->isEmpty()) {
- desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select a <b>group</b> to ungroup."));
+ selection_display_message(desktop, Inkscape::WARNING_MESSAGE, _("Select a <b>group</b> to ungroup."));
return;
}
@@ -806,12 +811,12 @@ void sp_selection_ungroup(SPDesktop *desktop)
g_slist_free(new_select);
}
if (!ungrouped) {
- desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No groups</b> to ungroup in the selection."));
+ selection_display_message(desktop, Inkscape::ERROR_MESSAGE, _("<b>No groups</b> to ungroup in the selection."));
}
g_slist_free(items);
-
- DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_SELECTION_UNGROUP,
+
+ DocumentUndo::done(selection->layers()->getDocument(), SP_VERB_SELECTION_UNGROUP,
_("Ungroup"));
}
@@ -889,22 +894,17 @@ static SPObject *prev_sibling(SPObject *child)
}
void
-sp_selection_raise(SPDesktop *desktop)
+sp_selection_raise(Inkscape::Selection *selection, SPDesktop *desktop)
{
- if (!desktop)
- return;
-
- Inkscape::Selection *selection = sp_desktop_selection(desktop);
-
GSList const *items = const_cast<GSList *>(selection->itemList());
if (!items) {
- desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to raise."));
+ selection_display_message(desktop, Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to raise."));
return;
}
SPGroup const *group = sp_item_list_common_parent_group(items);
if (!group) {
- desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>."));
+ selection_display_message(desktop, Inkscape::ERROR_MESSAGE, _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>."));
return;
}
@@ -942,21 +942,17 @@ sp_selection_raise(SPDesktop *desktop)
g_slist_free(rev);
}
- DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_SELECTION_RAISE,
+ DocumentUndo::done(selection->layers()->getDocument(), SP_VERB_SELECTION_RAISE,
//TRANSLATORS: "Raise" means "to raise an object" in the undo history
C_("Undo action", "Raise"));
}
-void sp_selection_raise_to_top(SPDesktop *desktop)
+void sp_selection_raise_to_top(Inkscape::Selection *selection, SPDesktop *desktop)
{
- if (desktop == NULL)
- return;
-
- SPDocument *document = sp_desktop_document(desktop);
- Inkscape::Selection *selection = sp_desktop_selection(desktop);
+ SPDocument *document = selection->layers()->getDocument();
if (selection->isEmpty()) {
- desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to raise to top."));
+ selection_display_message(desktop, Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to raise to top."));
return;
}
@@ -964,7 +960,7 @@ void sp_selection_raise_to_top(SPDesktop *desktop)
SPGroup const *group = sp_item_list_common_parent_group(items);
if (!group) {
- desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>."));
+ selection_display_message(desktop, Inkscape::ERROR_MESSAGE, _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>."));
return;
}
@@ -982,22 +978,17 @@ void sp_selection_raise_to_top(SPDesktop *desktop)
_("Raise to top"));
}
-void sp_selection_lower(SPDesktop *desktop)
+void sp_selection_lower(Inkscape::Selection *selection, SPDesktop *desktop)
{
- if (desktop == NULL)
- return;
-
- Inkscape::Selection *selection = sp_desktop_selection(desktop);
-
GSList const *items = const_cast<GSList *>(selection->itemList());
if (!items) {
- desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to lower."));
+ selection_display_message(desktop, Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to lower."));
return;
}
SPGroup const *group = sp_item_list_common_parent_group(items);
if (!group) {
- desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>."));
+ selection_display_message(desktop, Inkscape::ERROR_MESSAGE, _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>."));
return;
}
@@ -1040,20 +1031,16 @@ void sp_selection_lower(SPDesktop *desktop)
g_slist_free(rev);
}
- DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_SELECTION_LOWER,
+ DocumentUndo::done(selection->layers()->getDocument(), SP_VERB_SELECTION_LOWER,
_("Lower"));
}
-void sp_selection_lower_to_bottom(SPDesktop *desktop)
+void sp_selection_lower_to_bottom(Inkscape::Selection *selection, SPDesktop *desktop)
{
- if (desktop == NULL)
- return;
-
- SPDocument *document = sp_desktop_document(desktop);
- Inkscape::Selection *selection = sp_desktop_selection(desktop);
+ SPDocument *document = selection->layers()->getDocument();
if (selection->isEmpty()) {
- desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to lower to bottom."));
+ selection_display_message(desktop, Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to lower to bottom."));
return;
}
@@ -1061,7 +1048,7 @@ void sp_selection_lower_to_bottom(SPDesktop *desktop)
SPGroup const *group = sp_item_list_common_parent_group(items);
if (!group) {
- desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>."));
+ selection_display_message(desktop, Inkscape::ERROR_MESSAGE, _("You cannot raise/lower objects from <b>different groups</b> or <b>layers</b>."));
return;
}
@@ -2157,49 +2144,49 @@ sp_selection_scale_times(Inkscape::Selection *selection, gdouble times)
}
void
-sp_selection_move(SPDesktop *desktop, gdouble dx, gdouble dy)
+sp_selection_move(Inkscape::Selection *selection, gdouble dx, gdouble dy)
{
- Inkscape::Selection *selection = sp_desktop_selection(desktop);
if (selection->isEmpty()) {
return;
}
sp_selection_move_relative(selection, dx, dy);
+ SPDocument *doc = selection->layers()->getDocument();
if (dx == 0) {
- DocumentUndo::maybeDone(sp_desktop_document(desktop), "selector:move:vertical", SP_VERB_CONTEXT_SELECT,
+ DocumentUndo::maybeDone(doc, "selector:move:vertical", SP_VERB_CONTEXT_SELECT,
_("Move vertically"));
} else if (dy == 0) {
- DocumentUndo::maybeDone(sp_desktop_document(desktop), "selector:move:horizontal", SP_VERB_CONTEXT_SELECT,
+ DocumentUndo::maybeDone(doc, "selector:move:horizontal", SP_VERB_CONTEXT_SELECT,
_("Move horizontally"));
} else {
- DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_SELECT,
+ DocumentUndo::done(doc, SP_VERB_CONTEXT_SELECT,
_("Move"));
}
}
void
-sp_selection_move_screen(SPDesktop *desktop, gdouble dx, gdouble dy)
+sp_selection_move_screen(Inkscape::Selection *selection, gdouble dx, gdouble dy)
{
- Inkscape::Selection *selection = sp_desktop_selection(desktop);
- if (selection->isEmpty()) {
+ if (selection->isEmpty() || !selection->desktop()) {
return;
}
// same as sp_selection_move but divide deltas by zoom factor
- gdouble const zoom = desktop->current_zoom();
+ gdouble const zoom = selection->desktop()->current_zoom();
gdouble const zdx = dx / zoom;
gdouble const zdy = dy / zoom;
sp_selection_move_relative(selection, zdx, zdy);
+ SPDocument *doc = selection->layers()->getDocument();
if (dx == 0) {
- DocumentUndo::maybeDone(sp_desktop_document(desktop), "selector:move:vertical", SP_VERB_CONTEXT_SELECT,
+ DocumentUndo::maybeDone(doc, "selector:move:vertical", SP_VERB_CONTEXT_SELECT,
_("Move vertically by pixels"));
} else if (dy == 0) {
- DocumentUndo::maybeDone(sp_desktop_document(desktop), "selector:move:horizontal", SP_VERB_CONTEXT_SELECT,
+ DocumentUndo::maybeDone(doc, "selector:move:horizontal", SP_VERB_CONTEXT_SELECT,
_("Move horizontally by pixels"));
} else {
- DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_SELECT,
+ DocumentUndo::done(doc, SP_VERB_CONTEXT_SELECT,
_("Move"));
}
}
diff --git a/src/selection-chemistry.h b/src/selection-chemistry.h
index 8711a6cdf..f7a4f928c 100644
--- a/src/selection-chemistry.h
+++ b/src/selection-chemistry.h
@@ -53,7 +53,7 @@ namespace Inkscape {
void sp_selection_delete(SPDesktop *desktop);
void sp_selection_duplicate(SPDesktop *desktop, bool suppressDone = false);
-void sp_edit_clear_all(SPDesktop *desktop);
+void sp_edit_clear_all(Inkscape::Selection *selection);
void sp_edit_select_all(SPDesktop *desktop);
void sp_edit_select_all_in_all_layers (SPDesktop *desktop);
@@ -77,13 +77,13 @@ void sp_selection_tile(SPDesktop *desktop, bool apply = true);
void sp_selection_untile(SPDesktop *desktop);
//void sp_selection_group_impl(GSList const *reprs_to_group, Inkscape::XML::Node *group, Inkscape::XML::Document *xml_doc, SPDocument *doc);
-void sp_selection_group(SPDesktop *desktop);
-void sp_selection_ungroup(SPDesktop *desktop);
+void sp_selection_group(Inkscape::Selection *selection, SPDesktop *desktop);
+void sp_selection_ungroup(Inkscape::Selection *selection, SPDesktop *desktop);
-void sp_selection_raise(SPDesktop *desktop);
-void sp_selection_raise_to_top(SPDesktop *desktop);
-void sp_selection_lower(SPDesktop *desktop);
-void sp_selection_lower_to_bottom(SPDesktop *desktop);
+void sp_selection_raise(Inkscape::Selection *selection, SPDesktop *desktop);
+void sp_selection_raise_to_top(Inkscape::Selection *selection, SPDesktop *desktop);
+void sp_selection_lower(Inkscape::Selection *selection, SPDesktop *desktop);
+void sp_selection_lower_to_bottom(Inkscape::Selection *selection, SPDesktop *desktop);
SPCSSAttr *take_style_from_item (SPItem *item);
@@ -122,8 +122,8 @@ void sp_selection_scale (Inkscape::Selection *selection, gdouble grow);
void sp_selection_scale_screen (Inkscape::Selection *selection, gdouble grow_pixels);
void sp_selection_scale_times (Inkscape::Selection *selection, gdouble times);
-void sp_selection_move (SPDesktop *desktop, gdouble dx, gdouble dy);
-void sp_selection_move_screen (SPDesktop *desktop, gdouble dx, gdouble dy);
+void sp_selection_move (Inkscape::Selection *selection, gdouble dx, gdouble dy);
+void sp_selection_move_screen (Inkscape::Selection *selection, gdouble dx, gdouble dy);
void sp_selection_item_next (SPDesktop *desktop);
void sp_selection_item_prev (SPDesktop *desktop);
diff --git a/src/selection-describer.cpp b/src/selection-describer.cpp
index 72467c187..6ed8ca584 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->layers()->layerForObject(item);
+ SPObject *root = selection->layers()->currentRoot();
// Layer name
gchar *layer_name;
diff --git a/src/selection.cpp b/src/selection.cpp
index 564f1fdd3..784219c88 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 *layers, SPDesktop *desktop) :
_objs(NULL),
_reprs(NULL),
_items(NULL),
+ _layers(layers),
_desktop(desktop),
_selection_context(NULL),
_flags(0),
@@ -55,7 +55,7 @@ Selection::Selection(SPDesktop *desktop) :
Selection::~Selection() {
_clear();
- _desktop = NULL;
+ _layers = 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 = _layers->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 _layers->currentLayer();
}
bool Selection::includes(SPObject *obj) const {
@@ -358,6 +358,35 @@ SPItem *Selection::singleItem() {
}
}
+SPItem *Selection::smallestItem(Selection::CompareSize compare) {
+ return _sizeistItem(true, compare);
+}
+
+SPItem *Selection::largestItem(Selection::CompareSize compare) {
+ return _sizeistItem(false, compare);
+}
+
+SPItem *Selection::_sizeistItem(bool sml, Selection::CompareSize compare) {
+ GSList const *items = const_cast<Selection *>(this)->itemList();
+ gdouble max = sml ? 1e18 : 0;
+ SPItem *ist = NULL;
+
+ for ( GSList const *i = items; i != NULL ; i = i->next ) {
+ Geom::OptRect obox = SP_ITEM(i->data)->desktopPreferredBounds();
+ if (!obox || obox.isEmpty()) continue;
+ Geom::Rect bbox = *obox;
+
+ gdouble size = compare == 2 ? bbox.area() :
+ (compare == 1 ? bbox.width() : bbox.height());
+ size = sml ? size : size * -1;
+ if (size < max) {
+ max = size;
+ ist = SP_ITEM(i->data);
+ }
+ }
+ return ist;
+}
+
Inkscape::XML::Node *Selection::singleRepr() {
SPObject *obj=single();
return obj ? obj->getRepr() : NULL;
@@ -487,7 +516,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=_layers->getDocument()->getObjectById(id);
g_return_val_if_fail(object != NULL, NULL);
return object;
}
@@ -496,7 +525,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 = _layers->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..32eade21f 100644
--- a/src/selection.h
+++ b/src/selection.h
@@ -27,12 +27,14 @@
#include "sp-item.h"
#include "snapped-point.h"
+
class SPDesktop;
class SPItem;
class SPBox3D;
struct Persp3D;
namespace Inkscape {
+class LayerModel;
namespace XML {
class Node;
}
@@ -41,10 +43,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
@@ -62,19 +64,29 @@ class Selection : public Inkscape::GC::Managed<>,
public Inkscape::GC::Anchored
{
public:
+ enum CompareSize { HORIZONTAL, VERTICAL, AREA };
/**
* Constructs an selection object, bound to a particular
- * SPDesktop
+ * layer model
*
- * @param desktop the desktop in question
+ * @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(SPDesktop *desktop);
+ Selection(LayerModel *layers, 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 *layers() { return _layers; }
+
+ /**
* 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; }
@@ -210,6 +222,16 @@ public:
SPItem *singleItem();
/**
+ * Returns the smallest item from this selection.
+ */
+ SPItem *smallestItem(CompareSize compare);
+
+ /**
+ * Returns the largest item from this selection.
+ */
+ SPItem *largestItem(CompareSize compare);
+
+ /**
* Returns a single selected object's xml node.
*
* @return NULL unless exactly one object is selected
@@ -339,9 +361,11 @@ private:
void add_3D_boxes_recursively(SPObject *obj);
void remove_box_perspective(SPBox3D *box);
void remove_3D_boxes_recursively(SPObject *obj);
+ SPItem *_sizeistItem(bool sml, CompareSize compare);
std::list<SPBox3D *> _3dboxes;
+ LayerModel *_layers;
GC::soft_ptr<SPDesktop> _desktop;
SPObject* _selection_context;
guint _flags;
diff --git a/src/seltrans-handles.cpp b/src/seltrans-handles.cpp
index fc03789d6..6dd94d297 100644
--- a/src/seltrans-handles.cpp
+++ b/src/seltrans-handles.cpp
@@ -1,33 +1,40 @@
#include "seltrans-handles.h"
+#ifdef __cplusplus
+#undef N_
+#define N_(x) x
+#endif
-SPSelTransHandle const handles_scale[] = {
-//anchor cursor control action request x y
- {SP_ANCHOR_SE, GDK_TOP_LEFT_CORNER, 0, sp_sel_trans_scale, sp_sel_trans_scale_request, 0, 1},
- {SP_ANCHOR_S, GDK_TOP_SIDE, 3, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 0.5, 1},
- {SP_ANCHOR_SW, GDK_TOP_RIGHT_CORNER, 1, sp_sel_trans_scale, sp_sel_trans_scale_request, 1, 1},
- {SP_ANCHOR_W, GDK_RIGHT_SIDE, 2, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 1, 0.5},
- {SP_ANCHOR_NW, GDK_BOTTOM_RIGHT_CORNER, 0, sp_sel_trans_scale, sp_sel_trans_scale_request, 1, 0},
- {SP_ANCHOR_N, GDK_BOTTOM_SIDE, 3, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 0.5, 0},
- {SP_ANCHOR_NE, GDK_BOTTOM_LEFT_CORNER, 1, sp_sel_trans_scale, sp_sel_trans_scale_request, 0, 0},
- {SP_ANCHOR_E, GDK_LEFT_SIDE, 2, sp_sel_trans_stretch, sp_sel_trans_stretch_request, 0, 0.5}
+SPSelTransTypeInfo const handtypes[] = {
+ { DEF_COLOR, N_("<b>Squeeze or stretch</b> selection; with <b>Ctrl</b> to scale uniformly; with <b>Shift</b> to scale around rotation center") },
+ { DEF_COLOR, N_("<b>Scale</b> selection; with <b>Ctrl</b> to scale uniformly; with <b>Shift</b> to scale around rotation center") },
+ { DEF_COLOR, N_("<b>Skew</b> selection; with <b>Ctrl</b> to snap angle; with <b>Shift</b> to skew around the opposite side") },
+ { DEF_COLOR, N_("<b>Rotate</b> selection; with <b>Ctrl</b> to snap angle; with <b>Shift</b> to rotate around the opposite corner") },
+ { CEN_COLOR, N_("<b>Center</b> of rotation and skewing: drag to reposition; scaling with Shift also uses this center") }
};
-SPSelTransHandle const handles_rotate[] = {
- {SP_ANCHOR_SE, GDK_EXCHANGE, 4, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 0, 1},
- {SP_ANCHOR_S, GDK_SB_H_DOUBLE_ARROW, 5, sp_sel_trans_skew, sp_sel_trans_skew_request, 0.5, 1},
- {SP_ANCHOR_SW, GDK_EXCHANGE, 6, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 1, 1},
- {SP_ANCHOR_W, GDK_SB_V_DOUBLE_ARROW, 7, sp_sel_trans_skew, sp_sel_trans_skew_request, 1, 0.5},
- {SP_ANCHOR_NW, GDK_EXCHANGE, 8, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 1, 0},
- {SP_ANCHOR_N, GDK_SB_H_DOUBLE_ARROW, 9, sp_sel_trans_skew, sp_sel_trans_skew_request, 0.5, 0},
- {SP_ANCHOR_NE, GDK_EXCHANGE, 10, sp_sel_trans_rotate, sp_sel_trans_rotate_request, 0, 0},
- {SP_ANCHOR_E, GDK_SB_V_DOUBLE_ARROW, 11, sp_sel_trans_skew, sp_sel_trans_skew_request, 0, 0.5}
+SPSelTransHandle const hands[] = {
+//center handle will be 0 so we can reference it quickly.
+ {HANDLE_CENTER, SP_ANCHOR_CENTER, GDK_CROSSHAIR, 12, 0.5, 0.5},
+//handle-type anchor-nudge cursor image x y
+ {HANDLE_STRETCH, SP_ANCHOR_S, GDK_TOP_SIDE, 3, 0.5, 1},
+ {HANDLE_STRETCH, SP_ANCHOR_W, GDK_RIGHT_SIDE, 2, 1, 0.5},
+ {HANDLE_STRETCH, SP_ANCHOR_N, GDK_BOTTOM_SIDE, 3, 0.5, 0},
+ {HANDLE_STRETCH, SP_ANCHOR_E, GDK_LEFT_SIDE, 2, 0, 0.5},
+ {HANDLE_SCALE, SP_ANCHOR_SE, GDK_TOP_LEFT_CORNER, 0, 0, 1},
+ {HANDLE_SCALE, SP_ANCHOR_SW, GDK_TOP_RIGHT_CORNER, 1, 1, 1},
+ {HANDLE_SCALE, SP_ANCHOR_NW, GDK_BOTTOM_RIGHT_CORNER, 0, 1, 0},
+ {HANDLE_SCALE, SP_ANCHOR_NE, GDK_BOTTOM_LEFT_CORNER, 1, 0, 0},
+ {HANDLE_SKEW, SP_ANCHOR_S, GDK_SB_H_DOUBLE_ARROW, 8, 0.5, 1},
+ {HANDLE_SKEW, SP_ANCHOR_W, GDK_SB_V_DOUBLE_ARROW, 9, 1, 0.5},
+ {HANDLE_SKEW, SP_ANCHOR_N, GDK_SB_H_DOUBLE_ARROW, 10, 0.5, 0},
+ {HANDLE_SKEW, SP_ANCHOR_E, GDK_SB_V_DOUBLE_ARROW, 11, 0, 0.5},
+ {HANDLE_ROTATE, SP_ANCHOR_SE, GDK_EXCHANGE, 4, 0, 1},
+ {HANDLE_ROTATE, SP_ANCHOR_SW, GDK_EXCHANGE, 5, 1, 1},
+ {HANDLE_ROTATE, SP_ANCHOR_NW, GDK_EXCHANGE, 6, 1, 0},
+ {HANDLE_ROTATE, SP_ANCHOR_NE, GDK_EXCHANGE, 7, 0, 0},
};
-SPSelTransHandle const handle_center =
- {SP_ANCHOR_CENTER, GDK_CROSSHAIR, 12, sp_sel_trans_center, sp_sel_trans_center_request, 0.5, 0.5};
-
-
/*
Local Variables:
mode:c++
diff --git a/src/seltrans-handles.h b/src/seltrans-handles.h
index 14f50d784..740729a6e 100644
--- a/src/seltrans-handles.h
+++ b/src/seltrans-handles.h
@@ -21,40 +21,36 @@ namespace Inkscape
class SelTrans;
}
-struct SPSelTransHandle;
+guint32 const DEF_COLOR[] = { 0xff, 0xff6600, 0xff6600, 0xff, 0xff, 0xff };
+guint32 const CEN_COLOR[] = { 0x0, 0x0, 0x0, 0xff, 0xff0000b0, 0xff0000b0 };
+
+enum SPSelTransType {
+ HANDLE_STRETCH,
+ HANDLE_SCALE,
+ HANDLE_SKEW,
+ HANDLE_ROTATE,
+ HANDLE_CENTER
+};
-// request handlers
-gboolean sp_sel_trans_scale_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &handle, Geom::Point &p, guint state);
-gboolean sp_sel_trans_stretch_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &handle, Geom::Point &p, guint state);
-gboolean sp_sel_trans_skew_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &handle, Geom::Point &p, guint state);
-gboolean sp_sel_trans_rotate_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &handle, Geom::Point &p, guint state);
-gboolean sp_sel_trans_center_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &handle, Geom::Point &p, guint state);
+struct SPSelTransTypeInfo {
+ guint32 const *color;
+ gchar const *tip;
+};
+// One per handle type in order
+extern SPSelTransTypeInfo const handtypes[5];
-// action handlers
-void sp_sel_trans_scale(Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &p, guint state);
-void sp_sel_trans_stretch(Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &p, guint state);
-void sp_sel_trans_skew(Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &p, guint state);
-void sp_sel_trans_rotate(Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &p, guint state);
-void sp_sel_trans_center(Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &p, guint state);
+struct SPSelTransHandle;
struct SPSelTransHandle {
+ SPSelTransType type;
SPAnchorType anchor;
GdkCursorType cursor;
guint control;
- void (* action) (Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &p, guint state);
- gboolean (* request) (Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &p, guint state);
gdouble x, y;
};
-
-// TODO these must be purged:
-extern SPSelTransHandle const handles_scale[8];
-extern SPSelTransHandle const handles_rotate[8];
-extern SPSelTransHandle const handle_center;
+// These are 4 * each handle type + 1 for center
+int const NUMHANDS = 17;
+extern SPSelTransHandle const hands[17];
#endif // SEEN_SP_SELTRANS_HANDLES_H
diff --git a/src/seltrans.cpp b/src/seltrans.cpp
index 84c73e452..33bfe3e4a 100644
--- a/src/seltrans.cpp
+++ b/src/seltrans.cpp
@@ -48,12 +48,11 @@
#include <2geom/angle.h>
#include "display/snap-indicator.h"
#include "ui/control-manager.h"
+#include "seltrans-handles.h"
using Inkscape::ControlManager;
using Inkscape::DocumentUndo;
-static void sp_remove_handles(SPKnot *knot[], gint num);
-
static void sp_sel_trans_handle_grab(SPKnot *knot, guint state, gpointer data);
static void sp_sel_trans_handle_ungrab(SPKnot *knot, guint state, gpointer data);
static void sp_sel_trans_handle_click(SPKnot *knot, guint state, gpointer data);
@@ -62,7 +61,7 @@ static gboolean sp_sel_trans_handle_request(SPKnot *knot, Geom::Point *p, guint
extern GdkPixbuf *handles[];
-static gboolean sp_seltrans_handle_event(SPKnot *knot, GdkEvent *event, gpointer)
+static gboolean sp_sel_trans_handle_event(SPKnot *knot, GdkEvent *event, gpointer)
{
switch (event->type) {
case GDK_MOTION_NOTIFY:
@@ -112,7 +111,6 @@ Inkscape::SelTrans::SelTrans(SPDesktop *desktop) :
_opposite_for_bboxpoints(Geom::Point(0,0)),
_origin_for_specpoints(Geom::Point(0,0)),
_origin_for_bboxpoints(Geom::Point(0,0)),
- _chandle(NULL),
_stamp_cache(NULL),
_message_context(desktop->messageStack()),
_bounding_box_prefs_observer(*this)
@@ -124,16 +122,12 @@ Inkscape::SelTrans::SelTrans(SPDesktop *desktop) :
g_return_if_fail(desktop != NULL);
- for (int i = 0; i < 8; i++) {
- _shandle[i] = NULL;
- _rhandle[i] = NULL;
- }
-
_updateVolatileState();
_current_relative_affine.setIdentity();
_center_is_set = false; // reread _center from items, or set to bbox midpoint
+ _makeHandles();
_updateHandles();
_selection = sp_desktop_selection(desktop);
@@ -190,19 +184,9 @@ Inkscape::SelTrans::~SelTrans()
_sel_changed_connection.disconnect();
_sel_modified_connection.disconnect();
- for (unsigned int i = 0; i < 8; i++) {
- if (_shandle[i]) {
- g_object_unref(G_OBJECT(_shandle[i]));
- _shandle[i] = NULL;
- }
- if (_rhandle[i]) {
- g_object_unref(G_OBJECT(_rhandle[i]));
- _rhandle[i] = NULL;
- }
- }
- if (_chandle) {
- g_object_unref(G_OBJECT(_chandle));
- _chandle = NULL;
+ for (int i = 0; i < NUMHANDS; i++) {
+ g_object_unref(G_OBJECT(knots[i]));
+ knots[i] = NULL;
}
if (_norm) {
@@ -584,13 +568,11 @@ void Inkscape::SelTrans::stamp()
void Inkscape::SelTrans::_updateHandles()
{
+ for (int i = 0; i < NUMHANDS; i++)
+ sp_knot_hide(knots[i]);
+
if ( !_show_handles || _empty )
- {
- sp_remove_handles(_shandle, 8);
- sp_remove_handles(_rhandle, 8);
- sp_remove_handles(&_chandle, 1);
return;
- }
if (!_center_is_set) {
_center = _desktop->selection->center();
@@ -598,57 +580,12 @@ void Inkscape::SelTrans::_updateHandles()
}
if ( _state == STATE_SCALE ) {
- sp_remove_handles(_rhandle, 8);
- sp_remove_handles(&_chandle, 1);
- _showHandles(_shandle, handles_scale, 8,
- _("<b>Squeeze or stretch</b> selection; with <b>Ctrl</b> to scale uniformly; with <b>Shift</b> to scale around rotation center"),
- _("<b>Scale</b> selection; with <b>Ctrl</b> to scale uniformly; with <b>Shift</b> to scale around rotation center"));
+ _showHandles(HANDLE_STRETCH);
+ _showHandles(HANDLE_SCALE);
} else {
- sp_remove_handles(_shandle, 8);
- _showHandles(_rhandle, handles_rotate, 8,
- _("<b>Skew</b> selection; with <b>Ctrl</b> to snap angle; with <b>Shift</b> to skew around the opposite side"),
- _("<b>Rotate</b> selection; with <b>Ctrl</b> to snap angle; with <b>Shift</b> to rotate around the opposite corner"));
- // center handle
- /* Assuming that the center handle is in its default position, ie. in the center:
- * Multiple handles will be shown, for rotating, skewing and the center handle. For straight lines, the bounding box of the center handle will be
- * fully overlapped by bounding boxes of two of the skew handles. Due to the internals of sp_canvas_group_point, the center handle must be the
- * last handle in the SPCanvasGroup if it is to be selectable in such a case. So we have made sure here that the center handle is added to the
- * group after the rotation handles (determined by the chronological order of sp_knot_new() calls)
- * Now when the center handle is in still in the center, the skew handles can be selected because because the bounding box of the
- * center handle does not fully overlap the bounding box of either of the skew handles. However, if the center handle has been moved such that it
- * covers one of the other eight handles, then either the opposite handle has to be used (in case of rotating), or the center handle has to be moved.
- * Although this is annoying, this is still better than not being able to select the center handle at all
- */
- if ( _chandle == NULL ) {
- _chandle = sp_knot_new(_desktop, _("<b>Center</b> of rotation and skewing: drag to reposition; scaling with Shift also uses this center"));
-
- _chandle->setShape (SP_CTRL_SHAPE_BITMAP);
- _chandle->setSize (13);
- _chandle->setAnchor (handle_center.anchor);
- _chandle->setMode (SP_CTRL_MODE_XOR);
- _chandle->setFill(0x00000000, 0x00000000, 0x00000000);
- _chandle->setStroke(0x000000ff, 0xff0000b0, 0xff0000b0);
- _chandle->setPixbuf(handles[handle_center.control]);
- sp_knot_update_ctrl(_chandle);
-
- g_signal_connect(G_OBJECT(_chandle), "request",
- G_CALLBACK(sp_sel_trans_handle_request), (gpointer) &handle_center);
- g_signal_connect(G_OBJECT(_chandle), "moved",
- G_CALLBACK(sp_sel_trans_handle_new_event), (gpointer) &handle_center);
- g_signal_connect(G_OBJECT(_chandle), "grabbed",
- G_CALLBACK(sp_sel_trans_handle_grab), (gpointer) &handle_center);
- g_signal_connect(G_OBJECT(_chandle), "ungrabbed",
- G_CALLBACK(sp_sel_trans_handle_ungrab), (gpointer) &handle_center);
- g_signal_connect(G_OBJECT(_chandle), "clicked",
- G_CALLBACK(sp_sel_trans_handle_click), (gpointer) &handle_center);
- }
-
- if ( _center ) {
- sp_knot_show(_chandle);
- sp_knot_moveto(_chandle, *_center);
- } else {
- sp_remove_handles(&_chandle, 1);
- }
+ _showHandles(HANDLE_SKEW);
+ _showHandles(HANDLE_ROTATE);
+ _showHandles(HANDLE_CENTER);
}
}
@@ -673,53 +610,55 @@ void Inkscape::SelTrans::_updateVolatileState()
_strokewidth = stroke_average_width (selection->itemList());
}
-static void sp_remove_handles(SPKnot *knot[], gint num)
+void Inkscape::SelTrans::_showHandles(SPSelTransType type)
{
- for (int i = 0; i < num; i++) {
- if (knot[i] != NULL) {
- sp_knot_hide(knot[i]);
- }
+ // shouldn't have nullary bbox, but knots
+ g_assert(_bbox);
+
+ for (int i = 0; i < NUMHANDS; i++) {
+ if (hands[i].type != type)
+ continue;
+
+ // Position knots to scale the selection bbox
+ Geom::Point const bpos(hands[i].x, hands[i].y);
+ Geom::Point p(_bbox->min() + (_bbox->dimensions() * Geom::Scale(bpos)));
+ sp_knot_moveto(knots[i], p);
+ sp_knot_show(knots[i]);
+
+ // This controls the center handle's position, because the default can
+ // be moved and needs to be remembered.
+ if( type == HANDLE_CENTER && _center )
+ sp_knot_moveto(knots[i], *_center);
}
}
-void Inkscape::SelTrans::_showHandles(SPKnot *knot[], SPSelTransHandle const handle[], gint num,
- gchar const *even_tip, gchar const *odd_tip)
+void Inkscape::SelTrans::_makeHandles()
{
- g_return_if_fail( !_empty );
-
- for (int i = 0; i < num; i++) {
- if (knot[i] == NULL) {
- knot[i] = sp_knot_new(_desktop, i % 2 ? even_tip : odd_tip);
-
- knot[i]->setShape (SP_CTRL_SHAPE_BITMAP);
- knot[i]->setSize (13);
- knot[i]->setAnchor (handle[i].anchor);
- knot[i]->setMode (SP_CTRL_MODE_XOR);
- knot[i]->setFill(0x000000ff, 0x00ff6600, 0x00ff6600); // inversion, green, green
- knot[i]->setStroke(0x000000ff, 0x000000ff, 0x000000ff); // inversion
- knot[i]->setPixbuf(handles[handle[i].control]);
- sp_knot_update_ctrl(knot[i]);
-
- g_signal_connect(G_OBJECT(knot[i]), "request",
- G_CALLBACK(sp_sel_trans_handle_request), (gpointer) &handle[i]);
- g_signal_connect(G_OBJECT(knot[i]), "moved",
- G_CALLBACK(sp_sel_trans_handle_new_event), (gpointer) &handle[i]);
- g_signal_connect(G_OBJECT(knot[i]), "grabbed",
- G_CALLBACK(sp_sel_trans_handle_grab), (gpointer) &handle[i]);
- g_signal_connect(G_OBJECT(knot[i]), "ungrabbed",
- G_CALLBACK(sp_sel_trans_handle_ungrab), (gpointer) &handle[i]);
- g_signal_connect(G_OBJECT(knot[i]), "event", G_CALLBACK(sp_seltrans_handle_event), (gpointer) &handle[i]);
- }
- sp_knot_show(knot[i]);
-
- Geom::Point const handle_pt(handle[i].x, handle[i].y);
- // shouldn't have nullary bbox, but knots
- g_assert(_bbox);
- Geom::Point p( _bbox->min()
- + ( _bbox->dimensions()
- * Geom::Scale(handle_pt) ) );
-
- sp_knot_moveto(knot[i], p);
+ for (int i = 0; i < NUMHANDS; i++) {
+ SPSelTransTypeInfo info = handtypes[hands[i].type];
+ knots[i] = sp_knot_new(_desktop, info.tip);
+
+ knots[i]->setShape(SP_CTRL_SHAPE_BITMAP);
+ knots[i]->setSize(13);
+ knots[i]->setAnchor(hands[i].anchor);
+ knots[i]->setMode(SP_CTRL_MODE_XOR);
+ knots[i]->setFill(info.color[0], info.color[1], info.color[2]);
+ knots[i]->setStroke(info.color[3], info.color[4], info.color[5]);
+ knots[i]->setPixbuf(handles[hands[i].control]);
+ sp_knot_update_ctrl(knots[i]);
+
+ g_signal_connect(G_OBJECT(knots[i]), "request",
+ G_CALLBACK(sp_sel_trans_handle_request), (gpointer) &hands[i]);
+ g_signal_connect(G_OBJECT(knots[i]), "moved",
+ G_CALLBACK(sp_sel_trans_handle_new_event), (gpointer) &hands[i]);
+ g_signal_connect(G_OBJECT(knots[i]), "grabbed",
+ G_CALLBACK(sp_sel_trans_handle_grab), (gpointer) &hands[i]);
+ g_signal_connect(G_OBJECT(knots[i]), "ungrabbed",
+ G_CALLBACK(sp_sel_trans_handle_ungrab), (gpointer) &hands[i]);
+ g_signal_connect(G_OBJECT(knots[i]), "clicked",
+ G_CALLBACK(sp_sel_trans_handle_click), (gpointer) &hands[i]);
+ g_signal_connect(G_OBJECT(knots[i]), "event",
+ G_CALLBACK(sp_sel_trans_handle_event), (gpointer) &hands[i]);
}
}
@@ -758,8 +697,8 @@ static void sp_sel_trans_handle_click(SPKnot *knot, guint state, gpointer data)
void Inkscape::SelTrans::handleClick(SPKnot */*knot*/, guint state, SPSelTransHandle const &handle)
{
- switch (handle.anchor) {
- case SP_ANCHOR_CENTER:
+ switch (handle.type) {
+ case HANDLE_CENTER:
if (state & GDK_SHIFT_MASK) {
// Unset the center position for all selected items
for (GSList const *l = _desktop->selection->itemList(); l; l = l->next) {
@@ -780,8 +719,8 @@ void Inkscape::SelTrans::handleClick(SPKnot */*knot*/, guint state, SPSelTransHa
void Inkscape::SelTrans::handleGrab(SPKnot *knot, guint /*state*/, SPSelTransHandle const &handle)
{
- switch (handle.anchor) {
- case SP_ANCHOR_CENTER:
+ switch (handle.type) {
+ case HANDLE_CENTER:
g_object_set(G_OBJECT(_grip),
"shape", SP_CTRL_SHAPE_BITMAP,
"size", 13.0,
@@ -795,7 +734,6 @@ void Inkscape::SelTrans::handleGrab(SPKnot *knot, guint /*state*/, SPSelTransHan
NULL);
sp_canvas_item_show(_norm);
sp_canvas_item_show(_grip);
-
break;
}
@@ -816,21 +754,35 @@ void Inkscape::SelTrans::handleNewEvent(SPKnot *knot, Geom::Point *position, gui
return;
}
}
-
- handle.action(this, handle, *position, state);
+ switch (handle.type) {
+ case HANDLE_SCALE:
+ scale(*position, state);
+ break;
+ case HANDLE_STRETCH:
+ stretch(handle, *position, state);
+ break;
+ case HANDLE_SKEW:
+ skew(handle, *position, state);
+ break;
+ case HANDLE_ROTATE:
+ rotate(*position, state);
+ break;
+ case HANDLE_CENTER:
+ setCenter(*position);
+ break;
+ }
}
gboolean Inkscape::SelTrans::handleRequest(SPKnot *knot, Geom::Point *position, guint state, SPSelTransHandle const &handle)
{
- if (!SP_KNOT_IS_GRABBED(knot)) {
+ if (!SP_KNOT_IS_GRABBED(knot))
return TRUE;
- }
// When holding shift while rotating or skewing, the transformation will be
// relative to the point opposite of the handle; otherwise it will be relative
// to the center as set for the selection
- if ((!(state & GDK_SHIFT_MASK) == !(_state == STATE_ROTATE)) && (&handle != &handle_center)) {
+ if ((!(state & GDK_SHIFT_MASK) == !(_state == STATE_ROTATE)) && (handle.type != HANDLE_CENTER)) {
_origin = _opposite;
_origin_for_bboxpoints = _opposite_for_bboxpoints;
_origin_for_specpoints = _opposite_for_specpoints;
@@ -842,10 +794,10 @@ gboolean Inkscape::SelTrans::handleRequest(SPKnot *knot, Geom::Point *position,
// FIXME
return TRUE;
}
- if (handle.request(this, handle, *position, state)) {
+ if (request(handle, *position, state)) {
sp_knot_set_position(knot, *position, state);
SP_CTRL(_grip)->moveto(*position);
- if (&handle == &handle_center) {
+ if (handle.type == HANDLE_CENTER) {
SP_CTRL(_norm)->moveto(*position);
} else {
SP_CTRL(_norm)->moveto(_origin);
@@ -908,36 +860,6 @@ static double sign(double const x)
: 1 );
}
-gboolean sp_sel_trans_scale_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &, Geom::Point &pt, guint state)
-{
- return seltrans->scaleRequest(pt, state);
-}
-
-gboolean sp_sel_trans_stretch_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &handle, Geom::Point &pt, guint state)
-{
- return seltrans->stretchRequest(handle, pt, state);
-}
-
-gboolean sp_sel_trans_skew_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &handle, Geom::Point &pt, guint state)
-{
- return seltrans->skewRequest(handle, pt, state);
-}
-
-gboolean sp_sel_trans_rotate_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &, Geom::Point &pt, guint state)
-{
- return seltrans->rotateRequest(pt, state);
-}
-
-gboolean sp_sel_trans_center_request(Inkscape::SelTrans *seltrans,
- SPSelTransHandle const &, Geom::Point &pt, guint state)
-{
- return seltrans->centerRequest(pt, state);
-}
-
gboolean Inkscape::SelTrans::scaleRequest(Geom::Point &pt, guint state)
{
@@ -1117,6 +1039,24 @@ gboolean Inkscape::SelTrans::stretchRequest(SPSelTransHandle const &handle, Geom
return TRUE;
}
+gboolean Inkscape::SelTrans::request(SPSelTransHandle const &handle, Geom::Point &pt, guint state)
+{
+ // These _should_ be in the handstype somewhere instead
+ switch (handle.type) {
+ case HANDLE_SCALE:
+ return scaleRequest(pt, state);
+ case HANDLE_STRETCH:
+ return stretchRequest(handle, pt, state);
+ case HANDLE_SKEW:
+ return skewRequest(handle, pt, state);
+ case HANDLE_ROTATE:
+ return rotateRequest(pt, state);
+ case HANDLE_CENTER:
+ return centerRequest(pt, state);
+ }
+ return FALSE;
+}
+
gboolean Inkscape::SelTrans::skewRequest(SPSelTransHandle const &handle, Geom::Point &pt, guint state)
{
/* When skewing (or rotating):
@@ -1347,25 +1287,7 @@ gboolean Inkscape::SelTrans::centerRequest(Geom::Point &pt, guint state)
*
*/
-void sp_sel_trans_stretch(Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &pt, guint state)
-{
- seltrans->stretch(handle, pt, state);
-}
-
-void sp_sel_trans_scale(Inkscape::SelTrans *seltrans, SPSelTransHandle const &, Geom::Point &pt, guint state)
-{
- seltrans->scale(pt, state);
-}
-
-void sp_sel_trans_skew(Inkscape::SelTrans *seltrans, SPSelTransHandle const &handle, Geom::Point &pt, guint state)
-{
- seltrans->skew(handle, pt, state);
-}
-void sp_sel_trans_rotate(Inkscape::SelTrans *seltrans, SPSelTransHandle const &, Geom::Point &pt, guint state)
-{
- seltrans->rotate(pt, state);
-}
void Inkscape::SelTrans::stretch(SPSelTransHandle const &/*handle*/, Geom::Point &/*pt*/, guint /*state*/)
{
@@ -1387,12 +1309,6 @@ void Inkscape::SelTrans::rotate(Geom::Point &/*pt*/, guint /*state*/)
transform(_relative_affine, _origin);
}
-void sp_sel_trans_center(Inkscape::SelTrans *seltrans, SPSelTransHandle const &, Geom::Point &pt, guint /*state*/)
-{
- seltrans->setCenter(pt);
-}
-
-
void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state)
{
SnapManager &m = _desktop->namedview->snap_manager;
diff --git a/src/seltrans.h b/src/seltrans.h
index 10860f58f..d97375520 100644
--- a/src/seltrans.h
+++ b/src/seltrans.h
@@ -25,6 +25,7 @@
#include "message-context.h"
#include <vector>
#include "sp-item.h"
+#include "seltrans-handles.h"
struct SPKnot;
class SPDesktop;
@@ -64,6 +65,7 @@ public:
void scale(Geom::Point &pt, guint state);
void skew(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
void rotate(Geom::Point &pt, guint state);
+ gboolean request(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
gboolean scaleRequest(Geom::Point &pt, guint state);
gboolean stretchRequest(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
gboolean skewRequest(SPSelTransHandle const &handle, Geom::Point &pt, guint state);
@@ -91,7 +93,7 @@ public:
return _grabbed;
}
bool centerIsVisible() {
- return ( _chandle && SP_KNOT_IS_VISIBLE (_chandle) );
+ return ( SP_KNOT_IS_VISIBLE (knots[0]) );
}
void getNextClosestPoint(bool reverse);
@@ -115,8 +117,8 @@ private:
void _selChanged(Inkscape::Selection *selection);
void _selModified(Inkscape::Selection *selection, guint flags);
void _boundingBoxPrefsChanged(int prefs_bbox);
- void _showHandles(SPKnot *knot[], SPSelTransHandle const handle[], gint num,
- gchar const *even_tip, gchar const *odd_tip);
+ void _makeHandles();
+ void _showHandles(SPSelTransType type);
Geom::Point _getGeomHandlePos(Geom::Point const &visual_handle_pos);
Geom::Point _calcAbsAffineDefault(Geom::Scale const default_scale);
Geom::Point _calcAbsAffineGeom(Geom::Scale const geom_scale);
@@ -176,10 +178,9 @@ private:
boost::optional<Geom::Point> _center;
bool _center_is_set; ///< we've already set _center, no need to reread it from items
+ int _center_handle;
- SPKnot *_shandle[8];
- SPKnot *_rhandle[8];
- SPKnot *_chandle;
+ SPKnot *knots[NUMHANDS];
SPCanvasItem *_norm;
SPCanvasItem *_grip;
SPCtrlLine *_l[4];
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..356cf0161 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->layers()->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/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp
index 7f88824f7..8845b60e5 100644
--- a/src/ui/dialog/align-and-distribute.cpp
+++ b/src/ui/dialog/align-and-distribute.cpp
@@ -88,119 +88,73 @@ Action::Action(const Glib::ustring &id,
}
-void ActionAlign::do_action(SPDesktop *desktop, int index) {
-
+void ActionAlign::do_action(SPDesktop *desktop, int index)
+{
Inkscape::Selection *selection = sp_desktop_selection(desktop);
if (!selection) return;
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
bool sel_as_group = prefs->getBool("/dialogs/align/sel-as-groups");
- int prefs_bbox = prefs->getBool("/tools/bounding_box");
using Inkscape::Util::GSListConstIterator;
std::list<SPItem *> selected;
selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
if (selected.empty()) return;
- Geom::Point mp; //Anchor point
- AlignAndDistribute::AlignTarget target = AlignAndDistribute::getAlignTarget();
- const Coeffs &a= _allCoeffs[index];
- switch (target)
- {
- case AlignAndDistribute::LAST:
- case AlignAndDistribute::FIRST:
- case AlignAndDistribute::BIGGEST:
- case AlignAndDistribute::SMALLEST:
+ const Coeffs &a = _allCoeffs[index];
+ SPItem *focus = NULL;
+ Geom::OptRect b = Geom::OptRect();
+ Selection::CompareSize horiz = (a.mx0 != 0.0) || (a.mx1 != 0.0)
+ ? Selection::HORIZONTAL : Selection::VERTICAL;
+
+ switch (AlignTarget(prefs->getInt("/dialogs/align/align-to", 6)))
{
- //Check 2 or more selected objects
- std::list<SPItem *>::iterator second(selected.begin());
- ++second;
- if (second == selected.end())
- return;
- //Find the master (anchor on which the other objects are aligned)
- std::list<SPItem *>::iterator master(
- AlignAndDistribute::find_master (
- selected,
- (a.mx0 != 0.0) ||
- (a.mx1 != 0.0) )
- );
- //remove the master from the selection
- SPItem * thing = *master;
- // TODO: either uncomment or remove the following commented lines, depending on which
- // behaviour of moving objects makes most sense; also cf. discussion at
- // https://bugs.launchpad.net/inkscape/+bug/255933
- /*if (!sel_as_group) { */
- selected.erase(master);
- /*}*/
- //Compute the anchor point
- Geom::OptRect b = !prefs_bbox ? thing->desktopVisualBounds() : thing->desktopGeometricBounds();
- if (b) {
- mp = Geom::Point(a.mx0 * b->min()[Geom::X] + a.mx1 * b->max()[Geom::X],
- a.my0 * b->min()[Geom::Y] + a.my1 * b->max()[Geom::Y]);
- } else {
- return;
- }
+ case LAST:
+ focus = SP_ITEM(*selected.begin());
break;
- }
-
- case AlignAndDistribute::PAGE:
- mp = Geom::Point(a.mx1 * sp_desktop_document(desktop)->getWidth(),
- a.my1 * sp_desktop_document(desktop)->getHeight());
+ case FIRST:
+ focus = SP_ITEM(*--(selected.end()));
break;
-
- case AlignAndDistribute::DRAWING:
- {
- Geom::OptRect b = !prefs_bbox ? sp_desktop_document(desktop)->getRoot()->desktopVisualBounds()
- : sp_desktop_document(desktop)->getRoot()->desktopGeometricBounds();
- if (b) {
- mp = Geom::Point(a.mx0 * b->min()[Geom::X] + a.mx1 * b->max()[Geom::X],
- a.my0 * b->min()[Geom::Y] + a.my1 * b->max()[Geom::Y]);
- } else {
- return;
- }
+ case BIGGEST:
+ focus = selection->largestItem(horiz);
break;
- }
-
- case AlignAndDistribute::SELECTION:
- {
- Geom::OptRect b = !prefs_bbox ? selection->visualBounds() : selection->geometricBounds();
- if (b) {
- mp = Geom::Point(a.mx0 * b->min()[Geom::X] + a.mx1 * b->max()[Geom::X],
- a.my0 * b->min()[Geom::Y] + a.my1 * b->max()[Geom::Y]);
- } else {
- return;
- }
+ case SMALLEST:
+ focus = selection->smallestItem(horiz);
+ break;
+ case PAGE:
+ b = sp_desktop_document(desktop)->preferredBounds();
+ break;
+ case DRAWING:
+ b = sp_desktop_document(desktop)->getRoot()->desktopPreferredBounds();
+ break;
+ case SELECTION:
+ b = selection->preferredBounds();
break;
- }
-
default:
g_assert_not_reached ();
break;
- }; // end of switch
+ };
+
+ if(focus)
+ b = focus->desktopPreferredBounds();
+ g_return_if_fail(b);
- // Top hack: temporarily set clone compensation to unmoved, so that we can align/distribute
- // clones with their original (and the move of the original does not disturb the
- // clones). The only problem with this is that if there are outside-of-selection clones of
- // a selected original, they will be unmoved too, possibly contrary to user's
- // expecation. However this is a minor point compared to making align/distribute always
- // work as expected, and "unmoved" is the default option anyway.
- int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
- prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
+ // Generate the move point from the selected bounding box
+ Geom::Point mp = Geom::Point(a.mx0 * b->min()[Geom::X] + a.mx1 * b->max()[Geom::X],
+ a.my0 * b->min()[Geom::Y] + a.my1 * b->max()[Geom::Y]);
bool changed = false;
- Geom::OptRect b;
if (sel_as_group)
- b = !prefs_bbox ? selection->visualBounds() : selection->geometricBounds();
+ b = selection->preferredBounds();
//Move each item in the selected list separately
for (std::list<SPItem *>::iterator it(selected.begin());
- it != selected.end();
- ++it)
+ it != selected.end(); ++it)
{
sp_desktop_document (desktop)->ensureUpToDate();
if (!sel_as_group)
- b = !prefs_bbox ? (*it)->desktopVisualBounds() : (*it)->desktopGeometricBounds();
- if (b) {
+ b = (*it)->desktopPreferredBounds();
+ if (b && (!focus || (*it) != focus)) {
Geom::Point const sp(a.sx0 * b->min()[Geom::X] + a.sx1 * b->max()[Geom::X],
a.sy0 * b->min()[Geom::Y] + a.sy1 * b->max()[Geom::Y]);
Geom::Point const mp_rel( mp - sp );
@@ -211,15 +165,10 @@ void ActionAlign::do_action(SPDesktop *desktop, int index) {
}
}
- // restore compensation setting
- prefs->setInt("/options/clonecompensation/value", saved_compensation);
-
if (changed) {
DocumentUndo::done( sp_desktop_document(desktop) , SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
_("Align"));
}
-
-
}
@@ -1265,69 +1214,6 @@ void AlignAndDistribute::addBaselineButton(const Glib::ustring &id, const Glib::
*this, table, orientation, distribute));
}
-
-
-
-std::list<SPItem *>::iterator AlignAndDistribute::find_master( std::list<SPItem *> &list, bool horizontal){
- std::list<SPItem *>::iterator master = list.end();
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- int prefs_bbox = prefs->getBool("/tools/bounding_box");
- switch (getAlignTarget()) {
- case LAST:
- return list.begin();
- break;
-
- case FIRST:
- return --(list.end());
- break;
-
- case BIGGEST:
- {
- gdouble max = -1e18;
- for (std::list<SPItem *>::iterator it = list.begin(); it != list.end(); ++it) {
- Geom::OptRect b = !prefs_bbox ? (*it)->desktopVisualBounds() : (*it)->desktopGeometricBounds();
- if (b) {
- gdouble dim = (*b)[horizontal ? Geom::X : Geom::Y].extent();
- if (dim > max) {
- max = dim;
- master = it;
- }
- }
- }
- return master;
- }
-
- case SMALLEST:
- {
- gdouble max = 1e18;
- for (std::list<SPItem *>::iterator it = list.begin(); it != list.end(); ++it) {
- Geom::OptRect b = !prefs_bbox ? (*it)->desktopVisualBounds() : (*it)->desktopGeometricBounds();
- if (b) {
- gdouble dim = (*b)[horizontal ? Geom::X : Geom::Y].extent();
- if (dim < max) {
- max = dim;
- master = it;
- }
- }
- }
- return master;
- }
-
- default:
- g_assert_not_reached ();
- break;
-
- } // end of switch statement
- return master;
-}
-
-AlignAndDistribute::AlignTarget AlignAndDistribute::getAlignTarget() {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- return AlignTarget(prefs->getInt("/dialogs/align/align-to", 6));
-}
-
-
-
} // namespace Dialog
} // namespace UI
} // namespace Inkscape
diff --git a/src/ui/dialog/align-and-distribute.h b/src/ui/dialog/align-and-distribute.h
index c9165a83e..dfd84535b 100644
--- a/src/ui/dialog/align-and-distribute.h
+++ b/src/ui/dialog/align-and-distribute.h
@@ -47,12 +47,6 @@ public:
static AlignAndDistribute &getInstance() { return *new AlignAndDistribute(); }
- enum AlignTarget { LAST=0, FIRST, BIGGEST, SMALLEST, PAGE, DRAWING, SELECTION };
-
-
-
- static AlignTarget getAlignTarget();
-
#if WITH_GTKMM_3_0
Gtk::Grid &align_table(){return _alignTable;}
Gtk::Grid &distribute_table(){return _distributeTable;}
@@ -67,7 +61,6 @@ public:
Gtk::Table &nodes_table(){return _nodesTable;}
#endif
- static std::list<SPItem *>::iterator find_master(std::list <SPItem *> &list, bool horizontal);
void setMode(bool nodeEdit);
Geom::OptRect randomize_bbox;
@@ -189,6 +182,7 @@ public :
double sx0, sx1, sy0, sy1;
int verb_id;
};
+ enum AlignTarget { LAST=0, FIRST, BIGGEST, SMALLEST, PAGE, DRAWING, SELECTION };
ActionAlign(const Glib::ustring &id,
const Glib::ustring &tiptext,
guint row, guint column,
@@ -204,6 +198,7 @@ public :
* Static function called to align from a keyboard shortcut
*/
static void do_verb_action(SPDesktop *desktop, int verb);
+ static int verb_to_coeff(int verb);
private :
@@ -217,7 +212,6 @@ private :
}
static void do_action(SPDesktop *desktop, int index);
- static int verb_to_coeff(int verb);
guint _index;
AlignAndDistribute &_dialog;
diff --git a/src/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp
index ce923f6b4..c41046123 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 b71686a17..26bc52947 100644
--- a/src/ui/dialog/symbols.cpp
+++ b/src/ui/dialog/symbols.cpp
@@ -67,6 +67,7 @@
#include "verbs.h"
#include "helper/action.h"
+#include "helper/action-context.h"
#include "xml/repr.h"
namespace Inkscape {
@@ -329,13 +330,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/tool/transform-handle-set.cpp b/src/ui/tool/transform-handle-set.cpp
index f0bf149f4..30963cabd 100644
--- a/src/ui/tool/transform-handle-set.cpp
+++ b/src/ui/tool/transform-handle-set.cpp
@@ -458,9 +458,9 @@ private:
static Glib::RefPtr<Gdk::Pixbuf> _corner_to_pixbuf(unsigned c) {
sp_select_context_get_type();
switch (c % 4) {
- case 0: return Glib::wrap(handles[10], true);
- case 1: return Glib::wrap(handles[8], true);
- case 2: return Glib::wrap(handles[6], true);
+ case 0: return Glib::wrap(handles[7], true);
+ case 1: return Glib::wrap(handles[6], true);
+ case 2: return Glib::wrap(handles[5], true);
default: return Glib::wrap(handles[4], true);
}
}
@@ -605,9 +605,9 @@ private:
static Glib::RefPtr<Gdk::Pixbuf> _side_to_pixbuf(unsigned s) {
sp_select_context_get_type();
switch (s % 4) {
- case 0: return Glib::wrap(handles[9], true);
- case 1: return Glib::wrap(handles[7], true);
- case 2: return Glib::wrap(handles[5], true);
+ case 0: return Glib::wrap(handles[10], true);
+ case 1: return Glib::wrap(handles[9], true);
+ case 2: return Glib::wrap(handles[8], true);
default: return Glib::wrap(handles[11], true);
}
}
diff --git a/src/ui/widget/dock.cpp b/src/ui/widget/dock.cpp
index 2bfc7e0df..52e9ea605 100644
--- a/src/ui/widget/dock.cpp
+++ b/src/ui/widget/dock.cpp
@@ -48,11 +48,21 @@ const int Dock::_default_dock_bar_width = 36;
Dock::Dock(Gtk::Orientation orientation)
- : _gdl_dock (GDL_DOCK (gdl_dock_new())),
- _gdl_dock_bar (GDL_DOCK_BAR (gdl_dock_bar_new(GDL_DOCK(_gdl_dock)))),
+ : _gdl_dock(gdl_dock_new()),
+#if WITH_GDL_3_6
+ _gdl_dock_bar(GDL_DOCK_BAR(gdl_dock_bar_new(G_OBJECT(_gdl_dock)))),
+#else
+ _gdl_dock_bar(GDL_DOCK_BAR(gdl_dock_bar_new(GDL_DOCK(_gdl_dock)))),
+#endif
_scrolled_window (Gtk::manage(new Gtk::ScrolledWindow))
{
- gdl_dock_bar_set_orientation(_gdl_dock_bar, static_cast<GtkOrientation>(orientation));
+#if WITH_GDL_3_6
+ gtk_orientable_set_orientation(GTK_ORIENTABLE(_gdl_dock_bar),
+ static_cast<GtkOrientation>(orientation));
+#else
+ gdl_dock_bar_set_orientation(_gdl_dock_bar,
+ static_cast<GtkOrientation>(orientation));
+#endif
#if WITH_GTKMM_3_0
switch(orientation) {
@@ -127,7 +137,9 @@ Dock::~Dock()
void Dock::addItem(DockItem& item, DockItem::Placement placement)
{
_dock_items.push_back(&item);
- gdl_dock_add_item(_gdl_dock, GDL_DOCK_ITEM(item.gobj()), (GdlDockPlacement)placement);
+ gdl_dock_add_item(GDL_DOCK(_gdl_dock),
+ GDL_DOCK_ITEM(item.gobj()),
+ (GdlDockPlacement)placement);
// FIXME: This is a hack to prevent the dock from expanding the main window, this can't be done
// initially as the paned doesn't exist.
diff --git a/src/ui/widget/dock.h b/src/ui/widget/dock.h
index 611c10f46..33e60b836 100644
--- a/src/ui/widget/dock.h
+++ b/src/ui/widget/dock.h
@@ -74,11 +74,11 @@ protected:
/** Interface widgets, will be packed like
* _scrolled_window -> (_dock_box -> (_paned -> (_dock -> _filler) | _dock_bar))
*/
- Gtk::Box *_dock_box;
- Gtk::Paned* _paned;
- GdlDock *_gdl_dock;
- GdlDockBar *_gdl_dock_bar;
- Gtk::VBox _filler;
+ Gtk::Box *_dock_box;
+ Gtk::Paned *_paned;
+ GtkWidget *_gdl_dock;
+ GdlDockBar *_gdl_dock_bar;
+ Gtk::VBox _filler;
Gtk::ScrolledWindow *_scrolled_window;
/** Internal signal handlers */
diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp
index 14e280f6d..73b75090b 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 "util/units.h"
#include "inkscape.h"
#include "sp-namedview.h"
@@ -616,7 +617,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/util/units.cpp b/src/util/units.cpp
index e120207c9..f6350d569 100644
--- a/src/util/units.cpp
+++ b/src/util/units.cpp
@@ -22,6 +22,39 @@
#include "path-prefix.h"
#include "streq.h"
+using Inkscape::Util::UNIT_TYPE_DIMENSIONLESS;
+using Inkscape::Util::UNIT_TYPE_LINEAR;
+using Inkscape::Util::UNIT_TYPE_RADIAL;
+using Inkscape::Util::UNIT_TYPE_FONT_HEIGHT;
+
+namespace
+{
+
+/**
+ * A std::map that gives the data type value for the string version.
+ *
+ * Note that we'd normally not return a reference to an internal version, but
+ * for this constant case it allows us to check against getTypeMappings().end().
+ */
+/** @todo consider hiding map behind hasFoo() and getFoo() type functions.*/
+std::map<Glib::ustring, Inkscape::Util::UnitType> &getTypeMappings()
+{
+ static bool init = false;
+ static std::map<Glib::ustring, Inkscape::Util::UnitType> typeMap;
+ if (!init)
+ {
+ init = true;
+ typeMap["DIMENSIONLESS"] = UNIT_TYPE_DIMENSIONLESS;
+ typeMap["LINEAR"] = UNIT_TYPE_LINEAR;
+ typeMap["RADIAL"] = UNIT_TYPE_RADIAL;
+ typeMap["FONT_HEIGHT"] = UNIT_TYPE_FONT_HEIGHT;
+ // Note that code was not yet handling LINEAR_SCALED, TIME, QTY and NONE
+ }
+ return typeMap;
+}
+
+} // namespace
+
namespace Inkscape {
namespace Util {
@@ -51,19 +84,44 @@ UnitsSAXHandler::UnitsSAXHandler(UnitTable *table) :
#define BUFSIZE (255)
-/**
- * Returns the suggested precision to use for displaying numbers
- * of this unit.
- */
+Unit::Unit() :
+ type(UNIT_TYPE_DIMENSIONLESS), // should this or NONE be the default?
+ factor(1.0),
+ name(),
+ name_plural(),
+ abbr(),
+ description()
+{
+}
+
+Unit::Unit(UnitType type,
+ double factor,
+ Glib::ustring const &name,
+ Glib::ustring const &name_plural,
+ Glib::ustring const &abbr,
+ Glib::ustring const &description) :
+ type(type),
+ factor(factor),
+ name(name),
+ name_plural(name_plural),
+ abbr(abbr),
+ description(description)
+{
+}
+
+void Unit::clear()
+{
+ *this = Unit();
+}
+
int Unit::defaultDigits() const {
int factor_digits = int(log10(factor));
if (factor_digits < 0) {
g_warning("factor = %f, factor_digits = %d", factor, factor_digits);
g_warning("factor_digits < 0 - returning 0");
- return 0;
- } else {
- return factor_digits;
+ factor_digits = 0;
}
+ return factor_digits;
}
/** Checks if a unit is compatible with the specified unit. */
@@ -143,159 +201,132 @@ int Unit::metric() const {
*
* The primary unit's conversion factor is required to be 1.00
*/
-UnitTable::UnitTable()
+UnitTable::UnitTable()
{
// if we swich to the xml file, don't forget to force locale to 'C'
- // load("share/ui/units.xml"); // <-- Buggy
+ // load("share/ui/units.xml"); // <-- Buggy
gchar *filename = g_build_filename(INKSCAPE_UIDIR, "units.txt", NULL);
loadText(filename);
g_free(filename);
}
UnitTable::~UnitTable() {
- UnitMap::iterator iter = _unit_map.begin();
- while (iter != _unit_map.end()) {
- delete (*iter).second;
- ++iter;
+ for (UnitMap::iterator iter = _unit_map.begin(); iter != _unit_map.end(); ++iter)
+ {
+ delete (*iter).second;
}
}
-/** Add a new unit to the table */
void UnitTable::addUnit(Unit const &u, bool primary) {
_unit_map[u.abbr] = new Unit(u);
if (primary) {
- _primary_unit[u.type] = u.abbr;
+ _primary_unit[u.type] = u.abbr;
}
}
-/** Retrieve a given unit based on its string identifier */
Unit UnitTable::getUnit(Glib::ustring const &unit_abbr) const {
UnitMap::const_iterator iter = _unit_map.find(unit_abbr);
if (iter != _unit_map.end()) {
- return *((*iter).second);
+ return *((*iter).second);
} else {
- return Unit();
+ return Unit();
}
}
-/** Remove a unit definition from the given unit type table */
bool UnitTable::deleteUnit(Unit const &u) {
- if (u.abbr == _primary_unit[u.type]) {
- // Cannot delete the primary unit type since it's
- // used for conversions
- return false;
- }
- UnitMap::iterator iter = _unit_map.find(u.abbr);
- if (iter != _unit_map.end()) {
- delete (*iter).second;
- _unit_map.erase(iter);
- return true;
- } else {
- return false;
+ bool deleted = false;
+ // Cannot delete the primary unit type since it's
+ // used for conversions
+ if (u.abbr != _primary_unit[u.type]) {
+ UnitMap::iterator iter = _unit_map.find(u.abbr);
+ if (iter != _unit_map.end()) {
+ delete (*iter).second;
+ _unit_map.erase(iter);
+ deleted = true;
+ }
}
+ return deleted;
}
-/** Returns true if the given string 'name' is a valid unit in the table */
bool UnitTable::hasUnit(Glib::ustring const &unit) const
{
UnitMap::const_iterator iter = _unit_map.find(unit);
return (iter != _unit_map.end());
}
-/** Provides an iteratable list of items in the given unit table */
UnitTable::UnitMap UnitTable::units(UnitType type) const
{
UnitMap submap;
- for (UnitMap::const_iterator iter = _unit_map.begin();
- iter != _unit_map.end(); ++iter) {
- if (((*iter).second)->type == type) {
- submap.insert(UnitMap::value_type((*iter).first, new Unit(*((*iter).second))));
- }
+ for (UnitMap::const_iterator iter = _unit_map.begin(); iter != _unit_map.end(); ++iter) {
+ if (((*iter).second)->type == type) {
+ submap.insert(UnitMap::value_type((*iter).first, new Unit(*((*iter).second))));
+ }
}
return submap;
}
-/** Returns the default unit abbr for the given type */
Glib::ustring UnitTable::primary(UnitType type) const
{
return _primary_unit[type];
}
-/** Loads units from a text file.
-
- loadText loads and merges the contents of the given file into the UnitTable,
- possibly overwriting existing unit definitions.
-
- @param filename: file to be loaded*/
bool UnitTable::loadText(Glib::ustring const &filename)
{
- char buf[BUFSIZE];
+ char buf[BUFSIZE] = {0};
// Open file for reading
FILE * f = fopen(filename.c_str(), "r");
if (f == NULL) {
- g_warning("Could not open units file '%s': %s\n",
- filename.c_str(), strerror(errno));
+ g_warning("Could not open units file '%s': %s\n",
+ filename.c_str(), strerror(errno));
g_warning("* INKSCAPE_DATADIR is: '%s'\n", INKSCAPE_DATADIR);
g_warning("* INKSCAPE_UIDIR is: '%s'\n", INKSCAPE_UIDIR);
- return false;
+ return false;
}
+ /** @todo fix this to use C++ means and explicit locale to avoid need to change. */
// bypass current locale in order to make
// sscanf read floats with '.' as a separator
// set locale to 'C' and keep old locale
- char *old_locale;
- old_locale = g_strdup (setlocale (LC_NUMERIC, NULL));
+ char *old_locale = g_strdup(setlocale(LC_NUMERIC, NULL));
setlocale (LC_NUMERIC, "C");
while (fgets(buf, BUFSIZE, f) != NULL) {
- char name[BUFSIZE];
- char plural[BUFSIZE];
- char abbr[BUFSIZE];
- char type[BUFSIZE];
- double factor;
- char primary[BUFSIZE];
-
- int nchars = 0;
- // locale is set to C, scanning %lf should work _everywhere_
- if (sscanf(buf, "%15s %15s %15s %15s %8lf %1s %15n",
- name, plural, abbr, type, &factor, primary, &nchars) != 6)
- {
- // Skip the line - doesn't appear to be valid
- continue;
- }
-
- g_assert(nchars < BUFSIZE);
-
- char *desc = buf;
- desc += nchars; // buf is now only the description
-
- // insert into _unit_map
- Unit u;
- u.name = name;
- u.name_plural = plural;
- u.abbr = abbr;
- u.description = desc;
- u.factor = factor;
-
- if (streq(type, "DIMENSIONLESS")) {
- u.type = UNIT_TYPE_DIMENSIONLESS;
- } else if (streq(type, "LINEAR")) {
- u.type = UNIT_TYPE_LINEAR;
- } else if (streq(type, "RADIAL")) {
- u.type = UNIT_TYPE_RADIAL;
- } else if (streq(type, "FONT_HEIGHT")) {
- u.type = UNIT_TYPE_FONT_HEIGHT;
- } else {
- g_warning("Skipping unknown unit type '%s' for %s.\n",
- type, name);
- continue;
- }
-
- // if primary is 'Y', list this unit as a primary
- addUnit(u, (primary[0]=='Y' || primary[0]=='y'));
+ char name[BUFSIZE] = {0};
+ char plural[BUFSIZE] = {0};
+ char abbr[BUFSIZE] = {0};
+ char type[BUFSIZE] = {0};
+ double factor = 0.0;
+ char primary[BUFSIZE] = {0};
+
+ int nchars = 0;
+ // locale is set to C, scanning %lf should work _everywhere_
+ /** @todo address %15n, which causes a warning: */
+ if (sscanf(buf, "%15s %15s %15s %15s %8lf %1s %15n",
+ name, plural, abbr, type, &factor, primary, &nchars) != 6)
+ {
+ // Skip the line - doesn't appear to be valid
+ continue;
+ }
+
+ g_assert(nchars < BUFSIZE);
+
+ char *desc = buf;
+ desc += nchars; // buf is now only the description
+
+ // insert into _unit_map
+ if (getTypeMappings().find(type) == getTypeMappings().end())
+ {
+ g_warning("Skipping unknown unit type '%s' for %s.\n", type, name);
+ continue;
+ }
+ UnitType utype = getTypeMappings()[type];
+
+ Unit u(utype, factor, name, plural, abbr, desc);
+ // if primary is 'Y', list this unit as a primary
+ addUnit(u, (primary[0]=='Y' || primary[0]=='y'));
}
// set back the saved locale
@@ -304,9 +335,8 @@ bool UnitTable::loadText(Glib::ustring const &filename)
// close file
if (fclose(f) != 0) {
- g_warning("Error closing units file '%s': %s\n",
- filename.c_str(), strerror(errno));
- return false;
+ g_warning("Error closing units file '%s': %s\n", filename.c_str(), strerror(errno));
+ return false;
}
return true;
@@ -318,23 +348,20 @@ bool UnitTable::load(Glib::ustring const &filename) {
int result = handler.parseFile( filename.c_str() );
if ( result != 0 ) {
// perhaps
- g_warning("Problem loading units file '%s': %d\n",
- filename.c_str(), result);
- return false;
+ g_warning("Problem loading units file '%s': %d\n", filename.c_str(), result);
+ return false;
}
return true;
}
-/** Saves the current UnitTable to the given file. */
bool UnitTable::save(Glib::ustring const &filename) {
// open file for writing
FILE *f = fopen(filename.c_str(), "w");
if (f == NULL) {
- g_warning("Could not open units file '%s': %s\n",
- filename.c_str(), strerror(errno));
- return false;
+ g_warning("Could not open units file '%s': %s\n", filename.c_str(), strerror(errno));
+ return false;
}
// write out header
@@ -351,9 +378,8 @@ bool UnitTable::save(Glib::ustring const &filename) {
// close file
if (fclose(f) != 0) {
- g_warning("Error closing units file '%s': %s\n",
- filename.c_str(), strerror(errno));
- return false;
+ g_warning("Error closing units file '%s': %s\n", filename.c_str(), strerror(errno));
+ return false;
}
return true;
@@ -364,12 +390,7 @@ void UnitsSAXHandler::_startElement(xmlChar const *name, xmlChar const **attrs)
{
if (streq("unit", (char const *)name)) {
// reset for next use
- unit.name.clear();
- unit.name_plural.clear();
- unit.abbr.clear();
- unit.description.clear();
- unit.type = UNIT_TYPE_DIMENSIONLESS;
- unit.factor = 1.0;
+ unit.clear();
primary = false;
skip = false;
@@ -377,14 +398,9 @@ void UnitsSAXHandler::_startElement(xmlChar const *name, xmlChar const **attrs)
char const *const key = (char const *)attrs[i];
if (streq("type", key)) {
char const *type = (char const*)attrs[i+1];
- if (streq(type, "DIMENSIONLESS")) {
- unit.type = UNIT_TYPE_DIMENSIONLESS;
- } else if (streq(type, "LINEAR")) {
- unit.type = UNIT_TYPE_LINEAR;
- } else if (streq(type, "RADIAL")) {
- unit.type = UNIT_TYPE_RADIAL;
- } else if (streq(type, "FONT_HEIGHT")) {
- unit.type = UNIT_TYPE_FONT_HEIGHT;
+ if (getTypeMappings().find(type) != getTypeMappings().end())
+ {
+ unit.type = getTypeMappings()[type];
} else {
g_warning("Skipping unknown unit type '%s' for %s.\n", type, name);
skip = true;
diff --git a/src/util/units.h b/src/util/units.h
index f275d7c3a..ead49d3b4 100644
--- a/src/util/units.h
+++ b/src/util/units.h
@@ -47,6 +47,26 @@ const char DEG[] = "°";
class Unit {
public:
+ Unit();
+ Unit(UnitType type,
+ double factor,
+ Glib::ustring const &name,
+ Glib::ustring const &name_plural,
+ Glib::ustring const &abbr,
+ Glib::ustring const &description);
+
+ void clear();
+
+ bool isAbsolute() const { return type != UNIT_TYPE_DIMENSIONLESS; }
+
+ /**
+ * Returns the suggested precision to use for displaying numbers
+ * of this unit.
+ */
+ int defaultDigits() const;
+
+ UnitType type;
+ double factor;
Glib::ustring name;
Glib::ustring name_plural;
Glib::ustring abbr;
@@ -70,25 +90,50 @@ class Unit {
class UnitTable {
public:
+ /**
+ * Initializes the unit tables and identifies the primary unit types.
+ *
+ * The primary unit's conversion factor is required to be 1.00
+ */
UnitTable();
virtual ~UnitTable();
typedef std::map<Glib::ustring, Unit*> UnitMap;
+ /** Add a new unit to the table */
void addUnit(Unit const& u, bool primary);
+
+ /** Retrieve a given unit based on its string identifier */
Unit getUnit(Glib::ustring const& name) const;
+
+ /** Remove a unit definition from the given unit type table */
bool deleteUnit(Unit const& u);
+
+ /** Returns true if the given string 'name' is a valid unit in the table */
bool hasUnit(Glib::ustring const &name) const;
+ /** Provides an iteratable list of items in the given unit table */
UnitTable::UnitMap units(UnitType type) const;
+ /** Returns the default unit abbr for the given type */
Glib::ustring primary(UnitType type) const;
double getScale() const;
+
void setScale();
bool load(Glib::ustring const &filename);
+
+ /** Loads units from a text file.
+ *
+ * loadText loads and merges the contents of the given file into the UnitTable,
+ * possibly overwriting existing unit definitions.
+ *
+ * @param filename file to be loaded
+ */
bool loadText(Glib::ustring const &filename);
+
+ /** Saves the current UnitTable to the given file. */
bool save(Glib::ustring const &filename);
protected:
@@ -119,3 +164,13 @@ public:
} // namespace Inkscape
#endif // define INKSCAPE_UTIL_UNITS_H
+/*
+ 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/verbs.cpp b/src/verbs.cpp
index 3fdb97365..d0396155c 100644
--- a/src/verbs.cpp
+++ b/src/verbs.cpp
@@ -51,6 +51,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"
@@ -125,7 +126,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,
@@ -144,7 +145,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,
@@ -163,7 +164,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,
@@ -182,7 +183,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,
@@ -201,7 +202,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,
@@ -220,7 +221,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,
@@ -239,7 +240,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,
@@ -259,7 +260,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,
@@ -278,7 +279,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,
@@ -297,7 +298,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,
@@ -316,7 +317,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,
@@ -383,10 +384,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;
@@ -396,13 +397,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);
}
/**
@@ -410,13 +411,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);
}
/**
@@ -424,12 +425,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);
}
/**
@@ -437,12 +438,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);
}
/**
@@ -450,12 +451,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);
}
/**
@@ -463,12 +464,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);
}
/**
@@ -476,12 +477,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);
}
/**
@@ -489,12 +490,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);
}
/**
@@ -502,12 +503,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);
}
/**
@@ -515,12 +516,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);
}
/**
@@ -528,12 +529,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);
}
/**
@@ -547,16 +548,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;
@@ -588,22 +589,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);
@@ -611,21 +612,31 @@ 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;
}
+/* static */
+bool Verb::ensure_desktop_valid(SPAction *action)
+{
+ if (sp_action_get_desktop(action) != NULL) {
+ return true;
+ }
+ g_printerr("WARNING: ignoring verb %s - GUI required for this verb.\n", action->id);
+ return false;
+}
+
void Verb::sensitive(SPDocument *in_doc, bool in_sensitive)
{
// printf("Setting sensitivity of \"%s\" to %d\n", _name, in_sensitive);
@@ -800,15 +811,30 @@ Verb *Verb::getbyid(gchar const *id)
*/
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();
-#endif
+ // Convert verb impls to use this where possible, to reduce static cling
+ // to macros like SP_ACTIVE_DOCUMENT, which end up enforcing GUI-mode operation
+ SPDocument *doc = sp_action_get_document(action);
+
+ // We can vacuum defs, or exit, without needing a desktop!
+ bool handled = true;
+ switch (reinterpret_cast<std::size_t>(data)) {
+ case SP_VERB_FILE_VACUUM:
+ sp_file_vacuum(doc);
+ break;
+ case SP_VERB_FILE_QUIT:
+ sp_file_exit();
+ break;
+ default:
+ handled = false;
+ break;
+ }
+ if (handled) {
+ return;
+ }
+
+ g_return_if_fail(ensure_desktop_valid(action));
+ SPDesktop *desktop = sp_action_get_desktop(action);
- SPDesktop *desktop = dynamic_cast<SPDesktop*>(sp_action_get_view(action));
- g_assert(desktop != NULL);
Gtk::Window *parent = desktop->getToplevel();
g_assert(parent != NULL);
@@ -834,9 +860,6 @@ void FileVerb::perform(SPAction *action, void *data)
case SP_VERB_FILE_PRINT:
sp_file_print(*parent);
break;
- case SP_VERB_FILE_VACUUM:
- sp_file_vacuum();
- break;
case SP_VERB_FILE_IMPORT:
sp_file_import(*parent);
break;
@@ -858,9 +881,6 @@ void FileVerb::perform(SPAction *action, void *data)
case SP_VERB_FILE_CLOSE_VIEW:
sp_ui_close_view(NULL);
break;
- case SP_VERB_FILE_QUIT:
- sp_file_exit();
- break;
default:
break;
}
@@ -873,9 +893,22 @@ void FileVerb::perform(SPAction *action, void *data)
*/
void EditVerb::perform(SPAction *action, void *data)
{
- SPDesktop *dt = static_cast<SPDesktop*>(sp_action_get_view(action));
- if (!dt)
+ // We can clear all without a desktop
+ bool handled = true;
+ switch (reinterpret_cast<std::size_t>(data)) {
+ case SP_VERB_EDIT_CLEAR_ALL:
+ sp_edit_clear_all(sp_action_get_selection(action));
+ break;
+ default:
+ handled = false;
+ break;
+ }
+ if (handled) {
return;
+ }
+
+ g_return_if_fail(ensure_desktop_valid(action));
+ SPDesktop *dt = sp_action_get_desktop(action);
switch (reinterpret_cast<std::size_t>(data)) {
case SP_VERB_EDIT_UNDO:
@@ -965,9 +998,6 @@ void EditVerb::perform(SPAction *action, void *data)
case SP_VERB_EDIT_UNSYMBOL:
sp_selection_unsymbol(dt);
break;
- case SP_VERB_EDIT_CLEAR_ALL:
- sp_edit_clear_all(dt);
- break;
case SP_VERB_EDIT_SELECT_ALL:
SelectionHelper::selectAll(dt);
break;
@@ -1029,33 +1059,68 @@ void EditVerb::perform(SPAction *action, void *data)
*/
void SelectionVerb::perform(SPAction *action, void *data)
{
- SPDesktop *dt = static_cast<SPDesktop*>(sp_action_get_view(action));
+ Inkscape::Selection *selection = sp_action_get_selection(action);
+ SPDesktop *dt = sp_action_get_desktop(action);
- if (!dt)
+ // 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;
+ }
- g_assert(dt->_dlg_mgr != NULL);
-
+ bool handled = true;
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;
case SP_VERB_SELECTION_TO_FRONT:
- sp_selection_raise_to_top(dt);
+ sp_selection_raise_to_top(selection, dt);
break;
case SP_VERB_SELECTION_TO_BACK:
- sp_selection_lower_to_bottom(dt);
+ sp_selection_lower_to_bottom(selection, dt);
break;
case SP_VERB_SELECTION_RAISE:
- sp_selection_raise(dt);
+ sp_selection_raise(selection, dt);
break;
case SP_VERB_SELECTION_LOWER:
- sp_selection_lower(dt);
+ sp_selection_lower(selection, dt);
break;
case SP_VERB_SELECTION_GROUP:
- sp_selection_group(dt);
+ sp_selection_group(selection, dt);
break;
case SP_VERB_SELECTION_UNGROUP:
- sp_selection_ungroup(dt);
+ sp_selection_ungroup(selection, dt);
+ break;
+ default:
+ handled = false;
break;
+ }
+
+ if (handled) {
+ return;
+ }
+
+ // The remaining operations require a desktop
+ g_return_if_fail(ensure_desktop_valid(action));
+ g_assert(dt->_dlg_mgr != NULL);
+
+ switch (reinterpret_cast<std::size_t>(data)) {
case SP_VERB_SELECTION_TEXTTOPATH:
text_put_on_path();
break;
@@ -1066,26 +1131,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;
@@ -1150,10 +1195,11 @@ void SelectionVerb::perform(SPAction *action, void *data)
*/
void LayerVerb::perform(SPAction *action, void *data)
{
- SPDesktop *dt = static_cast<SPDesktop*>(sp_action_get_view(action));
+ g_return_if_fail(ensure_desktop_valid(action));
+ SPDesktop *dt = sp_action_get_desktop(action);
size_t verb = reinterpret_cast<std::size_t>(data);
-
- if ( !dt || !dt->currentLayer() ) {
+
+ if ( !dt->currentLayer() ) {
return;
}
@@ -1401,9 +1447,8 @@ void LayerVerb::perform(SPAction *action, void *data)
*/
void ObjectVerb::perform( SPAction *action, void *data)
{
- SPDesktop *dt = static_cast<SPDesktop*>(sp_action_get_view(action));
- if (!dt)
- return;
+ g_return_if_fail(ensure_desktop_valid(action));
+ SPDesktop *dt = sp_action_get_desktop(action);
SPEventContext *ec = dt->event_context;
@@ -1488,11 +1533,9 @@ void ContextVerb::perform(SPAction *action, void *data)
SPDesktop *dt;
sp_verb_t verb;
int vidx;
-
- dt = static_cast<SPDesktop*>(sp_action_get_view(action));
-
- if (!dt)
- return;
+
+ g_return_if_fail(ensure_desktop_valid(action));
+ dt = sp_action_get_desktop(action);
verb = (sp_verb_t)GPOINTER_TO_INT((gpointer)data);
@@ -1501,7 +1544,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);
}
@@ -1690,9 +1733,8 @@ void ContextVerb::perform(SPAction *action, void *data)
*/
void TextVerb::perform(SPAction *action, void */*data*/)
{
- SPDesktop *dt = static_cast<SPDesktop*>(sp_action_get_view(action));
- if (!dt)
- return;
+ g_return_if_fail(ensure_desktop_valid(action));
+ SPDesktop *dt = sp_action_get_desktop(action);
SPDocument *doc = sp_desktop_document(dt);
(void)doc;
@@ -1705,9 +1747,8 @@ void TextVerb::perform(SPAction *action, void */*data*/)
*/
void ZoomVerb::perform(SPAction *action, void *data)
{
- SPDesktop *dt = static_cast<SPDesktop*>(sp_action_get_view(action));
- if (!dt)
- return;
+ g_return_if_fail(ensure_desktop_valid(action));
+ SPDesktop *dt = sp_action_get_desktop(action);
SPEventContext *ec = dt->event_context;
SPDocument *doc = sp_desktop_document(dt);
@@ -1894,8 +1935,9 @@ void DialogVerb::perform(SPAction *action, void *data)
// unhide all when opening a new dialog
inkscape_dialogs_unhide();
}
-
- SPDesktop *dt = static_cast<SPDesktop*>(sp_action_get_view(action));
+
+ g_return_if_fail(ensure_desktop_valid(action));
+ SPDesktop *dt = sp_action_get_desktop(action);
g_assert(dt->_dlg_mgr != NULL);
switch (reinterpret_cast<std::size_t>(data)) {
@@ -2007,7 +2049,8 @@ void DialogVerb::perform(SPAction *action, void *data)
*/
void HelpVerb::perform(SPAction *action, void *data)
{
- SPDesktop *dt = static_cast<SPDesktop*>(sp_action_get_view(action));
+ g_return_if_fail(ensure_desktop_valid(action));
+ SPDesktop *dt = sp_action_get_desktop(action);
g_assert(dt->_dlg_mgr != NULL);
switch (reinterpret_cast<std::size_t>(data)) {
@@ -2040,8 +2083,9 @@ void HelpVerb::perform(SPAction *action, void *data)
/**
* Decode the verb code and take appropriate action.
*/
-void TutorialVerb::perform(SPAction */*action*/, void *data)
+void TutorialVerb::perform(SPAction *action, void *data)
{
+ g_return_if_fail(ensure_desktop_valid(action));
switch (reinterpret_cast<std::size_t>(data)) {
case SP_VERB_TUTORIAL_BASIC:
// TRANSLATORS: If you have translated the tutorial-basic.en.svgz file to your language,
@@ -2091,7 +2135,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,
@@ -2110,12 +2154,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);
}
/**
@@ -2123,14 +2167,12 @@ SPAction *EffectLastVerb::make_action(Inkscape::UI::View::View *view)
*/
void EffectLastVerb::perform(SPAction *action, void *data)
{
- // These aren't used, but are here to remind people not to use
- // the CURRENT_DOCUMENT macros unless they really have to.
+ g_return_if_fail(ensure_desktop_valid(action));
Inkscape::UI::View::View *current_view = sp_action_get_view(action);
- // SPDocument *current_document = SP_VIEW_DOCUMENT(current_view);
+
Inkscape::Extension::Effect *effect = Inkscape::Extension::Effect::get_last_effect();
if (effect == NULL) return;
- if (current_view == NULL) return;
switch (reinterpret_cast<std::size_t>(data)) {
case SP_VERB_EFFECT_LAST_PREF:
@@ -2156,7 +2198,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,
@@ -2175,12 +2217,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;
}
@@ -2189,8 +2231,8 @@ SPAction *FitCanvasVerb::make_action(Inkscape::UI::View::View *view)
*/
void FitCanvasVerb::perform(SPAction *action, void *data)
{
- SPDesktop *dt = static_cast<SPDesktop*>(sp_action_get_view(action));
- if (!dt) return;
+ g_return_if_fail(ensure_desktop_valid(action));
+ SPDesktop *dt = sp_action_get_desktop(action);
SPDocument *doc = sp_desktop_document(dt);
if (!doc) return;
@@ -2222,7 +2264,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,
@@ -2241,12 +2283,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;
}
@@ -2255,8 +2297,8 @@ SPAction *LockAndHideVerb::make_action(Inkscape::UI::View::View *view)
*/
void LockAndHideVerb::perform(SPAction *action, void *data)
{
- SPDesktop *dt = static_cast<SPDesktop*>(sp_action_get_view(action));
- if (!dt) return;
+ g_return_if_fail(ensure_desktop_valid(action));
+ SPDesktop *dt = sp_action_get_desktop(action);
SPDocument *doc = sp_desktop_document(dt);
if (!doc) return;
@@ -2861,7 +2903,17 @@ Verb *Verb::_base_verbs[] = {
N_("Link an ICC color profile"), NULL),
new EditVerb(SP_VERB_EDIT_REMOVE_COLOR_PROFILE, "RemoveColorProfile", N_("Remove Color Profile"),
N_("Remove a linked ICC color profile"), NULL),
-
+ // Scripting
+ new ContextVerb(SP_VERB_EDIT_ADD_EXTERNAL_SCRIPT, "AddExternalScript",
+ N_("Add External Script"), N_("Add an external script"), NULL),
+ new ContextVerb(SP_VERB_EDIT_ADD_EMBEDDED_SCRIPT, "AddEmbeddedScript",
+ N_("Add Embedded Script"), N_("Add an embedded script"), NULL),
+ new ContextVerb(SP_VERB_EDIT_EMBEDDED_SCRIPT, "EditEmbeddedScript",
+ N_("Edit Embedded Script"), N_("Edit an embedded script"), NULL),
+ new ContextVerb(SP_VERB_EDIT_REMOVE_EXTERNAL_SCRIPT, "RemoveExternalScript",
+ N_("Remove External Script"), N_("Remove an external script"), NULL),
+ new ContextVerb(SP_VERB_EDIT_REMOVE_EMBEDDED_SCRIPT, "RemoveEmbeddedScript",
+ N_("Remove Embedded Script"), N_("Remove an embedded script"), NULL),
// Align
new ContextVerb(SP_VERB_ALIGN_HORIZONTAL_RIGHT_TO_ANCHOR, "AlignHorizontalRightToAnchor", N_("Align right edges of objects to the left edge of the anchor"),
N_("Align right edges of objects to the left edge of the anchor"), INKSCAPE_ICON("align-horizontal-right-to-anchor")),
diff --git a/src/verbs.h b/src/verbs.h
index dab524d7a..053441b89 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);
@@ -547,6 +550,11 @@ public:
}
}
static Verb * getbyid (gchar const * id);
+
+ /**
+ * Print a message to stderr indicating that this verb needs a GUI to run
+ */
+ static bool ensure_desktop_valid(SPAction *action);
static void delete_all_view (Inkscape::UI::View::View * view);
void delete_view (Inkscape::UI::View::View * view);
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 f1e4458ff..fbef9bbce 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 8c481d2f1..65bb46e32 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 693fc870b..c0018751c 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 );