1d0c4c4af4757bb31063a5437eccf90c5b0157e5
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 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->parent(), _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 * start,
67 Inkscape::XML::Node * patern,
68 Inkscape::XML::Node * mergee) {
69 Glib::ustring mergename;
70 Inkscape::XML::Node * tomerge = NULL;
72 /* printf("Merge menu with '%s' '%s' '%s'\n",
73 base != NULL ? base->name() : "NULL",
74 patern != NULL ? patern->name() : "NULL",
75 mergee != NULL ? mergee->name() : "NULL"); */
77 if (patern == NULL) {
78 // Merge the verb name
79 tomerge = mergee;
80 mergename = _(this->get_name());
81 } else {
82 gchar const * menuname = patern->attribute("name");
83 if (menuname == NULL) menuname = patern->attribute("_name");
84 if (menuname == NULL) return;
86 tomerge = sp_repr_new("submenu");
87 tomerge->setAttribute("name", menuname, false);
89 mergename = _(menuname);
90 }
92 base->appendChild(tomerge);
93 Inkscape::GC::release(tomerge);
95 if (start != NULL) {
96 Inkscape::XML::Node * menupass;
97 for (menupass = start->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 continue;
104 }
105 compare_char = verb->get_name();
106 } else if (!strcmp(menupass->name(), "submenu")) {
107 compare_char = menupass->attribute("name");
108 if (compare_char == NULL)
109 compare_char = menupass->attribute("_name");
110 }
112 /* This will cause us to skip tags we don't understand */
113 if (compare_char == NULL) {
114 continue;
115 }
117 Glib::ustring compare(_(compare_char));
119 if (mergename < compare) {
120 tomerge->setPosition(menupass->position());
121 break;
122 }
123 } // for menu items
124 } // start != NULL
126 if (patern != NULL) {
127 merge_menu(tomerge, tomerge->firstChild(), patern->firstChild(), mergee);
128 }
130 return;
131 }
133 Effect::~Effect (void)
134 {
135 if (get_last_effect() == this)
136 set_last_effect(NULL);
137 return;
138 }
140 bool
141 Effect::check (void)
142 {
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;
152 }
154 bool
155 Effect::prefs (Inkscape::UI::View::View * doc)
156 {
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;
177 }
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)
191 {
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;
202 }
204 void
205 Effect::set_last_effect (Effect * in_effect)
206 {
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;
217 }
219 #define EFFECTS_LIST "effects-list"
221 bool
222 Effect::find_effects_list (Inkscape::XML::Node * menustruct)
223 {
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;
238 }
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)
248 {
249 return make_action_helper(view, &vector, static_cast<void *>(_effect));
250 }
252 /** \brief Decode the verb code and take appropriate action */
253 void
254 Effect::EffectVerb::perform (SPAction *action, void * data, void *pdata)
255 {
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;
268 }
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 :