Code

168688f0ef75b2e46b3897d4522b6d6b7034bcd1
[inkscape.git] / src / extension / effect.cpp
1 /*
2  * Authors:
3  *   Ted Gould <ted@gould.cx>
4  *
5  * Copyright (C) 2002-2006 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 "document.h"
13 #include "prefdialog.h"
14 #include "implementation/implementation.h"
15 #include "effect.h"
16 #include "ui/view/view.h"
18 /* Inkscape::Extension::Effect */
20 namespace Inkscape {
21 namespace Extension {
23 Effect * Effect::_last_effect = NULL;
24 Inkscape::XML::Node * Effect::_effects_list = NULL;
26 Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation * in_imp)
27     : Extension(in_repr, in_imp), _verb(get_id(), get_name(), NULL, NULL, this), _menu_node(NULL)
28 {
29     Inkscape::XML::Node * local_effects_menu = NULL;
31     // This is a weird hack
32     if (!strcmp(this->get_id(), "org.inkscape.filter.dropshadow"))
33         return;
35     bool hidden = false;
37     if (repr != NULL) {
38         Inkscape::XML::Node * child_repr;
40         for (child_repr = sp_repr_children(repr); child_repr != NULL; child_repr = child_repr->next()) {
41             if (!strcmp(child_repr->name(), "effect")) {
42                 for (child_repr = sp_repr_children(child_repr); child_repr != NULL; child_repr = child_repr->next()) {
43                     if (!strcmp(child_repr->name(), "effects-menu")) {
44                         // printf("Found local effects menu in %s\n", this->get_name());
45                         local_effects_menu = sp_repr_children(child_repr);
46                         if (child_repr->attribute("hidden") && !strcmp(child_repr->attribute("hidden"), "yes")) {
47                             hidden = true;
48                         }
49                     }
50                     if (!strcmp(child_repr->name(), "menu-name") ||
51                             !strcmp(child_repr->name(), "_menu-name")) {
52                         // printf("Found local effects menu in %s\n", this->get_name());
53                         _verb.set_name(sp_repr_children(child_repr)->content());
54                     }
55                     if (!strcmp(child_repr->name(), "menu-tip") ||
56                             !strcmp(child_repr->name(), "_menu-tip")) {
57                         // printf("Found local effects menu in %s\n", this->get_name());
58                         _verb.set_tip(sp_repr_children(child_repr)->content());
59                     }
60                 } // children of "effect"
61                 break; // there can only be one effect
62             } // find "effect"
63         } // children of "inkscape-extension"
64     } // if we have an XML file
66     if (_effects_list == NULL)
67         find_effects_list(inkscape_get_menus(INKSCAPE));
69     if (_effects_list != NULL) {
70         _menu_node = sp_repr_new("verb");
71         _menu_node->setAttribute("verb-id", this->get_id(), false);
73         if (!hidden)
74             merge_menu(_effects_list->parent(), _effects_list, local_effects_menu, _menu_node);
75     }
77     return;
78 }
80 void
81 Effect::merge_menu (Inkscape::XML::Node * base,
82                     Inkscape::XML::Node * start,
83                     Inkscape::XML::Node * patern,
84                     Inkscape::XML::Node * mergee) {
85     Glib::ustring mergename;
86     Inkscape::XML::Node * tomerge = NULL;
87     Inkscape::XML::Node * submenu = NULL;
89     /* printf("Merge menu with '%s' '%s' '%s'\n",
90             base != NULL ? base->name() : "NULL",
91             patern != NULL ? patern->name() : "NULL",
92             mergee != NULL ? mergee->name() : "NULL"); */
94     if (patern == NULL) {
95         // Merge the verb name
96         tomerge = mergee;
97         mergename = _(this->get_name());
98     } else {
99         gchar const * menuname = patern->attribute("name");
100         if (menuname == NULL) menuname = patern->attribute("_name");
101         if (menuname == NULL) return;
103         tomerge = sp_repr_new("submenu");
104         tomerge->setAttribute("name", menuname, false);
106         mergename = _(menuname);
107     }
109     int position = -1;
111     if (start != NULL) {
112         Inkscape::XML::Node * menupass;
113         for (menupass = start->next(); menupass != NULL; menupass = menupass->next()) {
114             gchar const * compare_char = NULL;
115             if (!strcmp(menupass->name(), "verb")) {
116                 gchar const * verbid = menupass->attribute("verb-id");
117                 Inkscape::Verb * verb = Inkscape::Verb::getbyid(verbid);
118                 if (verb == NULL) {
119                     continue;
120                 }
121                 compare_char = verb->get_name();
122             } else if (!strcmp(menupass->name(), "submenu")) {
123                 compare_char = menupass->attribute("name");
124                 if (compare_char == NULL)
125                     compare_char = menupass->attribute("_name");
126             }
128             /* This will cause us to skip tags we don't understand */
129             if (compare_char == NULL) {
130                 continue;
131             }
133             Glib::ustring compare(_(compare_char));
135             if (mergename == compare) {
136                 Inkscape::GC::release(tomerge);
137                 tomerge = NULL;
138                 submenu = menupass;
139                 break;
140             }
142             if (mergename < compare) {
143                 position = menupass->position();
144                 break;
145             }
146         } // for menu items
147     } // start != NULL
149     if (tomerge != NULL) {
150         base->appendChild(tomerge);
151         Inkscape::GC::release(tomerge);
152         if (position != -1)
153             tomerge->setPosition(position);
154     }
156     if (patern != NULL) {
157         if (submenu == NULL)
158             submenu = tomerge;
159         merge_menu(submenu, submenu->firstChild(), patern->firstChild(), mergee);
160     }
162     return;
165 Effect::~Effect (void)
167     if (get_last_effect() == this)
168         set_last_effect(NULL);
169     return;
172 bool
173 Effect::check (void)
175     if (!Extension::check()) {
176         /** \todo  Check to see if parent has this as its only child,
177                    if so, delete it too */
178         if (_menu_node != NULL)
179             sp_repr_unparent(_menu_node);
180         _menu_node = NULL;
181         return false;
182     }
183     return true;
186 bool
187 Effect::prefs (Inkscape::UI::View::View * doc)
189     if (!loaded())
190         set_state(Extension::STATE_LOADED);
191     if (!loaded()) return false;
193     Gtk::Widget * controls;
194     controls = imp->prefs_effect(this, doc);
195     if (controls == NULL) {
196         // std::cout << "No preferences for Effect" << std::endl;
197         return true;
198     }
200     PrefDialog * dialog = new PrefDialog(this->get_name(), this->get_help(), controls);
201     int response = dialog->run();
202     dialog->hide();
204     delete dialog;
206     if (response == Gtk::RESPONSE_OK) return true;
208     return false;
211 /**
212     \brief  The function that 'does' the effect itself
213     \param  doc  The Inkscape::UI::View::View to do the effect on
215     This function first insures that the extension is loaded, and if not,
216     loads it.  It then calls the implemention to do the actual work.  It
217     also resets the last effect pointer to be this effect.  Finally, it
218     executes a \c sp_document_done to commit the changes to the undo
219     stack.
220 */
221 void
222 Effect::effect (Inkscape::UI::View::View * doc)
224     if (!loaded())
225         set_state(Extension::STATE_LOADED);
226     if (!loaded()) return;
228     set_last_effect(this);
229     imp->effect(this, doc);
231     sp_document_done(doc->doc(), SP_VERB_NONE, 
232                      /* TODO: annotate */ "effect.cpp:226");
234     return;
237 void
238 Effect::set_last_effect (Effect * in_effect)
240     if (in_effect == NULL) {
241         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, false);
242         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, false);
243     } else if (_last_effect == NULL) {
244         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, true);
245         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, true);
246     }
248     _last_effect = in_effect;
249     return;
252 #define  EFFECTS_LIST  "effects-list"
254 bool
255 Effect::find_effects_list (Inkscape::XML::Node * menustruct)
257     if (menustruct == NULL) return false;
258     for (Inkscape::XML::Node * child = menustruct;
259             child != NULL;
260             child = child->next()) {
261         if (!strcmp(child->name(), EFFECTS_LIST)) {
262             _effects_list = child;
263             return true;
264         }
265         Inkscape::XML::Node * firstchild = child->firstChild();
266         if (firstchild != NULL)
267             if (find_effects_list(firstchild))
268                 return true;
269     }
270     return false;
273 Gtk::VBox *
274 Effect::get_info_widget(void)
276     return Extension::get_info_widget();
279 /** \brief  Create an action for a \c EffectVerb
280     \param  view  Which view the action should be created for
281     \return The built action.
283     Calls \c make_action_helper with the \c vector.
284 */
285 SPAction *
286 Effect::EffectVerb::make_action (Inkscape::UI::View::View * view)
288     return make_action_helper(view, &vector, static_cast<void *>(_effect));
291 /** \brief  Decode the verb code and take appropriate action */
292 void
293 Effect::EffectVerb::perform (SPAction *action, void * data, void *pdata)
295     Inkscape::UI::View::View * current_view = sp_action_get_view(action);
296 //  SPDocument * current_document = current_view->doc;
297     Effect * effect = reinterpret_cast<Effect *>(data);
299     if (effect == NULL) return;
300     if (current_view == NULL) return;
302     // std::cout << "Executing: " << effect->get_name() << std::endl;
303     if (effect->prefs(current_view))
304         effect->effect(current_view);
306     return;
309 /**
310  * Action vector to define functions called if a staticly defined file verb
311  * is called.
312  */
313 SPActionEventVector Effect::EffectVerb::vector =
314             {{NULL}, Effect::EffectVerb::perform, NULL, NULL, NULL, NULL};
317 } }  /* namespace Inkscape, Extension */
319 /*
320   Local Variables:
321   mode:c++
322   c-file-style:"stroustrup"
323   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
324   indent-tabs-mode:nil
325   fill-column:99
326   End:
327 */
328 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :