Code

fix lpe-PathPAram when deleting the path that it links to
[inkscape.git] / src / live_effects / parameter / pointparam-knotholder.cpp
1 #define INKSCAPE_LPE_POINTPARAM_KNOTHOLDER_C\r
2 \r
3 /*\r
4  * Container for PointParamKnotHolder visual handles\r
5  *\r
6  * Authors:\r
7  *   Johan Engelen <goejendaagh@zonnet.nl>\r
8  *\r
9  * Copyright (C) 2008 authors\r
10  *\r
11  * Released under GNU GPL, read the file 'COPYING' for more information\r
12  */\r
13 \r
14 #include "live_effects/parameter/pointparam-knotholder.h"\r
15 #include "live_effects/lpeobject.h"\r
16 #include "document.h"\r
17 #include "sp-shape.h"\r
18 #include "knot.h"\r
19 #include "knotholder.h"\r
20 #include "knot-holder-entity.h"\r
21 \r
22 #include <libnr/nr-matrix-div.h>\r
23 #include <glibmm/i18n.h>\r
24 #include <2geom/point.h>\r
25 #include <2geom/matrix.h>\r
26 #include "svg/stringstream.h"\r
27 #include "xml/repr.h"\r
28 \r
29 class SPDesktop;\r
30 \r
31 namespace Inkscape {\r
32 \r
33 static void pointparam_knot_clicked_handler (SPKnot *knot, guint state, PointParamKnotHolder *kh);\r
34 static void pointparam_knot_moved_handler(SPKnot *knot, NR::Point const *p, guint state, PointParamKnotHolder *kh);\r
35 static void pointparam_knot_ungrabbed_handler (SPKnot *knot, unsigned int state, PointParamKnotHolder *kh);\r
36 static void pointparam_knot_holder_class_init(PointParamKnotHolderClass *klass);\r
37 \r
38 void pointparam_knot_holder_dispose(GObject *object);\r
39 \r
40 static SPKnotHolderClass *parent_class;\r
41 \r
42 /**\r
43  * Registers PointParamKnotHolder class and returns its type number.\r
44  */\r
45 GType pointparam_knot_holder_get_type()\r
46 {\r
47     static GType type = 0;\r
48     if (!type) {\r
49         GTypeInfo info = {\r
50             sizeof(PointParamKnotHolderClass),\r
51             NULL,       /* base_init */\r
52             NULL,       /* base_finalize */\r
53             (GClassInitFunc) pointparam_knot_holder_class_init,\r
54             NULL,       /* class_finalize */\r
55             NULL,       /* class_data */\r
56             sizeof (PointParamKnotHolder),\r
57             16, /* n_preallocs */\r
58             NULL,\r
59             NULL\r
60         };\r
61         type = g_type_register_static (G_TYPE_OBJECT, "InkscapePointParamKnotHolder", &info, (GTypeFlags) 0);\r
62     }\r
63     return type;\r
64 }\r
65 \r
66 /**\r
67  * PointParamKnotHolder vtable initialization.\r
68  */\r
69 static void pointparam_knot_holder_class_init(PointParamKnotHolderClass *klass)\r
70 {\r
71     GObjectClass *gobject_class;\r
72     gobject_class = (GObjectClass *) klass;\r
73 \r
74     parent_class = (SPKnotHolderClass*) g_type_class_peek_parent(klass);\r
75     gobject_class->dispose = pointparam_knot_holder_dispose;\r
76 }\r
77 \r
78 PointParamKnotHolder *pointparam_knot_holder_new(SPDesktop *desktop, SPObject *lpeobject, const gchar * key, SPItem *item)\r
79 {\r
80     g_return_val_if_fail(desktop != NULL, NULL);\r
81     g_return_val_if_fail(item != NULL, NULL);\r
82     g_return_val_if_fail(SP_IS_ITEM(item), NULL);\r
83 \r
84     PointParamKnotHolder *knot_holder = (PointParamKnotHolder*)g_object_new (INKSCAPE_TYPE_POINTPARAM_KNOT_HOLDER, 0);\r
85     knot_holder->desktop = desktop;\r
86     knot_holder->item = item;\r
87     knot_holder->lpeobject = LIVEPATHEFFECT(lpeobject);\r
88     g_object_ref(G_OBJECT(item));\r
89     g_object_ref(G_OBJECT(lpeobject));\r
90     knot_holder->entity = NULL;\r
91 \r
92     knot_holder->released = NULL;\r
93 \r
94     knot_holder->repr = lpeobject->repr;\r
95     knot_holder->repr_key = key;\r
96 \r
97     knot_holder->local_change = FALSE;\r
98 \r
99     return knot_holder;\r
100 }\r
101 \r
102 void pointparam_knot_holder_dispose(GObject *object) {\r
103     PointParamKnotHolder *kh = G_TYPE_CHECK_INSTANCE_CAST((object), INKSCAPE_TYPE_POINTPARAM_KNOT_HOLDER, PointParamKnotHolder);\r
104 \r
105     g_object_unref(G_OBJECT(kh->item));\r
106     g_object_unref(G_OBJECT(kh->lpeobject));\r
107     while (kh->entity) {\r
108         SPKnotHolderEntity *e = (SPKnotHolderEntity *) kh->entity->data;\r
109         g_signal_handler_disconnect(e->knot, e->_click_handler_id);\r
110         g_signal_handler_disconnect(e->knot, e->_ungrab_handler_id);\r
111         /* unref should call destroy */\r
112         g_object_unref(e->knot);\r
113         g_free(e);\r
114         kh->entity = g_slist_remove(kh->entity, e);\r
115     }\r
116 }\r
117 \r
118 void\r
119 PointParamKnotHolder::add_knot (\r
120     Geom::Point         & p,\r
121     PointParamKnotHolderClickedFunc knot_click,\r
122     SPKnotShapeType     shape,\r
123     SPKnotModeType      mode,\r
124     guint32             color,\r
125     const gchar *tip )\r
126 {\r
127     /* create new SPKnotHolderEntry */\r
128     SPKnotHolderEntity *e = g_new(SPKnotHolderEntity, 1);\r
129     e->knot = sp_knot_new(desktop, tip);\r
130     e->knot_set = NULL;\r
131     e->knot_get = NULL;\r
132     if (knot_click) {\r
133         e->knot_click = knot_click;\r
134     } else {\r
135         e->knot_click = NULL;\r
136     }\r
137 \r
138     g_object_set(G_OBJECT (e->knot->item), "shape", shape, NULL);\r
139     g_object_set(G_OBJECT (e->knot->item), "mode", mode, NULL);\r
140 \r
141     e->knot->fill [SP_KNOT_STATE_NORMAL] = color;\r
142     g_object_set (G_OBJECT (e->knot->item), "fill_color", color, NULL);\r
143 \r
144     entity = g_slist_append(entity, e);\r
145 \r
146     /* Move to current point. */\r
147     NR::Point dp = p * sp_item_i2d_affine(item);\r
148     sp_knot_set_position(e->knot, &dp, SP_KNOT_STATE_NORMAL);\r
149 \r
150     e->handler_id = g_signal_connect(e->knot, "moved", G_CALLBACK(pointparam_knot_moved_handler), this);\r
151     e->_click_handler_id = g_signal_connect(e->knot, "clicked", G_CALLBACK(pointparam_knot_clicked_handler), this);\r
152     e->_ungrab_handler_id = g_signal_connect(e->knot, "ungrabbed", G_CALLBACK(pointparam_knot_ungrabbed_handler), this);\r
153 \r
154     sp_knot_show(e->knot);\r
155 }\r
156 \r
157 static void pointparam_knot_clicked_handler(SPKnot */*knot*/, guint /*state*/, PointParamKnotHolder */*kh*/)\r
158 {\r
159 \r
160 }\r
161 \r
162 /**\r
163  * \param p In desktop coordinates.\r
164  *  This function does not write to XML, but tries to write directly to the PointParam to quickly live update the effect\r
165  */\r
166 static void pointparam_knot_moved_handler(SPKnot */*knot*/, NR::Point const *p, guint /*state*/, PointParamKnotHolder *kh)\r
167 {\r
168     NR::Matrix const i2d(sp_item_i2d_affine(kh->item));\r
169     NR::Point pos = (*p) / i2d;\r
170 \r
171     Inkscape::SVGOStringStream os;\r
172     os << pos.to_2geom();\r
173 \r
174     kh->lpeobject->lpe->setParameter(kh->repr_key, os.str().c_str());\r
175 }\r
176 \r
177 static void pointparam_knot_ungrabbed_handler(SPKnot *knot, unsigned int /*state*/, PointParamKnotHolder *kh)\r
178 {\r
179     NR::Matrix const i2d(sp_item_i2d_affine(kh->item));\r
180     NR::Point pos = sp_knot_position(knot) / i2d;\r
181 \r
182     Inkscape::SVGOStringStream os;\r
183     os << pos.to_2geom();\r
184 \r
185     kh->repr->setAttribute(kh->repr_key , os.str().c_str());\r
186 \r
187     sp_document_done(SP_OBJECT_DOCUMENT (kh->lpeobject), SP_VERB_CONTEXT_LPE, _("Change LPE point parameter"));\r
188 }\r
189 \r
190 } // namespace Inkscape\r
191 \r
192 /*\r
193   Local Variables:\r
194   mode:c++\r
195   c-file-style:"stroustrup"\r
196   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
197   indent-tabs-mode:nil\r
198   fill-column:99\r
199   End:\r
200 */\r
201 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r