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 if (action->view) {
135 SPDocument *document = action->view->doc();
136 if (document) {
137 _addProperty(share_static_string("document"), document->serial());
138 }
139 }
140 _addProperty(share_static_string("verb"), action->id);
141 }
142 };
144 }
146 /**
147 \return None
148 \brief Executes an action
149 \param action The action to be executed
150 \param data Data that is passed into the action. This depends
151 on the situation that the action is used in.
153 This function implements the 'action' in SPActions. It first validates
154 its parameters, making sure it got an action passed in. Then it
155 turns that action into its parent class of NRActiveObject. The
156 NRActiveObject allows for listeners to be attached to it. This
157 function goes through those listeners and calls them with the
158 vector that was attached to the listener.
159 */
160 void
161 sp_action_perform (SPAction *action, void * data)
162 {
163 NRActiveObject *aobject;
165 nr_return_if_fail (action != NULL);
166 nr_return_if_fail (SP_IS_ACTION (action));
168 Inkscape::Debug::EventTracker<ActionEvent> tracker(action);
170 aobject = NR_ACTIVE_OBJECT(action);
171 if (aobject->callbacks) {
172 unsigned int i;
173 for (i = 0; i < aobject->callbacks->length; i++) {
174 NRObjectListener *listener;
175 SPActionEventVector *avector;
177 listener = &aobject->callbacks->listeners[i];
178 avector = (SPActionEventVector *) listener->vector;
180 if ((listener->size >= sizeof (SPActionEventVector)) && avector != NULL && avector->perform != NULL) {
181 avector->perform (action, listener->data, data);
182 }
183 }
184 }
185 }
187 /**
188 * Change activation in all actions that can be taken with the action.
189 */
190 void
191 sp_action_set_active (SPAction *action, unsigned int active)
192 {
193 nr_return_if_fail (action != NULL);
194 nr_return_if_fail (SP_IS_ACTION (action));
196 if (active != action->active) {
197 NRActiveObject *aobject;
198 action->active = active;
199 aobject = (NRActiveObject *) action;
200 if (aobject->callbacks) {
201 unsigned int i;
202 for (i = 0; i < aobject->callbacks->length; i++) {
203 NRObjectListener *listener;
204 SPActionEventVector *avector;
205 listener = aobject->callbacks->listeners + i;
206 avector = (SPActionEventVector *) listener->vector;
207 if ((listener->size >= sizeof (SPActionEventVector)) && avector->set_active) {
208 avector->set_active (action, active, listener->data);
209 }
210 }
211 }
212 }
213 }
215 /**
216 * Change sensitivity in all actions that can be taken with the action.
217 */
218 void
219 sp_action_set_sensitive (SPAction *action, unsigned int sensitive)
220 {
221 nr_return_if_fail (action != NULL);
222 nr_return_if_fail (SP_IS_ACTION (action));
224 if (sensitive != action->sensitive) {
225 NRActiveObject *aobject;
226 action->sensitive = sensitive;
227 aobject = (NRActiveObject *) action;
228 if (aobject->callbacks) {
229 unsigned int i;
230 for (i = 0; i < aobject->callbacks->length; i++) {
231 NRObjectListener *listener;
232 SPActionEventVector *avector;
233 listener = aobject->callbacks->listeners + i;
234 avector = (SPActionEventVector *) listener->vector;
235 if ((listener->size >= sizeof (SPActionEventVector)) && avector->set_sensitive) {
236 avector->set_sensitive (action, sensitive, listener->data);
237 }
238 }
239 }
240 }
241 }
244 /**
245 * Change name for all actions that can be taken with the action.
246 */
247 void
248 sp_action_set_name (SPAction *action, Glib::ustring name)
249 {
250 nr_return_if_fail (action != NULL);
251 nr_return_if_fail (SP_IS_ACTION (action));
253 NRActiveObject *aobject;
254 g_free(action->name);
255 action->name = g_strdup(name.c_str());
256 aobject = (NRActiveObject *) action;
257 if (aobject->callbacks) {
258 unsigned int i;
259 for (i = 0; i < aobject->callbacks->length; i++) {
260 NRObjectListener *listener;
261 SPActionEventVector *avector;
262 listener = aobject->callbacks->listeners + i;
263 avector = (SPActionEventVector *) listener->vector;
264 if ((listener->size >= sizeof (SPActionEventVector)) && avector->set_name) {
265 avector->set_name (action, name, listener->data);
266 }
267 }
268 }
269 }
274 /**
275 * Return View associated with the action.
276 */
277 Inkscape::UI::View::View *
278 sp_action_get_view (SPAction *action)
279 {
280 g_return_val_if_fail (SP_IS_ACTION (action), NULL);
281 return action->view;
282 }
284 /*
285 Local Variables:
286 mode:c++
287 c-file-style:"stroustrup"
288 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
289 indent-tabs-mode:nil
290 fill-column:99
291 End:
292 */
293 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :