Code

Merge and cleanup of GSoC C++-ification project.
[inkscape.git] / src / extension / param / parameter.cpp
1 /** @file
2  * @brief Parameters for extensions.
3  */
4 /* Author:
5  *   Ted Gould <ted@gould.cx>
6  *   Johan Engelen <johan@shouraizou.nl>
7  *   Jon A. Cruz <jon@joncruz.org>
8  *
9  * Copyright (C) 2005-2007 Authors
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
18 #ifdef linux  // does the dollar sign need escaping when passed as string parameter?
19 # define ESCAPE_DOLLAR_COMMANDLINE
20 #endif
22 #include <gtkmm/adjustment.h>
23 #include <gtkmm/box.h>
24 #include <gtkmm/spinbutton.h>
26 #include <xml/node.h>
28 #include <extension/extension.h>
29 #include "document-private.h"
30 #include "sp-object.h"
31 #include <color.h>
32 #include "widgets/sp-color-selector.h"
33 #include "widgets/sp-color-notebook.h"
35 #include "parameter.h"
36 #include "bool.h"
37 #include "color.h"
38 #include "description.h"
39 #include "groupheader.h"
40 #include "enum.h"
41 #include "float.h"
42 #include "int.h"
43 #include "notebook.h"
44 #include "radiobutton.h"
45 #include "string.h"
47 namespace Inkscape {
48 namespace Extension {
50 /**
51     \return None
52     \brief  This function creates a parameter that can be used later.  This
53             is typically done in the creation of the extension and defined
54             in the XML file describing the extension (it's private so people
55             have to use the system) :)
56     \param  in_repr  The XML describing the parameter
58     This function first grabs all of the data out of the Repr and puts
59     it into local variables.  Actually, these are just pointers, and the
60     data is not duplicated so we need to be careful with it.  If there
61     isn't a name or a type in the XML, then no parameter is created as
62     the function just returns.
64     From this point on, we're pretty committed as we've allocated an
65     object and we're starting to fill it.  The name is set first, and
66     is created with a strdup to actually allocate memory for it.  Then
67     there is a case statement (roughly because strcmp requires 'ifs')
68     based on what type of parameter this is.  Depending which type it
69     is, the value is interpreted differently, but they are relatively
70     straight forward.  In all cases the value is set to the default
71     value from the XML and the type is set to the interpreted type.
72 */
73 Parameter *
74 Parameter::make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
75 {
76     const char * name;
77     const char * type;
78     const char * guitext;
79     const char * desc;
80     const char * scope_str;
81     Parameter::_scope_t scope = Parameter::SCOPE_USER;
82         bool gui_hidden = false;
83         const char * gui_hide;
84         const char * gui_tip;
86     name = in_repr->attribute("name");
87     type = in_repr->attribute("type");
88     guitext = in_repr->attribute("gui-text");
89     if (guitext == NULL)
90         guitext = in_repr->attribute("_gui-text");
91     gui_tip = in_repr->attribute("gui-tip");
92     if (gui_tip == NULL)
93         gui_tip = in_repr->attribute("_gui-tip");
94     desc = in_repr->attribute("gui-description");
95     if (desc == NULL)
96         desc = in_repr->attribute("_gui-description");
97     scope_str = in_repr->attribute("scope");
98         gui_hide = in_repr->attribute("gui-hidden");
99         if (gui_hide != NULL) {
100                 if (strcmp(gui_hide, "1") == 0 ||
101                         strcmp(gui_hide, "true") == 0) {
102                         gui_hidden = true;
103                 }
104                 /* else stays false */
105         }
106     const gchar* appearance = in_repr->attribute("appearance");
108     /* In this case we just don't have enough information */
109     if (name == NULL || type == NULL) {
110         return NULL;
111     }
113     if (scope_str != NULL) {
114         if (!strcmp(scope_str, "user")) {
115             scope = Parameter::SCOPE_USER;
116         } else if (!strcmp(scope_str, "document")) {
117             scope = Parameter::SCOPE_DOCUMENT;
118         } else if (!strcmp(scope_str, "node")) {
119             scope = Parameter::SCOPE_NODE;
120         }
121     }
123     Parameter * param = NULL;
124     if (!strcmp(type, "boolean")) {
125         param = new ParamBool(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr);
126     } else if (!strcmp(type, "int")) {
127         param = new ParamInt(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr);
128     } else if (!strcmp(type, "float")) {
129         param = new ParamFloat(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr);
130     } else if (!strcmp(type, "string")) {
131         param = new ParamString(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr);
132         const gchar * max_length = in_repr->attribute("max_length");
133         if (max_length != NULL) {
134                 ParamString * ps = dynamic_cast<ParamString *>(param);
135                 ps->setMaxLength(atoi(max_length));
136         }
137     } else if (!strcmp(type, "description")) {
138         param = new ParamDescription(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr);
139     } else if (!strcmp(type, "groupheader")) {
140         param = new ParamGroupHeader(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr);        
141     } else if (!strcmp(type, "enum")) {
142         param = new ParamComboBox(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr);
143     } else if (!strcmp(type, "notebook")) {
144         param = new ParamNotebook(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr);
145     } else if (!strcmp(type, "optiongroup")) {
146         if (appearance && !strcmp(appearance, "minimal")) {
147             param = new ParamRadioButton(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr, ParamRadioButton::MINIMAL);
148         } else {
149             param = new ParamRadioButton(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr, ParamRadioButton::FULL);
150         }
151     } else if (!strcmp(type, "color")) {
152         param = new ParamColor(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr);
153     }
155     /* Note: param could equal NULL */
156     return param;
159 /** \brief  Wrapper to cast to the object and use it's function.  */
160 bool
161 Parameter::get_bool (const SPDocument * doc, const Inkscape::XML::Node * node)
163     ParamBool * boolpntr = dynamic_cast<ParamBool *>(this);
164     if (boolpntr == NULL)
165         throw Extension::param_not_bool_param();
166     return boolpntr->get(doc, node);
169 /** \brief  Wrapper to cast to the object and use it's function.  */
170 int
171 Parameter::get_int (const SPDocument * doc, const Inkscape::XML::Node * node)
173     ParamInt * intpntr = dynamic_cast<ParamInt *>(this);
174     if (intpntr == NULL)
175         throw Extension::param_not_int_param();
176     return intpntr->get(doc, node);
179 /** \brief  Wrapper to cast to the object and use it's function.  */
180 float
181 Parameter::get_float (const SPDocument * doc, const Inkscape::XML::Node * node)
183     ParamFloat * floatpntr = dynamic_cast<ParamFloat *>(this);
184     if (floatpntr == NULL)
185         throw Extension::param_not_float_param();
186     return floatpntr->get(doc, node);
189 /** \brief  Wrapper to cast to the object and use it's function.  */
190 const gchar *
191 Parameter::get_string (const SPDocument * doc, const Inkscape::XML::Node * node)
193     ParamString * stringpntr = dynamic_cast<ParamString *>(this);
194     if (stringpntr == NULL)
195         throw Extension::param_not_string_param();
196     return stringpntr->get(doc, node);
199 /** \brief  Wrapper to cast to the object and use it's function.  */
200 const gchar *
201 Parameter::get_enum (const SPDocument * doc, const Inkscape::XML::Node * node)
203     ParamComboBox * param = dynamic_cast<ParamComboBox *>(this);
204     if (param == NULL)
205         throw Extension::param_not_enum_param();
206     return param->get(doc, node);
209 /** \brief  Wrapper to cast to the object and use it's function.  */
210 gchar const *Parameter::get_optiongroup(SPDocument const * doc, Inkscape::XML::Node const * node)
212     ParamRadioButton * param = dynamic_cast<ParamRadioButton *>(this);
213     if (!param) {
214         throw Extension::param_not_optiongroup_param();
215     }
216     return param->get(doc, node);
219 guint32
220 Parameter::get_color(const SPDocument* doc, const Inkscape::XML::Node* node)
222     ParamColor* param = dynamic_cast<ParamColor *>(this);
223     if (param == NULL)
224         throw Extension::param_not_color_param();
225     return param->get(doc, node);
228 /** \brief  Wrapper to cast to the object and use it's function.  */
229 bool
230 Parameter::set_bool (bool in, SPDocument * doc, Inkscape::XML::Node * node)
232     ParamBool * boolpntr = dynamic_cast<ParamBool *>(this);
233     if (boolpntr == NULL)
234         throw Extension::param_not_bool_param();
235     return boolpntr->set(in, doc, node);
238 /** \brief  Wrapper to cast to the object and use it's function.  */
239 int
240 Parameter::set_int (int in, SPDocument * doc, Inkscape::XML::Node * node)
242     ParamInt * intpntr = dynamic_cast<ParamInt *>(this);
243     if (intpntr == NULL)
244         throw Extension::param_not_int_param();
245     return intpntr->set(in, doc, node);
248 /** \brief  Wrapper to cast to the object and use it's function.  */
249 float
250 Parameter::set_float (float in, SPDocument * doc, Inkscape::XML::Node * node)
252     ParamFloat * floatpntr;
253     floatpntr = dynamic_cast<ParamFloat *>(this);
254     if (floatpntr == NULL)
255         throw Extension::param_not_float_param();
256     return floatpntr->set(in, doc, node);
259 /** \brief  Wrapper to cast to the object and use it's function.  */
260 const gchar *
261 Parameter::set_string (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
263     ParamString * stringpntr = dynamic_cast<ParamString *>(this);
264     if (stringpntr == NULL)
265         throw Extension::param_not_string_param();
266     return stringpntr->set(in, doc, node);
269 gchar const * Parameter::set_optiongroup( gchar const * in, SPDocument * doc, Inkscape::XML::Node * node )
271     ParamRadioButton *param = dynamic_cast<ParamRadioButton *>(this);
272     if (!param) {
273         throw Extension::param_not_optiongroup_param();
274     }
275     return param->set(in, doc, node);
279 /** \brief  Wrapper to cast to the object and use it's function.  */
280 guint32
281 Parameter::set_color (guint32 in, SPDocument * doc, Inkscape::XML::Node * node)
283     ParamColor* param = dynamic_cast<ParamColor *>(this);
284     if (param == NULL)
285         throw Extension::param_not_color_param();
286     return param->set(in, doc, node);
290 /** \brief  Oop, now that we need a parameter, we need it's name.  */
291 Parameter::Parameter (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) :
292     extension(ext), _name(NULL), _desc(NULL), _scope(scope), _text(NULL), _gui_hidden(gui_hidden), _gui_tip(NULL)
294     if (name != NULL) {
295         _name = g_strdup(name);
296     }
297     if (desc != NULL) {
298         _desc = g_strdup(desc);
299 //        printf("Adding description: '%s' on '%s'\n", _desc, _name);
300     }
301     if (gui_tip != NULL) {
302         _gui_tip = g_strdup(gui_tip);
303     }
306     if (guitext != NULL)
307         _text = g_strdup(guitext);
308     else
309         _text = g_strdup(name);
311     return;
314 /** \brief  Just free the allocated name. */
315 Parameter::~Parameter (void)
317     g_free(_name);
318     g_free(_text);
319         g_free(_gui_tip);
320     g_free(_desc);
323 /** \brief  Build the name to write the parameter from the extension's
324             ID and the name of this parameter. */
325 gchar *
326 Parameter::pref_name (void)
328     return g_strdup_printf("%s.%s", extension->get_id(), _name);
331 Inkscape::XML::Node *
332 Parameter::find_child (Inkscape::XML::Node * adult)
334     return sp_repr_lookup_child(adult, "name", _name);
337 Inkscape::XML::Node *
338 Parameter::new_child (Inkscape::XML::Node * parent)
340     Inkscape::XML::Node * retval;
341     retval = parent->document()->createElement("inkscape:extension-param");
342     retval->setAttribute("name", _name);
344     parent->appendChild(retval);
345     Inkscape::GC::release(retval);
346     return retval;
349 Inkscape::XML::Node *Parameter::document_param_node(SPDocument * doc)
351     Inkscape::XML::Document *xml_doc = doc->getReprDoc();
352     Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc));
353     Inkscape::XML::Node * params = NULL;
355     GQuark const name_quark = g_quark_from_string("inkscape:extension-params");
357     for (Inkscape::XML::Node * child = defs->firstChild();
358             child != NULL;
359             child = child->next()) {
360         if ((GQuark)child->code() == name_quark &&
361                 !strcmp(child->attribute("extension"), extension->get_id())) {
362             params = child;
363             break;
364         }
365     }
367     if (params == NULL) {
368         params = xml_doc->createElement("inkscape:extension-param");
369         params->setAttribute("extension", extension->get_id());
370         defs->appendChild(params);
371         Inkscape::GC::release(params);
372     }
374     return params;
377 /** \brief  Basically, if there is no widget pass a NULL. */
378 Gtk::Widget *
379 Parameter::get_widget (SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/, sigc::signal<void> * /*changeSignal*/)
381     return NULL;
384 /** \brief  If I'm not sure which it is, just don't return a value. */
385 void
386 Parameter::string (std::string &/*string*/)
388     return;
391 void
392 Parameter::string (std::list <std::string> &list)
394     std::string value;
395     string(value);
396     if (value == "") {
397         return;
398     }
400     std::string final;
401     final += "--";
402     final += name();
403     final += "=";
404     final += value;
406     list.insert(list.end(), final);
407     return;
410 /** \brief  All the code in Notebook::get_param to get the notebook content */
411 Parameter *
412 Parameter::get_param(const gchar * name)
414     return NULL;
417 Glib::ustring const extension_pref_root = "/extensions/";
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 :