diff options
| author | Jabier Arraiza <jabier.arraiza@marker.es> | 2019-01-25 00:04:08 +0000 |
|---|---|---|
| committer | Jabier Arraiza <jabier.arraiza@marker.es> | 2019-01-27 00:37:54 +0000 |
| commit | eab7157c28648171c0b68e96d41478443c267f9f (patch) | |
| tree | 1b108140d21541942c1e037b055a5ac6c21bd26d /src | |
| parent | Improvements to icon loader code (diff) | |
| download | inkscape-eab7157c28648171c0b68e96d41478443c267f9f.tar.gz inkscape-eab7157c28648171c0b68e96d41478443c267f9f.zip | |
Initial work of LPESelector
Diffstat (limited to 'src')
| -rw-r--r-- | src/live_effects/effect-enum.h | 908 | ||||
| -rw-r--r-- | src/live_effects/effect.cpp | 70 | ||||
| -rw-r--r-- | src/ui/dialog/livepatheffect-add.cpp | 222 | ||||
| -rw-r--r-- | src/ui/dialog/livepatheffect-add.h | 69 | ||||
| -rw-r--r-- | src/ui/dialog/lpe-selector.cpp | 69 | ||||
| -rw-r--r-- | src/ui/dialog/lpe-selector.h | 38 |
6 files changed, 1169 insertions, 207 deletions
diff --git a/src/live_effects/effect-enum.h b/src/live_effects/effect-enum.h index b662d3263..595c81a78 100644 --- a/src/live_effects/effect-enum.h +++ b/src/live_effects/effect-enum.h @@ -11,6 +11,10 @@ */ #include "util/enums.h" +#include <glibmm/i18n.h> + + + namespace Inkscape { namespace LivePathEffect { @@ -75,8 +79,908 @@ enum EffectType { INVALID_LPE // This must be last (I made it such that it is not needed anymore I think..., Don't trust on it being last. - johan) }; -extern const Util::EnumData<EffectType> LPETypeData[]; /// defined in effect.cpp -extern const Util::EnumDataConverter<EffectType> LPETypeConverter; /// defined in effect.cpp +template<typename E> + struct EnumEffectData + { + E id; + const Glib::ustring label; + const Glib::ustring key; + const Glib::ustring icon; + const Glib::ustring description; + const bool on_path; + const bool on_shape; + const bool on_group; + const bool on_use; + const bool on_image; + const bool on_text; + }; + +const Glib::ustring empty_string(""); + +/** + * Simplified management of enumerations of LPE items with UI labels. + * + * @note that get_id_from_key and get_id_from_label return 0 if it cannot find an entry for that key string. + * @note that get_label and get_key return an empty string when the requested id is not in the list. + */ +template<typename E> class EnumEffectDataConverter +{ +public: + typedef EnumEffectData<E> Data; + + EnumEffectDataConverter(const EnumEffectData<E>* cd, const unsigned int length) + : _length(length), _data(cd) + {} + + E get_id_from_label(const Glib::ustring& label) const + { + for(unsigned int i = 0; i < _length; ++i) { + if(_data[i].label == label) + return _data[i].id; + } + + return (E)0; + } + + E get_id_from_key(const Glib::ustring& key) const + { + for(unsigned int i = 0; i < _length; ++i) { + if(_data[i].key == key) + return _data[i].id; + } + + return (E)0; + } + + bool is_valid_key(const Glib::ustring& key) const + { + for(unsigned int i = 0; i < _length; ++i) { + if(_data[i].key == key) + return true; + } + + return false; + } + + bool is_valid_id(const E id) const + { + for(unsigned int i = 0; i < _length; ++i) { + if(_data[i].id == id) + return true; + } + return false; + } + + const Glib::ustring& get_label(const E id) const + { + for(unsigned int i = 0; i < _length; ++i) { + if(_data[i].id == id) + return _data[i].label; + } + + return empty_string; + } + + const Glib::ustring& get_key(const E id) const + { + for(unsigned int i = 0; i < _length; ++i) { + if(_data[i].id == id) + return _data[i].key; + } + + return empty_string; + } + + const Glib::ustring& get_icon(const E id) const + { + for(unsigned int i = 0; i < _length; ++i) { + if(_data[i].id == id) + return _data[i].icon; + } + + return empty_string; + } + + const Glib::ustring& get_description(const E id) const + { + for(unsigned int i = 0; i < _length; ++i) { + if(_data[i].id == id) + return _data[i].description; + } + + return empty_string; + } + + const bool& get_on_path(const E id) const + { + for(unsigned int i = 0; i < _length; ++i) { + if(_data[i].id == id) + return _data[i].path; + } + + return false; + } + + const bool& get_on_shape(const E id) const + { + for(unsigned int i = 0; i < _length; ++i) { + if(_data[i].id == id) + return _data[i].shape; + } + + return false; + } + + const bool& get_on_group(const E id) const + { + for(unsigned int i = 0; i < _length; ++i) { + if(_data[i].id == id) + return _data[i].group; + } + + return false; + } + + const bool& get_on_text(const E id) const + { + for(unsigned int i = 0; i < _length; ++i) { + if(_data[i].id == id) + return _data[i].shape; + } + + return false; + } + + const bool& get_on_use(const E id) const + { + for(unsigned int i = 0; i < _length; ++i) { + if(_data[i].id == id) + return _data[i].use; + } + + return false; + } + + const EnumEffectData<E>& data(const unsigned int i) const + { + return _data[i]; + } + + const unsigned int _length; +private: + const EnumEffectData<E>* _data; +}; + +const EnumEffectData<EffectType> LPETypeData[] = { + // {constant defined in effect-enum.h, N_("name of your effect"), "name of your effect in SVG"} +/* 0.46 */ + { + BEND_PATH + , N_("Bend") //label + , "bend_path" //key + , "bend-path" //icon + , N_("Curve a item based on skeleton path") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + GEARS + , N_("Gears") //label + , "gears" //key + , "gears" //icon + , N_("Create configurable gears") //description + , true //on_path + , true //on_shape + , false //on_group + , false //on_use + , false //on_image + , false //on_text + }, + { + PATTERN_ALONG_PATH + , N_("Pattern Along Path") //label + , "skeletal" //key + , "skeletal" //icon + , N_("transform a tiem along path with or without repeating") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, // for historic reasons, this effect is called skeletal(strokes) in Inkscape:SVG + { + CURVE_STITCH + , N_("Stitch Sub-Paths") //label + , "curvestitching" //key + , "curvestitching" //icon + , N_("curvestitching") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, +/* 0.47 */ + { + VONKOCH + , N_("VonKoch") //label + , "vonkoch" //key + , "vonkoch" //icon + , N_("vonkoch") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + KNOT + , N_("Knot") //label + , "knot" //key + , "knot" //icon + , N_("knot") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + CONSTRUCT_GRID + , N_("Construct grid") //label + , "construct_grid" //key + , "construct-grid" //icon + , N_("construct_grid") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + SPIRO + , N_("Spiro spline") //label + , "spiro" //key + , "spiro" //icon + , N_("spiro") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + ENVELOPE + , N_("Envelope Deformation") //label + , "envelope" //key + , "envelope" //icon + , N_("Envelope Deformation") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + INTERPOLATE + , N_("Interpolate Sub-Paths") //label + , "interpolate" //key + , "interpolate" //icon + , N_("Interpolate Sub-Paths") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + ROUGH_HATCHES + , N_("Hatches (rough)") //label + , "rough_hatches" //key + , "rough-hatches" //icon + , N_("Hatches (rough)") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + SKETCH + , N_("Sketch") //label + , "sketch" //key + , "sketch" //icon + , N_("Sketch") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + RULER + , N_("Ruler") //label + , "ruler" //key + , "ruler" //icon + , N_("Ruler") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, +/* 0.91 */ + { + POWERSTROKE + , N_("Power stroke") //label + , "powerstroke" //key + , "powerstroke" //icon + , N_("Power stroke") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + CLONE_ORIGINAL + , N_("Clone original") //label + , "clone_original" //key + , "clone-original" //icon + , N_("Clone original") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, +/* 0.92 */ + { + SIMPLIFY + , N_("Simplify") //label + , "simplify" //key + , "simplify" //icon + , N_("Simplify") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + LATTICE2 + , N_("Lattice Deformation 2") //label + , "lattice2" //key + , "lattice2" //icon + , N_("Lattice Deformation 2") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + PERSPECTIVE_ENVELOPE + , N_("Perspective/Envelope") //label + , "perspective-envelope" //key wrong key with "-" retain because historic + , "perspective-envelope" //icon + , N_("Perspective/Envelope") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + INTERPOLATE_POINTS + , N_("Interpolate points") //label + , "interpolate_points" //key + , "interpolate-points" //icon + , N_("Interpolate points") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + TRANSFORM_2PTS + , N_("Transform by 2 points") //label + , "transform_2pts" //key + , "transform-2pts" //icon + , N_("Transform by 2 points") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + SHOW_HANDLES + , N_("Show handles") //label + , "show_handles" //key + , "show-handles" //icon + , N_("Show handles") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + ROUGHEN + , N_("Roughen") //label + , "roughen" //key + , "roughen" //icon + , N_("Roughen") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + BSPLINE + , N_("BSpline") //label + , "bspline" //key + , "bspline" //icon + , N_("BSpline") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + JOIN_TYPE + , N_("Join type") //label + , "join_type" //key + , "join-type" //icon + , N_("Join type") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + TAPER_STROKE + , N_("Taper stroke") //label + , "taper_stroke" //key + , "taper-stroke" //icon + , N_("Taper stroke") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + MIRROR_SYMMETRY + , N_("Mirror symmetry") //label + , "mirror_symmetry" //key + , "mirror-symmetry" //icon + , N_("Mirror symmetry") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + COPY_ROTATE + , N_("Rotate copies") //label + , "copy_rotate" //key + , "copy-rotate" //icon + , N_("Rotate copies") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, +/* Ponyscape -> Inkscape 0.92*/ + { + ATTACH_PATH + , N_("Attach path") //label + , "attach_path" //key + , "attach-path" //icon + , N_("Attach path") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + FILL_BETWEEN_STROKES + , N_("Fill between strokes") //label + , "fill_between_strokes" //key + , "fill-between-strokes" //icon + , N_("Fill between strokes") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + FILL_BETWEEN_MANY + , N_("Fill between many") //label + , "fill_between_many" //key + , "fill-between-many" //icon + , N_("Fill between many") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + ELLIPSE_5PTS + , N_("Ellipse by 5 points") //label + , "ellipse_5pts" //key + , "ellipse-5pts" //icon + , N_("Ellipse by 5 points") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + BOUNDING_BOX + , N_("Bounding Box") //label + , "bounding_box" //key + , "bounding-box" //icon + , N_("Bounding Box") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, +/* 1.0 */ + { + MEASURE_SEGMENTS + , N_("Measure Segments") //label + , "measure_segments" //key + , "measure-segments" //icon + , N_("Measure Segments") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + FILLET_CHAMFER + , N_("Fillet/Chamfer") //label + , "fillet_chamfer" //key + , "fillet-chamfer" //icon + , N_("Fillet/Chamfer") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + BOOL_OP + , N_("Boolean operation") //label + , "bool_op" //key + , "bool-op" //icon + , N_("Boolean operation") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + EMBRODERY_STITCH + , N_("Embroidery stitch") //label + , "embrodery_stitch" //key + , "embrodery-stitch" //icon + , N_("Embroidery stitch") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + POWERCLIP + , N_("Power clip") //label + , "powerclip" //key + , "powerclip" //icon + , N_("Power clip") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + POWERMASK + , N_("Power mask") //label + , "powermask" //key + , "powermask" //icon + , N_("Power mask") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + PTS2ELLIPSE + , N_("Ellipse from points") //label + , "pts2ellipse" //key + , "pts2ellipse" //icon + , N_("Ellipse from points") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + OFFSET + , N_("Offset") //label + , "offset" //key + , "offset" //icon + , N_("Offset") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + DASH_STROKE + , N_("Dash Stroke") //label + , "dash_stroke" //key + , "dash-stroke" //icon + , N_("Dash Stroke") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, +#ifdef LPE_ENABLE_TEST_EFFECTS + { + DOEFFECTSTACK_TEST + , N_("doEffect stack test") //label + , "doeffectstacktest" //key + , "experimental" //icon + , N_("doEffect stack test") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + ANGLE_BISECTOR + , N_("Angle bisector") //label + , "angle_bisector" //key + , "experimental" //icon + , N_("Angle bisector") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + CIRCLE_WITH_RADIUS + , N_("Circle (by center and radius)") //label + , "circle_with_radius" //key + , "experimental" //icon + , N_("Circle (by center and radius)") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + CIRCLE_3PTS + , N_("Circle by 3 points") //label + , "circle_3pts" //key + , "experimental" //icon + , N_("Circle by 3 points") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + DYNASTROKE + , N_("Dynamic stroke") //label + , "dynastroke" //key + , "experimental" //icon + , N_("Dynamic stroke") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + EXTRUDE + , N_("Extrude") //label + , "extrude" //key + , "experimental" //icon + , N_("Extrude") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + LATTICE + , N_("Lattice Deformation") //label + , "lattice" //key + , "experimental" //icon + , N_("Lattice Deformation") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + LINE_SEGMENT + , N_("Line Segment") //label + , "line_segment" //key + , "experimental" //icon + , N_("Line Segment") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + PARALLEL + , N_("Parallel") //label + , "parallel" //key + , "experimental" //icon + , N_("Parallel") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + PATH_LENGTH + , N_("Path length") //label + , "path_length" //key + , "experimental" //icon + , N_("Path length") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + PERP_BISECTOR + , N_("Perpendicular bisector") //label + , "perp_bisector" //key + , "experimental" //icon + , N_("Perpendicular bisector") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + RECURSIVE_SKELETON + , N_("Recursive skeleton") //label + , "recursive_skeleton" //key + , "experimental" //icon + , N_("Recursive skeleton") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + TANGENT_TO_CURVE + , N_("Tangent to curve") //label + , "tangent_to_curve" //key + , "experimental" //icon + , N_("Tangent to curve") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, + { + TEXT_LABEL + , N_("Text label") //label + , "text_label" //key + , "experimental" //icon + , N_("Text label") //description + , true //on_path + , true //on_shape + , true //on_group + , true //on_use + , false //on_image + , false //on_text + }, +#endif + +}; + +extern const EnumEffectData<EffectType> LPETypeData[]; /// defined in effect.cpp +extern const EnumEffectDataConverter<EffectType> LPETypeConverter; /// defined in effect.cpp } //namespace LivePathEffect } //namespace Inkscape diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 92f5a781a..f83d07c6d 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -94,74 +94,10 @@ namespace Inkscape { namespace LivePathEffect { -const Util::EnumData<EffectType> LPETypeData[] = { - // {constant defined in effect-enum.h, N_("name of your effect"), "name of your effect in SVG"} -/* 0.46 */ - {BEND_PATH, N_("Bend"), "bend_path"}, - {GEARS, N_("Gears"), "gears"}, - {PATTERN_ALONG_PATH, N_("Pattern Along Path"), "skeletal"}, // for historic reasons, this effect is called skeletal(strokes) in Inkscape:SVG - {CURVE_STITCH, N_("Stitch Sub-Paths"), "curvestitching"}, -/* 0.47 */ - {VONKOCH, N_("VonKoch"), "vonkoch"}, - {KNOT, N_("Knot"), "knot"}, - {CONSTRUCT_GRID, N_("Construct grid"), "construct_grid"}, - {SPIRO, N_("Spiro spline"), "spiro"}, - {ENVELOPE, N_("Envelope Deformation"), "envelope"}, - {INTERPOLATE, N_("Interpolate Sub-Paths"), "interpolate"}, - {ROUGH_HATCHES, N_("Hatches (rough)"), "rough_hatches"}, - {SKETCH, N_("Sketch"), "sketch"}, - {RULER, N_("Ruler"), "ruler"}, -/* 0.91 */ - {POWERSTROKE, N_("Power stroke"), "powerstroke"}, - {CLONE_ORIGINAL, N_("Clone original"), "clone_original"}, -/* 0.92 */ - {SIMPLIFY, N_("Simplify"), "simplify"}, - {LATTICE2, N_("Lattice Deformation 2"), "lattice2"}, - {PERSPECTIVE_ENVELOPE, N_("Perspective/Envelope"), "perspective-envelope"}, //TODO:Wrong name with "-" - {INTERPOLATE_POINTS, N_("Interpolate points"), "interpolate_points"}, - {TRANSFORM_2PTS, N_("Transform by 2 points"), "transform_2pts"}, - {SHOW_HANDLES, N_("Show handles"), "show_handles"}, - {ROUGHEN, N_("Roughen"), "roughen"}, - {BSPLINE, N_("BSpline"), "bspline"}, - {JOIN_TYPE, N_("Join type"), "join_type"}, - {TAPER_STROKE, N_("Taper stroke"), "taper_stroke"}, - {MIRROR_SYMMETRY, N_("Mirror symmetry"), "mirror_symmetry"}, - {COPY_ROTATE, N_("Rotate copies"), "copy_rotate"}, -/* Ponyscape -> Inkscape 0.92*/ - {ATTACH_PATH, N_("Attach path"), "attach_path"}, - {FILL_BETWEEN_STROKES, N_("Fill between strokes"), "fill_between_strokes"}, - {FILL_BETWEEN_MANY, N_("Fill between many"), "fill_between_many"}, - {ELLIPSE_5PTS, N_("Ellipse by 5 points"), "ellipse_5pts"}, - {BOUNDING_BOX, N_("Bounding Box"), "bounding_box"}, -/* 0.93 */ - {MEASURE_SEGMENTS, N_("Measure Segments"), "measure_segments"}, - {FILLET_CHAMFER, N_("Fillet/Chamfer"), "fillet_chamfer"}, - {BOOL_OP, N_("Boolean operation"), "bool_op"}, - {EMBRODERY_STITCH, N_("Embroidery stitch"), "embrodery_stitch"}, - {POWERCLIP, N_("Power clip"), "powerclip"}, - {POWERMASK, N_("Power mask"), "powermask"}, - {PTS2ELLIPSE, N_("Ellipse from points"), "pts2ellipse"}, - {OFFSET, N_("Offset"), "offset"}, - {DASH_STROKE, N_("Dash Stroke"), "dash_stroke"}, -#ifdef LPE_ENABLE_TEST_EFFECTS - {DOEFFECTSTACK_TEST, N_("doEffect stack test"), "doeffectstacktest"}, - {ANGLE_BISECTOR, N_("Angle bisector"), "angle_bisector"}, - {CIRCLE_WITH_RADIUS, N_("Circle (by center and radius)"), "circle_with_radius"}, - {CIRCLE_3PTS, N_("Circle by 3 points"), "circle_3pts"}, - {DYNASTROKE, N_("Dynamic stroke"), "dynastroke"}, - {EXTRUDE, N_("Extrude"), "extrude"}, - {LATTICE, N_("Lattice Deformation"), "lattice"}, - {LINE_SEGMENT, N_("Line Segment"), "line_segment"}, - {PARALLEL, N_("Parallel"), "parallel"}, - {PATH_LENGTH, N_("Path length"), "path_length"}, - {PERP_BISECTOR, N_("Perpendicular bisector"), "perp_bisector"}, - {RECURSIVE_SKELETON, N_("Recursive skeleton"), "recursive_skeleton"}, - {TANGENT_TO_CURVE, N_("Tangent to curve"), "tangent_to_curve"}, - {TEXT_LABEL, N_("Text label"), "text_label"}, -#endif -}; -const Util::EnumDataConverter<EffectType> LPETypeConverter(LPETypeData, sizeof(LPETypeData)/sizeof(*LPETypeData)); + + +const EnumEffectDataConverter<EffectType> LPETypeConverter(LPETypeData, sizeof(LPETypeData)/sizeof(*LPETypeData)); int Effect::acceptsNumClicks(EffectType type) { diff --git a/src/ui/dialog/livepatheffect-add.cpp b/src/ui/dialog/livepatheffect-add.cpp index 1fae9a513..f930199cf 100644 --- a/src/ui/dialog/livepatheffect-add.cpp +++ b/src/ui/dialog/livepatheffect-add.cpp @@ -13,9 +13,10 @@ # include "config.h" // only include where actually required! #endif +#include "live_effects/effect.h" #include "livepatheffect-add.h" #include <glibmm/i18n.h> - +#include "io/resource.h" #include "desktop.h" namespace Inkscape { @@ -23,87 +24,147 @@ namespace UI { namespace Dialog { LivePathEffectAdd::LivePathEffectAdd() : - add_button(_("_Add"), true), - close_button(_("_Cancel"), true), - converter(Inkscape::LivePathEffect::LPETypeConverter), - applied(false) + _add_button(_("_Add"), true), + _close_button(_("_Cancel"), true), + converter(Inkscape::LivePathEffect::LPETypeConverter) { - set_title(_("Add Path Effect")); - - /** - * Scrolled Window - */ - scrolled_window.add(effectlist_treeview); - scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); - scrolled_window.set_shadow_type(Gtk::SHADOW_IN); - scrolled_window.set_size_request(250, 200); - scrolled_window.set_can_focus(); - - /** - * Effect Store and Tree - */ - effectlist_store = Gtk::ListStore::create(_columns); - effectlist_store->set_sort_column (_columns.name, Gtk::SORT_ASCENDING ); - - effectlist_treeview.set_model(effectlist_store); - effectlist_treeview.set_headers_visible(false); - effectlist_treeview.append_column("Name", _columns.name); - //effectlist_treeview.set_activates_default(true); + const std::string req_widgets[] = {"LPESelector", "LPESelectorFlowBox"}; + Glib::ustring gladefile = get_filename(Inkscape::IO::Resource::UIS, "lpe-selector.glade"); + try { + _builder = Gtk::Builder::create_from_file(gladefile); + } catch(const Glib::Error& ex) { + g_warning("Glade file loading failed for filter effect dialog"); + return; + } + Gtk::Object* test; + for(std::string w:req_widgets) { + _builder->get_widget(w,test); + if(!test){ + g_warning("Required widget %s does not exist", w.c_str()); + return; + } + } + _builder->get_widget("LPESelector", _LPESelector); + auto mainVBox = get_content_area(); + mainVBox->pack_start(*_LPESelector, true, true); /** * Initialize Effect list */ - int show = LivePathEffect::ATTACH_PATH; -#ifdef LPE_ENABLE_TEST_EFFECTS - //TODO: Handle when showing the experimental effects without setting flag - show = LivePathEffect::ANGLE_BISECTOR; -#elif WITH_LPETOOL - //TODO: Handle when showing the experimental effects without setting flag - show = LivePathEffect::ANGLE_BISECTOR; -#endif - + _builder->get_widget("LPESelectorFlowBox", _LPESelectorFlowBox); + _builder->get_widget("LPEFilter", _LPEFilter); + _builder->get_widget("LPEInfo", _LPEInfo); + _LPEFilter->signal_search_changed().connect(sigc::mem_fun(*this, &LivePathEffectAdd::on_search)); + const std::string le_widgets[] = {"LPESelectorItem", "LPEName","LPEDescription"}; + Glib::ustring le_gladefile = get_filename(Inkscape::IO::Resource::UIS, "lpe-selector-item.glade"); for(int i = 0; i < static_cast<int>(converter._length); ++i) { - Gtk::TreeModel::Row row = *(effectlist_store->append()); - const Util::EnumData<LivePathEffect::EffectType>* data = &converter.data(i); - row[_columns.name] = _( converter.get_label(data->id).c_str() ); - row[_columns.data] = data; - if (i == show) { - Glib::RefPtr<Gtk::TreeSelection> select = effectlist_treeview.get_selection(); - select->select(row); + + try { + _builder = Gtk::Builder::create_from_file(le_gladefile); + } catch(const Glib::Error& ex) { + g_warning("Glade file loading failed for filter effect dialog"); + return; } - } - - /** - * Buttons - */ - //close_button.set_can_default(); - add_button.set_use_underline(true); - add_button.set_can_default(); - auto mainVBox = get_content_area(); - - mainVBox->pack_start(scrolled_window, true, true); - add_action_widget(close_button, Gtk::RESPONSE_CLOSE); - add_action_widget(add_button, Gtk::RESPONSE_APPLY); + Gtk::Object* test; + for(std::string w:le_widgets) { + _builder->get_widget(w,test); + if(!test){ + g_warning("Required widget %s does not exist", w.c_str()); + return; + } + } + const LivePathEffect::EnumEffectData<LivePathEffect::EffectType>* data = &converter.data(i); + Gtk::Label * LPEName; + _builder->get_widget("LPEName", LPEName); + Glib::ustring newid = "LPEName_" + Glib::ustring::format(i); + (*LPEName).set_name(newid); + (*LPEName).set_text(converter.get_label(data->id).c_str()); + Gtk::Label * LPEDescription; + _builder->get_widget("LPEDescription", LPEDescription); + newid = "LPEDescription_" + Glib::ustring::format(i); + (*LPEDescription).set_name(newid); + (*LPEDescription).set_text(converter.get_description(data->id)); + Gtk::Image * LPEIcon; + _builder->get_widget("LPEIcon", LPEIcon); + newid = "LPEIcon_" + Glib::ustring::format(i); + (*LPEIcon).set_name(newid); + (*LPEIcon).set_from_icon_name(converter.get_icon(data->id),Gtk::BuiltinIconSize(Gtk::ICON_SIZE_DIALOG)); + Gtk::Box * LPESelectorItem; + _builder->get_widget("LPESelectorItem", LPESelectorItem); + newid = "LPESelectorItem" + Glib::ustring::format(i); + (*LPESelectorItem).set_name(newid); + _LPESelectorFlowBox->insert(*LPESelectorItem, i); + } + _visiblelpe = _LPESelectorFlowBox->get_children().size(); + _LPESelectorFlowBox->signal_child_activated().connect(sigc::mem_fun(*this, &LivePathEffectAdd::on_activate)); + set_title(_("Live Efects Selector")); + show_all_children(); + _LPEInfo->set_visible(false); +} - - /** - * Signal handlers - */ - effectlist_treeview.signal_button_press_event().connect_notify( sigc::mem_fun(*this, &LivePathEffectAdd::onButtonEvent) ); - effectlist_treeview.signal_key_press_event().connect_notify(sigc::mem_fun(*this, &LivePathEffectAdd::onKeyEvent)); - close_button.signal_clicked().connect(sigc::mem_fun(*this, &LivePathEffectAdd::onClose)); - add_button.signal_clicked().connect(sigc::mem_fun(*this, &LivePathEffectAdd::onAdd)); - signal_delete_event().connect( sigc::bind_return(sigc::hide(sigc::mem_fun(*this, &LivePathEffectAdd::onClose)), true ) ); +void LivePathEffectAdd::on_activate(Gtk::FlowBoxChild *child){ + for (auto i:_LPESelectorFlowBox->get_children()) { + Gtk::FlowBoxChild * leitem = dynamic_cast<Gtk::FlowBoxChild *>(i); + leitem->get_style_context()->remove_class("lpeactive"); + Gtk::Box *box = dynamic_cast<Gtk::Box *>(leitem->get_child()); + if (box) { + std::vector<Gtk::Widget*> contents = box->get_children(); + Gtk::Box *actions = dynamic_cast<Gtk::Box *>(contents[3]); + if (actions) { + actions->set_visible(false); + } + } + } + child->get_style_context()->add_class("lpeactive"); + child->show_all_children(); +} - add_button.grab_default(); +bool LivePathEffectAdd::on_filter(Gtk::FlowBoxChild *child) +{ + if (_LPEFilter->get_text().length() < 4) { + _visiblelpe = _LPESelectorFlowBox->get_children().size(); + return true; + } + Gtk::Box *box = dynamic_cast<Gtk::Box *>(child->get_child()); + if (box) { + std::vector<Gtk::Widget*> contents = box->get_children(); + Gtk::Label *lpename = dynamic_cast<Gtk::Label *>(contents[1]); + if (lpename) { + size_t s = lpename->get_text().uppercase().find(_LPEFilter->get_text().uppercase(),0); + if(s != -1) { + _visiblelpe++; + return true; + } + } + Gtk::Label *lpedesc = dynamic_cast<Gtk::Label *>(contents[2]); + if (lpedesc) { + size_t s = lpedesc->get_text().uppercase().find(_LPEFilter->get_text().uppercase(),0); + if(s != -1) { + _visiblelpe++; + return true; + } + } + } + return false; +} - show_all_children(); +void LivePathEffectAdd::on_search() +{ + _visiblelpe = 0; + _LPESelectorFlowBox->set_filter_func(sigc::mem_fun(*this, &LivePathEffectAdd::on_filter)); + if (_visiblelpe == 0) { + _LPEInfo->set_text(_("Your search do a empty result, please try again")); + _LPEInfo->set_visible(true); + _LPEInfo->get_style_context()->add_class("lpeinfowarn"); + } else { + _LPEInfo->set_visible(false); + _LPEInfo->get_style_context()->remove_class("lpeinfowarn"); + } } void LivePathEffectAdd::onAdd() { - applied = true; onClose(); } @@ -122,35 +183,14 @@ void LivePathEffectAdd::onKeyEvent(GdkEventKey* evt) } } -void LivePathEffectAdd::onButtonEvent(GdkEventButton* evt) -{ - // Double click on tree is same as clicking the add button - if (evt->type == GDK_2BUTTON_PRESS) { - onAdd(); - } -} - -const Util::EnumData<LivePathEffect::EffectType>* -LivePathEffectAdd::getActiveData() -{ - Gtk::TreeModel::iterator iter = instance().effectlist_treeview.get_selection()->get_selected(); - if ( iter ) { - Gtk::TreeModel::Row row = *iter; - return row[instance()._columns.data]; - } - - return nullptr; -} - - void LivePathEffectAdd::show(SPDesktop *desktop) { LivePathEffectAdd &dial = instance(); - dial.applied=false; dial.set_modal(true); - desktop->setWindowTransient (dial.gobj()); + //dial.set_decorated(false); + dial.set_name("lpedialogselector"); + //desktop->setWindowTransient (dial.gobj()); dial.property_destroy_with_parent() = true; - dial.effectlist_treeview.grab_focus(); dial.run(); } diff --git a/src/ui/dialog/livepatheffect-add.h b/src/ui/dialog/livepatheffect-add.h index 84901385c..88aca58b2 100644 --- a/src/ui/dialog/livepatheffect-add.h +++ b/src/ui/dialog/livepatheffect-add.h @@ -12,10 +12,14 @@ #ifndef INKSCAPE_DIALOG_LIVEPATHEFFECT_ADD_H #define INKSCAPE_DIALOG_LIVEPATHEFFECT_ADD_H +#include <gtkmm/box.h> +#include <gtkmm/builder.h> +#include <gtkmm/label.h> +#include <gtkmm/flowbox.h> +#include <gtkmm/stylecontext.h> +#include <gtkmm/flowboxchild.h> +#include <gtkmm/searchentry.h> #include <gtkmm/dialog.h> -#include <gtkmm/liststore.h> -#include <gtkmm/treeview.h> -#include <gtkmm/scrolledwindow.h> #include "live_effects/effect-enum.h" class SPDesktop; @@ -37,31 +41,23 @@ public: * Show the dialog */ static void show(SPDesktop *desktop); - - /** - * Returns true is the "Add" button was pressed - */ static bool isApplied() { - return instance().applied; + return false; } - /** - * Return the data associated with the currently selected item - */ - static const Util::EnumData<LivePathEffect::EffectType>* getActiveData(); - + static const Util::EnumData<LivePathEffect::EffectType>* getActiveData(){return NULL;}; protected: - /** * Close button was clicked */ void onClose(); - + bool on_filter(Gtk::FlowBoxChild *child); + void on_search(); + void on_activate(Gtk::FlowBoxChild *child); /** * Add button was clicked */ void onAdd(); - /** * Tree was clicked */ @@ -72,37 +68,16 @@ protected: */ void onKeyEvent(GdkEventKey* evt); private: - - Gtk::TreeView effectlist_treeview; - Gtk::ScrolledWindow scrolled_window; - Gtk::Button add_button; - Gtk::Button close_button; - - class ModelColumns : public Gtk::TreeModel::ColumnRecord - { - public: - ModelColumns() - { - add(name); - //add(desc); - add(data); - } - ~ModelColumns() override = default; - - Gtk::TreeModelColumn<Glib::ustring> name; - /** - * TODO - Get detailed descriptions of each Effect to show in the dialog - */ - //Gtk::TreeModelColumn<Glib::ustring> desc; - Gtk::TreeModelColumn<const Util::EnumData<LivePathEffect::EffectType>*> data; - }; - - ModelColumns _columns; - Glib::RefPtr<Gtk::ListStore> effectlist_store; - const Util::EnumDataConverter<LivePathEffect::EffectType>& converter; - - bool applied; - + Gtk::Button _add_button; + Gtk::Button _close_button; + Glib::RefPtr<Gtk::Builder> _builder; + Gtk::FlowBox * _LPESelectorFlowBox; + Gtk::SearchEntry *_LPEFilter; + Gtk::Label *_LPEInfo; + Gtk::Box *_LPESelector; + guint _visiblelpe; + class Effect; + const LivePathEffect::EnumEffectDataConverter<LivePathEffect::EffectType>& converter; static LivePathEffectAdd &instance() { static LivePathEffectAdd instance_; return instance_; diff --git a/src/ui/dialog/lpe-selector.cpp b/src/ui/dialog/lpe-selector.cpp new file mode 100644 index 000000000..5a2f39db4 --- /dev/null +++ b/src/ui/dialog/lpe-selector.cpp @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** + * @file + * Filter Effects dialog. + */ +/* Authors: + * Marc Jeanmougin + * + * Copyright (C) 2017 Authors + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include <glibmm/convert.h> +#include <glibmm/error.h> +#include <glibmm/i18n.h> +#include <glibmm/main.h> +#include <glibmm/stringutils.h> +#include "io/sys.h" +#include "io/resource.h" + +namespace Inkscape { +namespace UI { + +LPESelector::LPESelector() : Gtk::Box() +{ + + const std::string req_widgets[] = {"LPESelector", "FilterList", "FilterFERX", "FilterFERY", "FilterFERH", "FilterFERW", "FilterPreview", "FilterPrimitiveDescImage", "FilterPrimitiveList", "FilterPrimitiveDescText", "FilterPrimitiveAdd"}; + Glib::ustring gladefile = get_filename(UIS, "lpe-selector.glade"); + try { + builder = Gtk::Builder::create_from_file(gladefile); + } catch(const Glib::Error& ex) { + g_warning("Glade file loading failed for filter effect dialog"); + return; + } + + Gtk::Object* test; + for(std::string w:req_widgets) { + builder->get_widget(w,test); + if(!test){ + g_warning("Required widget %s does not exist", w.c_str()); + return; + } + } + + builder->get_widget("LPESelector", LPESelector); + _getContents()->add(*LPESelector); + +} +LPESelector::~LPESelector()= default; + + + + + + +} // Never put these namespaces together unless you are using gcc 6+ +} + +/* + 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/lpe-selector.h b/src/ui/dialog/lpe-selector.h new file mode 100644 index 000000000..cc6d80f5a --- /dev/null +++ b/src/ui/dialog/lpe-selector.h @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** @file + * @brief Filter Editor dialog + */ +/* Authors: + * Marc Jeanmougin + * + * Copyright (C) 2017 Authors + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_LPE_SELECTOR_H +#define INKSCAPE_UI_LPE_SELECTOR_H + +#include <gtkmm/gtkmm.h> + +namespace Inkscape { +namespace UI { + +class LPESelector : public Gtk::Box { +public: + + LPESelector(); + ~LPESelector() override; + + static LPESelector &getInstance() + { return *new LPESelector(); } + +// void set_attrs_locked(const bool); +private: + Glib::RefPtr<Gtk::Builder> builder; + Glib::RefPtr<Glib::Object> FilterStore; + Gtk::Box *LPESelector; +}; +} +} +#endif |
