summaryrefslogtreecommitdiffstats
path: root/src/live_effects/parameter
diff options
context:
space:
mode:
authorLiam P. White <inkscapebrony@gmail.com>2014-07-24 21:21:30 +0000
committerLiam P. White <inkscapebrony@gmail.com>2014-07-24 21:21:30 +0000
commitf33396b871f4e4273bf131195dcaa2ebcb3163b8 (patch)
tree5bdc7e523e724799007f06cb63ec74ff97195a68 /src/live_effects/parameter
parentFix crash bug when exporting PNG from CLI (diff)
parentRead HSL color (CSS Color Module Level 3). (diff)
downloadinkscape-f33396b871f4e4273bf131195dcaa2ebcb3163b8.tar.gz
inkscape-f33396b871f4e4273bf131195dcaa2ebcb3163b8.zip
Update to experimental r13440
(bzr r13341.5.13)
Diffstat (limited to 'src/live_effects/parameter')
-rw-r--r--src/live_effects/parameter/Makefile_insert2
-rw-r--r--src/live_effects/parameter/bool.h2
-rw-r--r--src/live_effects/parameter/filletchamferpointarray.cpp656
-rw-r--r--src/live_effects/parameter/filletchamferpointarray.h117
-rw-r--r--src/live_effects/parameter/parameter.cpp31
-rw-r--r--src/live_effects/parameter/powerstrokepointarray.cpp5
-rw-r--r--src/live_effects/parameter/togglebutton.cpp88
-rw-r--r--src/live_effects/parameter/togglebutton.h31
8 files changed, 915 insertions, 17 deletions
diff --git a/src/live_effects/parameter/Makefile_insert b/src/live_effects/parameter/Makefile_insert
index 1026cf11c..1137ef34b 100644
--- a/src/live_effects/parameter/Makefile_insert
+++ b/src/live_effects/parameter/Makefile_insert
@@ -22,6 +22,8 @@ ink_common_sources += \
live_effects/parameter/originalpath.h \
live_effects/parameter/powerstrokepointarray.cpp \
live_effects/parameter/powerstrokepointarray.h \
+ live_effects/parameter/filletchamferpointarray.cpp \
+ live_effects/parameter/filletchamferpointarray.h \
live_effects/parameter/text.cpp \
live_effects/parameter/text.h \
live_effects/parameter/togglebutton.cpp \
diff --git a/src/live_effects/parameter/bool.h b/src/live_effects/parameter/bool.h
index fafb1beca..b45eeb0b3 100644
--- a/src/live_effects/parameter/bool.h
+++ b/src/live_effects/parameter/bool.h
@@ -4,7 +4,7 @@
/*
* Inkscape::LivePathEffectParameters
*
-* Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
+ * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
diff --git a/src/live_effects/parameter/filletchamferpointarray.cpp b/src/live_effects/parameter/filletchamferpointarray.cpp
new file mode 100644
index 000000000..457b68dd2
--- /dev/null
+++ b/src/live_effects/parameter/filletchamferpointarray.cpp
@@ -0,0 +1,656 @@
+/*
+ * Copyright (C) Jabiertxo Arraiza Cenoz <jabier.arraiza@marker.es>
+ * Special thanks to Johan Engelen for the base of the effect -powerstroke-
+ * Also to ScislaC for point me to the idea
+ * Also su_v for his construvtive feedback and time
+ * and finaly to Liam P. White for his big help on coding, that save me a lot of
+ * hours
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <2geom/piecewise.h>
+#include <2geom/sbasis-to-bezier.h>
+#include <2geom/sbasis-geometric.h>
+
+#include "ui/dialog/lpe-fillet-chamfer-properties.h"
+#include "live_effects/parameter/filletchamferpointarray.h"
+#include "live_effects/effect.h"
+#include "svg/svg.h"
+#include "svg/stringstream.h"
+#include "knotholder.h"
+#include "sp-lpe-item.h"
+#include "selection.h"
+
+// needed for on-canvas editting:
+#include "desktop.h"
+#include "live_effects/lpeobject.h"
+#include "helper/geom-nodetype.h"
+#include "helper/geom-curves.h"
+#include "ui/tools/node-tool.h"
+
+// TODO due to internal breakage in glibmm headers,
+// this has to be included last.
+#include <glibmm/i18n.h>
+
+using namespace Geom;
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+FilletChamferPointArrayParam::FilletChamferPointArrayParam(
+ const Glib::ustring &label, const Glib::ustring &tip,
+ const Glib::ustring &key, Inkscape::UI::Widget::Registry *wr,
+ Effect *effect)
+ : ArrayParam<Point>(label, tip, key, wr, effect, 0)
+{
+ knot_shape = SP_KNOT_SHAPE_DIAMOND;
+ knot_mode = SP_KNOT_MODE_XOR;
+ knot_color = 0x00ff0000;
+}
+
+FilletChamferPointArrayParam::~FilletChamferPointArrayParam() {}
+
+Gtk::Widget *FilletChamferPointArrayParam::param_newWidget()
+{
+ return NULL;
+ /*
+ Inkscape::UI::Widget::RegisteredTransformedPoint * pointwdg =
+ Gtk::manage(
+ new Inkscape::UI::Widget::RegisteredTransformedPoint(
+ param_label,
+ param_tooltip,
+ param_key,
+ *param_wr,
+ param_effect->getRepr(),
+ param_effect->getSPDoc()
+ ) );
+ // TODO: fix to get correct desktop (don't use SP_ACTIVE_DESKTOP)
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ Affine transf = desktop->doc2dt();
+ pointwdg->setTransform(transf);
+ pointwdg->setValue( *this );
+ pointwdg->clearProgrammatically();
+ pointwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT,
+ _("Change point parameter"));
+
+ Gtk::HBox * hbox = Gtk::manage( new Gtk::HBox() );
+ static_cast<Gtk::HBox*>(hbox)->pack_start(*pointwdg, true, true);
+ static_cast<Gtk::HBox*>(hbox)->show_all_children();
+
+ return dynamic_cast<Gtk::Widget *> (hbox);
+ */
+}
+
+void
+FilletChamferPointArrayParam::param_transform_multiply(Affine const &postmul,
+ bool /*set*/)
+{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+ if (prefs->getBool("/options/transform/rectcorners", true) &&
+ _vector[1][X] <= 0) {
+ std::vector<Geom::Point> result;
+ for (std::vector<Point>::const_iterator point_it = _vector.begin();
+ point_it != _vector.end(); ++point_it) {
+ Coord A =
+ (*point_it)[X] * ((postmul.expansionX() + postmul.expansionY()) / 2);
+ result.push_back(Point(A, (*point_it)[Y]));
+ }
+ param_set_and_write_new_value(result);
+ }
+
+ // param_set_and_write_new_value( (*this) * postmul );
+}
+
+/** call this method to recalculate the controlpoints such that they stay at the
+ * same location relative to the new path. Useful after adding/deleting nodes to
+ * the path.*/
+void FilletChamferPointArrayParam::recalculate_controlpoints_for_new_pwd2(
+ Piecewise<D2<SBasis> > const &pwd2_in)
+{
+ if (!last_pwd2.empty()) {
+ PathVector const pathv =
+ path_from_piecewise(remove_short_cuts(pwd2_in, 0.1), 0.001);
+ PathVector last_pathv =
+ path_from_piecewise(remove_short_cuts(last_pwd2, 0.1), 0.001);
+ std::vector<Point> result;
+ unsigned long counter = 0;
+ unsigned long counterPaths = 0;
+ unsigned long counterCurves = 0;
+ long offset = 0;
+ long offsetPaths = 0;
+ Geom::NodeType nodetype;
+ for (PathVector::const_iterator path_it = pathv.begin();
+ path_it != pathv.end(); ++path_it) {
+ if (path_it->empty()) {
+ counterPaths++;
+ counter++;
+ 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();
+ if (path_it->closed() && path_it->back_closed().isDegenerate()) {
+ const Curve &closingline = path_it->back_closed();
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ curve_endit = path_it->end_open();
+ }
+ }
+ counterCurves = 0;
+ while (curve_it1 != curve_endit) {
+ //if start a path get node type
+ if (counterCurves == 0) {
+ if (path_it->closed()) {
+ if (path_it->back_closed().isDegenerate()) {
+ nodetype = get_nodetype(path_it->back_open(), *curve_it1);
+ } else {
+ nodetype = get_nodetype(path_it->back_closed(), *curve_it1);
+ }
+ } else {
+ nodetype = NODE_NONE;
+ }
+ } else {
+ //check node type also whith straight lines because get_nodetype
+ //return non cusp node in a node inserted inside a straight line
+ //todo: if the path remove some nodes whith the result of a straight
+ //line but with handles, the node inserted into dont fire the knot
+ // because is not handle as cusp node by get_nodetype function
+ bool this_is_line = true;
+ bool next_is_line = is_straight_curve(*curve_it1);
+ this_is_line = is_straight_curve((*path_it)[counterCurves - 1]);
+ nodetype = get_nodetype((*path_it)[counterCurves - 1], *curve_it1);
+ if (this_is_line || next_is_line) {
+ nodetype = NODE_CUSP;
+ }
+ }
+ if (last_pathv.size() > pathv.size() ||
+ (last_pathv[counterPaths].size() > counter - offset &&
+ !are_near(curve_it1->initialPoint(),
+ last_pathv[counterPaths][counter - offset].initialPoint(),
+ 0.1))) {
+ if (last_pathv.size() > counterPaths && curve_it2 == curve_endit) {
+ if (last_pathv[counterPaths].size() < pathv[counterPaths].size()) {
+ offset = abs(last_pathv[counterPaths].size() -
+ pathv[counterPaths].size());
+ } else if (last_pathv[counterPaths].size() >
+ pathv[counterPaths].size()) {
+ offset = (abs(last_pathv[counterPaths].size() -
+ pathv[counterPaths].size())) * -1;
+ } else {
+ offset = 0;
+ }
+ offsetPaths += offset;
+ offset = offsetPaths;
+ } else if (counterCurves == 0 && last_pathv.size() <= pathv.size() &&
+ counter - offset <= last_pathv[counterPaths].size() &&
+ are_near(curve_it1->initialPoint(),
+ last_pathv[counterPaths].finalPoint(), 0.1) &&
+ !last_pathv[counterPaths].closed()) {
+ long e = counter - offset + 1;
+ std::vector<Point> tmp = _vector;
+ for (unsigned long i =
+ last_pathv[counterPaths].size() + counter - offset;
+ i > counterCurves - offset + 1; i--) {
+
+ if (tmp[i - 1][X] > 0) {
+ double fractpart, intpart;
+ fractpart = modf(tmp[i - 1][X], &intpart);
+ _vector[e] = Point(e + fractpart, tmp[i - 1][Y]);
+ } else {
+ _vector[e] = Point(tmp[i - 1][X], tmp[i - 1][Y]);
+ }
+ e++;
+ }
+ //delete temp vector
+ std::vector<Point>().swap(tmp);
+ if (last_pathv.size() > counterPaths) {
+ last_pathv[counterPaths] = last_pathv[counterPaths].reverse();
+ }
+ } else {
+ if (last_pathv.size() > counterPaths) {
+ if (last_pathv[counterPaths].size() <
+ pathv[counterPaths].size()) {
+ offset++;
+ } else if (last_pathv[counterPaths].size() >
+ pathv[counterPaths].size()) {
+ offset--;
+ continue;
+ }
+ } else {
+ offset++;
+ }
+ }
+ double xPos = 0;
+ if (_vector[1][X] > 0) {
+ xPos = nearest_point(curve_it1->initialPoint(), pwd2_in);
+ }
+ if (nodetype == NODE_CUSP) {
+ result.push_back(Point(xPos, 1));
+ } else {
+ result.push_back(Point(xPos, 0));
+ }
+ } else {
+ double xPos = _vector[counter - offset][X];
+ if (_vector.size() <= (unsigned)(counter - offset)) {
+ if (_vector[1][X] > 0) {
+ xPos = nearest_point(curve_it1->initialPoint(), pwd2_in);
+ } else {
+ xPos = 0;
+ }
+ }
+ if (nodetype == NODE_CUSP) {
+ double vectorY = _vector[counter - offset][Y];
+ if (_vector.size() <= (unsigned)(counter - offset) || vectorY == 0) {
+ vectorY = 1;
+ }
+ result.push_back(Point(xPos, vectorY));
+ } else {
+ if (_vector[1][X] < 0) {
+ xPos = 0;
+ }
+ result.push_back(Point(floor(xPos), 0));
+ }
+ }
+ ++curve_it1;
+ if (curve_it2 != curve_endit) {
+ ++curve_it2;
+ }
+ counter++;
+ counterCurves++;
+ }
+ counterPaths++;
+ }
+ _vector = result;
+ write_to_SVG();
+ }
+}
+
+void FilletChamferPointArrayParam::recalculate_knots(
+ Piecewise<D2<SBasis> > const &pwd2_in)
+{
+ bool change = false;
+ PathVector pathv = path_from_piecewise(pwd2_in, 0.001);
+ if (!pathv.empty()) {
+ std::vector<Point> result;
+ int counter = 0;
+ int counterCurves = 0;
+ Geom::NodeType nodetype;
+ for (PathVector::const_iterator path_it = pathv.begin();
+ path_it != pathv.end(); ++path_it) {
+ if (path_it->empty()) {
+ counter++;
+ 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();
+ if (path_it->closed() && path_it->back_closed().isDegenerate()) {
+ const Curve &closingline = path_it->back_closed();
+ if (are_near(closingline.initialPoint(), closingline.finalPoint())) {
+ curve_endit = path_it->end_open();
+ }
+ }
+ counterCurves = 0;
+ while (curve_it1 != curve_endit) {
+ //if start a path get node type
+ if (counterCurves == 0) {
+ if (path_it->closed()) {
+ if (path_it->back_closed().isDegenerate()) {
+ nodetype = get_nodetype(path_it->back_open(), *curve_it1);
+ } else {
+ nodetype = get_nodetype(path_it->back_closed(), *curve_it1);
+ }
+ } else {
+ nodetype = NODE_NONE;
+ }
+ } else {
+ bool this_is_line = true;
+ bool next_is_line = is_straight_curve(*curve_it1);
+ this_is_line = is_straight_curve((*path_it)[counterCurves - 1]);
+ nodetype = get_nodetype((*path_it)[counterCurves - 1], *curve_it1);
+ if (this_is_line || next_is_line) {
+ nodetype = NODE_CUSP;
+ }
+ }
+ if (nodetype == NODE_CUSP) {
+ double vectorY = _vector[counter][Y];
+ if (vectorY == 0) {
+ vectorY = 1;
+ change = true;
+ }
+ result.push_back(Point(_vector[counter][X], vectorY));
+ } else {
+ double xPos = floor(_vector[counter][X]);
+ if (_vector[1][X] < 0) {
+ xPos = 0;
+ }
+ double vectorY = _vector[counter][Y];
+ if (vectorY != 0) {
+ change = true;
+ }
+ result.push_back(Point(xPos, 0));
+ }
+ ++curve_it1;
+ ++curve_it2;
+ if (curve_it2 != curve_endit) {
+ counter++;
+ }
+ counterCurves++;
+ }
+ }
+ if (change) {
+ _vector = result;
+ write_to_SVG();
+ }
+ }
+}
+
+void FilletChamferPointArrayParam::set_pwd2(
+ Piecewise<D2<SBasis> > const &pwd2_in,
+ Piecewise<D2<SBasis> > const &pwd2_normal_in)
+{
+ last_pwd2 = pwd2_in;
+ last_pwd2_normal = pwd2_normal_in;
+}
+
+void FilletChamferPointArrayParam::set_helper_size(int hs)
+{
+ helper_size = hs;
+}
+
+void FilletChamferPointArrayParam::set_unit(const gchar *abbr)
+{
+ unit = abbr;
+}
+
+void FilletChamferPointArrayParam::updateCanvasIndicators()
+{
+ std::vector<Point> ts = data();
+ hp.clear();
+ unsigned int i = 0;
+ Piecewise<D2<SBasis> > const &n = get_pwd2_normal();
+ for (std::vector<Point>::const_iterator point_it = ts.begin();
+ point_it != ts.end(); ++point_it) {
+ double Xvalue = to_time(i, (*point_it)[X]);
+ double XPlusValue = to_time(i, -helper_size) - i;
+ if (Xvalue == i) {
+ i++;
+ continue;
+ }
+ Point canvas_point = last_pwd2.valueAt(Xvalue) + 0 * n.valueAt(Xvalue);
+ Point start_point = last_pwd2.valueAt(Xvalue + XPlusValue) +
+ helper_size * n.valueAt(Xvalue + XPlusValue);
+ Point end_point = last_pwd2.valueAt(Xvalue + XPlusValue) -
+ helper_size * n.valueAt(Xvalue + XPlusValue);
+ Geom::Path arrow;
+ arrow.start(start_point);
+ arrow.appendNew<Geom::LineSegment>(canvas_point);
+ arrow.appendNew<Geom::LineSegment>(end_point);
+ hp.push_back(arrow);
+ i++;
+ }
+}
+
+void FilletChamferPointArrayParam::addCanvasIndicators(
+ SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
+{
+ hp_vec.push_back(hp);
+}
+
+double FilletChamferPointArrayParam::len_to_time(int index, double len)
+{
+ double t = 0;
+ if (last_pwd2.size() > (unsigned) index) {
+ if (len != 0) {
+ if (last_pwd2[index][0].degreesOfFreedom() != 2) {
+ Piecewise<D2<SBasis> > u;
+ u.push_cut(0);
+ u.push(last_pwd2[index], 1);
+ std::vector<double> t_roots = roots(arcLengthSb(u) - std::abs(len));
+ if (t_roots.size() > 0) {
+ t = t_roots[0];
+ }
+ } else {
+ double lenghtPart = 0;
+ if (last_pwd2.size() > (unsigned) index) {
+ lenghtPart = length(last_pwd2[index], EPSILON);
+ }
+ if (std::abs(len) < lenghtPart && lenghtPart != 0) {
+ t = std::abs(len) / lenghtPart;
+ }
+ }
+ }
+ t = double(index) + t;
+ } else {
+ t = double(last_pwd2.size() - 1);
+ }
+
+ return t;
+}
+
+double FilletChamferPointArrayParam::time_to_len(int index, double time)
+{
+ double intpart;
+ double len = 0;
+ time = modf(time, &intpart);
+ double lenghtPart = 0;
+ if (last_pwd2.size() <= (unsigned) index || time == 0) {
+ return len;
+ }
+ if (last_pwd2[index][0].degreesOfFreedom() != 2) {
+ Piecewise<D2<SBasis> > u;
+ u.push_cut(0);
+ u.push(last_pwd2[index], 1);
+ u = portion(u, 0, time);
+ return length(u, 0.001) * -1;
+ }
+ lenghtPart = length(last_pwd2[index], EPSILON);
+ return (time * lenghtPart) * -1;
+}
+
+double FilletChamferPointArrayParam::to_time(int index, double A)
+{
+ if (A > 0) {
+ return A;
+ } else {
+ return len_to_time(index, A);
+ }
+}
+
+double FilletChamferPointArrayParam::to_len(int index, double A)
+{
+ if (A > 0) {
+ return time_to_len(index, A);
+ } else {
+ return A;
+ }
+}
+
+void FilletChamferPointArrayParam::set_oncanvas_looks(SPKnotShapeType shape,
+ SPKnotModeType mode,
+ guint32 color)
+{
+ knot_shape = shape;
+ knot_mode = mode;
+ knot_color = color;
+}
+/*
+class FilletChamferPointArrayParamKnotHolderEntity : public KnotHolderEntity {
+public:
+ FilletChamferPointArrayParamKnotHolderEntity(FilletChamferPointArrayParam
+*p, unsigned int index);
+ virtual ~FilletChamferPointArrayParamKnotHolderEntity() {}
+
+ virtual void knot_set(Point const &p, Point const &origin, guint state);
+ virtual Point knot_get() const;
+ virtual void knot_click(guint state);
+ virtual void knot_doubleclicked(guint state);
+
+ /Checks whether the index falls within the size of the parameter's vector/
+ bool valid_index(unsigned int index) const {
+ return (_pparam->_vector.size() > index);
+ };
+
+private:
+ FilletChamferPointArrayParam *_pparam;
+ unsigned int _index;
+};
+/*/
+
+FilletChamferPointArrayParamKnotHolderEntity::
+FilletChamferPointArrayParamKnotHolderEntity(
+ FilletChamferPointArrayParam *p, unsigned int index)
+ : _pparam(p), _index(index) {}
+
+void FilletChamferPointArrayParamKnotHolderEntity::knot_set(Point const &p,
+ Point const &origin,
+ guint state)
+{
+ using namespace Geom;
+
+ if (!valid_index(_index)) {
+ return;
+ }
+ /// @todo how about item transforms???
+ Piecewise<D2<SBasis> > const &pwd2 = _pparam->get_pwd2();
+ //todo: add snapping
+ //Geom::Point const s = snap_knot_position(p, state);
+ double t = nearest_point(p, pwd2[_index]);
+ if (t == 1) {
+ t = 0.9999;
+ }
+ t += _index;
+
+ if (_pparam->_vector.at(_index)[X] <= 0) {
+ _pparam->_vector.at(_index) =
+ Point(_pparam->time_to_len(_index, t), _pparam->_vector.at(_index)[Y]);
+ } else {
+ _pparam->_vector.at(_index) = Point(t, _pparam->_vector.at(_index)[Y]);
+ }
+ sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
+}
+
+Point FilletChamferPointArrayParamKnotHolderEntity::knot_get() const
+{
+ using namespace Geom;
+
+ if (!valid_index(_index)) {
+ return Point(infinity(), infinity());
+ }
+
+ Piecewise<D2<SBasis> > const &pwd2 = _pparam->get_pwd2();
+
+ double time_it = _pparam->to_time(_index, _pparam->_vector.at(_index)[X]);
+ Point canvas_point = pwd2.valueAt(time_it);
+
+ _pparam->updateCanvasIndicators();
+ return canvas_point;
+
+}
+
+void FilletChamferPointArrayParamKnotHolderEntity::knot_click(guint state)
+{
+ if (state & GDK_CONTROL_MASK) {
+ using namespace Geom;
+ double type = _pparam->_vector.at(_index)[Y] + 1;
+ if (type > 4) {
+ type = 1;
+ }
+ _pparam->_vector.at(_index) = Point(_pparam->_vector.at(_index)[X], type);
+ _pparam->param_set_and_write_new_value(_pparam->_vector);
+ sp_lpe_item_update_patheffect(SP_LPE_ITEM(item), false, false);
+ const gchar *tip;
+ if (type == 3) {
+ tip = _("<b>Chamfer</b>: <b>Ctrl+click</b> toogle type, "
+ "<b>Shift+click</b> open dialog");
+ } else if (type == 2) {
+ tip = _("<b>Inverse Fillet</b>: <b>Ctrl+click</b> toogle type, "
+ "<b>Shift+click</b> open dialog");
+ } else if (type == 1) {
+ tip = _("<b>Fillet</b>: <b>Ctrl+click</b> toogle type, "
+ "<b>Shift+click</b> open dialog");
+ } else {
+ tip = _("<b>Double Chamfer</b>: <b>Ctrl+click</b> toogle type, "
+ "<b>Shift+click</b> open dialog");
+ }
+ this->knot->tip = g_strdup(tip);
+ this->knot->show();
+ //}
+ } else if ((state & GDK_MOD1_MASK) || (state & GDK_SHIFT_MASK)) {
+ Geom::Point offset = Geom::Point(_pparam->_vector.at(_index).x(),
+ _pparam->_vector.at(_index).y());
+ Inkscape::UI::Dialogs::FilletChamferPropertiesDialog::showDialog(
+ this->desktop, offset, this, _pparam->unit);
+ }
+
+}
+
+void
+FilletChamferPointArrayParamKnotHolderEntity::knot_doubleclicked(guint state)
+{
+ //todo: fill the double click dialog whith this parameters in the added file
+ //src/ui/dialog/lpe-fillet-chamfer-properties.cpp(.h)
+ //My idea for when have enought time is:
+ //label whith radius in percent
+ //label whith radius in size -maybe handle units-
+ //entry whith actual radius -in flexible % mode or fixed -?px-
+ //2 radio options to switch entry from fixed or flexible, also update the
+ //entry
+ //Checkbox or two radios to swith fillet or chamfer
+
+}
+
+void FilletChamferPointArrayParamKnotHolderEntity::knot_set_offset(
+ Geom::Point offset)
+{
+ _pparam->_vector.at(_index) = Geom::Point(offset.x(), offset.y());
+ this->parent_holder->knot_ungrabbed_handler(this->knot, 0);
+}
+
+void FilletChamferPointArrayParam::addKnotHolderEntities(KnotHolder *knotholder,
+ SPDesktop *desktop,
+ SPItem *item)
+{
+ recalculate_knots(get_pwd2());
+ for (unsigned int i = 0; i < _vector.size(); ++i) {
+ if (_vector[i][Y] <= 0) {
+ continue;
+ }
+ const gchar *tip;
+ if (_vector[i][Y] == 3) {
+ tip = _("<b>Chamfer</b>: <b>Ctrl+click</b> toogle type, "
+ "<b>Shift+click</b> open dialog");
+ } else if (_vector[i][Y] == 2) {
+ tip = _("<b>Inverse Fillet</b>: <b>Ctrl+click</b> toogle type, "
+ "<b>Shift+click</b> open dialog");
+ } else if (_vector[i][Y] == 1) {
+ tip = _("<b>Fillet</b>: <b>Ctrl+click</b> toogle type, "
+ "<b>Shift+click</b> open dialog");
+ } else {
+ tip = _("<b>Double Chamfer</b>: <b>Ctrl+click</b> toogle type, "
+ "<b>Shift+click</b> open dialog");
+ }
+ FilletChamferPointArrayParamKnotHolderEntity *e =
+ new FilletChamferPointArrayParamKnotHolderEntity(this, i);
+ e->create(desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN, _(tip),
+ knot_shape, knot_mode, knot_color);
+ knotholder->add(e);
+ }
+ updateCanvasIndicators();
+}
+
+} /* namespace LivePathEffect */
+
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/parameter/filletchamferpointarray.h b/src/live_effects/parameter/filletchamferpointarray.h
new file mode 100644
index 000000000..93d6e9f4c
--- /dev/null
+++ b/src/live_effects/parameter/filletchamferpointarray.h
@@ -0,0 +1,117 @@
+#ifndef INKSCAPE_LIVEPATHEFFECT_FILLET_CHAMFER_POINT_ARRAY_H
+#define INKSCAPE_LIVEPATHEFFECT_FILLET_CHAMFER_POINT_ARRAY_H
+
+/*
+ * Inkscape::LivePathEffectParameters
+ * Copyright (C) Jabiertxo Arraiza Cenoz <jabier.arraiza@marker.es>
+ * Special thanks to Johan Engelen for the base of the effect -powerstroke-
+ * Also to ScislaC for point me to the idea
+ * Also su_v for his construvtive feedback and time
+ * and finaly to Liam P. White for his big help on coding, that save me a lot of
+ * hours
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib.h>
+#include <2geom/point.h>
+
+#include "live_effects/parameter/array.h"
+
+#include "knot-holder-entity.h"
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+class FilletChamferPointArrayParamKnotHolderEntity;
+
+class FilletChamferPointArrayParam : public ArrayParam<Geom::Point> {
+public:
+ FilletChamferPointArrayParam(const Glib::ustring &label,
+ const Glib::ustring &tip,
+ const Glib::ustring &key,
+ Inkscape::UI::Widget::Registry *wr,
+ Effect *effect);
+ virtual ~FilletChamferPointArrayParam();
+
+ virtual Gtk::Widget *param_newWidget();
+
+ virtual void param_transform_multiply(Geom::Affine const &postmul,
+ bool /*set*/);
+
+ void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode,
+ guint32 color);
+ virtual double to_time(int index, double A);
+ virtual double to_len(int index, double A);
+ virtual double len_to_time(int index, double len);
+ virtual double time_to_len(int index, double time);
+ virtual void set_helper_size(int hs);
+ virtual void set_unit(const gchar *abbr);
+ virtual void addCanvasIndicators(SPLPEItem const *lpeitem,
+ std::vector<Geom::PathVector> &hp_vec);
+ virtual bool providesKnotHolderEntities() const {
+ return true;
+ }
+ virtual void updateCanvasIndicators();
+ virtual void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop,
+ SPItem *item);
+
+ void set_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_in,
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_normal_in);
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > const &get_pwd2() const {
+ return last_pwd2;
+ }
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > const &get_pwd2_normal() const {
+ return last_pwd2_normal;
+ }
+
+ void recalculate_controlpoints_for_new_pwd2(
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_in);
+ void recalculate_knots(
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > const &pwd2_in);
+ friend class FilletChamferPointArrayParamKnotHolderEntity;
+
+private:
+ FilletChamferPointArrayParam(const FilletChamferPointArrayParam &);
+ FilletChamferPointArrayParam &operator=(const FilletChamferPointArrayParam &);
+
+ SPKnotShapeType knot_shape;
+ SPKnotModeType knot_mode;
+ guint32 knot_color;
+ int helper_size;
+ const gchar *unit;
+ Geom::PathVector hp;
+
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > last_pwd2;
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > last_pwd2_normal;
+};
+
+class FilletChamferPointArrayParamKnotHolderEntity : public KnotHolderEntity {
+public:
+ FilletChamferPointArrayParamKnotHolderEntity(FilletChamferPointArrayParam *p,
+ unsigned int index);
+ virtual ~FilletChamferPointArrayParamKnotHolderEntity() {}
+
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin,
+ guint state);
+ virtual Geom::Point knot_get() const;
+ virtual void knot_click(guint state);
+ virtual void knot_doubleclicked(guint state);
+ virtual void knot_set_offset(Geom::Point offset);
+
+ /*Checks whether the index falls within the size of the parameter's vector*/
+ bool valid_index(unsigned int index) const {
+ return (_pparam->_vector.size() > index);
+ }
+ ;
+
+private:
+ FilletChamferPointArrayParam *_pparam;
+ unsigned int _index;
+};
+
+} //namespace LivePathEffect
+
+} //namespace Inkscape
+
+#endif
diff --git a/src/live_effects/parameter/parameter.cpp b/src/live_effects/parameter/parameter.cpp
index a5de2169e..7732eee76 100644
--- a/src/live_effects/parameter/parameter.cpp
+++ b/src/live_effects/parameter/parameter.cpp
@@ -43,6 +43,15 @@ Parameter::param_write_to_repr(const char * svgd)
param_effect->getRepr()->setAttribute(param_key.c_str(), svgd);
}
+
+// In gtk2, this wasn't an issue; we could toss around
+// G_MAXDOUBLE and not worry about size allocations. But
+// in gtk3, it is an issue: it allocates widget size for the maxmium
+// value you pass to it, leading to some insane lengths.
+// If you need this to be more, please be conservative about it.
+const double SCALARPARAM_G_MAXDOUBLE = 10000000000;
+
+
/*###########################################
* REAL PARAM
*/
@@ -51,8 +60,8 @@ ScalarParam::ScalarParam( const Glib::ustring& label, const Glib::ustring& tip,
Effect* effect, gdouble default_value)
: Parameter(label, tip, key, wr, effect),
value(default_value),
- min(-G_MAXDOUBLE),
- max(G_MAXDOUBLE),
+ min(-SCALARPARAM_G_MAXDOUBLE),
+ max(SCALARPARAM_G_MAXDOUBLE),
integer(false),
defvalue(default_value),
digits(2),
@@ -108,8 +117,22 @@ ScalarParam::param_set_value(gdouble val)
void
ScalarParam::param_set_range(gdouble min, gdouble max)
{
- this->min = min;
- this->max = max;
+ // if you look at client code, you'll see that many effects
+ // has a tendency to set an upper range of Geom::infinity().
+ // Once again, in gtk2, this is not a problem. But in gtk3,
+ // widgets get allocated the amount of size they ask for,
+ // leading to excessively long widgets.
+
+ if (min >= -SCALARPARAM_G_MAXDOUBLE) {
+ this->min = min;
+ } else {
+ this->min = -SCALARPARAM_G_MAXDOUBLE;
+ }
+ if (max <= SCALARPARAM_G_MAXDOUBLE) {
+ this->max = max;
+ } else {
+ this->max = SCALARPARAM_G_MAXDOUBLE;
+ }
param_set_value(value); // reset value to see whether it is in ranges
}
diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp
index fecdfeda8..647986da6 100644
--- a/src/live_effects/parameter/powerstrokepointarray.cpp
+++ b/src/live_effects/parameter/powerstrokepointarray.cpp
@@ -176,7 +176,10 @@ PowerStrokePointArrayParamKnotHolderEntity::knot_get() const
Piecewise<D2<SBasis> > const & n = _pparam->get_pwd2_normal();
Point offset_point = _pparam->_vector.at(_index);
-
+ if (offset_point[X] > pwd2.size() || offset_point[X] < 0) {
+ g_warning("Broken powerstroke point at %f, I won't try to add that", offset_point[X]);
+ return Geom::Point(infinity(), infinity());
+ }
Point canvas_point = pwd2.valueAt(offset_point[X]) + offset_point[Y] * n.valueAt(offset_point[X]);
return canvas_point;
}
diff --git a/src/live_effects/parameter/togglebutton.cpp b/src/live_effects/parameter/togglebutton.cpp
index 03238f935..5658d238f 100644
--- a/src/live_effects/parameter/togglebutton.cpp
+++ b/src/live_effects/parameter/togglebutton.cpp
@@ -5,6 +5,9 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <gtkmm.h>
+#include <glibmm/i18n.h>
+
#include "ui/widget/registered-widget.h"
#include "live_effects/parameter/togglebutton.h"
#include "live_effects/effect.h"
@@ -14,7 +17,6 @@
#include "inkscape.h"
#include "verbs.h"
#include "helper-fns.h"
-#include <glibmm/i18n.h>
namespace Inkscape {
@@ -22,13 +24,20 @@ namespace LivePathEffect {
ToggleButtonParam::ToggleButtonParam( const Glib::ustring& label, const Glib::ustring& tip,
const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr,
- Effect* effect, bool default_value )
- : Parameter(label, tip, key, wr, effect), value(default_value), defvalue(default_value)
+ Effect* effect, bool default_value, const Glib::ustring& inactive_label,
+ char const * icon_active, char const * icon_inactive,
+ Inkscape::IconSize icon_size)
+ : Parameter(label, tip, key, wr, effect), value(default_value), defvalue(default_value),
+ inactiveLabel(inactive_label), iconActive(icon_active), iconInactive(icon_inactive), iconSize(icon_size)
{
+ checkwdg = NULL;
}
ToggleButtonParam::~ToggleButtonParam()
{
+ if (_toggled_connection.connected()) {
+ _toggled_connection.disconnect();
+ }
}
void
@@ -54,7 +63,11 @@ ToggleButtonParam::param_getSVGValue() const
Gtk::Widget *
ToggleButtonParam::param_newWidget()
{
- Inkscape::UI::Widget::RegisteredToggleButton * checkwdg = Gtk::manage(
+ if (_toggled_connection.connected()) {
+ _toggled_connection.disconnect();
+ }
+
+ checkwdg = Gtk::manage(
new Inkscape::UI::Widget::RegisteredToggleButton( param_label,
param_tooltip,
param_key,
@@ -62,18 +75,81 @@ ToggleButtonParam::param_newWidget()
false,
param_effect->getRepr(),
param_effect->getSPDoc()) );
-
+ GtkWidget * boxButton = gtk_hbox_new (false, 0);
+ GtkWidget * labelButton = gtk_label_new ("");
+ if (!param_label.empty()) {
+ if(value || inactiveLabel.empty()){
+ gtk_label_set_text(GTK_LABEL(labelButton), param_label.c_str());
+ }else{
+ gtk_label_set_text(GTK_LABEL(labelButton), inactiveLabel.c_str());
+ }
+ }
+ gtk_widget_show(labelButton);
+ if ( iconActive ) {
+ if(!iconInactive){
+ iconInactive = iconActive;
+ }
+ gtk_widget_show(boxButton);
+ GtkWidget *iconButton = sp_icon_new(iconSize, iconActive);
+ if(!value){
+ iconButton = sp_icon_new(iconSize, iconInactive);
+ }
+ gtk_widget_show(iconButton);
+ gtk_box_pack_start (GTK_BOX(boxButton), iconButton, false, false, 1);
+ if (!param_label.empty()) {
+ gtk_box_pack_start (GTK_BOX(boxButton), labelButton, false, false, 1);
+ }
+ }else{
+ gtk_box_pack_start (GTK_BOX(boxButton), labelButton, false, false, 1);
+ }
+ checkwdg->add(*Gtk::manage(Glib::wrap(boxButton)));
checkwdg->setActive(value);
checkwdg->setProgrammatically = false;
checkwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change togglebutton parameter"));
- return dynamic_cast<Gtk::Widget *> (checkwdg);
+ _toggled_connection = checkwdg->signal_toggled().connect(sigc::mem_fun(*this, &ToggleButtonParam::toggled));
+
+ return checkwdg;
+}
+
+void
+ToggleButtonParam::refresh_button()
+{
+ if(!checkwdg){
+ return;
+ }
+ Gtk::Widget * boxButton = checkwdg->get_child();
+ if(!boxButton){
+ return;
+ }
+ GList * childs = gtk_container_get_children(GTK_CONTAINER(boxButton->gobj()));
+ guint totalWidgets = g_list_length (childs);
+ if (!param_label.empty()) {
+ if(value || inactiveLabel.empty()){
+ gtk_label_set_text(GTK_LABEL(g_list_nth_data(childs, totalWidgets-1)), param_label.c_str());
+ }else{
+ gtk_label_set_text(GTK_LABEL(g_list_nth_data(childs, totalWidgets-1)), inactiveLabel.c_str());
+ }
+ }
+ if ( iconActive ) {
+ GdkPixbuf * iconPixbuf = sp_pixbuf_new( iconSize, iconActive );
+ if(!value){
+ iconPixbuf = sp_pixbuf_new( iconSize, iconInactive);
+ }
+ gtk_image_set_from_pixbuf (GTK_IMAGE(g_list_nth_data(childs, 0)), iconPixbuf);
+ }
}
void
ToggleButtonParam::param_setValue(bool newvalue)
{
value = newvalue;
+ refresh_button();
+}
+
+void
+ToggleButtonParam::toggled() {
+ _signal_toggled.emit();
}
} /* namespace LivePathEffect */
diff --git a/src/live_effects/parameter/togglebutton.h b/src/live_effects/parameter/togglebutton.h
index 9b1c71185..4e545bcfd 100644
--- a/src/live_effects/parameter/togglebutton.h
+++ b/src/live_effects/parameter/togglebutton.h
@@ -2,22 +2,27 @@
#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_TOGGLEBUTTON_H
/*
- * Inkscape::LivePathEffectParameters
- *
-* Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
+ * Copyright (C) Jabiertxo Arraiza Cenoz 2014
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include <glib.h>
+#include <sigc++/connection.h>
+#include <sigc++/signal.h>
#include "live_effects/parameter/parameter.h"
+#include "icon-size.h"
+#include "ui/widget/registered-widget.h"
namespace Inkscape {
namespace LivePathEffect {
-
+/**
+ * class ToggleButtonParam:
+ * represents a Gtk::ToggleButton as a Live Path Effect parameter
+ */
class ToggleButtonParam : public Parameter {
public:
ToggleButtonParam( const Glib::ustring& label,
@@ -25,7 +30,11 @@ public:
const Glib::ustring& key,
Inkscape::UI::Widget::Registry* wr,
Effect* effect,
- bool default_value = false);
+ bool default_value = false,
+ const Glib::ustring& inactive_label = "",
+ char const * icon_active = NULL,
+ char const * icon_inactive = NULL,
+ Inkscape::IconSize icon_size = Inkscape::ICON_SIZE_SMALL_TOOLBAR);
virtual ~ToggleButtonParam();
virtual Gtk::Widget * param_newWidget();
@@ -39,13 +48,25 @@ public:
bool get_value() const { return value; };
inline operator bool() const { return value; };
+
+ sigc::signal<void>& signal_toggled() { return _signal_toggled; }
+ virtual void toggled();
private:
ToggleButtonParam(const ToggleButtonParam&);
ToggleButtonParam& operator=(const ToggleButtonParam&);
+ void refresh_button();
bool value;
bool defvalue;
+ const Glib::ustring inactiveLabel;
+ const char * iconActive;
+ const char * iconInactive;
+ Inkscape::IconSize iconSize;
+ Inkscape::UI::Widget::RegisteredToggleButton * checkwdg;
+
+ sigc::signal<void> _signal_toggled;
+ sigc::connection _toggled_connection;
};