summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2016-03-14 16:37:50 +0000
committerJabiertxof <jtx@jtx.marker.es>2016-03-14 16:37:50 +0000
commitb8d22beef5345210ad27cdc2685083aeae6f8f3b (patch)
treed69b8bfd19d3627a8425a1b265c2abf229b05354 /src/ui
parentfixes for update to trunk (diff)
parent"Relative to" option for node alignment. (diff)
downloadinkscape-b8d22beef5345210ad27cdc2685083aeae6f8f3b.tar.gz
inkscape-b8d22beef5345210ad27cdc2685083aeae6f8f3b.zip
update to trunk
(bzr r13708.1.39)
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/CMakeLists.txt17
-rw-r--r--src/ui/clipboard.cpp51
-rw-r--r--src/ui/control-manager.cpp22
-rw-r--r--src/ui/control-manager.h6
-rw-r--r--src/ui/control-types.h1
-rw-r--r--src/ui/dialog/Makefile_insert12
-rw-r--r--src/ui/dialog/align-and-distribute.cpp128
-rw-r--r--src/ui/dialog/align-and-distribute.h13
-rw-r--r--src/ui/dialog/clonetiler.cpp34
-rw-r--r--src/ui/dialog/clonetiler.h4
-rw-r--r--src/ui/dialog/dialog-manager.cpp14
-rw-r--r--src/ui/dialog/document-properties.cpp126
-rw-r--r--src/ui/dialog/document-properties.h1
-rw-r--r--src/ui/dialog/export.cpp13
-rw-r--r--src/ui/dialog/filedialogimpl-gtkmm.cpp68
-rw-r--r--src/ui/dialog/filter-effects-dialog.cpp21
-rw-r--r--src/ui/dialog/filter-effects-dialog.h8
-rw-r--r--src/ui/dialog/find.cpp16
-rw-r--r--src/ui/dialog/font-substitution.cpp2
-rw-r--r--src/ui/dialog/glyphs.cpp4
-rw-r--r--src/ui/dialog/grid-arrange-tab.cpp20
-rw-r--r--src/ui/dialog/guides.cpp29
-rw-r--r--src/ui/dialog/guides.h1
-rw-r--r--src/ui/dialog/icon-preview.cpp2
-rw-r--r--src/ui/dialog/inkscape-preferences.cpp114
-rw-r--r--src/ui/dialog/inkscape-preferences.h10
-rw-r--r--src/ui/dialog/knot-properties.cpp213
-rw-r--r--src/ui/dialog/knot-properties.h97
-rw-r--r--src/ui/dialog/layers.cpp12
-rw-r--r--src/ui/dialog/new-from-template.cpp18
-rw-r--r--src/ui/dialog/new-from-template.h6
-rw-r--r--src/ui/dialog/objects.cpp16
-rw-r--r--src/ui/dialog/pixelartdialog.cpp2
-rw-r--r--src/ui/dialog/polar-arrange-tab.cpp4
-rw-r--r--src/ui/dialog/svg-fonts-dialog.cpp6
-rw-r--r--src/ui/dialog/swatches.cpp38
-rw-r--r--src/ui/dialog/tags.cpp8
-rw-r--r--src/ui/dialog/template-load-tab.cpp38
-rw-r--r--src/ui/dialog/template-load-tab.h4
-rw-r--r--src/ui/dialog/template-widget.cpp26
-rw-r--r--src/ui/dialog/template-widget.h1
-rw-r--r--src/ui/dialog/text-edit.cpp24
-rw-r--r--src/ui/dialog/transformation.cpp12
-rw-r--r--src/ui/interface.cpp27
-rw-r--r--src/ui/object-edit.cpp8
-rw-r--r--src/ui/tool-factory.cpp8
-rw-r--r--src/ui/tool/control-point-selection.cpp29
-rw-r--r--src/ui/tool/control-point-selection.h3
-rw-r--r--src/ui/tool/multi-path-manipulator.cpp9
-rw-r--r--src/ui/tool/node.cpp107
-rw-r--r--src/ui/tool/path-manipulator.cpp29
-rw-r--r--src/ui/tool/path-manipulator.h4
-rw-r--r--src/ui/tool/selector.cpp1
-rw-r--r--src/ui/tool/transform-handle-set.cpp48
-rw-r--r--src/ui/tools-switch.cpp8
-rw-r--r--src/ui/tools-switch.h8
-rw-r--r--src/ui/tools/Makefile_insert10
-rw-r--r--src/ui/tools/connector-tool.cpp2
-rw-r--r--src/ui/tools/eraser-tool.cpp216
-rw-r--r--src/ui/tools/eraser-tool.h1
-rw-r--r--src/ui/tools/freehand-base.cpp175
-rw-r--r--src/ui/tools/gradient-tool.cpp42
-rw-r--r--src/ui/tools/lpe-tool.cpp2
-rw-r--r--src/ui/tools/measure-tool.cpp1520
-rw-r--r--src/ui/tools/measure-tool.h81
-rw-r--r--src/ui/tools/mesh-tool.cpp67
-rw-r--r--src/ui/tools/mesh-tool.h2
-rw-r--r--src/ui/tools/node-tool.cpp6
-rw-r--r--src/ui/tools/pen-tool.cpp265
-rw-r--r--src/ui/tools/pen-tool.h104
-rw-r--r--src/ui/tools/pencil-tool.cpp20
-rw-r--r--src/ui/tools/select-tool.cpp96
-rw-r--r--src/ui/tools/select-tool.h8
-rw-r--r--src/ui/tools/spray-tool.cpp757
-rw-r--r--src/ui/tools/spray-tool.h29
-rw-r--r--src/ui/tools/tool-base.cpp11
-rw-r--r--src/ui/tools/tool-base.h7
-rw-r--r--src/ui/tools/tweak-tool.cpp2
-rw-r--r--src/ui/tools/zoom-tool.cpp2
-rw-r--r--src/ui/uxmanager.cpp9
-rw-r--r--src/ui/view/edit-widget-interface.h3
-rw-r--r--src/ui/widget/color-entry.h2
-rw-r--r--src/ui/widget/color-icc-selector.cpp7
-rw-r--r--src/ui/widget/font-variants.cpp70
-rw-r--r--src/ui/widget/preferences-widget.cpp1
-rw-r--r--src/ui/widget/preferences-widget.h1
-rw-r--r--src/ui/widget/unit-tracker.cpp10
-rw-r--r--src/ui/widget/unit-tracker.h1
88 files changed, 3537 insertions, 1543 deletions
diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt
index 58af7d935..587974b90 100644
--- a/src/ui/CMakeLists.txt
+++ b/src/ui/CMakeLists.txt
@@ -34,7 +34,6 @@ set(ui_SRC
tools/dropper-tool.cpp
tools/dynamic-base.cpp
tools/eraser-tool.cpp
- tools/flood-tool.cpp
tools/freehand-base.cpp
tools/gradient-tool.cpp
tools/lpe-tool.cpp
@@ -81,6 +80,7 @@ set(ui_SRC
dialog/icon-preview.cpp
dialog/inkscape-preferences.cpp
dialog/input.cpp
+ dialog/knot-properties.cpp
dialog/layer-properties.cpp
dialog/layers.cpp
dialog/livepatheffect-add.cpp
@@ -107,7 +107,6 @@ set(ui_SRC
dialog/template-widget.cpp
dialog/text-edit.cpp
dialog/tile.cpp
- dialog/tracedialog.cpp
dialog/transformation.cpp
dialog/undo-history.cpp
dialog/xml-tree.cpp
@@ -221,6 +220,7 @@ set(ui_SRC
dialog/icon-preview.h
dialog/inkscape-preferences.h
dialog/input.h
+ dialog/knot-properties.h
dialog/layer-properties.h
dialog/layers.h
dialog/livepatheffect-add.h
@@ -248,7 +248,6 @@ set(ui_SRC
dialog/template-widget.h
dialog/text-edit.h
dialog/tile.h
- dialog/tracedialog.h
dialog/transformation.h
dialog/undo-history.h
dialog/xml-tree.h
@@ -276,7 +275,6 @@ set(ui_SRC
tools/dropper-tool.h
tools/dynamic-base.h
tools/eraser-tool.h
- tools/flood-tool.h
tools/freehand-base.h
tools/gradient-tool.h
tools/lpe-tool.h
@@ -364,3 +362,14 @@ endif()
# add_inkscape_lib(ui_LIB "${ui_SRC}")
add_inkscape_source("${ui_SRC}")
+
+set ( ui_flood_and_trace_SRC
+ tools/flood-tool.h
+ tools/flood-tool.cpp
+ dialog/tracedialog.cpp
+ dialog/tracedialog.h
+)
+
+if ("${HAVE_POTRACE}")
+ add_inkscape_source("${ui_flood_and_trace_SRC}")
+endif()
diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp
index d6cf1f980..f04d8a591 100644
--- a/src/ui/clipboard.cpp
+++ b/src/ui/clipboard.cpp
@@ -154,6 +154,7 @@ private:
Inkscape::XML::Node *_root; ///< Reference to the clipboard's root node
Inkscape::XML::Node *_clipnode; ///< The node that holds extra information
Inkscape::XML::Document *_doc; ///< Reference to the clipboard's Inkscape::XML::Document
+ std::set<SPItem*> cloned_elements;
// we need a way to copy plain text AND remember its style;
// the standard _clipnode is only available in an SVG tree, hence this special storage
@@ -239,7 +240,7 @@ void ClipboardManagerImpl::copy(SPDesktop *desktop)
// Special case for when the color picker ("dropper") is active - copies color under cursor
if (tools_isactive(desktop, TOOLS_DROPPER)) {
//_setClipboardColor(sp_dropper_context_get_color(desktop->event_context));
- _setClipboardColor(SP_DROPPER_CONTEXT(desktop->event_context)->get_color());
+ _setClipboardColor(SP_DROPPER_CONTEXT(desktop->event_context)->get_color());
_discardInternalClipboard();
return;
}
@@ -523,8 +524,8 @@ bool ClipboardManagerImpl::pasteSize(SPDesktop *desktop, bool separately, bool a
// resize each object in the selection
if (separately) {
- std::vector<SPItem*> itemlist=selection->itemList();
- for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();i++){
+ std::vector<SPItem*> itemlist=selection->itemList();
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();++i){
SPItem *item = *i;
if (item) {
Geom::OptRect obj_size = item->desktopVisualBounds();
@@ -564,7 +565,7 @@ bool ClipboardManagerImpl::pastePathEffect(SPDesktop *desktop)
}
Inkscape::Selection *selection = desktop->getSelection();
- if (selection && selection->isEmpty()) {
+ if (!selection || selection->isEmpty()) {
_userWarn(desktop, _("Select <b>object(s)</b> to paste live path effect to."));
return false;
}
@@ -580,7 +581,7 @@ bool ClipboardManagerImpl::pastePathEffect(SPDesktop *desktop)
// make sure all selected items are converted to paths first (i.e. rectangles)
sp_selected_to_lpeitems(desktop);
std::vector<SPItem*> itemlist=selection->itemList();
- for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();++i){
SPItem *item = *i;
_applyPathEffect(item, effectstack);
}
@@ -630,7 +631,7 @@ Glib::ustring ClipboardManagerImpl::getShapeOrTextObjectId(SPDesktop *desktop)
// at the first object to be <svg:path> or <svg:text>.
// but that could then return the id of the object's
// clip path or mask, not the original path!
-
+
SPDocument *tempdoc = _retrieveClipboard(); // any target will do here
if ( tempdoc == NULL ) {
_userWarn(desktop, _("Nothing on the clipboard."));
@@ -662,8 +663,9 @@ Glib::ustring ClipboardManagerImpl::getShapeOrTextObjectId(SPDesktop *desktop)
void ClipboardManagerImpl::_copySelection(Inkscape::Selection *selection)
{
// copy the defs used by all items
- std::vector<SPItem*> itemlist=selection->itemList();
- for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();i++){
+ std::vector<SPItem*> itemlist=selection->itemList();
+ cloned_elements.clear();
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();++i){
SPItem *item = *i;
if (item) {
_copyUsedDefs(item);
@@ -673,14 +675,33 @@ void ClipboardManagerImpl::_copySelection(Inkscape::Selection *selection)
}
// copy the representation of the items
- std::vector<SPItem*> sorted_items(itemlist);
+ std::vector<SPObject*> sorted_items;
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();++i)
+ sorted_items.push_back(*i);
sort(sorted_items.begin(),sorted_items.end(),sp_object_compare_position_bool);
- for(std::vector<SPItem*>::const_iterator i=sorted_items.begin();i!=sorted_items.end();i++){
- SPItem *item = *i;
+ //remove already copied elements from cloned_elements
+ std::vector<SPItem*>tr;
+ for(std::set<SPItem*>::iterator it = cloned_elements.begin();it!=cloned_elements.end();++it){
+ if(std::find(sorted_items.begin(),sorted_items.end(),*it)!=sorted_items.end())
+ tr.push_back(*it);
+ }
+ for(std::vector<SPItem*>::iterator it = tr.begin();it!=tr.end();++it){
+ cloned_elements.erase(*it);
+ }
+
+ sorted_items.insert(sorted_items.end(),cloned_elements.begin(),cloned_elements.end());
+
+ for(std::vector<SPObject*>::const_iterator i=sorted_items.begin();i!=sorted_items.end();++i){
+ SPItem *item = dynamic_cast<SPItem*>(*i);
if (item) {
Inkscape::XML::Node *obj = item->getRepr();
- Inkscape::XML::Node *obj_copy = _copyNode(obj, _doc, _root);
+ Inkscape::XML::Node *obj_copy;
+ if(cloned_elements.find(item)==cloned_elements.end())
+ obj_copy = _copyNode(obj, _doc, _root);
+ else
+ obj_copy = _copyNode(obj, _doc, _clipnode);
+
// copy complete inherited style
SPCSSAttr *css = sp_repr_css_attr_inherited(obj, "style");
@@ -737,6 +758,12 @@ void ClipboardManagerImpl::_copySelection(Inkscape::Selection *selection)
*/
void ClipboardManagerImpl::_copyUsedDefs(SPItem *item)
{
+ SPUse *use=dynamic_cast<SPUse *>(item);
+ if(use){
+ if(cloned_elements.insert(use->get_original()).second)
+ _copyUsedDefs(use->get_original());
+ }
+
// copy fill and stroke styles (patterns and gradients)
SPStyle *style = item->style;
diff --git a/src/ui/control-manager.cpp b/src/ui/control-manager.cpp
index 5a3c5a496..cedaea405 100644
--- a/src/ui/control-manager.cpp
+++ b/src/ui/control-manager.cpp
@@ -20,7 +20,6 @@
#include "display/sp-canvas-item.h"
#include "display/sp-ctrlline.h"
#include "display/sp-ctrlcurve.h"
-#include "display/sp-ctrlpoint.h"
#include "preferences.h"
using Inkscape::ControlFlags;
@@ -139,8 +138,6 @@ ControlManagerImpl::ControlManagerImpl(ControlManager &manager) :
_typeTable[CTRL_TYPE_NODE_SMOOTH] = SP_TYPE_CTRL;
_typeTable[CTRL_TYPE_NODE_SYMETRICAL] = SP_TYPE_CTRL;
- _typeTable[CTRL_TYPE_ORIGIN] = SP_TYPE_CTRLPOINT;
-
_typeTable[CTRL_TYPE_LINE] = SP_TYPE_CTRLLINE;
@@ -183,10 +180,6 @@ ControlManagerImpl::ControlManagerImpl(ControlManager &manager) :
_sizeTable[CTRL_TYPE_SHAPER] = std::vector<int>(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0])));
}
{
- int sizes[] = {2, 3, 4, 7, 8, 9, 10};
- _sizeTable[CTRL_TYPE_ORIGIN] = std::vector<int>(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0])));
- }
- {
int sizes[] = {5, 7, 9, 10, 11, 12, 13};
_sizeTable[CTRL_TYPE_NODE_AUTO] = std::vector<int>(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0])));
_sizeTable[CTRL_TYPE_NODE_CUSP] = std::vector<int>(sizes, sizes + (sizeof(sizes) / sizeof(sizes[0])));
@@ -258,10 +251,6 @@ SPCanvasItem *ControlManagerImpl::createControl(SPCanvasGroup *parent, ControlTy
NULL);
break;
}
- case CTRL_TYPE_ORIGIN:
- item = sp_canvas_item_new(parent, SP_TYPE_CTRLPOINT,
- NULL);
- break;
case CTRL_TYPE_INVISIPOINT:
item = sp_canvas_item_new(parent, SP_TYPE_CTRL,
"shape", SP_CTRL_SHAPE_SQUARE,
@@ -297,14 +286,11 @@ void ControlManagerImpl::updateItem(SPCanvasItem *item)
if (item) {
double target = _sizeTable[item->ctrlType][_size - 1];
- if ((item->ctrlType == CTRL_TYPE_ORIGIN) && SP_IS_CTRLPOINT(item)) {
- sp_ctrlpoint_set_radius(SP_CTRLPOINT(item), target / 2.0);
- } else {
- if (_sizeChangers.count(item->ctrlType) && _manager.isSelected(item)) {
- target += 2;
- }
- g_object_set(item, "size", target, NULL);
+ if (_sizeChangers.count(item->ctrlType) && _manager.isSelected(item)) {
+ target += 2;
}
+ g_object_set(item, "size", target, NULL);
+
sp_canvas_item_request_update(item);
}
}
diff --git a/src/ui/control-manager.h b/src/ui/control-manager.h
index 05a53f6a0..964ad0a29 100644
--- a/src/ui/control-manager.h
+++ b/src/ui/control-manager.h
@@ -74,9 +74,11 @@ public:
private:
ControlManager();
-
+#if __cplusplus <= 199711L
std::auto_ptr<ControlManagerImpl> _impl;
-
+#else
+ std::unique_ptr<ControlManagerImpl> _impl;
+#endif
friend class ControlManagerImpl;
};
diff --git a/src/ui/control-types.h b/src/ui/control-types.h
index 0bbf31144..1a0230324 100644
--- a/src/ui/control-types.h
+++ b/src/ui/control-types.h
@@ -26,7 +26,6 @@ enum ControlType {
CTRL_TYPE_ROTATE,
CTRL_TYPE_SIZER,
CTRL_TYPE_SHAPER,
- CTRL_TYPE_ORIGIN,
CTRL_TYPE_LINE,
CTRL_TYPE_NODE_AUTO,
CTRL_TYPE_NODE_CUSP,
diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert
index cbdae1cb0..71628973e 100644
--- a/src/ui/dialog/Makefile_insert
+++ b/src/ui/dialog/Makefile_insert
@@ -61,6 +61,8 @@ ink_common_sources += \
ui/dialog/inkscape-preferences.h \
ui/dialog/input.cpp \
ui/dialog/input.h \
+ ui/dialog/knot-properties.cpp \
+ ui/dialog/knot-properties.h \
ui/dialog/layer-properties.cpp \
ui/dialog/layer-properties.h \
ui/dialog/layers.cpp \
@@ -106,8 +108,6 @@ ink_common_sources += \
ui/dialog/text-edit.h \
ui/dialog/tile.cpp \
ui/dialog/tile.h \
- ui/dialog/tracedialog.cpp \
- ui/dialog/tracedialog.h \
ui/dialog/pixelartdialog.cpp \
ui/dialog/pixelartdialog.h \
ui/dialog/transformation.cpp \
@@ -123,3 +123,11 @@ ink_common_sources += \
ui/dialog/lpe-fillet-chamfer-properties.cpp \
ui/dialog/lpe-fillet-chamfer-properties.h \
$(inkboard_dialogs)
+
+if HAVE_POTRACE
+
+ink_common_sources += \
+ ui/dialog/tracedialog.cpp \
+ ui/dialog/tracedialog.h
+
+endif
diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp
index 882427912..8f87932b8 100644
--- a/src/ui/dialog/align-and-distribute.cpp
+++ b/src/ui/dialog/align-and-distribute.cpp
@@ -42,7 +42,7 @@
#include "ui/icon-names.h"
#include "ui/tools/node-tool.h"
#include "ui/tool/multi-path-manipulator.h"
-#include "util/glib-list-iterators.h"
+#include "ui/tool/control-point-selection.h"
#include "verbs.h"
#include "widgets/icon.h"
#include "sp-root.h"
@@ -89,6 +89,42 @@ Action::Action(const Glib::ustring &id,
}
+void ActionAlign::do_node_action(Inkscape::UI::Tools::NodeTool *nt, int verb)
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int prev_pref = prefs->getInt("/dialogs/align/align-nodes-to");
+ switch(verb){
+ case SP_VERB_ALIGN_HORIZONTAL_LEFT:
+ prefs->setInt("/dialogs/align/align-nodes-to", MIN_NODE );
+ nt->_multipath->alignNodes(Geom::Y);
+ break;
+ case SP_VERB_ALIGN_HORIZONTAL_CENTER:
+ nt->_multipath->alignNodes(Geom::Y);
+ break;
+ case SP_VERB_ALIGN_HORIZONTAL_RIGHT:
+ prefs->setInt("/dialogs/align/align-nodes-to", MAX_NODE );
+ nt->_multipath->alignNodes(Geom::Y);
+ break;
+ case SP_VERB_ALIGN_VERTICAL_TOP:
+ prefs->setInt("/dialogs/align/align-nodes-to", MAX_NODE );
+ nt->_multipath->alignNodes(Geom::X);
+ break;
+ case SP_VERB_ALIGN_VERTICAL_CENTER:
+ nt->_multipath->alignNodes(Geom::X);
+ break;
+ case SP_VERB_ALIGN_VERTICAL_BOTTOM:
+ prefs->setInt("/dialogs/align/align-nodes-to", MIN_NODE );
+ nt->_multipath->alignNodes(Geom::X);
+ break;
+ case SP_VERB_ALIGN_VERTICAL_HORIZONTAL_CENTER:
+ nt->_multipath->alignNodes(Geom::X);
+ nt->_multipath->alignNodes(Geom::Y);
+ break;
+ default:return;
+ }
+ prefs->setInt("/dialogs/align/align-nodes-to", prev_pref );
+}
+
void ActionAlign::do_action(SPDesktop *desktop, int index)
{
Inkscape::Selection *selection = desktop->getSelection();
@@ -188,6 +224,14 @@ ActionAlign::Coeffs const ActionAlign::_allCoeffs[11] = {
void ActionAlign::do_verb_action(SPDesktop *desktop, int verb)
{
+ Inkscape::UI::Tools::ToolBase *event_context = desktop->getEventContext();
+ if (INK_IS_NODE_TOOL(event_context)) {
+ Inkscape::UI::Tools::NodeTool *nt = INK_NODE_TOOL(event_context);
+ if(!nt->_selected_nodes->empty()){
+ do_node_action(nt, verb);
+ return;
+ }
+ }
do_action(desktop, verb_to_coeff(verb));
}
@@ -535,7 +579,7 @@ private :
if (length_a != length_b) return (length_a > length_b);
}
// Last criteria: Sort according to the z-coordinate
- return (a->isSiblingOf(b));
+ return sp_item_repr_compare_position(a,b)<0;
}
virtual void on_button_click()
@@ -742,7 +786,6 @@ private :
if (!selection) return;
std::vector<SPItem*> selected(selection->itemList());
- if (selected.empty()) return;
//Check 2 or more selected objects
if (selected.size() < 2) return;
@@ -795,7 +838,51 @@ private :
_("Distribute text baselines"));
}
- } else {
+ } else { //align
+ Geom::Point ref_point;
+ SPItem *focus = NULL;
+ Geom::OptRect b = Geom::OptRect();
+
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+ switch (AlignTarget(prefs->getInt("/dialogs/align/align-to", 6)))
+ {
+ case LAST:
+ focus = SP_ITEM(*selected.begin());
+ break;
+ case FIRST:
+ focus = SP_ITEM(*--(selected.end()));
+ break;
+ case BIGGEST:
+ focus = selection->largestItem(Selection::AREA);
+ break;
+ case SMALLEST:
+ focus = selection->smallestItem(Selection::AREA);
+ break;
+ case PAGE:
+ b = desktop->getDocument()->preferredBounds();
+ break;
+ case DRAWING:
+ b = desktop->getDocument()->getRoot()->desktopPreferredBounds();
+ break;
+ case SELECTION:
+ b = selection->preferredBounds();
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ };
+
+ if(focus) {
+ if (SP_IS_TEXT (focus) || SP_IS_FLOWTEXT (focus)) {
+ ref_point = *(te_get_layout(focus)->baselineAnchorPoint())*(focus->i2dt_affine());
+ } else {
+ ref_point = focus->desktopPreferredBounds()->min();
+ }
+ } else {
+ ref_point = b->min();
+ }
+
for (std::vector<SPItem*>::iterator it(selected.begin());
it != selected.end();
++it)
@@ -807,7 +894,7 @@ private :
if (pt) {
Geom::Point base = *pt * (item)->i2dt_affine();
Geom::Point t(0.0, 0.0);
- t[_orientation] = b_min[_orientation] - base[_orientation];
+ t[_orientation] = ref_point[_orientation] - base[_orientation];
sp_item_move_rel(item, Geom::Translate(t));
changed = true;
}
@@ -829,6 +916,9 @@ static void on_tool_changed(AlignAndDistribute *daad)
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
if (desktop && desktop->getEventContext())
daad->setMode(tools_active(desktop) == TOOLS_NODES);
+ else
+ daad->setMode(false);
+
}
static void on_selection_changed(AlignAndDistribute *daad)
@@ -863,6 +953,7 @@ AlignAndDistribute::AlignAndDistribute()
_nodesTable(1, 4, true),
#endif
_anchorLabel(_("Relative to: ")),
+ _anchorLabelNode(_("Relative to: ")),
_selgrpLabel(_("_Treat selection as group: "), 1)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -1001,9 +1092,20 @@ AlignAndDistribute::AlignAndDistribute()
_combo.set_active(prefs->getInt("/dialogs/align/align-to", 6));
_combo.signal_changed().connect(sigc::mem_fun(*this, &AlignAndDistribute::on_ref_change));
+ _comboNode.append(_("Last selected"));
+ _comboNode.append(_("First selected"));
+ _comboNode.append(_("Middle of selection"));
+ _comboNode.append(_("Min value"));
+ _comboNode.append(_("Max value"));
+ _comboNode.set_active(prefs->getInt("/dialogs/align/align-nodes-to", 2));
+ _comboNode.signal_changed().connect(sigc::mem_fun(*this, &AlignAndDistribute::on_node_ref_change));
+
_anchorBox.pack_end(_combo, false, false);
_anchorBox.pack_end(_anchorLabel, false, false);
+ _anchorBoxNode.pack_end(_comboNode, false, false);
+ _anchorBoxNode.pack_end(_anchorLabelNode, false, false);
+
_selgrpLabel.set_mnemonic_widget(_selgrp);
_selgrpBox.pack_end(_selgrp, false, false);
_selgrpBox.pack_end(_selgrpLabel, false, false);
@@ -1021,11 +1123,15 @@ AlignAndDistribute::AlignAndDistribute()
_alignBox.pack_start(_selgrpBox);
_alignBox.pack_start(_alignTableBox);
+ _alignBoxNode.pack_start(_anchorBoxNode, false, false);
+ _alignBoxNode.pack_start(_nodesTableBox);
+
+
_alignFrame.add(_alignBox);
_distributeFrame.add(_distributeTableBox);
_rearrangeFrame.add(_rearrangeTableBox);
_removeOverlapFrame.add(_removeOverlapTableBox);
- _nodesFrame.add(_nodesTableBox);
+ _nodesFrame.add(_alignBoxNode);
Gtk::Box *contents = _getContents();
contents->set_spacing(4);
@@ -1036,7 +1142,7 @@ AlignAndDistribute::AlignAndDistribute()
contents->pack_start(_distributeFrame, true, true);
contents->pack_start(_rearrangeFrame, true, true);
contents->pack_start(_removeOverlapFrame, true, true);
- contents->pack_start(_nodesFrame, true, true);
+ contents->pack_start(_nodesFrame, true, false);
//Connect to the global tool change signal
_toolChangeConn = INKSCAPE.signal_eventcontext_set.connect(sigc::hide<0>(sigc::bind(sigc::ptr_fun(&on_tool_changed), this)));
@@ -1082,6 +1188,13 @@ void AlignAndDistribute::on_ref_change(){
//Make blink the master
}
+void AlignAndDistribute::on_node_ref_change(){
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setInt("/dialogs/align/align-nodes-to", _comboNode.get_active_row_number());
+
+ //Make blink the master
+}
+
void AlignAndDistribute::on_selgrp_toggled(){
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
prefs->setInt("/dialogs/align/sel-as-groups", _selgrp.get_active());
@@ -1107,6 +1220,7 @@ void AlignAndDistribute::setMode(bool nodeEdit)
((_rearrangeFrame).*(mSel))();
((_removeOverlapFrame).*(mSel))();
((_nodesFrame).*(mNode))();
+ _getContents()->queue_resize();
}
void AlignAndDistribute::addAlignButton(const Glib::ustring &id, const Glib::ustring tiptext,
diff --git a/src/ui/dialog/align-and-distribute.h b/src/ui/dialog/align-and-distribute.h
index eecc30ff8..f8cc61af2 100644
--- a/src/ui/dialog/align-and-distribute.h
+++ b/src/ui/dialog/align-and-distribute.h
@@ -18,6 +18,7 @@
#include <list>
#include "ui/widget/panel.h"
#include "ui/widget/frame.h"
+
#include <gtkmm/frame.h>
#include <gtkmm/comboboxtext.h>
#include <gtkmm/label.h>
@@ -35,6 +36,9 @@ class SPItem;
namespace Inkscape {
namespace UI {
+namespace Tools{
+class NodeTool;
+}
namespace Dialog {
class Action;
@@ -68,6 +72,7 @@ public:
protected:
void on_ref_change();
+ void on_node_ref_change();
void on_selgrp_toggled();
void addDistributeButton(const Glib::ustring &id, const Glib::ustring tiptext,
guint row, guint col, bool onInterSpace,
@@ -114,15 +119,19 @@ protected:
Gtk::HBox _anchorBox;
Gtk::HBox _selgrpBox;
Gtk::VBox _alignBox;
+ Gtk::VBox _alignBoxNode;
Gtk::HBox _alignTableBox;
Gtk::HBox _distributeTableBox;
Gtk::HBox _rearrangeTableBox;
Gtk::HBox _removeOverlapTableBox;
Gtk::HBox _nodesTableBox;
Gtk::Label _anchorLabel;
+ Gtk::Label _anchorLabelNode;
Gtk::Label _selgrpLabel;
Gtk::CheckButton _selgrp;
Gtk::ComboBoxText _combo;
+ Gtk::HBox _anchorBoxNode;
+ Gtk::ComboBoxText _comboNode;
SPDesktop *_desktop;
DesktopTracker _deskTrack;
@@ -149,6 +158,8 @@ bool operator< (const BBoxSort &a, const BBoxSort &b);
class Action {
public :
+ enum AlignTarget { LAST=0, FIRST, BIGGEST, SMALLEST, PAGE, DRAWING, SELECTION };
+ enum AlignTargetNode { LAST_NODE=0, FIRST_NODE, MID_NODE, MIN_NODE, MAX_NODE };
Action(const Glib::ustring &id,
const Glib::ustring &tiptext,
guint row, guint column,
@@ -183,7 +194,6 @@ 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,
@@ -213,6 +223,7 @@ private :
}
static void do_action(SPDesktop *desktop, int index);
+ static void do_node_action(Inkscape::UI::Tools::NodeTool *nt, int index);
guint _index;
AlignAndDistribute &_dialog;
diff --git a/src/ui/dialog/clonetiler.cpp b/src/ui/dialog/clonetiler.cpp
index f84a2ffd6..fbd050f8e 100644
--- a/src/ui/dialog/clonetiler.cpp
+++ b/src/ui/dialog/clonetiler.cpp
@@ -85,7 +85,7 @@ CloneTiler::CloneTiler () :
{
Gtk::Box *contents = _getContents();
contents->set_spacing(0);
-
+
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -101,7 +101,7 @@ CloneTiler::CloneTiler () :
contents->pack_start (*Gtk::manage(Glib::wrap(mainbox)), true, true, 0);
- GtkWidget *nb = gtk_notebook_new ();
+ nb = gtk_notebook_new ();
gtk_box_pack_start (GTK_BOX (mainbox), nb, FALSE, FALSE, 0);
@@ -662,7 +662,7 @@ CloneTiler::CloneTiler () :
gtk_box_pack_start (GTK_BOX (hb), l, FALSE, FALSE, 0);
guint32 rgba = 0x000000ff | sp_svg_read_color (prefs->getString(prefs_path + "initial_color").data(), 0x000000ff);
- color_picker = new Inkscape::UI::Widget::ColorPicker (*new Glib::ustring(_("Initial color of tiled clones")), *new Glib::ustring(_("Initial color for clones (works only if the original has unset fill or stroke)")), rgba, false);
+ color_picker = new Inkscape::UI::Widget::ColorPicker (*new Glib::ustring(_("Initial color of tiled clones")), *new Glib::ustring(_("Initial color for clones (works only if the original has unset fill or stroke or on spray tool in copy mode)")), rgba, false);
color_changed_connection = color_picker->connectChanged (sigc::ptr_fun(on_picker_color_changed));
gtk_box_pack_start (GTK_BOX (hb), reinterpret_cast<GtkWidget*>(color_picker->gobj()), FALSE, FALSE, 0);
@@ -776,8 +776,6 @@ CloneTiler::CloneTiler () :
// Trace
{
GtkWidget *vb = clonetiler_new_tab (nb, _("_Trace"));
-
-
{
#if GTK_CHECK_VERSION(3,0,0)
GtkWidget *hb = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, VB_MARGIN);
@@ -787,11 +785,11 @@ CloneTiler::CloneTiler () :
#endif
gtk_box_pack_start (GTK_BOX (vb), hb, FALSE, FALSE, 0);
- GtkWidget *b = gtk_check_button_new_with_label (_("Trace the drawing under the tiles"));
+ b = gtk_check_button_new_with_label (_("Trace the drawing under the clones/sprayed items"));
g_object_set_data (G_OBJECT(b), "uncheckable", GINT_TO_POINTER(TRUE));
bool old = prefs->getBool(prefs_path + "dotrace");
gtk_toggle_button_set_active ((GtkToggleButton *) b, old);
- gtk_widget_set_tooltip_text (b, _("For each clone, pick a value from the drawing in that clone's location and apply it to the clone"));
+ gtk_widget_set_tooltip_text (b, _("For each clone/sprayed item, pick a value from the drawing in its location and apply it"));
gtk_box_pack_start (GTK_BOX (hb), b, FALSE, FALSE, 0);
g_signal_connect(G_OBJECT(b), "toggled",
@@ -1001,6 +999,18 @@ CloneTiler::CloneTiler () :
}
}
+ {
+#if GTK_CHECK_VERSION(3,0,0)
+ GtkWidget *hb = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, VB_MARGIN);
+ gtk_box_set_homogeneous(GTK_BOX(hb), FALSE);
+#else
+ GtkWidget *hb = gtk_hbox_new(FALSE, VB_MARGIN);
+#endif
+ gtk_box_pack_start (GTK_BOX (mainbox), hb, FALSE, FALSE, 0);
+ GtkWidget *l = gtk_label_new(_(""));
+ gtk_label_set_markup (GTK_LABEL(l), _("Apply to tiled clones:"));
+ gtk_box_pack_start (GTK_BOX (hb), l, FALSE, FALSE, 0);
+ }
// Rows/columns, width/height
{
#if GTK_CHECK_VERSION(3,0,0)
@@ -1289,7 +1299,6 @@ CloneTiler::CloneTiler () :
}
gtk_widget_show_all (mainbox);
-
}
show_all();
@@ -2479,7 +2488,7 @@ void CloneTiler::clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg)
// Trace tab
if (dotrace) {
- Geom::Rect bbox_t = transform_rect (bbox_original, t);
+ Geom::Rect bbox_t = transform_rect (bbox_original, t*Geom::Scale(1.0/scale_units));
guint32 rgba = clonetiler_trace_pick (bbox_t);
float r = SP_RGBA32_R_F(rgba);
@@ -3005,6 +3014,13 @@ void CloneTiler::clonetiler_do_pick_toggled(GtkToggleButton *tb, GtkWidget *dlg)
}
}
+void CloneTiler::show_page_trace()
+{
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(nb),6);
+ gtk_toggle_button_set_active ((GtkToggleButton *) b, false);
+}
+
+
}
}
}
diff --git a/src/ui/dialog/clonetiler.h b/src/ui/dialog/clonetiler.h
index e5f5638b2..a8f1df0a0 100644
--- a/src/ui/dialog/clonetiler.h
+++ b/src/ui/dialog/clonetiler.h
@@ -31,7 +31,7 @@ public:
virtual ~CloneTiler();
static CloneTiler &getInstance() { return *new CloneTiler(); }
-
+ void show_page_trace();
protected:
GtkWidget * clonetiler_new_tab(GtkWidget *nb, const gchar *label);
@@ -113,6 +113,8 @@ private:
CloneTiler& operator=(CloneTiler const &d);
GtkWidget *dlg;
+ GtkWidget *nb;
+ GtkWidget *b;
SPDesktop *desktop;
DesktopTracker deskTrack;
Inkscape::UI::Widget::ColorPicker *color_picker;
diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp
index 7b1b36908..49853277c 100644
--- a/src/ui/dialog/dialog-manager.cpp
+++ b/src/ui/dialog/dialog-manager.cpp
@@ -34,7 +34,11 @@
#include "ui/dialog/messages.h"
#include "ui/dialog/symbols.h"
#include "ui/dialog/tile.h"
-#include "ui/dialog/tracedialog.h"
+
+#if HAVE_POTRACE
+# include "ui/dialog/tracedialog.h"
+#endif
+
#include "ui/dialog/pixelartdialog.h"
#include "ui/dialog/transformation.h"
#include "ui/dialog/undo-history.h"
@@ -124,7 +128,11 @@ DialogManager::DialogManager() {
registerFactory("Swatches", &create<SwatchesPanel, FloatingBehavior>);
registerFactory("TileDialog", &create<ArrangeDialog, FloatingBehavior>);
registerFactory("Symbols", &create<SymbolsDialog, FloatingBehavior>);
+
+#if HAVE_POTRACE
registerFactory("Trace", &create<TraceDialog, FloatingBehavior>);
+#endif
+
registerFactory("PixelArt", &create<PixelArtDialog, FloatingBehavior>);
registerFactory("Transformation", &create<Transformation, FloatingBehavior>);
registerFactory("UndoHistory", &create<UndoHistory, FloatingBehavior>);
@@ -159,7 +167,11 @@ DialogManager::DialogManager() {
registerFactory("Swatches", &create<SwatchesPanel, DockBehavior>);
registerFactory("TileDialog", &create<ArrangeDialog, DockBehavior>);
registerFactory("Symbols", &create<SymbolsDialog, DockBehavior>);
+
+#if HAVE_POTRACE
registerFactory("Trace", &create<TraceDialog, DockBehavior>);
+#endif
+
registerFactory("PixelArt", &create<PixelArtDialog, DockBehavior>);
registerFactory("Transformation", &create<Transformation, DockBehavior>);
registerFactory("UndoHistory", &create<UndoHistory, DockBehavior>);
diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp
index b04e8ecc1..c2c5c5005 100644
--- a/src/ui/dialog/document-properties.cpp
+++ b/src/ui/dialog/document-properties.cpp
@@ -116,10 +116,11 @@ DocumentProperties::DocumentProperties()
_page_metadata2(Gtk::manage(new UI::Widget::NotebookPage(1, 1))),
//---------------------------------------------------------------
_rcb_antialias(_("Use antialiasing"), _("If unset, no antialiasing will be done on the drawing"), "shape-rendering", _wr, false, NULL, NULL, NULL, "crispEdges"),
+ _rcb_checkerboard(_("Checkerboard background"), _("If set, use checkerboard for background, otherwise use background color at full opacity."), "inkscape:pagecheckerboard", _wr, false),
_rcb_canb(_("Show page _border"), _("If set, rectangular page border is shown"), "showborder", _wr, false),
_rcb_bord(_("Border on _top of drawing"), _("If set, border is always on top of the drawing"), "borderlayer", _wr, false),
_rcb_shad(_("_Show border shadow"), _("If set, page border shows a shadow on its right and lower side"), "inkscape:showpageshadow", _wr, false),
- _rcp_bg(_("Back_ground color:"), _("Background color"), _("Color of the page background. Note: transparency setting ignored while editing but used when exporting to bitmap."), "pagecolor", "inkscape:pageopacity", _wr),
+ _rcp_bg(_("Back_ground color:"), _("Background color"), _("Color of the page background. Note: transparency setting ignored while editing if 'Checkerboard background' unset (but used when exporting to bitmap)."), "pagecolor", "inkscape:pageopacity", _wr),
_rcp_bord(_("Border _color:"), _("Page border color"), _("Color of the page border"), "bordercolor", "borderopacity", _wr),
_rum_deflt(_("Display _units:"), "inkscape:document-units", _wr),
_page_sizer(_wr),
@@ -327,10 +328,19 @@ void DocumentProperties::build_page()
Gtk::Label* label_gen = Gtk::manage (new Gtk::Label);
label_gen->set_markup (_("<b>General</b>"));
+
Gtk::Label *label_for = Gtk::manage (new Gtk::Label);
label_for->set_markup (_("<b>Page Size</b>"));
+
+ Gtk::Label* label_bkg = Gtk::manage (new Gtk::Label);
+ label_bkg->set_markup (_("<b>Background</b>"));
+
+ Gtk::Label* label_bdr = Gtk::manage (new Gtk::Label);
+ label_bdr->set_markup (_("<b>Border</b>"));
+
Gtk::Label* label_dsp = Gtk::manage (new Gtk::Label);
label_dsp->set_markup (_("<b>Display</b>"));
+
_page_sizer.init();
Gtk::Widget *const widget_array[] =
@@ -343,13 +353,16 @@ void DocumentProperties::build_page()
label_for, 0,
0, &_page_sizer,
0, 0,
- label_dsp, 0,
+ label_bkg, 0,
+ 0, &_rcb_checkerboard,
+ _rcp_bg._label, &_rcp_bg,
+ label_bdr, 0,
0, &_rcb_canb,
0, &_rcb_bord,
0, &_rcb_shad,
- 0, &_rcb_antialias,
- _rcp_bg._label, &_rcp_bg,
_rcp_bord._label, &_rcp_bord,
+ label_dsp, 0,
+ 0, &_rcb_antialias,
};
std::list<Gtk::Widget*> _slaveList;
@@ -435,13 +448,13 @@ void DocumentProperties::populate_available_profiles(){
*/
static void sanitizeName( Glib::ustring& str )
{
- if (str.size() > 1) {
+ if (str.size() > 0) {
char val = str.at(0);
if (((val < 'A') || (val > 'Z'))
&& ((val < 'a') || (val > 'z'))
&& (val != '_')
&& (val != ':')) {
- str.replace(0, 1, "-");
+ str.insert(0, "_");
}
for (Glib::ustring::size_type i = 1; i < str.size(); i++) {
char val = str.at(i);
@@ -479,7 +492,13 @@ void DocumentProperties::linkSelectedProfile()
std::vector<std::pair<Glib::ustring, Glib::ustring> > pairs = ColorProfile::getProfileFilesWithNames();
Glib::ustring file = pairs[row].first;
Glib::ustring name = pairs[row].second;
-
+ std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" );
+ for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
+ SPObject* obj = *it;
+ Inkscape::ColorProfile* prof = reinterpret_cast<Inkscape::ColorProfile*>(obj);
+ if (!strcmp(prof->href, file.c_str()))
+ return;
+ }
Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
Inkscape::XML::Node *cprofRepr = xml_doc->createElement("svg:color-profile");
gchar* tmp = g_strdup(name.c_str());
@@ -487,6 +506,8 @@ void DocumentProperties::linkSelectedProfile()
sanitizeName(nameStr);
cprofRepr->setAttribute("name", nameStr.c_str());
cprofRepr->setAttribute("xlink:href", (gchar*) file.c_str());
+ cprofRepr->setAttribute("id", (gchar*) file.c_str());
+
// Checks whether there is a defs element. Creates it when needed
Inkscape::XML::Node *defsRepr = sp_repr_lookup_name(xml_doc, "svg:defs");
@@ -511,17 +532,16 @@ void DocumentProperties::linkSelectedProfile()
void DocumentProperties::populate_linked_profiles_box()
{
_LinkedProfilesListStore->clear();
- const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" );
- if (current) {
- _emb_profiles_observer.set(SP_OBJECT(current->data)->parent);
+ std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" );
+ if (! current.empty()) {
+ _emb_profiles_observer.set((*(current.begin()))->parent);
}
- while ( current ) {
- SPObject* obj = SP_OBJECT(current->data);
+ for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
+ SPObject* obj = *it;
Inkscape::ColorProfile* prof = reinterpret_cast<Inkscape::ColorProfile*>(obj);
Gtk::TreeModel::Row row = *(_LinkedProfilesListStore->append());
row[_LinkedProfilesListColumns.nameColumn] = prof->name;
// row[_LinkedProfilesListColumns.previewColumn] = "Color Preview";
- current = g_slist_next(current);
}
}
@@ -594,19 +614,15 @@ void DocumentProperties::removeSelectedProfile(){
return;
}
}
-
- const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" );
- while ( current ) {
- SPObject* obj = SP_OBJECT(current->data);
+ std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "iccprofile" );
+ for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
+ SPObject* obj = *it;
Inkscape::ColorProfile* prof = reinterpret_cast<Inkscape::ColorProfile*>(obj);
if (!name.compare(prof->name)){
-
- //XML Tree being used directly here while it shouldn't be.
- sp_repr_unparent(obj->getRepr());
+ prof->deleteObject(true, false);
DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_EDIT_REMOVE_COLOR_PROFILE, _("Remove linked color profile"));
break; // removing the color profile likely invalidates part of the traversed list, stop traversing here.
}
- current = g_slist_next(current);
}
populate_linked_profiles_box();
@@ -722,9 +738,9 @@ void DocumentProperties::build_cms()
_LinkedProfilesList.signal_button_release_event().connect_notify(sigc::mem_fun(*this, &DocumentProperties::linked_profiles_list_button_release));
cms_create_popup_menu(_LinkedProfilesList, sigc::mem_fun(*this, &DocumentProperties::removeSelectedProfile));
- const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "defs" );
- if (current) {
- _emb_profiles_observer.set(SP_OBJECT(current->data)->parent);
+ std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "defs" );
+ if (!current.empty()) {
+ _emb_profiles_observer.set((*(current.begin()))->parent);
}
_emb_profiles_observer.signal_changed().connect(sigc::mem_fun(*this, &DocumentProperties::populate_linked_profiles_box));
onColorProfileSelectRow();
@@ -959,9 +975,9 @@ void DocumentProperties::build_scripting()
#endif // defined(HAVE_LIBLCMS1) || defined(HAVE_LIBLCMS2)
//TODO: review this observers code:
- const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
- if (current) {
- _scripts_observer.set(SP_OBJECT(current->data)->parent);
+ std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
+ if (! current.empty()) {
+ _scripts_observer.set((*(current.begin()))->parent);
}
_scripts_observer.signal_changed().connect(sigc::mem_fun(*this, &DocumentProperties::populate_script_lists));
onEmbeddedScriptSelectRow();
@@ -1174,9 +1190,9 @@ void DocumentProperties::removeExternalScript(){
}
}
- const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
- while ( current ) {
- SPObject* obj = reinterpret_cast<SPObject *>(current->data);
+ std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
+ for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
+ SPObject* obj = *it;
if (obj) {
SPScript* script = dynamic_cast<SPScript *>(obj);
if (script && (name == script->xlinkhref)) {
@@ -1191,7 +1207,6 @@ void DocumentProperties::removeExternalScript(){
}
}
}
- current = g_slist_next(current);
}
populate_script_lists();
@@ -1253,9 +1268,9 @@ void DocumentProperties::changeEmbeddedScript(){
}
bool voidscript=true;
- const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
- while ( current ) {
- SPObject* obj = SP_OBJECT(current->data);
+ std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
+ for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
+ SPObject* obj = *it;
if (id == obj->getId()){
int count=0;
@@ -1279,7 +1294,6 @@ void DocumentProperties::changeEmbeddedScript(){
}
}
}
- current = g_slist_next(current);
}
if (voidscript)
@@ -1299,9 +1313,9 @@ void DocumentProperties::editEmbeddedScript(){
}
Inkscape::XML::Document *xml_doc = SP_ACTIVE_DOCUMENT->getReprDoc();
- const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
- while ( current ) {
- SPObject* obj = SP_OBJECT(current->data);
+ std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
+ for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
+ SPObject* obj = *it;
if (id == obj->getId()){
//XML Tree being used directly here while it shouldn't be.
@@ -1317,21 +1331,20 @@ void DocumentProperties::editEmbeddedScript(){
DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_EDIT_EMBEDDED_SCRIPT, _("Edit embedded script"));
}
}
- current = g_slist_next(current);
}
}
void DocumentProperties::populate_script_lists(){
_ExternalScriptsListStore->clear();
_EmbeddedScriptsListStore->clear();
- const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
- if (current) {
- SPObject *obj = reinterpret_cast<SPObject *>(current->data);
+ std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList( "script" );
+ if (!current.empty()) {
+ SPObject *obj = *(current.begin());
g_assert(obj != NULL);
_scripts_observer.set(obj->parent);
}
- while ( current ) {
- SPObject* obj = reinterpret_cast<SPObject *>(current->data);
+ for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
+ SPObject* obj = *it;
SPScript* script = dynamic_cast<SPScript *>(obj);
g_assert(script != NULL);
if (script->xlinkhref)
@@ -1344,8 +1357,6 @@ void DocumentProperties::populate_script_lists(){
Gtk::TreeModel::Row row = *(_EmbeddedScriptsListStore->append());
row[_EmbeddedScriptsListColumns.idColumn] = obj->getId();
}
-
- current = g_slist_next(current);
}
}
@@ -1364,12 +1375,11 @@ void DocumentProperties::update_gridspage()
//add tabs
bool grids_present = false;
- for (GSList const * l = nv->grids; l != NULL; l = l->next) {
- Inkscape::CanvasGrid * grid = (Inkscape::CanvasGrid*) l->data;
- if (!grid->repr->attribute("id")) continue; // update_gridspage is called again when "id" is added
- Glib::ustring name(grid->repr->attribute("id"));
+ for(std::vector<Inkscape::CanvasGrid *>::const_iterator it = nv->grids.begin(); it != nv->grids.end(); ++it) {
+ if (!(*it)->repr->attribute("id")) continue; // update_gridspage is called again when "id" is added
+ Glib::ustring name((*it)->repr->attribute("id"));
const char *icon = NULL;
- switch (grid->getGridType()) {
+ switch ((*it)->getGridType()) {
case GRID_RECTANGULAR:
icon = "grid-rectangular";
break;
@@ -1379,7 +1389,7 @@ void DocumentProperties::update_gridspage()
default:
break;
}
- _grids_notebook.append_page(*grid->newWidget(), _createPageTabLabel(name, icon));
+ _grids_notebook.append_page(*(*it)->newWidget(), _createPageTabLabel(name, icon));
grids_present = true;
}
_grids_notebook.show_all();
@@ -1441,6 +1451,7 @@ void DocumentProperties::update()
set_sensitive (true);
//-----------------------------------------------------------page page
+ _rcb_checkerboard.setActive (nv->pagecheckerboard);
_rcp_bg.setRgba32 (nv->pagecolor);
_rcb_canb.setActive (nv->showborder);
_rcb_bord.setActive (nv->borderlayer == SP_BORDER_LAYER_TOP);
@@ -1639,14 +1650,9 @@ void DocumentProperties::onRemoveGrid()
SPDesktop *dt = getDesktop();
SPNamedView *nv = dt->getNamedView();
Inkscape::CanvasGrid * found_grid = NULL;
- int i = 0;
- for (GSList const * l = nv->grids; l != NULL; l = l->next, i++) { // not a very nice fix, but works.
- Inkscape::CanvasGrid * grid = (Inkscape::CanvasGrid*) l->data;
- if (pagenum == i) {
- found_grid = grid;
- break; // break out of for-loop
- }
- }
+ if( pagenum < (gint)nv->grids.size())
+ found_grid = nv->grids[pagenum];
+
if (found_grid) {
// delete the grid that corresponds with the selected tab
// when the grid is deleted from SVG, the SPNamedview handler automatically deletes the object, so found_grid becomes an invalid pointer!
diff --git a/src/ui/dialog/document-properties.h b/src/ui/dialog/document-properties.h
index b1f90b4b7..7340b67f5 100644
--- a/src/ui/dialog/document-properties.h
+++ b/src/ui/dialog/document-properties.h
@@ -118,6 +118,7 @@ protected:
UI::Widget::Registry _wr;
//---------------------------------------------------------------
UI::Widget::RegisteredCheckButton _rcb_antialias;
+ UI::Widget::RegisteredCheckButton _rcb_checkerboard;
UI::Widget::RegisteredCheckButton _rcb_canb;
UI::Widget::RegisteredCheckButton _rcb_bord;
UI::Widget::RegisteredCheckButton _rcb_shad;
diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp
index 1edfdfe80..2fb5f9e3b 100644
--- a/src/ui/dialog/export.cpp
+++ b/src/ui/dialog/export.cpp
@@ -474,7 +474,14 @@ void Export::set_default_filename () {
doc_export_name = filename_entry.get_text();
}
+ else if ( SP_ACTIVE_DOCUMENT )
+ {
+ Glib::ustring filename = create_filepath_from_id (_("bitmap"), filename_entry.get_text());
+ filename_entry.set_text(filename);
+ filename_entry.set_position(filename.length());
+ doc_export_name = filename_entry.get_text();
+ }
}
#if WITH_GTKMM_3_0
@@ -814,7 +821,7 @@ void Export::onAreaToggled ()
if (filename.empty()) {
const gchar * id = "object";
const std::vector<XML::Node*> reprlst = SP_ACTIVE_DESKTOP->getSelection()->reprList();
- for(std::vector<XML::Node*>::const_iterator i=reprlst.begin(); reprlst.end() != i; i++) {
+ for(std::vector<XML::Node*>::const_iterator i=reprlst.begin(); reprlst.end() != i; ++i) {
Inkscape::XML::Node * repr = *i;
if (repr->attribute("id")) {
id = repr->attribute("id");
@@ -1023,7 +1030,7 @@ void Export::onExport ()
gint export_count = 0;
std::vector<SPItem*> itemlist=desktop->getSelection()->itemList();
- for(std::vector<SPItem*>::const_iterator i = itemlist.begin();i!=itemlist.end() && !interrupted ;i++){
+ for(std::vector<SPItem*>::const_iterator i = itemlist.begin();i!=itemlist.end() && !interrupted ;++i){
SPItem *item = *i;
prog_dlg->set_data("current", GINT_TO_POINTER(n));
@@ -1232,7 +1239,7 @@ void Export::onExport ()
DocumentUndo::setUndoSensitive(doc, false);
reprlst = desktop->getSelection()->reprList();
- for(std::vector<Inkscape::XML::Node*>::const_iterator i=reprlst.begin(); reprlst.end() != i; i++) {
+ for(std::vector<Inkscape::XML::Node*>::const_iterator i=reprlst.begin(); reprlst.end() != i; ++i) {
Inkscape::XML::Node * repr = *i;
const gchar * temp_string;
Glib::ustring dir = Glib::path_get_dirname(filename.c_str());
diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp
index 17cf835cd..042637d22 100644
--- a/src/ui/dialog/filedialogimpl-gtkmm.cpp
+++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp
@@ -199,37 +199,9 @@ void SVGPreview::showImage(Glib::ustring &theFileName)
// files so we assume they are well formed.
// std::cout << "SVGPreview::showImage: " << theFileName << std::endl;
- std::ifstream input(theFileName.c_str());
-
std::string width;
std::string height;
- if( !input ) {
- std::cerr << "SVGPreview::showImage: Failed to open file: " << theFileName << std::endl;
- } else {
-
- std::string token;
-
- Glib::MatchInfo match_info;
- Glib::RefPtr<Glib::Regex> regex1 = Glib::Regex::create("width=\"(.*)\"");
- Glib::RefPtr<Glib::Regex> regex2 = Glib::Regex::create("height=\"(.*)\"");
-
- while( !input.eof() && (height.empty() || width.empty()) ) {
-
- input >> token;
- // std::cout << "|" << token << "|" << std::endl;
-
- if (regex1->match(token, match_info)) {
- width = match_info.fetch(1).raw();
- }
-
- if (regex2->match(token, match_info)) {
- height = match_info.fetch(1).raw();
- }
-
- }
- }
-
/*#####################################
# LET'S HAVE SOME FUN WITH SVG!
# Instead of just loading an image, why
@@ -265,6 +237,46 @@ void SVGPreview::showImage(Glib::ustring &theFileName)
gint imgWidth = img->get_width();
gint imgHeight = img->get_height();
+
+ Glib::ustring svg = ".svg";
+ if (hasSuffix(fileName, svg)) {
+ std::ifstream input(theFileName.c_str());
+ if( !input ) {
+ std::cerr << "SVGPreview::showImage: Failed to open file: " << theFileName << std::endl;
+ } else {
+
+ std::string token;
+
+ Glib::MatchInfo match_info;
+ Glib::RefPtr<Glib::Regex> regex1 = Glib::Regex::create("width=\"(.*)\"");
+ Glib::RefPtr<Glib::Regex> regex2 = Glib::Regex::create("height=\"(.*)\"");
+
+ while( !input.eof() && (height.empty() || width.empty()) ) {
+
+ input >> token;
+ // std::cout << "|" << token << "|" << std::endl;
+
+ if (regex1->match(token, match_info)) {
+ width = match_info.fetch(1).raw();
+ }
+
+ if (regex2->match(token, match_info)) {
+ height = match_info.fetch(1).raw();
+ }
+
+ }
+ }
+ }
+
+ // TODO: replace int to string conversion with std::to_string when fully C++11 compliant
+ if (height.empty() || width.empty()) {
+ std::ostringstream s_width;
+ std::ostringstream s_height;
+ s_width << imgWidth;
+ s_height << imgHeight;
+ width = s_width.str();
+ height = s_height.str();
+ }
// Find the minimum scale to fit the image inside the preview area
double scaleFactorX = (0.9 * (double)previewWidth) / ((double)imgWidth);
diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp
index 1ff9e4a1b..7e9d8481a 100644
--- a/src/ui/dialog/filter-effects-dialog.cpp
+++ b/src/ui/dialog/filter-effects-dialog.cpp
@@ -1474,7 +1474,7 @@ void FilterEffectsDialog::FilterModifier::update_selection(Selection *sel)
std::set<SPObject*> used;
std::vector<SPItem*> itemlist=sel->itemList();
- for(std::vector<SPItem*>::const_iterator i=itemlist.begin(); itemlist.end() != i; i++) {
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin(); itemlist.end() != i; ++i) {
SPObject *obj = *i;
SPStyle *style = obj->style;
if (!style || !SP_IS_ITEM(obj)) {
@@ -1555,7 +1555,7 @@ void FilterEffectsDialog::FilterModifier::on_selection_toggled(const Glib::ustri
filter = 0;
std::vector<SPItem*> itemlist=sel->itemList();
- for(std::vector<SPItem*>::const_iterator i=itemlist.begin(); itemlist.end() != i; i++) {
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin(); itemlist.end() != i; ++i) {
SPItem * item = *i;
SPStyle *style = item->style;
g_assert(style != NULL);
@@ -1589,13 +1589,14 @@ void FilterEffectsDialog::FilterModifier::update_filters()
{
SPDesktop* desktop = _dialog.getDesktop();
SPDocument* document = desktop->getDocument();
- const GSList* filters = document->getResourceList("filter");
+
+ std::set<SPObject *> filters = document->getResourceList( "filter" );
_model->clear();
- for(const GSList *l = filters; l; l = l->next) {
+ for (std::set<SPObject *>::const_iterator it = filters.begin(); it != filters.end(); ++it) {
Gtk::TreeModel::Row row = *_model->append();
- SPFilter* f = SP_FILTER(l->data);
+ SPFilter* f = SP_FILTER(*it);
row[_columns.filter] = f;
const gchar* lbl = f->label();
const gchar* id = f->getId();
@@ -1669,7 +1670,7 @@ void FilterEffectsDialog::FilterModifier::remove_filter()
// Delete all references to this filter
std::vector<SPItem*> x,y;
std::vector<SPItem*> all = get_all_items(x, _desktop->currentRoot(), _desktop, false, false, true, y);
- for(std::vector<SPItem*>::const_iterator i=all.begin(); all.end() != i; i++) {
+ for(std::vector<SPItem*>::const_iterator i=all.begin(); all.end() != i; ++i) {
if (!SP_IS_ITEM(*i)) {
continue;
}
@@ -2756,8 +2757,6 @@ FilterEffectsDialog::FilterEffectsDialog()
_sizegroup = Gtk::SizeGroup::create(Gtk::SIZE_GROUP_HORIZONTAL);
_sizegroup->set_ignore_hidden();
- _add_primitive_type.remove_row(NR_FILTER_TILE);
-
// Initialize widget hierarchy
#if WITH_GTKMM_3_0
Gtk::Paned* hpaned = Gtk::manage(new Gtk::Paned);
@@ -2900,7 +2899,7 @@ void FilterEffectsDialog::init_settings_widgets()
_settings->add_spinscale(1, SP_PROP_FLOOD_OPACITY, _("Opacity:"), 0, 1, 0.1, 0.01, 2);
_settings->type(NR_FILTER_GAUSSIANBLUR);
- _settings->add_dualspinscale(SP_ATTR_STDDEVIATION, _("Standard Deviation:"), 0.01, 100, 1, 0.01, 1, _("The standard deviation for the blur operation."));
+ _settings->add_dualspinscale(SP_ATTR_STDDEVIATION, _("Standard Deviation:"), 0.01, 100, 1, 0.01, 2, _("The standard deviation for the blur operation."));
_settings->type(NR_FILTER_MERGE);
_settings->add_no_params();
@@ -2925,7 +2924,7 @@ void FilterEffectsDialog::init_settings_widgets()
_settings->add_lightsource();
_settings->type(NR_FILTER_TILE);
- _settings->add_notimplemented();
+ _settings->add_no_params();
_settings->type(NR_FILTER_TURBULENCE);
// _settings->add_checkbutton(false, SP_ATTR_STITCHTILES, _("Stitch Tiles"), "stitch", "noStitch");
@@ -3017,7 +3016,7 @@ void FilterEffectsDialog::update_primitive_infobox()
break;
case(NR_FILTER_TILE):
_infobox_icon.set_from_icon_name("feTile-icon", Gtk::ICON_SIZE_DIALOG);
- _infobox_desc.set_markup(_("The <b>feTile</b> filter primitive tiles a region with its input graphic"));
+ _infobox_desc.set_markup(_("The <b>feTile</b> filter primitive tiles a region with an input graphic. The source tile is defined by the filter primitive subregion of the input."));
break;
case(NR_FILTER_TURBULENCE):
_infobox_icon.set_from_icon_name("feTurbulence-icon", Gtk::ICON_SIZE_DIALOG);
diff --git a/src/ui/dialog/filter-effects-dialog.h b/src/ui/dialog/filter-effects-dialog.h
index a067cd70c..283abb5b0 100644
--- a/src/ui/dialog/filter-effects-dialog.h
+++ b/src/ui/dialog/filter-effects-dialog.h
@@ -127,7 +127,11 @@ private:
Gtk::Button _add;
Glib::RefPtr<Gtk::Menu> _menu;
sigc::signal<void> _signal_filter_changed;
+#if __cplusplus <= 199711L
std::auto_ptr<Inkscape::XML::SignalObserver> _observer;
+#else
+ std::unique_ptr<Inkscape::XML::SignalObserver> _observer;
+#endif
};
class PrimitiveColumns : public Gtk::TreeModel::ColumnRecord
@@ -243,7 +247,11 @@ private:
sigc::connection _scroll_connection;
int _autoscroll_y;
int _autoscroll_x;
+#if __cplusplus <= 199711L
std::auto_ptr<Inkscape::XML::SignalObserver> _observer;
+#else
+ std::unique_ptr<Inkscape::XML::SignalObserver> _observer;
+#endif
int _input_type_width;
int _input_type_height;
};
diff --git a/src/ui/dialog/find.cpp b/src/ui/dialog/find.cpp
index a8ac42a1b..0f368c5ac 100644
--- a/src/ui/dialog/find.cpp
+++ b/src/ui/dialog/find.cpp
@@ -561,7 +561,7 @@ std::vector<SPItem*> Find::filter_fields (std::vector<SPItem*> &l, bool exact, b
std::vector<SPItem*> out;
if (check_searchin_text.get_active()) {
- for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; i++) {
+ for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; ++i) {
SPObject *obj = *i;
SPItem *item = dynamic_cast<SPItem *>(obj);
g_assert(item != NULL);
@@ -584,7 +584,7 @@ std::vector<SPItem*> Find::filter_fields (std::vector<SPItem*> &l, bool exact, b
bool attrvalue = check_attributevalue.get_active();
if (ids) {
- for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; i++) {
+ for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; ++i) {
SPObject *obj = *i;
SPItem *item = dynamic_cast<SPItem *>(obj);
if (item_id_match(item, text, exact, casematch)) {
@@ -600,7 +600,7 @@ std::vector<SPItem*> Find::filter_fields (std::vector<SPItem*> &l, bool exact, b
if (style) {
- for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; i++) {
+ for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; ++i) {
SPObject *obj = *i;
SPItem *item = dynamic_cast<SPItem *>(obj);
g_assert(item != NULL);
@@ -617,7 +617,7 @@ std::vector<SPItem*> Find::filter_fields (std::vector<SPItem*> &l, bool exact, b
if (attrname) {
- for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; i++) {
+ for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; ++i) {
SPObject *obj = *i;
SPItem *item = dynamic_cast<SPItem *>(obj);
g_assert(item != NULL);
@@ -634,7 +634,7 @@ std::vector<SPItem*> Find::filter_fields (std::vector<SPItem*> &l, bool exact, b
if (attrvalue) {
- for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; i++) {
+ for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; ++i) {
SPObject *obj = *i;
SPItem *item = dynamic_cast<SPItem *>(obj);
g_assert(item != NULL);
@@ -651,7 +651,7 @@ std::vector<SPItem*> Find::filter_fields (std::vector<SPItem*> &l, bool exact, b
if (font) {
- for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; i++) {
+ for(std::vector<SPItem*>::const_reverse_iterator i=in.rbegin(); in.rend() != i; ++i) {
SPObject *obj = *i;
SPItem *item = dynamic_cast<SPItem *>(obj);
g_assert(item != NULL);
@@ -718,7 +718,7 @@ bool Find::item_type_match (SPItem *item)
std::vector<SPItem*> Find::filter_types (std::vector<SPItem*> &l)
{
std::vector<SPItem*> n;
- for(std::vector<SPItem*>::const_reverse_iterator i=l.rbegin(); l.rend() != i; i++) {
+ for(std::vector<SPItem*>::const_reverse_iterator i=l.rbegin(); l.rend() != i; ++i) {
SPObject *obj = *i;
SPItem *item = dynamic_cast<SPItem *>(obj);
g_assert(item != NULL);
@@ -762,7 +762,7 @@ std::vector<SPItem*> &Find::all_items (SPObject *r, std::vector<SPItem*> &l, boo
std::vector<SPItem*> &Find::all_selection_items (Inkscape::Selection *s, std::vector<SPItem*> &l, SPObject *ancestor, bool hidden, bool locked)
{
std::vector<SPItem*> itemlist=s->itemList();
- for(std::vector<SPItem*>::const_reverse_iterator i=itemlist.rbegin(); itemlist.rend() != i; i++) {
+ for(std::vector<SPItem*>::const_reverse_iterator i=itemlist.rbegin(); itemlist.rend() != i; ++i) {
SPObject *obj = *i;
SPItem *item = dynamic_cast<SPItem *>(obj);
g_assert(item != NULL);
diff --git a/src/ui/dialog/font-substitution.cpp b/src/ui/dialog/font-substitution.cpp
index 19506c6a3..f219f3db6 100644
--- a/src/ui/dialog/font-substitution.cpp
+++ b/src/ui/dialog/font-substitution.cpp
@@ -154,7 +154,7 @@ std::vector<SPItem*> FontSubstitution::getFontReplacedItems(SPDocument* doc, Gli
std::map<SPItem *, Glib::ustring> mapFontStyles;
allList = get_all_items(x, doc->getRoot(), desktop, false, false, true, y);
- for(std::vector<SPItem*>::const_iterator i = allList.begin();i!=allList.end();i++){
+ for(std::vector<SPItem*>::const_iterator i = allList.begin();i!=allList.end();++i){
SPItem *item = *i;
SPStyle *style = item->style;
Glib::ustring family = "";
diff --git a/src/ui/dialog/glyphs.cpp b/src/ui/dialog/glyphs.cpp
index 7ca277ea2..56b001291 100644
--- a/src/ui/dialog/glyphs.cpp
+++ b/src/ui/dialog/glyphs.cpp
@@ -579,7 +579,7 @@ void GlyphsPanel::insertText()
{
SPItem *textItem = 0;
std::vector<SPItem*> itemlist=targetDesktop->selection->itemList();
- for(std::vector<SPItem*>::const_iterator i=itemlist.begin(); itemlist.end() != i; i++) {
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin(); itemlist.end() != i; ++i) {
if (SP_IS_TEXT(*i) || SP_IS_FLOWTEXT(*i)) {
textItem = *i;
break;
@@ -689,7 +689,7 @@ void GlyphsPanel::calcCanInsert()
{
int items = 0;
std::vector<SPItem*> itemlist=targetDesktop->selection->itemList();
- for(std::vector<SPItem*>::const_iterator i=itemlist.begin(); itemlist.end() != i; i++) {
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin(); itemlist.end() != i; ++i) {
if (SP_IS_TEXT(*i) || SP_IS_FLOWTEXT(*i)) {
++items;
}
diff --git a/src/ui/dialog/grid-arrange-tab.cpp b/src/ui/dialog/grid-arrange-tab.cpp
index ccd23a572..639e463ea 100644
--- a/src/ui/dialog/grid-arrange-tab.cpp
+++ b/src/ui/dialog/grid-arrange-tab.cpp
@@ -75,16 +75,10 @@ static bool sp_compare_x_position(SPItem *first, SPItem *second)
a_in_b_vert = false;
}
- if (!a_in_b_vert) {
- return true;
- }
- if (a_in_b_vert && a->min()[X] > b->min()[X]) {
- return false;
+ if (!a_in_b_vert) { // a and b are not in the same row
+ return (a->min()[Y] < b->min()[Y]);
}
- if (a_in_b_vert && a->min()[X] < b->min()[X]) {
- return true;
- }
- return false;
+ return (a->min()[X] < b->min()[X]);
}
/*
@@ -170,7 +164,7 @@ void GridArrangeTab::arrange()
Inkscape::Selection *selection = desktop->getSelection();
const std::vector<SPItem*> items = selection ? selection->itemList() : std::vector<SPItem*>();
- for(std::vector<SPItem*>::const_iterator i = items.begin();i!=items.end();i++){
+ for(std::vector<SPItem*>::const_iterator i = items.begin();i!=items.end(); ++i){
SPItem *item = *i;
Geom::OptRect b = item->documentVisualBounds();
if (!b) {
@@ -208,7 +202,7 @@ void GridArrangeTab::arrange()
cnt=0;
const std::vector<SPItem*> sizes(sorted);
- for (std::vector<SPItem*>::const_iterator i = sizes.begin();i!=sizes.end();i++) {
+ for (std::vector<SPItem*>::const_iterator i = sizes.begin();i!=sizes.end(); ++i) {
SPItem *item = *i;
Geom::OptRect b = item->documentVisualBounds();
if (b) {
@@ -307,11 +301,11 @@ g_print("\n row = %f col = %f selection x= %f selection y = %f", total_row_h
cnt=0;
std::vector<SPItem*>::iterator it = sorted.begin();
- for (row_cnt=0; ((it != sorted.end()) && (row_cnt<NoOfRows)); row_cnt++) {
+ for (row_cnt=0; ((it != sorted.end()) && (row_cnt<NoOfRows)); ++row_cnt) {
GSList *current_row = NULL;
col_cnt = 0;
- for(;it!=sorted.end()&&col_cnt<NoOfCols;it++) {
+ for(;it!=sorted.end()&&col_cnt<NoOfCols;++it) {
current_row = g_slist_append (current_row, *it);
col_cnt++;
}
diff --git a/src/ui/dialog/guides.cpp b/src/ui/dialog/guides.cpp
index af8e2cc31..556d77a28 100644
--- a/src/ui/dialog/guides.cpp
+++ b/src/ui/dialog/guides.cpp
@@ -44,6 +44,7 @@ namespace Dialogs {
GuidelinePropertiesDialog::GuidelinePropertiesDialog(SPGuide *guide, SPDesktop *desktop)
: _desktop(desktop), _guide(guide),
+ _locked_toggle(_("Lo_cked"), _("Lock the movement of guides")),
_relative_toggle(_("Rela_tive change"), _("Move and/or rotate the guide relative to current settings")),
_spin_button_x(C_("Guides", "_X:"), "", UNIT_TYPE_LINEAR, "", "", &_unit_menu),
_spin_button_y(C_("Guides", "_Y:"), "", UNIT_TYPE_LINEAR, "", "", &_unit_menu),
@@ -97,9 +98,12 @@ void GuidelinePropertiesDialog::_onOK()
} else if ( deg_angle == 0. || deg_angle == 180. || deg_angle == -180.) {
normal = Geom::Point(0.,1.);
} else {
- double rad_angle = Geom::deg_to_rad( deg_angle );
+ double rad_angle = Geom::rad_from_deg( deg_angle );
normal = Geom::rot90(Geom::Point::polar(rad_angle, 1.0));
}
+ //To allow reposition from dialog
+ _guide->set_locked(false, true);
+
_guide->set_normal(normal, true);
double const points_x = _spin_button_x.getValue("px");
@@ -113,6 +117,11 @@ void GuidelinePropertiesDialog::_onOK()
const gchar* name = g_strdup( _label_entry.getEntry()->get_text().c_str() );
_guide->set_label(name, true);
+
+ const bool locked = _locked_toggle.get_active();
+
+ _guide->set_locked(locked, true);
+
g_free((gpointer) name);
#if WITH_GTKMM_3_0
@@ -269,6 +278,12 @@ void GuidelinePropertiesDialog::_setup() {
_relative_toggle.set_valign(Gtk::ALIGN_FILL);
_relative_toggle.set_hexpand();
_layout_table.attach(_relative_toggle, 1, 7, 2, 1);
+
+ // locked radio button
+ _locked_toggle.set_halign(Gtk::ALIGN_FILL);
+ _locked_toggle.set_valign(Gtk::ALIGN_FILL);
+ _locked_toggle.set_hexpand();
+ _layout_table.attach(_locked_toggle, 1, 8, 2, 1);
#else
_layout_table.attach(_spin_angle,
1, 3, 6, 7, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
@@ -276,11 +291,21 @@ void GuidelinePropertiesDialog::_setup() {
// mode radio button
_layout_table.attach(_relative_toggle,
1, 3, 7, 8, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
+
+ // locked radio button
+ _layout_table.attach(_locked_toggle,
+ 1, 3, 8, 9, Gtk::EXPAND | Gtk::FILL, Gtk::FILL);
#endif
_relative_toggle.signal_toggled().connect(sigc::mem_fun(*this, &GuidelinePropertiesDialog::_modeChanged));
_relative_toggle.set_active(_relative_toggle_status);
+ bool global_guides_lock = _desktop->namedview->lockguides;
+ if(global_guides_lock){
+ _locked_toggle.set_sensitive(false);
+ }
+ _locked_toggle.set_active(_guide->getLocked());
+
// don't know what this exactly does, but it results in that the dialog closes when entering a value and pressing enter (see LP bug 484187)
g_signal_connect_swapped(G_OBJECT(_spin_button_x.getWidget()->gobj()), "activate",
G_CALLBACK(gtk_window_activate_default), gobj());
@@ -301,7 +326,7 @@ void GuidelinePropertiesDialog::_setup() {
} else if (_guide->isHorizontal()) {
_oldangle = 0;
} else {
- _oldangle = Geom::rad_to_deg( std::atan2( - _guide->getNormal()[Geom::X], _guide->getNormal()[Geom::Y] ) );
+ _oldangle = Geom::deg_from_rad( std::atan2( - _guide->getNormal()[Geom::X], _guide->getNormal()[Geom::Y] ) );
}
{
diff --git a/src/ui/dialog/guides.h b/src/ui/dialog/guides.h
index 4ff7b4fde..5dce0d6ed 100644
--- a/src/ui/dialog/guides.h
+++ b/src/ui/dialog/guides.h
@@ -79,6 +79,7 @@ private:
Gtk::Label _label_name;
Gtk::Label _label_descr;
+ Inkscape::UI::Widget::CheckButton _locked_toggle;
Inkscape::UI::Widget::CheckButton _relative_toggle;
static bool _relative_toggle_status; // remember the status of the _relative_toggle_status button across instances
Inkscape::UI::Widget::UnitMenu _unit_menu;
diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp
index 77f120e1a..83656a1f2 100644
--- a/src/ui/dialog/icon-preview.cpp
+++ b/src/ui/dialog/icon-preview.cpp
@@ -363,7 +363,7 @@ void IconPreviewPanel::refreshPreview()
//g_message("found a selection to play with");
std::vector<SPItem*> const items = sel->itemList();
- for(std::vector<SPItem*>::const_iterator i=items.begin();!target && i!=items.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=items.begin();!target && i!=items.end();++i){
SPItem* item = *i;
gchar const *id = item->getId();
if ( id ) {
diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp
index 3b0731953..b20f71a6a 100644
--- a/src/ui/dialog/inkscape-preferences.cpp
+++ b/src/ui/dialog/inkscape-preferences.cpp
@@ -206,6 +206,15 @@ void InkscapePreferences::AddDotSizeSpinbutton(DialogPage &p, Glib::ustring cons
false );
}
+void InkscapePreferences::AddBaseSimplifySpinbutton(DialogPage &p, Glib::ustring const &prefs_path, double def_value)
+{
+ PrefSpinButton* sb = Gtk::manage( new PrefSpinButton);
+ sb->init ( prefs_path + "/base-simplify", 0.0, 100.0, 1.0, 10.0, def_value, false, false);
+ p.add_line( false, _("Base simplify:"), *sb, _("on dinamic LPE simplify"),
+ _("Base simplify of dinamic LPE based simplify"),
+ false );
+}
+
static void StyleFromSelectionToTool(Glib::ustring const &prefs_path, StyleSwatch *swatch)
{
@@ -425,6 +434,7 @@ void InkscapePreferences::initPageTools()
this->AddSelcueCheckbox(_page_pencil, "/tools/freehand/pencil", true);
this->AddNewObjectsStyle(_page_pencil, "/tools/freehand/pencil");
this->AddDotSizeSpinbutton(_page_pencil, "/tools/freehand/pencil", 3.0);
+ this->AddBaseSimplifySpinbutton(_page_pencil, "/tools/freehand/pencil", 25.0);
_page_pencil.add_group_header( _("Sketch mode"));
_page_pencil.add_line( true, "", _pencil_average_all_sketches, "",
_("If on, the sketch result will be the normal average of all sketches made, instead of averaging the old result with the new sketch"));
@@ -478,10 +488,12 @@ void InkscapePreferences::initPageTools()
this->AddPage(_page_eraser, _("Eraser"), iter_tools, PREFS_PAGE_TOOLS_ERASER);
this->AddNewObjectsStyle(_page_eraser, "/tools/eraser");
+#if HAVE_POTRACE
//Paint Bucket
this->AddPage(_page_paintbucket, _("Paint Bucket"), iter_tools, PREFS_PAGE_TOOLS_PAINTBUCKET);
this->AddSelcueCheckbox(_page_paintbucket, "/tools/paintbucket", false);
this->AddNewObjectsStyle(_page_paintbucket, "/tools/paintbucket");
+#endif
//Gradient
this->AddPage(_page_gradient, _("Gradient"), iter_tools, PREFS_PAGE_TOOLS_GRADIENT);
@@ -522,22 +534,54 @@ void InkscapePreferences::initPageUI()
Gtk::TreeModel::iterator iter_ui = this->AddPage(_page_ui, _("Interface"), PREFS_PAGE_UI);
_path_ui = _page_list.get_model()->get_path(iter_ui);
- Glib::ustring languages[] = {_("System default"), _("Albanian (sq)"), _("Amharic (am)"), _("Arabic (ar)"), _("Armenian (hy)"),_("Azerbaijani (az)"), _("Basque (eu)"), _("Belarusian (be)"),
- _("Bulgarian (bg)"), _("Bengali (bn)"), _("Bengali/Bangladesh (bn_BD)"), _("Breton (br)"), _("Catalan (ca)"), _("Valencian Catalan (ca@valencia)"), _("Chinese/China (zh_CN)"),
- _("Chinese/Taiwan (zh_TW)"), _("Croatian (hr)"), _("Czech (cs)"),
- _("Danish (da)"), _("Dutch (nl)"), _("Dzongkha (dz)"), _("German (de)"), _("Greek (el)"), _("English (en)"), _("English/Australia (en_AU)"),
- _("English/Canada (en_CA)"), _("English/Great Britain (en_GB)"), _("Pig Latin (en_US@piglatin)"),
- _("Esperanto (eo)"), _("Estonian (et)"), _("Farsi (fa)"), _("Finnish (fi)"),
- _("French (fr)"), _("Irish (ga)"), _("Galician (gl)"), _("Hebrew (he)"), _("Hungarian (hu)"),
- _("Indonesian (id)"), _("Icelandic (is)"), _("Italian (it)"), _("Japanese (ja)"), _("Khmer (km)"), _("Kinyarwanda (rw)"), _("Korean (ko)"), _("Lithuanian (lt)"), _("Latvian (lv)"), _("Macedonian (mk)"),
- _("Mongolian (mn)"), _("Nepali (ne)"), _("Norwegian BokmƄl (nb)"), _("Norwegian Nynorsk (nn)"), _("Panjabi (pa)"),
- _("Polish (pl)"), _("Portuguese (pt)"), _("Portuguese/Brazil (pt_BR)"), _("Romanian (ro)"), _("Russian (ru)"),
- _("Serbian (sr)"), _("Serbian in Latin script (sr@latin)"), _("Slovak (sk)"), _("Slovenian (sl)"), _("Spanish (es)"), _("Spanish/Mexico (es_MX)"),
- _("Swedish (sv)"),_("Telugu (te)"), _("Thai (th)"), _("Turkish (tr)"), _("Ukrainian (uk)"), _("Vietnamese (vi)")};
- Glib::ustring langValues[] = {"", "sq", "am", "ar", "hy", "az", "eu", "be", "bg", "bn", "bn_BD", "br", "ca", "ca@valencia", "zh_CN", "zh_TW", "hr", "cs", "da", "nl",
- "dz", "de", "el", "en", "en_AU", "en_CA", "en_GB", "en_US@piglatin", "eo", "et", "fa", "fi", "fr", "ga",
- "gl", "he", "hu", "id", "is", "it", "ja", "km", "rw", "ko", "lt", "lv", "mk", "mn", "ne", "nb", "nn", "pa",
- "pl", "pt", "pt_BR", "ro", "ru", "sr", "sr@latin", "sk", "sl", "es", "es_MX", "sv", "te", "th", "tr", "uk", "vi" };
+ Glib::ustring languages[] = {_("System default"),
+ _("Albanian (sq)"), _("Amharic (am)"), _("Arabic (ar)"), _("Armenian (hy)"), _("Assamese (as)"), _("Azerbaijani (az)"),
+ _("Basque (eu)"), _("Belarusian (be)"), _("Bulgarian (bg)"), _("Bengali (bn)"), _("Bengali/Bangladesh (bn_BD)"), _("Bodo (brx)"), _("Breton (br)"),
+ _("Catalan (ca)"), _("Valencian Catalan (ca@valencia)"), _("Chinese/China (zh_CN)"), _("Chinese/Taiwan (zh_TW)"), _("Croatian (hr)"), _("Czech (cs)"),
+ _("Danish (da)"), _("Dogri (doi)"), _("Dutch (nl)"), _("Dzongkha (dz)"),
+ _("German (de)"), _("Greek (el)"),
+ _("English (en)"), _("English/Australia (en_AU)"), _("English/Canada (en_CA)"), _("English/Great Britain (en_GB)"), _("Pig Latin (en_US@piglatin)"), _("Esperanto (eo)"), _("Estonian (et)"),
+ _("Farsi (fa)"), _("Finnish (fi)"), _("French (fr)"),
+ _("Galician (gl)"), _("Gujarati (gu)"),
+ _("Hebrew (he)"), _("Hindi (hi)"), _("Hungarian (hu)"),
+ _("Icelandic (is)"), _("Indonesian (id)"), _("Irish (ga)"), _("Italian (it)"),
+ _("Japanese (ja)"),
+ _("Kannada (kn)"), _("Kashmiri in Peso-Arabic script (ks@aran)"), _("Kashmiri in Devanagari script (ks@deva)"), _("Khmer (km)"), _("Kinyarwanda (rw)"), _("Konkani (kok)"), _("Konkani in Latin script (kok@latin)"), _("Korean (ko)"),
+ _("Latvian (lv)"), _("Lithuanian (lt)"),
+ _("Macedonian (mk)"), _("Maithili (mai)"), _("Malayalam (ml)"), _("Manipuri (mni)"), _("Manipuri in Bengali script (mni@beng)"), _("Marathi (mr)"), _("Mongolian (mn)"),
+ _("Nepali (ne)"), _("Norwegian BokmƄl (nb)"), _("Norwegian Nynorsk (nn)"),
+ _("Odia (or)"),
+ _("Panjabi (pa)"), _("Polish (pl)"), _("Portuguese (pt)"), _("Portuguese/Brazil (pt_BR)"),
+ _("Romanian (ro)"), _("Russian (ru)"),
+ _("Sanskrit (sa)"), _("Santali (sat)"), _("Santali in Devanagari script (sat@deva)"), _("Serbian (sr)"), _("Serbian in Latin script (sr@latin)"),
+ _("Sindhi (sd)"), _("Sindhi in Devanagari script (sd@deva)"), _("Slovak (sk)"), _("Slovenian (sl)"), _("Spanish (es)"), _("Spanish/Mexico (es_MX)"), _("Swedish (sv)"),
+ _("Tamil (ta)"), _("Telugu (te)"), _("Thai (th)"), _("Turkish (tr)"),
+ _("Ukrainian (uk)"), _("Urdu (ur)"),
+ _("Vietnamese (vi)")};
+ Glib::ustring langValues[] = {"",
+ "sq", "am", "ar", "hy", "as", "az",
+ "eu", "be", "bg", "bn", "bn_BD", "brx", "br",
+ "ca", "ca@valencia", "zh_CN", "zh_TW", "hr", "cs",
+ "da", "doi", "nl", "dz",
+ "de", "el",
+ "en", "en_AU", "en_CA", "en_GB", "en_US@piglatin", "eo", "et",
+ "fa", "fi", "fr",
+ "gl", "gu",
+ "he", "hi", "hu",
+ "is", "id", "ga", "it",
+ "ja",
+ "kn", "ks@aran", "ks@deva", "km", "rw", "kok", "kok@latin", "ko",
+ "lv", "lt",
+ "mk", "mai", "ml", "mni", "mni@beng", "mr", "mn",
+ "ne", "nb", "nn",
+ "or",
+ "pa", "pl", "pt", "pt_BR",
+ "ro", "ru",
+ "sa", "sat", "sat@deva", "sr", "sr@latin",
+ "sd", "sd@deva", "sk", "sl", "es", "es_MX", "sv",
+ "ta", "te", "th", "tr",
+ "uk", "ur",
+ "vi" };
{
// sorting languages according to translated name
@@ -569,7 +613,7 @@ void InkscapePreferences::initPageUI()
_("Set the language for menus and number formats"), false);
{
- Glib::ustring sizeLabels[] = {_("Large"), _("Small"), _("Smaller")};
+ Glib::ustring sizeLabels[] = {C_("Icon size", "Large"), C_("Icon size", "Small"), C_("Icon size", "Smaller")};
int sizeValues[] = {0, 1, 2};
_misc_small_tools.init( "/toolbox/tools/small", sizeLabels, sizeValues, G_N_ELEMENTS(sizeLabels), 0 );
@@ -654,7 +698,7 @@ void InkscapePreferences::initPageUI()
_win_ontop_agressive.init ( _("Aggressive"), "/options/transientpolicy/value", 2, false, &_win_ontop_none);
{
- Glib::ustring defaultSizeLabels[] = {_("Small"), _("Large"), _("Maximized")};
+ Glib::ustring defaultSizeLabels[] = {C_("Window size", "Small"), C_("Window size", "Large"), C_("Window size", "Maximized")};
int defaultSizeValues[] = {0, 1, 2};
_win_default_size.init( "/options/defaultwindowsize/value", defaultSizeLabels, defaultSizeValues, G_N_ELEMENTS(defaultSizeLabels), 1 );
@@ -1218,37 +1262,47 @@ void InkscapePreferences::initPageBehavior()
_scroll_auto_thres.init ( "/options/autoscrolldistance/value", -600.0, 600.0, 1.0, 1.0, -10.0, true, false);
_page_scrolling.add_line( true, _("_Threshold:"), _scroll_auto_thres, _("pixels"),
_("How far (in screen pixels) you need to be from the canvas edge to trigger autoscroll; positive is outside the canvas, negative is within the canvas"), false);
-/*
- _scroll_space.init ( _("Left mouse button pans when Space is pressed"), "/options/spacepans/value", false);
- _page_scrolling.add_line( false, "", _scroll_space, "",
- _("When on, pressing and holding Space and dragging with left mouse button pans canvas (as in Adobe Illustrator); when off, Space temporarily switches to Selector tool (default)"));
-*/
+ _scroll_space.init ( _("Mouse move pans when Space is pressed"), "/options/spacebarpans/value", true);
+ _page_scrolling.add_line( true, "", _scroll_space, "",
+ _("When on, pressing and holding Space and dragging pans canvas"));
_wheel_zoom.init ( _("Mouse wheel zooms by default"), "/options/wheelzooms/value", false);
_page_scrolling.add_line( false, "", _wheel_zoom, "",
_("When on, mouse wheel zooms without Ctrl and scrolls canvas with Ctrl; when off, it zooms with Ctrl and scrolls without Ctrl"));
this->AddPage(_page_scrolling, _("Scrolling"), iter_behavior, PREFS_PAGE_BEHAVIOR_SCROLLING);
// Snapping options
+ _page_snapping.add_group_header( _("Snap indicator"));
+
_snap_indicator.init( _("Enable snap indicator"), "/options/snapindicator/value", true);
- _page_snapping.add_line( false, "", _snap_indicator, "",
+ _page_snapping.add_line( true, "", _snap_indicator, "",
_("After snapping, a symbol is drawn at the point that has snapped"));
- _snap_delay.init("/options/snapdelay/value", 0, 1000, 50, 100, 300, 0);
- _page_snapping.add_line( false, _("_Delay (in ms):"), _snap_delay, "",
- _("Postpone snapping as long as the mouse is moving, and then wait an additional fraction of a second. This additional delay is specified here. When set to zero or to a very small number, snapping will be immediate."), true);
+ _snap_indicator.changed_signal.connect( sigc::mem_fun(_snap_persistence, &Gtk::Widget::set_sensitive) );
+
+ _snap_persistence.init("/options/snapindicatorpersistence/value", 0.1, 10, 0.1, 1, 2, 1);
+ _page_snapping.add_line( true, _("Snap indicator persistence (in seconds):"), _snap_persistence, "",
+ _("Controls how long the snap indicator message will be shown, before it disappears"), true);
+
+ _page_snapping.add_group_header( _("What should snap"));
_snap_closest_only.init( _("Only snap the node closest to the pointer"), "/options/snapclosestonly/value", false);
- _page_snapping.add_line( false, "", _snap_closest_only, "",
+ _page_snapping.add_line( true, "", _snap_closest_only, "",
_("Only try to snap the node that is initially closest to the mouse pointer"));
_snap_weight.init("/options/snapweight/value", 0, 1, 0.1, 0.2, 0.5, 1);
- _page_snapping.add_line( false, _("_Weight factor:"), _snap_weight, "",
+ _page_snapping.add_line( true, _("_Weight factor:"), _snap_weight, "",
_("When multiple snap solutions are found, then Inkscape can either prefer the closest transformation (when set to 0), or prefer the node that was initially the closest to the pointer (when set to 1)"), true);
_snap_mouse_pointer.init( _("Snap the mouse pointer when dragging a constrained knot"), "/options/snapmousepointer/value", false);
- _page_snapping.add_line( false, "", _snap_mouse_pointer, "",
+ _page_snapping.add_line( true, "", _snap_mouse_pointer, "",
_("When dragging a knot along a constraint line, then snap the position of the mouse pointer instead of snapping the projection of the knot onto the constraint line"));
+ _page_snapping.add_group_header( _("Delayed snap"));
+
+ _snap_delay.init("/options/snapdelay/value", 0, 1, 0.1, 0.2, 0.3, 1);
+ _page_snapping.add_line( true, _("Delay (in seconds):"), _snap_delay, "",
+ _("Postpone snapping as long as the mouse is moving, and then wait an additional fraction of a second. This additional delay is specified here. When set to zero or to a very small number, snapping will be immediate."), true);
+
this->AddPage(_page_snapping, _("Snapping"), iter_behavior, PREFS_PAGE_BEHAVIOR_SNAPPING);
// Steps options
diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h
index dcea91741..d1abcfc58 100644
--- a/src/ui/dialog/inkscape-preferences.h
+++ b/src/ui/dialog/inkscape-preferences.h
@@ -15,6 +15,10 @@
#ifndef INKSCAPE_UI_DIALOG_INKSCAPE_PREFERENCES_H
#define INKSCAPE_UI_DIALOG_INKSCAPE_PREFERENCES_H
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
#include <iostream>
#include <vector>
#include "ui/widget/preferences-widget.h"
@@ -56,7 +60,11 @@ enum {
PREFS_PAGE_TOOLS_TEXT,
PREFS_PAGE_TOOLS_SPRAY,
PREFS_PAGE_TOOLS_ERASER,
+
+#if HAVE_POTRACE
PREFS_PAGE_TOOLS_PAINTBUCKET,
+#endif
+
PREFS_PAGE_TOOLS_GRADIENT,
PREFS_PAGE_TOOLS_DROPPER,
PREFS_PAGE_TOOLS_CONNECTOR,
@@ -322,6 +330,7 @@ protected:
UI::Widget::PrefCheckButton _importexport_import_res_override;
UI::Widget::PrefSlider _snap_delay;
UI::Widget::PrefSlider _snap_weight;
+ UI::Widget::PrefSlider _snap_persistence;
UI::Widget::PrefCheckButton _font_dialog;
UI::Widget::PrefCombo _font_unit_type;
UI::Widget::PrefCheckButton _font_output_px;
@@ -493,6 +502,7 @@ protected:
static void AddConvertGuidesCheckbox(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, bool def_value);
static void AddFirstAndLastCheckbox(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, bool def_value);
static void AddDotSizeSpinbutton(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, double def_value);
+ static void AddBaseSimplifySpinbutton(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, double def_value);
static void AddNewObjectsStyle(UI::Widget::DialogPage& p, Glib::ustring const &prefs_path, const gchar* banner = NULL);
void on_pagelist_selection_changed();
diff --git a/src/ui/dialog/knot-properties.cpp b/src/ui/dialog/knot-properties.cpp
new file mode 100644
index 000000000..9c23c33e1
--- /dev/null
+++ b/src/ui/dialog/knot-properties.cpp
@@ -0,0 +1,213 @@
+/**
+ * @file
+ * Dialog for renaming layers.
+ */
+/* Author:
+ * Bryce W. Harrington <bryce@bryceharrington.com>
+ * Andrius R. <knutux@gmail.com>
+ * Abhishek Sharma
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ * Copyright (C) 2006 Andrius R.
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include "ui/dialog/knot-properties.h"
+#include <boost/lexical_cast.hpp>
+#include <gtkmm/stock.h>
+#include <glibmm/main.h>
+#include <glibmm/i18n.h>
+#include "inkscape.h"
+#include "util/units.h"
+#include "desktop.h"
+#include "document.h"
+#include "document-undo.h"
+#include "layer-manager.h"
+#include "message-stack.h"
+
+#include "sp-object.h"
+#include "sp-item.h"
+#include "verbs.h"
+#include "selection.h"
+#include "selection-chemistry.h"
+#include "ui/icon-names.h"
+#include "ui/widget/imagetoggler.h"
+
+//#include "event-context.h"
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+KnotPropertiesDialog::KnotPropertiesDialog()
+: _desktop(NULL), _knotpoint(NULL), _position_visible(false)
+{
+ Gtk::Box *mainVBox = get_vbox();
+
+ _layout_table.set_spacings(4);
+ _layout_table.resize (2, 2);
+ _unit_name = "";
+ // Layer name widgets
+ _knot_x_entry.set_activates_default(true);
+ _knot_x_entry.set_digits(4);
+ _knot_x_entry.set_increments(1,1);
+ _knot_x_entry.set_range(-G_MAXDOUBLE, G_MAXDOUBLE);
+ _knot_x_label.set_label(_("Position X:"));
+ _knot_x_label.set_alignment(1.0, 0.5);
+
+ _knot_y_entry.set_activates_default(true);
+ _knot_y_entry.set_digits(4);
+ _knot_y_entry.set_increments(1,1);
+ _knot_y_entry.set_range(-G_MAXDOUBLE, G_MAXDOUBLE);
+ _knot_y_label.set_label(_("Position Y:"));
+ _knot_y_label.set_alignment(1.0, 0.5);
+
+ _layout_table.attach(_knot_x_label,
+ 0, 1, 0, 1, Gtk::FILL, Gtk::FILL);
+ _layout_table.attach(_knot_x_entry,
+ 1, 2, 0, 1, Gtk::FILL | Gtk::EXPAND, Gtk::FILL);
+
+ _layout_table.attach(_knot_y_label, 0, 1, 1, 2, Gtk::FILL, Gtk::FILL);
+ _layout_table.attach(_knot_y_entry, 1, 2, 1, 2, Gtk::FILL | Gtk::EXPAND, Gtk::FILL);
+
+ mainVBox->pack_start(_layout_table, true, true, 4);
+
+ // Buttons
+ _close_button.set_use_stock(true);
+ _close_button.set_label(Gtk::Stock::CANCEL.id);
+ _close_button.set_can_default();
+
+ _apply_button.set_use_underline(true);
+ _apply_button.set_can_default();
+
+ _close_button.signal_clicked()
+ .connect(sigc::mem_fun(*this, &KnotPropertiesDialog::_close));
+ _apply_button.signal_clicked()
+ .connect(sigc::mem_fun(*this, &KnotPropertiesDialog::_apply));
+
+ signal_delete_event().connect(
+ sigc::bind_return(
+ sigc::hide(sigc::mem_fun(*this, &KnotPropertiesDialog::_close)),
+ true
+ )
+ );
+ add_action_widget(_close_button, Gtk::RESPONSE_CLOSE);
+ add_action_widget(_apply_button, Gtk::RESPONSE_APPLY);
+
+ _apply_button.grab_default();
+
+ show_all_children();
+
+ set_focus(_knot_y_entry);
+}
+
+KnotPropertiesDialog::~KnotPropertiesDialog() {
+
+ _setDesktop(NULL);
+}
+
+void KnotPropertiesDialog::showDialog(SPDesktop *desktop, const SPKnot *pt, Glib::ustring const unit_name)
+{
+ KnotPropertiesDialog *dialog = new KnotPropertiesDialog();
+ dialog->_setDesktop(desktop);
+ dialog->_setKnotPoint(pt->position(), unit_name);
+ dialog->_setPt(pt);
+
+ dialog->set_title(_("Modify Knot Position"));
+ dialog->_apply_button.set_label(_("_Move"));
+
+ dialog->set_modal(true);
+ desktop->setWindowTransient (dialog->gobj());
+ dialog->property_destroy_with_parent() = true;
+
+ dialog->show();
+ dialog->present();
+}
+
+void
+KnotPropertiesDialog::_apply()
+{
+ double d_x = Inkscape::Util::Quantity::convert(_knot_x_entry.get_value(), _unit_name, "px");
+ double d_y = Inkscape::Util::Quantity::convert(_knot_y_entry.get_value(), _unit_name, "px");
+ _knotpoint->moveto(Geom::Point(d_x, d_y));
+ _knotpoint->moved_signal.emit(_knotpoint, _knotpoint->position(), 0);
+ _close();
+}
+
+void
+KnotPropertiesDialog::_close()
+{
+ _setDesktop(NULL);
+ destroy_();
+ Glib::signal_idle().connect(
+ sigc::bind_return(
+ sigc::bind(sigc::ptr_fun(&::operator delete), this),
+ false
+ )
+ );
+}
+
+bool KnotPropertiesDialog::_handleKeyEvent(GdkEventKey * /*event*/)
+{
+
+ /*switch (get_group0_keyval(event)) {
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter: {
+ _apply();
+ return true;
+ }
+ break;
+ }*/
+ return false;
+}
+
+void KnotPropertiesDialog::_handleButtonEvent(GdkEventButton* event)
+{
+ if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) {
+ _apply();
+ }
+}
+
+void KnotPropertiesDialog::_setKnotPoint(Geom::Point knotpoint, Glib::ustring const unit_name)
+{
+ _unit_name = unit_name;
+ _knot_x_entry.set_value( Inkscape::Util::Quantity::convert(knotpoint.x(), "px", _unit_name));
+ _knot_y_entry.set_value( Inkscape::Util::Quantity::convert(knotpoint.y(), "px", _unit_name));
+ _knot_x_label.set_label(g_strdup_printf(_("Position X (%s):"), _unit_name.c_str()));
+ _knot_y_label.set_label(g_strdup_printf(_("Position Y (%s):"), _unit_name.c_str()));
+}
+
+void KnotPropertiesDialog::_setPt(const SPKnot *pt)
+{
+ _knotpoint = const_cast<SPKnot *>(pt);
+}
+
+void KnotPropertiesDialog::_setDesktop(SPDesktop *desktop) {
+ if (desktop) {
+ Inkscape::GC::anchor (desktop);
+ }
+ if (_desktop) {
+ Inkscape::GC::release (_desktop);
+ }
+ _desktop = desktop;
+}
+
+} // namespace
+} // namespace
+} // namespace
+
+
+/*
+ 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/ui/dialog/knot-properties.h b/src/ui/dialog/knot-properties.h
new file mode 100644
index 000000000..fd87df03d
--- /dev/null
+++ b/src/ui/dialog/knot-properties.h
@@ -0,0 +1,97 @@
+/** @file
+ * @brief
+ */
+/* Author:
+ * Bryce W. Harrington <bryce@bryceharrington.com>
+ *
+ * Copyright (C) 2004 Bryce Harrington
+ *
+ * Released under GNU GPL. Read the file 'COPYING' for more information
+ */
+
+#ifndef INKSCAPE_DIALOG_KNOT_PROPERTIES_H
+#define INKSCAPE_DIALOG_KNOT_PROPERTIES_H
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gtkmm.h>
+#include <2geom/point.h>
+#include "knot.h"
+#include "ui/tools/measure-tool.h"
+
+class SPDesktop;
+
+namespace Inkscape {
+namespace UI {
+namespace Dialogs {
+
+
+class KnotPropertiesDialog : public Gtk::Dialog {
+ public:
+ KnotPropertiesDialog();
+ virtual ~KnotPropertiesDialog();
+
+ Glib::ustring getName() const { return "LayerPropertiesDialog"; }
+
+ static void showDialog(SPDesktop *desktop, const SPKnot *pt, Glib::ustring const unit_name);
+
+protected:
+
+ SPDesktop *_desktop;
+ SPKnot *_knotpoint;
+
+ Gtk::Label _knot_x_label;
+ Gtk::SpinButton _knot_x_entry;
+ Gtk::Label _knot_y_label;
+ Gtk::SpinButton _knot_y_entry;
+ Gtk::Table _layout_table;
+ bool _position_visible;
+
+ Gtk::Button _close_button;
+ Gtk::Button _apply_button;
+ Glib::ustring _unit_name;
+
+ sigc::connection _destroy_connection;
+
+ static KnotPropertiesDialog &_instance() {
+ static KnotPropertiesDialog instance;
+ return instance;
+ }
+
+ void _setDesktop(SPDesktop *desktop);
+ void _setPt(const SPKnot *pt);
+
+ void _apply();
+ void _close();
+
+ void _setKnotPoint(Geom::Point knotpoint, Glib::ustring const unit_name);
+ void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row);
+
+ bool _handleKeyEvent(GdkEventKey *event);
+ void _handleButtonEvent(GdkEventButton* event);
+ friend class Inkscape::UI::Tools::MeasureTool;
+
+private:
+ KnotPropertiesDialog(KnotPropertiesDialog const &); // no copy
+ KnotPropertiesDialog &operator=(KnotPropertiesDialog const &); // no assign
+};
+
+} // namespace
+} // namespace
+} // namespace
+
+
+#endif //INKSCAPE_DIALOG_LAYER_PROPERTIES_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/ui/dialog/layers.cpp b/src/ui/dialog/layers.cpp
index 3f5e80f8d..1c022ecad 100644
--- a/src/ui/dialog/layers.cpp
+++ b/src/ui/dialog/layers.cpp
@@ -715,11 +715,11 @@ void LayersPanel::_doTreeMove( )
{
if (_dnd_source && _dnd_source->getRepr() ) {
if(!_dnd_target){
- _dnd_source->doWriteTransform(_dnd_source->getRepr(), _dnd_source->document->getRoot()->i2doc_affine().inverse() * _dnd_source->i2doc_affine());
+ _dnd_source->doWriteTransform(_dnd_source->getRepr(), _dnd_source->i2doc_affine() * _dnd_source->document->getRoot()->i2doc_affine().inverse());
}else{
SPItem* parent = _dnd_into ? _dnd_target : dynamic_cast<SPItem*>(_dnd_target->parent);
if(parent){
- Geom::Affine move = parent->i2doc_affine().inverse() * _dnd_source->i2doc_affine();
+ Geom::Affine move = _dnd_source->i2doc_affine() * parent->i2doc_affine().inverse();
_dnd_source->doWriteTransform(_dnd_source->getRepr(), move);
}
}
@@ -1040,14 +1040,6 @@ void LayersPanel::setDesktop( SPDesktop* desktop )
_layersChanged();
}
}
-/*
- GSList const *layers = _desktop->doc()->getResourceList( "layer" );
- g_message( "layers list starts at %p", layers );
- for ( GSList const *iter=layers ; iter ; iter = iter->next ) {
- SPObject *layer=static_cast<SPObject *>(iter->data);
- g_message(" {%s} [%s]", layer->id, layer->label() );
- }
-*/
deskTrack.setBase(desktop);
}
diff --git a/src/ui/dialog/new-from-template.cpp b/src/ui/dialog/new-from-template.cpp
index e30b148bb..74ec7111e 100644
--- a/src/ui/dialog/new-from-template.cpp
+++ b/src/ui/dialog/new-from-template.cpp
@@ -29,10 +29,12 @@ NewFromTemplate::NewFromTemplate()
set_title(_("New From Template"));
resize(400, 400);
+ _main_widget = new TemplateLoadTab(this);
+
#if WITH_GTKMM_3_0
- get_content_area()->pack_start(_main_widget);
+ get_content_area()->pack_start(*_main_widget);
#else
- get_vbox()->pack_start(_main_widget);
+ get_vbox()->pack_start(*_main_widget);
#endif
Gtk::Alignment *align;
@@ -49,14 +51,24 @@ NewFromTemplate::NewFromTemplate()
_create_template_button.signal_clicked().connect(
sigc::mem_fun(*this, &NewFromTemplate::_createFromTemplate));
+ _create_template_button.set_sensitive(false);
show_all();
}
+NewFromTemplate::~NewFromTemplate()
+{
+ delete _main_widget;
+}
+
+void NewFromTemplate::setCreateButtonSensitive(bool value)
+{
+ _create_template_button.set_sensitive(value);
+}
void NewFromTemplate::_createFromTemplate()
{
- _main_widget.createTemplate();
+ _main_widget->createTemplate();
_onClose();
}
diff --git a/src/ui/dialog/new-from-template.h b/src/ui/dialog/new-from-template.h
index 2b40af2a6..c0b65affb 100644
--- a/src/ui/dialog/new-from-template.h
+++ b/src/ui/dialog/new-from-template.h
@@ -27,11 +27,13 @@ class NewFromTemplate : public Gtk::Dialog
friend class TemplateLoadTab;
public:
static void load_new_from_template();
-
+ void setCreateButtonSensitive(bool value);
+ virtual ~NewFromTemplate();
+
private:
NewFromTemplate();
Gtk::Button _create_template_button;
- TemplateLoadTab _main_widget;
+ TemplateLoadTab* _main_widget;
void _createFromTemplate();
void _onClose();
diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp
index 835ecf35b..891048beb 100644
--- a/src/ui/dialog/objects.cpp
+++ b/src/ui/dialog/objects.cpp
@@ -479,7 +479,7 @@ void ObjectsPanel::_objectsSelected( Selection *sel ) {
_tree.get_selection()->unselect_all();
SPItem *item = NULL;
std::vector<SPItem*> const items = sel->itemList();
- for(std::vector<SPItem*>::const_iterator i=items.begin(); i!=items.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=items.begin(); i!=items.end(); ++i){
item = *i;
if (setOpacity)
{
@@ -1583,6 +1583,10 @@ void ObjectsPanel::_blurChangedIter(const Gtk::TreeIter& iter, double blur)
}
if (radius != 0) {
+ // The modify function expects radius to be in display pixels.
+ Geom::Affine i2d (item->i2dt_affine());
+ double expansion = i2d.descrim();
+ radius *= expansion;
SPFilter *filter = modify_filter_gaussian_blur_from_item(_document, item, radius);
sp_style_set_property_url(item, "filter", filter, false);
} else if (item->style->filter.set && item->style->getFilter()) {
@@ -1614,11 +1618,11 @@ ObjectsPanel::ObjectsPanel() :
_pending(0),
_toggleEvent(0),
_defer_target(),
- _visibleHeader(_("V")),
- _lockHeader(_("L")),
- _typeHeader(_("T")),
- _clipmaskHeader(_("CM")),
- _highlightHeader(_("HL")),
+ _visibleHeader(C_("Visibility", "V")),
+ _lockHeader(C_("Lock", "L")),
+ _typeHeader(C_("Type", "T")),
+ _clipmaskHeader(C_("Clip and mask", "CM")),
+ _highlightHeader(C_("Highlight", "HL")),
_nameHeader(_("Label")),
_composite_vbox(false, 0),
_opacity_vbox(false, 0),
diff --git a/src/ui/dialog/pixelartdialog.cpp b/src/ui/dialog/pixelartdialog.cpp
index 760391df6..f557ff0fc 100644
--- a/src/ui/dialog/pixelartdialog.cpp
+++ b/src/ui/dialog/pixelartdialog.cpp
@@ -373,7 +373,7 @@ void PixelArtDialogImpl::vectorize()
}
std::vector<SPItem*> const items = desktop->selection->itemList();
- for(std::vector<SPItem*>::const_iterator i=items.begin(); i!=items.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=items.begin(); i!=items.end();++i){
if ( !SP_IS_IMAGE(*i) )
continue;
diff --git a/src/ui/dialog/polar-arrange-tab.cpp b/src/ui/dialog/polar-arrange-tab.cpp
index af1386e27..5ec1285c1 100644
--- a/src/ui/dialog/polar-arrange-tab.cpp
+++ b/src/ui/dialog/polar-arrange-tab.cpp
@@ -304,7 +304,7 @@ void PolarArrangeTab::arrange()
bool arrangeOnFirstEllipse = arrangeOnEllipse && arrangeOnFirstCircleRadio.get_active();
int count = 0;
- for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();i++)
+ for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();++i)
{
if(arrangeOnEllipse)
{
@@ -373,7 +373,7 @@ void PolarArrangeTab::arrange()
Geom::Point realCenter = Geom::Point(cx, cy) * transformation;
int i = 0;
- for(std::vector<SPItem*>::const_iterator it=tmp.begin();it!=tmp.end();it++)
+ for(std::vector<SPItem*>::const_iterator it=tmp.begin();it!=tmp.end(); ++it)
{
SPItem *item = *it;
diff --git a/src/ui/dialog/svg-fonts-dialog.cpp b/src/ui/dialog/svg-fonts-dialog.cpp
index 12b423602..46e045c14 100644
--- a/src/ui/dialog/svg-fonts-dialog.cpp
+++ b/src/ui/dialog/svg-fonts-dialog.cpp
@@ -266,12 +266,12 @@ void SvgFontsDialog::update_fonts()
{
SPDesktop* desktop = this->getDesktop();
SPDocument* document = desktop->getDocument();
- const GSList* fonts = document->getResourceList("font");
+ std::set<SPObject *> fonts = document->getResourceList( "fonts" );
_model->clear();
- for(const GSList *l = fonts; l; l = l->next) {
+ for (std::set<SPObject *>::const_iterator it = fonts.begin(); it != fonts.end(); ++it) {
Gtk::TreeModel::Row row = *_model->append();
- SPFont* f = SP_FONT(l->data);
+ SPFont* f = SP_FONT(*it);
row[_columns.spfont] = f;
row[_columns.svgfont] = new SvgFont(f);
const gchar* lbl = f->label();
diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp
index 72677c07e..924ebe03d 100644
--- a/src/ui/dialog/swatches.cpp
+++ b/src/ui/dialog/swatches.cpp
@@ -171,9 +171,9 @@ static void editGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ )
SPDocument *doc = desktop ? desktop->doc() : 0;
if (doc) {
std::string targetName(bounceTarget->def.descr);
- const GSList *gradients = doc->getResourceList("gradient");
- for (const GSList *item = gradients; item; item = item->next) {
- SPGradient* grad = SP_GRADIENT(item->data);
+ std::set<SPObject *> gradients = doc->getResourceList("gradient");
+ for (std::set<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) {
+ SPGradient* grad = SP_GRADIENT(*item);
if ( targetName == grad->getId() ) {
editGradientImpl( desktop, grad );
break;
@@ -192,10 +192,10 @@ void SwatchesPanelHook::convertGradient( GtkMenuItem * /*menuitem*/, gpointer us
gint index = GPOINTER_TO_INT(userData);
if ( doc && (index >= 0) && (static_cast<guint>(index) < popupItems.size()) ) {
Glib::ustring targetName = popupItems[index];
+ std::set<SPObject *> gradients = doc->getResourceList("gradient");
+ for (std::set<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) {
+ SPGradient* grad = SP_GRADIENT(*item);
- const GSList *gradients = doc->getResourceList("gradient");
- for (const GSList *item = gradients; item; item = item->next) {
- SPGradient* grad = SP_GRADIENT(item->data);
if ( targetName == grad->getId() ) {
grad->setSwatch();
DocumentUndo::done(doc, SP_VERB_CONTEXT_GRADIENT,
@@ -326,10 +326,10 @@ gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, g
SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(wdgt);
if ( dtw && dtw->desktop ) {
// Pick up all gradients with vectors
- const GSList *gradients = (dtw->desktop->doc())->getResourceList("gradient");
+ std::set<SPObject *> gradients = (dtw->desktop->doc())->getResourceList("gradient");
gint index = 0;
- for (const GSList *curr = gradients; curr; curr = curr->next) {
- SPGradient* grad = SP_GRADIENT(curr->data);
+ for (std::set<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) {
+ SPGradient* grad = SP_GRADIENT(*item);
if ( grad->hasStops() && !grad->isSwatch() ) {
//gl = g_slist_prepend(gl, curr->data);
processed = true;
@@ -393,10 +393,10 @@ static bool parseNum( char*& str, int& val ) {
}
-void _loadPaletteFile( gchar const *filename, gboolean user/*=FALSE*/ )
+void _loadPaletteFile( gchar const *filename, gchar const *path, gboolean user/*=FALSE*/ )
{
char block[1024];
- FILE *f = Inkscape::IO::fopen_utf8name( filename, "r" );
+ FILE *f = Inkscape::IO::fopen_utf8name(path, "r" );
if ( f ) {
char* result = fgets( block, sizeof(block), f );
if ( result ) {
@@ -405,6 +405,7 @@ void _loadPaletteFile( gchar const *filename, gboolean user/*=FALSE*/ )
bool hasErr = false;
SwatchPage *onceMore = new SwatchPage();
+ onceMore->_name = filename;
do {
result = fgets( block, sizeof(block), f );
@@ -521,7 +522,7 @@ compare_swatch_names(SwatchPage const *a, SwatchPage const *b) {
static void loadEmUp()
{
static bool beenHere = false;
- gboolean userPalete = true;
+ gboolean userPalette = true;
if ( !beenHere ) {
beenHere = true;
@@ -549,7 +550,7 @@ static void loadEmUp()
if ( !g_str_has_suffix(lower, "~") ) {
gchar* full = g_build_filename(dirname, filename, NULL);
if ( !Inkscape::IO::file_test( full, G_FILE_TEST_IS_DIR ) ) {
- _loadPaletteFile(full, userPalete);
+ _loadPaletteFile(filename, full, userPalette);
}
g_free(full);
}
@@ -563,7 +564,7 @@ static void loadEmUp()
// toss the dirname
g_free(dirname);
sources.pop_front();
- userPalete = false;
+ userPalette = false;
}
}
@@ -923,12 +924,11 @@ static void recalcSwatchContents(SPDocument* doc,
std::map<ColorItem*, SPGradient*> &gradMappings)
{
std::vector<SPGradient*> newList;
-
- const GSList *gradients = doc->getResourceList("gradient");
- for (const GSList *item = gradients; item; item = item->next) {
- SPGradient* grad = SP_GRADIENT(item->data);
+ std::set<SPObject *> gradients = doc->getResourceList("gradient");
+ for (std::set<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) {
+ SPGradient* grad = SP_GRADIENT(*item);
if ( grad->isSwatch() ) {
- newList.push_back(SP_GRADIENT(item->data));
+ newList.push_back(SP_GRADIENT(*item));
}
}
diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp
index f36e3f18d..cbb2fb953 100644
--- a/src/ui/dialog/tags.cpp
+++ b/src/ui/dialog/tags.cpp
@@ -13,10 +13,6 @@
# include <config.h>
#endif
-#if WITH_GLIBMM_2_32
-# include <glibmm/threads.h>
-#endif
-
#include "tags.h"
#include <gtkmm/widget.h>
#include <gtkmm/icontheme.h>
@@ -353,7 +349,7 @@ void TagsPanel::_objectsSelected( Selection *sel ) {
_selectedConnection.block();
_tree.get_selection()->unselect_all();
std::vector<SPObject*> tmp=sel->list();
- for(std::vector<SPObject*>::const_iterator i=tmp.begin();i!=tmp.end();i++)
+ for(std::vector<SPObject*>::const_iterator i=tmp.begin();i!=tmp.end();++i)
{
SPObject *obj = *i;
_store->foreach(sigc::bind<SPObject *>( sigc::mem_fun(*this, &TagsPanel::_checkForSelected), obj));
@@ -651,7 +647,7 @@ bool TagsPanel::_handleButtonEvent(GdkEventButton* event)
if (SP_IS_TAG(obj)) {
bool wasadded = false;
std::vector<SPItem*> items=_desktop->selection->itemList();
- for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();++i){
SPObject *newobj = *i;
bool addchild = true;
for ( SPObject *child = obj->children; child != NULL; child = child->next) {
diff --git a/src/ui/dialog/template-load-tab.cpp b/src/ui/dialog/template-load-tab.cpp
index fca1f7b30..7eb04ff79 100644
--- a/src/ui/dialog/template-load-tab.cpp
+++ b/src/ui/dialog/template-load-tab.cpp
@@ -35,10 +35,11 @@
namespace Inkscape {
namespace UI {
-TemplateLoadTab::TemplateLoadTab()
+TemplateLoadTab::TemplateLoadTab(NewFromTemplate* parent)
: _current_keyword("")
, _keywords_combo(true)
, _current_search_type(ALL)
+ , _parent_widget(parent)
{
set_border_width(10);
@@ -94,7 +95,8 @@ void TemplateLoadTab::_displayTemplateInfo()
if (templateSelectionRef->get_selected()) {
_current_template = (*templateSelectionRef->get_selected())[_columns.textValue];
- _info_widget->display(_tdata[_current_template]);
+ _info_widget->display(_tdata[_current_template]);
+ _parent_widget->setCreateButtonSensitive(true);
}
}
@@ -148,11 +150,10 @@ void TemplateLoadTab::_keywordSelected()
void TemplateLoadTab::_refreshTemplatesList()
{
- _tlist_store->clear();
-
+ _tlist_store->clear();
+
switch (_current_search_type){
case ALL :{
-
for (std::map<Glib::ustring, TemplateData>::iterator it = _tdata.begin() ; it != _tdata.end() ; ++it) {
Gtk::TreeModel::iterator iter = _tlist_store->append();
Gtk::TreeModel::Row row = *iter;
@@ -160,7 +161,7 @@ void TemplateLoadTab::_refreshTemplatesList()
}
break;
}
-
+
case LIST_KEYWORD: {
for (std::map<Glib::ustring, TemplateData>::iterator it = _tdata.begin() ; it != _tdata.end() ; ++it) {
if (it->second.keywords.count(_current_keyword.lowercase()) != 0){
@@ -171,10 +172,10 @@ void TemplateLoadTab::_refreshTemplatesList()
}
break;
}
-
+
case USER_SPECIFIED : {
for (std::map<Glib::ustring, TemplateData>::iterator it = _tdata.begin() ; it != _tdata.end() ; ++it) {
- if (it->second.keywords.count(_current_keyword.lowercase()) != 0 ||
+ if (it->second.keywords.count(_current_keyword.lowercase()) != 0 ||
it->second.display_name.lowercase().find(_current_keyword.lowercase()) != Glib::ustring::npos ||
it->second.author.lowercase().find(_current_keyword.lowercase()) != Glib::ustring::npos ||
it->second.short_description.lowercase().find(_current_keyword.lowercase()) != Glib::ustring::npos ||
@@ -188,6 +189,27 @@ void TemplateLoadTab::_refreshTemplatesList()
break;
}
}
+
+ // reselect item
+ Gtk::TreeIter* item_to_select = NULL;
+ for (Gtk::TreeModel::Children::iterator it = _tlist_store->children().begin(); it != _tlist_store->children().end(); ++it) {
+ Gtk::TreeModel::Row row = *it;
+ if (_current_template == row[_columns.textValue]) {
+ item_to_select = new Gtk::TreeIter(it);
+ break;
+ }
+ }
+ if (_tlist_store->children().size() == 1) {
+ item_to_select = new Gtk::TreeIter(_tlist_store->children().begin());
+ }
+ if (item_to_select) {
+ _tlist_view.get_selection()->select(*item_to_select);
+ delete item_to_select;
+ } else {
+ _current_template = "";
+ _info_widget->clear();
+ _parent_widget->setCreateButtonSensitive(false);
+ }
}
diff --git a/src/ui/dialog/template-load-tab.h b/src/ui/dialog/template-load-tab.h
index 920ae6ca2..d11c4c77f 100644
--- a/src/ui/dialog/template-load-tab.h
+++ b/src/ui/dialog/template-load-tab.h
@@ -28,6 +28,7 @@ namespace Inkscape {
namespace UI {
class TemplateWidget;
+class NewFromTemplate;
class TemplateLoadTab : public Gtk::HBox
{
@@ -47,7 +48,7 @@ public:
Inkscape::Extension::Effect *tpl_effect;
};
- TemplateLoadTab();
+ TemplateLoadTab(NewFromTemplate* parent);
virtual ~TemplateLoadTab();
virtual void createTemplate();
@@ -95,6 +96,7 @@ private:
};
SearchType _current_search_type;
+ NewFromTemplate* _parent_widget;
void _getDataFromNode(Inkscape::XML::Node *, TemplateData &);
void _getProceduralTemplates();
diff --git a/src/ui/dialog/template-widget.cpp b/src/ui/dialog/template-widget.cpp
index eff75b311..0d110d853 100644
--- a/src/ui/dialog/template-widget.cpp
+++ b/src/ui/dialog/template-widget.cpp
@@ -56,6 +56,7 @@ TemplateWidget::TemplateWidget()
_more_info_button.signal_clicked().connect(
sigc::mem_fun(*this, &TemplateWidget::_displayTemplateDetails));
+ _more_info_button.set_sensitive(false);
}
@@ -85,14 +86,12 @@ void TemplateWidget::create()
void TemplateWidget::display(TemplateLoadTab::TemplateData data)
{
+ clear();
_current_template = data;
_template_name_label.set_text(_current_template.display_name);
_short_description_label.set_text(_current_template.short_description);
-
- _preview_render.hide();
- _preview_image.hide();
-
+
std::string imagePath = Glib::build_filename(Glib::path_get_dirname(_current_template.path), _current_template.preview_name);
if (data.preview_name != ""){
_preview_image.set(imagePath);
@@ -103,17 +102,26 @@ void TemplateWidget::display(TemplateLoadTab::TemplateData data)
_preview_render.showImage(gPath);
_preview_render.show();
}
-
- if (_effect_prefs != NULL){
- remove (*_effect_prefs);
- _effect_prefs = NULL;
- }
+
if (data.is_procedural){
_effect_prefs = data.tpl_effect->get_imp()->prefs_effect(data.tpl_effect, SP_ACTIVE_DESKTOP, NULL, NULL);
pack_start(*_effect_prefs);
}
+ _more_info_button.set_sensitive(true);
}
+void TemplateWidget::clear()
+{
+ _template_name_label.set_text("");
+ _short_description_label.set_text("");
+ _preview_render.hide();
+ _preview_image.hide();
+ if (_effect_prefs != NULL){
+ remove (*_effect_prefs);
+ _effect_prefs = NULL;
+ }
+ _more_info_button.set_sensitive(false);
+}
void TemplateWidget::_displayTemplateDetails()
{
diff --git a/src/ui/dialog/template-widget.h b/src/ui/dialog/template-widget.h
index bb35d26a0..13488089c 100644
--- a/src/ui/dialog/template-widget.h
+++ b/src/ui/dialog/template-widget.h
@@ -28,6 +28,7 @@ public:
TemplateWidget ();
void create();
void display(TemplateLoadTab::TemplateData);
+ void clear();
private:
TemplateLoadTab::TemplateData _current_template;
diff --git a/src/ui/dialog/text-edit.cpp b/src/ui/dialog/text-edit.cpp
index 7575cc854..c01da8864 100644
--- a/src/ui/dialog/text-edit.cpp
+++ b/src/ui/dialog/text-edit.cpp
@@ -127,8 +127,8 @@ TextEdit::TextEdit()
gtk_combo_box_text_append_text((GtkComboBoxText *) spacing_combo, spacings[i]);
}
- gtk_widget_set_tooltip_text (px, _("Spacing between lines (percent of font size)"));
- gtk_widget_set_tooltip_text (spacing_combo, _("Spacing between lines (percent of font size)"));
+ gtk_widget_set_tooltip_text (px, _("Spacing between baselines (percent of font size)"));
+ gtk_widget_set_tooltip_text (spacing_combo, _("Spacing between baselines (percent of font size)"));
layout_hbox.pack_start(*Gtk::manage(Glib::wrap(spacing_combo)), false, false);
layout_frame.set_padding(4,4,4,4);
layout_frame.add(layout_hbox);
@@ -175,6 +175,19 @@ TextEdit::TextEdit()
gtk_text_view_set_wrap_mode ((GtkTextView *) text_view, GTK_WRAP_WORD);
#ifdef WITH_GTKSPELL
+#ifdef WITH_GTKMM_3_0
+/*
+ TODO: Use computed xml:lang attribute of relevant element, if present, to specify the
+ language (either as 2nd arg of gtkspell_new_attach, or with explicit
+ gtkspell_set_language call in; see advanced.c example in gtkspell docs).
+ onReadSelection looks like a suitable place.
+*/
+ GtkSpellChecker * speller = gtk_spell_checker_new();
+
+ if (! gtk_spell_checker_attach(speller, GTK_TEXT_VIEW(text_view))) {
+ g_print("gtkspell error:\n");
+ }
+#else
GError *error = NULL;
/*
@@ -188,6 +201,7 @@ TextEdit::TextEdit()
g_error_free(error);
}
#endif
+#endif
gtk_widget_set_size_request (text_view, -1, 64);
gtk_text_view_set_editable (GTK_TEXT_VIEW (text_view), TRUE);
@@ -430,7 +444,7 @@ SPItem *TextEdit::getSelectedTextItem (void)
return NULL;
std::vector<SPItem*> tmp=SP_ACTIVE_DESKTOP->getSelection()->itemList();
- for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();i++)
+ for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();++i)
{
if (SP_IS_TEXT(*i) || SP_IS_FLOWTEXT(*i))
return *i;
@@ -448,7 +462,7 @@ unsigned TextEdit::getSelectedTextCount (void)
unsigned int items = 0;
std::vector<SPItem*> tmp=SP_ACTIVE_DESKTOP->getSelection()->itemList();
- for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();i++)
+ for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();++i)
{
if (SP_IS_TEXT(*i) || SP_IS_FLOWTEXT(*i))
++items;
@@ -558,7 +572,7 @@ void TextEdit::onApply()
SPCSSAttr *css = fillTextStyle ();
sp_desktop_set_style(desktop, css, true);
- for(std::vector<SPItem*>::const_iterator i=item_list.begin();i!=item_list.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=item_list.begin();i!=item_list.end();++i){
// apply style to the reprs of all text objects in the selection
if (SP_IS_TEXT (*i)) {
diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp
index 498ad7822..b7638e8c1 100644
--- a/src/ui/dialog/transformation.cpp
+++ b/src/ui/dialog/transformation.cpp
@@ -35,7 +35,6 @@
#include "sp-item-transform.h"
#include "macros.h"
#include "sp-item.h"
-#include "util/glib-list-iterators.h"
#include "ui/icon-names.h"
#include "widgets/icon.h"
@@ -812,7 +811,7 @@ void Transformation::applyPageScale(Inkscape::Selection *selection)
bool preserve = prefs->getBool("/options/preservetransform/value", false);
if (prefs->getBool("/dialogs/transformation/applyseparately")) {
std::vector<SPItem*> tmp=selection->itemList();
- for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();++i){
SPItem *item = *i;
Geom::OptRect bbox_pref = item->desktopPreferredBounds();
Geom::OptRect bbox_geom = item->desktopGeometricBounds();
@@ -876,7 +875,7 @@ void Transformation::applyPageRotate(Inkscape::Selection *selection)
if (prefs->getBool("/dialogs/transformation/applyseparately")) {
std::vector<SPItem*> tmp=selection->itemList();
- for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();++i){
SPItem *item = *i;
sp_item_rotate_rel(item, Geom::Rotate (angle*M_PI/180.0));
}
@@ -896,7 +895,7 @@ void Transformation::applyPageSkew(Inkscape::Selection *selection)
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
if (prefs->getBool("/dialogs/transformation/applyseparately")) {
std::vector<SPItem*> items=selection->itemList();
- for(std::vector<SPItem*>::const_iterator i = items.begin();i!=items.end();i++){
+ for(std::vector<SPItem*>::const_iterator i = items.begin();i!=items.end();++i){
SPItem *item = *i;
if (!_units_skew.isAbsolute()) { // percentage
@@ -998,7 +997,7 @@ void Transformation::applyPageTransform(Inkscape::Selection *selection)
if (_check_replace_matrix.get_active()) {
std::vector<SPItem*> tmp=selection->itemList();
- for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=tmp.begin();i!=tmp.end();++i){
SPItem *item = *i;
item->set_item_transform(displayed);
item->updateRepr();
@@ -1170,6 +1169,9 @@ void Transformation::onReplaceMatrixToggled()
void Transformation::onScaleProportionalToggled()
{
onScaleXValueChanged();
+ if (_scalar_scale_vertical.setProgrammatically) {
+ _scalar_scale_vertical.setProgrammatically = false;
+ }
}
diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp
index a129d4b92..69b229519 100644
--- a/src/ui/interface.cpp
+++ b/src/ui/interface.cpp
@@ -239,7 +239,7 @@ sp_create_window(SPViewWidget *vw, bool editable)
}
int pos = nui_drop_target_entries;
- for (std::vector<gchar*>::iterator it = types.begin() ; it != types.end() ; it++) {
+ for (std::vector<gchar*>::iterator it = types.begin() ; it != types.end() ; ++it) {
completeDropTargets[pos].target = *it;
completeDropTargets[pos].flags = 0;
completeDropTargets[pos].info = IMAGE_DATA;
@@ -577,6 +577,9 @@ static gboolean checkitem_update(GtkWidget *widget, GdkEventExpose * /*event*/,
if (!strcmp(action->id, "ToggleGrid")) {
ison = dt->gridsEnabled();
}
+ else if (!strcmp(action->id, "EditGuidesToggleLock")) {
+ ison = dt->namedview->lockguides;
+ }
else if (!strcmp(action->id, "ToggleGuides")) {
ison = dt->namedview->getGuides();
}
@@ -846,13 +849,11 @@ static void sp_ui_build_dyn_menus(Inkscape::XML::Node *menus, GtkWidget *menu, I
#endif
}
} else if (menu_pntr->attribute("check") != NULL) {
- SPAction *action = NULL;
if (verb->get_code() != SP_VERB_NONE) {
- action = verb->get_action(Inkscape::ActionContext(view));
- }
- sp_ui_menu_append_check_item_from_verb(GTK_MENU(menu), view, action->name, action->tip, NULL,
+ SPAction *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);
-
+ }
} else {
sp_ui_menu_append_item_from_verb(GTK_MENU(menu), verb, view);
group = NULL;
@@ -868,11 +869,7 @@ static void sp_ui_build_dyn_menus(Inkscape::XML::Node *menus, GtkWidget *menu, I
}
continue;
}
- if (!strcmp(menu_pntr->name(), "separator")
- // This was spelt wrong in the original version
- // and so this is for backward compatibility. It can
- // probably be dropped after the 0.44 release.
- || !strcmp(menu_pntr->name(), "seperator")) {
+ if (!strcmp(menu_pntr->name(), "separator")) {
GtkWidget *item = gtk_separator_menu_item_new();
gtk_widget_show(item);
gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
@@ -1119,9 +1116,9 @@ sp_ui_drag_data_received(GtkWidget *widget,
unsigned int b = color.getB();
SPGradient* matches = 0;
- const GSList *gradients = doc->getResourceList("gradient");
- for (const GSList *item = gradients; item; item = item->next) {
- SPGradient* grad = SP_GRADIENT(item->data);
+ std::set<SPObject *> gradients = doc->getResourceList("gradient");
+ for (std::set<SPObject *>::const_iterator item = gradients.begin(); item != gradients.end(); ++item) {
+ SPGradient* grad = SP_GRADIENT(*item);
if ( color.descr == grad->getId() ) {
if ( grad->hasStops() ) {
matches = grad;
@@ -2076,7 +2073,7 @@ void ContextMenu::ImageEdit(void)
#endif
std::vector<SPItem*> itemlist=_desktop->selection->itemList();
- for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=itemlist.begin();i!=itemlist.end();++i){
Inkscape::XML::Node *ir = (*i)->getRepr();
const gchar *href = ir->attribute("xlink:href");
diff --git a/src/ui/object-edit.cpp b/src/ui/object-edit.cpp
index 0a6c792dc..459acf002 100644
--- a/src/ui/object-edit.cpp
+++ b/src/ui/object-edit.cpp
@@ -1364,13 +1364,15 @@ public:
};
void
-OffsetKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int /*state*/)
+OffsetKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, unsigned int state)
{
SPOffset *offset = dynamic_cast<SPOffset *>(item);
g_assert(offset != NULL);
- offset->rad = sp_offset_distance_to_original(offset, p);
- offset->knot = p;
+ Geom::Point const p_snapped = snap_knot_position(p, state);
+
+ offset->rad = sp_offset_distance_to_original(offset, p_snapped);
+ offset->knot = p_snapped;
offset->knotSet = true;
offset->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
diff --git a/src/ui/tool-factory.cpp b/src/ui/tool-factory.cpp
index 700bd40ce..c6c579c9e 100644
--- a/src/ui/tool-factory.cpp
+++ b/src/ui/tool-factory.cpp
@@ -16,7 +16,11 @@
#include "ui/tools/connector-tool.h"
#include "ui/tools/dropper-tool.h"
#include "ui/tools/eraser-tool.h"
-#include "ui/tools/flood-tool.h"
+
+#if HAVE_POTRACE
+# include "ui/tools/flood-tool.h"
+#endif
+
#include "ui/tools/gradient-tool.h"
#include "ui/tools/lpe-tool.h"
#include "ui/tools/measure-tool.h"
@@ -52,8 +56,10 @@ ToolBase *ToolFactory::createObject(std::string const& id)
tool = new DropperTool;
else if (id == "/tools/eraser")
tool = new EraserTool;
+#if HAVE_POTRACE
else if (id == "/tools/paintbucket")
tool = new FloodTool;
+#endif
else if (id == "/tools/gradient")
tool = new GradientTool;
else if (id == "/tools/lpetool")
diff --git a/src/ui/tool/control-point-selection.cpp b/src/ui/tool/control-point-selection.cpp
index 998f74ee0..f36ad7374 100644
--- a/src/ui/tool/control-point-selection.cpp
+++ b/src/ui/tool/control-point-selection.cpp
@@ -19,6 +19,8 @@
#include "ui/tool/transform-handle-set.h"
#include "ui/tool/node.h"
+
+
#include <gdk/gdkkeysyms.h>
namespace Inkscape {
@@ -82,6 +84,7 @@ std::pair<ControlPointSelection::iterator, bool> ControlPointSelection::insert(c
}
found = _points.insert(x).first;
+ _points_list.push_back(x);
x->updateState();
_pointChanged(x, true);
@@ -97,6 +100,7 @@ std::pair<ControlPointSelection::iterator, bool> ControlPointSelection::insert(c
void ControlPointSelection::erase(iterator pos)
{
SelectableControlPoint *erased = *pos;
+ _points_list.remove(*pos);
_points.erase(pos);
erased->updateState();
_pointChanged(erased, false);
@@ -219,8 +223,11 @@ void ControlPointSelection::transform(Geom::Affine const &m)
/** Align control points on the specified axis. */
void ControlPointSelection::align(Geom::Dim2 axis)
{
+ enum AlignTargetNode { LAST_NODE=0, FIRST_NODE, MID_NODE, MIN_NODE, MAX_NODE };
if (empty()) return;
Geom::Dim2 d = static_cast<Geom::Dim2>((axis + 1) % 2);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
Geom::OptInterval bound;
for (iterator i = _points.begin(); i != _points.end(); ++i) {
@@ -229,7 +236,27 @@ void ControlPointSelection::align(Geom::Dim2 axis)
if (!bound) { return; }
- double new_coord = bound->middle();
+ double new_coord;
+ switch (AlignTargetNode(prefs->getInt("/dialogs/align/align-nodes-to", 2))){
+ case FIRST_NODE:
+ new_coord=(_points_list.front())->position()[d];
+ break;
+ case LAST_NODE:
+ new_coord=(_points_list.back())->position()[d];
+ break;
+ case MID_NODE:
+ new_coord=bound->middle();
+ break;
+ case MIN_NODE:
+ new_coord=bound->min();
+ break;
+ case MAX_NODE:
+ new_coord=bound->max();
+ break;
+ default:
+ return;
+ }
+
for (iterator i = _points.begin(); i != _points.end(); ++i) {
Geom::Point pos = (*i)->position();
pos[d] = new_coord;
diff --git a/src/ui/tool/control-point-selection.h b/src/ui/tool/control-point-selection.h
index 2d812c0a3..f122a468d 100644
--- a/src/ui/tool/control-point-selection.h
+++ b/src/ui/tool/control-point-selection.h
@@ -12,6 +12,7 @@
#ifndef SEEN_UI_TOOL_CONTROL_POINT_SELECTION_H
#define SEEN_UI_TOOL_CONTROL_POINT_SELECTION_H
+#include <list>
#include <memory>
#include <boost/optional.hpp>
#include <stddef.h>
@@ -140,6 +141,8 @@ private:
double _rotationRadius(Geom::Point const &);
set_type _points;
+ //the purpose of this list is to keep track of first and last selected
+ std::list<SelectableControlPoint *> _points_list;
set_type _all_points;
INK_UNORDERED_MAP<SelectableControlPoint *, Geom::Point> _original_positions;
INK_UNORDERED_MAP<SelectableControlPoint *, Geom::Affine> _last_trans;
diff --git a/src/ui/tool/multi-path-manipulator.cpp b/src/ui/tool/multi-path-manipulator.cpp
index 46c6246a1..9ec6f733f 100644
--- a/src/ui/tool/multi-path-manipulator.cpp
+++ b/src/ui/tool/multi-path-manipulator.cpp
@@ -683,13 +683,14 @@ bool MultiPathManipulator::event(Inkscape::UI::Tools::ToolBase *event_context, G
//if the trace is bspline ( mode 2)
if(mode==2){
// is this correct ?
- if(del_preserves_shape ^ held_control(event->key))
+ if(del_preserves_shape ^ held_control(event->key)){
deleteNodes(false);
- else
+ } else {
deleteNodes(true);
- }
- else
+ }
+ } else {
deleteNodes(del_preserves_shape ^ held_control(event->key));
+ }
// Delete any selected gradient nodes as well
event_context->deleteSelectedDrag(held_control(event->key));
diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp
index ca6f5abb1..d70147f80 100644
--- a/src/ui/tool/node.cpp
+++ b/src/ui/tool/node.cpp
@@ -60,10 +60,8 @@ Inkscape::ControlType nodeTypeToCtrlType(Inkscape::UI::NodeType type)
namespace Inkscape {
namespace UI {
-/*const double handleCubicGap = 0.01;*/
-const double noPower = 0.0;
-const double defaultStartPower = 0.3334;
-/*const double defaultEndPower = 0.6667;*/
+const double NO_POWER = 0.0;
+const double DEFAULT_START_POWER = 1.0/3.0;
ControlPoint::ColorSet Node::node_colors = {
{0xbfbfbf00, 0x000000ff}, // normal fill, stroke
@@ -142,6 +140,7 @@ void Handle::move(Geom::Point const &new_pos)
Node *node_away = _parent->nodeAwayFrom(this); // node in the opposite direction
Handle *towards = node_towards ? node_towards->handleAwayFrom(_parent) : NULL;
Handle *towards_second = node_towards ? node_towards->handleToward(_parent) : NULL;
+ double bspline_weight = 0.0;
if (Geom::are_near(new_pos, _parent->position())) {
// The handle becomes degenerate.
@@ -176,8 +175,9 @@ void Handle::move(Geom::Point const &new_pos)
//move the handler and its oposite the same proportion
if(_pm()._isBSpline()){
- setPosition(_pm()._bsplineHandleReposition(this,this));
- this->other()->setPosition(_pm()._bsplineHandleReposition(this->other(),this));
+ setPosition(_pm()._bsplineHandleReposition(this, false));
+ bspline_weight = _pm()._bsplineHandlePosition(this, false);
+ this->other()->setPosition(_pm()._bsplineHandleReposition(this->other(), bspline_weight));
}
return;
}
@@ -193,8 +193,9 @@ void Handle::move(Geom::Point const &new_pos)
//move the handler and its oposite the same proportion
if(_pm()._isBSpline()){
- setPosition(_pm()._bsplineHandleReposition(this,this));
- this->other()->setPosition(_pm()._bsplineHandleReposition(this->other(),this));
+ setPosition(_pm()._bsplineHandleReposition(this, false));
+ bspline_weight = _pm()._bsplineHandlePosition(this, false);
+ this->other()->setPosition(_pm()._bsplineHandleReposition(this->other(), bspline_weight));
}
return;
@@ -219,8 +220,9 @@ void Handle::move(Geom::Point const &new_pos)
// moves the handler and its oposite the same proportion
if(_pm()._isBSpline()){
- setPosition(_pm()._bsplineHandleReposition(this,this));
- this->other()->setPosition(_pm()._bsplineHandleReposition(this->other(),this));
+ setPosition(_pm()._bsplineHandleReposition(this, false));
+ bspline_weight = _pm()._bsplineHandlePosition(this, false);
+ this->other()->setPosition(_pm()._bsplineHandleReposition(this->other(), bspline_weight));
}
}
@@ -299,7 +301,7 @@ bool Handle::_eventHandler(Inkscape::UI::Tools::ToolBase *event_context, GdkEven
default: break;
}
break;
- // new double click event to set the handlers of a node to the default proportion, defaultStartPower%
+ // new double click event to set the handlers of a node to the default proportion, DEFAULT_START_POWER%
case GDK_2BUTTON_PRESS:
handle_2button_press();
break;
@@ -310,11 +312,11 @@ bool Handle::_eventHandler(Inkscape::UI::Tools::ToolBase *event_context, GdkEven
return ControlPoint::_eventHandler(event_context, event);
}
-//this function moves the handler and its oposite to the default proportion of defaultStartPower
+//this function moves the handler and its oposite to the default proportion of DEFAULT_START_POWER
void Handle::handle_2button_press(){
if(_pm()._isBSpline()){
- setPosition(_pm()._bsplineHandleReposition(this,defaultStartPower));
- this->other()->setPosition(_pm()._bsplineHandleReposition(this->other(),defaultStartPower));
+ setPosition(_pm()._bsplineHandleReposition(this, DEFAULT_START_POWER));
+ this->other()->setPosition(_pm()._bsplineHandleReposition(this->other(), DEFAULT_START_POWER));
_pm().update();
}
}
@@ -375,7 +377,7 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event)
if(_pm()._isBSpline()){
setPosition(new_pos);
int steps = _pm()._bsplineGetSteps();
- new_pos=_pm()._bsplineHandleReposition(this,ceilf(_pm()._bsplineHandlePosition(this,this)*steps)/steps);
+ new_pos=_pm()._bsplineHandleReposition(this,ceilf(_pm()._bsplineHandlePosition(this, false)*steps)/steps);
}
}
@@ -549,7 +551,7 @@ Glib::ustring Handle::_getTip(unsigned state) const
"<b>Auto node handle</b>: drag to convert to smooth node (%s)"), more);
}else{
return format_tip(C_("Path handle tip",
- "<b>BSpline node handle</b>: Shift to drag, double click to reset (%s). %g power"),more,_pm()._bsplineHandlePosition(h,NULL));
+ "<b>BSpline node handle</b>: Shift to drag, double click to reset (%s). %g power"),more,_pm()._bsplineHandlePosition(h));
}
}
}
@@ -627,22 +629,18 @@ void Node::move(Geom::Point const &new_pos)
Geom::Point delta = new_pos - position();
// save the previous nodes strength to apply it again once the node is moved
- double nodeWeight = noPower;
- double nextNodeWeight = noPower;
- double prevNodeWeight = noPower;
+ double nodeWeight = NO_POWER;
+ double nextNodeWeight = NO_POWER;
+ double prevNodeWeight = NO_POWER;
Node *n = this;
Node * nextNode = n->nodeToward(n->front());
Node * prevNode = n->nodeToward(n->back());
- nodeWeight = fmax(_pm()._bsplineHandlePosition(n->front()),_pm()._bsplineHandlePosition(n->back()));
+ nodeWeight = fmax(_pm()._bsplineHandlePosition(n->front(), false),_pm()._bsplineHandlePosition(n->back(), false));
if(prevNode){
- if(prevNode->isEndNode()){
- prevNodeWeight = _pm()._bsplineHandlePosition(prevNode->front(),prevNode->front());
- }
+ prevNodeWeight = _pm()._bsplineHandlePosition(prevNode->front());
}
if(nextNode){
- if(nextNode->isEndNode()){
- nextNodeWeight = _pm()._bsplineHandlePosition(nextNode->back(),nextNode->back());
- }
+ nextNodeWeight = _pm()._bsplineHandlePosition(nextNode->back());
}
setPosition(new_pos);
@@ -659,18 +657,10 @@ void Node::move(Geom::Point const &new_pos)
_front.setPosition(_pm()._bsplineHandleReposition(this->front(),nodeWeight));
_back.setPosition(_pm()._bsplineHandleReposition(this->back(),nodeWeight));
if(prevNode){
- if(prevNode->isEndNode()){
- prevNode->front()->setPosition(_pm()._bsplineHandleReposition(prevNode->front(),prevNodeWeight));
- }else{
- prevNode->front()->setPosition(_pm()._bsplineHandleReposition(prevNode->front(),prevNode->back()));
- }
+ prevNode->front()->setPosition(_pm()._bsplineHandleReposition(prevNode->front(), prevNodeWeight));
}
if(nextNode){
- if(nextNode->isEndNode()){
- nextNode->back()->setPosition(_pm()._bsplineHandleReposition(nextNode->back(),nextNodeWeight));
- }else{
- nextNode->back()->setPosition(_pm()._bsplineHandleReposition(nextNode->back(),nextNode->front()));
- }
+ nextNode->back()->setPosition(_pm()._bsplineHandleReposition(nextNode->back(), nextNodeWeight));
}
}
}
@@ -681,22 +671,18 @@ void Node::transform(Geom::Affine const &m)
Geom::Point old_pos = position();
// save the previous nodes strength to apply it again once the node is moved
- double nodeWeight = noPower;
- double nextNodeWeight = noPower;
- double prevNodeWeight = noPower;
+ double nodeWeight = NO_POWER;
+ double nextNodeWeight = NO_POWER;
+ double prevNodeWeight = NO_POWER;
Node *n = this;
Node * nextNode = n->nodeToward(n->front());
Node * prevNode = n->nodeToward(n->back());
nodeWeight = _pm()._bsplineHandlePosition(n->front());
if(prevNode){
- if(prevNode->isEndNode()){
- prevNodeWeight = _pm()._bsplineHandlePosition(prevNode->front(),prevNode->front());
- }
+ prevNodeWeight = _pm()._bsplineHandlePosition(prevNode->front());
}
if(nextNode){
- if(nextNode->isEndNode()){
- nextNodeWeight = _pm()._bsplineHandlePosition(nextNode->back(),nextNode->back());
- }
+ nextNodeWeight = _pm()._bsplineHandlePosition(nextNode->back());
}
setPosition(position() * m);
@@ -709,21 +695,13 @@ void Node::transform(Geom::Affine const &m)
// move the involved handlers, first the node ones, later the adjoining ones
if(_pm()._isBSpline()){
- _front.setPosition(_pm()._bsplineHandleReposition(this->front(),nodeWeight));
- _back.setPosition(_pm()._bsplineHandleReposition(this->back(),nodeWeight));
+ _front.setPosition(_pm()._bsplineHandleReposition(this->front(), nodeWeight));
+ _back.setPosition(_pm()._bsplineHandleReposition(this->back(), nodeWeight));
if(prevNode){
- if(prevNode->isEndNode()){
- prevNode->front()->setPosition(_pm()._bsplineHandleReposition(prevNode->front(),prevNodeWeight));
- }else{
- prevNode->front()->setPosition(_pm()._bsplineHandleReposition(prevNode->front(),prevNode->back()));
- }
+ prevNode->front()->setPosition(_pm()._bsplineHandleReposition(prevNode->front(), prevNodeWeight));
}
if(nextNode){
- if(nextNode->isEndNode()){
- nextNode->back()->setPosition(_pm()._bsplineHandleReposition(nextNode->back(),nextNodeWeight));
- }else{
- nextNode->back()->setPosition(_pm()._bsplineHandleReposition(nextNode->back(),nextNode->front()));
- }
+ nextNode->back()->setPosition(_pm()._bsplineHandleReposition(nextNode->back(), nextNodeWeight));
}
}
}
@@ -913,15 +891,15 @@ void Node::setType(NodeType type, bool update_handles)
break;
default: break;
}
- /* in node type changes, about bspline traces, we can mantain them with noPower power in border mode,
+ /* in node type changes, about bspline traces, we can mantain them with NO_POWER power in border mode,
or we give them the default power in curve mode */
if(_pm()._isBSpline()){
- double weight = noPower;
- if(_pm()._bsplineHandlePosition(this->front()) != noPower ){
- weight = defaultStartPower;
+ double weight = NO_POWER;
+ if(_pm()._bsplineHandlePosition(this->front()) != NO_POWER ){
+ weight = DEFAULT_START_POWER;
}
- _front.setPosition(_pm()._bsplineHandleReposition(this->front(),weight));
- _back.setPosition(_pm()._bsplineHandleReposition(this->back(),weight));
+ _front.setPosition(_pm()._bsplineHandleReposition(this->front(), weight));
+ _back.setPosition(_pm()._bsplineHandleReposition(this->back(), weight));
}
}
_type = type;
@@ -1435,7 +1413,6 @@ Glib::ustring Node::_getTip(unsigned state) const
{
bool isBSpline = _pm()._isBSpline();
Handle *h = const_cast<Handle *>(&_front);
- Handle *h2 = const_cast<Handle *>(&_back);
if (state_held_shift(state)) {
bool can_drag_out = (_next() && _front.isDegenerate()) || (_prev() && _back.isDegenerate());
if (can_drag_out) {
@@ -1464,7 +1441,7 @@ Glib::ustring Node::_getTip(unsigned state) const
// No modifiers: assemble tip from node type
char const *nodetype = node_type_to_localized_string(_type);
- double power = _pm()._bsplineHandlePosition(h,h2);
+ double power = _pm()._bsplineHandlePosition(h);
if (_selection.transformHandlesEnabled() && selected()) {
if (_selection.size() == 1 && !isBSpline) {
return format_tip(C_("Path node tip",
diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp
index 848b10373..f4790c317 100644
--- a/src/ui/tool/path-manipulator.cpp
+++ b/src/ui/tool/path-manipulator.cpp
@@ -56,9 +56,9 @@ enum PathChange {
};
} // anonymous namespace
-const double HANDLE_CUBIC_GAP = 0.01;
+const double HANDLE_CUBIC_GAP = 0.001;
const double NO_POWER = 0.0;
-const double defaultStartPower = 0.3334;
+const double DEFAULT_START_POWER = 1.0/3.0;
/**
@@ -695,10 +695,12 @@ unsigned PathManipulator::_deleteStretch(NodeList::iterator start, NodeList::ite
// if we are removing, we readjust the handlers
if(_isBSpline()){
if(start.prev()){
- start.prev()->front()->setPosition(_bsplineHandleReposition(start.prev()->front(),start.prev()->back()));
+ double bspline_weight = _bsplineHandlePosition(start.prev()->back(), false);
+ start.prev()->front()->setPosition(_bsplineHandleReposition(start.prev()->front(), bspline_weight));
}
if(end){
- end->back()->setPosition(_bsplineHandleReposition(end->back(),end->front()));
+ double bspline_weight = _bsplineHandlePosition(end->front(), false);
+ end->back()->setPosition(_bsplineHandleReposition(end->back(),bspline_weight));
}
}
@@ -1033,7 +1035,7 @@ NodeList::iterator PathManipulator::subdivideSegment(NodeList::iterator first, d
line_inside_nodes->moveto(n->position());
line_inside_nodes->lineto(second->position());
sbasis_inside_nodes = line_inside_nodes->first_segment()->toSBasis();
- Geom::Point next = sbasis_inside_nodes.valueAt(defaultStartPower);
+ Geom::Point next = sbasis_inside_nodes.valueAt(DEFAULT_START_POWER);
next = Geom::Point(next[Geom::X] + HANDLE_CUBIC_GAP,next[Geom::Y] + HANDLE_CUBIC_GAP);
line_inside_nodes->reset();
n->front()->setPosition(next);
@@ -1044,7 +1046,7 @@ NodeList::iterator PathManipulator::subdivideSegment(NodeList::iterator first, d
line_inside_nodes->moveto(n->position());
line_inside_nodes->lineto(first->position());
sbasis_inside_nodes = line_inside_nodes->first_segment()->toSBasis();
- Geom::Point previous = sbasis_inside_nodes.valueAt(defaultStartPower);
+ Geom::Point previous = sbasis_inside_nodes.valueAt(DEFAULT_START_POWER);
previous = Geom::Point(previous[Geom::X] + HANDLE_CUBIC_GAP,previous[Geom::Y] + HANDLE_CUBIC_GAP);
n->back()->setPosition(previous);
}else{
@@ -1277,13 +1279,10 @@ bool PathManipulator::_isBSpline() const {
}
// returns the corresponding strength to the position of the handlers
-double PathManipulator::_bsplineHandlePosition(Handle *h, Handle *h2)
+double PathManipulator::_bsplineHandlePosition(Handle *h, bool check_other)
{
using Geom::X;
using Geom::Y;
- if(h2){
- h = h2;
- }
double pos = NO_POWER;
Node *n = h->parent();
Node * next_node = NULL;
@@ -1293,19 +1292,19 @@ double PathManipulator::_bsplineHandlePosition(Handle *h, Handle *h2)
line_inside_nodes->moveto(n->position());
line_inside_nodes->lineto(next_node->position());
if(!are_near(h->position(), n->position())){
- pos = Geom::nearest_time(Geom::Point(h->position()[X] - HANDLE_CUBIC_GAP, h->position()[Y] - HANDLE_CUBIC_GAP), *line_inside_nodes->first_segment());
+ pos = Geom::nearest_time(Geom::Point(h->position()[X] - HANDLE_CUBIC_GAP, h->position()[Y] + HANDLE_CUBIC_GAP), *line_inside_nodes->first_segment());
}
}
- if (pos == NO_POWER && !h2){
- return _bsplineHandlePosition(h, h->other());
+ if (pos == NO_POWER && check_other){
+ return _bsplineHandlePosition(h->other(), false);
}
return pos;
}
// give the location for the handler in the corresponding position
-Geom::Point PathManipulator::_bsplineHandleReposition(Handle *h, Handle *h2)
+Geom::Point PathManipulator::_bsplineHandleReposition(Handle *h, bool check_other)
{
- double pos = this->_bsplineHandlePosition(h, h2);
+ double pos = this->_bsplineHandlePosition(h, check_other);
return _bsplineHandleReposition(h,pos);
}
diff --git a/src/ui/tool/path-manipulator.h b/src/ui/tool/path-manipulator.h
index 4c6f74ba4..283cb610a 100644
--- a/src/ui/tool/path-manipulator.h
+++ b/src/ui/tool/path-manipulator.h
@@ -111,8 +111,8 @@ private:
void _recalculateIsBSpline();
bool _isBSpline() const;
- double _bsplineHandlePosition(Handle *h, Handle *h2 = NULL);
- Geom::Point _bsplineHandleReposition(Handle *h, Handle *h2 = NULL);
+ double _bsplineHandlePosition(Handle *h, bool check_other = true);
+ Geom::Point _bsplineHandleReposition(Handle *h, bool check_other = true);
Geom::Point _bsplineHandleReposition(Handle *h, double pos);
void _createGeometryFromControlPoints(bool alert_LPE = false);
unsigned _deleteStretch(NodeList::iterator first, NodeList::iterator last, bool keep_shape);
diff --git a/src/ui/tool/selector.cpp b/src/ui/tool/selector.cpp
index 051cb41ae..9acf7de88 100644
--- a/src/ui/tool/selector.cpp
+++ b/src/ui/tool/selector.cpp
@@ -39,6 +39,7 @@ public:
setVisible(false);
_rubber = static_cast<CtrlRect*>(sp_canvas_item_new(_desktop->getControls(),
SP_TYPE_CTRLRECT, NULL));
+ _rubber->setShadow(1, 0xffffffff);
sp_canvas_item_hide(_rubber);
}
diff --git a/src/ui/tool/transform-handle-set.cpp b/src/ui/tool/transform-handle-set.cpp
index da2a54989..748b9d4cc 100644
--- a/src/ui/tool/transform-handle-set.cpp
+++ b/src/ui/tool/transform-handle-set.cpp
@@ -15,9 +15,11 @@
#include <glib/gi18n.h>
#include <2geom/transforms.h>
#include "desktop.h"
+#include "sp-namedview.h"
#include "display/sodipodi-ctrlrect.h"
#include "preferences.h"
+#include "pure-transform.h"
#include "snap.h"
#include "snap-candidate.h"
#include "sp-namedview.h"
@@ -93,6 +95,7 @@ TransformHandle::TransformHandle(TransformHandleSet &th, SPAnchorType anchor, Gl
setVisible(false);
}
+// TODO: This code is duplicated in seltrans.cpp; fix this!
void TransformHandle::getNextClosestPoint(bool reverse)
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -113,6 +116,11 @@ void TransformHandle::getNextClosestPoint(bool reverse)
_snap_points.clear();
_snap_points.push_back(*_all_snap_sources_iter);
+ // Show the updated snap source now; otherwise it won't be shown until the selection is being moved again
+ SnapManager &m = _desktop->namedview->snap_manager;
+ m.setup(_desktop);
+ m.displaySnapsource(*_all_snap_sources_iter);
+ m.unSetup();
}
}
}
@@ -247,7 +255,7 @@ protected:
if (Geom::are_near(vold[Geom::X], 0) || Geom::are_near(vold[Geom::Y], 0))
return Geom::identity();
- double scale[2] = { vnew[Geom::X] / vold[Geom::X], vnew[Geom::Y] / vold[Geom::Y] };
+ Geom::Scale scale = Geom::Scale(vnew[Geom::X] / vold[Geom::X], vnew[Geom::Y] / vold[Geom::Y]);
if (held_alt(*event)) {
for (unsigned i = 0; i < 2; ++i) {
@@ -261,20 +269,21 @@ protected:
SnapManager &m = _th._desktop->namedview->snap_manager;
m.setupIgnoreSelection(_th._desktop, true, &_unselected_points);
- Inkscape::SnappedPoint sp;
+ Inkscape::PureScale *ptr;
if (held_control(*event)) {
scale[0] = scale[1] = std::min(scale[0], scale[1]);
- sp = m.constrainedSnapScale(_snap_points, _origin, Geom::Scale(scale[0], scale[1]), scc);
+ ptr = new Inkscape::PureScaleConstrained(Geom::Scale(scale[0], scale[1]), scc);
} else {
- sp = m.freeSnapScale(_snap_points, _origin, Geom::Scale(scale[0], scale[1]), scc);
+ ptr = new Inkscape::PureScale(Geom::Scale(scale[0], scale[1]), scc, false);
}
+ m.snapTransformed(_snap_points, _origin, (*ptr));
m.unSetup();
- if (sp.getSnapped()) {
- Geom::Point result = sp.getTransformation();
- scale[0] = result[0];
- scale[1] = result[1];
+ if (ptr->best_snapped_point.getSnapped()) {
+ scale = ptr->getScaleSnapped();
}
+
+ delete ptr;
}
_last_scale_x = scale[0];
@@ -349,11 +358,12 @@ protected:
m.setupIgnoreSelection(_th._desktop, true, &_unselected_points);
bool uniform = held_control(*event);
- Inkscape::SnappedPoint sp = m.constrainedSnapStretch(_snap_points, _origin, vs[d1], scc, d1, uniform);
+ Inkscape::PureStretchConstrained psc = Inkscape::PureStretchConstrained(vs[d1], scc, d1, uniform);
+ m.snapTransformed(_snap_points, _origin, psc);
m.unSetup();
- if (sp.getSnapped()) {
- Geom::Point result = sp.getTransformation();
+ if (psc.best_snapped_point.getSnapped()) {
+ Geom::Point result = psc.getStretchSnapped().vector(); //best_snapped_point.getTransformation();
vs[d1] = result[d1];
vs[d2] = result[d2];
} else {
@@ -414,11 +424,12 @@ protected:
} else {
SnapManager &m = _th._desktop->namedview->snap_manager;
m.setupIgnoreSelection(_th._desktop, true, &_unselected_points);
- Inkscape::SnappedPoint sp = m.constrainedSnapRotate(_snap_points, _origin, angle, rotc);
+ Inkscape::PureRotateConstrained prc = Inkscape::PureRotateConstrained(angle, rotc);
+ m.snapTransformed(_snap_points, _origin, prc);
m.unSetup();
- if (sp.getSnapped()) {
- angle = sp.getTransformation()[0];
+ if (prc.best_snapped_point.getSnapped()) {
+ angle = prc.getAngleSnapped(); //best_snapped_point.getTransformation()[0];
}
}
@@ -528,13 +539,12 @@ protected:
SnapManager &m = _th._desktop->namedview->snap_manager;
m.setupIgnoreSelection(_th._desktop, true, &_unselected_points);
- Geom::Point cvec; cvec[d2] = 1.0;
- Inkscape::Snapper::SnapConstraint const constraint(cvec);
- Inkscape::SnappedPoint sp = m.constrainedSnapSkew(_snap_points, _origin, constraint, Geom::Point(skew[d1], scale[d1]), scc, d2);
+ Inkscape::PureSkewConstrained psc = Inkscape::PureSkewConstrained(skew[d1], scale[d1], scc, d2);
+ m.snapTransformed(_snap_points, _origin, psc);
m.unSetup();
- if (sp.getSnapped()) {
- skew[d1] = sp.getTransformation()[0];
+ if (psc.best_snapped_point.getSnapped()) {
+ skew[d1] = psc.getSkewSnapped(); //best_snapped_point.getTransformation()[0];
}
}
diff --git a/src/ui/tools-switch.cpp b/src/ui/tools-switch.cpp
index 11313f550..ea0431b0a 100644
--- a/src/ui/tools-switch.cpp
+++ b/src/ui/tools-switch.cpp
@@ -42,7 +42,11 @@
#include "ui/tools/connector-tool.h"
#include "ui/tools/dropper-tool.h"
#include "ui/tools/eraser-tool.h"
+
+#if HAVE_POTRACE
#include "ui/tools/flood-tool.h"
+#endif
+
#include "ui/tools/gradient-tool.h"
#include "ui/tools/lpe-tool.h"
#include "ui/tools/measure-tool.h"
@@ -83,7 +87,9 @@ static char const *const tool_names[] = {
"/tools/measure",
"/tools/dropper",
"/tools/connector",
+#if HAVE_POTRACE
"/tools/paintbucket",
+#endif
"/tools/eraser",
"/tools/lpetool",
NULL
@@ -111,7 +117,9 @@ static char const *const tool_msg[] = {
N_("<b>Drag</b> to measure the dimensions of objects."),
N_("<b>Click</b> to set fill, <b>Shift+click</b> to set stroke; <b>drag</b> to average color in area; with <b>Alt</b> to pick inverse color; <b>Ctrl+C</b> to copy the color under mouse to clipboard"),
N_("<b>Click and drag</b> between shapes to create a connector."),
+#if HAVE_POTRACE
N_("<b>Click</b> to paint a bounded area, <b>Shift+click</b> to union the new fill with the current selection, <b>Ctrl+click</b> to change the clicked object's fill and stroke to the current setting."),
+#endif
N_("<b>Drag</b> to erase."),
N_("Choose a subtool from the toolbar"),
};
diff --git a/src/ui/tools-switch.h b/src/ui/tools-switch.h
index 280837e87..d396597ca 100644
--- a/src/ui/tools-switch.h
+++ b/src/ui/tools-switch.h
@@ -12,6 +12,10 @@
#ifndef SEEN_TOOLS_SWITCH_H
#define SEEN_TOOLS_SWITCH_H
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
class SPDesktop;
class SPItem;
namespace Geom {
@@ -40,7 +44,11 @@ enum {
TOOLS_MEASURE,
TOOLS_DROPPER,
TOOLS_CONNECTOR,
+
+#if HAVE_POTRACE
TOOLS_PAINTBUCKET,
+#endif
+
TOOLS_ERASER,
TOOLS_LPETOOL
};
diff --git a/src/ui/tools/Makefile_insert b/src/ui/tools/Makefile_insert
index cd09a3230..686dfedd8 100644
--- a/src/ui/tools/Makefile_insert
+++ b/src/ui/tools/Makefile_insert
@@ -8,7 +8,6 @@ ink_common_sources += \
ui/tools/dropper-tool.cpp ui/tools/dropper-tool.h \
ui/tools/dynamic-base.cpp ui/tools/dynamic-base.h \
ui/tools/eraser-tool.cpp ui/tools/eraser-tool.h \
- ui/tools/flood-tool.cpp ui/tools/flood-tool.h \
ui/tools/freehand-base.cpp ui/tools/freehand-base.h \
ui/tools/gradient-tool.cpp ui/tools/gradient-tool.h \
ui/tools/lpe-tool.cpp ui/tools/lpe-tool.h \
@@ -25,4 +24,11 @@ ink_common_sources += \
ui/tools/text-tool.cpp ui/tools/text-tool.h \
ui/tools/tool-base.cpp ui/tools/tool-base.h \
ui/tools/tweak-tool.cpp ui/tools/tweak-tool.h \
- ui/tools/zoom-tool.cpp ui/tools/zoom-tool.h \ No newline at end of file
+ ui/tools/zoom-tool.cpp ui/tools/zoom-tool.h
+
+if HAVE_POTRACE
+
+ink_common_sources += \
+ ui/tools/flood-tool.cpp ui/tools/flood-tool.h
+
+endif
diff --git a/src/ui/tools/connector-tool.cpp b/src/ui/tools/connector-tool.cpp
index 0a36877ff..b84d16686 100644
--- a/src/ui/tools/connector-tool.cpp
+++ b/src/ui/tools/connector-tool.cpp
@@ -1307,7 +1307,7 @@ void cc_selection_set_avoid(bool const set_avoid)
int changes = 0;
std::vector<SPItem*> l = selection->itemList();
- for(std::vector<SPItem*>::const_iterator i=l.begin();i!=l.end();i++) {
+ for(std::vector<SPItem*>::const_iterator i=l.begin();i!=l.end(); ++i) {
SPItem *item = *i;
char const *value = (set_avoid) ? "true" : NULL;
diff --git a/src/ui/tools/eraser-tool.cpp b/src/ui/tools/eraser-tool.cpp
index e416fd7ef..6b32b5901 100644
--- a/src/ui/tools/eraser-tool.cpp
+++ b/src/ui/tools/eraser-tool.cpp
@@ -64,8 +64,11 @@
#include "livarot/Shape.h"
#include "document-undo.h"
#include "verbs.h"
+#include "style.h"
+#include "style-enums.h"
#include <2geom/math-utils.h>
#include <2geom/pathvector.h>
+#include "path-chemistry.h"
#include "display/curve.h"
#include "ui/tools/eraser-tool.h"
@@ -96,6 +99,7 @@ const std::string EraserTool::prefsPath = "/tools/eraser";
EraserTool::EraserTool()
: DynamicBase(cursor_eraser_xpm, 4, 4)
+ , nowidth(false)
{
}
@@ -145,6 +149,7 @@ static ProfileFloatElement f_profile[PROFILE_FLOAT_SIZE] = {
sp_event_context_read(this, "cap_rounding");
this->is_drawing = false;
+ //TODO not sure why get 0.01 if slider width == 0, maybe a double/int problem
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
if (prefs->getBool("/tools/eraser/selcue", 0) != 0) {
@@ -339,7 +344,10 @@ void EraserTool::brush() {
this->point1[this->npoints] = brush + del_left;
this->point2[this->npoints] = brush - del_right;
-
+
+ if (this->nowidth) {
+ this->point1[this->npoints] = Geom::middle_point(this->point1[this->npoints],this->point2[this->npoints]);
+ }
this->del = 0.5*(del_left + del_right);
this->npoints++;
@@ -371,7 +379,8 @@ void EraserTool::cancel() {
bool EraserTool::root_handler(GdkEvent* event) {
gint ret = FALSE;
-
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ gint eraserMode = prefs->getBool("/tools/eraser/mode") ? 1 : 0;
switch (event->type) {
case GDK_BUTTON_PRESS:
if (event->button.button == 1 && !this->space_panning) {
@@ -391,10 +400,10 @@ bool EraserTool::root_handler(GdkEvent* event) {
if (this->repr) {
this->repr = NULL;
}
-
- Inkscape::Rubberband::get(desktop)->start(desktop, button_dt);
- Inkscape::Rubberband::get(desktop)->setMode(RUBBERBAND_MODE_TOUCHPATH);
-
+ if ( ! eraserMode ) {
+ Inkscape::Rubberband::get(desktop)->start(desktop, button_dt);
+ Inkscape::Rubberband::get(desktop)->setMode(RUBBERBAND_MODE_TOUCHPATH);
+ }
/* initialize first point */
this->npoints = 0;
@@ -439,8 +448,10 @@ bool EraserTool::root_handler(GdkEvent* event) {
ret = TRUE;
}
-
- Inkscape::Rubberband::get(desktop)->move(motion_dt);
+ if ( !eraserMode ) {
+ this->accumulated->reset();
+ Inkscape::Rubberband::get(desktop)->move(motion_dt);
+ }
}
break;
@@ -480,7 +491,7 @@ bool EraserTool::root_handler(GdkEvent* event) {
ret = TRUE;
}
- if (Inkscape::Rubberband::get(desktop)->is_started()) {
+ if (!eraserMode && Inkscape::Rubberband::get(desktop)->is_started()) {
Inkscape::Rubberband::get(desktop)->stop();
}
@@ -489,33 +500,32 @@ bool EraserTool::root_handler(GdkEvent* event) {
case GDK_KEY_PRESS:
switch (get_group0_keyval (&event->key)) {
- case GDK_KEY_Up:
- case GDK_KEY_KP_Up:
- if (!MOD__CTRL_ONLY(event)) {
- this->angle += 5.0;
-
- if (this->angle > 90.0) {
- this->angle = 90.0;
- }
-
- sp_erc_update_toolbox (desktop, "eraser-angle", this->angle);
- ret = TRUE;
- }
- break;
-
- case GDK_KEY_Down:
- case GDK_KEY_KP_Down:
- if (!MOD__CTRL_ONLY(event)) {
- this->angle -= 5.0;
-
- if (this->angle < -90.0) {
- this->angle = -90.0;
- }
-
- sp_erc_update_toolbox (desktop, "eraser-angle", this->angle);
- ret = TRUE;
- }
- break;
+// case GDK_KEY_Up:
+// case GDK_KEY_KP_Up:
+// if (!MOD__CTRL_ONLY(event)) {
+// this->angle += 5.0;
+
+// if (this->angle > 90.0) {
+// this->angle = 90.0;
+// }
+// sp_erc_update_toolbox (desktop, "eraser-angle", this->angle);
+// ret = TRUE;
+// }
+// break;
+
+// case GDK_KEY_Down:
+// case GDK_KEY_KP_Down:
+// if (!MOD__CTRL_ONLY(event)) {
+// this->angle -= 5.0;
+
+// if (this->angle < -90.0) {
+// this->angle = -90.0;
+// }
+
+// sp_erc_update_toolbox (desktop, "eraser-angle", this->angle);
+// ret = TRUE;
+// }
+// break;
case GDK_KEY_Right:
case GDK_KEY_KP_Right:
@@ -568,8 +578,9 @@ bool EraserTool::root_handler(GdkEvent* event) {
break;
case GDK_KEY_Escape:
- Inkscape::Rubberband::get(desktop)->stop();
-
+ if ( !eraserMode ) {
+ Inkscape::Rubberband::get(desktop)->stop();
+ }
if (this->is_drawing) {
// if drawing, cancel, otherwise pass it up for deselecting
this->cancel();
@@ -640,15 +651,12 @@ void EraserTool::set_to_accumulated() {
sp_desktop_apply_style_tool (desktop, repr, "/tools/eraser", false);
this->repr = repr;
-
- SPItem *item=SP_ITEM(desktop->currentLayer()->appendChildRepr(this->repr));
- Inkscape::GC::release(this->repr);
-
- item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
- item->updateRepr();
}
-
+ SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(this->repr));
+ Inkscape::GC::release(this->repr);
+ item->updateRepr();
Geom::PathVector pathv = this->accumulated->get_pathvector() * desktop->dt2doc();
+ pathv *= item->i2doc_affine().inverse();
gchar *str = sp_svg_write_path(pathv);
g_assert( str != NULL );
this->repr->setAttribute("d", str);
@@ -658,50 +666,87 @@ void EraserTool::set_to_accumulated() {
bool wasSelection = false;
Inkscape::Selection *selection = desktop->getSelection();
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
-
gint eraserMode = prefs->getBool("/tools/eraser/mode") ? 1 : 0;
Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
SPItem* acid = SP_ITEM(desktop->doc()->getObjectByRepr(this->repr));
- Geom::OptRect eraserBbox = acid->visualBounds();
- Geom::Rect bounds = (*eraserBbox) * desktop->doc2dt();
+ Geom::OptRect eraserBbox = acid->desktopVisualBounds();
std::vector<SPItem*> remainingItems;
std::vector<SPItem*> toWorkOn;
if (selection->isEmpty()) {
if ( eraserMode ) {
- toWorkOn = desktop->getDocument()->getItemsPartiallyInBox(desktop->dkey, bounds);
+ toWorkOn = desktop->getDocument()->getItemsPartiallyInBox(desktop->dkey, *eraserBbox);
} else {
Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop);
toWorkOn = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints());
}
toWorkOn.erase(std::remove(toWorkOn.begin(), toWorkOn.end(), acid), toWorkOn.end());
} else {
- toWorkOn= selection->itemList();
+ if ( !eraserMode ) {
+ Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop);
+ std::vector<SPItem*> touched;
+ touched = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints());
+ for (std::vector<SPItem*>::const_iterator i = touched.begin();i!=touched.end();++i) {
+ if(selection->includes(*i)){
+ toWorkOn.push_back((*i));
+ }
+ }
+ } else {
+ toWorkOn = selection->itemList();
+ }
wasSelection = true;
}
if ( !toWorkOn.empty() ) {
if ( eraserMode ) {
- for (std::vector<SPItem*>::const_iterator i = toWorkOn.begin(); i != toWorkOn.end(); i++){
- SPItem *item = *i;
-
- if ( eraserMode ) {
- Geom::OptRect bbox = item->visualBounds();
-
+ for (std::vector<SPItem*>::const_iterator i = toWorkOn.begin(); i != toWorkOn.end(); ++i){
+ SPItem *item = *i;
+ SPUse *use = dynamic_cast<SPUse *>(item);
+ if (SP_IS_PATH(item) && SP_PATH(item)->nodesInPath () == 2){
+ sp_object_ref( *i, 0 );
+ SPItem *item = *i;
+ item->deleteObject(true);
+ sp_object_unref(item);
+ workDone = true;
+ workDone = true;
+ } else if (SP_IS_GROUP(item) || use ) {
+ /*Do nothing*/
+ } else {
+ Geom::OptRect bbox = item->desktopVisualBounds();
if (bbox && bbox->intersects(*eraserBbox)) {
Inkscape::XML::Node* dup = this->repr->duplicate(xml_doc);
this->repr->parent()->appendChild(dup);
Inkscape::GC::release(dup); // parent takes over
-
- selection->set(item);
- selection->add(dup);
- sp_selected_path_diff_skip_undo(selection, desktop);
+ selection->set(dup);
+ if (!this->nowidth) {
+ sp_selected_path_union_skip_undo(selection, desktop);
+ }
+ selection->add(item);
+ if(item->style->fill_rule.value == SP_WIND_RULE_EVENODD){
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property(css, "fill-rule", "evenodd");
+ sp_desktop_set_style(desktop, css);
+ sp_repr_css_attr_unref(css);
+ css = 0;
+ }
+ if (this->nowidth) {
+ sp_selected_path_cut_skip_undo(selection, desktop);
+ } else {
+ sp_selected_path_diff_skip_undo(selection, desktop);
+ }
workDone = true; // TODO set this only if something was cut.
-
+ bool break_apart = prefs->getBool("/tools/eraser/break_apart", false);
+ if(!break_apart){
+ sp_selected_path_combine(desktop, true);
+ } else {
+ if(!this->nowidth){
+ sp_selected_path_break_apart(desktop, true);
+ }
+ }
if ( !selection->isEmpty() ) {
// If the item was not completely erased, track the new remainder.
- std::vector<SPItem*> nowSel(selection->itemList());
- for (std::vector<SPItem*>::const_iterator i2 = nowSel.begin();i2!=nowSel.end();i2++) {
+ std::vector<SPItem*> nowSel(selection->itemList());
+ for (std::vector<SPItem*>::const_iterator i2 = nowSel.begin();i2!=nowSel.end();++i2) {
remainingItems.push_back(*i2);
}
}
@@ -711,11 +756,11 @@ void EraserTool::set_to_accumulated() {
}
}
} else {
- for (std::vector<SPItem*> ::const_iterator i = toWorkOn.begin();i!=toWorkOn.end();i++) {
+ for (std::vector<SPItem*> ::const_iterator i = toWorkOn.begin();i!=toWorkOn.end();++i) {
sp_object_ref( *i, 0 );
}
- for (std::vector<SPItem*>::const_iterator i = toWorkOn.begin();i!=toWorkOn.end();i++) {
+ for (std::vector<SPItem*>::const_iterator i = toWorkOn.begin();i!=toWorkOn.end();++i) {
SPItem *item = *i;
item->deleteObject(true);
sp_object_unref(item);
@@ -736,7 +781,6 @@ void EraserTool::set_to_accumulated() {
}
}
}
-
// Remove the eraser stroke itself:
sp_repr_unparent( this->repr );
this->repr = 0;
@@ -811,24 +855,25 @@ void EraserTool::accumulate() {
g_assert( rev_cal2_lastseg );
this->accumulated->append(this->cal1, FALSE);
-
- add_cap(this->accumulated,
- dc_cal1_lastseg->finalPoint() - dc_cal1_lastseg->unitTangentAt(1),
- dc_cal1_lastseg->finalPoint(),
- rev_cal2_firstseg->initialPoint(),
- rev_cal2_firstseg->initialPoint() + rev_cal2_firstseg->unitTangentAt(0),
- this->cap_rounding);
-
- this->accumulated->append(rev_cal2, TRUE);
-
- add_cap(this->accumulated,
- rev_cal2_lastseg->finalPoint() - rev_cal2_lastseg->unitTangentAt(1),
- rev_cal2_lastseg->finalPoint(),
- dc_cal1_firstseg->initialPoint(),
- dc_cal1_firstseg->initialPoint() + dc_cal1_firstseg->unitTangentAt(0),
- this->cap_rounding);
-
- this->accumulated->closepath();
+ if(!this->nowidth) {
+ add_cap(this->accumulated,
+ dc_cal1_lastseg->finalPoint() - dc_cal1_lastseg->unitTangentAt(1),
+ dc_cal1_lastseg->finalPoint(),
+ rev_cal2_firstseg->initialPoint(),
+ rev_cal2_firstseg->initialPoint() + rev_cal2_firstseg->unitTangentAt(0),
+ this->cap_rounding);
+
+ this->accumulated->append(rev_cal2, TRUE);
+
+ add_cap(this->accumulated,
+ rev_cal2_lastseg->finalPoint() - rev_cal2_lastseg->unitTangentAt(1),
+ rev_cal2_lastseg->finalPoint(),
+ dc_cal1_firstseg->initialPoint(),
+ dc_cal1_firstseg->initialPoint() + dc_cal1_firstseg->unitTangentAt(0),
+ this->cap_rounding);
+
+ this->accumulated->closepath();
+ }
rev_cal2->unref();
@@ -844,6 +889,8 @@ static double square(double const x)
void EraserTool::fit_and_split(bool release) {
double const tolerance_sq = square( desktop->w2d().descrim() * TOLERANCE_ERASER );
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ this->nowidth = prefs->getDouble( "/tools/eraser/width", 1) == 0;
#ifdef ERASER_VERBOSE
g_print("[F&S:R=%c]", release?'T':'F');
@@ -940,7 +987,6 @@ void EraserTool::fit_and_split(bool release) {
g_print("[%d]Yup\n", this->npoints);
#endif
if (!release) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
gint eraserMode = prefs->getBool("/tools/eraser/mode") ? 1 : 0;
g_assert(!this->currentcurve->is_empty());
diff --git a/src/ui/tools/eraser-tool.h b/src/ui/tools/eraser-tool.h
index 110f57ba3..50ce6b6e3 100644
--- a/src/ui/tools/eraser-tool.h
+++ b/src/ui/tools/eraser-tool.h
@@ -58,6 +58,7 @@ private:
void accumulate();
void fit_and_split(bool release);
void draw_temporary_box();
+ bool nowidth;
};
}
diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp
index e8cbfcdbf..613857626 100644
--- a/src/ui/tools/freehand-base.cpp
+++ b/src/ui/tools/freehand-base.cpp
@@ -20,7 +20,9 @@
# include "config.h"
#endif
+#include "live_effects/lpe-bendpath.h"
#include "live_effects/lpe-patternalongpath.h"
+#include "live_effects/lpe-simplify.h"
#include "display/canvas-bpath.h"
#include "xml/repr.h"
#include "svg/svg.h"
@@ -40,10 +42,12 @@
#include "selection-chemistry.h"
#include "snap.h"
#include "sp-path.h"
+#include "sp-use.h"
#include "sp-namedview.h"
#include "live_effects/lpe-powerstroke.h"
#include "style.h"
#include "ui/control-manager.h"
+#include "util/units.h"
// clipboard support
#include "ui/clipboard.h"
#include "ui/tools/freehand-base.h"
@@ -212,7 +216,7 @@ static Glib::ustring const tool_name(FreehandBase *dc)
: "/tools/freehand/pencil" );
}
-static void spdc_paste_curve_as_freehand_shape(const SPCurve *c, FreehandBase *dc, SPItem *item)
+static void spdc_paste_curve_as_freehand_shape(Geom::PathVector const &newpath, FreehandBase *dc, SPItem *item)
{
using namespace Inkscape::LivePathEffect;
@@ -220,8 +224,7 @@ static void spdc_paste_curve_as_freehand_shape(const SPCurve *c, FreehandBase *d
Effect::createAndApply(PATTERN_ALONG_PATH, dc->desktop->doc(), item);
Effect* lpe = SP_LPE_ITEM(item)->getCurrentLPE();
- gchar *svgd = sp_svg_write_path(c->get_pathvector());
- static_cast<LPEPatternAlongPath*>(lpe)->pattern.paste_param_path(svgd);
+ static_cast<LPEPatternAlongPath*>(lpe)->pattern.set_new_value(newpath,true);
}
static void spdc_apply_powerstroke_shape(const std::vector<Geom::Point> & points, FreehandBase *dc, SPItem *item)
@@ -266,37 +269,87 @@ static void spdc_apply_powerstroke_shape(const std::vector<Geom::Point> & points
lpe->getRepr()->setAttribute("offset_points", s.str().c_str());
}
+static void spdc_apply_bend_shape(gchar const *svgd, FreehandBase *dc, SPItem *item)
+{
+ using namespace Inkscape::LivePathEffect;
+ SPUse *use = dynamic_cast<SPUse *>(item);
+ if ( use ) {
+ return;
+ }
+ if(!SP_IS_LPE_ITEM(item) || !SP_LPE_ITEM(item)->hasPathEffectOfType(BEND_PATH)){
+ Effect::createAndApply(BEND_PATH, dc->desktop->doc(), item);
+ }
+ Effect* lpe = SP_LPE_ITEM(item)->getCurrentLPE();
+
+ // write bend parameters:
+ lpe->getRepr()->setAttribute("prop_scale", "1");
+ lpe->getRepr()->setAttribute("scale_y_rel", "false");
+ lpe->getRepr()->setAttribute("vertical", "false");
+ static_cast<LPEBendPath*>(lpe)->bend_path.paste_param_path(svgd);
+}
+
+static void spdc_apply_simplify(std::string threshold, FreehandBase *dc, SPItem *item)
+{
+ using namespace Inkscape::LivePathEffect;
+
+ Effect::createAndApply(SIMPLIFY, dc->desktop->doc(), item);
+ Effect* lpe = SP_LPE_ITEM(item)->getCurrentLPE();
+ // write simplify parameters:
+ lpe->getRepr()->setAttribute("steps", "1");
+ lpe->getRepr()->setAttribute("threshold", threshold);
+ lpe->getRepr()->setAttribute("smooth_angles", "360");
+ lpe->getRepr()->setAttribute("helper_size", "0");
+ lpe->getRepr()->setAttribute("simplifyindividualpaths", "false");
+ lpe->getRepr()->setAttribute("simplifyJustCoalesce", "false");
+}
+
+enum shapeType { NONE, TRIANGLE_IN, TRIANGLE_OUT, ELLIPSE, CLIPBOARD, BEND_CLIPBOARD, LAST_APPLIED };
+static shapeType previous_shape_type = NONE;
+
static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item, SPCurve *curve)
{
using namespace Inkscape::LivePathEffect;
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
if (item && SP_IS_LPE_ITEM(item)) {
+ bool simplify = prefs->getInt(tool_name(dc) + "/simplify", 0);
+ if(simplify){
+ double tol = prefs->getDoubleLimited("/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0);
+ tol = tol/(100.0*(102.0-tol));
+ std::ostringstream ss;
+ ss << tol;
+ spdc_apply_simplify(ss.str(), dc, item);
+ sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
+ }
if (prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 1) {
Effect::createAndApply(SPIRO, dc->desktop->doc(), item);
}
- //add the bspline node in the waiting effects
+
if (prefs->getInt(tool_name(dc) + "/freehand-mode", 0) == 2) {
Effect::createAndApply(BSPLINE, dc->desktop->doc(), item);
}
+ SPShape *sp_shape = dynamic_cast<SPShape *>(item);
+ if (sp_shape) {
+ curve = sp_shape->getCurve();
+ }
//Store the clipboard path to apply in the future without the use of clipboard
static Geom::PathVector previous_shape_pathv;
- enum shapeType { NONE, TRIANGLE_IN, TRIANGLE_OUT, ELLIPSE, CLIPBOARD, LAST_APPLIED };
- static shapeType previous_shape_type = NONE;
-
shapeType shape = (shapeType)prefs->getInt(tool_name(dc) + "/shape", 0);
bool shape_applied = false;
SPCSSAttr *css_item = sp_css_attr_from_object(item, SP_STYLE_FLAG_ALWAYS);
const char *cstroke = sp_repr_css_property(css_item, "stroke", "none");
+ static SPItem *bend_item;
#define SHAPE_LENGTH 10
#define SHAPE_HEIGHT 10
+
if(shape == LAST_APPLIED){
+
shape = previous_shape_type;
- if(shape == CLIPBOARD){
+ if(shape == CLIPBOARD || shape == BEND_CLIPBOARD){
shape = LAST_APPLIED;
}
}
@@ -337,7 +390,7 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
c->curveto(SHAPE_LENGTH, (1 + C1) * SHAPE_HEIGHT/2, (1 + C1) * SHAPE_LENGTH/2, SHAPE_HEIGHT, SHAPE_LENGTH/2, SHAPE_HEIGHT);
c->curveto((1 - C1) * SHAPE_LENGTH/2, SHAPE_HEIGHT, 0, (1 + C1) * SHAPE_HEIGHT/2, 0, SHAPE_HEIGHT/2);
c->closepath();
- spdc_paste_curve_as_freehand_shape(c, dc, item);
+ spdc_paste_curve_as_freehand_shape(c->get_pathvector(), dc, item);
c->unref();
shape_applied = true;
@@ -345,26 +398,90 @@ static void spdc_check_for_and_apply_waiting_LPE(FreehandBase *dc, SPItem *item,
}
case CLIPBOARD:
{
- // take shape from clipboard; TODO: catch the case where clipboard is empty
- Effect::createAndApply(PATTERN_ALONG_PATH, dc->desktop->doc(), item);
- Effect* lpe = SP_LPE_ITEM(item)->getCurrentLPE();
- static_cast<LPEPatternAlongPath*>(lpe)->pattern.on_paste_button_click();
+ // take shape from clipboard;
Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get();
- Glib::ustring svgd = cm->getPathParameter(SP_ACTIVE_DESKTOP);
- previous_shape_pathv = sp_svg_read_pathv(svgd.data());
-
- shape_applied = true;
+ if(cm->paste(SP_ACTIVE_DESKTOP,true) == true){
+ SPItem * pasted_clipboard = dc->selection->singleItem();
+ if(pasted_clipboard){
+ Inkscape::XML::Node *pasted_clipboard_root = pasted_clipboard->getRepr();
+ Inkscape::XML::Node *path = sp_repr_lookup_name(pasted_clipboard_root, "svg:path", -1); // unlimited search depth
+ if ( path != NULL ) {
+ gchar const *svgd = path->attribute("d");
+ dc->selection->remove(SP_OBJECT(pasted_clipboard));
+ previous_shape_pathv = sp_svg_read_pathv(svgd);
+ previous_shape_pathv *= pasted_clipboard->transform;
+ spdc_paste_curve_as_freehand_shape(previous_shape_pathv, dc, item);
+
+ shape = CLIPBOARD;
+ shape_applied = true;
+ pasted_clipboard->deleteObject();
+ } else {
+ shape = NONE;
+ }
+ } else {
+ shape = NONE;
+ }
+ } else {
+ shape = NONE;
+ }
+ break;
+ }
+ case BEND_CLIPBOARD:
+ {
+ Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get();
+ if(cm->paste(SP_ACTIVE_DESKTOP,true) == true){
+ gchar const *svgd = item->getRepr()->attribute("d");
+ bend_item = dc->selection->singleItem();
+ if(bend_item){
+ bend_item->moveTo(item,false);
+ bend_item->transform.setTranslation(Geom::Point());
+ spdc_apply_bend_shape(svgd, dc, bend_item);
+ dc->selection->add(SP_OBJECT(bend_item));
+
+ shape = BEND_CLIPBOARD;
+ } else {
+ shape = NONE;
+ }
+ } else {
+ shape = NONE;
+ }
break;
}
case LAST_APPLIED:
{
- if(previous_shape_pathv.size() != 0){
- SPCurve * c = new SPCurve();
- c->set_pathvector(previous_shape_pathv);
- spdc_paste_curve_as_freehand_shape(c, dc, item);
- c->unref();
-
- shape_applied = true;
+ if(previous_shape_type == CLIPBOARD){
+ if(previous_shape_pathv.size() != 0){
+ spdc_paste_curve_as_freehand_shape(previous_shape_pathv, dc, item);
+
+ shape_applied = true;
+ shape = CLIPBOARD;
+ } else{
+ shape = NONE;
+ }
+ } else {
+ if(bend_item != NULL && bend_item->getRepr() != NULL){
+ gchar const *svgd = item->getRepr()->attribute("d");
+ dc->selection->add(SP_OBJECT(bend_item));
+ sp_selection_duplicate(dc->desktop);
+ dc->selection->remove(SP_OBJECT(bend_item));
+ bend_item = dc->selection->singleItem();
+ if(bend_item){
+ bend_item->moveTo(item,false);
+ Geom::Coord expansion_X = bend_item->transform.expansionX();
+ Geom::Coord expansion_Y = bend_item->transform.expansionY();
+ bend_item->transform = Geom::Affine(1,0,0,1,0,0);
+ bend_item->transform.setExpansionX(expansion_X);
+ bend_item->transform.setExpansionY(expansion_Y);
+ spdc_apply_bend_shape(svgd, dc, bend_item);
+ dc->selection->add(SP_OBJECT(bend_item));
+
+ shape = BEND_CLIPBOARD;
+ } else {
+ shape = NONE;
+ }
+ } else {
+ shape = NONE;
+ }
}
break;
}
@@ -643,7 +760,6 @@ void spdc_concat_colors_and_flush(FreehandBase *dc, gboolean forceclosed)
static void spdc_flush_white(FreehandBase *dc, SPCurve *gc)
{
SPCurve *c;
-
if (dc->white_curves) {
g_assert(dc->white_item);
c = SPCurve::concat(dc->white_curves);
@@ -695,14 +811,17 @@ static void spdc_flush_white(FreehandBase *dc, SPCurve *gc)
// Attach repr
SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr));
- // we finished the path; now apply any waiting LPEs or freehand shapes
spdc_check_for_and_apply_waiting_LPE(dc, item, c);
-
- dc->selection->set(repr);
+ if(previous_shape_type != BEND_CLIPBOARD){
+ dc->selection->set(repr);
+ }
Inkscape::GC::release(repr);
item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
item->updateRepr();
item->doWriteTransform(item->getRepr(), item->transform, NULL, true);
+ if(previous_shape_type == BEND_CLIPBOARD){
+ repr->parent()->removeChild(repr);
+ }
}
DocumentUndo::done(doc, SP_IS_PEN_CONTEXT(dc)? SP_VERB_CONTEXT_PEN : SP_VERB_CONTEXT_PENCIL,
diff --git a/src/ui/tools/gradient-tool.cpp b/src/ui/tools/gradient-tool.cpp
index 603458983..9d8101cc4 100644
--- a/src/ui/tools/gradient-tool.cpp
+++ b/src/ui/tools/gradient-tool.cpp
@@ -225,13 +225,13 @@ sp_gradient_context_get_stop_intervals (GrDrag *drag, GSList **these_stops, GSLi
std::vector<Geom::Point> coords;
// for all selected draggers
- for (GList *i = drag->selected; i != NULL; i = i->next) {
- GrDragger *dragger = (GrDragger *) i->data;
+ for (std::set<GrDragger *>::const_iterator i = drag->selected.begin(); i != drag->selected.end() ; ++i ) {
+ GrDragger *dragger = *i;
// remember the coord of the dragger to reselect it later
coords.push_back(dragger->point);
// for all draggables of dragger
- for (GSList const* j = dragger->draggables; j != NULL; j = j->next) {
- GrDraggable *d = (GrDraggable *) j->data;
+ for (std::vector<GrDraggable *>::const_iterator j = dragger->draggables.begin(); j != dragger->draggables.end(); ++j) {
+ GrDraggable *d = *j;
// find the gradient
SPGradient *gradient = getGradient(d->item, d->fill_or_stroke);
@@ -315,9 +315,9 @@ sp_gradient_context_add_stops_between_selected_stops (GradientTool *rc)
if (g_slist_length(these_stops) == 0 && drag->numSelected() == 1) {
// if a single stop is selected, add between that stop and the next one
- GrDragger *dragger = (GrDragger *) drag->selected->data;
- for (GSList const* j = dragger->draggables; j != NULL; j = j->next) {
- GrDraggable *d = (GrDraggable *) j->data;
+ GrDragger *dragger = *(drag->selected.begin());
+ for (std::vector<GrDraggable *>::const_iterator j = dragger->draggables.begin(); j != dragger->draggables.end(); ++j) {
+ GrDraggable *d = *j;
if (d->point_type == POINT_RG_FOCUS) {
/*
* There are 2 draggables at the center (start) of a radial gradient
@@ -482,9 +482,9 @@ bool GradientTool::root_handler(GdkEvent* event) {
bool over_line = false;
SPCtrlLine *line = NULL;
- if (drag->lines) {
- for (GSList *l = drag->lines; (l != NULL) && (!over_line); l = l->next) {
- line = (SPCtrlLine*) l->data;
+ if (!drag->lines.empty()) {
+ for (std::vector<SPCtrlLine *>::const_iterator l = drag->lines.begin(); l != drag->lines.end() && (!over_line); ++l) {
+ line = *l;
over_line |= sp_gradient_context_is_over_line (this, (SPItem*) line, Geom::Point(event->motion.x, event->motion.y));
}
}
@@ -495,7 +495,7 @@ bool GradientTool::root_handler(GdkEvent* event) {
sp_gradient_context_add_stop_near_point(this, SP_ITEM(selection->itemList().front()), this->mousepoint_doc, event->button.time);
} else {
std::vector<SPItem*> items=selection->itemList();
- for (std::vector<SPItem*>::const_iterator i = items.begin();i!=items.end();i++) {
+ for (std::vector<SPItem*>::const_iterator i = items.begin();i!=items.end();++i) {
SPItem *item = *i;
SPGradientType new_type = (SPGradientType) prefs->getInt("/tools/gradient/newgradient", SP_GRADIENT_TYPE_LINEAR);
Inkscape::PaintTarget fsmode = (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE;
@@ -588,9 +588,9 @@ bool GradientTool::root_handler(GdkEvent* event) {
bool over_line = false;
- if (drag->lines) {
- for (GSList *l = drag->lines; l != NULL; l = l->next) {
- over_line |= sp_gradient_context_is_over_line (this, (SPItem*) l->data, Geom::Point(event->motion.x, event->motion.y));
+ if (!drag->lines.empty()) {
+ for (std::vector<SPCtrlLine *>::const_iterator l = drag->lines.begin(); l != drag->lines.end(); ++l) {
+ over_line |= sp_gradient_context_is_over_line (this, (SPItem*) (*l), Geom::Point(event->motion.x, event->motion.y));
}
}
@@ -613,12 +613,10 @@ bool GradientTool::root_handler(GdkEvent* event) {
bool over_line = false;
SPCtrlLine *line = NULL;
- if (drag->lines) {
- for (GSList *l = drag->lines; (l != NULL) && (!over_line); l = l->next) {
- line = (SPCtrlLine*) l->data;
+ if (!drag->lines.empty()) {
+ for (std::vector<SPCtrlLine *>::const_iterator l = drag->lines.begin(); l != drag->lines.end() && (!over_line); ++l) {
+ line = *l;
over_line = sp_gradient_context_is_over_line (this, (SPItem*) line, Geom::Point(event->motion.x, event->motion.y));
- if (over_line)
- break;
}
}
@@ -663,7 +661,7 @@ bool GradientTool::root_handler(GdkEvent* event) {
}
} else {
// click in an empty space; do the same as Esc
- if (drag->selected) {
+ if (!drag->selected.empty()) {
drag->deselectAll();
} else {
selection->clear();
@@ -719,7 +717,7 @@ bool GradientTool::root_handler(GdkEvent* event) {
break;
case GDK_KEY_Escape:
- if (drag->selected) {
+ if (!drag->selected.empty()) {
drag->deselectAll();
} else {
Inkscape::SelectionHelper::selectNone(desktop);
@@ -910,7 +908,7 @@ static void sp_gradient_drag(GradientTool &rc, Geom::Point const pt, guint /*sta
sp_repr_css_set_property(css, "fill-opacity", "1.0");
std::vector<SPItem*> itemlist = selection->itemList();
- for (std::vector<SPItem*>::const_iterator i = itemlist.begin();i!=itemlist.end();i++) {
+ for (std::vector<SPItem*>::const_iterator i = itemlist.begin();i!=itemlist.end();++i) {
//FIXME: see above
sp_repr_css_change_recursive((*i)->getRepr(), css, "style");
diff --git a/src/ui/tools/lpe-tool.cpp b/src/ui/tools/lpe-tool.cpp
index 13e47f3a6..9bbc1ac20 100644
--- a/src/ui/tools/lpe-tool.cpp
+++ b/src/ui/tools/lpe-tool.cpp
@@ -397,7 +397,7 @@ lpetool_create_measuring_items(LpeTool *lc, Inkscape::Selection *selection)
gchar *arc_length;
double lengthval;
std::vector<SPItem*> items=selection->itemList();
- for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();++i){
if (SP_IS_PATH(*i)) {
path = SP_PATH(*i);
curve = path->getCurve();
diff --git a/src/ui/tools/measure-tool.cpp b/src/ui/tools/measure-tool.cpp
index 570f3e796..a2a440ef4 100644
--- a/src/ui/tools/measure-tool.cpp
+++ b/src/ui/tools/measure-tool.cpp
@@ -4,67 +4,86 @@
* Authors:
* Felipe Correa da Silva Sanches <juca@members.fsf.org>
* Jon A. Cruz <jon@joncruz.org>
+ * Jabiertxo Arraiza <jabier.arraiza@marker.es>
*
* Copyright (C) 2011 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
-
+#include <gtkmm.h>
#include <gdk/gdkkeysyms.h>
#include <boost/none_t.hpp>
#include "util/units.h"
-#include "macros.h"
#include "display/curve.h"
-#include "sp-shape.h"
-#include "sp-text.h"
-#include "sp-flowtext.h"
-#include "text-editing.h"
-#include "display/sp-ctrlline.h"
#include "display/sodipodi-ctrl.h"
+#include "display/sp-ctrlline.h"
+#include "display/sp-ctrlcurve.h"
+#include "display/sp-canvas.h"
#include "display/sp-canvas-item.h"
#include "display/sp-canvas-util.h"
-#include "desktop.h"
-#include "document.h"
-#include "pixmaps/cursor-measure.xpm"
-#include "preferences.h"
-#include "inkscape.h"
-
+#include "svg/svg.h"
+#include "svg/svg-color.h"
#include "ui/tools/measure-tool.h"
#include "ui/tools/freehand-base.h"
-#include "display/canvas-text.h"
-#include "path-chemistry.h"
-#include "2geom/line.h"
+#include <2geom/line.h>
#include <2geom/path-intersection.h>
#include <2geom/pathvector.h>
#include <2geom/crossing.h>
#include <2geom/angle.h>
-#include "snap.h"
+#include <2geom/transforms.h>
+#include "ui/dialog/knot-properties.h"
#include "sp-namedview.h"
+#include "sp-shape.h"
+#include "sp-text.h"
+#include "sp-flowtext.h"
+#include "sp-defs.h"
+#include "sp-item.h"
+#include "sp-root.h"
+#include "macros.h"
+#include "svg/stringstream.h"
+#include "rubberband.h"
+#include "path-chemistry.h"
+#include "desktop.h"
+#include "document.h"
+#include "document-undo.h"
+#include "viewbox.h"
+#include "snap.h"
+#include "knot.h"
+#include "text-editing.h"
+#include "pixmaps/cursor-measure.xpm"
+#include "preferences.h"
+#include "inkscape.h"
#include "enums.h"
-#include "ui/control-manager.h"
#include "knot-enums.h"
+#include "desktop-style.h"
+#include "verbs.h"
+#include <glibmm/i18n.h>
using Inkscape::ControlManager;
using Inkscape::CTLINE_SECONDARY;
using Inkscape::Util::unit_table;
+using Inkscape::DocumentUndo;
+
+#define MT_KNOT_COLOR_NORMAL 0xffffff00
+#define MT_KNOT_COLOR_MOUSEOVER 0xff000000
+
namespace Inkscape {
namespace UI {
namespace Tools {
-std::vector<Inkscape::Display::TemporaryItem*> measure_tmp_items;
-
-const std::string& MeasureTool::getPrefsPath() {
- return MeasureTool::prefsPath;
+const std::string& MeasureTool::getPrefsPath()
+{
+ return MeasureTool::prefsPath;
}
const std::string MeasureTool::prefsPath = "/tools/measure";
-namespace
-{
-
-gint const DIMENSION_OFFSET = 35;
+namespace {
/**
* Simple class to use for removing label overlap.
@@ -87,14 +106,16 @@ bool SortLabelPlacement(LabelPlacement const &first, LabelPlacement const &secon
}
}
-void repositionOverlappingLabels(std::vector<LabelPlacement> &placements, SPDesktop *desktop, Geom::Point const &normal, double fontsize)
+//precision is for give the number of decimal positions
+//of the label to calculate label width
+void repositionOverlappingLabels(std::vector<LabelPlacement> &placements, SPDesktop *desktop, Geom::Point const &normal, double fontsize, int precision)
{
std::sort(placements.begin(), placements.end(), SortLabelPlacement);
double border = 3;
Geom::Rect box;
{
- Geom::Point tmp(fontsize * 8 + (border * 2), fontsize + (border * 2));
+ Geom::Point tmp(fontsize * (6 + precision) + (border * 2), fontsize + (border * 2));
tmp = desktop->w2d(tmp);
box = Geom::Rect(-tmp[Geom::X] / 2, -tmp[Geom::Y] / 2, tmp[Geom::X] / 2, tmp[Geom::Y] / 2);
}
@@ -175,6 +196,76 @@ Geom::Point calcAngleDisplayAnchor(SPDesktop *desktop, double angle, double base
}
/**
+ * Create a measure iten in current document.
+ *
+ * @param pathv the path to create.
+ * @param markers, if the path resuts get markers.
+ * @param color of the stroke.
+ * @param measure_repr container element.
+ */
+void setMeasureItem(Geom::PathVector pathv, bool is_curve, bool markers, guint32 color, Inkscape::XML::Node *measure_repr)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if(!desktop) {
+ return;
+ }
+ SPDocument *doc = desktop->getDocument();
+ Inkscape::XML::Document *xml_doc = doc->getReprDoc();
+ Inkscape::XML::Node *repr;
+ repr = xml_doc->createElement("svg:path");
+ gchar *str = sp_svg_write_path(pathv);
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ Geom::Coord strokewidth = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse().expansionX();
+ std::stringstream stroke_width;
+ stroke_width.imbue(std::locale::classic());
+ if(measure_repr) {
+ stroke_width << strokewidth / desktop->current_zoom();
+ } else {
+ stroke_width << strokewidth;
+ }
+ sp_repr_css_set_property (css, "stroke-width", stroke_width.str().c_str());
+ sp_repr_css_set_property (css, "fill", "none");
+ if(color) {
+ gchar color_line[64];
+ sp_svg_write_color (color_line, sizeof(color_line), color);
+ sp_repr_css_set_property (css, "stroke", color_line);
+ } else {
+ sp_repr_css_set_property (css, "stroke", "#ff0000");
+ }
+ char const * stroke_linecap = is_curve ? "butt" : "square";
+ sp_repr_css_set_property (css, "stroke-linecap", stroke_linecap);
+ sp_repr_css_set_property (css, "stroke-linejoin", "miter");
+ sp_repr_css_set_property (css, "stroke-miterlimit", "4");
+ sp_repr_css_set_property (css, "stroke-dasharray", "none");
+ if(measure_repr) {
+ sp_repr_css_set_property (css, "stroke-opacity", "0.5");
+ } else {
+ sp_repr_css_set_property (css, "stroke-opacity", "1");
+ }
+ if(markers) {
+ sp_repr_css_set_property (css, "marker-start", "url(#Arrow2Sstart)");
+ sp_repr_css_set_property (css, "marker-end", "url(#Arrow2Send)");
+ }
+ Glib::ustring css_str;
+ sp_repr_css_write_string(css,css_str);
+ repr->setAttribute("style", css_str.c_str());
+ sp_repr_css_attr_unref (css);
+ g_assert( str != NULL );
+ repr->setAttribute("d", str);
+ g_free(str);
+ if(measure_repr) {
+ measure_repr->addChild(repr, NULL);
+ Inkscape::GC::release(repr);
+ } else {
+ SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(repr));
+ Inkscape::GC::release(repr);
+ item->updateRepr();
+ desktop->getSelection()->clear();
+ desktop->getSelection()->add(item);
+ }
+}
+
+/**
* Given an angle, the arc center and edge point, draw an arc segment centered around that edge point.
*
* @param desktop the desktop that is being used.
@@ -182,8 +273,9 @@ Geom::Point calcAngleDisplayAnchor(SPDesktop *desktop, double angle, double base
* @param end the point that ends at the edge of the arc segment.
* @param anchor the anchor point for displaying the text label.
* @param angle the angle of the arc segment to draw.
+ * @param measure_rpr the container of the curve if converted to items.
*/
-void createAngleDisplayCurve(SPDesktop *desktop, Geom::Point const &center, Geom::Point const &end, Geom::Point const &anchor, double angle)
+void createAngleDisplayCurve(SPDesktop *desktop, Geom::Point const &center, Geom::Point const &end, Geom::Point const &anchor, double angle, bool to_phantom, std::vector<SPCanvasItem *> &measure_phantom_items , std::vector<SPCanvasItem *> &measure_tmp_items , Inkscape::XML::Node *measure_repr = NULL)
{
// Given that we have a point on the arc's edge and the angle of the arc, we need to get the two endpoints.
@@ -191,7 +283,7 @@ void createAngleDisplayCurve(SPDesktop *desktop, Geom::Point const &center, Geom
double sideLen = std::abs((end - center).length());
if (sideLen > 0.0) {
double factor = std::min(1.0, textLen / sideLen);
-
+
// arc start
Geom::Point p1 = end * (Geom::Affine(Geom::Translate(-center))
* Geom::Affine(Geom::Scale(factor))
@@ -219,24 +311,212 @@ void createAngleDisplayCurve(SPDesktop *desktop, Geom::Point const &center, Geom
Geom::Point p3(xc + bx + (k2 * by),
yc + by - (k2 * bx));
SPCtrlCurve *curve = ControlManager::getManager().createControlCurve(desktop->getTempGroup(), p1, p2, p3, p4, CTLINE_SECONDARY);
-
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(SP_CANVAS_ITEM(curve), 0, true));
+ if(to_phantom){
+ curve->rgba = 0x8888887f;
+ measure_phantom_items.push_back(SP_CANVAS_ITEM(curve));
+ } else {
+ measure_tmp_items.push_back(SP_CANVAS_ITEM(curve));
+ }
+ sp_canvas_item_move_to_z(SP_CANVAS_ITEM(curve), 0);
+ sp_canvas_item_show(SP_CANVAS_ITEM(curve));
+ if(measure_repr) {
+ Geom::PathVector pathv;
+ Geom::Path path;
+ path.start(desktop->doc2dt(p1));
+ path.appendNew<Geom::CubicBezier>(desktop->doc2dt(p2),desktop->doc2dt(p3),desktop->doc2dt(p4));
+ pathv.push_back(path);
+ pathv *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
+ if(!pathv.empty()) {
+ setMeasureItem(pathv, true, false, 0xff00007f, measure_repr);
+ }
+ }
}
}
-} // namespace
+} // namespace
+boost::optional<Geom::Point> explicit_base_tmp = boost::none;
MeasureTool::MeasureTool()
: ToolBase(cursor_measure_xpm, 4, 4)
, grabbed(NULL)
{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ start_p = readMeasurePoint(true);
+ end_p = readMeasurePoint(false);
+ dimension_offset = 35;
+ // create the knots
+ this->knot_start = new SPKnot(desktop, N_("Measure start, <b>Shift+Click</b> for position dialog"));
+ this->knot_start->setMode(SP_KNOT_MODE_XOR);
+ this->knot_start->setFill(MT_KNOT_COLOR_NORMAL, MT_KNOT_COLOR_MOUSEOVER, MT_KNOT_COLOR_MOUSEOVER);
+ this->knot_start->setStroke(0x0000007f, 0x0000007f, 0x0000007f);
+ this->knot_start->setShape(SP_KNOT_SHAPE_CIRCLE);
+ this->knot_start->updateCtrl();
+ this->knot_end = new SPKnot(desktop, N_("Measure end, <b>Shift+Click</b> for position dialog"));
+ this->knot_end->setMode(SP_KNOT_MODE_XOR);
+ this->knot_end->setFill(MT_KNOT_COLOR_NORMAL, MT_KNOT_COLOR_MOUSEOVER, MT_KNOT_COLOR_MOUSEOVER);
+ this->knot_end->setStroke(0x0000007f, 0x0000007f, 0x0000007f);
+ this->knot_end->setShape(SP_KNOT_SHAPE_CIRCLE);
+ this->knot_end->updateCtrl();
+ Geom::Rect display_area = desktop->get_display_area();
+ if(display_area.interiorContains(start_p) && display_area.interiorContains(end_p) && end_p != Geom::Point()) {
+ this->knot_start->moveto(start_p);
+ this->knot_start->show();
+ this->knot_end->moveto(end_p);
+ this->knot_end->show();
+ showCanvasItems();
+ } else {
+ start_p = Geom::Point(0,0);
+ end_p = Geom::Point(0,0);
+ writeMeasurePoint(start_p, true);
+ writeMeasurePoint(end_p, false);
+ }
+ this->_knot_start_moved_connection = this->knot_start->moved_signal.connect(sigc::mem_fun(*this, &MeasureTool::knotStartMovedHandler));
+ this->_knot_start_click_connection = this->knot_start->click_signal.connect(sigc::mem_fun(*this, &MeasureTool::knotClickHandler));
+ this->_knot_start_ungrabbed_connection = this->knot_start->ungrabbed_signal.connect(sigc::mem_fun(*this, &MeasureTool::knotUngrabbedHandler));
+ this->_knot_end_moved_connection = this->knot_end->moved_signal.connect(sigc::mem_fun(*this, &MeasureTool::knotEndMovedHandler));
+ this->_knot_end_click_connection = this->knot_end->click_signal.connect(sigc::mem_fun(*this, &MeasureTool::knotClickHandler));
+ this->_knot_end_ungrabbed_connection = this->knot_end->ungrabbed_signal.connect(sigc::mem_fun(*this, &MeasureTool::knotUngrabbedHandler));
+
}
-MeasureTool::~MeasureTool() {
+MeasureTool::~MeasureTool()
+{
+ this->_knot_start_moved_connection.disconnect();
+ this->_knot_start_ungrabbed_connection.disconnect();
+ this->_knot_end_moved_connection.disconnect();
+ this->_knot_end_ungrabbed_connection.disconnect();
+
+ /* unref should call destroy */
+ knot_unref(this->knot_start);
+ knot_unref(this->knot_end);
+ for (size_t idx = 0; idx < measure_tmp_items.size(); ++idx) {
+ sp_canvas_item_destroy(measure_tmp_items[idx]);
+ }
+ measure_tmp_items.clear();
+ for (size_t idx = 0; idx < measure_phantom_items.size(); ++idx) {
+ sp_canvas_item_destroy(measure_phantom_items[idx]);
+ }
+ measure_phantom_items.clear();
}
-void MeasureTool::finish() {
+Geom::Point MeasureTool::readMeasurePoint(bool is_start) {
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SPNamedView *namedview = desktop->namedview;
+ if(!namedview) {
+ return Geom::Point(Geom::infinity(),Geom::infinity());
+ }
+ char const * measure_point = is_start ? "inkscape:measure-start" : "inkscape:measure-end";
+ char const * measure_point_data = namedview->getAttribute (measure_point);
+ if(!measure_point_data) {
+ measure_point_data = "0,0";
+ namedview->setAttribute (measure_point, measure_point_data);
+ }
+ gchar ** strarray = g_strsplit(measure_point_data, ",", 2);
+ double newx, newy;
+ unsigned int success = sp_svg_number_read_d(strarray[0], &newx);
+ success += sp_svg_number_read_d(strarray[1], &newy);
+ g_strfreev (strarray);
+ if (success == 2) {
+ Geom::Point point_data(newx, newy);
+ return point_data;
+ }
+ return Geom::Point(Geom::infinity(),Geom::infinity());
+
+}
+
+void MeasureTool::writeMeasurePoint(Geom::Point point, bool is_start) {
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SPNamedView *namedview = desktop->namedview;
+ if(!namedview) {
+ return;
+ }
+ std::stringstream meassure_point_str;
+ meassure_point_str.imbue(std::locale::classic());
+ meassure_point_str << point[Geom::X] << "," << point[Geom::Y];
+ gchar const *measure_point = is_start ? "inkscape:measure-start" : "inkscape:measure-end";
+ namedview->setAttribute (measure_point, meassure_point_str.str().c_str());
+}
+
+//This function is used to reverse the Measure, I do it in two steps because when move the knot the
+//start_ or the end_p are overwrite so I need the original values.
+void MeasureTool::reverseKnots()
+{
+ Geom::Point start = start_p;
+ Geom::Point end = end_p;
+ this->knot_start->moveto(end);
+ this->knot_start->show();
+ this->knot_end->moveto(start);
+ this->knot_end->show();
+ start_p = end;
+ end_p = start;
+ this->showCanvasItems();
+}
+
+void MeasureTool::knotClickHandler(SPKnot *knot, guint state)
+{
+ if (state & GDK_SHIFT_MASK) {
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ Glib::ustring const unit_name = prefs->getString("/tools/measure/unit");
+ explicit_base = explicit_base_tmp;
+ Inkscape::UI::Dialogs::KnotPropertiesDialog::showDialog(desktop, knot, unit_name);
+ }
+}
+
+void MeasureTool::knotStartMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state)
+{
+ Geom::Point point = this->knot_start->position();
+ if (state & GDK_CONTROL_MASK) {
+ spdc_endpoint_snap_rotation(this, point, end_p, state);
+ } else if (!(state & GDK_SHIFT_MASK)) {
+ SnapManager &snap_manager = desktop->namedview->snap_manager;
+ snap_manager.setup(desktop);
+ Inkscape::SnapCandidatePoint scp(point, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ scp.addOrigin(this->knot_end->position());
+ Inkscape::SnappedPoint sp = snap_manager.freeSnap(scp);
+ point = sp.getPoint();
+ snap_manager.unSetup();
+ }
+ if(start_p != point) {
+ start_p = point;
+ this->knot_start->moveto(start_p);
+ }
+ showCanvasItems();
+}
+
+void MeasureTool::knotEndMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state)
+{
+ Geom::Point point = this->knot_end->position();
+ if (state & GDK_CONTROL_MASK) {
+ spdc_endpoint_snap_rotation(this, point, start_p, state);
+ } else if (!(state & GDK_SHIFT_MASK)) {
+ SnapManager &snap_manager = desktop->namedview->snap_manager;
+ snap_manager.setup(desktop);
+ Inkscape::SnapCandidatePoint scp(point, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ scp.addOrigin(this->knot_start->position());
+ Inkscape::SnappedPoint sp = snap_manager.freeSnap(scp);
+ point = sp.getPoint();
+ snap_manager.unSetup();
+ }
+ if(end_p != point) {
+ end_p = point;
+ this->knot_end->moveto(end_p);
+ }
+ showCanvasItems();
+}
+
+void MeasureTool::knotUngrabbedHandler(SPKnot */*knot*/, unsigned int state)
+{
+ this->knot_start->moveto(start_p);
+ this->knot_end->moveto(end_p);
+ showCanvasItems();
+}
+
+
+//todo: we need this function?
+void MeasureTool::finish()
+{
this->enableGrDrag(false);
if (this->grabbed) {
@@ -247,498 +527,816 @@ void MeasureTool::finish() {
ToolBase::finish();
}
-//void MeasureTool::setup() {
-// ToolBase* ec = this;
-//
-//// if (SP_EVENT_CONTEXT_CLASS(sp_measure_context_parent_class)->setup) {
-//// SP_EVENT_CONTEXT_CLASS(sp_measure_context_parent_class)->setup(ec);
-//// }
-// ToolBase::setup();
-//}
-
-//gint MeasureTool::item_handler(SPItem* item, GdkEvent* event) {
-// gint ret = FALSE;
-//
-//// if (SP_EVENT_CONTEXT_CLASS(sp_measure_context_parent_class)->item_handler) {
-//// ret = SP_EVENT_CONTEXT_CLASS(sp_measure_context_parent_class)->item_handler(event_context, item, event);
-//// }
-// ret = ToolBase::item_handler(item, event);
-//
-// return ret;
-//}
-
static void calculate_intersections(SPDesktop * /*desktop*/, SPItem* item, Geom::PathVector const &lineseg, SPCurve *curve, std::vector<double> &intersections)
{
-
curve->transform(item->i2doc_affine());
// Find all intersections of the control-line with this shape
Geom::CrossingSet cs = Geom::crossings(lineseg, curve->get_pathvector());
Geom::delete_duplicates(cs[0]);
// Reconstruct and store the points of intersection
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ bool show_hidden = prefs->getBool("/tools/measure/show_hidden", true);
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
for (Geom::Crossings::const_iterator m = cs[0].begin(); m != cs[0].end(); ++m) {
-#if 0
-//TODO: consider only visible intersections
- Geom::Point intersection = lineseg[0].pointAt((*m).ta);
- double eps = 0.0001;
- SPDocument* doc = desktop->getDocument();
- if (((*m).ta > eps &&
- item == doc->getItemAtPoint(desktop->dkey, lineseg[0].pointAt((*m).ta - eps), false, NULL)) ||
+ if (!show_hidden) {
+ double eps = 0.0001;
+ if (((*m).ta > eps &&
+ item == desktop->getItemAtPoint(desktop->d2w(desktop->dt2doc(lineseg[0].pointAt((*m).ta - eps))), true, NULL)) ||
((*m).ta + eps < 1 &&
- item == doc->getItemAtPoint(desktop->dkey, lineseg[0].pointAt((*m).ta + eps), false, NULL)) ) {
+ item == desktop->getItemAtPoint(desktop->d2w(desktop->dt2doc(lineseg[0].pointAt((*m).ta + eps))), true, NULL))) {
+ intersections.push_back((*m).ta);
+ }
+ } else {
intersections.push_back((*m).ta);
}
-#else
- intersections.push_back((*m).ta);
-
-#endif
}
}
-bool MeasureTool::root_handler(GdkEvent* event) {
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
-
+bool MeasureTool::root_handler(GdkEvent* event)
+{
gint ret = FALSE;
switch (event->type) {
- case GDK_BUTTON_PRESS: {
- Geom::Point const button_w(event->button.x, event->button.y);
- explicitBase = boost::none;
- lastEnd = boost::none;
- start_point = desktop->w2d(button_w);
-
- if (event->button.button == 1 && !this->space_panning) {
- // save drag origin
- xp = static_cast<gint>(event->button.x);
- yp = static_cast<gint>(event->button.y);
- within_tolerance = true;
-
- ret = TRUE;
- }
+ case GDK_BUTTON_PRESS: {
+ this->knot_start->hide();
+ this->knot_end->hide();
+ Geom::Point const button_w(event->button.x, event->button.y);
+ explicit_base = boost::none;
+ explicit_base_tmp = boost::none;
+ last_end = boost::none;
+ start_p = desktop->w2d(button_w);
+
+ if (event->button.button == 1 && !this->space_panning) {
+ // save drag origin
+ start_p = desktop->w2d(Geom::Point(event->button.x, event->button.y));
+ within_tolerance = true;
+
+ ret = TRUE;
+ }
- SnapManager &m = desktop->namedview->snap_manager;
- m.setup(desktop);
- m.freeSnapReturnByRef(start_point, Inkscape::SNAPSOURCE_OTHER_HANDLE);
- m.unSetup();
+ SnapManager &snap_manager = desktop->namedview->snap_manager;
+ snap_manager.setup(desktop);
+ snap_manager.freeSnapReturnByRef(start_p, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ snap_manager.unSetup();
- sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
- GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK,
- NULL, event->button.time);
- this->grabbed = SP_CANVAS_ITEM(desktop->acetate);
- break;
- }
- case GDK_KEY_PRESS: {
- if ((event->key.keyval == GDK_KEY_Shift_L) || (event->key.keyval == GDK_KEY_Shift_R)) {
- if (lastEnd) {
- explicitBase = lastEnd;
- }
- }
- break;
+ sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
+ GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK,
+ NULL, event->button.time);
+ this->grabbed = SP_CANVAS_ITEM(desktop->acetate);
+ break;
+ }
+ case GDK_KEY_PRESS: {
+ if ((event->key.keyval == GDK_KEY_Shift_L) || (event->key.keyval == GDK_KEY_Shift_R)) {
+ explicit_base_tmp = explicit_base;
+ explicit_base = end_p;
}
- case GDK_MOTION_NOTIFY: {
- if (!((event->motion.state & GDK_BUTTON1_MASK) && !this->space_panning)) {
- if (!(event->motion.state & GDK_SHIFT_MASK)) {
- Geom::Point const motion_w(event->motion.x, event->motion.y);
- Geom::Point const motion_dt(desktop->w2d(motion_w));
-
- SnapManager &m = desktop->namedview->snap_manager;
- m.setup(desktop);
+ break;
+ }
+ case GDK_MOTION_NOTIFY: {
+ if (!(event->motion.state & GDK_BUTTON1_MASK)) {
+ if(!(event->motion.state & GDK_SHIFT_MASK)) {
+ Geom::Point const motion_w(event->motion.x, event->motion.y);
+ Geom::Point const motion_dt(desktop->w2d(motion_w));
- Inkscape::SnapCandidatePoint scp(motion_dt, Inkscape::SNAPSOURCE_OTHER_HANDLE);
- scp.addOrigin(start_point);
+ SnapManager &snap_manager = desktop->namedview->snap_manager;
+ snap_manager.setup(desktop);
- m.preSnap(scp);
- m.unSetup();
- }
- } else {
- ret = TRUE;
+ Inkscape::SnapCandidatePoint scp(motion_dt, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ scp.addOrigin(start_p);
- if ( within_tolerance
- && ( abs( static_cast<gint>(event->motion.x) - xp ) < tolerance )
- && ( abs( static_cast<gint>(event->motion.y) - yp ) < tolerance ) ) {
- break; // do not drag if we're within tolerance from origin
- }
- // Once the user has moved farther than tolerance from the original location
- // (indicating they intend to move the object, not click), then always process the
- // motion notify coordinates as given (no snapping back to origin)
- within_tolerance = false;
-
- //clear previous temporary canvas items, we'll draw new ones
- for (size_t idx = 0; idx < measure_tmp_items.size(); ++idx) {
- desktop->remove_temporary_canvasitem(measure_tmp_items[idx]);
+ snap_manager.preSnap(scp);
+ snap_manager.unSetup();
+ }
+ } else {
+ ret = TRUE;
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
+ Geom::Point const motion_w(event->motion.x, event->motion.y);
+ if ( within_tolerance) {
+ if ( Geom::LInfty( motion_w - start_p ) < tolerance) {
+ return FALSE; // Do not drag if we're within tolerance from origin.
}
-
- measure_tmp_items.clear();
-
- Geom::Point const motion_w(event->motion.x, event->motion.y);
+ }
+ // Once the user has moved farther than tolerance from the original location
+ // (indicating they intend to move the object, not click), then always process the
+ // motion notify coordinates as given (no snapping back to origin)
+ within_tolerance = false;
+ if(event->motion.time == 0 || !last_end || Geom::LInfty( motion_w - *last_end ) > (tolerance/4.0)) {
Geom::Point const motion_dt(desktop->w2d(motion_w));
- Geom::Point end_point = motion_dt;
+ end_p = motion_dt;
if (event->motion.state & GDK_CONTROL_MASK) {
- spdc_endpoint_snap_rotation(this, end_point, start_point, event->motion.state);
- } else {
- if (!(event->motion.state & GDK_SHIFT_MASK)) {
- SnapManager &m = desktop->namedview->snap_manager;
- m.setup(desktop);
- Inkscape::SnapCandidatePoint scp(end_point, Inkscape::SNAPSOURCE_OTHER_HANDLE);
- scp.addOrigin(start_point);
- Inkscape::SnappedPoint sp = m.freeSnap(scp);
- end_point = sp.getPoint();
- m.unSetup();
- }
+ spdc_endpoint_snap_rotation(this, end_p, start_p, event->motion.state);
+ } else if (!(event->motion.state & GDK_SHIFT_MASK)) {
+ SnapManager &snap_manager = desktop->namedview->snap_manager;
+ snap_manager.setup(desktop);
+ Inkscape::SnapCandidatePoint scp(end_p, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ scp.addOrigin(start_p);
+ Inkscape::SnappedPoint sp = snap_manager.freeSnap(scp);
+ end_p = sp.getPoint();
+ snap_manager.unSetup();
}
+ showCanvasItems();
+ last_end = motion_w ;
+ }
+ gobble_motion_events(GDK_BUTTON1_MASK);
+ }
+ break;
+ }
+ case GDK_BUTTON_RELEASE: {
+ this->knot_start->moveto(start_p);
+ this->knot_start->show();
+ if(last_end) {
+ end_p = desktop->w2d(*last_end);
+ if (event->button.state & GDK_CONTROL_MASK) {
+ spdc_endpoint_snap_rotation(this, end_p, start_p, event->motion.state);
+ } else if (!(event->button.state & GDK_SHIFT_MASK)) {
+ SnapManager &snap_manager = desktop->namedview->snap_manager;
+ snap_manager.setup(desktop);
+ Inkscape::SnapCandidatePoint scp(end_p, Inkscape::SNAPSOURCE_OTHER_HANDLE);
+ scp.addOrigin(start_p);
+ Inkscape::SnappedPoint sp = snap_manager.freeSnap(scp);
+ end_p = sp.getPoint();
+ snap_manager.unSetup();
+ }
+ }
+ this->knot_end->moveto(end_p);
+ this->knot_end->show();
+ showCanvasItems();
- Geom::PathVector lineseg;
- Geom::Path p;
- p.start(desktop->dt2doc(start_point));
- p.appendNew<Geom::LineSegment>(desktop->dt2doc(end_point));
- lineseg.push_back(p);
-
- double deltax = end_point[Geom::X] - start_point[Geom::X];
- double deltay = end_point[Geom::Y] - start_point[Geom::Y];
- double angle = atan2(deltay, deltax);
- double baseAngle = 0;
-
- if (explicitBase) {
- double deltax2 = explicitBase.get()[Geom::X] - start_point[Geom::X];
- double deltay2 = explicitBase.get()[Geom::Y] - start_point[Geom::Y];
-
- baseAngle = atan2(deltay2, deltax2);
- angle -= baseAngle;
-
- if (angle < -M_PI) {
- angle += 2 * M_PI;
- } else if (angle > M_PI) {
- angle -= 2 * M_PI;
- }
- }
+ if (this->grabbed) {
+ sp_canvas_item_ungrab(this->grabbed, event->button.time);
+ this->grabbed = NULL;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ if (!ret) {
+ ret = ToolBase::root_handler(event);
+ }
-//TODO: calculate NPOINTS
-//800 seems to be a good value for 800x600 resolution
-#define NPOINTS 800
+ return ret;
+}
- std::vector<Geom::Point> points;
+void MeasureTool::setMarkers()
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SPDocument *doc = desktop->getDocument();
+ SPObject *arrowStart = doc->getObjectById("Arrow2Sstart");
+ SPObject *arrowEnd = doc->getObjectById("Arrow2Send");
+ if (!arrowStart) {
+ setMarker(true);
+ }
+ if(!arrowEnd) {
+ setMarker(false);
+ }
+}
+void MeasureTool::setMarker(bool isStart)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SPDocument *doc = desktop->getDocument();
+ SPDefs *defs = doc->getDefs();
+ Inkscape::XML::Node *rmarker;
+ Inkscape::XML::Document *xml_doc = doc->getReprDoc();
+ rmarker = xml_doc->createElement("svg:marker");
+ rmarker->setAttribute("id", isStart ? "Arrow2Sstart" : "Arrow2Send");
+ rmarker->setAttribute("inkscape:isstock", "true");
+ rmarker->setAttribute("inkscape:stockid", isStart ? "Arrow2Sstart" : "Arrow2Send");
+ rmarker->setAttribute("orient", "auto");
+ rmarker->setAttribute("refX", "0.0");
+ rmarker->setAttribute("refY", "0.0");
+ rmarker->setAttribute("style", "overflow:visible;");
+ SPItem *marker = SP_ITEM(defs->appendChildRepr(rmarker));
+ Inkscape::GC::release(rmarker);
+ marker->updateRepr();
+ Inkscape::XML::Node *rpath;
+ rpath = xml_doc->createElement("svg:path");
+ rpath->setAttribute("d", "M 8.72,4.03 L -2.21,0.02 L 8.72,-4.00 C 6.97,-1.63 6.98,1.62 8.72,4.03 z");
+ rpath->setAttribute("id", isStart ? "Arrow2SstartPath" : "Arrow2SendPath");
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property (css, "stroke", "none");
+ sp_repr_css_set_property (css, "fill", "#000000");
+ sp_repr_css_set_property (css, "fill-opacity", "1");
+ Glib::ustring css_str;
+ sp_repr_css_write_string(css,css_str);
+ rpath->setAttribute("style", css_str.c_str());
+ sp_repr_css_attr_unref (css);
+ rpath->setAttribute("transform", isStart ? "scale(0.3) translate(-2.3,0)" : "scale(0.3) rotate(180) translate(-2.3,0)");
+ SPItem *path = SP_ITEM(marker->appendChildRepr(rpath));
+ Inkscape::GC::release(rpath);
+ path->updateRepr();
+}
- for (double i = 0; i < NPOINTS; i++) {
- points.push_back(desktop->d2w(start_point + (i / NPOINTS) * (end_point - start_point)));
- }
+void MeasureTool::toGuides()
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if(!desktop || !start_p.isFinite() || !end_p.isFinite() || start_p == end_p) {
+ return;
+ }
+ SPDocument *doc = desktop->getDocument();
+ Geom::Point start = desktop->doc2dt(start_p) * desktop->doc2dt();
+ Geom::Point end = desktop->doc2dt(end_p) * desktop->doc2dt();
+ Geom::Ray ray(start,end);
+ SPNamedView *namedview = desktop->namedview;
+ if(!namedview) {
+ return;
+ }
+ setGuide(start,ray.angle(), _("Measure"));
+ if(explicit_base) {
+ explicit_base = *explicit_base * SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
+ ray.setPoints(start, *explicit_base);
+ if(ray.angle() != 0) {
+ setGuide(start,ray.angle(), _("Base"));
+ }
+ }
+ setGuide(start,0,"");
+ setGuide(start,Geom::rad_from_deg(90),_("Start"));
+ setGuide(end,0,_("End"));
+ setGuide(end,Geom::rad_from_deg(90),"");
+ showCanvasItems(true);
+ doc->ensureUpToDate();
+ DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE,_("Add guides from measure tool"));
+}
- // TODO: Felipe, why don't you simply iterate over all items, and test whether their bounding boxes intersect
- // with the measurement line, instead of interpolating over 800 points? E.g. bbox_of_measurement_line.intersects(*bbox_of_item).
- // That's also how the object-snapper works, see _findCandidates() in object-snapper.cpp.
-
- // TODO switch to a different variable name. The single letter 'l' is easy to misread.
-
- //select elements crossed by line segment:
- std::vector<SPItem*> items = desktop->getDocument()->getItemsAtPoints(desktop->dkey, points);
- std::vector<double> intersection_times;
- for (std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++) {
- SPItem *item = *i;
-
- if (SP_IS_SHAPE(item)) {
- calculate_intersections(desktop, item, lineseg, SP_SHAPE(item)->getCurve(), intersection_times);
- } else {
- if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
- Inkscape::Text::Layout::iterator iter = te_get_layout(item)->begin();
- do {
- Inkscape::Text::Layout::iterator iter_next = iter;
- iter_next.nextGlyph(); // iter_next is one glyph ahead from iter
- if (iter == iter_next) {
- break;
- }
-
- // get path from iter to iter_next:
- SPCurve *curve = te_get_layout(item)->convertToCurves(iter, iter_next);
- iter = iter_next; // shift to next glyph
- if (!curve) {
- continue; // error converting this glyph
- }
- if (curve->is_empty()) { // whitespace glyph?
- curve->unref();
- continue;
- }
-
- curve->transform(item->i2doc_affine());
-
- calculate_intersections(desktop, item, lineseg, curve, intersection_times);
-
- if (iter == te_get_layout(item)->end()) {
- break;
- }
- } while (true);
- }
- }
- }
+void MeasureTool::toPhantom()
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if(!desktop || !start_p.isFinite() || !end_p.isFinite() || start_p == end_p) {
+ return;
+ }
+ SPDocument *doc = desktop->getDocument();
+ for (size_t idx = 0; idx < measure_phantom_items.size(); ++idx) {
+ sp_canvas_item_destroy(measure_phantom_items[idx]);
+ }
+ measure_phantom_items.clear();
+ for (size_t idx = 0; idx < measure_tmp_items.size(); ++idx) {
+ sp_canvas_item_destroy(measure_tmp_items[idx]);
+ }
+ measure_tmp_items.clear();
+ showCanvasItems(false, false, true);
+ doc->ensureUpToDate();
+ DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE,_("Add Stored to measure tool"));
+}
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- if (!prefs->getBool("/tools/measure/ignore_1st_and_last", true)) {
- intersection_times.push_back(0);
- intersection_times.push_back(1);
- }
+void MeasureTool::toItem()
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if(!desktop || !start_p.isFinite() || !end_p.isFinite() || start_p == end_p) {
+ return;
+ }
+ SPDocument *doc = desktop->getDocument();
+ Geom::Ray ray(start_p,end_p);
+ guint32 line_color_primary = 0x0000ff7f;
+ Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
+ Inkscape::XML::Node *rgroup = xml_doc->createElement("svg:g");
+ showCanvasItems(false, true, false, rgroup);
+ setLine(start_p,end_p, false, line_color_primary, rgroup);
+ SPItem *measure_item = SP_ITEM(desktop->currentLayer()->appendChildRepr(rgroup));
+ Inkscape::GC::release(rgroup);
+ measure_item->updateRepr();
+ doc->ensureUpToDate();
+ DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE,_("Convert measure to items"));
+ reset();
+}
- Glib::ustring unit_name = prefs->getString("/tools/measure/unit");
- if (!unit_name.compare("")) {
- unit_name = "px";
- }
+void MeasureTool::toMarkDimension()
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if(!desktop || !start_p.isFinite() || !end_p.isFinite() || start_p == end_p) {
+ return;
+ }
+ SPDocument *doc = desktop->getDocument();
+ setMarkers();
+ Geom::Ray ray(start_p,end_p);
+ Geom::Point start = start_p + Geom::Point::polar(ray.angle(), 5);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ dimension_offset = prefs->getDouble("/tools/measure/offset", 5.0);
+ start = start + Geom::Point::polar(ray.angle() + Geom::rad_from_deg(90), -dimension_offset);
+ Geom::Point end = end_p + Geom::Point::polar(ray.angle(), -5);
+ end = end+ Geom::Point::polar(ray.angle() + Geom::rad_from_deg(90), -dimension_offset);
+ guint32 color = 0x000000ff;
+ setLine(start, end, true, color);
+ Glib::ustring unit_name = prefs->getString("/tools/measure/unit");
+ if (!unit_name.compare("")) {
+ unit_name = "px";
+ }
+ double fontsize = prefs->getDouble("/tools/measure/fontsize", 10.0);
+ int precision = prefs->getInt("/tools/measure/precision", 2);
+ std::stringstream precision_str;
+ precision_str.imbue(std::locale::classic());
+ precision_str << "%." << precision << "f %s";
+ Geom::Point middle = Geom::middle_point(start, end);
+ double totallengthval = (end_p - start_p).length();
+ totallengthval = Inkscape::Util::Quantity::convert(totallengthval, "px", unit_name);
+ double scale = prefs->getDouble("/tools/measure/scale", 100.0) / 100.0;
+ gchar *totallength_str = g_strdup_printf(precision_str.str().c_str(), totallengthval * scale, unit_name.c_str());
+ setLabelText(totallength_str, middle, fontsize, Geom::rad_from_deg(180) - ray.angle(), color);
+ g_free(totallength_str);
+ doc->ensureUpToDate();
+ DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MEASURE,_("Add global measure line"));
+}
- double fontsize = prefs->getInt("/tools/measure/fontsize");
+void MeasureTool::setGuide(Geom::Point origin,double angle, const char *label)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SPDocument *doc = desktop->getDocument();
+ Inkscape::XML::Document *xml_doc = doc->getReprDoc();
+ SPRoot const *root = doc->getRoot();
+ Geom::Affine affine(Geom::identity());
+ if(root) {
+ affine *= root->c2p.inverse();
+ }
+ SPNamedView *namedview = desktop->namedview;
+ if(!namedview) {
+ return;
+ }
+ origin *= affine;
+ //measure angle
+ Inkscape::XML::Node *guide;
+ guide = xml_doc->createElement("sodipodi:guide");
+ std::stringstream position;
+ position.imbue(std::locale::classic());
+ position << origin[Geom::X] << "," << origin[Geom::Y];
+ guide->setAttribute("position", position.str().c_str() );
+ guide->setAttribute("inkscape:color", "rgb(167,0,255)");
+ guide->setAttribute("inkscape:label", label);
+ Geom::Point unit_vector = Geom::rot90(origin.polar(angle));
+ std::stringstream angle_str;
+ angle_str.imbue(std::locale::classic());
+ angle_str << unit_vector[Geom::X] << "," << unit_vector[Geom::Y];
+ guide->setAttribute("orientation", angle_str.str().c_str());
+ namedview->appendChild(guide);
+ Inkscape::GC::release(guide);
+}
- // Normal will be used for lines and text
- Geom::Point windowNormal = Geom::unit_vector(Geom::rot90(desktop->d2w(end_point - start_point)));
- Geom::Point normal = desktop->w2d(windowNormal);
+void MeasureTool::setLine(Geom::Point start_point,Geom::Point end_point, bool markers, guint32 color, Inkscape::XML::Node *measure_repr)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if(!desktop || !start_p.isFinite() || !end_p.isFinite()) {
+ return;
+ }
+ Geom::PathVector pathv;
+ Geom::Path path;
+ path.start(desktop->doc2dt(start_point));
+ path.appendNew<Geom::LineSegment>(desktop->doc2dt(end_point));
+ pathv.push_back(path);
+ pathv *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
+ if(!pathv.empty()) {
+ setMeasureItem(pathv, false, markers, color, measure_repr);
+ }
+}
- std::vector<Geom::Point> intersections;
- std::sort(intersection_times.begin(), intersection_times.end());
- for (std::vector<double>::iterator iter_t = intersection_times.begin(); iter_t != intersection_times.end(); iter_t++) {
- intersections.push_back(lineseg[0].pointAt(*iter_t));
- }
+void MeasureTool::setPoint(Geom::Point origin, Inkscape::XML::Node *measure_repr)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if(!desktop || !origin.isFinite()) {
+ return;
+ }
+ char const * svgd;
+ svgd = "m 0.707,0.707 6.586,6.586 m 0,-6.586 -6.586,6.586";
+ Geom::PathVector pathv = sp_svg_read_pathv(svgd);
+ Geom::Scale scale = Geom::Scale(desktop->current_zoom()).inverse();
+ pathv *= Geom::Translate(Geom::Point(-3.5,-3.5));
+ pathv *= scale;
+ pathv *= Geom::Translate(Geom::Point() - (scale.vector() * 0.5));
+ pathv *= Geom::Translate(desktop->doc2dt(origin));
+ pathv *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
+ if (!pathv.empty()) {
+ guint32 line_color_secondary = 0xff0000ff;
+ setMeasureItem(pathv, false, false, line_color_secondary, measure_repr);
+ }
+}
- std::vector<LabelPlacement> placements;
- for (size_t idx = 1; idx < intersections.size(); ++idx) {
- LabelPlacement placement;
- placement.lengthVal = (intersections[idx] - intersections[idx - 1]).length();
- placement.lengthVal = Inkscape::Util::Quantity::convert(placement.lengthVal, "px", unit_name);
- placement.offset = DIMENSION_OFFSET;
- placement.start = desktop->doc2dt( (intersections[idx - 1] + intersections[idx]) / 2 );
- placement.end = placement.start - (normal * placement.offset);
+void MeasureTool::setLabelText(const char *value, Geom::Point pos, double fontsize, Geom::Coord angle, guint32 background, Inkscape::XML::Node *measure_repr, CanvasTextAnchorPositionEnum text_anchor)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
+ /* Create <text> */
+ pos = desktop->doc2dt(pos);
+ Inkscape::XML::Node *rtext = xml_doc->createElement("svg:text");
+ rtext->setAttribute("xml:space", "preserve");
+
+
+ /* Set style */
+ sp_desktop_apply_style_tool(desktop, rtext, "/tools/text", true);
+ if(measure_repr) {
+ sp_repr_set_svg_double(rtext, "x", 2);
+ sp_repr_set_svg_double(rtext, "y", 2);
+ } else {
+ sp_repr_set_svg_double(rtext, "x", 0);
+ sp_repr_set_svg_double(rtext, "y", 0);
+ }
- placements.push_back(placement);
- }
+ /* Create <tspan> */
+ Inkscape::XML::Node *rtspan = xml_doc->createElement("svg:tspan");
+ rtspan->setAttribute("sodipodi:role", "line");
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ std::stringstream font_size;
+ font_size.imbue(std::locale::classic());
+ if(measure_repr) {
+ font_size << fontsize;
+ } else {
+ font_size << fontsize << "pt";
+ }
+ sp_repr_css_set_property (css, "font-size", font_size.str().c_str());
+ sp_repr_css_set_property (css, "font-style", "normal");
+ sp_repr_css_set_property (css, "font-weight", "normal");
+ sp_repr_css_set_property (css, "line-height", "125%");
+ sp_repr_css_set_property (css, "letter-spacing", "0");
+ sp_repr_css_set_property (css, "word-spacing", "0");
+ sp_repr_css_set_property (css, "text-align", "center");
+ sp_repr_css_set_property (css, "text-anchor", "middle");
+ if(measure_repr) {
+ sp_repr_css_set_property (css, "fill", "#FFFFFF");
+ } else {
+ sp_repr_css_set_property (css, "fill", "#000000");
+ }
+ sp_repr_css_set_property (css, "fill-opacity", "1");
+ sp_repr_css_set_property (css, "stroke", "none");
+ Glib::ustring css_str;
+ sp_repr_css_write_string(css,css_str);
+ rtspan->setAttribute("style", css_str.c_str());
+ sp_repr_css_attr_unref (css);
+ rtext->addChild(rtspan, NULL);
+ Inkscape::GC::release(rtspan);
+ /* Create TEXT */
+ Inkscape::XML::Node *rstring = xml_doc->createTextNode(value);
+ rtspan->addChild(rstring, NULL);
+ Inkscape::GC::release(rstring);
+ SPItem *text_item = SP_ITEM(desktop->currentLayer()->appendChildRepr(rtext));
+ Inkscape::GC::release(rtext);
+ text_item->updateRepr();
+ Geom::OptRect bbox = text_item->geometricBounds();
+ if (!measure_repr && bbox) {
+ Geom::Point center = bbox->midpoint();
+ text_item->transform *= Geom::Translate(center).inverse();
+ pos += Geom::Point::polar(angle+ Geom::rad_from_deg(90), -bbox->height());
+ }
+ if(measure_repr) {
+ /* Create <group> */
+ Inkscape::XML::Node *rgroup = xml_doc->createElement("svg:g");
+ /* Create <rect> */
+ Inkscape::XML::Node *rrect = xml_doc->createElement("svg:rect");
+ SPCSSAttr *css = sp_repr_css_attr_new ();
+ gchar color_line[64];
+ sp_svg_write_color (color_line, sizeof(color_line), background);
+ sp_repr_css_set_property (css, "fill", color_line);
+ sp_repr_css_set_property (css, "fill-opacity", "0.5");
+ sp_repr_css_set_property (css, "stroke-width", "0");
+ Glib::ustring css_str;
+ sp_repr_css_write_string(css,css_str);
+ rrect->setAttribute("style", css_str.c_str());
+ sp_repr_css_attr_unref (css);
+ sp_repr_set_svg_double(rgroup, "x", 0);
+ sp_repr_set_svg_double(rgroup, "y", 0);
+ sp_repr_set_svg_double(rrect, "x", -bbox->width()/2.0);
+ sp_repr_set_svg_double(rrect, "y", -bbox->height());
+ sp_repr_set_svg_double(rrect, "width", bbox->width() + 6);
+ sp_repr_set_svg_double(rrect, "height", bbox->height() + 6);
+ Inkscape::XML::Node *rtextitem = text_item->getRepr();
+ text_item->deleteObject();
+ rgroup->addChild(rtextitem, NULL);
+ Inkscape::GC::release(rtextitem);
+ rgroup->addChild(rrect, NULL);
+ Inkscape::GC::release(rrect);
+ SPItem *text_item_box = SP_ITEM(desktop->currentLayer()->appendChildRepr(rgroup));
+ Geom::Scale scale = Geom::Scale(desktop->current_zoom()).inverse();
+ if(bbox && text_anchor == TEXT_ANCHOR_CENTER) {
+ text_item_box->transform *= Geom::Translate(bbox->midpoint() - Geom::Point(1.0,1.0)).inverse();
+ }
+ text_item_box->transform *= scale;
+ text_item_box->transform *= Geom::Translate(Geom::Point() - (scale.vector() * 0.5));
+ text_item_box->transform *= Geom::Translate(pos);
+ text_item_box->transform *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
+ text_item_box->updateRepr();
+ text_item_box->doWriteTransform(text_item_box->getRepr(), text_item_box->transform, NULL, true);
+ Inkscape::XML::Node *rlabel = text_item_box->getRepr();
+ text_item_box->deleteObject();
+ measure_repr->addChild(rlabel, NULL);
+ Inkscape::GC::release(rlabel);
+ } else {
+ text_item->transform *= Geom::Rotate(angle);
+ text_item->transform *= Geom::Translate(pos);
+ text_item->transform *= SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
+ text_item->doWriteTransform(text_item->getRepr(), text_item->transform, NULL, true);
+ }
+}
- // Adjust positions
- repositionOverlappingLabels(placements, desktop, windowNormal, fontsize);
-
- for (std::vector<LabelPlacement>::iterator it = placements.begin(); it != placements.end(); ++it)
- {
- LabelPlacement &place = *it;
-
- // TODO cleanup memory, Glib::ustring, etc.:
- gchar *measure_str = g_strdup_printf("%.2f %s", place.lengthVal, unit_name.c_str());
- SPCanvasText *canvas_tooltip = sp_canvastext_new(desktop->getTempGroup(),
- desktop,
- place.end,
- measure_str);
- sp_canvastext_set_fontsize(canvas_tooltip, fontsize);
- canvas_tooltip->rgba = 0xffffffff;
- canvas_tooltip->rgba_background = 0x0000007f;
- canvas_tooltip->outline = false;
- canvas_tooltip->background = true;
- canvas_tooltip->anchor_position = TEXT_ANCHOR_CENTER;
-
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvas_tooltip, 0));
- g_free(measure_str);
- }
+void MeasureTool::reset()
+{
+ this->knot_start->hide();
+ this->knot_end->hide();
+ for (size_t idx = 0; idx < measure_tmp_items.size(); ++idx) {
+ sp_canvas_item_destroy(measure_tmp_items[idx]);
+ }
+ measure_tmp_items.clear();
+}
- Geom::Point angleDisplayPt = calcAngleDisplayAnchor(desktop, angle, baseAngle,
- start_point, end_point,
- fontsize);
-
- {
- // TODO cleanup memory, Glib::ustring, etc.:
- gchar *angle_str = g_strdup_printf("%.2f °", angle * 180/M_PI);
-
- SPCanvasText *canvas_tooltip = sp_canvastext_new(desktop->getTempGroup(),
- desktop,
- angleDisplayPt,
- angle_str);
- sp_canvastext_set_fontsize(canvas_tooltip, fontsize);
- canvas_tooltip->rgba = 0xffffffff;
- canvas_tooltip->rgba_background = 0x337f337f;
- canvas_tooltip->outline = false;
- canvas_tooltip->background = true;
- canvas_tooltip->anchor_position = TEXT_ANCHOR_CENTER;
-
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvas_tooltip, 0));
- g_free(angle_str);
- }
+void MeasureTool::setMeasureCanvasText(bool is_angle, double precision, double amount, double fontsize, Glib::ustring unit_name, Geom::Point position, guint32 background, CanvasTextAnchorPositionEnum text_anchor, bool to_item, bool to_phantom, Inkscape::XML::Node *measure_repr)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ std::stringstream precision_str;
+ precision_str.imbue(std::locale::classic());
+ if(is_angle){
+ precision_str << "%." << precision << "f °";
+ } else {
+ precision_str << "%." << precision << "f %s";
+ }
+ gchar *measure_str = g_strdup_printf(precision_str.str().c_str(), amount, unit_name.c_str());
+ SPCanvasText *canvas_tooltip = sp_canvastext_new(desktop->getTempGroup(),
+ desktop,
+ position,
+ measure_str);
+ sp_canvastext_set_fontsize(canvas_tooltip, fontsize);
+ canvas_tooltip->rgba = 0xffffffff;
+ canvas_tooltip->rgba_background = background;
+ canvas_tooltip->outline = false;
+ canvas_tooltip->background = true;
+ canvas_tooltip->anchor_position = text_anchor;
+ if(to_phantom){
+ canvas_tooltip->rgba_background = 0x4444447f;
+ measure_phantom_items.push_back(SP_CANVAS_ITEM(canvas_tooltip));
+ sp_canvas_item_show(SP_CANVAS_ITEM(canvas_tooltip));
+ } else {
+ measure_tmp_items.push_back(SP_CANVAS_ITEM(canvas_tooltip));
+ sp_canvas_item_show(SP_CANVAS_ITEM(canvas_tooltip));
+ }
- {
- double totallengthval = (end_point - start_point).length();
- totallengthval = Inkscape::Util::Quantity::convert(totallengthval, "px", unit_name);
-
- // TODO cleanup memory, Glib::ustring, etc.:
- gchar *totallength_str = g_strdup_printf("%.2f %s", totallengthval, unit_name.c_str());
- SPCanvasText *canvas_tooltip = sp_canvastext_new(desktop->getTempGroup(),
- desktop,
- end_point + desktop->w2d(Geom::Point(3*fontsize, -fontsize)),
- totallength_str);
- sp_canvastext_set_fontsize(canvas_tooltip, fontsize);
- canvas_tooltip->rgba = 0xffffffff;
- canvas_tooltip->rgba_background = 0x3333337f;
- canvas_tooltip->outline = false;
- canvas_tooltip->background = true;
- canvas_tooltip->anchor_position = TEXT_ANCHOR_LEFT;
-
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvas_tooltip, 0));
- g_free(totallength_str);
- }
+ if(to_item) {
+ setLabelText(measure_str, position, fontsize, 0, background, measure_repr);
+ }
+ g_free(measure_str);
+}
- if (intersections.size() > 2) {
- double totallengthval = (intersections[intersections.size()-1] - intersections[0]).length();
- totallengthval = Inkscape::Util::Quantity::convert(totallengthval, "px", unit_name);
-
- // TODO cleanup memory, Glib::ustring, etc.:
- gchar *total_str = g_strdup_printf("%.2f %s", totallengthval, unit_name.c_str());
- SPCanvasText *canvas_tooltip = sp_canvastext_new(desktop->getTempGroup(),
- desktop,
- desktop->doc2dt((intersections[0] + intersections[intersections.size()-1])/2) + normal * 60,
- total_str);
- sp_canvastext_set_fontsize(canvas_tooltip, fontsize);
- canvas_tooltip->rgba = 0xffffffff;
- canvas_tooltip->rgba_background = 0x33337f7f;
- canvas_tooltip->outline = false;
- canvas_tooltip->background = true;
- canvas_tooltip->anchor_position = TEXT_ANCHOR_CENTER;
-
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvas_tooltip, 0));
- g_free(total_str);
- }
+void MeasureTool::setMeasureCanvasItem(Geom::Point position, bool to_item, bool to_phantom, Inkscape::XML::Node *measure_repr){
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ guint32 color = 0xff0000ff;
+ if(to_phantom){
+ color = 0x888888ff;
+ }
+ SPCanvasItem * canvasitem = sp_canvas_item_new(desktop->getTempGroup(),
+ SP_TYPE_CTRL,
+ "anchor", SP_ANCHOR_CENTER,
+ "size", 8.0,
+ "stroked", TRUE,
+ "stroke_color", color,
+ "mode", SP_KNOT_MODE_XOR,
+ "shape", SP_KNOT_SHAPE_CROSS,
+ NULL );
+
+ SP_CTRL(canvasitem)->moveto(position);
+ if(to_phantom){
+ measure_phantom_items.push_back(canvasitem);
+ } else {
+ measure_tmp_items.push_back(canvasitem);
+ }
+ sp_canvas_item_show(canvasitem);
+ sp_canvas_item_move_to_z(canvasitem, 0);
+
+ if(to_item) {
+ setPoint(position, measure_repr);
+ }
+}
- // Now that text has been added, we can add lines and controls so that they go underneath
-
- for (size_t idx = 0; idx < intersections.size(); ++idx) {
- // Display the intersection indicator (i.e. the cross)
- SPCanvasItem * canvasitem = sp_canvas_item_new(desktop->getTempGroup(),
- SP_TYPE_CTRL,
- "anchor", SP_ANCHOR_CENTER,
- "size", 8.0,
- "stroked", TRUE,
- "stroke_color", 0xff0000ff,
- "mode", SP_KNOT_MODE_XOR,
- "shape", SP_KNOT_SHAPE_CROSS,
- NULL );
-
- SP_CTRL(canvasitem)->moveto(desktop->doc2dt(intersections[idx]));
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvasitem, 0));
- }
+void MeasureTool::setMeasureCanvasControlLine(Geom::Point start, Geom::Point end, bool to_item, bool to_phantom, Inkscape::CtrlLineType ctrl_line_type, Inkscape::XML::Node *measure_repr){
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ gint32 color = ctrl_line_type == CTLINE_PRIMARY ? 0x0000ff7f : 0xff00007f;
+ if(to_phantom){
+ color = ctrl_line_type == CTLINE_PRIMARY ? 0x4444447f : 0x8888887f;
+ }
+ SPCtrlLine *control_line = ControlManager::getManager().createControlLine(desktop->getTempGroup(),
+ start,
+ end,
+ ctrl_line_type);
+ control_line->rgba = color;
+ if(to_phantom){
+ measure_phantom_items.push_back(SP_CANVAS_ITEM(control_line));
+ } else {
+ measure_tmp_items.push_back(SP_CANVAS_ITEM(control_line));
+ }
+ sp_canvas_item_move_to_z(SP_CANVAS_ITEM(control_line), 0);
+ sp_canvas_item_show(SP_CANVAS_ITEM(control_line));
+ if(to_item) {
+ setLine(start,
+ end,
+ false,
+ color,
+ measure_repr);
+ }
+}
+
+void MeasureTool::showCanvasItems(bool to_guides, bool to_item, bool to_phantom, Inkscape::XML::Node *measure_repr)
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if(!desktop || !start_p.isFinite() || !end_p.isFinite() || start_p == end_p) {
+ return;
+ }
+ writeMeasurePoint(start_p, true);
+ writeMeasurePoint(end_p, false);
+ //clear previous canvas items, we'll draw new ones
+ for (size_t idx = 0; idx < measure_tmp_items.size(); ++idx) {
+ sp_canvas_item_destroy(measure_tmp_items[idx]);
+ }
+ measure_tmp_items.clear();
+ //TODO:Calculate the measure area for current lenght and origin
+ // and use canvas->requestRedraw. In the calculation need a gap for outside text
+ // maybe this remove the trash lines on measure use
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ bool show_in_between = prefs->getBool("/tools/measure/show_in_between", true);
+ bool all_layers = prefs->getBool("/tools/measure/all_layers", true);
+ dimension_offset = 70;
+ Geom::PathVector lineseg;
+ Geom::Path p;
+ p.start(desktop->dt2doc(start_p));
+ p.appendNew<Geom::LineSegment>(desktop->dt2doc(end_p));
+ lineseg.push_back(p);
+
+ double angle = atan2(end_p - start_p);
+ double baseAngle = 0;
+
+ if (explicit_base) {
+ baseAngle = atan2(explicit_base.get() - start_p);
+ angle -= baseAngle;
+ }
- // Since adding goes to the bottom, do all lines last.
-
- // draw main control line
- {
- SPCtrlLine *control_line = ControlManager::getManager().createControlLine(desktop->getTempGroup(),
- start_point,
- end_point);
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
-
- if ((end_point[Geom::X] != start_point[Geom::X]) && (end_point[Geom::Y] != start_point[Geom::Y])) {
- double length = std::abs((end_point - start_point).length());
- Geom::Point anchorEnd = start_point;
- anchorEnd[Geom::X] += length;
- if (explicitBase) {
- anchorEnd *= (Geom::Affine(Geom::Translate(-start_point))
- * Geom::Affine(Geom::Rotate(baseAngle))
- * Geom::Affine(Geom::Translate(start_point)));
+ std::vector<SPItem*> items;
+ SPDocument *doc = desktop->getDocument();
+ Geom::Rect rect(start_p, end_p);
+ items = doc->getItemsPartiallyInBox(desktop->dkey, rect, true);
+ Inkscape::LayerModel *layer_model = NULL;
+ SPObject *current_layer = NULL;
+ if(desktop){
+ layer_model = desktop->layers;
+ current_layer = desktop->currentLayer();
+ }
+ std::vector<double> intersection_times;
+ for (std::vector<SPItem*>::const_iterator i=items.begin(); i!=items.end(); ++i) {
+ SPItem *item = *i;
+ if(all_layers || (layer_model && layer_model->layerForObject(item) == current_layer)){
+ if (SP_IS_SHAPE(item)) {
+ calculate_intersections(desktop, item, lineseg, SP_SHAPE(item)->getCurve(), intersection_times);
+ } else {
+ if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
+ Inkscape::Text::Layout::iterator iter = te_get_layout(item)->begin();
+ do {
+ Inkscape::Text::Layout::iterator iter_next = iter;
+ iter_next.nextGlyph(); // iter_next is one glyph ahead from iter
+ if (iter == iter_next) {
+ break;
}
- SPCtrlLine *control_line = ControlManager::getManager().createControlLine(desktop->getTempGroup(),
- start_point,
- anchorEnd,
- CTLINE_SECONDARY);
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
+ // get path from iter to iter_next:
+ SPCurve *curve = te_get_layout(item)->convertToCurves(iter, iter_next);
+ iter = iter_next; // shift to next glyph
+ if (!curve) {
+ continue; // error converting this glyph
+ }
+ if (curve->is_empty()) { // whitespace glyph?
+ curve->unref();
+ continue;
+ }
- createAngleDisplayCurve(desktop, start_point, end_point, angleDisplayPt, angle);
- }
- }
+ curve->transform(item->i2doc_affine());
- if (intersections.size() > 2) {
- ControlManager &mgr = ControlManager::getManager();
- SPCtrlLine *control_line = 0;
- control_line = mgr.createControlLine(desktop->getTempGroup(),
- desktop->doc2dt(intersections[0]) + normal * 60,
- desktop->doc2dt(intersections[intersections.size() - 1]) + normal * 60);
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
-
- control_line = mgr.createControlLine(desktop->getTempGroup(),
- desktop->doc2dt(intersections[0]),
- desktop->doc2dt(intersections[0]) + normal * 65);
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
-
- control_line = mgr.createControlLine(desktop->getTempGroup(),
- desktop->doc2dt(intersections[intersections.size() - 1]),
- desktop->doc2dt(intersections[intersections.size() - 1]) + normal * 65);
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
+ calculate_intersections(desktop, item, lineseg, curve, intersection_times);
+ if (iter == te_get_layout(item)->end()) {
+ break;
+ }
+ } while (true);
}
+ }
+ }
+ }
+ Glib::ustring unit_name = prefs->getString("/tools/measure/unit");
+ if (!unit_name.compare("")) {
+ unit_name = "px";
+ }
+ double scale = prefs->getDouble("/tools/measure/scale", 100.0) / 100.0;
+ double fontsize = prefs->getDouble("/tools/measure/fontsize", 10.0);
+ // Normal will be used for lines and text
+ Geom::Point windowNormal = Geom::unit_vector(Geom::rot90(desktop->d2w(end_p - start_p)));
+ Geom::Point normal = desktop->w2d(windowNormal);
+
+ std::vector<Geom::Point> intersections;
+ std::sort(intersection_times.begin(), intersection_times.end());
+ for (std::vector<double>::iterator iter_t = intersection_times.begin(); iter_t != intersection_times.end(); ++iter_t) {
+ intersections.push_back(lineseg[0].pointAt(*iter_t));
+ }
- // call-out lines
- for (std::vector<LabelPlacement>::iterator it = placements.begin(); it != placements.end(); ++it)
- {
- LabelPlacement &place = *it;
-
- ControlManager &mgr = ControlManager::getManager();
- SPCtrlLine *control_line = mgr.createControlLine(desktop->getTempGroup(),
- place.start,
- place.end,
- CTLINE_SECONDARY);
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
- }
+ if(!show_in_between && intersection_times.size() > 1) {
+ Geom::Point start = lineseg[0].pointAt(intersection_times[0]);
+ Geom::Point end = lineseg[0].pointAt(intersection_times[intersection_times.size()-1]);
+ intersections.clear();
+ intersections.push_back(start);
+ intersections.push_back(end);
+ }
+ if (!prefs->getBool("/tools/measure/ignore_1st_and_last", true)) {
+ intersections.insert(intersections.begin(),lineseg[0].pointAt(0));
+ intersections.push_back(lineseg[0].pointAt(1));
+ }
+ std::vector<LabelPlacement> placements;
+ for (size_t idx = 1; idx < intersections.size(); ++idx) {
+ LabelPlacement placement;
+ placement.lengthVal = (intersections[idx] - intersections[idx - 1]).length();
+ placement.lengthVal = Inkscape::Util::Quantity::convert(placement.lengthVal, "px", unit_name);
+ placement.offset = dimension_offset / 2;
+ placement.start = desktop->doc2dt( (intersections[idx - 1] + intersections[idx]) / 2 );
+ placement.end = placement.start - (normal * placement.offset);
+
+ placements.push_back(placement);
+ }
+ int precision = prefs->getInt("/tools/measure/precision", 2);
+ // Adjust positions
+ repositionOverlappingLabels(placements, desktop, windowNormal, fontsize, precision);
+ for (std::vector<LabelPlacement>::iterator it = placements.begin(); it != placements.end(); ++it) {
+ LabelPlacement &place = *it;
+
+ setMeasureCanvasText(false, precision, place.lengthVal * scale, fontsize, unit_name, place.end, 0x0000007f, TEXT_ANCHOR_CENTER, to_item, to_phantom, measure_repr);
+ }
+ Geom::Point angleDisplayPt = calcAngleDisplayAnchor(desktop, angle, baseAngle,
+ start_p, end_p,
+ fontsize);
+ {
+ setMeasureCanvasText(true, precision, Geom::deg_from_rad(angle), fontsize, unit_name, angleDisplayPt, 0x337f337f, TEXT_ANCHOR_CENTER, to_item, to_phantom, measure_repr);
+ }
- {
- for (size_t idx = 1; idx < intersections.size(); ++idx) {
- Geom::Point measure_text_pos = (intersections[idx - 1] + intersections[idx]) / 2;
-
- ControlManager &mgr = ControlManager::getManager();
- SPCtrlLine *control_line = mgr.createControlLine(desktop->getTempGroup(),
- desktop->doc2dt(measure_text_pos),
- desktop->doc2dt(measure_text_pos) - (normal * DIMENSION_OFFSET),
- CTLINE_SECONDARY);
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(control_line, 0));
- }
- }
+ {
+ double totallengthval = (end_p - start_p).length();
+ totallengthval = Inkscape::Util::Quantity::convert(totallengthval, "px", unit_name);
+ Geom::Point origin = end_p + desktop->w2d(Geom::Point(3*fontsize, -fontsize));
+ setMeasureCanvasText(false, precision, totallengthval * scale, fontsize, unit_name, origin, 0x3333337f, TEXT_ANCHOR_LEFT, to_item, to_phantom, measure_repr);
+ }
- // Initial point
- {
- SPCanvasItem * canvasitem = sp_canvas_item_new(desktop->getTempGroup(),
- SP_TYPE_CTRL,
- "anchor", SP_ANCHOR_CENTER,
- "size", 8.0,
- "stroked", TRUE,
- "stroke_color", 0xff0000ff,
- "mode", SP_KNOT_MODE_XOR,
- "shape", SP_KNOT_SHAPE_CROSS,
- NULL );
-
- SP_CTRL(canvasitem)->moveto(start_point);
- measure_tmp_items.push_back(desktop->add_temporary_canvasitem(canvasitem, 0));
- }
+ if (intersections.size() > 2) {
+ double totallengthval = (intersections[intersections.size()-1] - intersections[0]).length();
+ totallengthval = Inkscape::Util::Quantity::convert(totallengthval, "px", unit_name);
+ Geom::Point origin = desktop->doc2dt((intersections[0] + intersections[intersections.size()-1])/2) + normal * dimension_offset;
+ setMeasureCanvasText(false, precision, totallengthval * scale, fontsize, unit_name, origin, 0x33337f7f, TEXT_ANCHOR_CENTER, to_item, to_phantom, measure_repr);
+ }
- lastEnd = end_point; // track in case we get a anchoring key-press later
+ // Initial point
+ {
+ setMeasureCanvasItem(start_p, false, to_phantom, measure_repr);
+ }
- gobble_motion_events(GDK_BUTTON1_MASK);
+ // Now that text has been added, we can add lines and controls so that they go underneath
+ for (size_t idx = 0; idx < intersections.size(); ++idx) {
+ setMeasureCanvasItem(desktop->doc2dt(intersections[idx]), to_item, to_phantom, measure_repr);
+ if(to_guides) {
+ gchar *cross_number;
+ if (!prefs->getBool("/tools/measure/ignore_1st_and_last", true)) {
+ cross_number= g_strdup_printf(_("Crossing %u"), idx);
+ } else {
+ cross_number= g_strdup_printf(_("Crossing %u"), idx + 1);
}
- break;
- }
- case GDK_BUTTON_RELEASE: {
- sp_event_context_discard_delayed_snap_event(this);
- explicitBase = boost::none;
- lastEnd = boost::none;
-
- //clear all temporary canvas items related to the measurement tool.
- for (size_t idx = 0; idx < measure_tmp_items.size(); ++idx) {
- desktop->remove_temporary_canvasitem(measure_tmp_items[idx]);
+ if (!prefs->getBool("/tools/measure/ignore_1st_and_last", true) && idx == 0) {
+ setGuide(desktop->doc2dt(intersections[idx]), angle + Geom::rad_from_deg(90), "");
+ } else {
+ setGuide(desktop->doc2dt(intersections[idx]), angle + Geom::rad_from_deg(90), cross_number);
}
+ g_free(cross_number);
+ }
+ }
+ // Since adding goes to the bottom, do all lines last.
- measure_tmp_items.clear();
+ // draw main control line
+ {
+ setMeasureCanvasControlLine(start_p, end_p, false, to_phantom, CTLINE_PRIMARY, measure_repr);
+ double length = std::abs((end_p - start_p).length());
+ Geom::Point anchorEnd = start_p;
+ anchorEnd[Geom::X] += length;
+ if (explicit_base) {
+ anchorEnd *= (Geom::Affine(Geom::Translate(-start_p))
+ * Geom::Affine(Geom::Rotate(baseAngle))
+ * Geom::Affine(Geom::Translate(start_p)));
+ }
+ setMeasureCanvasControlLine(start_p, anchorEnd, to_item, to_phantom, CTLINE_SECONDARY, measure_repr);
+ createAngleDisplayCurve(desktop, start_p, end_p, angleDisplayPt, angle, to_phantom, measure_phantom_items, measure_tmp_items, measure_repr);
+ }
- if (this->grabbed) {
- sp_canvas_item_ungrab(this->grabbed, event->button.time);
- this->grabbed = NULL;
- }
+ if (intersections.size() > 2) {
+ setMeasureCanvasControlLine(desktop->doc2dt(intersections[0]) + normal * dimension_offset, desktop->doc2dt(intersections[intersections.size() - 1]) + normal * dimension_offset, to_item, to_phantom, CTLINE_PRIMARY , measure_repr);
+
+ setMeasureCanvasControlLine(desktop->doc2dt(intersections[0]), desktop->doc2dt(intersections[0]) + normal * dimension_offset, to_item, to_phantom, CTLINE_PRIMARY , measure_repr);
- xp = 0;
- yp = 0;
- break;
- }
- default:
- break;
+ setMeasureCanvasControlLine(desktop->doc2dt(intersections[intersections.size() - 1]), desktop->doc2dt(intersections[intersections.size() - 1]) + normal * dimension_offset, to_item, to_phantom, CTLINE_PRIMARY , measure_repr);
}
- if (!ret) {
- ret = ToolBase::root_handler(event);
+ // call-out lines
+ for (std::vector<LabelPlacement>::iterator it = placements.begin(); it != placements.end(); ++it) {
+ LabelPlacement &place = *it;
+ setMeasureCanvasControlLine(place.start, place.end, to_item, to_phantom, CTLINE_SECONDARY, measure_repr);
}
- return ret;
+ {
+ for (size_t idx = 1; idx < intersections.size(); ++idx) {
+ Geom::Point measure_text_pos = (intersections[idx - 1] + intersections[idx]) / 2;
+ setMeasureCanvasControlLine(desktop->doc2dt(measure_text_pos), desktop->doc2dt(measure_text_pos) - (normal * dimension_offset / 2), to_item, to_phantom, CTLINE_SECONDARY, measure_repr);
+ }
+ }
}
}
diff --git a/src/ui/tools/measure-tool.h b/src/ui/tools/measure-tool.h
index 9701ba6ea..14fc9f81a 100644
--- a/src/ui/tools/measure-tool.h
+++ b/src/ui/tools/measure-tool.h
@@ -6,41 +6,83 @@
*
* Authors:
* Felipe Correa da Silva Sanches <juca@members.fsf.org>
- *
+ * Jabiertxo Arraiza <jabier.arraiza@marker.es>
* Copyright (C) 2011 Authors
*
* 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>
#include "ui/tools/tool-base.h"
#include <2geom/point.h>
+#include "display/canvas-text.h"
+#include "display/canvas-temporary-item.h"
+#include "ui/control-manager.h"
#include <boost/optional.hpp>
#define SP_MEASURE_CONTEXT(obj) (dynamic_cast<Inkscape::UI::Tools::MeasureTool*>((Inkscape::UI::Tools::ToolBase*)obj))
#define SP_IS_MEASURE_CONTEXT(obj) (dynamic_cast<const Inkscape::UI::Tools::MeasureTool*>((const Inkscape::UI::Tools::ToolBase*)obj) != NULL)
+class SPKnot;
+
namespace Inkscape {
namespace UI {
namespace Tools {
class MeasureTool : public ToolBase {
public:
- MeasureTool();
- virtual ~MeasureTool();
-
- static const std::string prefsPath;
+ MeasureTool();
+ virtual ~MeasureTool();
- virtual void finish();
- virtual bool root_handler(GdkEvent* event);
-
- virtual const std::string& getPrefsPath();
+ static const std::string prefsPath;
+ virtual void finish();
+ virtual bool root_handler(GdkEvent* event);
+ virtual void showCanvasItems(bool to_guides = false, bool to_item = false, bool to_phantom = false, Inkscape::XML::Node *measure_repr = NULL);
+ virtual void reverseKnots();
+ virtual void toGuides();
+ virtual void toPhantom();
+ virtual void toMarkDimension();
+ virtual void toItem();
+ virtual void reset();
+ virtual void setMarkers();
+ virtual void setMarker(bool isStart);
+ virtual const std::string& getPrefsPath();
+ Geom::Point readMeasurePoint(bool is_start);
+ void writeMeasurePoint(Geom::Point point, bool is_start);
+ void setGuide(Geom::Point origin, double angle, const char *label);
+ void setPoint(Geom::Point origin, Inkscape::XML::Node *measure_repr);
+ void setLine(Geom::Point start_point,Geom::Point end_point, bool markers, guint32 color, Inkscape::XML::Node *measure_repr = NULL);
+ void setMeasureCanvasText(bool is_angle, double precision, double amount, double fontsize, Glib::ustring unit_name, Geom::Point position, guint32 background, CanvasTextAnchorPositionEnum text_anchor, bool to_item, bool to_phantom, Inkscape::XML::Node *measure_repr);
+ void setMeasureCanvasItem(Geom::Point position, bool to_item, bool to_phantom, Inkscape::XML::Node *measure_repr);
+ void setMeasureCanvasControlLine(Geom::Point start, Geom::Point end, bool to_item, bool to_phantom, Inkscape::CtrlLineType ctrl_line_type, Inkscape::XML::Node *measure_repr);
+ void setLabelText(const char *value, Geom::Point pos, double fontsize, Geom::Coord angle, guint32 background , Inkscape::XML::Node *measure_repr = NULL, CanvasTextAnchorPositionEnum text_anchor = TEXT_ANCHOR_CENTER );
+ void knotStartMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state);
+ void knotEndMovedHandler(SPKnot */*knot*/, Geom::Point const &ppointer, guint state);
+ void knotClickHandler(SPKnot *knot, guint state);
+ void knotUngrabbedHandler(SPKnot */*knot*/, unsigned int /*state*/);
private:
- SPCanvasItem* grabbed;
-
- Geom::Point start_point;
- boost::optional<Geom::Point> explicitBase;
- boost::optional<Geom::Point> lastEnd;
+ SPCanvasItem* grabbed;
+ boost::optional<Geom::Point> explicit_base;
+ boost::optional<Geom::Point> last_end;
+ SPKnot *knot_start;
+ SPKnot *knot_end;
+ gint dimension_offset;
+ Geom::Point start_p;
+ Geom::Point end_p;
+ std::vector<SPCanvasItem *> measure_tmp_items;
+ std::vector<SPCanvasItem *> measure_phantom_items;
+ sigc::connection _knot_start_moved_connection;
+ sigc::connection _knot_start_ungrabbed_connection;
+ sigc::connection _knot_start_click_connection;
+ sigc::connection _knot_end_moved_connection;
+ sigc::connection _knot_end_click_connection;
+ sigc::connection _knot_end_ungrabbed_connection;
};
}
@@ -48,3 +90,14 @@ private:
}
#endif // SEEN_SP_MEASURING_CONTEXT_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/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp
index 813d6ae5b..47927667c 100644
--- a/src/ui/tools/mesh-tool.cpp
+++ b/src/ui/tools/mesh-tool.cpp
@@ -57,7 +57,7 @@ namespace Inkscape {
namespace UI {
namespace Tools {
-static void sp_mesh_drag(MeshTool &rc, Geom::Point const pt, guint state, guint32 etime);
+static void sp_mesh_end_drag(MeshTool &rc);
const std::string& MeshTool::getPrefsPath() {
return MeshTool::prefsPath;
@@ -316,7 +316,7 @@ static void sp_mesh_context_split_near_point(MeshTool *rc, SPItem *item, Geom::
/**
Wrapper for various mesh operations that require a list of selected corner nodes.
*/
-static void
+void
sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation )
{
@@ -332,11 +332,11 @@ sp_mesh_context_corner_operation (MeshTool *rc, MeshCornerOperation operation )
// Get list of selected draggers for each mesh.
// For all selected draggers
- for (GList *i = drag->selected; i != NULL; i = i->next) {
- GrDragger *dragger = (GrDragger *) i->data;
+ for (std::set<GrDragger *>::const_iterator i = drag->selected.begin(); i != drag->selected.end(); ++i) {
+ GrDragger *dragger = *i;
// For all draggables of dragger
- for (GSList const* j = dragger->draggables; j != NULL; j = j->next) {
- GrDraggable *d = (GrDraggable *) j->data;
+ for (std::vector<GrDraggable *>::const_iterator j = dragger->draggables.begin(); j != dragger->draggables.end() ; ++j) {
+ GrDraggable *d = *j;
// Only mesh corners
if( d->point_type != POINT_MG_CORNER ) continue;
@@ -457,9 +457,9 @@ bool MeshTool::root_handler(GdkEvent* event) {
bool over_line = false;
SPCtrlCurve *line = NULL;
- if (drag->lines) {
- for (GSList *l = drag->lines; (l != NULL) && (!over_line); l = l->next) {
- line = (SPCtrlCurve*) l->data;
+ if (! drag->lines.empty()) {
+ for (std::vector<SPCtrlLine *>::const_iterator l = drag->lines.begin(); l != drag->lines.end() && (!over_line); ++l) {
+ line = (SPCtrlCurve*) (*l);
over_line |= sp_mesh_context_is_over_line (this, (SPItem*) line, Geom::Point(event->motion.x, event->motion.y));
}
}
@@ -471,7 +471,7 @@ bool MeshTool::root_handler(GdkEvent* event) {
} else {
// Create a new gradient with default coordinates.
std::vector<SPItem*> items=selection->itemList();
- for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();++i){
SPItem *item = *i;
SPGradientType new_type = SP_GRADIENT_TYPE_MESH;
Inkscape::PaintTarget fsmode = (prefs->getInt("/tools/gradient/newfillorstroke", 1) != 0) ? Inkscape::FOR_FILL : Inkscape::FOR_STROKE;
@@ -560,8 +560,9 @@ bool MeshTool::root_handler(GdkEvent* event) {
Inkscape::Rubberband::get(desktop)->move(motion_dt);
this->defaultMessageContext()->set(Inkscape::NORMAL_MESSAGE, _("<b>Draw around</b> handles to select them"));
} else {
- // Create new gradient with coordinates determined by drag.
- sp_mesh_drag(*this, motion_dt, event->motion.state, event->motion.time);
+ // Do nothing. For a linear/radial gradient we follow the drag, updating the
+ // gradient as the end node is dragged. For a mesh gradient, the gradient is always
+ // created to fill the object when the drag ends.
}
gobble_motion_events(GDK_BUTTON1_MASK);
@@ -592,9 +593,9 @@ bool MeshTool::root_handler(GdkEvent* event) {
// Change cursor shape if over line
bool over_line = false;
- if (drag->lines) {
- for (GSList *l = drag->lines; l != NULL; l = l->next) {
- over_line |= sp_mesh_context_is_over_line (this, (SPItem*) l->data, Geom::Point(event->motion.x, event->motion.y));
+ if (!drag->lines.empty()) {
+ for (std::vector<SPCtrlLine *>::const_iterator l = drag->lines.begin(); l != drag->lines.end() ; ++l) {
+ over_line |= sp_mesh_context_is_over_line (this, (SPItem*)(*l), Geom::Point(event->motion.x, event->motion.y));
}
}
@@ -623,9 +624,9 @@ bool MeshTool::root_handler(GdkEvent* event) {
bool over_line = false;
SPCtrlLine *line = NULL;
- if (drag->lines) {
- for (GSList *l = drag->lines; (l != NULL) && (!over_line); l = l->next) {
- line = (SPCtrlLine*) l->data;
+ if (!drag->lines.empty()) {
+ for (std::vector<SPCtrlLine *>::const_iterator l = drag->lines.begin(); l != drag->lines.end() && (!over_line); ++l) {
+ line = (SPCtrlLine*)(*l);
over_line = sp_mesh_context_is_over_line (this, (SPItem*) line, Geom::Point(event->motion.x, event->motion.y));
if (over_line) {
@@ -649,7 +650,7 @@ bool MeshTool::root_handler(GdkEvent* event) {
}
if (!this->within_tolerance) {
- // we've been dragging, either do nothing (grdrag handles that),
+ // we've been dragging, either create a new gradient
// or rubberband-select if we have rubberband
Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop);
@@ -659,6 +660,9 @@ bool MeshTool::root_handler(GdkEvent* event) {
Geom::OptRect const b = r->getRectangle();
drag->selectRect(*b);
}
+ } else {
+ // Create a new mesh gradient
+ sp_mesh_end_drag(*this);
}
} else if (this->item_to_select) {
if (over_line && line) {
@@ -674,7 +678,7 @@ bool MeshTool::root_handler(GdkEvent* event) {
}
} else {
// click in an empty space; do the same as Esc
- if (drag->selected) {
+ if (!drag->selected.empty()) {
drag->deselectAll();
} else {
selection->clear();
@@ -720,7 +724,7 @@ bool MeshTool::root_handler(GdkEvent* event) {
break;
case GDK_KEY_Escape:
- if (drag->selected) {
+ if (!drag->selected.empty()) {
drag->deselectAll();
} else {
selection->clear();
@@ -837,7 +841,7 @@ bool MeshTool::root_handler(GdkEvent* event) {
case GDK_KEY_Delete:
case GDK_KEY_KP_Delete:
case GDK_KEY_BackSpace:
- if ( drag->selected ) {
+ if ( !drag->selected.empty() ) {
std::cout << "Deleting mesh stops not implemented yet" << std::endl;
ret = TRUE;
}
@@ -922,7 +926,7 @@ bool MeshTool::root_handler(GdkEvent* event) {
return ret;
}
-static void sp_mesh_drag(MeshTool &rc, Geom::Point const /*pt*/, guint /*state*/, guint32 /*etime*/) {
+static void sp_mesh_end_drag(MeshTool &rc) {
SPDesktop *desktop = SP_EVENT_CONTEXT(&rc)->desktop;
Inkscape::Selection *selection = desktop->getSelection();
SPDocument *document = desktop->getDocument();
@@ -952,7 +956,7 @@ static void sp_mesh_drag(MeshTool &rc, Geom::Point const /*pt*/, guint /*state*/
sp_repr_css_set_property(css, "fill-opacity", "1.0");
std::vector<SPItem*> items=selection->itemList();
- for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();++i){
//FIXME: see above
sp_repr_css_change_recursive((*i)->getRepr(), css, "style");
@@ -963,19 +967,8 @@ static void sp_mesh_drag(MeshTool &rc, Geom::Point const /*pt*/, guint /*state*/
(*i)->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
- // if (ec->_grdrag) {
- // ec->_grdrag->updateDraggers();
- // // prevent regenerating draggers by selection modified signal, which sometimes
- // // comes too late and thus destroys the knot which we will now grab:
- // ec->_grdrag->local_change = true;
- // // give the grab out-of-bounds values of xp/yp because we're already dragging
- // // and therefore are already out of tolerance
- // ec->_grdrag->grabKnot (SP_ITEM(selection->itemList()->data),
- // type == SP_GRADIENT_TYPE_LINEAR? POINT_LG_END : POINT_RG_R1,
- // -1, // ignore number (though it is always 1)
- // fill_or_stroke, 99999, 99999, etime);
- // }
- // We did an undoable action, but SPDocumentUndo::done will be called by the knot when released
+
+ DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_MESH, _("Create mesh"));
// status text; we do not track coords because this branch is run once, not all the time
// during drag
diff --git a/src/ui/tools/mesh-tool.h b/src/ui/tools/mesh-tool.h
index d952c9010..91b35b3af 100644
--- a/src/ui/tools/mesh-tool.h
+++ b/src/ui/tools/mesh-tool.h
@@ -20,6 +20,7 @@
#include <stddef.h>
#include <sigc++/sigc++.h>
#include "ui/tools/tool-base.h"
+#include "sp-mesh-array.h"
#define SP_MESH_CONTEXT(obj) (dynamic_cast<Inkscape::UI::Tools::MeshTool*>((Inkscape::UI::Tools::ToolBase*)obj))
#define SP_IS_MESH_CONTEXT(obj) (dynamic_cast<const Inkscape::UI::Tools::MeshTool*>((const Inkscape::UI::Tools::ToolBase*)obj) != NULL)
@@ -57,6 +58,7 @@ private:
void sp_mesh_context_select_next(ToolBase *event_context);
void sp_mesh_context_select_prev(ToolBase *event_context);
+void sp_mesh_context_corner_operation(MeshTool *event_context, MeshCornerOperation operation );
}
}
diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp
index 6a6ca0b26..4149403ea 100644
--- a/src/ui/tools/node-tool.cpp
+++ b/src/ui/tools/node-tool.cpp
@@ -413,7 +413,7 @@ void NodeTool::selection_changed(Inkscape::Selection *sel) {
std::set<ShapeRecord> shapes;
std::vector<SPItem*> items=sel->itemList();
- for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();++i){
SPObject *obj = *i;
if (SP_IS_ITEM(obj)) {
@@ -495,7 +495,7 @@ bool NodeTool::root_handler(GdkEvent* event) {
// We will show a pre-snap indication for when the user adds a node through double-clicking
// Adding a node will only work when a path has been selected; if that's not the case then snapping is useless
- if (not this->desktop->selection->isEmpty()) {
+ if (!this->desktop->selection->isEmpty()) {
if (!(event->motion.state & GDK_SHIFT_MASK)) {
m.setup(this->desktop);
Inkscape::SnapCandidatePoint scp(motion_dt, Inkscape::SNAPSOURCE_OTHER_HANDLE);
@@ -678,7 +678,7 @@ void NodeTool::update_tip(GdkEvent *event) {
}
}
g_assert(positions.size() == 2);
- const double angle = Geom::rad_to_deg(Geom::Line(positions[0], positions[1]).angle());
+ const double angle = Geom::deg_from_rad(Geom::Line(positions[0], positions[1]).angle());
nodestring = g_strdup_printf("<b>%u of %u</b> nodes selected, angle: %.2f°.", sz, total, angle);
}
else {
diff --git a/src/ui/tools/pen-tool.cpp b/src/ui/tools/pen-tool.cpp
index 827dbf5c3..2ed366a7d 100644
--- a/src/ui/tools/pen-tool.cpp
+++ b/src/ui/tools/pen-tool.cpp
@@ -84,7 +84,7 @@ namespace Tools {
static Geom::Point pen_drag_origin_w(0, 0);
static bool pen_within_tolerance = false;
static int pen_last_paraxial_dir = 0; // last used direction in horizontal/vertical mode; 0 = horizontal, 1 = vertical
-const double HANDLE_CUBIC_GAP = 0.01;
+const double HANDLE_CUBIC_GAP = 0.001;
const std::string& PenTool::getPrefsPath() {
return PenTool::prefsPath;
@@ -268,6 +268,9 @@ void PenTool::_endpointSnap(Geom::Point &p, guint const state) const {
if ((state & GDK_CONTROL_MASK) && !this->polylines_paraxial) { //CTRL enables angular snapping
if (this->npoints > 0) {
spdc_endpoint_snap_rotation(this, p, this->p[0], state);
+ } else {
+ boost::optional<Geom::Point> origin = boost::optional<Geom::Point>();
+ spdc_endpoint_snap_free(this, p, origin, state);
}
} else {
// We cannot use shift here to disable snapping because the shift-key is already used
@@ -379,11 +382,12 @@ bool PenTool::_handleButtonPress(GdkEventButton const &bevent) {
if( anchor && anchor == this->sa && this->green_curve->is_empty()){
//remove the following line to avoid having one node on top of another
_finishSegment(event_dt, bevent.state);
- _finish( false);
+ _finish(true);
return true;
}
return false;
}
+
bool ret = false;
if (bevent.button == 1 && !this->space_panning
// make sure this is not the last click for a waiting LPE (otherwise we want to finish the path)
@@ -857,7 +861,7 @@ bool PenTool::_handleButtonRelease(GdkEventButton const &revent) {
bool PenTool::_handle2ButtonPress(GdkEventButton const &bevent) {
bool ret = false;
// only end on LMB double click. Otherwise horizontal scrolling causes ending of the path
- if (this->npoints != 0 && bevent.button == 1) {
+ if (this->npoints != 0 && bevent.button == 1 && this->state != PenTool::CLOSE) {
this->_finish(false);
ret = true;
}
@@ -1714,9 +1718,9 @@ void PenTool::_bsplineSpiroBuild()
//Effect *spr = static_cast<Effect*> ( new LPEbspline(lpeobj) );
//spr->doEffect(curve);
if(this->bspline){
- this->_bsplineDoEffect(curve);
+ LivePathEffect::sp_bspline_do_effect(curve, 0);
}else{
- this->_spiroDoEffect(curve);
+ LivePathEffect::sp_spiro_do_effect(curve);
}
sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(this->blue_bpath), curve);
@@ -1740,257 +1744,6 @@ void PenTool::_bsplineSpiroBuild()
}
}
-//from LPE BSPLINE:
-void PenTool::_bsplineDoEffect(SPCurve * curve)
-{
- //const double NO_POWER = 0.0;
- const double DEFAULT_START_POWER = 0.3334;
- const double DEFAULT_END_POWER = 0.6667;
- if (curve->get_segment_count() < 1) {
- return;
- }
- // Make copy of old path as it is changed during processing
- Geom::PathVector const original_pathv = curve->get_pathvector();
-
- curve->reset();
-
- for (Geom::PathVector::const_iterator path_it = original_pathv.begin();
- path_it != original_pathv.end(); ++path_it) {
- if (path_it->empty()) {
- continue;
- }
- Geom::Path::const_iterator curve_it1 = path_it->begin();
- Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
- Geom::Path::const_iterator curve_endit = path_it->end_default();
- SPCurve *curve_n = new SPCurve();
- Geom::Point previousNode(0, 0);
- Geom::Point node(0, 0);
- Geom::Point point_at1(0, 0);
- Geom::Point point_at2(0, 0);
- Geom::Point next_point_at1(0, 0);
- Geom::D2<Geom::SBasis> sbasis_in;
- Geom::D2<Geom::SBasis> sbasis_out;
- Geom::D2<Geom::SBasis> sbasis_helper;
- Geom::CubicBezier const *cubic = NULL;
- if (path_it->closed()) {
- // if the path is closed, maybe we have to stop a bit earlier because the
- // closing line segment has zerolength.
- const Geom::Curve &closingline =
- path_it->back_closed(); // the closing line segment is always of type
- // Geom::LineSegment.
- if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
- // closingline.isDegenerate() did not work, because it only checks for
- // *exact* zero length, which goes wrong for relative coordinates and
- // rounding errors...
- // the closing line segment has zero-length. So stop before that one!
- curve_endit = path_it->end_open();
- }
- }
- curve_n->moveto(curve_it1->initialPoint());
- while (curve_it1 != curve_endit) {
- SPCurve *in = new SPCurve();
- in->moveto(curve_it1->initialPoint());
- in->lineto(curve_it1->finalPoint());
- cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
- if (cubic) {
- sbasis_in = in->first_segment()->toSBasis();
- if(are_near((*cubic)[1],(*cubic)[0]) && !are_near((*cubic)[2],(*cubic)[3])) {
- point_at1 = sbasis_in.valueAt(DEFAULT_START_POWER);
- } else {
- point_at1 = sbasis_in.valueAt(Geom::nearest_time((*cubic)[1], *in->first_segment()));
- }
- if(are_near((*cubic)[2],(*cubic)[3]) && !are_near((*cubic)[1],(*cubic)[0])) {
- point_at2 = sbasis_in.valueAt(DEFAULT_END_POWER);
- } else {
- point_at2 = sbasis_in.valueAt(Geom::nearest_time((*cubic)[2], *in->first_segment()));
- }
- } else {
- point_at1 = in->first_segment()->initialPoint();
- point_at2 = in->first_segment()->finalPoint();
- }
- in->reset();
- delete in;
- if ( curve_it2 != curve_endit ) {
- SPCurve *out = new SPCurve();
- out->moveto(curve_it2->initialPoint());
- out->lineto(curve_it2->finalPoint());
- cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it2);
- if (cubic) {
- sbasis_out = out->first_segment()->toSBasis();
- if(are_near((*cubic)[1],(*cubic)[0]) && !are_near((*cubic)[2],(*cubic)[3])) {
- next_point_at1 = sbasis_in.valueAt(DEFAULT_START_POWER);
- } else {
- next_point_at1 = sbasis_out.valueAt(Geom::nearest_time((*cubic)[1], *out->first_segment()));
- }
- } else {
- next_point_at1 = out->first_segment()->initialPoint();
- }
- out->reset();
- delete out;
- }
- if (path_it->closed() && curve_it2 == curve_endit) {
- SPCurve *start = new SPCurve();
- start->moveto(path_it->begin()->initialPoint());
- start->lineto(path_it->begin()->finalPoint());
- Geom::D2<Geom::SBasis> sbasis_start = start->first_segment()->toSBasis();
- SPCurve *line_helper = new SPCurve();
- cubic = dynamic_cast<Geom::CubicBezier const *>(&*path_it->begin());
- if (cubic) {
- line_helper->moveto(sbasis_start.valueAt(
- Geom::nearest_time((*cubic)[1], *start->first_segment())));
- } else {
- line_helper->moveto(start->first_segment()->initialPoint());
- }
- start->reset();
- delete start;
-
- SPCurve *end = new SPCurve();
- end->moveto(curve_it1->initialPoint());
- end->lineto(curve_it1->finalPoint());
- Geom::D2<Geom::SBasis> sbasis_end = end->first_segment()->toSBasis();
- cubic = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
- if (cubic) {
- line_helper->lineto(sbasis_end.valueAt(
- Geom::nearest_time((*cubic)[2], *end->first_segment())));
- } else {
- line_helper->lineto(end->first_segment()->finalPoint());
- }
- end->reset();
- delete end;
- sbasis_helper = line_helper->first_segment()->toSBasis();
- line_helper->reset();
- delete line_helper;
- node = sbasis_helper.valueAt(0.5);
- curve_n->curveto(point_at1, point_at2, node);
- curve_n->move_endpoints(node, node);
- } else if ( curve_it2 == curve_endit) {
- curve_n->curveto(point_at1, point_at2, curve_it1->finalPoint());
- curve_n->move_endpoints(path_it->begin()->initialPoint(), curve_it1->finalPoint());
- } else {
- SPCurve *line_helper = new SPCurve();
- line_helper->moveto(point_at2);
- line_helper->lineto(next_point_at1);
- sbasis_helper = line_helper->first_segment()->toSBasis();
- line_helper->reset();
- delete line_helper;
- previousNode = node;
- node = sbasis_helper.valueAt(0.5);
- Geom::CubicBezier const *cubic2 = dynamic_cast<Geom::CubicBezier const *>(&*curve_it1);
- if((cubic && are_near((*cubic)[0],(*cubic)[1])) || (cubic2 && are_near((*cubic2)[2],(*cubic2)[3]))) {
- node = curve_it1->finalPoint();
- }
- curve_n->curveto(point_at1, point_at2, node);
- }
- ++curve_it1;
- ++curve_it2;
- }
- //y cerramos la curva
- if (path_it->closed()) {
- curve_n->closepath_current();
- }
- curve->append(curve_n, false);
- curve_n->reset();
- delete curve_n;
- }
-}
-
-//Spiro function cloned from lpe-spiro.cpp
-// commenting the function "doEffect" from src/live_effects/lpe-spiro.cpp
-void PenTool::_spiroDoEffect(SPCurve * curve)
-{
- using Geom::X;
- using Geom::Y;
-
- Geom::PathVector const original_pathv = curve->get_pathvector();
- guint len = curve->get_segment_count() + 2;
-
- curve->reset();
- Spiro::spiro_cp *path = g_new (Spiro::spiro_cp, len);
- int ip = 0;
-
- for(Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) {
- if (path_it->empty())
- continue;
-
- {
- Geom::Point p = path_it->front().pointAt(0);
- path[ip].x = p[X];
- path[ip].y = p[Y];
- path[ip].ty = '{' ;
- ip++;
- }
-
- Geom::Path::const_iterator curve_it1 = path_it->begin();
- Geom::Path::const_iterator curve_it2 = ++(path_it->begin());
-
- Geom::Path::const_iterator curve_endit = path_it->end_default();
- if (path_it->closed()) {
- const Geom::Curve &closingline = path_it->back_closed();
- if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
- curve_endit = path_it->end_open();
- }
- }
-
- while ( curve_it2 != curve_endit )
- {
- Geom::Point p = curve_it1->finalPoint();
- path[ip].x = p[X];
- path[ip].y = p[Y];
-
- bool this_is_line = is_straight_curve(*curve_it1);
- bool next_is_line = is_straight_curve(*curve_it2);
-
- Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, *curve_it2);
-
- if ( nodetype == Geom::NODE_SMOOTH || nodetype == Geom::NODE_SYMM )
- {
- if (this_is_line && !next_is_line) {
- path[ip].ty = ']';
- } else if (next_is_line && !this_is_line) {
- path[ip].ty = '[';
- } else {
- path[ip].ty = 'c';
- }
- } else {
- path[ip].ty = 'v';
- }
-
- ++curve_it1;
- ++curve_it2;
- ip++;
- }
-
- Geom::Point p = curve_it1->finalPoint();
- path[ip].x = p[X];
- path[ip].y = p[Y];
- if (path_it->closed()) {
- Geom::NodeType nodetype = Geom::get_nodetype(*curve_it1, path_it->front());
- switch (nodetype) {
- case Geom::NODE_NONE:
- path[ip].ty = '}';
- ip++;
- break;
- case Geom::NODE_CUSP:
- path[0].ty = path[ip].ty = 'v';
- break;
- case Geom::NODE_SMOOTH:
- case Geom::NODE_SYMM:
- path[0].ty = path[ip].ty = 'c';
- break;
- }
- } else {
- path[ip].ty = '}';
- ip++;
- }
-
- int sp_len = ip;
- Spiro::spiro_run(path, sp_len, *curve);
- ip = 0;
- }
-
- g_free (path);
-}
-
void PenTool::_setSubsequentPoint(Geom::Point const p, bool statusbar, guint status) {
g_assert( this->npoints != 0 );
diff --git a/src/ui/tools/pen-tool.h b/src/ui/tools/pen-tool.h
index 0ae16caf0..5a21e3bac 100644
--- a/src/ui/tools/pen-tool.h
+++ b/src/ui/tools/pen-tool.h
@@ -22,21 +22,21 @@ namespace Tools {
*/
class PenTool : public FreehandBase {
public:
- PenTool();
- PenTool(gchar const *const *cursor_shape, gint hot_x, gint hot_y);
- virtual ~PenTool();
-
- enum Mode {
- MODE_CLICK,
- MODE_DRAG
- };
-
- enum State {
- POINT,
- CONTROL,
- CLOSE,
- STOP
- };
+ PenTool();
+ PenTool(gchar const *const *cursor_shape, gint hot_x, gint hot_y);
+ virtual ~PenTool();
+
+ enum Mode {
+ MODE_CLICK,
+ MODE_DRAG
+ };
+
+ enum State {
+ POINT,
+ CONTROL,
+ CLOSE,
+ STOP
+ };
Geom::Point p[5];
@@ -66,28 +66,28 @@ public:
bool events_disabled;
- static const std::string prefsPath;
+ static const std::string prefsPath;
- virtual const std::string& getPrefsPath();
+ virtual const std::string& getPrefsPath();
- int nextParaxialDirection(Geom::Point const &pt, Geom::Point const &origin, guint state) const;
- void setPolylineMode();
- bool hasWaitingLPE();
+ int nextParaxialDirection(Geom::Point const &pt, Geom::Point const &origin, guint state) const;
+ void setPolylineMode();
+ bool hasWaitingLPE();
void waitForLPEMouseClicks(Inkscape::LivePathEffect::EffectType effect_type, unsigned int num_clicks, bool use_polylines = true);
protected:
- virtual void setup();
- virtual void finish();
- virtual void set(const Inkscape::Preferences::Entry& val);
- virtual bool root_handler(GdkEvent* event);
- virtual bool item_handler(SPItem* item, GdkEvent* event);
+ virtual void setup();
+ virtual void finish();
+ virtual void set(const Inkscape::Preferences::Entry& val);
+ virtual bool root_handler(GdkEvent* event);
+ virtual bool item_handler(SPItem* item, GdkEvent* event);
private:
- bool _handleButtonPress(GdkEventButton const &bevent);
- bool _handleMotionNotify(GdkEventMotion const &mevent);
- bool _handleButtonRelease(GdkEventButton const &revent);
- bool _handle2ButtonPress(GdkEventButton const &bevent);
- bool _handleKeyPress(GdkEvent *event);
+ bool _handleButtonPress(GdkEventButton const &bevent);
+ bool _handleMotionNotify(GdkEventMotion const &mevent);
+ bool _handleButtonRelease(GdkEventButton const &revent);
+ bool _handle2ButtonPress(GdkEventButton const &bevent);
+ bool _handleKeyPress(GdkEvent *event);
//adds spiro & bspline modes
void _penContextSetMode(guint mode);
//this function changes the colors red, green and blue making them transparent or not depending on if the function uses spiro
@@ -110,40 +110,36 @@ private:
void _bsplineSpiroEndAnchorOn();
//closes the curve with the last node in CUSP mode
void _bsplineSpiroEndAnchorOff();
- //CHECK: join all the curves "in game" and we call doEffect function
+ //apply the effect
void _bsplineSpiroBuild();
- //function bspline cloned from lpe-bspline.cpp
- void _bsplineDoEffect(SPCurve * curve);
- //function spiro cloned from lpe-spiro.cpp
- void _spiroDoEffect(SPCurve * curve);
-
- void _setInitialPoint(Geom::Point const p);
- void _setSubsequentPoint(Geom::Point const p, bool statusbar, guint status = 0);
- void _setCtrl(Geom::Point const p, guint state);
- void _finishSegment(Geom::Point p, guint state);
+
+ void _setInitialPoint(Geom::Point const p);
+ void _setSubsequentPoint(Geom::Point const p, bool statusbar, guint status = 0);
+ void _setCtrl(Geom::Point const p, guint state);
+ void _finishSegment(Geom::Point p, guint state);
bool _undoLastPoint();
- void _finish(gboolean closed);
+ void _finish(gboolean closed);
- void _resetColors();
+ void _resetColors();
- void _disableEvents();
- void _enableEvents();
+ void _disableEvents();
+ void _enableEvents();
- void _setToNearestHorizVert(Geom::Point &pt, guint const state, bool snap) const;
+ void _setToNearestHorizVert(Geom::Point &pt, guint const state, bool snap) const;
- void _setAngleDistanceStatusMessage(Geom::Point const p, int pc_point_to_compare, gchar const *message);
+ void _setAngleDistanceStatusMessage(Geom::Point const p, int pc_point_to_compare, gchar const *message);
- void _lastpointToLine();
- void _lastpointToCurve();
- void _lastpointMoveScreen(gdouble x, gdouble y);
- void _lastpointMove(gdouble x, gdouble y);
- void _redrawAll();
+ void _lastpointToLine();
+ void _lastpointToCurve();
+ void _lastpointMoveScreen(gdouble x, gdouble y);
+ void _lastpointMove(gdouble x, gdouble y);
+ void _redrawAll();
- void _endpointSnapHandle(Geom::Point &p, guint const state) const;
- void _endpointSnap(Geom::Point &p, guint const state) const;
+ void _endpointSnapHandle(Geom::Point &p, guint const state) const;
+ void _endpointSnap(Geom::Point &p, guint const state) const;
- void _cancel();
+ void _cancel();
};
}
diff --git a/src/ui/tools/pencil-tool.cpp b/src/ui/tools/pencil-tool.cpp
index 16c26546f..b029ca613 100644
--- a/src/ui/tools/pencil-tool.cpp
+++ b/src/ui/tools/pencil-tool.cpp
@@ -634,8 +634,13 @@ void PencilTool::_interpolate() {
using Geom::Y;
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- double const tol = prefs->getDoubleLimited("/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0) * 0.4;
- double const tolerance_sq = 0.02 * square(this->desktop->w2d().descrim() * tol) * exp(0.2 * tol - 2);
+ double tol = prefs->getDoubleLimited("/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0) * 0.4;
+ bool simplify = prefs->getInt("/tools/freehand/pencil/simplify", 0);
+ if(simplify){
+ double tol2 = prefs->getDoubleLimited("/tools/freehand/pencil/base-simplify", 25.0, 1.0, 100.0) * 0.4;
+ tol = std::min(tol,tol2);
+ }
+ double tolerance_sq = 0.02 * square(this->desktop->w2d().descrim() * tol) * exp(0.2 * tol - 2);
g_assert(is_zero(this->req_tangent) || is_unit_vector(this->req_tangent));
@@ -702,9 +707,14 @@ void PencilTool::_sketchInterpolate() {
}
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- double const tol = prefs->getDoubleLimited("/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0) * 0.4;
- double const tolerance_sq = 0.02 * square(this->desktop->w2d().descrim() * tol) * exp(0.2 * tol - 2);
-
+ double tol = prefs->getDoubleLimited("/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0) * 0.4;
+ bool simplify = prefs->getInt("/tools/freehand/pencil/simplify", 0);
+ if(simplify){
+ double tol2 = prefs->getDoubleLimited("/tools/freehand/pencil/base-simplify", 25.0, 1.0, 100.0) * 0.4;
+ tol = std::min(tol,tol2);
+ }
+ double tolerance_sq = 0.02 * square(this->desktop->w2d().descrim() * tol) * exp(0.2 * tol - 2);
+
bool average_all_sketches = prefs->getBool("/tools/freehand/pencil/average_all_sketches", true);
g_assert(is_zero(this->req_tangent) || is_unit_vector(this->req_tangent));
diff --git a/src/ui/tools/select-tool.cpp b/src/ui/tools/select-tool.cpp
index f06b03d91..905e38f2b 100644
--- a/src/ui/tools/select-tool.cpp
+++ b/src/ui/tools/select-tool.cpp
@@ -89,10 +89,6 @@ SelectTool::SelectTool()
, button_press_shift(false)
, button_press_ctrl(false)
, button_press_alt(false)
- , cycling_items(NULL)
- , cycling_items_cmp(NULL)
- , cycling_items_selected_before(NULL)
- , cycling_cur_item(NULL)
, cycling_wrap(true)
, item(NULL)
, grabbed(NULL)
@@ -390,16 +386,16 @@ bool SelectTool::item_handler(SPItem* item, GdkEvent* event) {
}
void SelectTool::sp_select_context_cycle_through_items(Inkscape::Selection *selection, GdkEventScroll *scroll_event, bool shift_pressed) {
- if (!this->cycling_cur_item) {
+ if (this->cycling_cur_item == this->cycling_items.end()) {
return;
}
Inkscape::DrawingItem *arenaitem;
- SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(cycling_cur_item->data));
+ SPItem *item = *cycling_cur_item;
g_assert(item != NULL);
// Deactivate current item
- if (!g_list_find(this->cycling_items_selected_before, item) && selection->includes(item)) {
+ if (std::find(cycling_items_selected_before.begin(), cycling_items_selected_before.end(), item) == cycling_items_selected_before.end() && selection->includes(item)) {
selection->remove(item);
}
@@ -407,20 +403,22 @@ void SelectTool::sp_select_context_cycle_through_items(Inkscape::Selection *sele
arenaitem->setOpacity(0.3);
// Find next item and activate it
- GList *next;
+ std::vector<SPItem *>::iterator next = this->cycling_cur_item;
if (scroll_event->direction == GDK_SCROLL_UP) {
- next = this->cycling_cur_item->next;
- if (next == NULL && this->cycling_wrap)
- next = this->cycling_items;
+ ++next;
+ if (next == this->cycling_items.end() && this->cycling_wrap) {
+ next = this->cycling_items.begin();
+ }
} else {
- next = this->cycling_cur_item->prev;
- if (next == NULL && this->cycling_wrap)
- next = g_list_last(this->cycling_items);
+ if(next == this->cycling_items.begin()) {
+ next = this->cycling_items.end();
+ }
+ --next;
}
- if (next) {
+ if (next!=this->cycling_items.end()) {
this->cycling_cur_item = next;
- item = dynamic_cast<SPItem *>(static_cast<SPObject *>(this->cycling_cur_item->data));
+ item = *next;
g_assert(item != NULL);
}
@@ -435,8 +433,8 @@ void SelectTool::sp_select_context_cycle_through_items(Inkscape::Selection *sele
}
void SelectTool::sp_select_context_reset_opacities() {
- for (GList *l = this->cycling_items; l != NULL; l = g_list_next(l)) {
- SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(l->data));
+ for (std::vector<SPItem *>::const_iterator l = this->cycling_items.begin(); l != this->cycling_items.end(); ++l ) {
+ SPItem *item = *l;
if (item) {
Inkscape::DrawingItem *arenaitem = item->get_arenaitem(desktop->dkey);
arenaitem->setOpacity(SP_SCALE24_TO_FLOAT(item->style->opacity.value));
@@ -445,14 +443,10 @@ void SelectTool::sp_select_context_reset_opacities() {
}
}
- g_list_free(this->cycling_items);
- g_list_free(this->cycling_items_selected_before);
- g_list_free(this->cycling_items_cmp);
-
- this->cycling_items = NULL;
- this->cycling_items_selected_before = NULL;
- this->cycling_cur_item = NULL;
- this->cycling_items_cmp = NULL;
+ this->cycling_items.clear();
+ this->cycling_items_selected_before.clear();
+ this->cycling_cur_item = this->cycling_items.end();
+ this->cycling_items_cmp.clear();
}
bool SelectTool::root_handler(GdkEvent* event) {
@@ -819,70 +813,57 @@ bool SelectTool::root_handler(GdkEvent* event) {
SPItem *item = desktop->getItemAtPoint(p, true, NULL);
// Save pointer to current cycle-item so that we can find it again later, in the freshly built list
- SPItem *tmp_cur_item = this->cycling_cur_item ? dynamic_cast<SPItem *>(static_cast<SPObject *>(this->cycling_cur_item->data)) : NULL;
- g_list_free(this->cycling_items);
- this->cycling_items = NULL;
- this->cycling_cur_item = NULL;
-
+ SPItem *tmp_cur_item = this->cycling_cur_item!=this->cycling_items.end() ? (*(this->cycling_cur_item)) : NULL;
+ this->cycling_items.clear();
+ this->cycling_cur_item = this->cycling_items.end();
while(item != NULL) {
- this->cycling_items = g_list_append(this->cycling_items, item);
+ this->cycling_items.push_back(item);
item = desktop->getItemAtPoint(p, true, item);
}
/* Compare current item list with item list during previous scroll ... */
- GList *l1, *l2;
- bool item_lists_differ = false;
-
- // Note that we can do an 'or' comparison in the loop because it is safe to call g_list_next with a NULL pointer.
- for (l1 = this->cycling_items, l2 = this->cycling_items_cmp; l1 != NULL || l2 != NULL; l1 = g_list_next(l1), l2 = g_list_next(l2)) {
- if ((l1 !=NULL && l2 == NULL) || (l1 == NULL && l2 != NULL) || (l1->data != l2->data)) {
- item_lists_differ = true;
- break;
- }
- }
+ bool item_lists_differ = this->cycling_items != this->cycling_items_cmp;
/* If list of items under mouse pointer hasn't changed ... */
if (!item_lists_differ) {
// ... find current item in the freshly built list and continue cycling ...
// TODO: This wouldn't be necessary if cycling_cur_item pointed to an element of cycling_items_cmp instead
- this->cycling_cur_item = g_list_find(this->cycling_items, tmp_cur_item);
- g_assert(this->cycling_cur_item != NULL || this->cycling_items == NULL);
+ this->cycling_cur_item = std::find(this->cycling_items.begin(), this->cycling_items.end(), tmp_cur_item);
+ g_assert(this->cycling_cur_item != this->cycling_items.end() || this->cycling_items.empty());
} else {
// ... otherwise reset opacities for outdated items ...
Inkscape::DrawingItem *arenaitem;
- for(GList *l = this->cycling_items_cmp; l != NULL; l = l->next) {
- SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(l->data));
+ for (std::vector<SPItem *>::const_iterator l = this->cycling_items_cmp.begin(); l != this->cycling_items_cmp.end(); ++l) {
+ SPItem *item = *l;
if (item) {
arenaitem = item->get_arenaitem(desktop->dkey);
arenaitem->setOpacity(1.0);
//if (!shift_pressed && !g_list_find(this->cycling_items_selected_before, item) && selection->includes(item))
- if (!g_list_find(this->cycling_items_selected_before, item) && selection->includes(item)) {
+ if (std::find(this->cycling_items_selected_before.begin(),this->cycling_items_selected_before.end(), item)==this->cycling_items_selected_before.end() && selection->includes(item)) {
selection->remove(item);
}
}
}
// ... clear the lists ...
- g_list_free(this->cycling_items_cmp);
- g_list_free(this->cycling_items_selected_before);
- this->cycling_items_cmp = NULL;
- this->cycling_items_selected_before = NULL;
- this->cycling_cur_item = NULL;
+ this->cycling_items_cmp.clear();
+ this->cycling_items_selected_before.clear();
+ this->cycling_cur_item = this->cycling_items.end();
// ... and rebuild them with the new items.
- this->cycling_items_cmp = g_list_copy(this->cycling_items);
+ this->cycling_items_cmp = (this->cycling_items);
- for(GList *l = this->cycling_items; l != NULL; l = l->next) {
- SPItem *item = dynamic_cast<SPItem *>(static_cast<SPObject *>(l->data));
+ for(std::vector<SPItem *>::const_iterator l = this->cycling_items.begin(); l != this->cycling_items.end(); ++l) {
+ SPItem *item =*l;
if (item) {
arenaitem = item->get_arenaitem(desktop->dkey);
arenaitem->setOpacity(0.3);
if (selection->includes(item)) {
// already selected items are stored separately, too
- this->cycling_items_selected_before = g_list_append(this->cycling_items_selected_before, item);
+ this->cycling_items_selected_before.push_back(item);
}
} else {
g_assert_not_reached();
@@ -890,7 +871,8 @@ bool SelectTool::root_handler(GdkEvent* event) {
}
// set the current item to the bottommost one so that the cycling step below re-starts at the top
- this->cycling_cur_item = g_list_last(this->cycling_items);
+ this->cycling_cur_item = this->cycling_items.end();
+ this->cycling_cur_item--;
}
this->cycling_wrap = prefs->getBool("/options/selection/cycleWrap", true);
diff --git a/src/ui/tools/select-tool.h b/src/ui/tools/select-tool.h
index 5af99a56a..af183b1ca 100644
--- a/src/ui/tools/select-tool.h
+++ b/src/ui/tools/select-tool.h
@@ -40,10 +40,10 @@ public:
bool button_press_ctrl;
bool button_press_alt;
- GList *cycling_items;
- GList *cycling_items_cmp;
- GList *cycling_items_selected_before;
- GList *cycling_cur_item;
+ std::vector<SPItem *> cycling_items;
+ std::vector<SPItem *> cycling_items_cmp;
+ std::vector<SPItem *> cycling_items_selected_before;
+ std::vector<SPItem *>::iterator cycling_cur_item;
bool cycling_wrap;
SPItem *item;
diff --git a/src/ui/tools/spray-tool.cpp b/src/ui/tools/spray-tool.cpp
index e2be5ca4b..9adaf3879 100644
--- a/src/ui/tools/spray-tool.cpp
+++ b/src/ui/tools/spray-tool.cpp
@@ -12,6 +12,7 @@
* Steren GIANNINI (steren.giannini@gmail.com)
* Jon A. Cruz <jon@joncruz.org>
* Abhishek Sharma
+ * Jabiertxo Arraiza <jabier.arraiza@marker.es>
*
* Copyright (C) 2009 authors
*
@@ -48,7 +49,15 @@
#include "sp-path.h"
#include "path-chemistry.h"
+// For color picking
+#include "display/drawing.h"
+#include "display/drawing-context.h"
+#include "display/cairo-utils.h"
+#include "desktop-style.h"
+#include "svg/svg-color.h"
+
#include "sp-text.h"
+#include "sp-root.h"
#include "sp-flowtext.h"
#include "display/sp-canvas.h"
#include "display/canvas-bpath.h"
@@ -88,6 +97,17 @@ namespace Inkscape {
namespace UI {
namespace Tools {
+enum {
+ PICK_COLOR,
+ PICK_OPACITY,
+ PICK_R,
+ PICK_G,
+ PICK_B,
+ PICK_H,
+ PICK_S,
+ PICK_L
+};
+
const std::string& SprayTool::getPrefsPath() {
return SprayTool::prefsPath;
}
@@ -133,7 +153,9 @@ SprayTool::SprayTool()
: ToolBase(cursor_spray_xpm, 4, 4, false)
, pressure(TC_DEFAULT_PRESSURE)
, dragging(false)
- , usepressure(false)
+ , usepressurewidth(false)
+ , usepressurepopulation(false)
+ , usepressurescale(false)
, usetilt(false)
, usetext(false)
, width(0.2)
@@ -151,6 +173,25 @@ SprayTool::SprayTool()
, is_dilating(false)
, has_dilated(false)
, dilate_area(NULL)
+ , no_overlap(false)
+ , picker(false)
+ , pick_center(true)
+ , pick_inverse_value(false)
+ , pick_fill(false)
+ , pick_stroke(false)
+ , pick_no_overlap(false)
+ , over_transparent(true)
+ , over_no_transparent(true)
+ , offset(0)
+ , pick(0)
+ , do_trace(false)
+ , pick_to_size(false)
+ , pick_to_presence(false)
+ , pick_to_color(false)
+ , pick_to_opacity(false)
+ , invert_picked(false)
+ , gamma_picked(0)
+ , rand_picked(0)
{
}
@@ -211,6 +252,15 @@ void SprayTool::setup() {
this->is_drawing = false;
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setBool("/dialogs/clonetiler/dotrace", false);
+ if (prefs->getBool("/tools/spray/selcue")) {
+ this->enableSelectionCue();
+ }
+ if (prefs->getBool("/tools/spray/gradientdrag")) {
+ this->enableGrDrag();
+ }
+
sp_event_context_read(this, "distrib");
sp_event_context_read(this, "width");
sp_event_context_read(this, "ratio");
@@ -221,16 +271,33 @@ void SprayTool::setup() {
sp_event_context_read(this, "population");
sp_event_context_read(this, "mean");
sp_event_context_read(this, "standard_deviation");
- sp_event_context_read(this, "usepressure");
+ sp_event_context_read(this, "usepressurewidth");
+ sp_event_context_read(this, "usepressurepopulation");
+ sp_event_context_read(this, "usepressurescale");
sp_event_context_read(this, "Scale");
+ sp_event_context_read(this, "offset");
+ sp_event_context_read(this, "picker");
+ sp_event_context_read(this, "pick_center");
+ sp_event_context_read(this, "pick_inverse_value");
+ sp_event_context_read(this, "pick_fill");
+ sp_event_context_read(this, "pick_stroke");
+ sp_event_context_read(this, "pick_no_overlap");
+ sp_event_context_read(this, "over_no_transparent");
+ sp_event_context_read(this, "over_transparent");
+ sp_event_context_read(this, "no_overlap");
+}
+void SprayTool::setCloneTilerPrefs() {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- if (prefs->getBool("/tools/spray/selcue")) {
- this->enableSelectionCue();
- }
- if (prefs->getBool("/tools/spray/gradientdrag")) {
- this->enableGrDrag();
- }
+ this->do_trace = prefs->getBool("/dialogs/clonetiler/dotrace", false);
+ this->pick = prefs->getInt("/dialogs/clonetiler/pick");
+ this->pick_to_size = prefs->getBool("/dialogs/clonetiler/pick_to_size", false);
+ this->pick_to_presence = prefs->getBool("/dialogs/clonetiler/pick_to_presence", false);
+ this->pick_to_color = prefs->getBool("/dialogs/clonetiler/pick_to_color", false);
+ this->pick_to_opacity = prefs->getBool("/dialogs/clonetiler/pick_to_opacity", false);
+ this->rand_picked = 0.01 * prefs->getDoubleLimited("/dialogs/clonetiler/rand_picked", 0, 0, 100);
+ this->invert_picked = prefs->getBool("/dialogs/clonetiler/invert_picked", false);
+ this->gamma_picked = prefs->getDoubleLimited("/dialogs/clonetiler/gamma_picked", 0, -10, 10);
}
void SprayTool::set(const Inkscape::Preferences::Entry& val) {
@@ -241,8 +308,12 @@ void SprayTool::set(const Inkscape::Preferences::Entry& val) {
this->update_cursor(false);
} else if (path == "width") {
this->width = 0.01 * CLAMP(val.getInt(10), 1, 100);
- } else if (path == "usepressure") {
- this->usepressure = val.getBool();
+ } else if (path == "usepressurewidth") {
+ this->usepressurewidth = val.getBool();
+ } else if (path == "usepressurepopulation") {
+ this->usepressurepopulation = val.getBool();
+ } else if (path == "usepressurescale") {
+ this->usepressurescale = val.getBool();
} else if (path == "population") {
this->population = 0.01 * CLAMP(val.getInt(10), 1, 100);
} else if (path == "rotation_variation") {
@@ -260,6 +331,26 @@ void SprayTool::set(const Inkscape::Preferences::Entry& val) {
this->tilt = CLAMP(val.getDouble(0.1), 0, 1000.0);
} else if (path == "ratio") {
this->ratio = CLAMP(val.getDouble(), 0.0, 0.9);
+ } else if (path == "offset") {
+ this->offset = val.getDoubleLimited(100.0, 0, 1000.0);
+ } else if (path == "pick_center") {
+ this->pick_center = val.getBool(true);
+ } else if (path == "pick_inverse_value") {
+ this->pick_inverse_value = val.getBool(false);
+ } else if (path == "pick_fill") {
+ this->pick_fill = val.getBool(false);
+ } else if (path == "pick_stroke") {
+ this->pick_stroke = val.getBool(false);
+ } else if (path == "pick_no_overlap") {
+ this->pick_no_overlap = val.getBool(false);
+ } else if (path == "over_no_transparent") {
+ this->over_no_transparent = val.getBool(true);
+ } else if (path == "over_transparent") {
+ this->over_transparent = val.getBool(true);
+ } else if (path == "no_overlap") {
+ this->no_overlap = val.getBool(false);
+ } else if (path == "picker") {
+ this->picker = val.getBool(false);
}
}
@@ -272,9 +363,15 @@ static void sp_spray_extinput(SprayTool *tc, GdkEvent *event)
}
}
+static double get_width(SprayTool *tc)
+{
+ double pressure = (tc->usepressurewidth? tc->pressure / TC_DEFAULT_PRESSURE : 1);
+ return pressure * tc->width;
+}
+
static double get_dilate_radius(SprayTool *tc)
{
- return 250 * tc->width/SP_EVENT_CONTEXT(tc)->desktop->current_zoom();
+ return 250 * get_width(tc)/SP_EVENT_CONTEXT(tc)->desktop->current_zoom();
}
static double get_path_mean(SprayTool *tc)
@@ -289,11 +386,16 @@ static double get_path_standard_deviation(SprayTool *tc)
static double get_population(SprayTool *tc)
{
- double pressure = (tc->usepressure? tc->pressure / TC_DEFAULT_PRESSURE : 1);
- //g_warning("Pressure, population: %f, %f", pressure, pressure * tc->population);
+ double pressure = (tc->usepressurepopulation? tc->pressure / TC_DEFAULT_PRESSURE : 1);
return pressure * tc->population;
}
+static double get_pressure(SprayTool *tc)
+{
+ double pressure = tc->pressure / TC_DEFAULT_PRESSURE;
+ return pressure;
+}
+
static double get_move_mean(SprayTool *tc)
{
return tc->mean;
@@ -332,6 +434,433 @@ static void random_position(double &radius, double &angle, double &a, double &s,
}
+static void sp_spray_transform_path(SPItem * item, Geom::Path &path, Geom::Affine affine, Geom::Point center){
+ path *= i2anc_affine(static_cast<SPItem *>(item->parent), NULL).inverse();
+ path *= item->transform.inverse();
+ Geom::Affine dt2p;
+ if (item->parent) {
+ dt2p = static_cast<SPItem *>(item->parent)->i2dt_affine().inverse();
+ } else {
+ SPDesktop *dt = SP_ACTIVE_DESKTOP;
+ dt2p = dt->dt2doc();
+ }
+ Geom::Affine i2dt = item->i2dt_affine() * Geom::Translate(center).inverse() * affine * Geom::Translate(center);
+ path *= i2dt * dt2p;
+ path *= i2anc_affine(static_cast<SPItem *>(item->parent), NULL);
+}
+
+/**
+Randomizes \a val by \a rand, with 0 < val < 1 and all values (including 0, 1) having the same
+probability of being displaced.
+ */
+double randomize01(double val, double rand)
+{
+ double base = MIN (val - rand, 1 - 2*rand);
+ if (base < 0) {
+ base = 0;
+ }
+ val = base + g_random_double_range (0, MIN (2 * rand, 1 - base));
+ return CLAMP(val, 0, 1); // this should be unnecessary with the above provisions, but just in case...
+}
+
+guint32 getPickerData(Geom::IntRect area){
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ double R = 0, G = 0, B = 0, A = 0;
+ cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, area.width(), area.height());
+ sp_canvas_arena_render_surface(SP_CANVAS_ARENA(desktop->getDrawing()), s, area);
+ ink_cairo_surface_average_color(s, R, G, B, A);
+ cairo_surface_destroy(s);
+ //this can fix the bug #1511998 if confirmed
+ if( A == 0 || A < 1e-6){
+ R = 1;
+ G = 1;
+ B = 1;
+ }
+ return SP_RGBA32_F_COMPOSE(R, G, B, A);
+}
+
+static void showHidden(std::vector<SPItem *> items_down){
+ for (std::vector<SPItem *>::const_iterator k=items_down.begin(); k!=items_down.end(); ++k) {
+ SPItem *item_hidden = *k;
+ item_hidden->setHidden(false);
+ item_hidden->updateRepr();
+ }
+}
+//todo: maybe move same parameter to preferences
+static bool fit_item(SPDesktop *desktop,
+ SPItem *item,
+ Geom::OptRect bbox,
+ Geom::Point &move,
+ Geom::Point center,
+ gint mode,
+ double angle,
+ double &_scale,
+ double scale,
+ bool picker,
+ bool pick_center,
+ bool pick_inverse_value,
+ bool pick_fill,
+ bool pick_stroke,
+ bool pick_no_overlap,
+ bool over_no_transparent,
+ bool over_transparent,
+ bool no_overlap,
+ double offset,
+ SPCSSAttr *css,
+ bool trace_scale,
+ int pick,
+ bool do_trace,
+ bool pick_to_size,
+ bool pick_to_presence,
+ bool pick_to_color,
+ bool pick_to_opacity,
+ bool invert_picked,
+ double gamma_picked ,
+ double rand_picked)
+{
+ SPDocument *doc = item->document;
+ double width = bbox->width();
+ double height = bbox->height();
+ double offset_width = (offset * width)/100.0 - (width);
+ if(offset_width < 0 ){
+ offset_width = 0;
+ }
+ double offset_height = (offset * height)/100.0 - (height);
+ if(offset_height < 0 ){
+ offset_height = 0;
+ }
+ if(picker && pick_to_size && !trace_scale && do_trace){
+ _scale = 0.1;
+ }
+ Geom::OptRect bbox_procesed = Geom::Rect(Geom::Point(bbox->left() - offset_width, bbox->top() - offset_height),Geom::Point(bbox->right() + offset_width, bbox->bottom() + offset_height));
+ Geom::Path path;
+ path.start(Geom::Point(bbox_procesed->left(), bbox_procesed->top()));
+ path.appendNew<Geom::LineSegment>(Geom::Point(bbox_procesed->right(), bbox_procesed->top()));
+ path.appendNew<Geom::LineSegment>(Geom::Point(bbox_procesed->right(), bbox_procesed->bottom()));
+ path.appendNew<Geom::LineSegment>(Geom::Point(bbox_procesed->left(), bbox_procesed->bottom()));
+ path.close(true);
+ sp_spray_transform_path(item, path, Geom::Scale(_scale), center);
+ sp_spray_transform_path(item, path, Geom::Scale(scale), center);
+ sp_spray_transform_path(item, path, Geom::Rotate(angle), center);
+ path *= Geom::Translate(move);
+ path *= desktop->doc2dt();
+ bbox_procesed = path.boundsFast();
+ double bbox_left_main = bbox_procesed->left();
+ double bbox_right_main = bbox_procesed->right();
+ double bbox_top_main = bbox_procesed->top();
+ double bbox_bottom_main = bbox_procesed->bottom();
+ double width_transformed = bbox_procesed->width();
+ double height_transformed = bbox_procesed->height();
+ Geom::Point mid_point = desktop->d2w(bbox_procesed->midpoint());
+ Geom::IntRect area = Geom::IntRect::from_xywh(floor(mid_point[Geom::X]), floor(mid_point[Geom::Y]), 1, 1);
+ guint32 rgba = getPickerData(area);
+ guint32 rgba2 = 0xffffff00;
+ Geom::Rect rect_sprayed(desktop->d2w(Geom::Point(bbox_left_main,bbox_top_main)), desktop->d2w(Geom::Point(bbox_right_main,bbox_bottom_main)));
+ if (!rect_sprayed.hasZeroArea()) {
+ rgba2 = getPickerData(rect_sprayed.roundOutwards());
+ }
+ if(pick_no_overlap) {
+ if(rgba != rgba2) {
+ if(mode != SPRAY_MODE_ERASER) {
+ return false;
+ }
+ }
+ }
+ if(!pick_center) {
+ rgba = rgba2;
+ }
+ if(!over_transparent && (SP_RGBA32_A_F(rgba) == 0 || SP_RGBA32_A_F(rgba) < 1e-6)) {
+ if(mode != SPRAY_MODE_ERASER) {
+ return false;
+ }
+ }
+ if(!over_no_transparent && SP_RGBA32_A_F(rgba) > 0) {
+ if(mode != SPRAY_MODE_ERASER) {
+ return false;
+ }
+ }
+ if(offset < 100 ) {
+ offset_width = ((99.0 - offset) * width_transformed)/100.0 - width_transformed;
+ offset_height = ((99.0 - offset) * height_transformed)/100.0 - height_transformed;
+ } else {
+ offset_width = 0;
+ offset_height = 0;
+ }
+ std::vector<SPItem*> items_down = desktop->getDocument()->getItemsPartiallyInBox(desktop->dkey, *bbox_procesed);
+ Inkscape::Selection *selection = desktop->getSelection();
+ if (selection->isEmpty()) {
+ return false;
+ }
+ std::vector<SPItem*> const items_selected(selection->itemList());
+ std::vector<SPItem*> items_down_erased;
+ for (std::vector<SPItem*>::const_iterator i=items_down.begin(); i!=items_down.end(); ++i) {
+ SPItem *item_down = *i;
+ Geom::OptRect bbox_down = item_down->documentVisualBounds();
+ double bbox_left = bbox_down->left();
+ double bbox_top = bbox_down->top();
+ gchar const * item_down_sharp = g_strdup_printf("#%s", item_down->getId());
+ items_down_erased.push_back(item_down);
+ for (std::vector<SPItem*>::const_iterator j=items_selected.begin(); j!=items_selected.end(); ++j) {
+ SPItem *item_selected = *j;
+ gchar const * spray_origin;
+ if(!item_selected->getAttribute("inkscape:spray-origin")){
+ spray_origin = g_strdup_printf("#%s", item_selected->getId());
+ } else {
+ spray_origin = item_selected->getAttribute("inkscape:spray-origin");
+ }
+ if(strcmp(item_down_sharp, spray_origin) == 0 ||
+ (item_down->getAttribute("inkscape:spray-origin") &&
+ strcmp(item_down->getAttribute("inkscape:spray-origin"),spray_origin) == 0 ))
+ {
+ if(mode == SPRAY_MODE_ERASER) {
+ if(strcmp(item_down_sharp, spray_origin) != 0 && !selection->includes(item_down) ){
+ item_down->deleteObject();
+ items_down_erased.pop_back();
+ break;
+ }
+ } else if(no_overlap) {
+ if(!(offset_width < 0 && offset_height < 0 && std::abs(bbox_left - bbox_left_main) > std::abs(offset_width) &&
+ std::abs(bbox_top - bbox_top_main) > std::abs(offset_height))){
+ if(!no_overlap && (picker || over_transparent || over_no_transparent)){
+ showHidden(items_down);
+ }
+ return false;
+ }
+ } else if(picker || over_transparent || over_no_transparent) {
+ item_down->setHidden(true);
+ item_down->updateRepr();
+ }
+ }
+ }
+ }
+ if(mode == SPRAY_MODE_ERASER){
+ if(!no_overlap && (picker || over_transparent || over_no_transparent)){
+ showHidden(items_down_erased);
+ }
+ return false;
+ }
+ if(picker || over_transparent || over_no_transparent){
+ if(!no_overlap){
+ doc->ensureUpToDate();
+ rgba = getPickerData(area);
+ if (!rect_sprayed.hasZeroArea()) {
+ rgba2 = getPickerData(rect_sprayed.roundOutwards());
+ }
+ }
+ if(pick_no_overlap){
+ if(rgba != rgba2){
+ if(!no_overlap && (picker || over_transparent || over_no_transparent)){
+ showHidden(items_down);
+ }
+ return false;
+ }
+ }
+ if(!pick_center){
+ rgba = rgba2;
+ }
+ double opacity = 1.0;
+ gchar color_string[32]; *color_string = 0;
+ float r = SP_RGBA32_R_F(rgba);
+ float g = SP_RGBA32_G_F(rgba);
+ float b = SP_RGBA32_B_F(rgba);
+ float a = SP_RGBA32_A_F(rgba);
+ if(!over_transparent && (a == 0 || a < 1e-6)){
+ if(!no_overlap && (picker || over_transparent || over_no_transparent)){
+ showHidden(items_down);
+ }
+ return false;
+ }
+ if(!over_no_transparent && a > 0){
+ if(!no_overlap && (picker || over_transparent || over_no_transparent)){
+ showHidden(items_down);
+ }
+ return false;
+ }
+
+ if(picker && do_trace){
+ float hsl[3];
+ sp_color_rgb_to_hsl_floatv (hsl, r, g, b);
+
+ gdouble val = 0;
+ switch (pick) {
+ case PICK_COLOR:
+ val = 1 - hsl[2]; // inverse lightness; to match other picks where black = max
+ break;
+ case PICK_OPACITY:
+ val = a;
+ break;
+ case PICK_R:
+ val = r;
+ break;
+ case PICK_G:
+ val = g;
+ break;
+ case PICK_B:
+ val = b;
+ break;
+ case PICK_H:
+ val = hsl[0];
+ break;
+ case PICK_S:
+ val = hsl[1];
+ break;
+ case PICK_L:
+ val = 1 - hsl[2];
+ break;
+ default:
+ break;
+ }
+
+ if (rand_picked > 0) {
+ val = randomize01 (val, rand_picked);
+ r = randomize01 (r, rand_picked);
+ g = randomize01 (g, rand_picked);
+ b = randomize01 (b, rand_picked);
+ }
+
+ if (gamma_picked != 0) {
+ double power;
+ if (gamma_picked > 0)
+ power = 1/(1 + fabs(gamma_picked));
+ else
+ power = 1 + fabs(gamma_picked);
+
+ val = pow (val, power);
+ r = pow ((double)r, (double)power);
+ g = pow ((double)g, (double)power);
+ b = pow ((double)b, (double)power);
+ }
+
+ if (invert_picked) {
+ val = 1 - val;
+ r = 1 - r;
+ g = 1 - g;
+ b = 1 - b;
+ }
+
+ val = CLAMP (val, 0, 1);
+ r = CLAMP (r, 0, 1);
+ g = CLAMP (g, 0, 1);
+ b = CLAMP (b, 0, 1);
+
+ // recompose tweaked color
+ rgba = SP_RGBA32_F_COMPOSE(r, g, b, a);
+ if (pick_to_size) {
+ if(!trace_scale){
+ if(pick_inverse_value) {
+ _scale = 1.0 - val;
+ } else {
+ _scale = val;
+ }
+ if(_scale == 0.0) {
+ if(!no_overlap && (picker || over_transparent || over_no_transparent)){
+ showHidden(items_down);
+ }
+ return false;
+ }
+ if(!fit_item(desktop
+ , item
+ , bbox
+ , move
+ , center
+ , mode
+ , angle
+ , _scale
+ , scale
+ , picker
+ , pick_center
+ , pick_inverse_value
+ , pick_fill
+ , pick_stroke
+ , pick_no_overlap
+ , over_no_transparent
+ , over_transparent
+ , no_overlap
+ , offset
+ , css
+ , true
+ , pick
+ , do_trace
+ , pick_to_size
+ , pick_to_presence
+ , pick_to_color
+ , pick_to_opacity
+ , invert_picked
+ , gamma_picked
+ , rand_picked)
+ )
+ {
+ if(!no_overlap && (picker || over_transparent || over_no_transparent)){
+ showHidden(items_down);
+ }
+ return false;
+ }
+ }
+ }
+
+ if (pick_to_opacity) {
+ if(pick_inverse_value) {
+ opacity *= 1.0 - val;
+ } else {
+ opacity *= val;
+ }
+ std::stringstream opacity_str;
+ opacity_str.imbue(std::locale::classic());
+ opacity_str << opacity;
+ sp_repr_css_set_property(css, "opacity", opacity_str.str().c_str());
+ }
+ if (pick_to_presence) {
+ if (g_random_double_range (0, 1) > val) {
+ //Hidding the element is a way to retain original
+ //behaviour of tiled clones for presence option.
+ sp_repr_css_set_property(css, "opacity", "0");
+ }
+ }
+ if (pick_to_color) {
+ sp_svg_write_color(color_string, sizeof(color_string), rgba);
+ if(pick_fill){
+ sp_repr_css_set_property(css, "fill", color_string);
+ }
+ if(pick_stroke){
+ sp_repr_css_set_property(css, "stroke", color_string);
+ }
+ }
+ if (opacity < 1e-6) { // invisibly transparent, skip
+ if(!no_overlap && (picker || over_transparent || over_no_transparent)){
+ showHidden(items_down);
+ }
+ return false;
+ }
+ }
+ if(!do_trace){
+ if(!pick_center){
+ rgba = rgba2;
+ }
+ if (pick_inverse_value) {
+ r = 1 - SP_RGBA32_R_F(rgba);
+ g = 1 - SP_RGBA32_G_F(rgba);
+ b = 1 - SP_RGBA32_B_F(rgba);
+ } else {
+ r = SP_RGBA32_R_F(rgba);
+ g = SP_RGBA32_G_F(rgba);
+ b = SP_RGBA32_B_F(rgba);
+ }
+ rgba = SP_RGBA32_F_COMPOSE(r, g, b, a);
+ sp_svg_write_color(color_string, sizeof(color_string), rgba);
+ if(pick_fill){
+ sp_repr_css_set_property(css, "fill", color_string);
+ }
+ if(pick_stroke){
+ sp_repr_css_set_property(css, "stroke", color_string);
+ }
+ }
+ if(!no_overlap && (picker || over_transparent || over_no_transparent)){
+ showHidden(items_down);
+ }
+ }
+ return true;
+}
+
static bool sp_spray_recursive(SPDesktop *desktop,
Inkscape::Selection *selection,
SPItem *item,
@@ -348,7 +877,28 @@ static bool sp_spray_recursive(SPDesktop *desktop,
double ratio,
double tilt,
double rotation_variation,
- gint _distrib)
+ gint _distrib,
+ bool no_overlap,
+ bool picker,
+ bool pick_center,
+ bool pick_inverse_value,
+ bool pick_fill,
+ bool pick_stroke,
+ bool pick_no_overlap,
+ bool over_no_transparent,
+ bool over_transparent,
+ double offset,
+ bool usepressurescale,
+ double pressure,
+ int pick,
+ bool do_trace,
+ bool pick_to_size,
+ bool pick_to_presence,
+ bool pick_to_color,
+ bool pick_to_opacity,
+ bool invert_picked,
+ double gamma_picked ,
+ double rand_picked)
{
bool did = false;
@@ -364,34 +914,83 @@ static bool sp_spray_recursive(SPDesktop *desktop,
double _fid = g_random_double_range(0, 1);
double angle = g_random_double_range( - rotation_variation / 100.0 * M_PI , rotation_variation / 100.0 * M_PI );
double _scale = g_random_double_range( 1.0 - scale_variation / 100.0, 1.0 + scale_variation / 100.0 );
+ if(usepressurescale){
+ _scale = pressure;
+ }
double dr; double dp;
random_position( dr, dp, mean, standard_deviation, _distrib );
dr=dr*radius;
- if (mode == SPRAY_MODE_COPY) {
+ if (mode == SPRAY_MODE_COPY || mode == SPRAY_MODE_ERASER) {
Geom::OptRect a = item->documentVisualBounds();
if (a) {
- SPItem *item_copied;
if(_fid <= population)
{
- // Duplicate
SPDocument *doc = item->document;
+ gchar const * spray_origin;
+ if(!item->getAttribute("inkscape:spray-origin")){
+ spray_origin = g_strdup_printf("#%s", item->getId());
+ } else {
+ spray_origin = item->getAttribute("inkscape:spray-origin");
+ }
+ Geom::Point center = item->getCenter();
+ Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio), -sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ if(mode == SPRAY_MODE_ERASER || no_overlap || picker || !over_transparent || !over_no_transparent){
+ if(!fit_item(desktop
+ , item
+ , a
+ , move
+ , center
+ , mode
+ , angle
+ , _scale
+ , scale
+ , picker
+ , pick_center
+ , pick_inverse_value
+ , pick_fill
+ , pick_stroke
+ , pick_no_overlap
+ , over_no_transparent
+ , over_transparent
+ , no_overlap
+ , offset
+ , css
+ , false
+ , pick
+ , do_trace
+ , pick_to_size
+ , pick_to_presence
+ , pick_to_color
+ , pick_to_opacity
+ , invert_picked
+ , gamma_picked
+ , rand_picked)){
+ return false;
+ }
+ }
+ SPItem *item_copied;
+ // Duplicate
Inkscape::XML::Document* xml_doc = doc->getReprDoc();
Inkscape::XML::Node *old_repr = item->getRepr();
Inkscape::XML::Node *parent = old_repr->parent();
Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc);
+ if(!copy->attribute("inkscape:spray-origin")){
+ copy->setAttribute("inkscape:spray-origin", spray_origin);
+ }
parent->appendChild(copy);
-
SPObject *new_obj = doc->getObjectByRepr(copy);
item_copied = dynamic_cast<SPItem *>(new_obj); // Conversion object->item
- Geom::Point center=item->getCenter();
- sp_spray_scale_rel(center,desktop, item_copied, Geom::Scale(_scale,_scale));
- sp_spray_scale_rel(center,desktop, item_copied, Geom::Scale(scale,scale));
-
+ sp_spray_scale_rel(center,desktop, item_copied, Geom::Scale(_scale));
+ sp_spray_scale_rel(center,desktop, item_copied, Geom::Scale(scale));
sp_spray_rotate_rel(center,desktop,item_copied, Geom::Rotate(angle));
// Move the cursor p
- Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio), -sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());
sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y]));
+ Inkscape::GC::release(copy);
+ if(picker){
+ sp_desktop_apply_css_recursive(item_copied, css, true);
+ }
did = true;
}
}
@@ -404,7 +1003,7 @@ static bool sp_spray_recursive(SPDesktop *desktop,
int i=1;
std::vector<SPItem*> items=selection->itemList();
- for(std::vector<SPItem*>::const_iterator it=items.begin();it!=items.end();it++){
+ for(std::vector<SPItem*>::const_iterator it=items.begin();it!=items.end(); ++it){
SPItem *item1 = *it;
if (i == 1) {
parent_item = item1;
@@ -425,6 +1024,13 @@ static bool sp_spray_recursive(SPDesktop *desktop,
if (_fid <= population) { // Rules the population of objects sprayed
// Duplicates the parent item
Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc);
+ gchar const * spray_origin;
+ if(!copy->attribute("inkscape:spray-origin")){
+ spray_origin = g_strdup_printf("#%s", old_repr->attribute("id"));
+ copy->setAttribute("inkscape:spray-origin", spray_origin);
+ } else {
+ spray_origin = copy->attribute("inkscape:spray-origin");
+ }
parent->appendChild(copy);
SPObject *new_obj = doc->getObjectByRepr(copy);
item_copied = dynamic_cast<SPItem *>(new_obj);
@@ -456,8 +1062,52 @@ static bool sp_spray_recursive(SPDesktop *desktop,
Geom::OptRect a = item->documentVisualBounds();
if (a) {
if(_fid <= population) {
- SPItem *item_copied;
SPDocument *doc = item->document;
+ gchar const * spray_origin;
+ if(!item->getAttribute("inkscape:spray-origin")){
+ spray_origin = g_strdup_printf("#%s", item->getId());
+ } else {
+ spray_origin = item->getAttribute("inkscape:spray-origin");
+ }
+ Geom::Point center=item->getCenter();
+ Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio), -sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ if(mode == SPRAY_MODE_ERASER || no_overlap || picker || !over_transparent || !over_no_transparent){
+ if(!fit_item(desktop
+ , item
+ , a
+ , move
+ , center
+ , mode
+ , angle
+ , _scale
+ , scale
+ , picker
+ , pick_center
+ , pick_inverse_value
+ , pick_fill
+ , pick_stroke
+ , pick_no_overlap
+ , over_no_transparent
+ , over_transparent
+ , no_overlap
+ , offset
+ , css
+ , true
+ , pick
+ , do_trace
+ , pick_to_size
+ , pick_to_presence
+ , pick_to_color
+ , pick_to_opacity
+ , invert_picked
+ , gamma_picked
+ , rand_picked))
+ {
+ return false;
+ }
+ }
+ SPItem *item_copied;
Inkscape::XML::Document* xml_doc = doc->getReprDoc();
Inkscape::XML::Node *old_repr = item->getRepr();
Inkscape::XML::Node *parent = old_repr->parent();
@@ -467,6 +1117,9 @@ static bool sp_spray_recursive(SPDesktop *desktop,
// Ad the clone to the list of the parent's children
parent->appendChild(clone);
// Generates the link between parent and child attributes
+ if(!clone->attribute("inkscape:spray-origin")){
+ clone->setAttribute("inkscape:spray-origin", spray_origin);
+ }
gchar *href_str = g_strdup_printf("#%s", old_repr->attribute("id"));
clone->setAttribute("xlink:href", href_str, false);
g_free(href_str);
@@ -474,15 +1127,14 @@ static bool sp_spray_recursive(SPDesktop *desktop,
SPObject *clone_object = doc->getObjectByRepr(clone);
// Conversion object->item
item_copied = dynamic_cast<SPItem *>(clone_object);
- Geom::Point center = item->getCenter();
sp_spray_scale_rel(center, desktop, item_copied, Geom::Scale(_scale, _scale));
sp_spray_scale_rel(center, desktop, item_copied, Geom::Scale(scale, scale));
sp_spray_rotate_rel(center, desktop, item_copied, Geom::Rotate(angle));
- Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio), -sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());
sp_item_move_rel(item_copied, Geom::Translate(move[Geom::X], -move[Geom::Y]));
-
+ if(picker){
+ sp_desktop_apply_css_recursive(item_copied, css, true);
+ }
Inkscape::GC::release(clone);
-
did = true;
}
}
@@ -520,22 +1172,57 @@ static bool sp_spray_dilate(SprayTool *tc, Geom::Point /*event_p*/, Geom::Point
{
std::vector<SPItem*> const items(selection->itemList());
- for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end(); ++i){
SPItem *item = *i;
g_assert(item != NULL);
sp_object_ref(item);
}
- for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end(); ++i){
SPItem *item = *i;
g_assert(item != NULL);
-
- if (sp_spray_recursive(desktop, selection, item, p, vector, tc->mode, radius, population, tc->scale, tc->scale_variation, reverse, move_mean, move_standard_deviation, tc->ratio, tc->tilt, tc->rotation_variation, tc->distrib)) {
+ if (sp_spray_recursive(desktop
+ , selection
+ , item
+ , p, vector
+ , tc->mode
+ , radius
+ , population
+ , tc->scale
+ , tc->scale_variation
+ , reverse
+ , move_mean
+ , move_standard_deviation
+ , tc->ratio
+ , tc->tilt
+ , tc->rotation_variation
+ , tc->distrib
+ , tc->no_overlap
+ , tc->picker
+ , tc->pick_center
+ , tc->pick_inverse_value
+ , tc->pick_fill
+ , tc->pick_stroke
+ , tc->pick_no_overlap
+ , tc->over_no_transparent
+ , tc->over_transparent
+ , tc->offset
+ , tc->usepressurescale
+ , get_pressure(tc)
+ , tc->pick
+ , tc->do_trace
+ , tc->pick_to_size
+ , tc->pick_to_presence
+ , tc->pick_to_color
+ , tc->pick_to_opacity
+ , tc->invert_picked
+ , tc->gamma_picked
+ , tc->rand_picked)) {
did = true;
}
}
- for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end(); ++i){
SPItem *item = *i;
g_assert(item != NULL);
sp_object_unref(item);
@@ -577,7 +1264,7 @@ bool SprayTool::root_handler(GdkEvent* event) {
if (Inkscape::have_viable_layer(desktop, this->message_context) == false) {
return TRUE;
}
-
+ this->setCloneTilerPrefs();
Geom::Point const motion_w(event->button.x, event->button.y);
Geom::Point const motion_dt(desktop->w2d(motion_w));
this->last_push = desktop->dt2doc(motion_dt);
diff --git a/src/ui/tools/spray-tool.h b/src/ui/tools/spray-tool.h
index 8df730201..c81110b37 100644
--- a/src/ui/tools/spray-tool.h
+++ b/src/ui/tools/spray-tool.h
@@ -12,6 +12,7 @@
* BenoƮt LAVORATA
* Vincent MONTAGNE
* Pierre BARBRY-BLOT
+ * Jabiertxo ARRAIZA
*
* Copyright (C) 2009 authors
*
@@ -46,7 +47,8 @@ namespace Tools {
enum {
SPRAY_MODE_COPY,
SPRAY_MODE_CLONE,
- SPRAY_MODE_SINGLE_PATH,
+ SPRAY_MODE_SINGLE_PATH,
+ SPRAY_MODE_ERASER,
SPRAY_OPTION,
};
@@ -62,7 +64,9 @@ public:
/* attributes */
bool dragging; /* mouse state: mouse is dragging */
- bool usepressure;
+ bool usepressurewidth;
+ bool usepressurepopulation;
+ bool usepressurescale;
bool usetilt;
bool usetext;
@@ -86,13 +90,32 @@ public:
bool has_dilated;
Geom::Point last_push;
SPCanvasItem *dilate_area;
-
+ bool no_overlap;
+ bool picker;
+ bool pick_center;
+ bool pick_inverse_value;
+ bool pick_fill;
+ bool pick_stroke;
+ bool pick_no_overlap;
+ bool over_transparent;
+ bool over_no_transparent;
+ double offset;
+ int pick;
+ bool do_trace;
+ bool pick_to_size;
+ bool pick_to_presence;
+ bool pick_to_color;
+ bool pick_to_opacity;
+ bool invert_picked;
+ double gamma_picked;
+ double rand_picked;
sigc::connection style_set_connection;
static const std::string prefsPath;
virtual void setup();
virtual void set(const Inkscape::Preferences::Entry& val);
+ virtual void setCloneTilerPrefs();
virtual bool root_handler(GdkEvent* event);
virtual const std::string& getPrefsPath();
diff --git a/src/ui/tools/tool-base.cpp b/src/ui/tools/tool-base.cpp
index 0f9b3ee7a..abac2c091 100644
--- a/src/ui/tools/tool-base.cpp
+++ b/src/ui/tools/tool-base.cpp
@@ -358,7 +358,7 @@ bool ToolBase::root_handler(GdkEvent* event) {
/// @todo REmove redundant /value in preference keys
tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100);
-
+ bool allow_panning = prefs->getBool("/options/spacebarpans/value");
gint ret = FALSE;
switch (event->type) {
@@ -582,7 +582,6 @@ bool ToolBase::root_handler(GdkEvent* event) {
case GDK_KEY_PRESS: {
double const acceleration = prefs->getDoubleLimited(
"/options/scrollingacceleration/value", 0, 0, 6);
-
int const key_scroll = prefs->getIntLimited("/options/keyscroll/value",
10, 0, 1000);
@@ -692,10 +691,10 @@ bool ToolBase::root_handler(GdkEvent* event) {
break;
case GDK_KEY_space:
- xp = yp = 0;
within_tolerance = true;
+ xp = yp = 0;
+ if (!allow_panning) break;
panning = 4;
-
this->space_panning = true;
this->message_context->set(Inkscape::INFORMATION_MESSAGE,
_("<b>Space+mouse move</b> to pan canvas"));
@@ -742,7 +741,7 @@ bool ToolBase::root_handler(GdkEvent* event) {
switch (get_group0_keyval(&event->key)) {
case GDK_KEY_space:
- if (within_tolerance == true) {
+ if (within_tolerance) {
// Space was pressed, but not panned
sp_toggle_selector(desktop);
@@ -925,7 +924,7 @@ void ToolBase::enableGrDrag(bool enable) {
*/
bool ToolBase::deleteSelectedDrag(bool just_one) {
- if (_grdrag && _grdrag->selected) {
+ if (_grdrag && !_grdrag->selected.empty()) {
_grdrag->deleteSelected(just_one);
return TRUE;
}
diff --git a/src/ui/tools/tool-base.h b/src/ui/tools/tool-base.h
index 7a6ab83e7..58eb6f88e 100644
--- a/src/ui/tools/tool-base.h
+++ b/src/ui/tools/tool-base.h
@@ -75,7 +75,12 @@ public:
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
double value = prefs->getDoubleLimited("/options/snapdelay/value", 0, 0, 1000);
- _timer_id = g_timeout_add(value, &sp_event_context_snap_watchdog_callback, this);
+ // We used to have this specified in milliseconds; this has changed to seconds now for consistency's sake
+ if (value > 1) { // Apparently we have an old preference file, this value must have been in milliseconds;
+ value = value / 1000.0; // now convert this value to seconds
+ }
+
+ _timer_id = g_timeout_add(value*1000.0, &sp_event_context_snap_watchdog_callback, this);
_event = gdk_event_copy((GdkEvent*) event);
((GdkEventMotion *)_event)->time = GDK_CURRENT_TIME;
diff --git a/src/ui/tools/tweak-tool.cpp b/src/ui/tools/tweak-tool.cpp
index 94f7aa135..39a7a3f0b 100644
--- a/src/ui/tools/tweak-tool.cpp
+++ b/src/ui/tools/tweak-tool.cpp
@@ -1077,7 +1077,7 @@ sp_tweak_dilate (TweakTool *tc, Geom::Point event_p, Geom::Point p, Geom::Point
double color_force = MIN(sqrt(path_force)/20.0, 1);
std::vector<SPItem*> items=selection->itemList();
- for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end();i++){
+ for(std::vector<SPItem*>::const_iterator i=items.begin();i!=items.end(); ++i){
SPItem *item = *i;
if (is_color_mode (tc->mode)) {
diff --git a/src/ui/tools/zoom-tool.cpp b/src/ui/tools/zoom-tool.cpp
index 6a4d4dbbd..13e097c18 100644
--- a/src/ui/tools/zoom-tool.cpp
+++ b/src/ui/tools/zoom-tool.cpp
@@ -142,7 +142,7 @@ bool ZoomTool::root_handler(GdkEvent* event) {
if ( event->button.button == 1 && !this->space_panning) {
Geom::OptRect const b = Inkscape::Rubberband::get(desktop)->getRectangle();
- if (b && !within_tolerance) {
+ if (b && !within_tolerance && !(GDK_SHIFT_MASK & event->button.state) ) {
desktop->set_display_area(*b, 10);
} else if (!escaped) {
double const zoom_rel( (event->button.state & GDK_SHIFT_MASK)
diff --git a/src/ui/uxmanager.cpp b/src/ui/uxmanager.cpp
index 051df691e..036659661 100644
--- a/src/ui/uxmanager.cpp
+++ b/src/ui/uxmanager.cpp
@@ -244,12 +244,13 @@ void UXManagerImpl::delTrack( SPDesktopWidget* dtw )
void UXManagerImpl::connectToDesktop( vector<GtkWidget *> const & toolboxes, SPDesktop *desktop )
{
- TrackItem &tracker = trackedBoxes[desktop];
- vector<GtkWidget*>& tracked = tracker.boxes;
- if (desktop)
+ if (!desktop)
{
- tracker.destroyConn = desktop->connectDestroy(&desktopDestructHandler);
+ return;
}
+ TrackItem &tracker = trackedBoxes[desktop];
+ vector<GtkWidget*>& tracked = tracker.boxes;
+ tracker.destroyConn = desktop->connectDestroy(&desktopDestructHandler);
for (vector<GtkWidget*>::const_iterator it = toolboxes.begin(); it != toolboxes.end(); ++it ) {
GtkWidget* toolbox = *it;
diff --git a/src/ui/view/edit-widget-interface.h b/src/ui/view/edit-widget-interface.h
index 55683871d..fcba0c6da 100644
--- a/src/ui/view/edit-widget-interface.h
+++ b/src/ui/view/edit-widget-interface.h
@@ -116,6 +116,9 @@ struct EditWidgetInterface
/// Toggle CMS on/off and set preference value accordingly
virtual void toggleColorProfAdjust() = 0;
+ /// Toggle lock guides on/off and set namedview value accordingly
+ virtual void toggleGuidesLock() = 0;
+
/// Is CMS on/off
virtual bool colorProfAdjustEnabled() = 0;
diff --git a/src/ui/widget/color-entry.h b/src/ui/widget/color-entry.h
index edabe1980..08537f26d 100644
--- a/src/ui/widget/color-entry.h
+++ b/src/ui/widget/color-entry.h
@@ -9,7 +9,7 @@
*/
#ifndef SEEN_COLOR_ENTRY_H
-#define SEEN_COLOR_ENTRY_H_
+#define SEEN_COLOR_ENTRY_H
#include <gtkmm/entry.h>
#include "ui/selected-color.h"
diff --git a/src/ui/widget/color-icc-selector.cpp b/src/ui/widget/color-icc-selector.cpp
index 1c31ae33a..2fe4a0704 100644
--- a/src/ui/widget/color-icc-selector.cpp
+++ b/src/ui/widget/color-icc-selector.cpp
@@ -676,9 +676,9 @@ void ColorICCSelectorImpl::_profilesChanged(std::string const &name)
gtk_combo_box_set_active(combo, 0);
int index = 1;
- const GSList *current = SP_ACTIVE_DOCUMENT->getResourceList("iccprofile");
- while (current) {
- SPObject *obj = SP_OBJECT(current->data);
+ std::set<SPObject *> current = SP_ACTIVE_DOCUMENT->getResourceList("iccprofile");
+ for (std::set<SPObject *>::const_iterator it = current.begin(); it != current.end(); ++it) {
+ SPObject *obj = *it;
Inkscape::ColorProfile *prof = reinterpret_cast<Inkscape::ColorProfile *>(obj);
gtk_list_store_append(store, &iter);
@@ -690,7 +690,6 @@ void ColorICCSelectorImpl::_profilesChanged(std::string const &name)
}
index++;
- current = g_slist_next(current);
}
g_signal_handler_unblock(G_OBJECT(_profileSel), _profChangedID);
diff --git a/src/ui/widget/font-variants.cpp b/src/ui/widget/font-variants.cpp
index 5d1e40971..62598dead 100644
--- a/src/ui/widget/font-variants.cpp
+++ b/src/ui/widget/font-variants.cpp
@@ -35,41 +35,41 @@ namespace Widget {
FontVariants::FontVariants () :
Gtk::VBox (),
- _ligatures_frame ( Glib::ustring(_("Ligatures" )) ),
- _ligatures_common ( Glib::ustring(_("Common" )) ),
- _ligatures_discretionary ( Glib::ustring(_("Discretionary")) ),
- _ligatures_historical ( Glib::ustring(_("Historical" )) ),
- _ligatures_contextual ( Glib::ustring(_("Contextual" )) ),
-
- _position_frame ( Glib::ustring(_("Position" )) ),
- _position_normal ( Glib::ustring(_("Normal" )) ),
- _position_sub ( Glib::ustring(_("Subscript" )) ),
- _position_super ( Glib::ustring(_("Superscript" )) ),
-
- _caps_frame ( Glib::ustring(_("Capitals" )) ),
- _caps_normal ( Glib::ustring(_("Normal" )) ),
- _caps_small ( Glib::ustring(_("Small" )) ),
- _caps_all_small ( Glib::ustring(_("All small" )) ),
- _caps_petite ( Glib::ustring(_("Petite" )) ),
- _caps_all_petite ( Glib::ustring(_("All petite" )) ),
- _caps_unicase ( Glib::ustring(_("Unicase" )) ),
- _caps_titling ( Glib::ustring(_("Titling" )) ),
-
- _numeric_frame ( Glib::ustring(_("Numeric" )) ),
- _numeric_lining ( Glib::ustring(_("Lining" )) ),
- _numeric_old_style ( Glib::ustring(_("Old Style" )) ),
- _numeric_default_style ( Glib::ustring(_("Default Style")) ),
- _numeric_proportional ( Glib::ustring(_("Proportional" )) ),
- _numeric_tabular ( Glib::ustring(_("Tabular" )) ),
- _numeric_default_width ( Glib::ustring(_("Default Width")) ),
- _numeric_diagonal ( Glib::ustring(_("Diagonal" )) ),
- _numeric_stacked ( Glib::ustring(_("Stacked" )) ),
- _numeric_default_fractions( Glib::ustring(_("Default Fractions")) ),
- _numeric_ordinal ( Glib::ustring(_("Ordinal" )) ),
- _numeric_slashed_zero ( Glib::ustring(_("Slashed Zero" )) ),
-
- _feature_frame ( Glib::ustring(_("Feature Settings")) ),
- _feature_label ( Glib::ustring(_("Selection has different Feature Settings!")) ),
+ _ligatures_frame ( Glib::ustring(C_("Font variant", "Ligatures" )) ),
+ _ligatures_common ( Glib::ustring(C_("Font variant", "Common" )) ),
+ _ligatures_discretionary ( Glib::ustring(C_("Font variant", "Discretionary")) ),
+ _ligatures_historical ( Glib::ustring(C_("Font variant", "Historical" )) ),
+ _ligatures_contextual ( Glib::ustring(C_("Font variant", "Contextual" )) ),
+
+ _position_frame ( Glib::ustring(C_("Font variant", "Position" )) ),
+ _position_normal ( Glib::ustring(C_("Font variant", "Normal" )) ),
+ _position_sub ( Glib::ustring(C_("Font variant", "Subscript" )) ),
+ _position_super ( Glib::ustring(C_("Font variant", "Superscript" )) ),
+
+ _caps_frame ( Glib::ustring(C_("Font variant", "Capitals" )) ),
+ _caps_normal ( Glib::ustring(C_("Font variant", "Normal" )) ),
+ _caps_small ( Glib::ustring(C_("Font variant", "Small" )) ),
+ _caps_all_small ( Glib::ustring(C_("Font variant", "All small" )) ),
+ _caps_petite ( Glib::ustring(C_("Font variant", "Petite" )) ),
+ _caps_all_petite ( Glib::ustring(C_("Font variant", "All petite" )) ),
+ _caps_unicase ( Glib::ustring(C_("Font variant", "Unicase" )) ),
+ _caps_titling ( Glib::ustring(C_("Font variant", "Titling" )) ),
+
+ _numeric_frame ( Glib::ustring(C_("Font variant", "Numeric" )) ),
+ _numeric_lining ( Glib::ustring(C_("Font variant", "Lining" )) ),
+ _numeric_old_style ( Glib::ustring(C_("Font variant", "Old Style" )) ),
+ _numeric_default_style ( Glib::ustring(C_("Font variant", "Default Style")) ),
+ _numeric_proportional ( Glib::ustring(C_("Font variant", "Proportional" )) ),
+ _numeric_tabular ( Glib::ustring(C_("Font variant", "Tabular" )) ),
+ _numeric_default_width ( Glib::ustring(C_("Font variant", "Default Width")) ),
+ _numeric_diagonal ( Glib::ustring(C_("Font variant", "Diagonal" )) ),
+ _numeric_stacked ( Glib::ustring(C_("Font variant", "Stacked" )) ),
+ _numeric_default_fractions( Glib::ustring(C_("Font variant", "Default Fractions")) ),
+ _numeric_ordinal ( Glib::ustring(C_("Font variant", "Ordinal" )) ),
+ _numeric_slashed_zero ( Glib::ustring(C_("Font variant", "Slashed Zero" )) ),
+
+ _feature_frame ( Glib::ustring(C_("Font variant", "Feature Settings")) ),
+ _feature_label ( Glib::ustring(C_("Font variant", "Selection has different Feature Settings!")) ),
_ligatures_changed( false ),
_position_changed( false ),
diff --git a/src/ui/widget/preferences-widget.cpp b/src/ui/widget/preferences-widget.cpp
index 72597e4d9..e906762e3 100644
--- a/src/ui/widget/preferences-widget.cpp
+++ b/src/ui/widget/preferences-widget.cpp
@@ -205,6 +205,7 @@ void PrefCheckButton::init(Glib::ustring const &label, Glib::ustring const &pref
void PrefCheckButton::on_toggled()
{
+ this->changed_signal.emit(this->get_active());
if (this->get_visible()) //only take action if the user toggled it
{
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
diff --git a/src/ui/widget/preferences-widget.h b/src/ui/widget/preferences-widget.h
index 8b75b8368..1d2d77699 100644
--- a/src/ui/widget/preferences-widget.h
+++ b/src/ui/widget/preferences-widget.h
@@ -59,6 +59,7 @@ class PrefCheckButton : public Gtk::CheckButton
public:
void init(Glib::ustring const &label, Glib::ustring const &prefs_path,
bool default_value);
+ sigc::signal<void, bool> changed_signal;
protected:
Glib::ustring _prefs_path;
void on_toggled();
diff --git a/src/ui/widget/unit-tracker.cpp b/src/ui/widget/unit-tracker.cpp
index c6318db25..a1501c229 100644
--- a/src/ui/widget/unit-tracker.cpp
+++ b/src/ui/widget/unit-tracker.cpp
@@ -12,6 +12,7 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include "style-internal.h"
#include "unit-tracker.h"
#include "widgets/ege-select-one-action.h"
@@ -121,6 +122,15 @@ void UnitTracker::addUnit(Inkscape::Util::Unit const *u)
gtk_list_store_set(_store, &iter, COLUMN_STRING, u ? u->abbr.c_str() : "NULL", -1);
}
+void UnitTracker::prependUnit(Inkscape::Util::Unit const *u)
+{
+ GtkTreeIter iter;
+ gtk_list_store_prepend(_store, &iter);
+ gtk_list_store_set(_store, &iter, COLUMN_STRING, u ? u->abbr.c_str() : "NULL", -1);
+ /* Re-shuffle our default selection here (_active gets out of sync) */
+ setActiveUnit(_activeUnit);
+}
+
void UnitTracker::setFullVal(GtkAdjustment *adj, gdouble val)
{
_priorValues[adj] = val;
diff --git a/src/ui/widget/unit-tracker.h b/src/ui/widget/unit-tracker.h
index 06245930e..0fe5bda80 100644
--- a/src/ui/widget/unit-tracker.h
+++ b/src/ui/widget/unit-tracker.h
@@ -42,6 +42,7 @@ public:
Inkscape::Util::Unit const * getActiveUnit() const;
void addUnit(Inkscape::Util::Unit const *u);
+ void prependUnit(Inkscape::Util::Unit const *u);
void addAdjustment(GtkAdjustment *adj);
void setFullVal(GtkAdjustment *adj, gdouble val);