Code

0b333f3f8440593f1d5602e92e069246cb6eb942
[inkscape.git] / src / extension / effect.cpp
1 /*
2  * Authors:
3  *   Ted Gould <ted@gould.cx>
4  *
5  * Copyright (C) 2002-2005 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, local_effects_menu, _menu_node);
59     }
61     return;
62 }
64 void
65 Effect::merge_menu (Inkscape::XML::Node * base,
66                     Inkscape::XML::Node * patern,
67                     Inkscape::XML::Node * mergee) {
68     Glib::ustring mergename;
69     Inkscape::XML::Node * tomerge = NULL;
71     if (patern == NULL) {
72         // Merge the verb name
73         tomerge = mergee;
74         mergename = _(this->get_name());
75     } else {
76         gchar const * menuname = patern->attribute("name");
77         if (menuname == NULL) menuname = patern->attribute("_name");
78         if (menuname == NULL) return;
80         tomerge = sp_repr_new("submenu");
81         tomerge->setAttribute("name", menuname, false);
83         mergename = _(menuname);
84     }
86     base->parent()->appendChild(tomerge);
87     Inkscape::GC::release(tomerge);
89     Inkscape::XML::Node * menupass;
90     for (menupass = base->next(); menupass != NULL; menupass = menupass->next()) {
91         gchar const * compare_char = NULL;
92         if (!strcmp(menupass->name(), "verb")) {
93             gchar const * verbid = menupass->attribute("verb-id");
94             Inkscape::Verb * verb = Inkscape::Verb::getbyid(verbid);
95             if (verb == NULL) {
96                 printf("Unable to find verb\n");
97                 return;
98             }
99             compare_char = verb->get_name();
100         } else { // submenu
101             compare_char = menupass->attribute("name");
102             if (compare_char == NULL)
103                 compare_char = menupass->attribute("_name");
104         }
106         if (compare_char == NULL) {
107             printf("Nothing to compare against\n");
108             return;
109         }
111         Glib::ustring compare(_(compare_char));
113         if (mergename < compare) {
114             tomerge->setPosition(menupass->position());
115             break;
116         }
117     }
119     if (patern != NULL) {
120         printf("Going recursive\n");
121         merge_menu(tomerge, patern->firstChild(), mergee);
122     }
124     return;
127 Effect::~Effect (void)
129     if (get_last_effect() == this)
130         set_last_effect(NULL);
131     return;
134 bool
135 Effect::check (void)
137     if (!Extension::check()) {
138         /** \todo  Check to see if parent has this as its only child,
139                    if so, delete it too */
140         if (_menu_node != NULL)
141             sp_repr_unparent(_menu_node);
142         _menu_node = NULL;
143         return false;
144     }
145     return true;
148 bool
149 Effect::prefs (Inkscape::UI::View::View * doc)
151     if (!loaded())
152         set_state(Extension::STATE_LOADED);
153     if (!loaded()) return false;
155     Gtk::Widget * controls;
156     controls = imp->prefs_effect(this, doc);
157     if (controls == NULL) {
158         // std::cout << "No preferences for Effect" << std::endl;
159         return true;
160     }
162     PrefDialog * dialog = new PrefDialog(this->get_name(), controls);
163     int response = dialog->run();
164     dialog->hide();
166     delete dialog;
168     if (response == Gtk::RESPONSE_OK) return true;
170     return false;
173 /**
174     \brief  The function that 'does' the effect itself
175     \param  doc  The Inkscape::UI::View::View to do the effect on
177     This function first insures that the extension is loaded, and if not,
178     loads it.  It then calls the implemention to do the actual work.  It
179     also resets the last effect pointer to be this effect.  Finally, it
180     executes a \c sp_document_done to commit the changes to the undo
181     stack.
182 */
183 void
184 Effect::effect (Inkscape::UI::View::View * doc)
186     if (!loaded())
187         set_state(Extension::STATE_LOADED);
188     if (!loaded()) return;
190     set_last_effect(this);
191     imp->effect(this, doc);
193     sp_document_done(doc->doc());
195     return;
198 void
199 Effect::set_last_effect (Effect * in_effect)
201     if (in_effect == NULL) {
202         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, false);
203         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, false);
204     } else if (_last_effect == NULL) {
205         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, true);
206         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, true);
207     }
209     _last_effect = in_effect;
210     return;
213 #define  EFFECTS_LIST  "effects-list"
215 bool
216 Effect::find_effects_list (Inkscape::XML::Node * menustruct)
218     if (menustruct == NULL) return false;
219     for (Inkscape::XML::Node * child = menustruct;
220             child != NULL;
221             child = child->next()) {
222         if (!strcmp(child->name(), EFFECTS_LIST)) {
223             _effects_list = child;
224             return true;
225         }
226         Inkscape::XML::Node * firstchild = child->firstChild();
227         if (firstchild != NULL)
228             if (find_effects_list(firstchild))
229                 return true;
230     }
231     return false;
234 /** \brief  Create an action for a \c EffectVerb
235     \param  view  Which view the action should be created for
236     \return The built action.
238     Calls \c make_action_helper with the \c vector.
239 */
240 SPAction *
241 Effect::EffectVerb::make_action (Inkscape::UI::View::View * view)
243     return make_action_helper(view, &vector, static_cast<void *>(_effect));
246 /** \brief  Decode the verb code and take appropriate action */
247 void
248 Effect::EffectVerb::perform (SPAction *action, void * data, void *pdata)
250     Inkscape::UI::View::View * current_view = sp_action_get_view(action);
251 //  SPDocument * current_document = current_view->doc;
252     Effect * effect = reinterpret_cast<Effect *>(data);
254     if (effect == NULL) return;
255     if (current_view == NULL) return;
257     // std::cout << "Executing: " << effect->get_name() << std::endl;
258     if (effect->prefs(current_view))
259         effect->effect(current_view);
261     return;
264 /**
265  * Action vector to define functions called if a staticly defined file verb
266  * is called.
267  */
268 SPActionEventVector Effect::EffectVerb::vector =
269             {{NULL},Effect::EffectVerb::perform, NULL, NULL, NULL};
272 } }  /* namespace Inkscape, Extension */
274 /*
275   Local Variables:
276   mode:c++
277   c-file-style:"stroustrup"
278   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
279   indent-tabs-mode:nil
280   fill-column:99
281   End:
282 */
283 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :