3
* Ted Gould <ted@gould.cx>
5
* Copyright (C) 2002-2007 Authors
7
* Released under GNU GPL, read the file 'COPYING' for more information
10
#include "inkscape-private.h"
11
#include "helper/action.h"
12
#include "ui/view/view.h"
13
#include "desktop-handles.h"
14
#include "selection.h"
15
#include "sp-namedview.h"
17
#include "implementation/implementation.h"
19
#include "execution-env.h"
24
/* Inkscape::Extension::Effect */
29
Effect * Effect::_last_effect = NULL;
30
Inkscape::XML::Node * Effect::_effects_list = NULL;
31
Inkscape::XML::Node * Effect::_filters_list = NULL;
33
#define EFFECTS_LIST "effects-list"
34
#define FILTERS_LIST "filters-list"
36
Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation * in_imp)
37
: Extension(in_repr, in_imp),
38
_id_noprefs(Glib::ustring(get_id()) + ".noprefs"),
39
_name_noprefs(Glib::ustring(get_name()) + _(" (No preferences)")),
40
_verb(get_id(), get_name(), NULL, NULL, this, true),
41
_verb_nopref(_id_noprefs.c_str(), _name_noprefs.c_str(), NULL, NULL, this, false),
42
_menu_node(NULL), _workingDialog(true),
45
Inkscape::XML::Node * local_effects_menu = NULL;
47
// This is a weird hack
48
if (!strcmp(this->get_id(), "org.inkscape.filter.dropshadow"))
54
no_live_preview = false;
58
for (Inkscape::XML::Node *child = sp_repr_children(repr); child != NULL; child = child->next()) {
59
if (!strcmp(child->name(), INKSCAPE_EXTENSION_NS "effect")) {
60
if (child->attribute("needs-document") && !strcmp(child->attribute("needs-document"), "false")) {
63
if (child->attribute("needs-live-preview") && !strcmp(child->attribute("needs-live-preview"), "false")) {
64
no_live_preview = true;
66
for (Inkscape::XML::Node *effect_child = sp_repr_children(child); effect_child != NULL; effect_child = effect_child->next()) {
67
if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "effects-menu")) {
68
// printf("Found local effects menu in %s\n", this->get_name());
69
local_effects_menu = sp_repr_children(effect_child);
70
if (effect_child->attribute("hidden") && !strcmp(effect_child->attribute("hidden"), "true")) {
74
if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "menu-name") ||
75
!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "_menu-name")) {
76
// printf("Found local effects menu in %s\n", this->get_name());
77
_verb.set_name(sp_repr_children(effect_child)->content());
79
if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "menu-tip") ||
80
!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "_menu-tip")) {
81
// printf("Found local effects menu in %s\n", this->get_name());
82
_verb.set_tip(sp_repr_children(effect_child)->content());
84
} // children of "effect"
85
break; // there can only be one effect
87
} // children of "inkscape-extension"
88
} // if we have an XML file
90
if (INKSCAPE != NULL) {
91
if (_effects_list == NULL)
92
_effects_list = find_menu(inkscape_get_menus(INKSCAPE), EFFECTS_LIST);
93
if (_filters_list == NULL)
94
_filters_list = find_menu(inkscape_get_menus(INKSCAPE), FILTERS_LIST);
97
if ((_effects_list != NULL || _filters_list != NULL)) {
98
Inkscape::XML::Document *xml_doc;
99
xml_doc = _effects_list->document();
100
_menu_node = xml_doc->createElement("verb");
101
_menu_node->setAttribute("verb-id", this->get_id(), false);
105
local_effects_menu &&
106
local_effects_menu->attribute("name") &&
107
!strcmp(local_effects_menu->attribute("name"), ("Filters"))) {
108
merge_menu(_filters_list->parent(), _filters_list, sp_repr_children(local_effects_menu), _menu_node);
109
} else if (_effects_list) {
110
merge_menu(_effects_list->parent(), _effects_list, local_effects_menu, _menu_node);
119
Effect::merge_menu (Inkscape::XML::Node * base,
120
Inkscape::XML::Node * start,
121
Inkscape::XML::Node * patern,
122
Inkscape::XML::Node * mergee) {
123
Glib::ustring mergename;
124
Inkscape::XML::Node * tomerge = NULL;
125
Inkscape::XML::Node * submenu = NULL;
127
/* printf("Merge menu with '%s' '%s' '%s'\n",
128
base != NULL ? base->name() : "NULL",
129
patern != NULL ? patern->name() : "NULL",
130
mergee != NULL ? mergee->name() : "NULL"); */
132
if (patern == NULL) {
133
// Merge the verb name
135
mergename = _(this->get_name());
137
gchar const * menuname = patern->attribute("name");
138
if (menuname == NULL) menuname = patern->attribute("_name");
139
if (menuname == NULL) return;
141
Inkscape::XML::Document *xml_doc;
142
xml_doc = base->document();
143
tomerge = xml_doc->createElement("submenu");
144
tomerge->setAttribute("name", menuname, false);
146
mergename = _(menuname);
152
Inkscape::XML::Node * menupass;
153
for (menupass = start; menupass != NULL && strcmp(menupass->name(), "separator"); menupass = menupass->next()) {
154
gchar const * compare_char = NULL;
155
if (!strcmp(menupass->name(), "verb")) {
156
gchar const * verbid = menupass->attribute("verb-id");
157
Inkscape::Verb * verb = Inkscape::Verb::getbyid(verbid);
159
g_warning("Unable to find verb '%s' which is referred to in the menus.", verbid);
162
compare_char = verb->get_name();
163
} else if (!strcmp(menupass->name(), "submenu")) {
164
compare_char = menupass->attribute("name");
165
if (compare_char == NULL)
166
compare_char = menupass->attribute("_name");
169
position = menupass->position() + 1;
171
/* This will cause us to skip tags we don't understand */
172
if (compare_char == NULL) {
176
Glib::ustring compare(_(compare_char));
178
if (mergename == compare) {
179
Inkscape::GC::release(tomerge);
185
if (mergename < compare) {
186
position = menupass->position();
192
if (tomerge != NULL) {
193
base->appendChild(tomerge);
194
Inkscape::GC::release(tomerge);
196
tomerge->setPosition(position);
199
if (patern != NULL) {
202
merge_menu(submenu, submenu->firstChild(), patern->firstChild(), mergee);
208
Effect::~Effect (void)
210
if (get_last_effect() == this)
211
set_last_effect(NULL);
213
Inkscape::GC::release(_menu_node);
220
if (!Extension::check()) {
221
/** \todo Check to see if parent has this as its only child,
222
if so, delete it too */
223
if (_menu_node != NULL)
224
sp_repr_unparent(_menu_node);
232
Effect::prefs (Inkscape::UI::View::View * doc)
234
if (_prefDialog != NULL) {
235
_prefDialog->raise();
239
if (param_visible_count() == 0) {
245
set_state(Extension::STATE_LOADED);
246
if (!loaded()) return false;
248
_prefDialog = new PrefDialog(this->get_name(), this->get_help(), NULL, this);
255
\brief The function that 'does' the effect itself
256
\param doc The Inkscape::UI::View::View to do the effect on
258
This function first insures that the extension is loaded, and if not,
259
loads it. It then calls the implemention to do the actual work. It
260
also resets the last effect pointer to be this effect. Finally, it
261
executes a \c sp_document_done to commit the changes to the undo
265
Effect::effect (Inkscape::UI::View::View * doc)
267
//printf("Execute effect\n");
269
set_state(Extension::STATE_LOADED);
270
if (!loaded()) return;
273
ExecutionEnv executionEnv(this, doc);
276
if (executionEnv.wait()) {
277
executionEnv.commit();
279
executionEnv.cancel();
286
/** \brief Sets which effect was called last
287
\param in_effect The effect that has been called
289
This function sets the static variable \c _last_effect and it
290
ensures that the last effect verb is sensitive.
292
If the \c in_effect variable is \c NULL then the last effect
293
verb is made insesitive.
296
Effect::set_last_effect (Effect * in_effect)
298
if (in_effect == NULL) {
299
Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, false);
300
Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, false);
301
} else if (_last_effect == NULL) {
302
Inkscape::Verb::get(SP_VERB_EFFECT_LAST)->sensitive(NULL, true);
303
Inkscape::Verb::get(SP_VERB_EFFECT_LAST_PREF)->sensitive(NULL, true);
306
_last_effect = in_effect;
310
Inkscape::XML::Node *
311
Effect::find_menu (Inkscape::XML::Node * menustruct, const gchar *name)
313
if (menustruct == NULL) return false;
314
for (Inkscape::XML::Node * child = menustruct;
316
child = child->next()) {
317
if (!strcmp(child->name(), name)) {
320
Inkscape::XML::Node * firstchild = child->firstChild();
321
if (firstchild != NULL) {
322
Inkscape::XML::Node *found = find_menu (firstchild, name);
332
Effect::get_info_widget(void)
334
return Extension::get_info_widget();
338
Effect::set_pref_dialog (PrefDialog * prefdialog)
340
_prefDialog = prefdialog;
344
/** \brief Create an action for a \c EffectVerb
345
\param view Which view the action should be created for
346
\return The built action.
348
Calls \c make_action_helper with the \c vector.
351
Effect::EffectVerb::make_action (Inkscape::UI::View::View * view)
353
return make_action_helper(view, &vector, static_cast<void *>(this));
356
/** \brief Decode the verb code and take appropriate action */
358
Effect::EffectVerb::perform( SPAction *action, void * data, void */*pdata*/ )
360
Inkscape::UI::View::View * current_view = sp_action_get_view(action);
361
// SPDocument * current_document = current_view->doc;
362
Effect::EffectVerb * ev = reinterpret_cast<Effect::EffectVerb *>(data);
363
Effect * effect = ev->_effect;
365
if (effect == NULL) return;
366
if (current_view == NULL) return;
368
if (ev->_showPrefs) {
369
effect->prefs(current_view);
371
effect->effect(current_view);
378
* Action vector to define functions called if a staticly defined file verb
381
SPActionEventVector Effect::EffectVerb::vector =
382
{{NULL}, Effect::EffectVerb::perform, NULL, NULL, NULL, NULL};
385
} } /* namespace Inkscape, Extension */
390
c-file-style:"stroustrup"
391
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
396
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :