Code

Translations. POTFILES.in, inkcape.pot and fr.po updated.
[inkscape.git] / src / shape-editor.cpp
1 /*
2  * Inkscape::ShapeEditor
3  *
4  * Authors:
5  *   bulia byak <buliabyak@users.sf.net>
6  *   Krzysztof KosiƄski <tweenk.pl@gmail.com>
7  *
8  */
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
14 #include <string.h>
15 #include <glibmm/i18n.h>
17 #include "sp-object.h"
18 #include "sp-item.h"
19 #include "sp-lpe-item.h"
20 #include "live_effects/lpeobject.h"
21 #include "selection.h"
22 #include "desktop.h"
23 #include "document.h"
24 #include "desktop-handles.h"
25 #include "knotholder.h"
26 #include "live_effects/parameter/point.h"
27 #include "xml/node-event-vector.h"
28 #include "preferences.h"
29 #include "object-edit.h"
30 #include "style.h"
31 #include "display/curve.h"
32 #include <2geom/pathvector.h>
34 #include "shape-editor.h"
36 ShapeEditor::ShapeEditor(SPDesktop *dt) {
37     this->desktop = dt;
38     this->knotholder = NULL;
39     this->knotholder_listener_attached_for = NULL;
40 }
42 ShapeEditor::~ShapeEditor() {
43     unset_item(SH_KNOTHOLDER);
44 }
46 void ShapeEditor::unset_item(SubType type, bool keep_knotholder) {
47     Inkscape::XML::Node *old_repr = NULL;
49     switch (type) {
50         case SH_NODEPATH:
51             // defunct
52             break;
53         case SH_KNOTHOLDER:
54             if (this->knotholder) {
55                 old_repr = this->knotholder->repr;
56                 if (old_repr && old_repr == knotholder_listener_attached_for) {
57                     sp_repr_remove_listener_by_data(old_repr, this);
58                     Inkscape::GC::release(old_repr);
59                     knotholder_listener_attached_for = NULL;
60                 }
62                 if (!keep_knotholder) {
63                     delete this->knotholder;
64                     this->knotholder = NULL;
65                 }
66             }
67             break;
68     }
69 }
71 bool ShapeEditor::has_nodepath () {
72     return false;
73 }
75 bool ShapeEditor::has_knotholder () {
76     return (this->knotholder != NULL);
77 }
79 void ShapeEditor::update_knotholder () {
80     if (this->knotholder)
81         this->knotholder->update_knots();
82 }
84 bool ShapeEditor::has_local_change (SubType type) {
85     switch (type) {
86         case SH_NODEPATH:
87             // defunct
88             return false;
89         case SH_KNOTHOLDER:
90             return (this->knotholder && this->knotholder->local_change != 0);
91         default:
92             g_assert_not_reached();
93     }
94 }
96 void ShapeEditor::decrement_local_change (SubType type) {
97     switch (type) {
98         case SH_NODEPATH:
99             // defunct
100             break;
101         case SH_KNOTHOLDER:
102             if (this->knotholder) {
103                 this->knotholder->local_change = FALSE;
104             }
105             break;
106         default:
107             g_assert_not_reached();
108     }
111 const SPItem *ShapeEditor::get_item (SubType type) {
112     const SPItem *item = NULL;
113     switch (type) {
114         case SH_NODEPATH:
115             // defunct
116             break;
117         case SH_KNOTHOLDER:
118             if (this->has_knotholder()) {
119                 item = this->knotholder->getItem();
120             }
121             break;
122     }
123     return item;
126 GList *ShapeEditor::save_nodepath_selection () {
127     // defunct stub
128     return NULL;
131 void ShapeEditor::restore_nodepath_selection (GList */*saved*/) {
132     // defunct stub
135 void ShapeEditor::shapeeditor_event_attr_changed(gchar const *name)
137     gboolean changed_kh = FALSE;
139     if (has_knotholder())
140     {
141         changed_kh = !has_local_change(SH_KNOTHOLDER);
142         decrement_local_change(SH_KNOTHOLDER);
143         if (changed_kh) {
144             // this can happen if an LPEItem's knotholder handle was dragged, in which case we want
145             // to keep the knotholder; in all other cases (e.g., if the LPE itself changes) we delete it
146             reset_item(SH_KNOTHOLDER, !strcmp(name, "d"));
147         }
148     }
152 static void shapeeditor_event_attr_changed(Inkscape::XML::Node */*repr*/, gchar const *name,
153                                            gchar const */*old_value*/, gchar const */*new_value*/,
154                                            bool /*is_interactive*/, gpointer data)
156     g_assert(data);
157     ShapeEditor *sh = ((ShapeEditor *) data);
159     sh->shapeeditor_event_attr_changed(name);
162 static Inkscape::XML::NodeEventVector shapeeditor_repr_events = {
163     NULL, /* child_added */
164     NULL, /* child_removed */
165     shapeeditor_event_attr_changed,
166     NULL, /* content_changed */
167     NULL  /* order_changed */
168 };
171 void ShapeEditor::set_item(SPItem *item, SubType type, bool keep_knotholder) {
172     // this happens (and should only happen) when for an LPEItem having both knotholder and
173     // nodepath the knotholder is adapted; in this case we don't want to delete the knotholder
174     // since this freezes the handles
175     unset_item(type, keep_knotholder);
177     if (item) {
178         Inkscape::XML::Node *repr;
179         switch(type) {
180             case SH_NODEPATH:
181                 // defunct
182                 break;
184             case SH_KNOTHOLDER:
185                 if (!this->knotholder) {
186                     // only recreate knotholder if none is present
187                     this->knotholder = sp_item_knot_holder(item, desktop);
188                 }
189                 if (this->knotholder) {
190                     this->knotholder->update_knots();
191                     // setting new listener
192                     repr = this->knotholder->repr;
193                     if (repr != knotholder_listener_attached_for) {
194                         Inkscape::GC::anchor(repr);
195                         sp_repr_add_listener(repr, &shapeeditor_repr_events, this);
196                         knotholder_listener_attached_for = repr;
197                     }
198                 }
199                 break;
200         }
201     }
205 /** FIXME: This thing is only called when the item needs to be updated in response to repr change.
206    Why not make a reload function in NodePath and in KnotHolder? */
207 void ShapeEditor::reset_item (SubType type, bool keep_knotholder)
209     switch (type) {
210         case SH_NODEPATH:
211             // defunct
212             break;
213         case SH_KNOTHOLDER:
214             if ( knotholder ) {
215                 SPObject *obj = sp_desktop_document(desktop)->getObjectByRepr(knotholder_listener_attached_for); /// note that it is not certain that this is an SPItem; it could be a LivePathEffectObject.
216                 set_item(SP_ITEM(obj), SH_KNOTHOLDER, keep_knotholder);
217             }
218             break;
219     }
222 void ShapeEditor::nodepath_destroyed () {
225 bool ShapeEditor::has_selection() {
226     return false; //  so far, knotholder cannot have selection
229 /**
230  * \brief Returns true if this ShapeEditor has a knot above which the mouse currently hovers
231  */
232 bool ShapeEditor::knot_mouseover()
234     if (this->knotholder) {
235         return knotholder->knot_mouseover();
236     }
237     return false;
240 /*
241   Local Variables:
242   mode:c++
243   c-file-style:"stroustrup"
244   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
245   indent-tabs-mode:nil
246   fill-column:99
247   End:
248 */
249 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :