4e6c6fd79522af4730a7182a6ecf0350a9b828c0
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, _(this->get_name()));
233 return;
234 }
236 void
237 Effect::set_last_effect (Effect * in_effect)
238 {
239 if (in_effect == NULL) {
240 Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, false);
241 Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, false);
242 } else if (_last_effect == NULL) {
243 Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, true);
244 Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, true);
245 }
247 _last_effect = in_effect;
248 return;
249 }
251 #define EFFECTS_LIST "effects-list"
253 bool
254 Effect::find_effects_list (Inkscape::XML::Node * menustruct)
255 {
256 if (menustruct == NULL) return false;
257 for (Inkscape::XML::Node * child = menustruct;
258 child != NULL;
259 child = child->next()) {
260 if (!strcmp(child->name(), EFFECTS_LIST)) {
261 _effects_list = child;
262 return true;
263 }
264 Inkscape::XML::Node * firstchild = child->firstChild();
265 if (firstchild != NULL)
266 if (find_effects_list(firstchild))
267 return true;
268 }
269 return false;
270 }
272 Gtk::VBox *
273 Effect::get_info_widget(void)
274 {
275 return Extension::get_info_widget();
276 }
278 /** \brief Create an action for a \c EffectVerb
279 \param view Which view the action should be created for
280 \return The built action.
282 Calls \c make_action_helper with the \c vector.
283 */
284 SPAction *
285 Effect::EffectVerb::make_action (Inkscape::UI::View::View * view)
286 {
287 return make_action_helper(view, &vector, static_cast<void *>(_effect));
288 }
290 /** \brief Decode the verb code and take appropriate action */
291 void
292 Effect::EffectVerb::perform (SPAction *action, void * data, void *pdata)
293 {
294 Inkscape::UI::View::View * current_view = sp_action_get_view(action);
295 // SPDocument * current_document = current_view->doc;
296 Effect * effect = reinterpret_cast<Effect *>(data);
298 if (effect == NULL) return;
299 if (current_view == NULL) return;
301 // std::cout << "Executing: " << effect->get_name() << std::endl;
302 if (effect->prefs(current_view))
303 effect->effect(current_view);
305 return;
306 }
308 /**
309 * Action vector to define functions called if a staticly defined file verb
310 * is called.
311 */
312 SPActionEventVector Effect::EffectVerb::vector =
313 {{NULL}, Effect::EffectVerb::perform, NULL, NULL, NULL, NULL};
316 } } /* namespace Inkscape, Extension */
318 /*
319 Local Variables:
320 mode:c++
321 c-file-style:"stroustrup"
322 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
323 indent-tabs-mode:nil
324 fill-column:99
325 End:
326 */
327 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :