Code

Filters, Extensions menus
[inkscape.git] / src / extension / effect.cpp
index f2f1a0295827e9837d0943b4abc8e9746bcec957..20f0d0b3dec0eee3bbdb72b521418455e875610b 100644 (file)
 #include "desktop-handles.h"
 #include "selection.h"
 #include "sp-namedview.h"
-#include "document.h"
-#include "prefdialog.h"
+#include "desktop.h"
 #include "implementation/implementation.h"
 #include "effect.h"
+#include "execution-env.h"
 #include "timer.h"
-#include "ui/view/view.h"
 
-#include "gtkmm/messagedialog.h"
 
-#include "util/glib-list-iterators.h"
 
 /* Inkscape::Extension::Effect */
 
@@ -31,6 +28,10 @@ namespace Extension {
 
 Effect * Effect::_last_effect = NULL;
 Inkscape::XML::Node * Effect::_effects_list = NULL;
+Inkscape::XML::Node * Effect::_filters_list = NULL;
+
+#define  EFFECTS_LIST  "effects-list"
+#define  FILTERS_LIST  "filters-list"
 
 Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation * in_imp)
     : Extension(in_repr, in_imp),
@@ -38,7 +39,8 @@ Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation *
       _name_noprefs(Glib::ustring(get_name()) + _(" (No preferences)")),
       _verb(get_id(), get_name(), NULL, NULL, this, true),
       _verb_nopref(_id_noprefs.c_str(), _name_noprefs.c_str(), NULL, NULL, this, false),
-      _menu_node(NULL), _workingDialog(true)
+      _menu_node(NULL), _workingDialog(true),
+      _prefDialog(NULL)
 {
     Inkscape::XML::Node * local_effects_menu = NULL;
 
@@ -49,29 +51,33 @@ Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation *
     bool hidden = false;
 
     no_doc = false;
+    no_live_preview = false;
 
     if (repr != NULL) {
 
         for (Inkscape::XML::Node *child = sp_repr_children(repr); child != NULL; child = child->next()) {
-            if (!strcmp(child->name(), "effect")) {
-                if (child->attribute("needs-document") && !strcmp(child->attribute("needs-document"), "no")) {
+            if (!strcmp(child->name(), INKSCAPE_EXTENSION_NS "effect")) {
+                if (child->attribute("needs-document") && !strcmp(child->attribute("needs-document"), "false")) {
                   no_doc = true;
                 }
+                if (child->attribute("needs-live-preview") && !strcmp(child->attribute("needs-live-preview"), "false")) {
+                  no_live_preview = true;
+                }
                 for (Inkscape::XML::Node *effect_child = sp_repr_children(child); effect_child != NULL; effect_child = effect_child->next()) {
-                    if (!strcmp(effect_child->name(), "effects-menu")) {
+                    if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "effects-menu")) {
                         // printf("Found local effects menu in %s\n", this->get_name());
                         local_effects_menu = sp_repr_children(effect_child);
-                        if (effect_child->attribute("hidden") && !strcmp(effect_child->attribute("hidden"), "yes")) {
+                        if (effect_child->attribute("hidden") && !strcmp(effect_child->attribute("hidden"), "true")) {
                             hidden = true;
                         }
                     }
-                    if (!strcmp(effect_child->name(), "menu-name") ||
-                            !strcmp(effect_child->name(), "_menu-name")) {
+                    if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "menu-name") ||
+                            !strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "_menu-name")) {
                         // printf("Found local effects menu in %s\n", this->get_name());
                         _verb.set_name(sp_repr_children(effect_child)->content());
                     }
-                    if (!strcmp(effect_child->name(), "menu-tip") ||
-                            !strcmp(effect_child->name(), "_menu-tip")) {
+                    if (!strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "menu-tip") ||
+                            !strcmp(effect_child->name(), INKSCAPE_EXTENSION_NS "_menu-tip")) {
                         // printf("Found local effects menu in %s\n", this->get_name());
                         _verb.set_tip(sp_repr_children(effect_child)->content());
                     }
@@ -81,18 +87,29 @@ Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation *
         } // children of "inkscape-extension"
     } // if we have an XML file
 
-    if (_effects_list == NULL && INKSCAPE != NULL) {
-        find_effects_list(inkscape_get_menus(INKSCAPE));
+    if (INKSCAPE != NULL) {
+        if (_effects_list == NULL)
+            _effects_list = find_menu(inkscape_get_menus(INKSCAPE), EFFECTS_LIST);
+        if (_filters_list == NULL)
+            _filters_list = find_menu(inkscape_get_menus(INKSCAPE), FILTERS_LIST);
     }
 
-    if (_effects_list != NULL) {
+    if ((_effects_list != NULL || _filters_list != NULL)) {
         Inkscape::XML::Document *xml_doc;
         xml_doc = _effects_list->document();
         _menu_node = xml_doc->createElement("verb");
         _menu_node->setAttribute("verb-id", this->get_id(), false);
 
-        if (!hidden)
-            merge_menu(_effects_list->parent(), _effects_list, local_effects_menu, _menu_node);
+        if (!hidden) {
+            if (_filters_list &&
+                local_effects_menu && 
+                local_effects_menu->attribute("name") && 
+                !strcmp(local_effects_menu->attribute("name"), _("Filters"))) {
+                merge_menu(_filters_list->parent(), _filters_list, sp_repr_children(local_effects_menu), _menu_node);
+            } else if (_effects_list) {
+                merge_menu(_effects_list->parent(), _effects_list, local_effects_menu, _menu_node);
+            }
+        }
     }
 
     return;
@@ -133,12 +150,13 @@ Effect::merge_menu (Inkscape::XML::Node * base,
 
     if (start != NULL) {
         Inkscape::XML::Node * menupass;
-        for (menupass = start->next(); menupass != NULL; menupass = menupass->next()) {
+        for (menupass = start; menupass != NULL && strcmp(menupass->name(), "separator"); menupass = menupass->next()) {
             gchar const * compare_char = NULL;
             if (!strcmp(menupass->name(), "verb")) {
                 gchar const * verbid = menupass->attribute("verb-id");
                 Inkscape::Verb * verb = Inkscape::Verb::getbyid(verbid);
                 if (verb == NULL) {
+                                       g_warning("Unable to find verb '%s' which is referred to in the menus.", verbid);
                     continue;
                 }
                 compare_char = verb->get_name();
@@ -148,6 +166,8 @@ Effect::merge_menu (Inkscape::XML::Node * base,
                     compare_char = menupass->attribute("_name");
             }
 
+            position = menupass->position() + 1;
+
             /* This will cause us to skip tags we don't understand */
             if (compare_char == NULL) {
                 continue;
@@ -189,6 +209,8 @@ Effect::~Effect (void)
 {
     if (get_last_effect() == this)
         set_last_effect(NULL);
+    if (_menu_node)
+        Inkscape::GC::release(_menu_node);
     return;
 }
 
@@ -206,227 +228,25 @@ Effect::check (void)
     return true;
 }
 
-class ExecutionEnv {
-private:
-    Effect * _effect;
-    Gtk::Dialog * _visibleDialog;
-    bool _prefsVisible;
-    bool _finished;
-    bool _humanWait;
-    bool _canceled;
-    bool _prefsChanged;
-    Glib::RefPtr<Glib::MainLoop> _mainloop;
-    Inkscape::UI::View::View * _doc;
-    std::list<Glib::ustring> _selected;
-
-public:
-    void run (void);
-
-    ExecutionEnv (Effect * effect, Inkscape::UI::View::View * doc, Gtk::Widget * controls = NULL) :
-        _effect(effect),
-        _visibleDialog(NULL),
-        _prefsVisible(false),
-        _finished(false),
-        _humanWait(false),
-        _canceled(false),
-        _prefsChanged(false),
-        _doc(doc) {
-
-        SPDesktop *desktop = (SPDesktop *)_doc;
-        sp_namedview_document_from_window(desktop);
-
-        if (desktop != NULL) {
-            Inkscape::Util::GSListConstIterator<SPItem *> selected =
-                 sp_desktop_selection(desktop)->itemList();
-            while ( selected != NULL ) {
-                Glib::ustring selected_id;
-                selected_id = SP_OBJECT_ID(*selected);
-                _selected.insert(_selected.end(), selected_id);
-                //std::cout << "Selected: " << selected_id << std::endl;
-                ++selected;
-            }
-        }
-
-        _mainloop = Glib::MainLoop::create(false);
-
-        if (controls != NULL) {
-            createPrefsDialog(controls);
-        } else {
-            createWorkingDialog();
-        }
-
-        return;
-    }
-
-    ~ExecutionEnv (void) {
-        if (_visibleDialog != NULL) {
-            delete _visibleDialog;
-        }
-        return;
-    }
-
-    void preferencesChange (void) {
-        //std::cout << "Preferences are a changin'" << std::endl;
-        _prefsChanged = true;
-        if (_humanWait) {
-            _mainloop->quit();
-            documentCancel();
-            _humanWait = false;
-        } else {
-            processingCancel();
-            documentCancel();
-        }
-        return;
-    }
-
-private:
-    void createPrefsDialog (Gtk::Widget * controls) {
-        if (_visibleDialog != NULL) {
-            delete _visibleDialog;
-        }
-
-        _visibleDialog = new PrefDialog(_effect->get_name(), _effect->get_help(), controls);
-        _visibleDialog->signal_response().connect(sigc::mem_fun(this, &ExecutionEnv::preferencesResponse));
-        _visibleDialog->show();
-
-        _prefsVisible = true;
-        return;
-    }
-
-    void createWorkingDialog (void) {
-        if (_visibleDialog != NULL) {
-            delete _visibleDialog;
-        }
-
-        gchar * dlgmessage = g_strdup_printf(_("The effect '%s' is working on your document.  Please wait."), _effect->get_name());
-        _visibleDialog = new Gtk::MessageDialog(dlgmessage,
-                                   false, // use markup
-                                   Gtk::MESSAGE_INFO,
-                                   Gtk::BUTTONS_CANCEL,
-                                   true); // modal
-        _visibleDialog->signal_response().connect(sigc::mem_fun(this, &ExecutionEnv::workingCanceled));
-        g_free(dlgmessage);
-        _visibleDialog->show();
-
-        _prefsVisible = false;
-        return;
-    }
-
-    void workingCanceled (const int resp) {
-        processingCancel();
-        documentCancel();
-        _finished = true;
-        return;
-    }
-
-    void preferencesResponse (const int resp) {
-        if (resp == Gtk::RESPONSE_OK) {
-            if (_humanWait) {
-                documentCommit();
-                _mainloop->quit();
-                _finished = true;
-            } else {
-                createWorkingDialog();
-            }
-        } else {
-            if (_humanWait) {
-                _mainloop->quit();
-            } else {
-                processingCancel();
-            }
-            documentCancel();
-            _finished = true;
-        }
-        return;
-    }
-
-    void processingComplete(void) {
-        //std::cout << "Processing Complete" << std::endl;
-        if (_prefsChanged) { return; } // do it all again
-        if (_prefsVisible) {
-            _humanWait = true;
-        } else {
-            documentCommit();
-            _finished = true;
-        }
-        return;
-    }
-
-    void processingCancel (void) {
-        _effect->get_imp()->cancelProcessing();
-        return;
-    }
-
-    void documentCancel (void) {
-        _canceled = true;
-        return;
-    }
-
-    void documentCommit (void) {
-        sp_document_done(_doc->doc(), SP_VERB_NONE, _(_effect->get_name()));
-        Effect::set_last_effect(_effect);
-        return;
-    }
-    
-    void reselect (void) {
-        SPDocument * doc = _doc->doc();
-
-        SPDesktop *desktop = (SPDesktop *)_doc;
-        sp_namedview_document_from_window(desktop);
-
-        if (desktop == NULL) { return; }
-
-        Inkscape::Selection * selection = sp_desktop_selection(desktop);
-
-        for (std::list<Glib::ustring>::iterator i = _selected.begin(); i != _selected.end(); i++) {
-            selection->add(doc->getObjectById(i->c_str()));
-        }
-
-        return;
-    }
-};
-
-void
-ExecutionEnv::run (void) {
-    while (!_finished) {
-        _canceled = false;
-        if (_humanWait) {
-            _mainloop->run();
-        } else {
-            _prefsChanged = false;
-            _effect->get_imp()->effect(_effect, _doc);
-            processingComplete();
-        }
-        if (_canceled) {
-            sp_document_cancel(_doc->doc());
-            reselect();
-        }
-    }
-    return;
-}
-
 bool
 Effect::prefs (Inkscape::UI::View::View * doc)
 {
-    if (!loaded())
-        set_state(Extension::STATE_LOADED);
-    if (!loaded()) return false;
-
-    sigc::signal<void> changeSignal;
+    if (_prefDialog != NULL) {
+        _prefDialog->raise();
+        return true;
+    }
 
-    Gtk::Widget * controls;
-    controls = imp->prefs_effect(this, doc, &changeSignal);
-    if (controls == NULL) {
-        // std::cout << "No preferences for Effect" << std::endl;
+    if (param_visible_count() == 0) {
+        effect(doc);
         return true;
     }
 
-    ExecutionEnv executionEnv(this, doc, controls);
-    changeSignal.connect(sigc::mem_fun(executionEnv, &ExecutionEnv::preferencesChange));
+    if (!loaded())
+        set_state(Extension::STATE_LOADED);
+    if (!loaded()) return false;
 
-    timer->lock();
-    executionEnv.run();
-    timer->unlock();
+    _prefDialog = new PrefDialog(this->get_name(), this->get_help(), NULL, this);
+    _prefDialog->show();
 
     return true;
 }
@@ -444,13 +264,21 @@ Effect::prefs (Inkscape::UI::View::View * doc)
 void
 Effect::effect (Inkscape::UI::View::View * doc)
 {
+    //printf("Execute effect\n");
     if (!loaded())
         set_state(Extension::STATE_LOADED);
     if (!loaded()) return;
 
 
-    ExecutionEnv executionEnv(this, doc, NULL);
+    ExecutionEnv executionEnv(this, doc);
+    timer->lock();
     executionEnv.run();
+    if (executionEnv.wait()) {
+        executionEnv.commit();
+    } else {
+        executionEnv.cancel();
+    }
+    timer->unlock();
 
     return;
 }
@@ -479,33 +307,40 @@ Effect::set_last_effect (Effect * in_effect)
     return;
 }
 
-#define  EFFECTS_LIST  "effects-list"
-
-bool
-Effect::find_effects_list (Inkscape::XML::Node * menustruct)
+Inkscape::XML::Node *
+Effect::find_menu (Inkscape::XML::Node * menustruct, const gchar *name)
 {
     if (menustruct == NULL) return false;
     for (Inkscape::XML::Node * child = menustruct;
             child != NULL;
             child = child->next()) {
-        if (!strcmp(child->name(), EFFECTS_LIST)) {
-            _effects_list = child;
-            return true;
+        if (!strcmp(child->name(), name)) {
+            return child;
         }
         Inkscape::XML::Node * firstchild = child->firstChild();
-        if (firstchild != NULL)
-            if (find_effects_list(firstchild))
-                return true;
+        if (firstchild != NULL) {
+            Inkscape::XML::Node *found = find_menu (firstchild, name);
+            if (found)
+                return found;
+        }
     }
-    return false;
+    return NULL;
 }
 
+
 Gtk::VBox *
 Effect::get_info_widget(void)
 {
     return Extension::get_info_widget();
 }
 
+void
+Effect::set_pref_dialog (PrefDialog * prefdialog)
+{
+    _prefDialog = prefdialog;
+    return;
+}
+
 /** \brief  Create an action for a \c EffectVerb
     \param  view  Which view the action should be created for
     \return The built action.
@@ -520,7 +355,7 @@ Effect::EffectVerb::make_action (Inkscape::UI::View::View * view)
 
 /** \brief  Decode the verb code and take appropriate action */
 void
-Effect::EffectVerb::perform (SPAction *action, void * data, void *pdata)
+Effect::EffectVerb::perform( SPAction *action, void * data, void */*pdata*/ )
 {
     Inkscape::UI::View::View * current_view = sp_action_get_view(action);
 //  SPDocument * current_document = current_view->doc;