Code

Super duper mega (fun!) commit: replaced encoding=utf-8 with fileencoding=utf-8 in...
[inkscape.git] / src / extension / param / notebook.cpp
1 /** \file
2  * Notebook and NotebookPage parameters for extensions.
3  */
5 /*
6  * Author:
7  *   Johan Engelen <johan@shouraizou.nl>
8  *
9  * Copyright (C) 2006 Author
10  *
11  * Released under GNU GPL, read the file 'COPYING' for more information
12  */
14 #ifdef HAVE_CONFIG_H
15 # include "config.h"
16 #endif
19 #include <gtkmm/adjustment.h>
20 #include <gtkmm/box.h>
21 #include <gtkmm/spinbutton.h>
22 #include <gtkmm/notebook.h>
23 #include <gtkmm/tooltips.h>
25 #include <glibmm/i18n.h>
27 #include <xml/node.h>
29 #include <extension/extension.h>
30 #include "preferences.h"
31 #include "document-private.h"
32 #include "sp-object.h"
34 #include "notebook.h"
36 /** \brief  The root directory in the preferences database for extension
37             related parameters. */
38 #define PREF_DIR "extensions"
40 namespace Inkscape {
41 namespace Extension {
44 // \brief  A class to represent the pages of a notebookparameter of an extension
45 class ParamNotebookPage : public Parameter {
46 private:
47     GSList * parameters; /**< A table to store the parameters for this page.
48                               This only gets created if there are parameters on this
49                               page */
50     Gtk::Tooltips * _tooltips;
52 public:
53     static ParamNotebookPage * makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext);
55     ParamNotebookPage(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
56     ~ParamNotebookPage(void);
57     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal);
58     void paramString (std::list <std::string> &list);
59     gchar * get_guitext (void) {return _text;};
61 }; /* class ParamNotebookPage */
64 ParamNotebookPage::ParamNotebookPage (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
65     Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext)
66 {
67     parameters = NULL;
69     // Read XML to build page
70     if (xml != NULL) {
71         Inkscape::XML::Node *child_repr = sp_repr_children(xml);
72         while (child_repr != NULL) {
73             char const * chname = child_repr->name();
74                         if (!strncmp(chname, INKSCAPE_EXTENSION_NS_NC, strlen(INKSCAPE_EXTENSION_NS_NC))) {
75                                 chname += strlen(INKSCAPE_EXTENSION_NS);
76                         }
77             if (chname[0] == '_') // Allow _ for translation of tags
78                 chname++;
79             if (!strcmp(chname, "param") || !strcmp(chname, "_param")) {
80                 Parameter * param;
81                 param = Parameter::make(child_repr, ext);
82                 if (param != NULL) parameters = g_slist_append(parameters, param);
83             }
84             child_repr = sp_repr_next(child_repr);
85         }
86     }
88     return;
89 }
91 ParamNotebookPage::~ParamNotebookPage (void)
92 {
93     if (_tooltips) delete _tooltips;
94     //destroy parameters
95     for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {
96         Parameter * param = reinterpret_cast<Parameter *>(list->data);
97         delete param;
98     }
99     g_slist_free(parameters);
102 /** \brief  Return the value as a string */
103 void
104 ParamNotebookPage::paramString (std::list <std::string> &list)
106     for (GSList * plist = parameters; plist != NULL; plist = g_slist_next(plist)) {
107         Parameter * param = reinterpret_cast<Parameter *>(plist->data);
108         param->string(list);
109     }
111     return;
115 /**
116     \return None
117     \brief  This function creates a page that can be used later.  This
118             is typically done in the creation of the notebook and defined
119             in the XML file describing the extension (it's private so people
120             have to use the system) :)
121     \param  in_repr  The XML describing the page
123     This function first grabs all of the data out of the Repr and puts
124     it into local variables.  Actually, these are just pointers, and the
125     data is not duplicated so we need to be careful with it.  If there
126     isn't a name in the XML, then no page is created as
127     the function just returns.
129     From this point on, we're pretty committed as we've allocated an
130     object and we're starting to fill it.  The name is set first, and
131     is created with a strdup to actually allocate memory for it.  Then
132     there is a case statement (roughly because strcmp requires 'ifs')
133     based on what type of parameter this is.  Depending which type it
134     is, the value is interpreted differently, but they are relatively
135     straight forward.  In all cases the value is set to the default
136     value from the XML and the type is set to the interpreted type.
137 */
138 ParamNotebookPage *
139 ParamNotebookPage::makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
141     const char * name;
142     const char * guitext;
143     const char * desc;
144     const char * scope_str;
145     Parameter::_scope_t scope = Parameter::SCOPE_USER;
146         bool gui_hidden = false;
147         const char * gui_hide;
148         const char * gui_tip;
150     name = in_repr->attribute("name");
151     guitext = in_repr->attribute("gui-text");
152     if (guitext == NULL)
153         guitext = in_repr->attribute("_gui-text");
154     gui_tip = in_repr->attribute("gui-tip");
155     if (gui_tip == NULL)
156         gui_tip = in_repr->attribute("_gui-tip");
157     desc = in_repr->attribute("gui-description");
158     if (desc == NULL)
159         desc = in_repr->attribute("_gui-description");
160     scope_str = in_repr->attribute("scope");
161         gui_hide = in_repr->attribute("gui-hidden");
162         if (gui_hide != NULL) {
163                 if (strcmp(gui_hide, "1") == 0 ||
164                         strcmp(gui_hide, "true") == 0) {
165                         gui_hidden = true;
166                 }
167                 /* else stays false */
168         }
170     /* In this case we just don't have enough information */
171     if (name == NULL) {
172         return NULL;
173     }
175     if (scope_str != NULL) {
176         if (!strcmp(scope_str, "user")) {
177             scope = Parameter::SCOPE_USER;
178         } else if (!strcmp(scope_str, "document")) {
179             scope = Parameter::SCOPE_DOCUMENT;
180         } else if (!strcmp(scope_str, "node")) {
181             scope = Parameter::SCOPE_NODE;
182         }
183     }
185     ParamNotebookPage * page = new ParamNotebookPage(name, guitext, desc, scope, gui_hide, gui_tip, in_ext, in_repr);
187     /* Note: page could equal NULL */
188     return page;
193 /**
194     \brief  Creates a notebookpage widget for a notebook
196     Builds a notebook page (a vbox) and puts parameters on it.
197 */
198 Gtk::Widget *
199 ParamNotebookPage::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal)
201         if (_gui_hidden) return NULL;
203     if (!_tooltips) _tooltips = new Gtk::Tooltips();
205     Gtk::VBox * vbox = Gtk::manage(new Gtk::VBox);
206     vbox->set_border_width(5);
208     // add parameters onto page (if any)
209     for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) {
210         Parameter * param = reinterpret_cast<Parameter *>(list->data);
211         Gtk::Widget * widg = param->get_widget(doc, node, changeSignal);
212         gchar const * tip = param->get_tooltip();
213 //        printf("Tip: '%s'\n", tip);
214         vbox->pack_start(*widg, false, false, 2);
215         if (tip != NULL) {
216             _tooltips->set_tip(*widg, Glib::ustring(tip));
217         }
218     }
220     vbox->show();
222     return dynamic_cast<Gtk::Widget *>(vbox);
226 ParamNotebook::ParamNotebook (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
227     Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext)
229     pages = NULL;
231     // Read XML tree to add pages:
232     if (xml != NULL) {
233         Inkscape::XML::Node *child_repr = sp_repr_children(xml);
234         while (child_repr != NULL) {
235             char const * chname = child_repr->name();
236                         if (!strncmp(chname, INKSCAPE_EXTENSION_NS_NC, strlen(INKSCAPE_EXTENSION_NS_NC))) {
237                                 chname += strlen(INKSCAPE_EXTENSION_NS);
238                         }
239             if (chname[0] == '_') // Allow _ for translation of tags
240                 chname++;
241             if (!strcmp(chname, "page")) {
242                 ParamNotebookPage * page;
243                 page = ParamNotebookPage::makepage(child_repr, ext);
244                 if (page != NULL) pages = g_slist_append(pages, page);
245             }
246             child_repr = sp_repr_next(child_repr);
247         }
248     }
250     // Initialize _value with the current page
251     const char * defaultval = NULL;
252     // set first page as default
253     if (pages != NULL) {
254         ParamNotebookPage * defpage = reinterpret_cast<ParamNotebookPage *>(pages->data);
255         defaultval = defpage->name();
256     }
258     gchar * pref_name = this->pref_name();
259     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
260     Glib::ustring paramval = prefs->getString(extension_pref_root + pref_name);
261     g_free(pref_name);
263     if (!paramval.empty())
264         defaultval = paramval.data();
265     if (defaultval != NULL)
266         _value = g_strdup(defaultval);  // allocate space for _value
268     return;
271 ParamNotebook::~ParamNotebook (void)
273     //destroy pages
274     for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {
275         ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);
276         delete page;
277     }
278     g_slist_free(pages);
280     g_free(_value);
284 /** \brief  A function to set the \c _value
285     \param  in   The number of the page which value must be set
286     \param  doc  A document that should be used to set the value.
287     \param  node The node where the value may be placed
289     This function sets the internal value, but it also sets the value
290     in the preferences structure.  To put it in the right place, \c PREF_DIR
291     and \c pref_name() are used.
293     To copy the data into _value the old memory must be free'd first.
294     It is important to note that \c g_free handles \c NULL just fine.  Then
295     the passed in value is duplicated using \c g_strdup().
296 */
297 const gchar *
298 ParamNotebook::set (const int in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/)
300     ParamNotebookPage * page = NULL;
301     int i = 0;
302     for (GSList * list = pages; (list != NULL) && (i <= in); list = g_slist_next(list)) {
303         page = reinterpret_cast<ParamNotebookPage *>(list->data);
304         i++;
305     }
307     if (page == NULL) return _value;
309     if (_value != NULL) g_free(_value);
310     _value = g_strdup(page->name());
312     gchar * prefname = this->pref_name();
313     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
314     prefs->setString(extension_pref_root + prefname, _value);
315     g_free(prefname);
317     return _value;
321 /**
322     \brief  A function to get the currentpage and the parameters in a string form
323     \return A string with the 'value' and all the parameters on all pages as command line arguments
324 */
325 void
326 ParamNotebook::string (std::list <std::string> &list)
328     std::string param_string;
329     param_string += "--";
330     param_string += name();
331     param_string += "=";
333     param_string += "\"";
334     param_string += _value;  // the name of the current page
335     param_string += "\"";
336     list.insert(list.end(), param_string);
338     for (GSList * pglist = pages; pglist != NULL; pglist = g_slist_next(pglist)) {
339         ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(pglist->data);
340         page->paramString(list);
341     }
343     return;
346 /** \brief  A special category of Gtk::Notebook to handle notebook parameters */
347 class ParamNotebookWdg : public Gtk::Notebook {
348 private:
349     ParamNotebook * _pref;
350     SPDocument * _doc;
351     Inkscape::XML::Node * _node;
352 public:
353     /** \brief  Build a notebookpage preference for the given parameter
354         \param  pref  Where to get the string (pagename) from, and where to put it
355                       when it changes.
356     */
357     ParamNotebookWdg (ParamNotebook * pref, SPDocument * doc, Inkscape::XML::Node * node) :
358         Gtk::Notebook(), _pref(pref), _doc(doc), _node(node), activated(false) {
359         // don't have to set the correct page: this is done in ParamNotebook::get_widget.
360         // hook function
361         this->signal_switch_page().connect(sigc::mem_fun(this, &ParamNotebookWdg::changed_page));
362         return;
363     };
364     void changed_page(GtkNotebookPage *page, guint pagenum);
365     bool activated;
366 };
368 /** \brief  Respond to the selected page of notebook changing
369     This function responds to the changing by reporting it to
370     ParamNotebook. The change is only reported when the notebook
371     is actually visible. This to exclude 'fake' changes when the
372     notebookpages are added or removed.
373 */
374 void
375 ParamNotebookWdg::changed_page(GtkNotebookPage */*page*/,
376                                    guint pagenum)
378     if (is_visible()) {
379         _pref->set((int)pagenum, _doc, _node);
380     }
381     return;
386 /**
387     \brief  Creates a Notebook widget for a notebook parameter
389     Builds a notebook and puts pages in it.
390 */
391 Gtk::Widget *
392 ParamNotebook::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal)
394         if (_gui_hidden) return NULL;
396     ParamNotebookWdg * nb = Gtk::manage(new ParamNotebookWdg(this, doc, node));
398     // add pages (if any)
399     int i = -1;
400     int pagenr = i;
401     for (GSList * list = pages; list != NULL; list = g_slist_next(list)) {
402         i++;
403         ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data);
404         Gtk::Widget * widg = page->get_widget(doc, node, changeSignal);
405         nb->append_page(*widg, _(page->get_guitext()));
406         if (!strcmp(_value, page->name())) {
407             pagenr = i; // this is the page to be displayed?
408         }
409     }
411     nb->show();
413     if (pagenr >= 0) nb->set_current_page(pagenr);
415     return dynamic_cast<Gtk::Widget *>(nb);
419 }  /* namespace Extension */
420 }  /* namespace Inkscape */
422 /*
423   Local Variables:
424   mode:c++
425   c-file-style:"stroustrup"
426   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
427   indent-tabs-mode:nil
428   fill-column:99
429   End:
430 */
431 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :