0b333f3f8440593f1d5602e92e069246cb6eb942
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;
125 }
127 Effect::~Effect (void)
128 {
129 if (get_last_effect() == this)
130 set_last_effect(NULL);
131 return;
132 }
134 bool
135 Effect::check (void)
136 {
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;
146 }
148 bool
149 Effect::prefs (Inkscape::UI::View::View * doc)
150 {
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;
171 }
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)
185 {
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;
196 }
198 void
199 Effect::set_last_effect (Effect * in_effect)
200 {
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;
211 }
213 #define EFFECTS_LIST "effects-list"
215 bool
216 Effect::find_effects_list (Inkscape::XML::Node * menustruct)
217 {
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;
232 }
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)
242 {
243 return make_action_helper(view, &vector, static_cast<void *>(_effect));
244 }
246 /** \brief Decode the verb code and take appropriate action */
247 void
248 Effect::EffectVerb::perform (SPAction *action, void * data, void *pdata)
249 {
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;
262 }
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 :