168688f0ef75b2e46b3897d4522b6d6b7034bcd1
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 bool hidden = false;
37 if (repr != NULL) {
38 Inkscape::XML::Node * child_repr;
40 for (child_repr = sp_repr_children(repr); child_repr != NULL; child_repr = child_repr->next()) {
41 if (!strcmp(child_repr->name(), "effect")) {
42 for (child_repr = sp_repr_children(child_repr); child_repr != NULL; child_repr = child_repr->next()) {
43 if (!strcmp(child_repr->name(), "effects-menu")) {
44 // printf("Found local effects menu in %s\n", this->get_name());
45 local_effects_menu = sp_repr_children(child_repr);
46 if (child_repr->attribute("hidden") && !strcmp(child_repr->attribute("hidden"), "yes")) {
47 hidden = true;
48 }
49 }
50 if (!strcmp(child_repr->name(), "menu-name") ||
51 !strcmp(child_repr->name(), "_menu-name")) {
52 // printf("Found local effects menu in %s\n", this->get_name());
53 _verb.set_name(sp_repr_children(child_repr)->content());
54 }
55 if (!strcmp(child_repr->name(), "menu-tip") ||
56 !strcmp(child_repr->name(), "_menu-tip")) {
57 // printf("Found local effects menu in %s\n", this->get_name());
58 _verb.set_tip(sp_repr_children(child_repr)->content());
59 }
60 } // children of "effect"
61 break; // there can only be one effect
62 } // find "effect"
63 } // children of "inkscape-extension"
64 } // if we have an XML file
66 if (_effects_list == NULL)
67 find_effects_list(inkscape_get_menus(INKSCAPE));
69 if (_effects_list != NULL) {
70 _menu_node = sp_repr_new("verb");
71 _menu_node->setAttribute("verb-id", this->get_id(), false);
73 if (!hidden)
74 merge_menu(_effects_list->parent(), _effects_list, local_effects_menu, _menu_node);
75 }
77 return;
78 }
80 void
81 Effect::merge_menu (Inkscape::XML::Node * base,
82 Inkscape::XML::Node * start,
83 Inkscape::XML::Node * patern,
84 Inkscape::XML::Node * mergee) {
85 Glib::ustring mergename;
86 Inkscape::XML::Node * tomerge = NULL;
87 Inkscape::XML::Node * submenu = NULL;
89 /* printf("Merge menu with '%s' '%s' '%s'\n",
90 base != NULL ? base->name() : "NULL",
91 patern != NULL ? patern->name() : "NULL",
92 mergee != NULL ? mergee->name() : "NULL"); */
94 if (patern == NULL) {
95 // Merge the verb name
96 tomerge = mergee;
97 mergename = _(this->get_name());
98 } else {
99 gchar const * menuname = patern->attribute("name");
100 if (menuname == NULL) menuname = patern->attribute("_name");
101 if (menuname == NULL) return;
103 tomerge = sp_repr_new("submenu");
104 tomerge->setAttribute("name", menuname, false);
106 mergename = _(menuname);
107 }
109 int position = -1;
111 if (start != NULL) {
112 Inkscape::XML::Node * menupass;
113 for (menupass = start->next(); menupass != NULL; menupass = menupass->next()) {
114 gchar const * compare_char = NULL;
115 if (!strcmp(menupass->name(), "verb")) {
116 gchar const * verbid = menupass->attribute("verb-id");
117 Inkscape::Verb * verb = Inkscape::Verb::getbyid(verbid);
118 if (verb == NULL) {
119 continue;
120 }
121 compare_char = verb->get_name();
122 } else if (!strcmp(menupass->name(), "submenu")) {
123 compare_char = menupass->attribute("name");
124 if (compare_char == NULL)
125 compare_char = menupass->attribute("_name");
126 }
128 /* This will cause us to skip tags we don't understand */
129 if (compare_char == NULL) {
130 continue;
131 }
133 Glib::ustring compare(_(compare_char));
135 if (mergename == compare) {
136 Inkscape::GC::release(tomerge);
137 tomerge = NULL;
138 submenu = menupass;
139 break;
140 }
142 if (mergename < compare) {
143 position = menupass->position();
144 break;
145 }
146 } // for menu items
147 } // start != NULL
149 if (tomerge != NULL) {
150 base->appendChild(tomerge);
151 Inkscape::GC::release(tomerge);
152 if (position != -1)
153 tomerge->setPosition(position);
154 }
156 if (patern != NULL) {
157 if (submenu == NULL)
158 submenu = tomerge;
159 merge_menu(submenu, submenu->firstChild(), patern->firstChild(), mergee);
160 }
162 return;
163 }
165 Effect::~Effect (void)
166 {
167 if (get_last_effect() == this)
168 set_last_effect(NULL);
169 return;
170 }
172 bool
173 Effect::check (void)
174 {
175 if (!Extension::check()) {
176 /** \todo Check to see if parent has this as its only child,
177 if so, delete it too */
178 if (_menu_node != NULL)
179 sp_repr_unparent(_menu_node);
180 _menu_node = NULL;
181 return false;
182 }
183 return true;
184 }
186 bool
187 Effect::prefs (Inkscape::UI::View::View * doc)
188 {
189 if (!loaded())
190 set_state(Extension::STATE_LOADED);
191 if (!loaded()) return false;
193 Gtk::Widget * controls;
194 controls = imp->prefs_effect(this, doc);
195 if (controls == NULL) {
196 // std::cout << "No preferences for Effect" << std::endl;
197 return true;
198 }
200 PrefDialog * dialog = new PrefDialog(this->get_name(), this->get_help(), controls);
201 int response = dialog->run();
202 dialog->hide();
204 delete dialog;
206 if (response == Gtk::RESPONSE_OK) return true;
208 return false;
209 }
211 /**
212 \brief The function that 'does' the effect itself
213 \param doc The Inkscape::UI::View::View to do the effect on
215 This function first insures that the extension is loaded, and if not,
216 loads it. It then calls the implemention to do the actual work. It
217 also resets the last effect pointer to be this effect. Finally, it
218 executes a \c sp_document_done to commit the changes to the undo
219 stack.
220 */
221 void
222 Effect::effect (Inkscape::UI::View::View * doc)
223 {
224 if (!loaded())
225 set_state(Extension::STATE_LOADED);
226 if (!loaded()) return;
228 set_last_effect(this);
229 imp->effect(this, doc);
231 sp_document_done(doc->doc(), SP_VERB_NONE,
232 /* TODO: annotate */ "effect.cpp:226");
234 return;
235 }
237 void
238 Effect::set_last_effect (Effect * in_effect)
239 {
240 if (in_effect == NULL) {
241 Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, false);
242 Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, false);
243 } else if (_last_effect == NULL) {
244 Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, true);
245 Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, true);
246 }
248 _last_effect = in_effect;
249 return;
250 }
252 #define EFFECTS_LIST "effects-list"
254 bool
255 Effect::find_effects_list (Inkscape::XML::Node * menustruct)
256 {
257 if (menustruct == NULL) return false;
258 for (Inkscape::XML::Node * child = menustruct;
259 child != NULL;
260 child = child->next()) {
261 if (!strcmp(child->name(), EFFECTS_LIST)) {
262 _effects_list = child;
263 return true;
264 }
265 Inkscape::XML::Node * firstchild = child->firstChild();
266 if (firstchild != NULL)
267 if (find_effects_list(firstchild))
268 return true;
269 }
270 return false;
271 }
273 Gtk::VBox *
274 Effect::get_info_widget(void)
275 {
276 return Extension::get_info_widget();
277 }
279 /** \brief Create an action for a \c EffectVerb
280 \param view Which view the action should be created for
281 \return The built action.
283 Calls \c make_action_helper with the \c vector.
284 */
285 SPAction *
286 Effect::EffectVerb::make_action (Inkscape::UI::View::View * view)
287 {
288 return make_action_helper(view, &vector, static_cast<void *>(_effect));
289 }
291 /** \brief Decode the verb code and take appropriate action */
292 void
293 Effect::EffectVerb::perform (SPAction *action, void * data, void *pdata)
294 {
295 Inkscape::UI::View::View * current_view = sp_action_get_view(action);
296 // SPDocument * current_document = current_view->doc;
297 Effect * effect = reinterpret_cast<Effect *>(data);
299 if (effect == NULL) return;
300 if (current_view == NULL) return;
302 // std::cout << "Executing: " << effect->get_name() << std::endl;
303 if (effect->prefs(current_view))
304 effect->effect(current_view);
306 return;
307 }
309 /**
310 * Action vector to define functions called if a staticly defined file verb
311 * is called.
312 */
313 SPActionEventVector Effect::EffectVerb::vector =
314 {{NULL}, Effect::EffectVerb::perform, NULL, NULL, NULL, NULL};
317 } } /* namespace Inkscape, Extension */
319 /*
320 Local Variables:
321 mode:c++
322 c-file-style:"stroustrup"
323 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
324 indent-tabs-mode:nil
325 fill-column:99
326 End:
327 */
328 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :