Code

revert interface change
[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     if (repr != NULL) {
36         Inkscape::XML::Node * child_repr;
38         for (child_repr = sp_repr_children(repr); child_repr != NULL; child_repr = child_repr->next()) {
39             if (!strcmp(child_repr->name(), "effect")) {
40                 for (child_repr = sp_repr_children(child_repr); child_repr != NULL; child_repr = child_repr->next()) {
41                     if (!strcmp(child_repr->name(), "effects-menu")) {
42                         // printf("Found local effects menu in %s\n", this->get_name());
43                         local_effects_menu = sp_repr_children(child_repr);
44                     }
45                     if (!strcmp(child_repr->name(), "menu-name") ||
46                             !strcmp(child_repr->name(), "_menu-name")) {
47                         // printf("Found local effects menu in %s\n", this->get_name());
48                         _verb.set_name(sp_repr_children(child_repr)->content());
49                     }
50                     if (!strcmp(child_repr->name(), "menu-tip") ||
51                             !strcmp(child_repr->name(), "_menu-tip")) {
52                         // printf("Found local effects menu in %s\n", this->get_name());
53                         _verb.set_tip(sp_repr_children(child_repr)->content());
54                     }
55                 } // children of "effect"
56                 break; // there can only be one effect
57             } // find "effect"
58         } // children of "inkscape-extension"
59     } // if we have an XML file
61     if (_effects_list == NULL)
62         find_effects_list(inkscape_get_menus(INKSCAPE));
64     if (_effects_list != NULL) {
65         _menu_node = sp_repr_new("verb");
66         _menu_node->setAttribute("verb-id", this->get_id(), false);
68         merge_menu(_effects_list->parent(), _effects_list, local_effects_menu, _menu_node);
69     }
71     return;
72 }
74 void
75 Effect::merge_menu (Inkscape::XML::Node * base,
76                     Inkscape::XML::Node * start,
77                     Inkscape::XML::Node * patern,
78                     Inkscape::XML::Node * mergee) {
79     Glib::ustring mergename;
80     Inkscape::XML::Node * tomerge = NULL;
81     Inkscape::XML::Node * submenu = NULL;
83     /* printf("Merge menu with '%s' '%s' '%s'\n",
84             base != NULL ? base->name() : "NULL",
85             patern != NULL ? patern->name() : "NULL",
86             mergee != NULL ? mergee->name() : "NULL"); */
88     if (patern == NULL) {
89         // Merge the verb name
90         tomerge = mergee;
91         mergename = _(this->get_name());
92     } else {
93         gchar const * menuname = patern->attribute("name");
94         if (menuname == NULL) menuname = patern->attribute("_name");
95         if (menuname == NULL) return;
97         tomerge = sp_repr_new("submenu");
98         tomerge->setAttribute("name", menuname, false);
100         mergename = _(menuname);
101     }
103     int position = -1;
105     if (start != NULL) {
106         Inkscape::XML::Node * menupass;
107         for (menupass = start->next(); menupass != NULL; menupass = menupass->next()) {
108             gchar const * compare_char = NULL;
109             if (!strcmp(menupass->name(), "verb")) {
110                 gchar const * verbid = menupass->attribute("verb-id");
111                 Inkscape::Verb * verb = Inkscape::Verb::getbyid(verbid);
112                 if (verb == NULL) {
113                     continue;
114                 }
115                 compare_char = verb->get_name();
116             } else if (!strcmp(menupass->name(), "submenu")) {
117                 compare_char = menupass->attribute("name");
118                 if (compare_char == NULL)
119                     compare_char = menupass->attribute("_name");
120             }
122             /* This will cause us to skip tags we don't understand */
123             if (compare_char == NULL) {
124                 continue;
125             }
127             Glib::ustring compare(_(compare_char));
129             if (mergename == compare) {
130                 Inkscape::GC::release(tomerge);
131                 tomerge = NULL;
132                 submenu = menupass;
133                 break;
134             }
136             if (mergename < compare) {
137                 position = menupass->position();
138                 break;
139             }
140         } // for menu items
141     } // start != NULL
143     if (tomerge != NULL) {
144         base->appendChild(tomerge);
145         Inkscape::GC::release(tomerge);
146         if (position != -1)
147             tomerge->setPosition(position);
148     }
150     if (patern != NULL) {
151         if (submenu == NULL)
152             submenu = tomerge;
153         merge_menu(submenu, submenu->firstChild(), patern->firstChild(), mergee);
154     }
156     return;
159 Effect::~Effect (void)
161     if (get_last_effect() == this)
162         set_last_effect(NULL);
163     return;
166 bool
167 Effect::check (void)
169     if (!Extension::check()) {
170         /** \todo  Check to see if parent has this as its only child,
171                    if so, delete it too */
172         if (_menu_node != NULL)
173             sp_repr_unparent(_menu_node);
174         _menu_node = NULL;
175         return false;
176     }
177     return true;
180 bool
181 Effect::prefs (Inkscape::UI::View::View * doc)
183     if (!loaded())
184         set_state(Extension::STATE_LOADED);
185     if (!loaded()) return false;
187     Gtk::Widget * controls;
188     controls = imp->prefs_effect(this, doc);
189     if (controls == NULL) {
190         // std::cout << "No preferences for Effect" << std::endl;
191         return true;
192     }
194     PrefDialog * dialog = new PrefDialog(this->get_name(), this->get_help(), controls);
195     int response = dialog->run();
196     dialog->hide();
198     delete dialog;
200     if (response == Gtk::RESPONSE_OK) return true;
202     return false;
205 /**
206     \brief  The function that 'does' the effect itself
207     \param  doc  The Inkscape::UI::View::View to do the effect on
209     This function first insures that the extension is loaded, and if not,
210     loads it.  It then calls the implemention to do the actual work.  It
211     also resets the last effect pointer to be this effect.  Finally, it
212     executes a \c sp_document_done to commit the changes to the undo
213     stack.
214 */
215 void
216 Effect::effect (Inkscape::UI::View::View * doc)
218     if (!loaded())
219         set_state(Extension::STATE_LOADED);
220     if (!loaded()) return;
222     set_last_effect(this);
223     imp->effect(this, doc);
225     sp_document_done(doc->doc());
227     return;
230 void
231 Effect::set_last_effect (Effect * in_effect)
233     if (in_effect == NULL) {
234         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, false);
235         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, false);
236     } else if (_last_effect == NULL) {
237         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, true);
238         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, true);
239     }
241     _last_effect = in_effect;
242     return;
245 #define  EFFECTS_LIST  "effects-list"
247 bool
248 Effect::find_effects_list (Inkscape::XML::Node * menustruct)
250     if (menustruct == NULL) return false;
251     for (Inkscape::XML::Node * child = menustruct;
252             child != NULL;
253             child = child->next()) {
254         if (!strcmp(child->name(), EFFECTS_LIST)) {
255             _effects_list = child;
256             return true;
257         }
258         Inkscape::XML::Node * firstchild = child->firstChild();
259         if (firstchild != NULL)
260             if (find_effects_list(firstchild))
261                 return true;
262     }
263     return false;
266 Gtk::VBox *
267 Effect::get_info_widget(void)
269     return Extension::get_info_widget();
272 /** \brief  Create an action for a \c EffectVerb
273     \param  view  Which view the action should be created for
274     \return The built action.
276     Calls \c make_action_helper with the \c vector.
277 */
278 SPAction *
279 Effect::EffectVerb::make_action (Inkscape::UI::View::View * view)
281     return make_action_helper(view, &vector, static_cast<void *>(_effect));
284 /** \brief  Decode the verb code and take appropriate action */
285 void
286 Effect::EffectVerb::perform (SPAction *action, void * data, void *pdata)
288     Inkscape::UI::View::View * current_view = sp_action_get_view(action);
289 //  SPDocument * current_document = current_view->doc;
290     Effect * effect = reinterpret_cast<Effect *>(data);
292     if (effect == NULL) return;
293     if (current_view == NULL) return;
295     // std::cout << "Executing: " << effect->get_name() << std::endl;
296     if (effect->prefs(current_view))
297         effect->effect(current_view);
299     return;
302 /**
303  * Action vector to define functions called if a staticly defined file verb
304  * is called.
305  */
306 SPActionEventVector Effect::EffectVerb::vector =
307             {{NULL},Effect::EffectVerb::perform, NULL, NULL, NULL};
310 } }  /* namespace Inkscape, Extension */
312 /*
313   Local Variables:
314   mode:c++
315   c-file-style:"stroustrup"
316   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
317   indent-tabs-mode:nil
318   fill-column:99
319   End:
320 */
321 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :