Code

r10920@tres: ted | 2006-02-13 09:38:31 -0800
[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                         // printf("Found local effects menu in %s\n", this->get_name());
47                         _verb.set_name(sp_repr_children(child_repr)->content());
48                     }
49                     if (!strcmp(child_repr->name(), "menu-tip")) {
50                         // printf("Found local effects menu in %s\n", this->get_name());
51                         _verb.set_tip(sp_repr_children(child_repr)->content());
52                     }
53                 } // children of "effect"
54                 break; // there can only be one effect
55             } // find "effect"
56         } // children of "inkscape-extension"
57     } // if we have an XML file
59     if (_effects_list == NULL)
60         find_effects_list(inkscape_get_menus(INKSCAPE));
62     if (_effects_list != NULL) {
63         _menu_node = sp_repr_new("verb");
64         _menu_node->setAttribute("verb-id", this->get_id(), false);
66         merge_menu(_effects_list->parent(), _effects_list, local_effects_menu, _menu_node);
67     }
69     return;
70 }
72 void
73 Effect::merge_menu (Inkscape::XML::Node * base,
74                     Inkscape::XML::Node * start,
75                     Inkscape::XML::Node * patern,
76                     Inkscape::XML::Node * mergee) {
77     Glib::ustring mergename;
78     Inkscape::XML::Node * tomerge = NULL;
79     Inkscape::XML::Node * submenu = NULL;
81     /* printf("Merge menu with '%s' '%s' '%s'\n",
82             base != NULL ? base->name() : "NULL",
83             patern != NULL ? patern->name() : "NULL",
84             mergee != NULL ? mergee->name() : "NULL"); */
86     if (patern == NULL) {
87         // Merge the verb name
88         tomerge = mergee;
89         mergename = _(this->get_name());
90     } else {
91         gchar const * menuname = patern->attribute("name");
92         if (menuname == NULL) menuname = patern->attribute("_name");
93         if (menuname == NULL) return;
95         tomerge = sp_repr_new("submenu");
96         tomerge->setAttribute("name", menuname, false);
98         mergename = _(menuname);
99     }
101     int position = -1;
103     if (start != NULL) {
104         Inkscape::XML::Node * menupass;
105         for (menupass = start->next(); menupass != NULL; menupass = menupass->next()) {
106             gchar const * compare_char = NULL;
107             if (!strcmp(menupass->name(), "verb")) {
108                 gchar const * verbid = menupass->attribute("verb-id");
109                 Inkscape::Verb * verb = Inkscape::Verb::getbyid(verbid);
110                 if (verb == NULL) {
111                     continue;
112                 }
113                 compare_char = verb->get_name();
114             } else if (!strcmp(menupass->name(), "submenu")) {
115                 compare_char = menupass->attribute("name");
116                 if (compare_char == NULL)
117                     compare_char = menupass->attribute("_name");
118             }
120             /* This will cause us to skip tags we don't understand */
121             if (compare_char == NULL) {
122                 continue;
123             }
125             Glib::ustring compare(_(compare_char));
127             if (mergename == compare) {
128                 Inkscape::GC::release(tomerge);
129                 tomerge = NULL;
130                 submenu = menupass;
131                 break;
132             }
134             if (mergename < compare) {
135                 position = menupass->position();
136                 break;
137             }
138         } // for menu items
139     } // start != NULL
141     if (tomerge != NULL) {
142         base->appendChild(tomerge);
143         Inkscape::GC::release(tomerge);
144         if (position != -1)
145             tomerge->setPosition(position);
146     }
148     if (patern != NULL) {
149         if (submenu == NULL)
150             submenu = tomerge;
151         merge_menu(submenu, submenu->firstChild(), patern->firstChild(), mergee);
152     }
154     return;
157 Effect::~Effect (void)
159     if (get_last_effect() == this)
160         set_last_effect(NULL);
161     return;
164 bool
165 Effect::check (void)
167     if (!Extension::check()) {
168         /** \todo  Check to see if parent has this as its only child,
169                    if so, delete it too */
170         if (_menu_node != NULL)
171             sp_repr_unparent(_menu_node);
172         _menu_node = NULL;
173         return false;
174     }
175     return true;
178 bool
179 Effect::prefs (Inkscape::UI::View::View * doc)
181     if (!loaded())
182         set_state(Extension::STATE_LOADED);
183     if (!loaded()) return false;
185     Gtk::Widget * controls;
186     controls = imp->prefs_effect(this, doc);
187     if (controls == NULL) {
188         // std::cout << "No preferences for Effect" << std::endl;
189         return true;
190     }
192     PrefDialog * dialog = new PrefDialog(this->get_name(), controls);
193     int response = dialog->run();
194     dialog->hide();
196     delete dialog;
198     if (response == Gtk::RESPONSE_OK) return true;
200     return false;
203 /**
204     \brief  The function that 'does' the effect itself
205     \param  doc  The Inkscape::UI::View::View to do the effect on
207     This function first insures that the extension is loaded, and if not,
208     loads it.  It then calls the implemention to do the actual work.  It
209     also resets the last effect pointer to be this effect.  Finally, it
210     executes a \c sp_document_done to commit the changes to the undo
211     stack.
212 */
213 void
214 Effect::effect (Inkscape::UI::View::View * doc)
216     if (!loaded())
217         set_state(Extension::STATE_LOADED);
218     if (!loaded()) return;
220     set_last_effect(this);
221     imp->effect(this, doc);
223     sp_document_done(doc->doc());
225     return;
228 void
229 Effect::set_last_effect (Effect * in_effect)
231     if (in_effect == NULL) {
232         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, false);
233         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, false);
234     } else if (_last_effect == NULL) {
235         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, true);
236         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, true);
237     }
239     _last_effect = in_effect;
240     return;
243 #define  EFFECTS_LIST  "effects-list"
245 bool
246 Effect::find_effects_list (Inkscape::XML::Node * menustruct)
248     if (menustruct == NULL) return false;
249     for (Inkscape::XML::Node * child = menustruct;
250             child != NULL;
251             child = child->next()) {
252         if (!strcmp(child->name(), EFFECTS_LIST)) {
253             _effects_list = child;
254             return true;
255         }
256         Inkscape::XML::Node * firstchild = child->firstChild();
257         if (firstchild != NULL)
258             if (find_effects_list(firstchild))
259                 return true;
260     }
261     return false;
264 /** \brief  Create an action for a \c EffectVerb
265     \param  view  Which view the action should be created for
266     \return The built action.
268     Calls \c make_action_helper with the \c vector.
269 */
270 SPAction *
271 Effect::EffectVerb::make_action (Inkscape::UI::View::View * view)
273     return make_action_helper(view, &vector, static_cast<void *>(_effect));
276 /** \brief  Decode the verb code and take appropriate action */
277 void
278 Effect::EffectVerb::perform (SPAction *action, void * data, void *pdata)
280     Inkscape::UI::View::View * current_view = sp_action_get_view(action);
281 //  SPDocument * current_document = current_view->doc;
282     Effect * effect = reinterpret_cast<Effect *>(data);
284     if (effect == NULL) return;
285     if (current_view == NULL) return;
287     // std::cout << "Executing: " << effect->get_name() << std::endl;
288     if (effect->prefs(current_view))
289         effect->effect(current_view);
291     return;
294 /**
295  * Action vector to define functions called if a staticly defined file verb
296  * is called.
297  */
298 SPActionEventVector Effect::EffectVerb::vector =
299             {{NULL},Effect::EffectVerb::perform, NULL, NULL, NULL};
302 } }  /* namespace Inkscape, Extension */
304 /*
305   Local Variables:
306   mode:c++
307   c-file-style:"stroustrup"
308   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
309   indent-tabs-mode:nil
310   fill-column:99
311   End:
312 */
313 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :