Code

allow inx to suppress live preview checkbox
[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(), "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(), "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(), "menu-name") ||
71                             !strcmp(effect_child->name(), "_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(), "menu-tip") ||
76                             !strcmp(effect_child->name(), "_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->next(); 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                     continue;
145                 }
146                 compare_char = verb->get_name();
147             } else if (!strcmp(menupass->name(), "submenu")) {
148                 compare_char = menupass->attribute("name");
149                 if (compare_char == NULL)
150                     compare_char = menupass->attribute("_name");
151             }
153             /* This will cause us to skip tags we don't understand */
154             if (compare_char == NULL) {
155                 continue;
156             }
158             Glib::ustring compare(_(compare_char));
160             if (mergename == compare) {
161                 Inkscape::GC::release(tomerge);
162                 tomerge = NULL;
163                 submenu = menupass;
164                 break;
165             }
167             if (mergename < compare) {
168                 position = menupass->position();
169                 break;
170             }
171         } // for menu items
172     } // start != NULL
174     if (tomerge != NULL) {
175         base->appendChild(tomerge);
176         Inkscape::GC::release(tomerge);
177         if (position != -1)
178             tomerge->setPosition(position);
179     }
181     if (patern != NULL) {
182         if (submenu == NULL)
183             submenu = tomerge;
184         merge_menu(submenu, submenu->firstChild(), patern->firstChild(), mergee);
185     }
187     return;
190 Effect::~Effect (void)
192     if (get_last_effect() == this)
193         set_last_effect(NULL);
194     return;
197 bool
198 Effect::check (void)
200     if (!Extension::check()) {
201         /** \todo  Check to see if parent has this as its only child,
202                    if so, delete it too */
203         if (_menu_node != NULL)
204             sp_repr_unparent(_menu_node);
205         _menu_node = NULL;
206         return false;
207     }
208     return true;
211 bool
212 Effect::prefs (Inkscape::UI::View::View * doc)
214     if (_prefDialog != NULL) {
215         _prefDialog->raise();
216         return true;
217     }
219     if (param_visible_count() == 0) {
220         effect(doc);
221         return true;
222     }
224     if (!loaded())
225         set_state(Extension::STATE_LOADED);
226     if (!loaded()) return false;
228     _prefDialog = new PrefDialog(this->get_name(), this->get_help(), NULL, this);
229     _prefDialog->show();
231     return true;
234 /**
235     \brief  The function that 'does' the effect itself
236     \param  doc  The Inkscape::UI::View::View to do the effect on
238     This function first insures that the extension is loaded, and if not,
239     loads it.  It then calls the implemention to do the actual work.  It
240     also resets the last effect pointer to be this effect.  Finally, it
241     executes a \c sp_document_done to commit the changes to the undo
242     stack.
243 */
244 void
245 Effect::effect (Inkscape::UI::View::View * doc)
247     //printf("Execute effect\n");
248     if (!loaded())
249         set_state(Extension::STATE_LOADED);
250     if (!loaded()) return;
253     ExecutionEnv executionEnv(this, doc);
254     timer->lock();
255     executionEnv.run();
256     if (executionEnv.wait()) {
257         executionEnv.commit();
258     } else {
259         executionEnv.cancel();
260     }
261     timer->unlock();
263     return;
266 /** \brief  Sets which effect was called last
267     \param in_effect  The effect that has been called
268     
269     This function sets the static variable \c _last_effect and it
270     ensures that the last effect verb is sensitive.
272     If the \c in_effect variable is \c NULL then the last effect
273     verb is made insesitive.
274 */
275 void
276 Effect::set_last_effect (Effect * in_effect)
278     if (in_effect == NULL) {
279         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, false);
280         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, false);
281     } else if (_last_effect == NULL) {
282         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, true);
283         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, true);
284     }
286     _last_effect = in_effect;
287     return;
290 #define  EFFECTS_LIST  "effects-list"
292 bool
293 Effect::find_effects_list (Inkscape::XML::Node * menustruct)
295     if (menustruct == NULL) return false;
296     for (Inkscape::XML::Node * child = menustruct;
297             child != NULL;
298             child = child->next()) {
299         if (!strcmp(child->name(), EFFECTS_LIST)) {
300             _effects_list = child;
301             return true;
302         }
303         Inkscape::XML::Node * firstchild = child->firstChild();
304         if (firstchild != NULL)
305             if (find_effects_list(firstchild))
306                 return true;
307     }
308     return false;
311 Gtk::VBox *
312 Effect::get_info_widget(void)
314     return Extension::get_info_widget();
317 void
318 Effect::set_pref_dialog (PrefDialog * prefdialog)
320     _prefDialog = prefdialog;
321     return;
324 /** \brief  Create an action for a \c EffectVerb
325     \param  view  Which view the action should be created for
326     \return The built action.
328     Calls \c make_action_helper with the \c vector.
329 */
330 SPAction *
331 Effect::EffectVerb::make_action (Inkscape::UI::View::View * view)
333     return make_action_helper(view, &vector, static_cast<void *>(this));
336 /** \brief  Decode the verb code and take appropriate action */
337 void
338 Effect::EffectVerb::perform( SPAction *action, void * data, void */*pdata*/ )
340     Inkscape::UI::View::View * current_view = sp_action_get_view(action);
341 //  SPDocument * current_document = current_view->doc;
342     Effect::EffectVerb * ev = reinterpret_cast<Effect::EffectVerb *>(data);
343     Effect * effect = ev->_effect;
345     if (effect == NULL) return;
346     if (current_view == NULL) return;
348     if (ev->_showPrefs) {
349         effect->prefs(current_view);
350     } else {
351         effect->effect(current_view);
352     }
354     return;
357 /**
358  * Action vector to define functions called if a staticly defined file verb
359  * is called.
360  */
361 SPActionEventVector Effect::EffectVerb::vector =
362             {{NULL}, Effect::EffectVerb::perform, NULL, NULL, NULL, NULL};
365 } }  /* namespace Inkscape, Extension */
367 /*
368   Local Variables:
369   mode:c++
370   c-file-style:"stroustrup"
371   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
372   indent-tabs-mode:nil
373   fill-column:99
374   End:
375 */
376 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :