Code

r10818@tres: ted | 2006-01-29 16:08:07 -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                 } // children of "effect"
46                 break; // there can only be one effect
47             } // find "effect"
48         } // children of "inkscape-extension"
49     } // if we have an XML file
51     if (_effects_list == NULL)
52         find_effects_list(inkscape_get_menus(INKSCAPE));
54     if (_effects_list != NULL) {
55         _menu_node = sp_repr_new("verb");
56         _menu_node->setAttribute("verb-id", this->get_id(), false);
58         merge_menu(_effects_list->parent(), _effects_list, local_effects_menu, _menu_node);
59     }
61     return;
62 }
64 void
65 Effect::merge_menu (Inkscape::XML::Node * base,
66                     Inkscape::XML::Node * start,
67                     Inkscape::XML::Node * patern,
68                     Inkscape::XML::Node * mergee) {
69     Glib::ustring mergename;
70     Inkscape::XML::Node * tomerge = NULL;
71     Inkscape::XML::Node * submenu = NULL;
73     /* printf("Merge menu with '%s' '%s' '%s'\n",
74             base != NULL ? base->name() : "NULL",
75             patern != NULL ? patern->name() : "NULL",
76             mergee != NULL ? mergee->name() : "NULL"); */
78     if (patern == NULL) {
79         // Merge the verb name
80         tomerge = mergee;
81         mergename = _(this->get_name());
82     } else {
83         gchar const * menuname = patern->attribute("name");
84         if (menuname == NULL) menuname = patern->attribute("_name");
85         if (menuname == NULL) return;
87         tomerge = sp_repr_new("submenu");
88         tomerge->setAttribute("name", menuname, false);
90         mergename = _(menuname);
91     }
93     int position = -1;
95     if (start != NULL) {
96         Inkscape::XML::Node * menupass;
97         for (menupass = start->next(); menupass != NULL; menupass = menupass->next()) {
98             gchar const * compare_char = NULL;
99             if (!strcmp(menupass->name(), "verb")) {
100                 gchar const * verbid = menupass->attribute("verb-id");
101                 Inkscape::Verb * verb = Inkscape::Verb::getbyid(verbid);
102                 if (verb == NULL) {
103                     continue;
104                 }
105                 compare_char = verb->get_name();
106             } else if (!strcmp(menupass->name(), "submenu")) {
107                 compare_char = menupass->attribute("name");
108                 if (compare_char == NULL)
109                     compare_char = menupass->attribute("_name");
110             }
112             /* This will cause us to skip tags we don't understand */
113             if (compare_char == NULL) {
114                 continue;
115             }
117             Glib::ustring compare(_(compare_char));
119             if (mergename == compare) {
120                 Inkscape::GC::release(tomerge);
121                 tomerge = NULL;
122                 submenu = menupass;
123                 break;
124             }
126             if (mergename < compare) {
127                 position = menupass->position();
128                 break;
129             }
130         } // for menu items
131     } // start != NULL
133     if (tomerge != NULL) {
134         base->appendChild(tomerge);
135         Inkscape::GC::release(tomerge);
136         if (position != -1)
137             tomerge->setPosition(position);
138     }
140     if (patern != NULL) {
141         if (submenu == NULL)
142             submenu = tomerge;
143         merge_menu(submenu, submenu->firstChild(), patern->firstChild(), mergee);
144     }
146     return;
149 Effect::~Effect (void)
151     if (get_last_effect() == this)
152         set_last_effect(NULL);
153     return;
156 bool
157 Effect::check (void)
159     if (!Extension::check()) {
160         /** \todo  Check to see if parent has this as its only child,
161                    if so, delete it too */
162         if (_menu_node != NULL)
163             sp_repr_unparent(_menu_node);
164         _menu_node = NULL;
165         return false;
166     }
167     return true;
170 bool
171 Effect::prefs (Inkscape::UI::View::View * doc)
173     if (!loaded())
174         set_state(Extension::STATE_LOADED);
175     if (!loaded()) return false;
177     Gtk::Widget * controls;
178     controls = imp->prefs_effect(this, doc);
179     if (controls == NULL) {
180         // std::cout << "No preferences for Effect" << std::endl;
181         return true;
182     }
184     PrefDialog * dialog = new PrefDialog(this->get_name(), controls);
185     int response = dialog->run();
186     dialog->hide();
188     delete dialog;
190     if (response == Gtk::RESPONSE_OK) return true;
192     return false;
195 /**
196     \brief  The function that 'does' the effect itself
197     \param  doc  The Inkscape::UI::View::View to do the effect on
199     This function first insures that the extension is loaded, and if not,
200     loads it.  It then calls the implemention to do the actual work.  It
201     also resets the last effect pointer to be this effect.  Finally, it
202     executes a \c sp_document_done to commit the changes to the undo
203     stack.
204 */
205 void
206 Effect::effect (Inkscape::UI::View::View * doc)
208     if (!loaded())
209         set_state(Extension::STATE_LOADED);
210     if (!loaded()) return;
212     set_last_effect(this);
213     imp->effect(this, doc);
215     sp_document_done(doc->doc());
217     return;
220 void
221 Effect::set_last_effect (Effect * in_effect)
223     if (in_effect == NULL) {
224         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, false);
225         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, false);
226     } else if (_last_effect == NULL) {
227         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, true);
228         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, true);
229     }
231     _last_effect = in_effect;
232     return;
235 #define  EFFECTS_LIST  "effects-list"
237 bool
238 Effect::find_effects_list (Inkscape::XML::Node * menustruct)
240     if (menustruct == NULL) return false;
241     for (Inkscape::XML::Node * child = menustruct;
242             child != NULL;
243             child = child->next()) {
244         if (!strcmp(child->name(), EFFECTS_LIST)) {
245             _effects_list = child;
246             return true;
247         }
248         Inkscape::XML::Node * firstchild = child->firstChild();
249         if (firstchild != NULL)
250             if (find_effects_list(firstchild))
251                 return true;
252     }
253     return false;
256 /** \brief  Create an action for a \c EffectVerb
257     \param  view  Which view the action should be created for
258     \return The built action.
260     Calls \c make_action_helper with the \c vector.
261 */
262 SPAction *
263 Effect::EffectVerb::make_action (Inkscape::UI::View::View * view)
265     return make_action_helper(view, &vector, static_cast<void *>(_effect));
268 /** \brief  Decode the verb code and take appropriate action */
269 void
270 Effect::EffectVerb::perform (SPAction *action, void * data, void *pdata)
272     Inkscape::UI::View::View * current_view = sp_action_get_view(action);
273 //  SPDocument * current_document = current_view->doc;
274     Effect * effect = reinterpret_cast<Effect *>(data);
276     if (effect == NULL) return;
277     if (current_view == NULL) return;
279     // std::cout << "Executing: " << effect->get_name() << std::endl;
280     if (effect->prefs(current_view))
281         effect->effect(current_view);
283     return;
286 /**
287  * Action vector to define functions called if a staticly defined file verb
288  * is called.
289  */
290 SPActionEventVector Effect::EffectVerb::vector =
291             {{NULL},Effect::EffectVerb::perform, NULL, NULL, NULL};
294 } }  /* namespace Inkscape, Extension */
296 /*
297   Local Variables:
298   mode:c++
299   c-file-style:"stroustrup"
300   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
301   indent-tabs-mode:nil
302   fill-column:99
303   End:
304 */
305 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :