Code

display/inkscape-cairo.h: Supply missing #includes/declarations so that we don't...
[inkscape.git] / src / extension / effect.cpp
index 78380dde1d71a74d4f36909d46535df6cbf5dbdb..615aeac7ae90d4ec006ea92d49f6992eee4597f7 100644 (file)
@@ -2,18 +2,24 @@
  * Authors:
  *   Ted Gould <ted@gould.cx>
  *
- * Copyright (C) 2002-2005 Authors
+ * Copyright (C) 2002-2007 Authors
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
 #include "inkscape-private.h"
 #include "helper/action.h"
-#include "document.h"
-#include "prefdialog.h"
+#include "ui/view/view.h"
+#include "desktop-handles.h"
+#include "selection.h"
+#include "sp-namedview.h"
+#include "desktop.h"
 #include "implementation/implementation.h"
 #include "effect.h"
-#include "ui/view/view.h"
+#include "execution-env.h"
+#include "timer.h"
+
+
 
 /* Inkscape::Extension::Effect */
 
@@ -24,7 +30,13 @@ Effect * Effect::_last_effect = NULL;
 Inkscape::XML::Node * Effect::_effects_list = NULL;
 
 Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation * in_imp)
-    : Extension(in_repr, in_imp), _verb(get_id(), get_name(), NULL, NULL, this), _menu_node(NULL)
+    : Extension(in_repr, in_imp),
+      _id_noprefs(Glib::ustring(get_id()) + ".noprefs"),
+      _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),
+      _prefDialog(NULL)
 {
     Inkscape::XML::Node * local_effects_menu = NULL;
 
@@ -32,15 +44,38 @@ Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation *
     if (!strcmp(this->get_id(), "org.inkscape.filter.dropshadow"))
         return;
 
+    bool hidden = false;
+
+    no_doc = false;
+    no_live_preview = false;
+
     if (repr != NULL) {
-        Inkscape::XML::Node * child_repr;
-
-        for (child_repr = sp_repr_children(repr); child_repr != NULL; child_repr = child_repr->next()) {
-            if (!strcmp(child_repr->name(), "effect")) {
-                for (child_repr = sp_repr_children(child_repr); child_repr != NULL; child_repr = child_repr->next()) {
-                    if (!strcmp(child_repr->name(), "effects-menu")) {
-                        printf("Found local effects menu in %s\n", this->get_name());
-                        local_effects_menu = sp_repr_children(child_repr);
+
+        for (Inkscape::XML::Node *child = sp_repr_children(repr); child != NULL; child = child->next()) {
+            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(), 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"), "true")) {
+                            hidden = true;
+                        }
+                    }
+                    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(), 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());
                     }
                 } // children of "effect"
                 break; // there can only be one effect
@@ -48,16 +83,18 @@ Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation *
         } // children of "inkscape-extension"
     } // if we have an XML file
 
-    if (_effects_list == NULL)
+    if (_effects_list == NULL && INKSCAPE != NULL) {
         find_effects_list(inkscape_get_menus(INKSCAPE));
+    }
 
     if (_effects_list != NULL) {
-        _menu_node = sp_repr_new("verb");
+        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);
 
-        merge_menu(_effects_list, local_effects_menu, _menu_node);
-        if (!strcmp(this->get_id(), "org.ekips.filter.interp"))
-            sp_repr_print(_effects_list->parent());
+        if (!hidden)
+            merge_menu(_effects_list->parent(), _effects_list, local_effects_menu, _menu_node);
     }
 
     return;
@@ -65,10 +102,12 @@ Effect::Effect (Inkscape::XML::Node * in_repr, Implementation::Implementation *
 
 void
 Effect::merge_menu (Inkscape::XML::Node * base,
+                    Inkscape::XML::Node * start,
                     Inkscape::XML::Node * patern,
                     Inkscape::XML::Node * mergee) {
     Glib::ustring mergename;
     Inkscape::XML::Node * tomerge = NULL;
+    Inkscape::XML::Node * submenu = NULL;
 
     /* printf("Merge menu with '%s' '%s' '%s'\n",
             base != NULL ? base->name() : "NULL",
@@ -83,48 +122,66 @@ Effect::merge_menu (Inkscape::XML::Node * base,
         gchar const * menuname = patern->attribute("name");
         if (menuname == NULL) menuname = patern->attribute("_name");
         if (menuname == NULL) return;
-
-        tomerge = sp_repr_new("submenu");
+        
+        Inkscape::XML::Document *xml_doc;
+        xml_doc = base->document();
+        tomerge = xml_doc->createElement("submenu");
         tomerge->setAttribute("name", menuname, false);
 
         mergename = _(menuname);
     }
 
-    base->parent()->appendChild(tomerge);
-    Inkscape::GC::release(tomerge);
-
-    Inkscape::XML::Node * menupass;
-    for (menupass = base->next(); menupass != NULL; 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) {
-                printf("Unable to find verb\n");
-                return;
+    int position = -1;
+
+    if (start != NULL) {
+        Inkscape::XML::Node * menupass;
+        for (menupass = start->next(); menupass != NULL; 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) {
+                    continue;
+                }
+                compare_char = verb->get_name();
+            } else if (!strcmp(menupass->name(), "submenu")) {
+                compare_char = menupass->attribute("name");
+                if (compare_char == NULL)
+                    compare_char = menupass->attribute("_name");
             }
-            compare_char = verb->get_name();
-        } else { // submenu
-            compare_char = menupass->attribute("name");
-            if (compare_char == NULL)
-                compare_char = menupass->attribute("_name");
-        }
 
-        if (compare_char == NULL) {
-            printf("Nothing to compare against\n");
-            return;
-        }
+            /* This will cause us to skip tags we don't understand */
+            if (compare_char == NULL) {
+                continue;
+            }
 
-        Glib::ustring compare(_(compare_char));
+            Glib::ustring compare(_(compare_char));
 
-        if (mergename < compare) {
-            tomerge->setPosition(menupass->position());
-            break;
-        }
+            if (mergename == compare) {
+                Inkscape::GC::release(tomerge);
+                tomerge = NULL;
+                submenu = menupass;
+                break;
+            }
+
+            if (mergename < compare) {
+                position = menupass->position();
+                break;
+            }
+        } // for menu items
+    } // start != NULL
+
+    if (tomerge != NULL) {
+        base->appendChild(tomerge);
+        Inkscape::GC::release(tomerge);
+        if (position != -1)
+            tomerge->setPosition(position);
     }
 
     if (patern != NULL) {
-        merge_menu(tomerge, patern->firstChild(), mergee);
+        if (submenu == NULL)
+            submenu = tomerge;
+        merge_menu(submenu, submenu->firstChild(), patern->firstChild(), mergee);
     }
 
     return;
@@ -154,26 +211,24 @@ Effect::check (void)
 bool
 Effect::prefs (Inkscape::UI::View::View * doc)
 {
-    if (!loaded())
-        set_state(Extension::STATE_LOADED);
-    if (!loaded()) return false;
-
-    Gtk::Widget * controls;
-    controls = imp->prefs_effect(this, doc);
-    if (controls == NULL) {
-        // std::cout << "No preferences for Effect" << std::endl;
+    if (_prefDialog != NULL) {
+        _prefDialog->raise();
         return true;
     }
 
-    PrefDialog * dialog = new PrefDialog(this->get_name(), controls);
-    int response = dialog->run();
-    dialog->hide();
+    if (param_visible_count() == 0) {
+        effect(doc);
+        return true;
+    }
 
-    delete dialog;
+    if (!loaded())
+        set_state(Extension::STATE_LOADED);
+    if (!loaded()) return false;
 
-    if (response == Gtk::RESPONSE_OK) return true;
+    _prefDialog = new PrefDialog(this->get_name(), this->get_help(), NULL, this);
+    _prefDialog->show();
 
-    return false;
+    return true;
 }
 
 /**
@@ -189,18 +244,34 @@ 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;
 
-    set_last_effect(this);
-    imp->effect(this, doc);
 
-    sp_document_done(doc->doc());
+    ExecutionEnv executionEnv(this, doc);
+    timer->lock();
+    executionEnv.run();
+    if (executionEnv.wait()) {
+        executionEnv.commit();
+    } else {
+        executionEnv.cancel();
+    }
+    timer->unlock();
 
     return;
 }
 
+/** \brief  Sets which effect was called last
+    \param in_effect  The effect that has been called
+    
+    This function sets the static variable \c _last_effect and it
+    ensures that the last effect verb is sensitive.
+
+    If the \c in_effect variable is \c NULL then the last effect
+    verb is made insesitive.
+*/
 void
 Effect::set_last_effect (Effect * in_effect)
 {
@@ -237,6 +308,19 @@ Effect::find_effects_list (Inkscape::XML::Node * menustruct)
     return false;
 }
 
+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.
@@ -246,23 +330,26 @@ Effect::find_effects_list (Inkscape::XML::Node * menustruct)
 SPAction *
 Effect::EffectVerb::make_action (Inkscape::UI::View::View * view)
 {
-    return make_action_helper(view, &vector, static_cast<void *>(_effect));
+    return make_action_helper(view, &vector, static_cast<void *>(this));
 }
 
 /** \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;
-    Effect * effect = reinterpret_cast<Effect *>(data);
+    Effect::EffectVerb * ev = reinterpret_cast<Effect::EffectVerb *>(data);
+    Effect * effect = ev->_effect;
 
     if (effect == NULL) return;
     if (current_view == NULL) return;
 
-    // std::cout << "Executing: " << effect->get_name() << std::endl;
-    if (effect->prefs(current_view))
+    if (ev->_showPrefs) {
+        effect->prefs(current_view);
+    } else {
         effect->effect(current_view);
+    }
 
     return;
 }
@@ -272,7 +359,7 @@ Effect::EffectVerb::perform (SPAction *action, void * data, void *pdata)
  * is called.
  */
 SPActionEventVector Effect::EffectVerb::vector =
-            {{NULL},Effect::EffectVerb::perform, NULL, NULL, NULL};
+            {{NULL}, Effect::EffectVerb::perform, NULL, NULL, NULL, NULL};
 
 
 } }  /* namespace Inkscape, Extension */