Code

Added an 'appearance' hint to .inx optiongroups to allow for dropdowns instead of...
[inkscape.git] / src / extension / param / 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/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 "bool.h"
38 #include "color.h"
39 #include "description.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, "enum")) {
140         param = new ParamComboBox(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr);
141     } else if (!strcmp(type, "notebook")) {
142         param = new ParamNotebook(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr);
143     } else if (!strcmp(type, "optiongroup")) {
144         if (appearance && !strcmp(appearance, "minimal")) {
145             param = new ParamRadioButton(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr, ParamRadioButton::MINIMAL);
146         } else {
147             param = new ParamRadioButton(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr, ParamRadioButton::FULL);
148         }
149     } else if (!strcmp(type, "color")) {
150         param = new ParamColor(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr);
151     }
153     /* Note: param could equal NULL */
154     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 guint32
210 Parameter::get_color(const SPDocument* doc, const Inkscape::XML::Node* node)
212     ParamColor* param = dynamic_cast<ParamColor *>(this);
213     if (param == NULL)
214         throw Extension::param_not_color_param();
215     return param->get(doc, node);
218 /** \brief  Wrapper to cast to the object and use it's function.  */
219 bool
220 Parameter::set_bool (bool in, SPDocument * doc, Inkscape::XML::Node * node)
222     ParamBool * boolpntr = dynamic_cast<ParamBool *>(this);
223     if (boolpntr == NULL)
224         throw Extension::param_not_bool_param();
225     return boolpntr->set(in, doc, node);
228 /** \brief  Wrapper to cast to the object and use it's function.  */
229 int
230 Parameter::set_int (int in, SPDocument * doc, Inkscape::XML::Node * node)
232     ParamInt * intpntr = dynamic_cast<ParamInt *>(this);
233     if (intpntr == NULL)
234         throw Extension::param_not_int_param();
235     return intpntr->set(in, doc, node);
238 /** \brief  Wrapper to cast to the object and use it's function.  */
239 float
240 Parameter::set_float (float in, SPDocument * doc, Inkscape::XML::Node * node)
242     ParamFloat * floatpntr;
243     floatpntr = dynamic_cast<ParamFloat *>(this);
244     if (floatpntr == NULL)
245         throw Extension::param_not_float_param();
246     return floatpntr->set(in, doc, node);
249 /** \brief  Wrapper to cast to the object and use it's function.  */
250 const gchar *
251 Parameter::set_string (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
253     ParamString * stringpntr = dynamic_cast<ParamString *>(this);
254     if (stringpntr == NULL)
255         throw Extension::param_not_string_param();
256     return stringpntr->set(in, doc, node);
258 /** \brief  Wrapper to cast to the object and use it's function.  */
259 guint32
260 Parameter::set_color (guint32 in, SPDocument * doc, Inkscape::XML::Node * node)
262     ParamColor* param = dynamic_cast<ParamColor *>(this);
263     if (param == NULL)
264         throw Extension::param_not_color_param();
265     return param->set(in, doc, node);
269 /** \brief  Oop, now that we need a parameter, we need it's name.  */
270 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) :
271     extension(ext), _name(NULL), _desc(NULL), _scope(scope), _text(NULL), _gui_hidden(gui_hidden), _gui_tip(NULL)
273     if (name != NULL) {
274         _name = g_strdup(name);
275     }
276     if (desc != NULL) {
277         _desc = g_strdup(desc);
278         // printf("Adding description: '%s' on '%s'\n", _desc, _name);
279     }
280     if (gui_tip != NULL) {
281         _gui_tip = g_strdup(gui_tip);
282     }
285     if (guitext != NULL)
286         _text = g_strdup(guitext);
287     else
288         _text = g_strdup(name);
290     return;
293 /** \brief  Just free the allocated name. */
294 Parameter::~Parameter (void)
296     g_free(_name);
297     g_free(_text);
298         g_free(_gui_tip);
301 /** \brief  Build the name to write the parameter from the extension's
302             ID and the name of this parameter. */
303 gchar *
304 Parameter::pref_name (void)
306     return g_strdup_printf("%s.%s", extension->get_id(), _name);
309 Inkscape::XML::Node *
310 Parameter::find_child (Inkscape::XML::Node * adult)
312     return sp_repr_lookup_child(adult, "name", _name);
315 Inkscape::XML::Node *
316 Parameter::new_child (Inkscape::XML::Node * parent)
318     Inkscape::XML::Node * retval;
319     retval = parent->document()->createElement("inkscape:extension-param");
320     retval->setAttribute("name", _name);
322     parent->appendChild(retval);
323     return retval;
326 Inkscape::XML::Node *
327 Parameter::document_param_node (SPDocument * doc)
329     Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
330     Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc));
331     Inkscape::XML::Node * params = NULL;
333     GQuark const name_quark = g_quark_from_string("inkscape:extension-params");
335     for (Inkscape::XML::Node * child = defs->firstChild();
336             child != NULL;
337             child = child->next()) {
338         if ((GQuark)child->code() == name_quark &&
339                 !strcmp(child->attribute("extension"), extension->get_id())) {
340             params = child;
341             break;
342         }
343     }
345     if (params == NULL) {
346         params = xml_doc->createElement("inkscape:extension-param");
347         params->setAttribute("extension", extension->get_id());
348         defs->appendChild(params);
349     }
351     return params;
354 /** \brief  Basically, if there is no widget pass a NULL. */
355 Gtk::Widget *
356 Parameter::get_widget (SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/, sigc::signal<void> * /*changeSignal*/)
358     return NULL;
361 /** \brief  If I'm not sure which it is, just don't return a value. */
362 void
363 Parameter::string (std::string &/*string*/)
365     return;
368 void
369 Parameter::string (std::list <std::string> &list)
371     std::string value;
372     string(value);
373     if (value == "") {
374         return;
375     }
377     std::string final;
378     final += "--";
379     final += name();
380     final += "=";
381     final += value;
383     list.insert(list.end(), final);
384     return;
387 }  /* namespace Extension */
388 }  /* namespace Inkscape */
390 /*
391   Local Variables:
392   mode:c++
393   c-file-style:"stroustrup"
394   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
395   indent-tabs-mode:nil
396   fill-column:99
397   End:
398 */
399 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :