summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/selection-chemistry.cpp32
-rw-r--r--src/selection-chemistry.h6
-rw-r--r--src/sp-lpe-item.cpp36
-rw-r--r--src/ui/tools/eraser-tool.cpp145
-rw-r--r--src/ui/tools/eraser-tool.h4
-rw-r--r--src/widgets/eraser-toolbar.cpp154
-rw-r--r--src/widgets/toolbox.cpp7
7 files changed, 302 insertions, 82 deletions
diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp
index 834f82edc..7bed0a71d 100644
--- a/src/selection-chemistry.cpp
+++ b/src/selection-chemistry.cpp
@@ -1021,6 +1021,7 @@ void sp_selection_raise(Inkscape::Selection *selection, SPDesktop *desktop)
C_("Undo action", "Raise"));
}
+
void sp_object_set_raise_to_top(ObjectSet *set) {
std::vector<Inkscape::XML::Node*> rl(set->xmlNodes().begin(), set->xmlNodes().end());
sort(rl.begin(),rl.end(),sp_repr_compare_position_bool);
@@ -1031,7 +1032,7 @@ void sp_object_set_raise_to_top(ObjectSet *set) {
}
}
-void sp_selection_raise_to_top(Inkscape::Selection *selection, SPDesktop *desktop)
+void sp_selection_raise_to_top(Inkscape::Selection *selection, SPDesktop *desktop, bool skip_undo)
{
SPDocument *document = selection->layers()->getDocument();
@@ -1048,8 +1049,10 @@ void sp_selection_raise_to_top(Inkscape::Selection *selection, SPDesktop *deskto
sp_object_set_raise_to_top(selection);
- DocumentUndo::done(document, SP_VERB_SELECTION_TO_FRONT,
- _("Raise to top"));
+ if (!skip_undo) {
+ DocumentUndo::done(document, SP_VERB_SELECTION_TO_FRONT,
+ _("Raise to top"));
+ }
}
void sp_object_set_lower(ObjectSet *set) {
@@ -1111,6 +1114,7 @@ void sp_selection_lower(Inkscape::Selection *selection, SPDesktop *desktop)
C_("Undo action", "Lower"));
}
+
void sp_object_set_lower_to_bottom(ObjectSet *set) {
std::vector<Inkscape::XML::Node*> rl(set->xmlNodes().begin(), set->xmlNodes().end());
sort(rl.begin(),rl.end(),sp_repr_compare_position_bool);
@@ -1132,7 +1136,7 @@ void sp_object_set_lower_to_bottom(ObjectSet *set) {
}
}
-void sp_selection_lower_to_bottom(Inkscape::Selection *selection, SPDesktop *desktop)
+void sp_selection_lower_to_bottom(Inkscape::Selection *selection, SPDesktop *desktop, bool skip_undo)
{
if (selection->isEmpty()) {
selection_display_message(desktop, Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to lower to bottom."));
@@ -1146,9 +1150,10 @@ void sp_selection_lower_to_bottom(Inkscape::Selection *selection, SPDesktop *des
}
sp_object_set_lower_to_bottom(selection);
-
- DocumentUndo::done(selection->layers()->getDocument(), SP_VERB_SELECTION_TO_BACK,
- _("Lower to bottom"));
+ if (!skip_undo) {
+ DocumentUndo::done(desktop->getDocument(), SP_VERB_SELECTION_TO_BACK,
+ _("Lower to bottom"));
+ }
}
void
@@ -3859,7 +3864,7 @@ void sp_selection_set_clipgroup(SPDesktop *desktop)
* If \a apply_clip_path parameter is true, clipPath is created, otherwise mask
*
*/
-void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_layer)
+void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_layer, bool skip_undo)
{
if (desktop == NULL) {
return;
@@ -4017,11 +4022,12 @@ void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_
}
selection->addList(items_to_select);
-
- if (apply_clip_path) {
- DocumentUndo::done(doc, SP_VERB_OBJECT_SET_CLIPPATH, _("Set clipping path"));
- } else {
- DocumentUndo::done(doc, SP_VERB_OBJECT_SET_MASK, _("Set mask"));
+ if (!skip_undo) {
+ if (apply_clip_path) {
+ DocumentUndo::done(doc, SP_VERB_OBJECT_SET_CLIPPATH, _("Set clipping path"));
+ } else {
+ DocumentUndo::done(doc, SP_VERB_OBJECT_SET_MASK, _("Set mask"));
+ }
}
}
diff --git a/src/selection-chemistry.h b/src/selection-chemistry.h
index ca9062320..72e4acc66 100644
--- a/src/selection-chemistry.h
+++ b/src/selection-chemistry.h
@@ -85,9 +85,9 @@ void sp_object_set_lower(Inkscape::ObjectSet *set);
void sp_object_set_lower_to_bottom(Inkscape::ObjectSet *set);
void sp_selection_raise(Inkscape::Selection *selection, SPDesktop *desktop);
-void sp_selection_raise_to_top(Inkscape::Selection *selection, SPDesktop *desktop);
+void sp_selection_raise_to_top(Inkscape::Selection *selection, SPDesktop *desktop, bool skip_undo = false);
void sp_selection_lower(Inkscape::Selection *selection, SPDesktop *desktop);
-void sp_selection_lower_to_bottom(Inkscape::Selection *selection, SPDesktop *desktop);
+void sp_selection_lower_to_bottom(Inkscape::Selection *selection, SPDesktop *desktop, bool skip_undo = false);
SPCSSAttr *take_style_from_item (SPObject *object);
@@ -164,7 +164,7 @@ void sp_document_get_export_hints (SPDocument * doc, Glib::ustring &filename, fl
void sp_selection_create_bitmap_copy (SPDesktop *desktop);
void sp_selection_set_clipgroup(SPDesktop *desktop);
-void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_layer);
+void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_layer, bool skip_undo = false);
void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path);
bool fit_canvas_to_selection(SPDesktop *, bool with_margins = false);
diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp
index 4719f98d0..d83593b31 100644
--- a/src/sp-lpe-item.cpp
+++ b/src/sp-lpe-item.cpp
@@ -337,10 +337,10 @@ sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem)
{
sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(mask->firstChild()));
}
- SPClipPath * clipPath = lpeitem->clip_ref->getObject();
- if(clipPath)
+ SPClipPath * clip_path = lpeitem->clip_ref->getObject();
+ if(clip_path)
{
- sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(clipPath->firstChild()));
+ sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild()));
}
if (SP_IS_GROUP(lpeitem)) {
std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(lpeitem));
@@ -371,10 +371,10 @@ sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem)
{
sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(mask->firstChild()));
}
- SPClipPath * clipPath = lpeitem->clip_ref->getObject();
- if(clipPath)
+ SPClipPath * clip_path = lpeitem->clip_ref->getObject();
+ if(clip_path)
{
- sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clipPath->firstChild()));
+ sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild()));
}
}
std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(lpeitem));
@@ -393,10 +393,10 @@ sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem)
{
sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(mask->firstChild()));
}
- SPClipPath * clipPath = lpeitem->clip_ref->getObject();
- if(clipPath)
+ SPClipPath * clip_path = lpeitem->clip_ref->getObject();
+ if(clip_path)
{
- sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clipPath->firstChild()));
+ sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild()));
}
repr->setAttribute("d", repr->attribute("inkscape:original-d"));
repr->setAttribute("inkscape:original-d", NULL);
@@ -628,10 +628,13 @@ bool SPLPEItem::hasPathEffectRecursive() const
void
SPLPEItem::apply_to_clippath(SPItem *item)
{
- SPClipPath *clipPath = item->clip_ref->getObject();
- if(clipPath) {
- SPObject * clip_data = clipPath->firstChild();
- apply_to_clip_or_mask(SP_ITEM(clip_data), item);
+ SPClipPath *clip_path = item->clip_ref->getObject();
+ if(clip_path) {
+ std::vector<SPObject*> clip_path_list = clip_path->childList(true);
+ for ( std::vector<SPObject*>::const_iterator iter=clip_path_list.begin();iter!=clip_path_list.end();++iter) {
+ SPObject * clip_data = *iter;
+ apply_to_clip_or_mask(SP_ITEM(clip_data), item);
+ }
}
if(SP_IS_GROUP(item)){
std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(item));
@@ -647,8 +650,11 @@ SPLPEItem::apply_to_mask(SPItem *item)
{
SPMask *mask = item->mask_ref->getObject();
if(mask) {
- SPObject *mask_data = mask->firstChild();
- apply_to_clip_or_mask(SP_ITEM(mask_data), item);
+ std::vector<SPObject*> mask_list = mask->childList(true);
+ for ( std::vector<SPObject*>::const_iterator iter=mask_list.begin();iter!=mask_list.end();++iter) {
+ SPObject * mask_data = *iter;
+ apply_to_clip_or_mask(SP_ITEM(mask_data), item);
+ }
}
if(SP_IS_GROUP(item)){
std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(item));
diff --git a/src/ui/tools/eraser-tool.cpp b/src/ui/tools/eraser-tool.cpp
index 4b40262cd..38c72cac0 100644
--- a/src/ui/tools/eraser-tool.cpp
+++ b/src/ui/tools/eraser-tool.cpp
@@ -51,15 +51,21 @@
#include "sp-item-group.h"
#include "sp-shape.h"
#include "sp-path.h"
+#include "sp-clippath.h"
+#include "sp-rect.h"
#include "sp-text.h"
+#include "sp-root.h"
+#include "display/canvas-bpath.h"
#include "display/canvas-arena.h"
#include "document-undo.h"
#include "verbs.h"
#include "style.h"
#include <2geom/pathvector.h>
#include "path-chemistry.h"
+#include "selection-chemistry.h"
#include "display/curve.h"
-
+#include "layer-model.h"
+#include "layer-manager.h"
#include "ui/tools/eraser-tool.h"
using Inkscape::DocumentUndo;
@@ -369,7 +375,7 @@ 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;
+ gint eraser_mode = prefs->getInt("/tools/eraser/mode", 2);
switch (event->type) {
case GDK_BUTTON_PRESS:
if (event->button.button == 1 && !this->space_panning) {
@@ -389,7 +395,7 @@ bool EraserTool::root_handler(GdkEvent* event) {
if (this->repr) {
this->repr = NULL;
}
- if ( ! eraserMode ) {
+ if ( eraser_mode == ERASER_MODE_DELETE ) {
Inkscape::Rubberband::get(desktop)->start(desktop, button_dt);
Inkscape::Rubberband::get(desktop)->setMode(RUBBERBAND_MODE_TOUCHPATH);
}
@@ -437,7 +443,7 @@ bool EraserTool::root_handler(GdkEvent* event) {
ret = TRUE;
}
- if ( !eraserMode ) {
+ if ( eraser_mode == ERASER_MODE_DELETE ) {
this->accumulated->reset();
Inkscape::Rubberband::get(desktop)->move(motion_dt);
}
@@ -480,7 +486,7 @@ bool EraserTool::root_handler(GdkEvent* event) {
ret = TRUE;
}
- if (!eraserMode && Inkscape::Rubberband::get(desktop)->is_started()) {
+ if (eraser_mode == ERASER_MODE_DELETE && Inkscape::Rubberband::get(desktop)->is_started()) {
Inkscape::Rubberband::get(desktop)->stop();
}
@@ -567,7 +573,7 @@ bool EraserTool::root_handler(GdkEvent* event) {
break;
case GDK_KEY_Escape:
- if ( !eraserMode ) {
+ if ( eraser_mode == ERASER_MODE_DELETE ) {
Inkscape::Rubberband::get(desktop)->stop();
}
if (this->is_drawing) {
@@ -629,52 +635,53 @@ void EraserTool::clear_current() {
void EraserTool::set_to_accumulated() {
bool workDone = false;
-
+ SPDocument *document = this->desktop->doc();
if (!this->accumulated->is_empty()) {
if (!this->repr) {
/* Create object */
- Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
+ Inkscape::XML::Document *xml_doc = this->desktop->doc()->getReprDoc();
Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
/* Set style */
- sp_desktop_apply_style_tool (desktop, repr, "/tools/eraser", false);
+ sp_desktop_apply_style_tool (this->desktop, repr, "/tools/eraser", false);
this->repr = repr;
}
- SPItem *item = SP_ITEM(desktop->currentLayer()->appendChildRepr(this->repr));
+ SPObject * top_layer = desktop->layer_manager->nthChildOf(desktop->layers->currentRoot(), 0);
+ SPItem *item_repr = SP_ITEM(top_layer->appendChildRepr(this->repr));
Inkscape::GC::release(this->repr);
- item->updateRepr();
- Geom::PathVector pathv = this->accumulated->get_pathvector() * desktop->dt2doc();
- pathv *= item->i2doc_affine().inverse();
+ item_repr->updateRepr();
+ Geom::PathVector pathv = this->accumulated->get_pathvector() * this->desktop->dt2doc();
+ pathv *= item_repr->i2doc_affine().inverse();
gchar *str = sp_svg_write_path(pathv);
g_assert( str != NULL );
this->repr->setAttribute("d", str);
g_free(str);
-
+ Geom::OptRect eraserBbox;
if ( this->repr ) {
bool wasSelection = false;
- Inkscape::Selection *selection = desktop->getSelection();
+ Inkscape::Selection *selection = this->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();
+ gint eraser_mode = prefs->getInt("/tools/eraser/mode", ERASER_MODE_CLIP);
+ Inkscape::XML::Document *xml_doc = this->desktop->doc()->getReprDoc();
- SPItem* acid = SP_ITEM(desktop->doc()->getObjectByRepr(this->repr));
- Geom::OptRect eraserBbox = acid->desktopVisualBounds();
+ SPItem* acid = SP_ITEM(this->desktop->doc()->getObjectByRepr(this->repr));
+ eraserBbox = acid->desktopVisualBounds();
std::vector<SPItem*> remainingItems;
std::vector<SPItem*> toWorkOn;
if (selection->isEmpty()) {
- if ( eraserMode ) {
- toWorkOn = desktop->getDocument()->getItemsPartiallyInBox(desktop->dkey, *eraserBbox);
+ if (eraser_mode == ERASER_MODE_CUT || eraser_mode == ERASER_MODE_CLIP) {
+ toWorkOn = document->getItemsPartiallyInBox(this->desktop->dkey, *eraserBbox);
} else {
- Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop);
- toWorkOn = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints());
+ Inkscape::Rubberband *r = Inkscape::Rubberband::get(this->desktop);
+ toWorkOn = document->getItemsAtPoints(this->desktop->dkey, r->getPoints());
}
toWorkOn.erase(std::remove(toWorkOn.begin(), toWorkOn.end(), acid), toWorkOn.end());
} else {
- if ( !eraserMode ) {
- Inkscape::Rubberband *r = Inkscape::Rubberband::get(desktop);
+ if (eraser_mode == ERASER_MODE_DELETE) {
+ Inkscape::Rubberband *r = Inkscape::Rubberband::get(this->desktop);
std::vector<SPItem*> touched;
- touched = desktop->getDocument()->getItemsAtPoints(desktop->dkey, r->getPoints());
+ touched = document->getItemsAtPoints(this->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));
@@ -687,7 +694,7 @@ void EraserTool::set_to_accumulated() {
}
if ( !toWorkOn.empty() ) {
- if ( eraserMode ) {
+ if (eraser_mode == ERASER_MODE_CUT) {
for (std::vector<SPItem*>::const_iterator i = toWorkOn.begin(); i != toWorkOn.end(); ++i){
SPItem *item = *i;
SPUse *use = dynamic_cast<SPUse *>(item);
@@ -713,7 +720,7 @@ void EraserTool::set_to_accumulated() {
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_desktop_set_style(this->desktop, css);
sp_repr_css_attr_unref(css);
css = 0;
}
@@ -725,10 +732,10 @@ void EraserTool::set_to_accumulated() {
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);
+ sp_selected_path_combine(this->desktop, true);
} else {
if(!this->nowidth){
- sp_selected_path_break_apart(desktop, true);
+ sp_selected_path_break_apart(this->desktop, true);
}
}
if ( !selection->isEmpty() ) {
@@ -743,6 +750,70 @@ void EraserTool::set_to_accumulated() {
}
}
}
+ } else if (eraser_mode == ERASER_MODE_CLIP) {
+ if (!this->nowidth) {
+ remainingItems.clear();
+ for (std::vector<SPItem*>::const_iterator i = toWorkOn.begin(); i != toWorkOn.end(); ++i){
+ selection->clear();
+ SPItem *item = *i;
+ Geom::OptRect bbox = item->desktopVisualBounds();
+ Inkscape::XML::Document *xml_doc = this->desktop->doc()->getReprDoc();
+ Inkscape::XML::Node* dup = this->repr->duplicate(xml_doc);
+ this->repr->parent()->appendChild(dup);
+ Inkscape::GC::release(dup); // parent takes over
+ selection->set(dup);
+ sp_selected_path_union_skip_undo(selection);
+ if (bbox && bbox->intersects(*eraserBbox)) {
+ SPClipPath *clip_path = item->clip_ref->getObject();
+ if (clip_path) {
+ SPPath *clip_data = SP_PATH(clip_path->firstChild());
+ if (clip_data) {
+ Inkscape::XML::Node *dup_clip = SP_OBJECT(clip_data)->getRepr()->duplicate(xml_doc);
+ if (dup_clip) {
+ SPItem * dup_clip_obj = SP_ITEM(item_repr->parent->appendChildRepr(dup_clip));
+ if (dup_clip_obj) {
+ dup_clip_obj->doWriteTransform(dup_clip, item->transform);
+ sp_object_ref(clip_path, 0);
+ clip_path->deleteObject(true);
+ sp_object_unref(clip_path);
+ sp_selection_raise_to_top(selection, this->desktop, true);
+ selection->add(dup_clip);
+ sp_selected_path_diff_skip_undo(selection);
+ SPItem * clip = SP_ITEM(*(selection->items().begin()));
+ }
+ }
+ }
+ } else {
+ Inkscape::XML::Node *rect_repr = xml_doc->createElement("svg:rect");
+ sp_desktop_apply_style_tool (this->desktop, rect_repr, "/tools/eraser", false);
+ SPRect * rect = SP_RECT(item_repr->parent->appendChildRepr(rect_repr));
+ Inkscape::GC::release(rect_repr);
+ rect->setPosition (bbox->left(), bbox->top(), bbox->width(), bbox->height());
+ rect->transform = SP_ITEM(rect->parent)->i2dt_affine().inverse();
+ rect->updateRepr();
+ rect->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ sp_selection_raise_to_top(selection, this->desktop, true);
+ selection->add(rect);
+ sp_selected_path_diff_skip_undo(selection);
+ }
+ sp_selection_raise_to_top(selection, this->desktop, true);
+ selection->add(item);
+ sp_selection_set_mask(this->desktop, true, false, true);
+ } else {
+ SPItem *erase_clip = selection->singleItem();
+ if (erase_clip) {
+ sp_object_ref(erase_clip, 0);
+ erase_clip->deleteObject(true);
+ sp_object_unref(erase_clip);
+ }
+ }
+ workDone = true;
+ selection->clear();
+ if (wasSelection) {
+ remainingItems.push_back(item);
+ }
+ }
+ }
} else {
for (std::vector<SPItem*> ::const_iterator i = toWorkOn.begin();i!=toWorkOn.end();++i) {
sp_object_ref( *i, 0 );
@@ -756,8 +827,8 @@ void EraserTool::set_to_accumulated() {
}
}
- if ( !eraserMode ) {
- //sp_selection_delete(desktop);
+ if (eraser_mode == ERASER_MODE_DELETE) {
+ sp_selection_delete(this->desktop);
remainingItems.clear();
}
@@ -779,12 +850,10 @@ void EraserTool::set_to_accumulated() {
this->repr = 0;
}
}
-
-
if ( workDone ) {
- DocumentUndo::done(desktop->getDocument(), SP_VERB_CONTEXT_ERASER, _("Draw eraser stroke"));
+ DocumentUndo::done(document, SP_VERB_CONTEXT_ERASER, _("Draw eraser stroke"));
} else {
- DocumentUndo::cancel(desktop->getDocument());
+ DocumentUndo::cancel(document);
}
}
@@ -975,7 +1044,7 @@ void EraserTool::fit_and_split(bool release) {
g_print("[%d]Yup\n", this->npoints);
#endif
if (!release) {
- gint eraserMode = prefs->getBool("/tools/eraser/mode") ? 1 : 0;
+ gint eraser_mode = prefs->getInt("/tools/eraser/mode",2);
g_assert(!this->currentcurve->is_empty());
SPCanvasItem *cbp = sp_canvas_item_new(desktop->getSketch(), SP_TYPE_CANVAS_BPATH, NULL);
@@ -997,7 +1066,7 @@ void EraserTool::fit_and_split(bool release) {
this->segments = g_slist_prepend(this->segments, cbp);
- if ( !eraserMode ) {
+ if (eraser_mode == ERASER_MODE_DELETE) {
sp_canvas_item_hide(cbp);
sp_canvas_item_hide(this->currentshape);
}
diff --git a/src/ui/tools/eraser-tool.h b/src/ui/tools/eraser-tool.h
index 50ce6b6e3..bd0e98057 100644
--- a/src/ui/tools/eraser-tool.h
+++ b/src/ui/tools/eraser-tool.h
@@ -31,6 +31,10 @@
#define ERC_MAX_TILT 1.0
#define ERC_DEFAULT_TILT 0.0
+#define ERASER_MODE_DELETE 0
+#define ERASER_MODE_CUT 1
+#define ERASER_MODE_CLIP 2
+
namespace Inkscape {
namespace UI {
namespace Tools {
diff --git a/src/widgets/eraser-toolbar.cpp b/src/widgets/eraser-toolbar.cpp
index 7f710a777..bcfa662a2 100644
--- a/src/widgets/eraser-toolbar.cpp
+++ b/src/widgets/eraser-toolbar.cpp
@@ -42,6 +42,7 @@
#include "ink-toggle-action.h"
#include "toolbox.h"
#include "ui/icon-names.h"
+#include "ui/tools/eraser-tool.h"
using Inkscape::DocumentUndo;
using Inkscape::UI::ToolboxFactory;
@@ -65,22 +66,60 @@ static void sp_erc_mass_value_changed( GtkAdjustment *adj, GObject* tbl )
update_presets_list(tbl);
}
+static void sp_erc_velthin_value_changed( GtkAdjustment *adj, GObject* tbl )
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setDouble("/tools/eraser/thinning", gtk_adjustment_get_value(adj) );
+ update_presets_list(tbl);
+}
+
+static void sp_erc_cap_rounding_value_changed( GtkAdjustment *adj, GObject* tbl )
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setDouble( "/tools/eraser/cap_rounding", gtk_adjustment_get_value(adj) );
+ update_presets_list(tbl);
+}
+
+static void sp_erc_tremor_value_changed( GtkAdjustment *adj, GObject* tbl )
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setDouble( "/tools/eraser/tremor", gtk_adjustment_get_value(adj) );
+ update_presets_list(tbl);
+}
+
+
static void sp_erasertb_mode_changed( EgeSelectOneAction *act, GObject *tbl )
{
SPDesktop *desktop = static_cast<SPDesktop *>(g_object_get_data( tbl, "desktop" ));
- bool eraserMode = ege_select_one_action_get_active( act ) != 0;
+ guint eraser_mode = ege_select_one_action_get_active( act );
if (DocumentUndo::getUndoSensitive(desktop->getDocument())) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- prefs->setBool( "/tools/eraser/mode", eraserMode );
+ prefs->setInt( "/tools/eraser/mode", eraser_mode );
}
GtkAction *split = GTK_ACTION( g_object_get_data(tbl, "split") );
GtkAction *mass = GTK_ACTION( g_object_get_data(tbl, "mass") );
GtkAction *width = GTK_ACTION( g_object_get_data(tbl, "width") );
- if(eraserMode == TRUE){
- gtk_action_set_visible( split, TRUE );
+ GtkAction *usepressure = GTK_ACTION( g_object_get_data(tbl, "usepressure") );
+ GtkAction *cap_rounding = GTK_ACTION( g_object_get_data(tbl, "cap_rounding") );
+ GtkAction *thinning = GTK_ACTION( g_object_get_data(tbl, "thinning") );
+ GtkAction *tremor = GTK_ACTION( g_object_get_data(tbl, "tremor") );
+ if (eraser_mode != ERASER_MODE_DELETE) {
+ if(eraser_mode == ERASER_MODE_CUT) {
+ gtk_action_set_visible( split, TRUE );
+ } else {
+ gtk_action_set_visible( split, FALSE );
+ }
+ gtk_action_set_visible(usepressure, TRUE );
+ gtk_action_set_visible(tremor, TRUE );
+ gtk_action_set_visible(cap_rounding, TRUE );
+ gtk_action_set_visible(thinning, TRUE );
gtk_action_set_visible( mass, TRUE );
gtk_action_set_visible( width, TRUE );
} else {
+ gtk_action_set_visible(usepressure, FALSE );
+ gtk_action_set_visible(tremor, FALSE );
+ gtk_action_set_visible(cap_rounding, FALSE );
+ gtk_action_set_visible(thinning, FALSE );
gtk_action_set_visible( split, FALSE );
gtk_action_set_visible( mass, FALSE );
gtk_action_set_visible( width, FALSE );
@@ -91,7 +130,7 @@ static void sp_erasertb_mode_changed( EgeSelectOneAction *act, GObject *tbl )
g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) );
/*
- if ( eraserMode != 0 ) {
+ if ( eraser_mode != ERASER_MODE_DELETE ) {
} else {
}
*/
@@ -112,7 +151,7 @@ void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GOb
{
Inkscape::IconSize secondarySize = ToolboxFactory::prefToSize("/toolbox/secondary", 1);
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- gint eraserMode = FALSE;
+ gint eraser_mode = FALSE;
{
GtkListStore* model = gtk_list_store_new( 3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING );
GtkTreeIter iter;
@@ -126,10 +165,17 @@ void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GOb
gtk_list_store_append( model, &iter );
gtk_list_store_set( model, &iter,
0, _("Cut"),
- 1, _("Cut out from objects"),
+ 1, _("Cut out from paths and shapes"),
2, INKSCAPE_ICON("path-difference"),
-1 );
+ gtk_list_store_append( model, &iter );
+ gtk_list_store_set( model, &iter,
+ 0, _("Clip"),
+ 1, _("Clip from objects"),
+ 2, INKSCAPE_ICON("path-intersection"),
+ -1 );
+
EgeSelectOneAction* act = ege_select_one_action_new( "EraserModeAction", (""), (""), NULL, GTK_TREE_MODEL(model) );
g_object_set( act, "short_label", _("Mode:"), NULL );
gtk_action_group_add_action( mainActions, GTK_ACTION(act) );
@@ -138,12 +184,13 @@ void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GOb
ege_select_one_action_set_appearance( act, "full" );
ege_select_one_action_set_radio_action_type( act, INK_RADIO_ACTION_TYPE );
g_object_set( G_OBJECT(act), "icon-property", "iconId", NULL );
- ege_select_one_action_set_icon_column( act, 2 );
- ege_select_one_action_set_tooltip_column( act, 1 );
+ ege_select_one_action_set_icon_column( act, 2);
+ ege_select_one_action_set_icon_size( act, secondarySize );
+ ege_select_one_action_set_tooltip_column( act, 1);
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- eraserMode = prefs->getBool("/tools/eraser/mode") ? TRUE : FALSE;
- ege_select_one_action_set_active( act, eraserMode );
+ eraser_mode = prefs->getInt("/tools/eraser/mode", ERASER_MODE_CLIP);
+ ege_select_one_action_set_active( act, eraser_mode );
g_signal_connect_after( G_OBJECT(act), "changed", G_CALLBACK(sp_erasertb_mode_changed), holder );
}
@@ -164,6 +211,71 @@ void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GOb
g_object_set_data( holder, "width", eact );
gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
}
+ /* Use Pressure button */
+ {
+ InkToggleAction* act = ink_toggle_action_new( "EraserPressureAction",
+ _("Eraser Pressure"),
+ _("Use the pressure of the input device to alter the width of the pen"),
+ INKSCAPE_ICON("draw-use-pressure"),
+ Inkscape::ICON_SIZE_DECORATION );
+ gtk_action_group_add_action( mainActions, GTK_ACTION( act ) );
+ PrefPusher *pusher = new PrefPusher(GTK_TOGGLE_ACTION(act), "/tools/eraser/usepressure", update_presets_list, holder);
+ g_signal_connect( holder, "destroy", G_CALLBACK(delete_prefspusher), pusher);
+ g_object_set_data( holder, "usepressure", act );
+ }
+ {
+
+ /* Thinning */
+ gchar const* labels[] = {_("(speed blows up stroke)"), 0, 0, _("(slight widening)"), _("(constant width)"), _("(slight thinning, default)"), 0, 0, _("(speed deflates stroke)")};
+ gdouble values[] = {-100, -40, -20, -10, 0, 10, 20, 40, 100};
+ EgeAdjustmentAction* eact = create_adjustment_action( "EraserThinningAction",
+ _("Eraser Stroke Thinning"), _("Thinning:"),
+ _("How much velocity thins the stroke (> 0 makes fast strokes thinner, < 0 makes them broader, 0 makes width independent of velocity)"),
+ "/tools/eraser/thinning", 10,
+ GTK_WIDGET(desktop->canvas), holder, FALSE, NULL,
+ -100, 100, 1, 10.0,
+ labels, values, G_N_ELEMENTS(labels),
+ sp_erc_velthin_value_changed, NULL /*unit tracker*/, 1, 0);
+ gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+ g_object_set_data( holder, "thinning", eact );
+ gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
+ }
+ {
+ /* Cap Rounding */
+ gchar const* labels[] = {_("(blunt caps, default)"), _("(slightly bulging)"), 0, 0, _("(approximately round)"), _("(long protruding caps)")};
+ gdouble values[] = {0, 0.3, 0.5, 1.0, 1.4, 5.0};
+ // TRANSLATORS: "cap" means "end" (both start and finish) here
+ EgeAdjustmentAction* eact = create_adjustment_action( "EraserCapRoundingAction",
+ _("Eraser Cap rounding"), _("Caps:"),
+ _("Increase to make caps at the ends of strokes protrude more (0 = no caps, 1 = round caps)"),
+ "/tools/eraser/cap_rounding", 0.0,
+ GTK_WIDGET(desktop->canvas), holder, FALSE, NULL,
+ 0.0, 5.0, 0.01, 0.1,
+ labels, values, G_N_ELEMENTS(labels),
+ sp_erc_cap_rounding_value_changed, NULL /*unit tracker*/, 0.01, 2 );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+ g_object_set_data( holder, "cap_rounding", eact );
+ gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
+ }
+
+ {
+ /* Tremor */
+ gchar const* labels[] = {_("(smooth line)"), _("(slight tremor)"), _("(noticeable tremor)"), 0, 0, _("(maximum tremor)")};
+ gdouble values[] = {0, 10, 20, 40, 60, 100};
+ EgeAdjustmentAction* eact = create_adjustment_action( "EraserTremorAction",
+ _("EraserStroke Tremor"), _("Tremor:"),
+ _("Increase to make strokes rugged and trembling"),
+ "/tools/eraser/tremor", 0.0,
+ GTK_WIDGET(desktop->canvas), holder, FALSE, NULL,
+ 0.0, 100, 1, 10.0,
+ labels, values, G_N_ELEMENTS(labels),
+ sp_erc_tremor_value_changed, NULL /*unit tracker*/, 1, 0);
+
+ ege_adjustment_action_set_appearance( eact, TOOLBAR_SLIDER_HINT );
+ g_object_set_data( holder, "tremor", eact );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+ gtk_action_set_sensitive( GTK_ACTION(eact), TRUE );
+ }
{
/* Mass */
gchar const* labels[] = {_("(no inertia)"), _("(slight smoothing, default)"), _("(noticeable lagging)"), 0, 0, _("(maximum inertia)")};
@@ -196,11 +308,27 @@ void sp_eraser_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GOb
GtkAction *split = GTK_ACTION( g_object_get_data(holder, "split") );
GtkAction *mass = GTK_ACTION( g_object_get_data(holder, "mass") );
GtkAction *width = GTK_ACTION( g_object_get_data(holder, "width") );
- if(eraserMode == TRUE){
- gtk_action_set_visible( split, TRUE );
+ GtkAction *usepressure = GTK_ACTION( g_object_get_data(holder, "usepressure") );
+ GtkAction *cap_rounding = GTK_ACTION( g_object_get_data(holder, "cap_rounding") );
+ GtkAction *thinning = GTK_ACTION( g_object_get_data(holder, "thinning") );
+ GtkAction *tremor = GTK_ACTION( g_object_get_data(holder, "tremor") );
+ if (eraser_mode != ERASER_MODE_DELETE) {
+ if(eraser_mode == ERASER_MODE_CUT) {
+ gtk_action_set_visible( split, TRUE );
+ } else {
+ gtk_action_set_visible( split, FALSE );
+ }
+ gtk_action_set_visible(usepressure, TRUE );
+ gtk_action_set_visible(tremor, TRUE );
+ gtk_action_set_visible(cap_rounding, TRUE );
+ gtk_action_set_visible(thinning, TRUE );
gtk_action_set_visible( mass, TRUE );
gtk_action_set_visible( width, TRUE );
} else {
+ gtk_action_set_visible(usepressure, FALSE );
+ gtk_action_set_visible(tremor, FALSE );
+ gtk_action_set_visible(cap_rounding, FALSE );
+ gtk_action_set_visible(thinning, FALSE );
gtk_action_set_visible( split, FALSE );
gtk_action_set_visible( mass, FALSE );
gtk_action_set_visible( width, FALSE );
diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp
index f74be4b15..c03ca85e6 100644
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
@@ -493,6 +493,13 @@ static gchar const * ui_descr =
" <toolitem action='EraserModeAction' />"
" <separator />"
" <toolitem action='EraserWidthAction' />"
+ " <toolitem action='EraserPressureAction' />"
+ " <separator />"
+ " <toolitem action='EraserThinningAction' />"
+ " <separator />"
+ " <toolitem action='EraserCapRoundingAction' />"
+ " <separator />"
+ " <toolitem action='EraserTremorAction' />"
" <separator />"
" <toolitem action='EraserMassAction' />"
" <separator />"