Code

Added notebook (tabs) support for Effects. Now you can specify a notebook parameter...
authorjohanengelen <johanengelen@users.sourceforge.net>
Thu, 14 Sep 2006 22:14:19 +0000 (22:14 +0000)
committerjohanengelen <johanengelen@users.sourceforge.net>
Thu, 14 Sep 2006 22:14:19 +0000 (22:14 +0000)
src/extension/parameter.cpp
src/extension/paramnotebook.cpp [new file with mode: 0644]
src/extension/paramnotebook.h [new file with mode: 0644]

index a034022d9f8a5b2413626569ffa86d35ad516010..a821a626dfec18909790205504af6d35b1496974 100644 (file)
@@ -3,10 +3,11 @@
  */
 
 /*
- * Authors:
+ * Author:
  *   Ted Gould <ted@gould.cx>
  *
- * Copyright (C) 2005-2006 Authors
+ * Copyright (C) 2006 Johan Engelen <johan@shouraizou.nl>
+ * Copyright (C) 2005-2006 Author
  *
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
@@ -30,6 +31,7 @@
 #include "sp-object.h"
 
 #include "parameter.h"
+#include "paramnotebook.h"
 
 /** \brief  The root directory in the preferences database for extension
             related parameters. */
@@ -239,6 +241,7 @@ public:
     Glib::ustring * string (void);
 }; /* class ParamEnum */
 
+
 /**
     \return None
     \brief  This function creates a parameter that can be used later.  This
@@ -310,6 +313,8 @@ Parameter::make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension *
         param = new ParamDescription(name, guitext, desc, scope, in_ext, in_repr);
     } else if (!strcmp(type, "enum")) {
         param = new ParamEnum(name, guitext, desc, scope, in_ext, in_repr);
+    } else if (!strcmp(type, "notebook")) {
+        param = new ParamNotebook(name, guitext, desc, scope, in_ext, in_repr);
     }
 
     /* Note: param could equal NULL */
diff --git a/src/extension/paramnotebook.cpp b/src/extension/paramnotebook.cpp
new file mode 100644 (file)
index 0000000..a44f836
--- /dev/null
@@ -0,0 +1,431 @@
+/** \file\r
+ * Notebook and NotebookPage parameters for extensions.\r
+ */\r
+\r
+/*\r
+ * Author:\r
+ *   Johan Engelen <johan@shouraizou.nl>\r
+ *\r
+ * Copyright (C) 2006 Author\r
+ *\r
+ * Released under GNU GPL, read the file 'COPYING' for more information\r
+ */\r
+\r
+#ifdef HAVE_CONFIG_H\r
+# include "config.h"\r
+#endif\r
+\r
+\r
+#include <gtkmm/adjustment.h>\r
+#include <gtkmm/box.h>\r
+#include <gtkmm/spinbutton.h>\r
+#include <gtkmm/notebook.h>\r
+#include <gtkmm/tooltips.h>\r
+\r
+#include <glibmm/i18n.h>\r
+\r
+#include <xml/node.h>\r
+\r
+#include "extension.h"\r
+#include "prefs-utils.h"\r
+#include "document-private.h"\r
+#include "sp-object.h"\r
+\r
+#include "paramnotebook.h"\r
+\r
+/** \brief  The root directory in the preferences database for extension\r
+            related parameters. */\r
+#define PREF_DIR "extensions"\r
+\r
+namespace Inkscape {\r
+namespace Extension {\r
+\r
+\r
+// \brief  A class to represent the pages of a notebookparameter of an extension\r
+class ParamNotebookPage : public Parameter {\r
+private:\r
+    GSList * parameters; /**< A table to store the parameters for this page.\r
+                              This only gets created if there are parameters on this\r
+                              page */\r
+    Gtk::Tooltips _tooltips;\r
+    \r
+public:\r
+    static ParamNotebookPage * makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext);\r
+\r
+    ParamNotebookPage(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);\r
+    ~ParamNotebookPage(void);\r
+    Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);\r
+    Glib::ustring * paramString (void);\r
+    gchar * get_guitext (void) {return _text;};\r
+    \r
+}; /* class ParamNotebookPage */\r
+\r
+\r
+ParamNotebookPage::ParamNotebookPage (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :\r
+    Parameter(name, guitext, desc, scope, ext)\r
+{\r
+    parameters = NULL;\r
+    \r
+    // Read XML to build page\r
+    if (xml != NULL) {\r
+        Inkscape::XML::Node *child_repr = sp_repr_children(xml);\r
+        while (child_repr != NULL) {\r
+            char const * chname = child_repr->name();\r
+            if (chname[0] == '_') /* Allow _ for translation of tags */\r
+                chname++;\r
+            if (!strcmp(chname, "param") || !strcmp(chname, "_param")) {\r
+                Parameter * param;\r
+                param = Parameter::make(child_repr, ext);\r
+                if (param != NULL)\r
+                    parameters = g_slist_append(parameters, param);\r
+            }\r
+            child_repr = sp_repr_next(child_repr);\r
+        }\r
+    }\r
+    \r
+    return;\r
+}\r
+\r
+ParamNotebookPage::~ParamNotebookPage (void)\r
+{\r
+    //destroy parameters\r
+    for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {\r
+        Parameter * param = reinterpret_cast<Parameter *>(list->data);\r
+        delete param;\r
+    }\r
+    g_slist_free(parameters);\r
+}\r
+\r
+/** \brief  Return the value as a string */\r
+Glib::ustring *\r
+ParamNotebookPage::paramString (void)\r
+{\r
+    Glib::ustring * param_string = new Glib::ustring("");\r
+\r
+    for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {\r
+        Parameter * param = reinterpret_cast<Parameter *>(list->data);\r
+\r
+        *param_string += " --";\r
+        *param_string += param->name();\r
+        *param_string += "=";\r
+        Glib::ustring * paramstr = param->string();\r
+        *param_string += *paramstr;\r
+        delete paramstr;\r
+    }\r
+\r
+    return param_string;\r
+}\r
+\r
+\r
+/**\r
+    \return None\r
+    \brief  This function creates a page that can be used later.  This\r
+            is typically done in the creation of the notebook and defined\r
+            in the XML file describing the extension (it's private so people\r
+            have to use the system) :)\r
+    \param  in_repr  The XML describing the page\r
+\r
+    This function first grabs all of the data out of the Repr and puts\r
+    it into local variables.  Actually, these are just pointers, and the\r
+    data is not duplicated so we need to be careful with it.  If there\r
+    isn't a name in the XML, then no page is created as\r
+    the function just returns.\r
+\r
+    From this point on, we're pretty committed as we've allocated an\r
+    object and we're starting to fill it.  The name is set first, and\r
+    is created with a strdup to actually allocate memory for it.  Then\r
+    there is a case statement (roughly because strcmp requires 'ifs')\r
+    based on what type of parameter this is.  Depending which type it\r
+    is, the value is interpreted differently, but they are relatively\r
+    straight forward.  In all cases the value is set to the default\r
+    value from the XML and the type is set to the interpreted type.\r
+*/\r
+ParamNotebookPage *\r
+ParamNotebookPage::makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)\r
+{\r
+    const char * name;\r
+    const char * guitext;\r
+    const char * desc;\r
+    const char * scope_str;\r
+    Parameter::_scope_t scope = Parameter::SCOPE_USER;\r
+\r
+    name = in_repr->attribute("name");\r
+    guitext = in_repr->attribute("gui-text");\r
+    if (guitext == NULL)\r
+        guitext = in_repr->attribute("_gui-text");\r
+    desc = in_repr->attribute("gui-description");\r
+    if (desc == NULL)\r
+        desc = in_repr->attribute("_gui-description");\r
+    scope_str = in_repr->attribute("scope");\r
+\r
+    /* In this case we just don't have enough information */\r
+    if (name == NULL) {\r
+        return NULL;\r
+    }\r
+\r
+    if (scope_str != NULL) {\r
+        if (!strcmp(scope_str, "user")) {\r
+            scope = Parameter::SCOPE_USER;\r
+        } else if (!strcmp(scope_str, "document")) {\r
+            scope = Parameter::SCOPE_DOCUMENT;\r
+        } else if (!strcmp(scope_str, "node")) {\r
+            scope = Parameter::SCOPE_NODE;\r
+        }\r
+    }\r
+\r
+    ParamNotebookPage * page = new ParamNotebookPage(name, guitext, desc, scope, in_ext, in_repr);\r
+    \r
+    /* Note: page could equal NULL */\r
+    return page;\r
+}\r
+\r
+\r
+\r
+/**\r
+    \brief  Creates a notebookpage widget for a notebook\r
+\r
+    Builds a notebook page (a vbox) and puts parameters on it.\r
+*/\r
+Gtk::Widget *\r
+ParamNotebookPage::get_widget (SPDocument * doc, Inkscape::XML::Node * node)\r
+{\r
+    Gtk::VBox * vbox = Gtk::manage(new Gtk::VBox);\r
+    vbox->set_border_width(5);  \r
+    \r
+    // add parameters onto page (if any)    \r
+    for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {\r
+        Parameter * param = reinterpret_cast<Parameter *>(list->data);\r
+        Gtk::Widget * widg = param->get_widget(doc, node);\r
+        gchar const * tip = param->get_tooltip();\r
+        \r
+        vbox->pack_start(*widg, true, true, 2);\r
+        if (tip != NULL) {\r
+            _tooltips.set_tip(*widg, Glib::ustring(tip));\r
+            // printf("Setting tooltip: %s\n", tooltip);\r
+        }\r
+    }\r
+        \r
+    vbox->show();\r
+    \r
+    return dynamic_cast<Gtk::Widget *>(vbox);\r
+}\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+\r
+ParamNotebook::ParamNotebook (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :\r
+    Parameter(name, guitext, desc, scope, ext)\r
+{\r
+    pages = NULL;\r
+    \r
+    // Read XML tree to add pages:\r
+    // printf("Extension Constructor: ");\r
+    if (xml != NULL) {\r
+        Inkscape::XML::Node *child_repr = sp_repr_children(xml);\r
+        while (child_repr != NULL) {\r
+            char const * chname = child_repr->name();\r
+            if (chname[0] == '_') /* Allow _ for translation of tags */\r
+                chname++;\r
+            if (!strcmp(chname, "page")) {\r
+                ParamNotebookPage * page;\r
+                page = ParamNotebookPage::makepage(child_repr, ext);\r
+                if (page != NULL) pages = g_slist_append(pages, page);\r
+            }\r
+            child_repr = sp_repr_next(child_repr);\r
+        }\r
+    }\r
+    \r
+    // Initialize _value with the current page\r
+    const char * defaultval = NULL;\r
+    // set first page as default\r
+    if (pages != NULL) {\r
+        ParamNotebookPage * defpage = reinterpret_cast<ParamNotebookPage *>(pages->data);\r
+        defaultval = defpage->name();\r
+    }\r
+\r
+    gchar * pref_name = this->pref_name();\r
+    const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);\r
+    g_free(pref_name);\r
+\r
+    if (paramval != NULL)\r
+        defaultval = paramval;\r
+    if (defaultval != NULL)\r
+        _value = g_strdup(defaultval);  // allocate space for _value\r
+        \r
+    return;\r
+}\r
+\r
+ParamNotebook::~ParamNotebook (void)\r
+{\r
+    //destroy pages\r
+    for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {\r
+        ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);\r
+        delete page;\r
+    }\r
+    g_slist_free(pages);\r
+\r
+    g_free(_value);\r
+}\r
+\r
+\r
+/** \brief  A function to set the \c _value\r
+    \param  in   The number of the page which value must be set\r
+    \param  doc  A document that should be used to set the value.\r
+    \param  node The node where the value may be placed\r
+\r
+    This function sets the internal value, but it also sets the value\r
+    in the preferences structure.  To put it in the right place, \c PREF_DIR\r
+    and \c pref_name() are used.\r
+\r
+    To copy the data into _value the old memory must be free'd first.\r
+    It is important to note that \c g_free handles \c NULL just fine.  Then\r
+    the passed in value is duplicated using \c g_strdup().\r
+*/\r
+const gchar *\r
+ParamNotebook::set (const int in, SPDocument * doc, Inkscape::XML::Node * node)\r
+{\r
+    ParamNotebookPage * page = NULL;\r
+    int i = 0;\r
+    for (GSList * list = pages; (list != NULL) && (i <= in); list = g_slist_next(list)) {\r
+        page = reinterpret_cast<ParamNotebookPage *>(list->data);\r
+        i++;\r
+    }\r
+    \r
+    if (page == NULL) return _value;\r
+   \r
+    if (_value != NULL) g_free(_value);\r
+    _value = g_strdup(page->name());\r
+\r
+    gchar * prefname = this->pref_name();\r
+    prefs_set_string_attribute(PREF_DIR, prefname, _value);\r
+    g_free(prefname);\r
+\r
+    return _value;\r
+}\r
+\r
+\r
+/**\r
+    \brief  A function to get the currentpage and the parameters in a string form\r
+    \return A string with the 'value' and all the parameters on all pages as command line arguments\r
+\r
+    This is really a hack. The function is called by Extension::paramString() to build\r
+    the commandline string like: '--param1name=\"param1value\" --param2name=\"param2value\" ...'\r
+    Extension::paramString expects this function to return '\"param1value\"'; but instead, \r
+    this function returns: '\"param1value\" --page1param1name=\"page1param1value\" ...'\r
+\r
+    \TODO  Do this better. For example, make Parameter::paramString() that returns '--name=\"value\"'\r
+    instead of just returning '\"value\"'.\r
+*/\r
+Glib::ustring *\r
+ParamNotebook::string (void)\r
+{\r
+    Glib::ustring * param_string = new Glib::ustring("");\r
+\r
+    *param_string += "\"";\r
+    *param_string += _value;  // the name of the current page\r
+    *param_string += "\"";\r
+\r
+    for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {\r
+        ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);\r
+\r
+        Glib::ustring * pageparamstr = page->paramString();\r
+        *param_string += *pageparamstr;\r
+        delete pageparamstr;\r
+    }\r
+    \r
+    // this function is called when the user pressed OK. This means the dialog will close\r
+    // very soon, and we should deactivate the 'switch-page' hook, so the last page is remembered.\r
+       \r
+\r
+    return param_string;\r
+}\r
+\r
+/** \brief  A special category of Gtk::Notebook to handle notebook parameters */\r
+class ParamNotebookWdg : public Gtk::Notebook {\r
+private:\r
+    ParamNotebook * _pref;\r
+    SPDocument * _doc;\r
+    Inkscape::XML::Node * _node;\r
+public:\r
+    /** \brief  Build a notebookpage preference for the given parameter\r
+        \param  pref  Where to get the string (pagename) from, and where to put it\r
+                      when it changes.\r
+    */\r
+    ParamNotebookWdg (ParamNotebook * pref, SPDocument * doc, Inkscape::XML::Node * node) :\r
+        Gtk::Notebook(), _pref(pref), _doc(doc), _node(node), activated(false) {\r
+        // don't have to set the correct page: this is done in ParamNotebook::get_widget.\r
+        // hook function\r
+        this->signal_switch_page().connect(sigc::mem_fun(this, &ParamNotebookWdg::changed_page));\r
+        return;\r
+    };\r
+    void changed_page(GtkNotebookPage *page, guint pagenum);\r
+    bool activated;\r
+};\r
+\r
+/** \brief  Respond to the selected page of notebook changing\r
+    This function responds to the changing by reporting it to\r
+    ParamNotebook. The change is only reported when the notebook\r
+    is actually visible. This to exclude 'fake' changes when the\r
+    notebookpages are added or removed.\r
+*/\r
+void\r
+ParamNotebookWdg::changed_page(GtkNotebookPage *page,\r
+                                   guint pagenum)\r
+{\r
+    if (is_visible()) {\r
+        _pref->set((int)pagenum, _doc, _node);\r
+    }\r
+    return;\r
+}\r
+\r
+\r
+\r
+/**\r
+    \brief  Creates a Notebook widget for a notebook parameter\r
+\r
+    Builds a notebook and puts pages in it.\r
+*/\r
+Gtk::Widget *\r
+ParamNotebook::get_widget (SPDocument * doc, Inkscape::XML::Node * node)\r
+{\r
+    ParamNotebookWdg * nb = Gtk::manage(new ParamNotebookWdg(this, doc, node));\r
+\r
+    // add pages (if any)    \r
+    int i = -1;\r
+    int pagenr = i;\r
+    for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {\r
+        i++;  \r
+        ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);\r
+        Gtk::Widget * widg = page->get_widget(doc, node);\r
+        nb->append_page(*widg, _(page->get_guitext()));\r
+        if (!strcmp(_value, page->name())) {\r
+            pagenr = i; // this is the page to be displayed?\r
+        }\r
+    }\r
+\r
+    nb->show();\r
+    \r
+    if (pagenr >= 0) nb->set_current_page(pagenr);\r
+\r
+    return dynamic_cast<Gtk::Widget *>(nb);\r
+}\r
+\r
+\r
+}  /* namespace Extension */\r
+}  /* namespace Inkscape */\r
+\r
+/*\r
+  Local Variables:\r
+  mode:c++\r
+  c-file-style:"stroustrup"\r
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
+  indent-tabs-mode:nil\r
+  fill-column:99\r
+  End:\r
+*/\r
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r
diff --git a/src/extension/paramnotebook.h b/src/extension/paramnotebook.h
new file mode 100644 (file)
index 0000000..a781157
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef __INK_EXTENSION_PARAMNOTEBOOK_H__\r
+#define __INK_EXTENSION_PARAMNOTEBOOK_H__\r
+\r
+/** \file\r
+ * Notebook parameter for extensions.\r
+ */\r
+\r
+/*\r
+ * Author:\r
+ *   Johan Engelen <johan@shouraizou.nl>\r
+ *\r
+ * Copyright (C) 2006 Author\r
+ *\r
+ * Released under GNU GPL, read the file 'COPYING' for more information\r
+ */\r
+\r
+#include <gtkmm/widget.h>\r
+\r
+#include "xml/document.h"\r
+#include "extension-forward.h"\r
+\r
+#include "parameter.h"\r
+\r
+namespace Inkscape {\r
+namespace Extension {\r
+\r
+\r
+\r
+// \brief  A class to represent a notebookparameter of an extension\r
+class ParamNotebook : public Parameter {\r
+private:\r
+    /** \brief  Internal value.  This should point to a string that has\r
+                been allocated in memory.  And should be free'd. \r
+                It is the name of the current page. */\r
+    gchar * _value;\r
+    \r
+    GSList * pages; /**< A table to store the pages with parameters for this notebook.\r
+                              This only gets created if there are pages in this\r
+                              notebook */\r
+public:\r
+    ParamNotebook(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);\r
+    ~ParamNotebook(void);\r
+    Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);\r
+    Glib::ustring * string (void);\r
+        \r
+    const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }\r
+    const gchar * set (const int in, SPDocument * doc, Inkscape::XML::Node * node);\r
+}; /* class ParamNotebook */\r
+\r
+\r
+\r
+\r
+\r
+}  /* namespace Extension */\r
+}  /* namespace Inkscape */\r
+\r
+#endif /* __INK_EXTENSION_PARAMNOTEBOOK_H__ */\r
+\r
+/*\r
+  Local Variables:\r
+  mode:c++\r
+  c-file-style:"stroustrup"\r
+  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
+  indent-tabs-mode:nil\r
+  fill-column:99\r
+  End:\r
+*/\r
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r