Code

r10816@tres: ted | 2006-01-29 15:14:36 -0800
[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         if (!strcmp(this->get_id(), "org.ekips.filter.interp"))
60             sp_repr_print(_effects_list->parent());
61     }
63     return;
64 }
66 void
67 Effect::merge_menu (Inkscape::XML::Node * base,
68                     Inkscape::XML::Node * patern,
69                     Inkscape::XML::Node * mergee) {
70     Glib::ustring mergename;
71     Inkscape::XML::Node * tomerge = 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     base->parent()->appendChild(tomerge);
94     Inkscape::GC::release(tomerge);
96     Inkscape::XML::Node * menupass;
97     for (menupass = base->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                 printf("Unable to find verb\n");
104                 return;
105             }
106             compare_char = verb->get_name();
107         } else { // submenu
108             compare_char = menupass->attribute("name");
109             if (compare_char == NULL)
110                 compare_char = menupass->attribute("_name");
111         }
113         if (compare_char == NULL) {
114             printf("Nothing to compare against\n");
115             return;
116         }
118         Glib::ustring compare(_(compare_char));
120         if (mergename < compare) {
121             tomerge->setPosition(menupass->position());
122             break;
123         }
124     }
126     if (patern != NULL) {
127         merge_menu(tomerge, patern->firstChild(), mergee);
128     }
130     return;
133 Effect::~Effect (void)
135     if (get_last_effect() == this)
136         set_last_effect(NULL);
137     return;
140 bool
141 Effect::check (void)
143     if (!Extension::check()) {
144         /** \todo  Check to see if parent has this as its only child,
145                    if so, delete it too */
146         if (_menu_node != NULL)
147             sp_repr_unparent(_menu_node);
148         _menu_node = NULL;
149         return false;
150     }
151     return true;
154 bool
155 Effect::prefs (Inkscape::UI::View::View * doc)
157     if (!loaded())
158         set_state(Extension::STATE_LOADED);
159     if (!loaded()) return false;
161     Gtk::Widget * controls;
162     controls = imp->prefs_effect(this, doc);
163     if (controls == NULL) {
164         // std::cout << "No preferences for Effect" << std::endl;
165         return true;
166     }
168     PrefDialog * dialog = new PrefDialog(this->get_name(), controls);
169     int response = dialog->run();
170     dialog->hide();
172     delete dialog;
174     if (response == Gtk::RESPONSE_OK) return true;
176     return false;
179 /**
180     \brief  The function that 'does' the effect itself
181     \param  doc  The Inkscape::UI::View::View to do the effect on
183     This function first insures that the extension is loaded, and if not,
184     loads it.  It then calls the implemention to do the actual work.  It
185     also resets the last effect pointer to be this effect.  Finally, it
186     executes a \c sp_document_done to commit the changes to the undo
187     stack.
188 */
189 void
190 Effect::effect (Inkscape::UI::View::View * doc)
192     if (!loaded())
193         set_state(Extension::STATE_LOADED);
194     if (!loaded()) return;
196     set_last_effect(this);
197     imp->effect(this, doc);
199     sp_document_done(doc->doc());
201     return;
204 void
205 Effect::set_last_effect (Effect * in_effect)
207     if (in_effect == NULL) {
208         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, false);
209         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, false);
210     } else if (_last_effect == NULL) {
211         Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, true);
212         Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, true);
213     }
215     _last_effect = in_effect;
216     return;
219 #define  EFFECTS_LIST  "effects-list"
221 bool
222 Effect::find_effects_list (Inkscape::XML::Node * menustruct)
224     if (menustruct == NULL) return false;
225     for (Inkscape::XML::Node * child = menustruct;
226             child != NULL;
227             child = child->next()) {
228         if (!strcmp(child->name(), EFFECTS_LIST)) {
229             _effects_list = child;
230             return true;
231         }
232         Inkscape::XML::Node * firstchild = child->firstChild();
233         if (firstchild != NULL)
234             if (find_effects_list(firstchild))
235                 return true;
236     }
237     return false;
240 /** \brief  Create an action for a \c EffectVerb
241     \param  view  Which view the action should be created for
242     \return The built action.
244     Calls \c make_action_helper with the \c vector.
245 */
246 SPAction *
247 Effect::EffectVerb::make_action (Inkscape::UI::View::View * view)
249     return make_action_helper(view, &vector, static_cast<void *>(_effect));
252 /** \brief  Decode the verb code and take appropriate action */
253 void
254 Effect::EffectVerb::perform (SPAction *action, void * data, void *pdata)
256     Inkscape::UI::View::View * current_view = sp_action_get_view(action);
257 //  SPDocument * current_document = current_view->doc;
258     Effect * effect = reinterpret_cast<Effect *>(data);
260     if (effect == NULL) return;
261     if (current_view == NULL) return;
263     // std::cout << "Executing: " << effect->get_name() << std::endl;
264     if (effect->prefs(current_view))
265         effect->effect(current_view);
267     return;
270 /**
271  * Action vector to define functions called if a staticly defined file verb
272  * is called.
273  */
274 SPActionEventVector Effect::EffectVerb::vector =
275             {{NULL},Effect::EffectVerb::perform, NULL, NULL, NULL};
278 } }  /* namespace Inkscape, Extension */
280 /*
281   Local Variables:
282   mode:c++
283   c-file-style:"stroustrup"
284   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
285   indent-tabs-mode:nil
286   fill-column:99
287   End:
288 */
289 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :