summaryrefslogtreecommitdiffstats
path: root/src/ui
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2016-03-14 16:47:47 +0000
committerJabiertxof <jtx@jtx.marker.es>2016-03-14 16:47:47 +0000
commitfee7ec667cc353e1efda6a1a92f1f4715836fa4f (patch)
tree63fe115530cd3f8511b29cf2e250fcf23dc8fe08 /src/ui
parentupdate credits (diff)
parent"Relative to" option for node alignment. (diff)
downloadinkscape-fee7ec667cc353e1efda6a1a92f1f4715836fa4f.tar.gz
inkscape-fee7ec667cc353e1efda6a1a92f1f4715836fa4f.zip
update to trunk
(bzr r13682.1.32)
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.cpp88
-rw-r--r--src/ui/dialog/inkscape-preferences.h9
-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/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/unit-tracker.cpp10
-rw-r--r--src/ui/widget/unit-tracker.h1
85 files changed, 3509 insertions, 1535 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 98695e080..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,11 +1262,9 @@ 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"));
diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h
index 7e0184c55..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,
@@ -494,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/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/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);