Code

r16217@tres: ted | 2007-08-10 10:36:27 -0700
[inkscape.git] / src / extension / parameter.cpp
1 /** \file
2  * Parameters for extensions.
3  */
5 /*
6  * Author:
7  *   Ted Gould <ted@gould.cx>
8  *   Johan Engelen <johan@shouraizou.nl>
9  *
10  * Copyright (C) 2005-2007 Authors
11  *
12  * Released under GNU GPL, read the file 'COPYING' for more information
13  */
15 #ifdef HAVE_CONFIG_H
16 # include "config.h"
17 #endif
19 #ifdef linux  // does the dollar sign need escaping when passed as string parameter?
20 # define ESCAPE_DOLLAR_COMMANDLINE
21 #endif
23 #include <gtkmm/adjustment.h>
24 #include <gtkmm/box.h>
25 #include <gtkmm/spinbutton.h>
27 #include <xml/node.h>
29 #include "extension.h"
30 #include "document-private.h"
31 #include "sp-object.h"
32 #include "color.h"
33 #include "widgets/sp-color-selector.h"
34 #include "widgets/sp-color-notebook.h"
36 #include "parameter.h"
37 #include "parambool.h"
38 #include "paramcolor.h"
39 #include "paramdescription.h"
40 #include "paramenum.h"
41 #include "paramfloat.h"
42 #include "paramint.h"
43 #include "paramnotebook.h"
44 #include "paramradiobutton.h"
45 #include "paramstring.h"
47 namespace Inkscape {
48 namespace Extension {
50 class ParamEnum : public Parameter {
51 private:
52     class Choice {
53     public:
54         gchar * _gui_name;
55         gchar * _value;
56         Choice(gchar * gui_name, gchar * value) : _gui_name(NULL), _value(NULL) {
57             if (gui_name != NULL)
58                 _gui_name = g_strdup(_(gui_name));
59             if (value != NULL)
60                 _value = g_strdup(value);
61             return;
62         };
63         ~Choice (void) {
64             g_free(_gui_name);
65             g_free(_value);
66         };
67     }; /* class Choice */
68     /** \brief  Internal value.  This should point to a string that has
69                 been allocated in memory.  And should be free'd. */
70     Choice * _current_choice;
71     typedef std::list<Choice *> choice_list_t;
72     choice_list_t _choice_list;
73 public:
74     ParamEnum(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
75     ~ParamEnum(void);
76     /** \brief  Returns \c _value, with a \i const to protect it. */
77     const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _current_choice != NULL ? _current_choice->_value : NULL; }
78     const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
79     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal);
80     Glib::ustring * string (void);
81 }; /* class ParamEnum */
82      
83 /**
84     \return None
85     \brief  This function creates a parameter that can be used later.  This
86             is typically done in the creation of the extension and defined
87             in the XML file describing the extension (it's private so people
88             have to use the system) :)
89     \param  in_repr  The XML describing the parameter
91     This function first grabs all of the data out of the Repr and puts
92     it into local variables.  Actually, these are just pointers, and the
93     data is not duplicated so we need to be careful with it.  If there
94     isn't a name or a type in the XML, then no parameter is created as
95     the function just returns.
97     From this point on, we're pretty committed as we've allocated an
98     object and we're starting to fill it.  The name is set first, and
99     is created with a strdup to actually allocate memory for it.  Then
100     there is a case statement (roughly because strcmp requires 'ifs')
101     based on what type of parameter this is.  Depending which type it
102     is, the value is interpreted differently, but they are relatively
103     straight forward.  In all cases the value is set to the default
104     value from the XML and the type is set to the interpreted type.
105 */
106 Parameter *
107 Parameter::make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
109     const char * name;
110     const char * type;
111     const char * guitext;
112     const char * desc;
113     const char * scope_str;
114     Parameter::_scope_t scope = Parameter::SCOPE_USER;
116     name = in_repr->attribute("name");
117     type = in_repr->attribute("type");
118     guitext = in_repr->attribute("gui-text");
119     if (guitext == NULL)
120         guitext = in_repr->attribute("_gui-text");
121     desc = in_repr->attribute("gui-description");
122     if (desc == NULL)
123         desc = in_repr->attribute("_gui-description");
124     scope_str = in_repr->attribute("scope");
126     /* In this case we just don't have enough information */
127     if (name == NULL || type == NULL) {
128         return NULL;
129     }
131     if (scope_str != NULL) {
132         if (!strcmp(scope_str, "user")) {
133             scope = Parameter::SCOPE_USER;
134         } else if (!strcmp(scope_str, "document")) {
135             scope = Parameter::SCOPE_DOCUMENT;
136         } else if (!strcmp(scope_str, "node")) {
137             scope = Parameter::SCOPE_NODE;
138         }
139     }
141     Parameter * param = NULL;
142     if (!strcmp(type, "boolean")) {
143         param = new ParamBool(name, guitext, desc, scope, in_ext, in_repr);
144     } else if (!strcmp(type, "int")) {
145         param = new ParamInt(name, guitext, desc, scope, in_ext, in_repr);
146     } else if (!strcmp(type, "float")) {
147         param = new ParamFloat(name, guitext, desc, scope, in_ext, in_repr);
148     } else if (!strcmp(type, "string")) {
149         param = new ParamString(name, guitext, desc, scope, in_ext, in_repr);
150     } else if (!strcmp(type, "description")) {
151         param = new ParamDescription(name, guitext, desc, scope, in_ext, in_repr);
152     } else if (!strcmp(type, "enum")) {
153         param = new ParamComboBox(name, guitext, desc, scope, in_ext, in_repr);
154     } else if (!strcmp(type, "notebook")) {
155         param = new ParamNotebook(name, guitext, desc, scope, in_ext, in_repr);
156     } else if (!strcmp(type, "optiongroup")) {
157         param = new ParamRadioButton(name, guitext, desc, scope, in_ext, in_repr);
158     } else if (!strcmp(type, "color")) {
159         param = new ParamColor(name, guitext, desc, scope, in_ext, in_repr);
160     }
162     /* Note: param could equal NULL */
163     return param;
168 /** \brief  Wrapper to cast to the object and use it's function.  */
169 bool
170 Parameter::get_bool (const SPDocument * doc, const Inkscape::XML::Node * node)
172     ParamBool * boolpntr = dynamic_cast<ParamBool *>(this);    
173     if (boolpntr == NULL)
174         throw Extension::param_not_bool_param();
175     return boolpntr->get(doc, node);
178 /** \brief  Wrapper to cast to the object and use it's function.  */
179 int
180 Parameter::get_int (const SPDocument * doc, const Inkscape::XML::Node * node)
182     ParamInt * intpntr = dynamic_cast<ParamInt *>(this);    
183     if (intpntr == NULL)
184         throw Extension::param_not_int_param();
185     return intpntr->get(doc, node);
188 /** \brief  Wrapper to cast to the object and use it's function.  */
189 float
190 Parameter::get_float (const SPDocument * doc, const Inkscape::XML::Node * node)
192     ParamFloat * floatpntr = dynamic_cast<ParamFloat *>(this);    
193     if (floatpntr == NULL)
194         throw Extension::param_not_float_param();
195     return floatpntr->get(doc, node);
198 /** \brief  Wrapper to cast to the object and use it's function.  */
199 const gchar *
200 Parameter::get_string (const SPDocument * doc, const Inkscape::XML::Node * node)
202     ParamString * stringpntr = dynamic_cast<ParamString *>(this);
203     if (stringpntr == NULL)
204         throw Extension::param_not_string_param();
205     return stringpntr->get(doc, node);
208 /** \brief  Wrapper to cast to the object and use it's function.  */
209 const gchar *
210 Parameter::get_enum (const SPDocument * doc, const Inkscape::XML::Node * node)
212     ParamComboBox * param = dynamic_cast<ParamComboBox *>(this);
213     if (param == NULL)
214         throw Extension::param_not_enum_param();
215     return param->get(doc, node);
218 SPColor*
219 Parameter::get_color(const SPDocument* doc, const Inkscape::XML::Node* node)
221     ParamColor* param = dynamic_cast<ParamColor *>(this);
222     if (param == NULL)
223         throw Extension::param_not_color_param();
224     return param->get(doc, node);
227 /** \brief  Wrapper to cast to the object and use it's function.  */
228 bool
229 Parameter::set_bool (bool in, SPDocument * doc, Inkscape::XML::Node * node)
231     ParamBool * boolpntr = dynamic_cast<ParamBool *>(this);
232     if (boolpntr == NULL)
233         throw Extension::param_not_bool_param();
234     return boolpntr->set(in, doc, node);
237 /** \brief  Wrapper to cast to the object and use it's function.  */
238 int
239 Parameter::set_int (int in, SPDocument * doc, Inkscape::XML::Node * node)
241     ParamInt * intpntr = dynamic_cast<ParamInt *>(this);    
242     if (intpntr == NULL)
243         throw Extension::param_not_int_param();
244     return intpntr->set(in, doc, node);
247 /** \brief  Wrapper to cast to the object and use it's function.  */
248 float
249 Parameter::set_float (float in, SPDocument * doc, Inkscape::XML::Node * node)
251     ParamFloat * floatpntr;
252     floatpntr = dynamic_cast<ParamFloat *>(this);
253     if (floatpntr == NULL)
254         throw Extension::param_not_float_param();
255     return floatpntr->set(in, doc, node);
258 /** \brief  Wrapper to cast to the object and use it's function.  */
259 const gchar *
260 Parameter::set_string (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
262     ParamString * stringpntr = dynamic_cast<ParamString *>(this);    
263     if (stringpntr == NULL)
264         throw Extension::param_not_string_param();
265     return stringpntr->set(in, doc, node);
267 /** \brief  Wrapper to cast to the object and use it's function.  */
268 SPColor*
269 Parameter::set_color (SPColor* in, SPDocument * doc, Inkscape::XML::Node * node)
271     ParamColor* param = dynamic_cast<ParamColor *>(this);
272     if (param == NULL)
273         throw Extension::param_not_color_param();
274     return param->set(in, doc, node);
278 /** \brief  Oop, now that we need a parameter, we need it's name.  */
279 Parameter::Parameter (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext) :
280     extension(ext), _name(NULL), _desc(NULL), _scope(scope), _text(NULL)
282     if (name != NULL)
283         _name = g_strdup(name);
284     if (desc != NULL) {
285         _desc = g_strdup(desc);
286         // printf("Adding description: '%s' on '%s'\n", _desc, _name);
287     }
290     if (guitext != NULL)
291         _text = g_strdup(guitext);
292     else
293         _text = g_strdup(name);
295     return;
298 /** \brief  Just free the allocated name. */
299 Parameter::~Parameter (void)
301     g_free(_name);
302     g_free(_text);
305 /** \brief  Build the name to write the parameter from the extension's
306             ID and the name of this parameter. */
307 gchar *
308 Parameter::pref_name (void)
310     return g_strdup_printf("%s.%s", extension->get_id(), _name);
313 Inkscape::XML::Node *
314 Parameter::find_child (Inkscape::XML::Node * adult)
316     return sp_repr_lookup_child(adult, "name", _name);
319 Inkscape::XML::Node *
320 Parameter::new_child (Inkscape::XML::Node * parent)
322     Inkscape::XML::Node * retval;
323     retval = parent->document()->createElement("inkscape:extension-param");
324     retval->setAttribute("name", _name);
326     parent->appendChild(retval);
327     return retval;
330 Inkscape::XML::Node *
331 Parameter::document_param_node (SPDocument * doc)
333     Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
334     Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc));
335     Inkscape::XML::Node * params = NULL;
337     GQuark const name_quark = g_quark_from_string("inkscape:extension-params");
339     for (Inkscape::XML::Node * child = defs->firstChild();
340             child != NULL;
341             child = child->next()) {
342         if ((GQuark)child->code() == name_quark &&
343                 !strcmp(child->attribute("extension"), extension->get_id())) {
344             params = child;
345             break;
346         }
347     }
349     if (params == NULL) {
350         params = xml_doc->createElement("inkscape:extension-param");
351         params->setAttribute("extension", extension->get_id());
352         defs->appendChild(params);
353     }
355     return params;
358 /** \brief  Basically, if there is no widget pass a NULL. */
359 Gtk::Widget *
360 Parameter::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal)
362     return NULL;
365 /** \brief  If I'm not sure which it is, just don't return a value. */
366 Glib::ustring *
367 Parameter::string (void)
369     Glib::ustring * mystring = new Glib::ustring("");
370     return mystring;
377 ParamEnum::ParamEnum (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
378     Parameter(name, guitext, desc, scope, ext), _current_choice(NULL)
380     return;
383 ParamEnum::~ParamEnum (void)
388 /** \brief  Return the value as a string */
389 Glib::ustring *
390 ParamEnum::string (void)
392     Glib::ustring * mystring = new Glib::ustring("");
393     *mystring += this->get(NULL, NULL);
394     return mystring;
397 Gtk::Widget *
398 ParamEnum::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal)
400     return NULL;
403 const gchar *
404 ParamEnum::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
406     return NULL;
410 }  /* namespace Extension */
411 }  /* namespace Inkscape */
413 /*
414   Local Variables:
415   mode:c++
416   c-file-style:"stroustrup"
417   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
418   indent-tabs-mode:nil
419   fill-column:99
420   End:
421 */
422 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :