Code

string fixes from bug 1516157
[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, _(this->get_name()));
233     return;
236 void
237 Effect::set_last_effect (Effect * in_effect)
239     if (in_effect == NULL) {
240         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, false);
241         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, false);
242     } else if (_last_effect == NULL) {
243         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, true);
244         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, true);
245     }
247     _last_effect = in_effect;
248     return;
251 #define  EFFECTS_LIST  "effects-list"
253 bool
254 Effect::find_effects_list (Inkscape::XML::Node * menustruct)
256     if (menustruct == NULL) return false;
257     for (Inkscape::XML::Node * child = menustruct;
258             child != NULL;
259             child = child->next()) {
260         if (!strcmp(child->name(), EFFECTS_LIST)) {
261             _effects_list = child;
262             return true;
263         }
264         Inkscape::XML::Node * firstchild = child->firstChild();
265         if (firstchild != NULL)
266             if (find_effects_list(firstchild))
267                 return true;
268     }
269     return false;
272 Gtk::VBox *
273 Effect::get_info_widget(void)
275     return Extension::get_info_widget();
278 /** \brief  Create an action for a \c EffectVerb
279     \param  view  Which view the action should be created for
280     \return The built action.
282     Calls \c make_action_helper with the \c vector.
283 */
284 SPAction *
285 Effect::EffectVerb::make_action (Inkscape::UI::View::View * view)
287     return make_action_helper(view, &vector, static_cast<void *>(_effect));
290 /** \brief  Decode the verb code and take appropriate action */
291 void
292 Effect::EffectVerb::perform (SPAction *action, void * data, void *pdata)
294     Inkscape::UI::View::View * current_view = sp_action_get_view(action);
295 //  SPDocument * current_document = current_view->doc;
296     Effect * effect = reinterpret_cast<Effect *>(data);
298     if (effect == NULL) return;
299     if (current_view == NULL) return;
301     // std::cout << "Executing: " << effect->get_name() << std::endl;
302     if (effect->prefs(current_view))
303         effect->effect(current_view);
305     return;
308 /**
309  * Action vector to define functions called if a staticly defined file verb
310  * is called.
311  */
312 SPActionEventVector Effect::EffectVerb::vector =
313             {{NULL}, Effect::EffectVerb::perform, NULL, NULL, NULL, NULL};
316 } }  /* namespace Inkscape, Extension */
318 /*
319   Local Variables:
320   mode:c++
321   c-file-style:"stroustrup"
322   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
323   indent-tabs-mode:nil
324   fill-column:99
325   End:
326 */
327 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :