1 #define __SP_ACTION_C__
3 /** \file
4 * SPAction implementation
5 *
6 * Author:
7 * Lauris Kaplinski <lauris@kaplinski.com>
8 *
9 * Copyright (C) 2003 Lauris Kaplinski
10 *
11 * This code is in public domain
12 */
14 #include <string.h>
16 #include "debug/logger.h"
17 #include "debug/timestamp.h"
18 #include "debug/simple-event.h"
19 #include "debug/event-tracker.h"
20 #include "ui/view/view.h"
21 #include "document.h"
22 #include "helper/action.h"
24 static void sp_action_class_init (SPActionClass *klass);
25 static void sp_action_init (SPAction *action);
26 static void sp_action_finalize (NRObject *object);
28 static NRActiveObjectClass *parent_class;
30 /**
31 * Register SPAction class and return its type.
32 */
33 NRType
34 sp_action_get_type (void)
35 {
36 static unsigned int type = 0;
37 if (!type) {
38 type = nr_object_register_type (NR_TYPE_ACTIVE_OBJECT,
39 "SPAction",
40 sizeof (SPActionClass),
41 sizeof (SPAction),
42 (void (*) (NRObjectClass *)) sp_action_class_init,
43 (void (*) (NRObject *)) sp_action_init);
44 }
45 return type;
46 }
48 /**
49 * SPAction vtable initialization.
50 */
51 static void
52 sp_action_class_init (SPActionClass *klass)
53 {
54 NRObjectClass * object_class;
56 object_class = (NRObjectClass *) klass;
58 parent_class = (NRActiveObjectClass *) (((NRObjectClass *) klass)->parent);
60 object_class->finalize = sp_action_finalize;
61 object_class->cpp_ctor = NRObject::invoke_ctor<SPAction>;
62 }
64 /**
65 * Callback for SPAction object initialization.
66 */
67 static void
68 sp_action_init (SPAction *action)
69 {
70 action->sensitive = 0;
71 action->active = 0;
72 action->view = NULL;
73 action->id = action->name = action->tip = NULL;
74 action->image = NULL;
75 }
77 /**
78 * Called before SPAction object destruction.
79 */
80 static void
81 sp_action_finalize (NRObject *object)
82 {
83 SPAction *action;
85 action = (SPAction *) object;
87 if (action->image) free (action->image);
88 if (action->tip) free (action->tip);
89 if (action->name) free (action->name);
90 if (action->id) free (action->id);
92 ((NRObjectClass *) (parent_class))->finalize (object);
93 }
95 /**
96 * Create new SPAction object and set its properties.
97 */
98 SPAction *
99 sp_action_new(Inkscape::UI::View::View *view,
100 const gchar *id,
101 const gchar *name,
102 const gchar *tip,
103 const gchar *image,
104 Inkscape::Verb * verb)
105 {
106 SPAction *action = (SPAction *)nr_object_new(SP_TYPE_ACTION);
108 action->view = view;
109 action->sensitive = TRUE;
110 if (id) action->id = strdup (id);
111 if (name) action->name = strdup (name);
112 if (tip) action->tip = strdup (tip);
113 if (image) action->image = strdup (image);
114 action->verb = verb;
116 return action;
117 }
119 namespace {
121 using Inkscape::Debug::SimpleEvent;
122 using Inkscape::Debug::Event;
123 using Inkscape::Util::share_static_string;
124 using Inkscape::Debug::timestamp;
126 typedef SimpleEvent<Event::INTERACTION> ActionEventBase;
128 class ActionEvent : public ActionEventBase {
129 public:
130 ActionEvent(SPAction const *action)
131 : ActionEventBase(share_static_string("action"))
132 {
133 _addProperty(share_static_string("timestamp"), timestamp());
134 SPDocument *document = action->view->doc();
135 if (document) {
136 _addProperty(share_static_string("document"), document->serial());
137 }
138 _addProperty(share_static_string("verb"), action->id);
139 }
140 };
142 }
144 /**
145 \return None
146 \brief Executes an action
147 \param action The action to be executed
148 \param data Data that is passed into the action. This depends
149 on the situation that the action is used in.
151 This function implements the 'action' in SPActions. It first validates
152 its parameters, making sure it got an action passed in. Then it
153 turns that action into its parent class of NRActiveObject. The
154 NRActiveObject allows for listeners to be attached to it. This
155 function goes through those listeners and calls them with the
156 vector that was attached to the listener.
157 */
158 void
159 sp_action_perform (SPAction *action, void * data)
160 {
161 NRActiveObject *aobject;
163 nr_return_if_fail (action != NULL);
164 nr_return_if_fail (SP_IS_ACTION (action));
166 Inkscape::Debug::EventTracker<ActionEvent> tracker(action);
168 aobject = NR_ACTIVE_OBJECT(action);
169 if (aobject->callbacks) {
170 unsigned int i;
171 for (i = 0; i < aobject->callbacks->length; i++) {
172 NRObjectListener *listener;
173 SPActionEventVector *avector;
175 listener = &aobject->callbacks->listeners[i];
176 avector = (SPActionEventVector *) listener->vector;
178 if ((listener->size >= sizeof (SPActionEventVector)) && avector != NULL && avector->perform != NULL) {
179 avector->perform (action, listener->data, data);
180 }
181 }
182 }
183 }
185 /**
186 * Change activation in all actions that can be taken with the action.
187 */
188 void
189 sp_action_set_active (SPAction *action, unsigned int active)
190 {
191 nr_return_if_fail (action != NULL);
192 nr_return_if_fail (SP_IS_ACTION (action));
194 if (active != action->active) {
195 NRActiveObject *aobject;
196 action->active = active;
197 aobject = (NRActiveObject *) action;
198 if (aobject->callbacks) {
199 unsigned int i;
200 for (i = 0; i < aobject->callbacks->length; i++) {
201 NRObjectListener *listener;
202 SPActionEventVector *avector;
203 listener = aobject->callbacks->listeners + i;
204 avector = (SPActionEventVector *) listener->vector;
205 if ((listener->size >= sizeof (SPActionEventVector)) && avector->set_active) {
206 avector->set_active (action, active, listener->data);
207 }
208 }
209 }
210 }
211 }
213 /**
214 * Change sensitivity in all actions that can be taken with the action.
215 */
216 void
217 sp_action_set_sensitive (SPAction *action, unsigned int sensitive)
218 {
219 nr_return_if_fail (action != NULL);
220 nr_return_if_fail (SP_IS_ACTION (action));
222 if (sensitive != action->sensitive) {
223 NRActiveObject *aobject;
224 action->sensitive = sensitive;
225 aobject = (NRActiveObject *) action;
226 if (aobject->callbacks) {
227 unsigned int i;
228 for (i = 0; i < aobject->callbacks->length; i++) {
229 NRObjectListener *listener;
230 SPActionEventVector *avector;
231 listener = aobject->callbacks->listeners + i;
232 avector = (SPActionEventVector *) listener->vector;
233 if ((listener->size >= sizeof (SPActionEventVector)) && avector->set_sensitive) {
234 avector->set_sensitive (action, sensitive, listener->data);
235 }
236 }
237 }
238 }
239 }
242 /**
243 * Change name for all actions that can be taken with the action.
244 */
245 void
246 sp_action_set_name (SPAction *action, Glib::ustring name)
247 {
248 nr_return_if_fail (action != NULL);
249 nr_return_if_fail (SP_IS_ACTION (action));
251 NRActiveObject *aobject;
252 g_free(action->name);
253 action->name = g_strdup(name.c_str());
254 aobject = (NRActiveObject *) action;
255 if (aobject->callbacks) {
256 unsigned int i;
257 for (i = 0; i < aobject->callbacks->length; i++) {
258 NRObjectListener *listener;
259 SPActionEventVector *avector;
260 listener = aobject->callbacks->listeners + i;
261 avector = (SPActionEventVector *) listener->vector;
262 if ((listener->size >= sizeof (SPActionEventVector)) && avector->set_name) {
263 avector->set_name (action, name, listener->data);
264 }
265 }
266 }
267 }
272 /**
273 * Return View associated with the action.
274 */
275 Inkscape::UI::View::View *
276 sp_action_get_view (SPAction *action)
277 {
278 g_return_val_if_fail (SP_IS_ACTION (action), NULL);
279 return action->view;
280 }
282 /*
283 Local Variables:
284 mode:c++
285 c-file-style:"stroustrup"
286 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
287 indent-tabs-mode:nil
288 fill-column:99
289 End:
290 */
291 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :