Code

Warning cleanup.
[inkscape.git] / src / extension / effect.cpp
1 /*
2  * Authors:
3  *   Ted Gould <ted@gould.cx>
4  *
5  * Copyright (C) 2002-2007 Authors
6  *
7  * Released under GNU GPL, read the file 'COPYING' for more information
8  */
10 #include "inkscape-private.h"
11 #include "helper/action.h"
12 #include "ui/view/view.h"
13 #include "desktop-handles.h"
14 #include "selection.h"
15 #include "sp-namedview.h"
16 #include "desktop.h"
17 #include "implementation/implementation.h"
18 #include "effect.h"
19 #include "execution-env.h"
20 #include "timer.h"
24 /* Inkscape::Extension::Effect */
26 namespace Inkscape {
27 namespace Extension {
29 Effect * Effect::_last_effect = NULL;
30 Inkscape::XML::Node * Effect::_effects_list = NULL;
32 Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation * in_imp)
33     : Extension(in_repr, in_imp),
34       _id_noprefs(Glib::ustring(get_id()) + ".noprefs"),
35       _name_noprefs(Glib::ustring(get_name()) + _(" (No preferences)")),
36       _verb(get_id(), get_name(), NULL, NULL, this, true),
37       _verb_nopref(_id_noprefs.c_str(), _name_noprefs.c_str(), NULL, NULL, this, false),
38       _menu_node(NULL), _workingDialog(true),
39       _prefDialog(NULL)
40 {
41     Inkscape::XML::Node * local_effects_menu = NULL;
43     // This is a weird hack
44     if (!strcmp(this->get_id(), "org.inkscape.filter.dropshadow"))
45         return;
47     bool hidden = false;
49     no_doc = false;
50     no_live_preview = false;
52     if (repr != NULL) {
54         for (Inkscape::XML::Node *child = sp_repr_children(repr); child != NULL; child = child->next()) {
55             if (!strcmp(child->name(), INKSCAPE_EXTENSION_NS "effect")) {
56                 if (child->attribute("needs-document") && !strcmp(child->attribute("needs-document"), "false")) {
57                   no_doc = true;
58                 }
59                 if (child->attribute("needs-live-preview") && !strcmp(child->attribute("needs-live-preview"), "false")) {
60                   no_live_preview = true;
61                 }
62                 for (Inkscape::XML::Node *effect_child = sp_repr_children(child); effect_child != NULL; effect_child = effect_child->next()) {
63                     if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "effects-menu")) {
64                         // printf("Found local effects menu in %s\n", this->get_name());
65                         local_effects_menu = sp_repr_children(effect_child);
66                         if (effect_child->attribute("hidden") && !strcmp(effect_child->attribute("hidden"), "true")) {
67                             hidden = true;
68                         }
69                     }
70                     if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "menu-name") ||
71                             !strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "_menu-name")) {
72                         // printf("Found local effects menu in %s\n", this->get_name());
73                         _verb.set_name(sp_repr_children(effect_child)->content());
74                     }
75                     if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "menu-tip") ||
76                             !strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "_menu-tip")) {
77                         // printf("Found local effects menu in %s\n", this->get_name());
78                         _verb.set_tip(sp_repr_children(effect_child)->content());
79                     }
80                 } // children of "effect"
81                 break; // there can only be one effect
82             } // find "effect"
83         } // children of "inkscape-extension"
84     } // if we have an XML file
86     if (_effects_list == NULL && INKSCAPE != NULL) {
87         find_effects_list(inkscape_get_menus(INKSCAPE));
88     }
90     if (_effects_list != NULL) {
91         Inkscape::XML::Document *xml_doc;
92         xml_doc = _effects_list->document();
93         _menu_node = xml_doc->createElement("verb");
94         _menu_node->setAttribute("verb-id", this->get_id(), false);
96         if (!hidden)
97             merge_menu(_effects_list->parent(), _effects_list, local_effects_menu, _menu_node);
98     }
100     return;
103 void
104 Effect::merge_menu (Inkscape::XML::Node * base,
105                     Inkscape::XML::Node * start,
106                     Inkscape::XML::Node * patern,
107                     Inkscape::XML::Node * mergee) {
108     Glib::ustring mergename;
109     Inkscape::XML::Node * tomerge = NULL;
110     Inkscape::XML::Node * submenu = NULL;
112     /* printf("Merge menu with '%s' '%s' '%s'\n",
113             base != NULL ? base->name() : "NULL",
114             patern != NULL ? patern->name() : "NULL",
115             mergee != NULL ? mergee->name() : "NULL"); */
117     if (patern == NULL) {
118         // Merge the verb name
119         tomerge = mergee;
120         mergename = _(this->get_name());
121     } else {
122         gchar const * menuname = patern->attribute("name");
123         if (menuname == NULL) menuname = patern->attribute("_name");
124         if (menuname == NULL) return;
125         
126         Inkscape::XML::Document *xml_doc;
127         xml_doc = base->document();
128         tomerge = xml_doc->createElement("submenu");
129         tomerge->setAttribute("name", menuname, false);
131         mergename = _(menuname);
132     }
134     int position = -1;
136     if (start != NULL) {
137         Inkscape::XML::Node * menupass;
138         for (menupass = start; menupass != NULL; menupass = menupass->next()) {
139             gchar const * compare_char = NULL;
140             if (!strcmp(menupass->name(), "verb")) {
141                 gchar const * verbid = menupass->attribute("verb-id");
142                 Inkscape::Verb * verb = Inkscape::Verb::getbyid(verbid);
143                 if (verb == NULL) {
144                                         g_warning("Unable to find verb '%s' which is referred to in the menus.", verbid);
145                     continue;
146                 }
147                 compare_char = verb->get_name();
148             } else if (!strcmp(menupass->name(), "submenu")) {
149                 compare_char = menupass->attribute("name");
150                 if (compare_char == NULL)
151                     compare_char = menupass->attribute("_name");
152             }
154             /* This will cause us to skip tags we don't understand */
155             if (compare_char == NULL) {
156                 continue;
157             }
159             Glib::ustring compare(_(compare_char));
161             if (mergename == compare) {
162                 Inkscape::GC::release(tomerge);
163                 tomerge = NULL;
164                 submenu = menupass;
165                 break;
166             }
168             if (mergename < compare) {
169                 position = menupass->position();
170                 break;
171             }
172         } // for menu items
173     } // start != NULL
175     if (tomerge != NULL) {
176         base->appendChild(tomerge);
177         Inkscape::GC::release(tomerge);
178         if (position != -1)
179             tomerge->setPosition(position);
180     }
182     if (patern != NULL) {
183         if (submenu == NULL)
184             submenu = tomerge;
185         merge_menu(submenu, submenu->firstChild(), patern->firstChild(), mergee);
186     }
188     return;
191 Effect::~Effect (void)
193     if (get_last_effect() == this)
194         set_last_effect(NULL);
195     if (_menu_node)
196         Inkscape::GC::release(_menu_node);
197     return;
200 bool
201 Effect::check (void)
203     if (!Extension::check()) {
204         /** \todo  Check to see if parent has this as its only child,
205                    if so, delete it too */
206         if (_menu_node != NULL)
207             sp_repr_unparent(_menu_node);
208         _menu_node = NULL;
209         return false;
210     }
211     return true;
214 bool
215 Effect::prefs (Inkscape::UI::View::View * doc)
217     if (_prefDialog != NULL) {
218         _prefDialog->raise();
219         return true;
220     }
222     if (param_visible_count() == 0) {
223         effect(doc);
224         return true;
225     }
227     if (!loaded())
228         set_state(Extension::STATE_LOADED);
229     if (!loaded()) return false;
231     _prefDialog = new PrefDialog(this->get_name(), this->get_help(), NULL, this);
232     _prefDialog->show();
234     return true;
237 /**
238     \brief  The function that 'does' the effect itself
239     \param  doc  The Inkscape::UI::View::View to do the effect on
241     This function first insures that the extension is loaded, and if not,
242     loads it.  It then calls the implemention to do the actual work.  It
243     also resets the last effect pointer to be this effect.  Finally, it
244     executes a \c sp_document_done to commit the changes to the undo
245     stack.
246 */
247 void
248 Effect::effect (Inkscape::UI::View::View * doc)
250     //printf("Execute effect\n");
251     if (!loaded())
252         set_state(Extension::STATE_LOADED);
253     if (!loaded()) return;
256     ExecutionEnv executionEnv(this, doc);
257     timer->lock();
258     executionEnv.run();
259     if (executionEnv.wait()) {
260         executionEnv.commit();
261     } else {
262         executionEnv.cancel();
263     }
264     timer->unlock();
266     return;
269 /** \brief  Sets which effect was called last
270     \param in_effect  The effect that has been called
271     
272     This function sets the static variable \c _last_effect and it
273     ensures that the last effect verb is sensitive.
275     If the \c in_effect variable is \c NULL then the last effect
276     verb is made insesitive.
277 */
278 void
279 Effect::set_last_effect (Effect * in_effect)
281     if (in_effect == NULL) {
282         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, false);
283         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, false);
284     } else if (_last_effect == NULL) {
285         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, true);
286         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, true);
287     }
289     _last_effect = in_effect;
290     return;
293 #define  EFFECTS_LIST  "effects-list"
295 bool
296 Effect::find_effects_list (Inkscape::XML::Node * menustruct)
298     if (menustruct == NULL) return false;
299     for (Inkscape::XML::Node * child = menustruct;
300             child != NULL;
301             child = child->next()) {
302         if (!strcmp(child->name(), EFFECTS_LIST)) {
303             _effects_list = child;
304             return true;
305         }
306         Inkscape::XML::Node * firstchild = child->firstChild();
307         if (firstchild != NULL)
308             if (find_effects_list(firstchild))
309                 return true;
310     }
311     return false;
314 Gtk::VBox *
315 Effect::get_info_widget(void)
317     return Extension::get_info_widget();
320 void
321 Effect::set_pref_dialog (PrefDialog * prefdialog)
323     _prefDialog = prefdialog;
324     return;
327 /** \brief  Create an action for a \c EffectVerb
328     \param  view  Which view the action should be created for
329     \return The built action.
331     Calls \c make_action_helper with the \c vector.
332 */
333 SPAction *
334 Effect::EffectVerb::make_action (Inkscape::UI::View::View * view)
336     return make_action_helper(view, &vector, static_cast<void *>(this));
339 /** \brief  Decode the verb code and take appropriate action */
340 void
341 Effect::EffectVerb::perform( SPAction *action, void * data, void */*pdata*/ )
343     Inkscape::UI::View::View * current_view = sp_action_get_view(action);
344 //  SPDocument * current_document = current_view->doc;
345     Effect::EffectVerb * ev = reinterpret_cast<Effect::EffectVerb *>(data);
346     Effect * effect = ev->_effect;
348     if (effect == NULL) return;
349     if (current_view == NULL) return;
351     if (ev->_showPrefs) {
352         effect->prefs(current_view);
353     } else {
354         effect->effect(current_view);
355     }
357     return;
360 /**
361  * Action vector to define functions called if a staticly defined file verb
362  * is called.
363  */
364 SPActionEventVector Effect::EffectVerb::vector =
365             {{NULL}, Effect::EffectVerb::perform, NULL, NULL, NULL, NULL};
368 } }  /* namespace Inkscape, Extension */
370 /*
371   Local Variables:
372   mode:c++
373   c-file-style:"stroustrup"
374   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
375   indent-tabs-mode:nil
376   fill-column:99
377   End:
378 */
379 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :