~valavanisalex/ubuntu/precise/inkscape/fix-943984

« back to all changes in this revision

Viewing changes to inkscape-0.47pre1/src/extension/effect.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2009-07-02 17:09:45 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702170945-nn6d6zswovbwju1t
Tags: 0.47~pre1-0ubuntu1
* New upstream release.
  - Don't constrain maximization on small resolution devices (pre0)
    (LP: #348842)
  - Fixes segfault on startup (pre0)
    (LP: #391149)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Authors:
 
3
 *   Ted Gould <ted@gould.cx>
 
4
 *
 
5
 * Copyright (C) 2002-2007 Authors
 
6
 *
 
7
 * Released under GNU GPL, read the file 'COPYING' for more information
 
8
 */
 
9
 
 
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"
 
16
#include "desktop.h"
 
17
#include "implementation/implementation.h"
 
18
#include "effect.h"
 
19
#include "execution-env.h"
 
20
#include "timer.h"
 
21
 
 
22
 
 
23
 
 
24
/* Inkscape::Extension::Effect */
 
25
 
 
26
namespace Inkscape {
 
27
namespace Extension {
 
28
 
 
29
Effect * Effect::_last_effect = NULL;
 
30
Inkscape::XML::Node * Effect::_effects_list = NULL;
 
31
Inkscape::XML::Node * Effect::_filters_list = NULL;
 
32
 
 
33
#define  EFFECTS_LIST  "effects-list"
 
34
#define  FILTERS_LIST  "filters-list"
 
35
 
 
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),
 
43
      _prefDialog(NULL)
 
44
{
 
45
    Inkscape::XML::Node * local_effects_menu = NULL;
 
46
 
 
47
    // This is a weird hack
 
48
    if (!strcmp(this->get_id(), "org.inkscape.filter.dropshadow"))
 
49
        return;
 
50
 
 
51
    bool hidden = false;
 
52
 
 
53
    no_doc = false;
 
54
    no_live_preview = false;
 
55
 
 
56
    if (repr != NULL) {
 
57
 
 
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")) {
 
61
                  no_doc = true;
 
62
                }
 
63
                if (child->attribute("needs-live-preview") && !strcmp(child->attribute("needs-live-preview"), "false")) {
 
64
                  no_live_preview = true;
 
65
                }
 
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")) {
 
71
                            hidden = true;
 
72
                        }
 
73
                    }
 
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());
 
78
                    }
 
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());
 
83
                    }
 
84
                } // children of "effect"
 
85
                break; // there can only be one effect
 
86
            } // find "effect"
 
87
        } // children of "inkscape-extension"
 
88
    } // if we have an XML file
 
89
 
 
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);
 
95
    }
 
96
 
 
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);
 
102
 
 
103
        if (!hidden) {
 
104
            if (_filters_list &&
 
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);
 
111
            }
 
112
        }
 
113
    }
 
114
 
 
115
    return;
 
116
}
 
117
 
 
118
void
 
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;
 
126
 
 
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"); */
 
131
 
 
132
    if (patern == NULL) {
 
133
        // Merge the verb name
 
134
        tomerge = mergee;
 
135
        mergename = _(this->get_name());
 
136
    } else {
 
137
        gchar const * menuname = patern->attribute("name");
 
138
        if (menuname == NULL) menuname = patern->attribute("_name");
 
139
        if (menuname == NULL) return;
 
140
        
 
141
        Inkscape::XML::Document *xml_doc;
 
142
        xml_doc = base->document();
 
143
        tomerge = xml_doc->createElement("submenu");
 
144
        tomerge->setAttribute("name", menuname, false);
 
145
 
 
146
        mergename = _(menuname);
 
147
    }
 
148
 
 
149
    int position = -1;
 
150
 
 
151
    if (start != NULL) {
 
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);
 
158
                if (verb == NULL) {
 
159
                                        g_warning("Unable to find verb '%s' which is referred to in the menus.", verbid);
 
160
                    continue;
 
161
                }
 
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");
 
167
            }
 
168
 
 
169
            position = menupass->position() + 1;
 
170
 
 
171
            /* This will cause us to skip tags we don't understand */
 
172
            if (compare_char == NULL) {
 
173
                continue;
 
174
            }
 
175
 
 
176
            Glib::ustring compare(_(compare_char));
 
177
 
 
178
            if (mergename == compare) {
 
179
                Inkscape::GC::release(tomerge);
 
180
                tomerge = NULL;
 
181
                submenu = menupass;
 
182
                break;
 
183
            }
 
184
 
 
185
            if (mergename < compare) {
 
186
                position = menupass->position();
 
187
                break;
 
188
            }
 
189
        } // for menu items
 
190
    } // start != NULL
 
191
 
 
192
    if (tomerge != NULL) {
 
193
        base->appendChild(tomerge);
 
194
        Inkscape::GC::release(tomerge);
 
195
        if (position != -1)
 
196
            tomerge->setPosition(position);
 
197
    }
 
198
 
 
199
    if (patern != NULL) {
 
200
        if (submenu == NULL)
 
201
            submenu = tomerge;
 
202
        merge_menu(submenu, submenu->firstChild(), patern->firstChild(), mergee);
 
203
    }
 
204
 
 
205
    return;
 
206
}
 
207
 
 
208
Effect::~Effect (void)
 
209
{
 
210
    if (get_last_effect() == this)
 
211
        set_last_effect(NULL);
 
212
    if (_menu_node)
 
213
        Inkscape::GC::release(_menu_node);
 
214
    return;
 
215
}
 
216
 
 
217
bool
 
218
Effect::check (void)
 
219
{
 
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);
 
225
        _menu_node = NULL;
 
226
        return false;
 
227
    }
 
228
    return true;
 
229
}
 
230
 
 
231
bool
 
232
Effect::prefs (Inkscape::UI::View::View * doc)
 
233
{
 
234
    if (_prefDialog != NULL) {
 
235
        _prefDialog->raise();
 
236
        return true;
 
237
    }
 
238
 
 
239
    if (param_visible_count() == 0) {
 
240
        effect(doc);
 
241
        return true;
 
242
    }
 
243
 
 
244
    if (!loaded())
 
245
        set_state(Extension::STATE_LOADED);
 
246
    if (!loaded()) return false;
 
247
 
 
248
    _prefDialog = new PrefDialog(this->get_name(), this->get_help(), NULL, this);
 
249
    _prefDialog->show();
 
250
 
 
251
    return true;
 
252
}
 
253
 
 
254
/**
 
255
    \brief  The function that 'does' the effect itself
 
256
    \param  doc  The Inkscape::UI::View::View to do the effect on
 
257
 
 
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
 
262
    stack.
 
263
*/
 
264
void
 
265
Effect::effect (Inkscape::UI::View::View * doc)
 
266
{
 
267
    //printf("Execute effect\n");
 
268
    if (!loaded())
 
269
        set_state(Extension::STATE_LOADED);
 
270
    if (!loaded()) return;
 
271
 
 
272
 
 
273
    ExecutionEnv executionEnv(this, doc);
 
274
    timer->lock();
 
275
    executionEnv.run();
 
276
    if (executionEnv.wait()) {
 
277
        executionEnv.commit();
 
278
    } else {
 
279
        executionEnv.cancel();
 
280
    }
 
281
    timer->unlock();
 
282
 
 
283
    return;
 
284
}
 
285
 
 
286
/** \brief  Sets which effect was called last
 
287
    \param in_effect  The effect that has been called
 
288
    
 
289
    This function sets the static variable \c _last_effect and it
 
290
    ensures that the last effect verb is sensitive.
 
291
 
 
292
    If the \c in_effect variable is \c NULL then the last effect
 
293
    verb is made insesitive.
 
294
*/
 
295
void
 
296
Effect::set_last_effect (Effect * in_effect)
 
297
{
 
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);
 
304
    }
 
305
 
 
306
    _last_effect = in_effect;
 
307
    return;
 
308
}
 
309
 
 
310
Inkscape::XML::Node *
 
311
Effect::find_menu (Inkscape::XML::Node * menustruct, const gchar *name)
 
312
{
 
313
    if (menustruct == NULL) return false;
 
314
    for (Inkscape::XML::Node * child = menustruct;
 
315
            child != NULL;
 
316
            child = child->next()) {
 
317
        if (!strcmp(child->name(), name)) {
 
318
            return child;
 
319
        }
 
320
        Inkscape::XML::Node * firstchild = child->firstChild();
 
321
        if (firstchild != NULL) {
 
322
            Inkscape::XML::Node *found = find_menu (firstchild, name);
 
323
            if (found)
 
324
                return found;
 
325
        }
 
326
    }
 
327
    return NULL;
 
328
}
 
329
 
 
330
 
 
331
Gtk::VBox *
 
332
Effect::get_info_widget(void)
 
333
{
 
334
    return Extension::get_info_widget();
 
335
}
 
336
 
 
337
void
 
338
Effect::set_pref_dialog (PrefDialog * prefdialog)
 
339
{
 
340
    _prefDialog = prefdialog;
 
341
    return;
 
342
}
 
343
 
 
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.
 
347
 
 
348
    Calls \c make_action_helper with the \c vector.
 
349
*/
 
350
SPAction *
 
351
Effect::EffectVerb::make_action (Inkscape::UI::View::View * view)
 
352
{
 
353
    return make_action_helper(view, &vector, static_cast<void *>(this));
 
354
}
 
355
 
 
356
/** \brief  Decode the verb code and take appropriate action */
 
357
void
 
358
Effect::EffectVerb::perform( SPAction *action, void * data, void */*pdata*/ )
 
359
{
 
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;
 
364
 
 
365
    if (effect == NULL) return;
 
366
    if (current_view == NULL) return;
 
367
 
 
368
    if (ev->_showPrefs) {
 
369
        effect->prefs(current_view);
 
370
    } else {
 
371
        effect->effect(current_view);
 
372
    }
 
373
 
 
374
    return;
 
375
}
 
376
 
 
377
/**
 
378
 * Action vector to define functions called if a staticly defined file verb
 
379
 * is called.
 
380
 */
 
381
SPActionEventVector Effect::EffectVerb::vector =
 
382
            {{NULL}, Effect::EffectVerb::perform, NULL, NULL, NULL, NULL};
 
383
 
 
384
 
 
385
} }  /* namespace Inkscape, Extension */
 
386
 
 
387
/*
 
388
  Local Variables:
 
389
  mode:c++
 
390
  c-file-style:"stroustrup"
 
391
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
 
392
  indent-tabs-mode:nil
 
393
  fill-column:99
 
394
  End:
 
395
*/
 
396
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :