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 static void pointparam_knot_clicked_handler (SPKnot *knot, guint state, gpointer data);\r
32 static void pointparam_knot_moved_handler(SPKnot *knot, NR::Point const *p, guint state, gpointer data);\r
33 static void pointparam_knot_ungrabbed_handler (SPKnot *knot, unsigned int state, PointParamKnotHolder *kh);\r
34 static void pointparam_knot_holder_class_init(PointParamKnotHolderClass *klass);\r
35 \r
36 void pointparam_knot_holder_dispose(GObject *object);\r
37 \r
38 static SPKnotHolderClass *parent_class;\r
39 \r
40 /**\r
41 * Registers SPKnotHolder class and returns its type number.\r
42 */\r
43 GType pointparam_knot_holder_get_type()\r
44 {\r
45 static GType type = 0;\r
46 if (!type) {\r
47 GTypeInfo info = {\r
48 sizeof(PointParamKnotHolderClass),\r
49 NULL, /* base_init */\r
50 NULL, /* base_finalize */\r
51 (GClassInitFunc) pointparam_knot_holder_class_init,\r
52 NULL, /* class_finalize */\r
53 NULL, /* class_data */\r
54 sizeof (PointParamKnotHolder),\r
55 16, /* n_preallocs */\r
56 NULL,\r
57 NULL\r
58 };\r
59 type = g_type_register_static (G_TYPE_OBJECT, "InkscapePointParamKnotHolder", &info, (GTypeFlags) 0);\r
60 }\r
61 return type;\r
62 }\r
63 \r
64 /**\r
65 * PointParamKnotHolder vtable initialization.\r
66 */\r
67 static void pointparam_knot_holder_class_init(PointParamKnotHolderClass *klass)\r
68 {\r
69 GObjectClass *gobject_class;\r
70 gobject_class = (GObjectClass *) klass;\r
71 \r
72 parent_class = (SPKnotHolderClass*) g_type_class_peek_parent(klass);\r
73 gobject_class->dispose = pointparam_knot_holder_dispose;\r
74 }\r
75 \r
76 PointParamKnotHolder *pointparam_knot_holder_new(SPDesktop *desktop, SPObject *lpeobject, const gchar * key, SPItem *item)\r
77 {\r
78 g_return_val_if_fail(desktop != NULL, NULL);\r
79 g_return_val_if_fail(item != NULL, NULL);\r
80 g_return_val_if_fail(SP_IS_ITEM(item), NULL);\r
81 \r
82 PointParamKnotHolder *knot_holder = (PointParamKnotHolder*)g_object_new (INKSCAPE_TYPE_POINTPARAM_KNOT_HOLDER, 0);\r
83 knot_holder->desktop = desktop;\r
84 knot_holder->item = item;\r
85 knot_holder->lpeobject = LIVEPATHEFFECT(lpeobject);\r
86 g_object_ref(G_OBJECT(item));\r
87 g_object_ref(G_OBJECT(lpeobject));\r
88 knot_holder->entity = NULL;\r
89 \r
90 knot_holder->released = NULL;\r
91 \r
92 knot_holder->repr = lpeobject->repr;\r
93 knot_holder->repr_key = key;\r
94 \r
95 knot_holder->local_change = FALSE;\r
96 \r
97 return knot_holder;\r
98 }\r
99 \r
100 void pointparam_knot_holder_dispose(GObject *object) {\r
101 PointParamKnotHolder *kh = G_TYPE_CHECK_INSTANCE_CAST((object), INKSCAPE_TYPE_POINTPARAM_KNOT_HOLDER, PointParamKnotHolder);\r
102 \r
103 g_object_unref(G_OBJECT(kh->item));\r
104 g_object_unref(G_OBJECT(kh->lpeobject));\r
105 while (kh->entity) {\r
106 SPKnotHolderEntity *e = (SPKnotHolderEntity *) kh->entity->data;\r
107 g_signal_handler_disconnect(e->knot, e->_click_handler_id);\r
108 g_signal_handler_disconnect(e->knot, e->_ungrab_handler_id);\r
109 /* unref should call destroy */\r
110 g_object_unref(e->knot);\r
111 g_free(e);\r
112 kh->entity = g_slist_remove(kh->entity, e);\r
113 }\r
114 }\r
115 \r
116 void pointparam_knot_holder_destroy(PointParamKnotHolder *kh) {\r
117 g_object_unref(kh);\r
118 }\r
119 \r
120 void pointparam_knot_holder_add_full(\r
121 PointParamKnotHolder *knot_holder,\r
122 Geom::Point & p,\r
123 void (* knot_click) (SPItem *item, guint state),\r
124 SPKnotShapeType shape,\r
125 SPKnotModeType mode,\r
126 guint32 color,\r
127 const gchar *tip )\r
128 {\r
129 g_return_if_fail(knot_holder != NULL);\r
130 \r
131 SPItem *item = SP_ITEM(knot_holder->item);\r
132 \r
133 /* create new SPKnotHolderEntry */\r
134 SPKnotHolderEntity *e = g_new(SPKnotHolderEntity, 1);\r
135 e->knot = sp_knot_new(knot_holder->desktop, tip);\r
136 e->knot_set = NULL;\r
137 e->knot_get = NULL;\r
138 if (knot_click) {\r
139 e->knot_click = knot_click;\r
140 } else {\r
141 e->knot_click = NULL;\r
142 }\r
143 \r
144 g_object_set(G_OBJECT (e->knot->item), "shape", shape, NULL);\r
145 g_object_set(G_OBJECT (e->knot->item), "mode", mode, NULL);\r
146 \r
147 e->knot->fill [SP_KNOT_STATE_NORMAL] = color;\r
148 g_object_set (G_OBJECT (e->knot->item), "fill_color", color, NULL);\r
149 \r
150 knot_holder->entity = g_slist_append(knot_holder->entity, e);\r
151 \r
152 /* Move to current point. */\r
153 NR::Point dp = p * sp_item_i2d_affine(item);\r
154 sp_knot_set_position(e->knot, &dp, SP_KNOT_STATE_NORMAL);\r
155 \r
156 e->handler_id = g_signal_connect(e->knot, "moved", G_CALLBACK(pointparam_knot_moved_handler), knot_holder);\r
157 e->_click_handler_id = g_signal_connect(e->knot, "clicked", G_CALLBACK(pointparam_knot_clicked_handler), knot_holder);\r
158 e->_ungrab_handler_id = g_signal_connect(e->knot, "ungrabbed", G_CALLBACK(pointparam_knot_ungrabbed_handler), knot_holder);\r
159 \r
160 sp_knot_show(e->knot);\r
161 }\r
162 \r
163 static void pointparam_knot_clicked_handler(SPKnot */*knot*/, guint /*state*/, gpointer data)\r
164 {\r
165 SPKnotHolder *knot_holder = (SPKnotHolder *) data;\r
166 }\r
167 \r
168 /**\r
169 * \param p In desktop coordinates.\r
170 */\r
171 static void pointparam_knot_moved_handler(SPKnot */*knot*/, NR::Point const */*p*/, guint /*state*/, gpointer data)\r
172 {\r
173 SPKnotHolder *knot_holder = (SPKnotHolder *) data;\r
174 }\r
175 \r
176 static void pointparam_knot_ungrabbed_handler(SPKnot *knot, unsigned int /*state*/, PointParamKnotHolder *kh)\r
177 {\r
178 NR::Matrix const i2d(sp_item_i2d_affine(kh->item));\r
179 NR::Point pos = sp_knot_position(knot) / i2d;\r
180 \r
181 Inkscape::SVGOStringStream os;\r
182 os << pos[0] << "," << pos[1];\r
183 \r
184 kh->repr->setAttribute(kh->repr_key , os.str().c_str());\r
185 \r
186 sp_document_done(SP_OBJECT_DOCUMENT (kh->lpeobject), SP_VERB_CONTEXT_LPE, _("Change LPE point parameter"));\r
187 }\r
188 \r
189 /*\r
190 Local Variables:\r
191 mode:c++\r
192 c-file-style:"stroustrup"\r
193 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
194 indent-tabs-mode:nil\r
195 fill-column:99\r
196 End:\r
197 */\r
198 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :\r