Code

fix 1520018: sync up the embed/not embed transform logic when ungrouping with that...
[inkscape.git] / src / extension / parameter.cpp
1 /** \file
2  * Parameters for extensions.
3  */
5 /*
6  * Author:
7  *   Ted Gould <ted@gould.cx>
8  *
9  * Copyright (C) 2006 Johan Engelen <johan@shouraizou.nl>
10  * Copyright (C) 2005-2006 Author
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
20 #include <gtkmm/adjustment.h>
21 #include <gtkmm/box.h>
22 #include <gtkmm/spinbutton.h>
24 #include <glibmm/i18n.h>
26 #include <xml/node.h>
28 #include "extension.h"
29 #include "prefs-utils.h"
30 #include "document-private.h"
31 #include "sp-object.h"
33 #include "parameter.h"
34 #include "paramnotebook.h"
35 #include "paramenum.h"
37 /** \brief  The root directory in the preferences database for extension
38             related parameters. */
39 #define PREF_DIR "extensions"
41 namespace Inkscape {
42 namespace Extension {
44 /** \brief  A description parameter */
45 class ParamDescription : public Parameter {
46 private:
47     /** \brief  Internal value. */
48     gchar * _value;
49 public:
50     ParamDescription(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
51     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
52 };
54 /** \brief  A boolean parameter */
55 class ParamBool : public Parameter {
56 private:
57     /** \brief  Internal value. */
58     bool _value;
59 public:
60     ParamBool(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
61     /** \brief  Returns \c _value */
62     bool get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
63     bool set (bool in, SPDocument * doc, Inkscape::XML::Node * node);
64     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
65     Glib::ustring * string (void);
66 };
68 /** \brief  Use the superclass' allocator and set the \c _value */
69 ParamBool::ParamBool (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
70         Parameter(name, guitext, desc, scope, ext), _value(false)
71 {
72     const char * defaultval = NULL;
73     if (sp_repr_children(xml) != NULL)
74         defaultval = sp_repr_children(xml)->content();
76     if (defaultval != NULL && (!strcmp(defaultval, "TRUE") || !strcmp(defaultval, "true") || !strcmp(defaultval, "1"))) {
77         _value = true;
78     } else {
79         _value = false;
80     }
82     gchar * pref_name = this->pref_name();
83     _value = (bool)prefs_get_int_attribute(PREF_DIR, pref_name, _value);
84     g_free(pref_name);
86     return;
87 }
89 class ParamInt : public Parameter {
90 private:
91     /** \brief  Internal value. */
92     int _value;
93     int _min;
94     int _max;
95 public:
96     ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
97     /** \brief  Returns \c _value */
98     int get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
99     int set (int in, SPDocument * doc, Inkscape::XML::Node * node);
100     int max (void) { return _max; }
101     int min (void) { return _min; }
102     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
103     Glib::ustring * string (void);
104 };
106 /** \brief  Use the superclass' allocator and set the \c _value */
107 ParamInt::ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
108         Parameter(name, guitext, desc, scope, ext), _value(0), _min(0), _max(10)
110     const char * defaultval = NULL;
111     if (sp_repr_children(xml) != NULL)
112         defaultval = sp_repr_children(xml)->content();
113     if (defaultval != NULL) {
114         _value = atoi(defaultval);
115     }
117     const char * maxval = xml->attribute("max");
118     if (maxval != NULL)
119         _max = atoi(maxval);
121     const char * minval = xml->attribute("min");
122     if (minval != NULL)
123         _min = atoi(minval);
125     /* We're handling this by just killing both values */
126     if (_max < _min) {
127         _max = 10;
128         _min = 0;
129     }
131     gchar * pref_name = this->pref_name();
132     _value = prefs_get_int_attribute(PREF_DIR, pref_name, _value);
133     g_free(pref_name);
135     // std::cout << "New Int::  value: " << _value << "  max: " << _max << "  min: " << _min << std::endl;
137     if (_value > _max) _value = _max;
138     if (_value < _min) _value = _min;
140     return;
143 class ParamFloat : public Parameter {
144 private:
145     /** \brief  Internal value. */
146     float _value;
147     float _min;
148     float _max;
149 public:
150     ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
151     /** \brief  Returns \c _value */
152     float get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
153     float set (float in, SPDocument * doc, Inkscape::XML::Node * node);
154     float max (void) { return _max; }
155     float min (void) { return _min; }
156     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
157     Glib::ustring * string (void);
158 };
160 /** \brief  Use the superclass' allocator and set the \c _value */
161 ParamFloat::ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
162         Parameter(name, guitext, desc, scope, ext), _value(0.0), _min(0.0), _max(10.0)
164     const char * defaultval = NULL;
165     if (sp_repr_children(xml) != NULL)
166         defaultval = sp_repr_children(xml)->content();
167     if (defaultval != NULL) {
168         _value = atof(defaultval);
169     }
171     const char * maxval = xml->attribute("max");
172     if (maxval != NULL)
173         _max = atof(maxval);
175     const char * minval = xml->attribute("min");
176     if (minval != NULL)
177         _min = atof(minval);
179     /* We're handling this by just killing both values */
180     if (_max < _min) {
181         _max = 10.0;
182         _min = 0.0;
183     }
185     gchar * pref_name = this->pref_name();
186     _value = prefs_get_double_attribute(PREF_DIR, pref_name, _value);
187     g_free(pref_name);
189     // std::cout << "New Float::  value: " << _value << "  max: " << _max << "  min: " << _min << std::endl;
191     if (_value > _max) _value = _max;
192     if (_value < _min) _value = _min;
194     return;
197 class ParamString : public Parameter {
198 private:
199     /** \brief  Internal value.  This should point to a string that has
200                 been allocated in memory.  And should be free'd. */
201     gchar * _value;
202 public:
203     ParamString(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
204     ~ParamString(void);
205     /** \brief  Returns \c _value, with a \i const to protect it. */
206     const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
207     const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
208     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
209     Glib::ustring * string (void);
210 };
212 class ParamEnum : public Parameter {
213 private:
214     class Choice {
215     public:
216         gchar * _gui_name;
217         gchar * _value;
218         Choice(gchar * gui_name, gchar * value) : _gui_name(NULL), _value(NULL) {
219             if (gui_name != NULL)
220                 _gui_name = g_strdup(_(gui_name));
221             if (value != NULL)
222                 _value = g_strdup(value);
223             return;
224         };
225         ~Choice (void) {
226             g_free(_gui_name);
227             g_free(_value);
228         };
229     }; /* class Choice */
230     /** \brief  Internal value.  This should point to a string that has
231                 been allocated in memory.  And should be free'd. */
232     Choice * _current_choice;
233     typedef std::list<Choice *> choice_list_t;
234     choice_list_t _choice_list;
235 public:
236     ParamEnum(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
237     ~ParamEnum(void);
238     /** \brief  Returns \c _value, with a \i const to protect it. */
239     const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _current_choice != NULL ? _current_choice->_value : NULL; }
240     const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
241     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
242     Glib::ustring * string (void);
243 }; /* class ParamEnum */
246 /**
247     \return None
248     \brief  This function creates a parameter that can be used later.  This
249             is typically done in the creation of the extension and defined
250             in the XML file describing the extension (it's private so people
251             have to use the system) :)
252     \param  in_repr  The XML describing the parameter
254     This function first grabs all of the data out of the Repr and puts
255     it into local variables.  Actually, these are just pointers, and the
256     data is not duplicated so we need to be careful with it.  If there
257     isn't a name or a type in the XML, then no parameter is created as
258     the function just returns.
260     From this point on, we're pretty committed as we've allocated an
261     object and we're starting to fill it.  The name is set first, and
262     is created with a strdup to actually allocate memory for it.  Then
263     there is a case statement (roughly because strcmp requires 'ifs')
264     based on what type of parameter this is.  Depending which type it
265     is, the value is interpreted differently, but they are relatively
266     straight forward.  In all cases the value is set to the default
267     value from the XML and the type is set to the interpreted type.
268 */
269 Parameter *
270 Parameter::make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
272     const char * name;
273     const char * type;
274     const char * guitext;
275     const char * desc;
276     const char * scope_str;
277     Parameter::_scope_t scope = Parameter::SCOPE_USER;
279     name = in_repr->attribute("name");
280     type = in_repr->attribute("type");
281     guitext = in_repr->attribute("gui-text");
282     if (guitext == NULL)
283         guitext = in_repr->attribute("_gui-text");
284     desc = in_repr->attribute("gui-description");
285     if (desc == NULL)
286         desc = in_repr->attribute("_gui-description");
287     scope_str = in_repr->attribute("scope");
289     /* In this case we just don't have enough information */
290     if (name == NULL || type == NULL) {
291         return NULL;
292     }
294     if (scope_str != NULL) {
295         if (!strcmp(scope_str, "user")) {
296             scope = Parameter::SCOPE_USER;
297         } else if (!strcmp(scope_str, "document")) {
298             scope = Parameter::SCOPE_DOCUMENT;
299         } else if (!strcmp(scope_str, "node")) {
300             scope = Parameter::SCOPE_NODE;
301         }
302     }
304     Parameter * param = NULL;
305     if (!strcmp(type, "boolean")) {
306         param = new ParamBool(name, guitext, desc, scope, in_ext, in_repr);
307     } else if (!strcmp(type, "int")) {
308         param = new ParamInt(name, guitext, desc, scope, in_ext, in_repr);
309     } else if (!strcmp(type, "float")) {
310         param = new ParamFloat(name, guitext, desc, scope, in_ext, in_repr);
311     } else if (!strcmp(type, "string")) {
312         param = new ParamString(name, guitext, desc, scope, in_ext, in_repr);
313     } else if (!strcmp(type, "description")) {
314         param = new ParamDescription(name, guitext, desc, scope, in_ext, in_repr);
315     } else if (!strcmp(type, "enum")) {
316         param = new ParamComboBox(name, guitext, desc, scope, in_ext, in_repr);
317     } else if (!strcmp(type, "notebook")) {
318         param = new ParamNotebook(name, guitext, desc, scope, in_ext, in_repr);
319     }
321     /* Note: param could equal NULL */
322     return param;
325 /** \brief  A function to set the \c _value
326     \param  in   The value to set to
327     \param  doc  A document that should be used to set the value.
328     \param  node The node where the value may be placed
330     This function sets the internal value, but it also sets the value
331     in the preferences structure.  To put it in the right place, \c PREF_DIR
332     and \c pref_name() are used.
333 */
334 bool
335 ParamBool::set (bool in, SPDocument * doc, Inkscape::XML::Node * node)
337     _value = in;
339     gchar * prefname = this->pref_name();
340     prefs_set_int_attribute(PREF_DIR, prefname, _value == true ? 1 : 0);
341     g_free(prefname);
343     return _value;
346 /** \brief  A function to set the \c _value
347     \param  in   The value to set to
348     \param  doc  A document that should be used to set the value.
349     \param  node The node where the value may be placed
351     This function sets the internal value, but it also sets the value
352     in the preferences structure.  To put it in the right place, \c PREF_DIR
353     and \c pref_name() are used.
354 */
355 int
356 ParamInt::set (int in, SPDocument * doc, Inkscape::XML::Node * node)
358     _value = in;
359     if (_value > _max) _value = _max;
360     if (_value < _min) _value = _min;
362     gchar * prefname = this->pref_name();
363     prefs_set_int_attribute(PREF_DIR, prefname, _value);
364     g_free(prefname);
366     return _value;
369 /** \brief  A function to set the \c _value
370     \param  in   The value to set to
371     \param  doc  A document that should be used to set the value.
372     \param  node The node where the value may be placed
374     This function sets the internal value, but it also sets the value
375     in the preferences structure.  To put it in the right place, \c PREF_DIR
376     and \c pref_name() are used.
377 */
378 float
379 ParamFloat::set (float in, SPDocument * doc, Inkscape::XML::Node * node)
381     _value = in;
382     if (_value > _max) _value = _max;
383     if (_value < _min) _value = _min;
385     gchar * prefname = this->pref_name();
386     prefs_set_double_attribute(PREF_DIR, prefname, _value);
387     g_free(prefname);
389     return _value;
392 /** \brief  A function to set the \c _value
393     \param  in   The value to set to
394     \param  doc  A document that should be used to set the value.
395     \param  node The node where the value may be placed
397     This function sets the internal value, but it also sets the value
398     in the preferences structure.  To put it in the right place, \c PREF_DIR
399     and \c pref_name() are used.
401     To copy the data into _value the old memory must be free'd first.
402     It is important to note that \c g_free handles \c NULL just fine.  Then
403     the passed in value is duplicated using \c g_strdup().
404 */
405 const gchar *
406 ParamString::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
408     if (in == NULL) return NULL; /* Can't have NULL string */
410     if (_value != NULL)
411         g_free(_value);
412     _value = g_strdup(in);
414     gchar * prefname = this->pref_name();
415     prefs_set_string_attribute(PREF_DIR, prefname, _value);
416     g_free(prefname);
418     return _value;
421 /** \brief  Wrapper to cast to the object and use it's function.  */
422 bool
423 Parameter::get_bool (const SPDocument * doc, const Inkscape::XML::Node * node)
425     ParamBool * boolpntr;
426     boolpntr = dynamic_cast<ParamBool *>(this);
427     if (boolpntr == NULL)
428         throw Extension::param_wrong_type();
429     return boolpntr->get(doc, node);
432 /** \brief  Wrapper to cast to the object and use it's function.  */
433 int
434 Parameter::get_int (const SPDocument * doc, const Inkscape::XML::Node * node)
436     ParamInt * intpntr;
437     intpntr = dynamic_cast<ParamInt *>(this);
438     if (intpntr == NULL)
439         throw Extension::param_wrong_type();
440     return intpntr->get(doc, node);
443 /** \brief  Wrapper to cast to the object and use it's function.  */
444 float
445 Parameter::get_float (const SPDocument * doc, const Inkscape::XML::Node * node)
447     ParamFloat * floatpntr;
448     floatpntr = dynamic_cast<ParamFloat *>(this);
449     if (floatpntr == NULL)
450         throw Extension::param_wrong_type();
451     return floatpntr->get(doc, node);
454 /** \brief  Wrapper to cast to the object and use it's function.  */
455 const gchar *
456 Parameter::get_string (const SPDocument * doc, const Inkscape::XML::Node * node)
458     ParamString * stringpntr;
459     stringpntr = dynamic_cast<ParamString *>(this);
460     if (stringpntr == NULL)
461         throw Extension::param_wrong_type();
462     return stringpntr->get(doc, node);
465 /** \brief  Wrapper to cast to the object and use it's function.  */
466 bool
467 Parameter::set_bool (bool in, SPDocument * doc, Inkscape::XML::Node * node)
469     ParamBool * boolpntr;
470     boolpntr = dynamic_cast<ParamBool *>(this);
471     if (boolpntr == NULL)
472         throw Extension::param_wrong_type();
473     return boolpntr->set(in, doc, node);
476 /** \brief  Wrapper to cast to the object and use it's function.  */
477 int
478 Parameter::set_int (int in, SPDocument * doc, Inkscape::XML::Node * node)
480     ParamInt * intpntr;
481     intpntr = dynamic_cast<ParamInt *>(this);
482     if (intpntr == NULL)
483         throw Extension::param_wrong_type();
484     return intpntr->set(in, doc, node);
487 /** \brief  Wrapper to cast to the object and use it's function.  */
488 float
489 Parameter::set_float (float in, SPDocument * doc, Inkscape::XML::Node * node)
491     ParamFloat * floatpntr;
492     floatpntr = dynamic_cast<ParamFloat *>(this);
493     if (floatpntr == NULL)
494         throw Extension::param_wrong_type();
495     return floatpntr->set(in, doc, node);
498 /** \brief  Wrapper to cast to the object and use it's function.  */
499 const gchar *
500 Parameter::set_string (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
502     ParamString * stringpntr;
503     stringpntr = dynamic_cast<ParamString *>(this);
504     if (stringpntr == NULL)
505         throw Extension::param_wrong_type();
506     return stringpntr->set(in, doc, node);
509 /** \brief  Initialize the object, to do that, copy the data. */
510 ParamString::ParamString (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
511     Parameter(name, guitext, desc, scope, ext), _value(NULL)
513     const char * defaultval = NULL;
514     if (sp_repr_children(xml) != NULL)
515         defaultval = sp_repr_children(xml)->content();
517     gchar * pref_name = this->pref_name();
518     const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
519     g_free(pref_name);
521     if (paramval != NULL)
522         defaultval = paramval;
523     if (defaultval != NULL)
524         _value = g_strdup(defaultval);
526     return;
529 /** \brief  Free the allocated data. */
530 ParamString::~ParamString(void)
532     g_free(_value);
535 /** \brief  Oop, now that we need a parameter, we need it's name.  */
536 Parameter::Parameter (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext) :
537     extension(ext), _name(NULL), _desc(NULL), _scope(scope), _text(NULL)
539     if (name != NULL)
540         _name = g_strdup(name);
541     if (desc != NULL) {
542         _desc = g_strdup(desc);
543         // printf("Adding description: '%s' on '%s'\n", _desc, _name);
544     }
547     if (guitext != NULL)
548         _text = g_strdup(guitext);
549     else
550         _text = g_strdup(name);
552     return;
555 /** \brief  Just free the allocated name. */
556 Parameter::~Parameter (void)
558     g_free(_name);
559     g_free(_text);
562 /** \brief  Build the name to write the parameter from the extension's
563             ID and the name of this parameter. */
564 gchar *
565 Parameter::pref_name (void)
567     return g_strdup_printf("%s.%s", extension->get_id(), _name);
570 Inkscape::XML::Node *
571 Parameter::find_child (Inkscape::XML::Node * adult)
573     return sp_repr_lookup_child(adult, "name", _name);
576 Inkscape::XML::Node *
577 Parameter::new_child (Inkscape::XML::Node * parent)
579     Inkscape::XML::Node * retval;
580     retval = sp_repr_new("inkscape:extension-param");
581     retval->setAttribute("name", _name);
583     parent->appendChild(retval);
584     return retval;
587 Inkscape::XML::Node *
588 Parameter::document_param_node (SPDocument * doc)
590     Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc));
591     Inkscape::XML::Node * params = NULL;
593     GQuark const name_quark = g_quark_from_string("inkscape:extension-params");
595     for (Inkscape::XML::Node * child = defs->firstChild();
596             child != NULL;
597             child = child->next()) {
598         if ((GQuark)child->code() == name_quark &&
599                 !strcmp(child->attribute("extension"), extension->get_id())) {
600             params = child;
601             break;
602         }
603     }
605     if (params == NULL) {
606         params = sp_repr_new("inkscape:extension-param");
607         params->setAttribute("extension", extension->get_id());
608         defs->appendChild(params);
609     }
611     return params;
614 /** \brief  Basically, if there is no widget pass a NULL. */
615 Gtk::Widget *
616 Parameter::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
618     return NULL;
621 /** \brief  If I'm not sure which it is, just don't return a value. */
622 Glib::ustring *
623 Parameter::string (void)
625     Glib::ustring * mystring = new Glib::ustring("");
626     return mystring;
629 /** \brief  A class to make an adjustment that uses Extension params */
630 class ParamFloatAdjustment : public Gtk::Adjustment {
631     /** The parameter to adjust */
632     ParamFloat * _pref;
633     SPDocument * _doc;
634     Inkscape::XML::Node * _node;
635 public:
636     /** \brief  Make the adjustment using an extension and the string
637                 describing the parameter. */
638     ParamFloatAdjustment (ParamFloat * param, SPDocument * doc, Inkscape::XML::Node * node) :
639             Gtk::Adjustment(0.0, param->min(), param->max(), 0.1), _pref(param), _doc(doc), _node(node) {
640         this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
641         this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed));
642         return;
643     };
645     void val_changed (void);
646 }; /* class ParamFloatAdjustment */
648 /** \brief  A function to respond to the value_changed signal from the
649             adjustment.
651     This function just grabs the value from the adjustment and writes
652     it to the parameter.  Very simple, but yet beautiful.
653 */
654 void
655 ParamFloatAdjustment::val_changed (void)
657     // std::cout << "Value Changed to: " << this->get_value() << std::endl;
658     _pref->set(this->get_value(), _doc, _node);
659     return;
662 /** \brief  A class to make an adjustment that uses Extension params */
663 class ParamIntAdjustment : public Gtk::Adjustment {
664     /** The parameter to adjust */
665     ParamInt * _pref;
666     SPDocument * _doc;
667     Inkscape::XML::Node * _node;
668 public:
669     /** \brief  Make the adjustment using an extension and the string
670                 describing the parameter. */
671     ParamIntAdjustment (ParamInt * param, SPDocument * doc, Inkscape::XML::Node * node) :
672             Gtk::Adjustment(0.0, param->min(), param->max(), 1.0), _pref(param), _doc(doc), _node(node) {
673         this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
674         this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed));
675         return;
676     };
678     void val_changed (void);
679 }; /* class ParamIntAdjustment */
681 /** \brief  A function to respond to the value_changed signal from the
682             adjustment.
684     This function just grabs the value from the adjustment and writes
685     it to the parameter.  Very simple, but yet beautiful.
686 */
687 void
688 ParamIntAdjustment::val_changed (void)
690     // std::cout << "Value Changed to: " << this->get_value() << std::endl;
691     _pref->set((int)this->get_value(), _doc, _node);
692     return;
695 /**
696     \brief  Creates a Float Adjustment for a float parameter
698     Builds a hbox with a label and a float adjustment in it.
699 */
700 Gtk::Widget *
701 ParamFloat::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
703     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
705     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
706     label->show();
707     hbox->pack_start(*label, true, true);
709     ParamFloatAdjustment * fadjust = Gtk::manage(new ParamFloatAdjustment(this, doc, node));
710     Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 0.1, 1));
711     spin->show();
712     hbox->pack_start(*spin, false, false);
714     hbox->show();
716     return dynamic_cast<Gtk::Widget *>(hbox);
719 /**
720     \brief  Creates a Int Adjustment for a int parameter
722     Builds a hbox with a label and a int adjustment in it.
723 */
724 Gtk::Widget *
725 ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
727     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
729     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
730     label->show();
731     hbox->pack_start(*label, true, true);
733     ParamIntAdjustment * fadjust = Gtk::manage(new ParamIntAdjustment(this, doc, node));
734     Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 1.0, 0));
735     spin->show();
736     hbox->pack_start(*spin, false, false);
738     hbox->show();
740     return dynamic_cast<Gtk::Widget *>(hbox);
743 /** \brief  A check button which is Param aware.  It works with the
744             parameter to change it's value as the check button changes
745             value. */
746 class ParamBoolCheckButton : public Gtk::CheckButton {
747 private:
748     /** \brief  Param to change */
749     ParamBool * _pref;
750     SPDocument * _doc;
751     Inkscape::XML::Node * _node;
752 public:
753     /** \brief  Initialize the check button
754         \param  param  Which parameter to adjust on changing the check button
756         This function sets the value of the checkbox to be that of the
757         parameter, and then sets up a callback to \c on_toggle.
758     */
759     ParamBoolCheckButton (ParamBool * param, SPDocument * doc, Inkscape::XML::Node * node) :
760             Gtk::CheckButton(), _pref(param), _doc(doc), _node(node) {
761         this->set_active(_pref->get(NULL, NULL) /**\todo fix */);
762         this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle));
763         return;
764     }
765     void on_toggle (void);
766 };
768 /**
769     \brief  A function to respond to the check box changing
771     Adjusts the value of the preference to match that in the check box.
772 */
773 void
774 ParamBoolCheckButton::on_toggle (void)
776     _pref->set(this->get_active(), NULL /**\todo fix this */, NULL);
777     return;
780 /**
781     \brief  Creates a bool check button for a bool parameter
783     Builds a hbox with a label and a check button in it.
784 */
785 Gtk::Widget *
786 ParamBool::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
788     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
790     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
791     label->show();
792     hbox->pack_start(*label, true, true);
794     ParamBoolCheckButton * checkbox = new ParamBoolCheckButton(this, doc, node);
795     checkbox->show();
796     hbox->pack_start(*checkbox, false, false);
798     hbox->show();
800     return dynamic_cast<Gtk::Widget *>(hbox);
803 /** \brief  A special category of Gtk::Entry to handle string parameteres */
804 class ParamStringEntry : public Gtk::Entry {
805 private:
806     ParamString * _pref;
807     SPDocument * _doc;
808     Inkscape::XML::Node * _node;
809 public:
810     /** \brief  Build a string preference for the given parameter
811         \param  pref  Where to get the string from, and where to put it
812                       when it changes.
813     */
814     ParamStringEntry (ParamString * pref, SPDocument * doc, Inkscape::XML::Node * node) :
815         Gtk::Entry(), _pref(pref), _doc(doc), _node(node) {
816         if (_pref->get(NULL, NULL) != NULL)
817             this->set_text(Glib::ustring(_pref->get(NULL, NULL)));
818         this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text));
819     };
820     void changed_text (void);
821 };
823 /** \brief  Respond to the text box changing
825     This function responds to the box changing by grabbing the value
826     from the text box and putting it in the parameter.
827 */
828 void
829 ParamStringEntry::changed_text (void)
831     Glib::ustring data = this->get_text();
832     _pref->set(data.c_str(), _doc, _node);
833     return;
836 /**
837     \brief  Creates a text box for the string parameter
839     Builds a hbox with a label and a text box in it.
840 */
841 Gtk::Widget *
842 ParamString::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
844     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
846     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
847     label->show();
848     hbox->pack_start(*label, false, false);
850     ParamStringEntry * textbox = new ParamStringEntry(this, doc, node);
851     textbox->show();
852     hbox->pack_start(*textbox, true, true);
854     hbox->show();
856     return dynamic_cast<Gtk::Widget *>(hbox);
859 /** \brief  Return 'true' or 'false' */
860 Glib::ustring *
861 ParamBool::string (void)
863     Glib::ustring * mystring;
865     if (_value)
866         mystring = new Glib::ustring("true");
867     else
868         mystring = new Glib::ustring("false");
870     return mystring;
873 /** \brief  Return the value as a string */
874 Glib::ustring *
875 ParamInt::string (void)
877     char startstring[32];
878     sprintf(startstring, "%d", _value);
879     Glib::ustring * mystring = new Glib::ustring(startstring);
880     return mystring;
883 /** \brief  Return the value as a string */
884 Glib::ustring *
885 ParamFloat::string (void)
887     char startstring[G_ASCII_DTOSTR_BUF_SIZE];
888     g_ascii_dtostr(startstring, G_ASCII_DTOSTR_BUF_SIZE, _value);
889     Glib::ustring * mystring = new Glib::ustring(startstring);
890     return mystring;
893 /** \brief  Return the value as a string */
894 Glib::ustring *
895 ParamString::string (void)
897     Glib::ustring * mystring = new Glib::ustring("");
898     *mystring += "\"";
899     *mystring += _value;
900     *mystring += "\"";
901     return mystring;
904 /** \brief  Create a label for the description */
905 Gtk::Widget *
906 ParamDescription::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
908     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_value)));
909     label->set_line_wrap();
910     label->show();
912     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
913     hbox->pack_start(*label, true, true, 5);
914     hbox->show();
916     return hbox;
919 /** \brief  Initialize the object, to do that, copy the data. */
920 ParamDescription::ParamDescription (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
921     Parameter(name, guitext, desc, scope, ext), _value(NULL)
923     // printf("Building Description\n");
924     const char * defaultval = NULL;
925     if (sp_repr_children(xml) != NULL)
926         defaultval = sp_repr_children(xml)->content();
928     if (defaultval != NULL)
929         _value = g_strdup(defaultval);
931     return;
934 ParamEnum::ParamEnum (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
935     Parameter(name, guitext, desc, scope, ext), _current_choice(NULL)
937     return;
940 ParamEnum::~ParamEnum (void)
945 /** \brief  Return the value as a string */
946 Glib::ustring *
947 ParamEnum::string (void)
949     Glib::ustring * mystring = new Glib::ustring("");
950     *mystring += "\"";
951     *mystring += this->get(NULL, NULL);
952     *mystring += "\"";
953     return mystring;
956 Gtk::Widget *
957 ParamEnum::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
959     return NULL;
962 const gchar *
963 ParamEnum::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
965     return NULL;
969 }  /* namespace Extension */
970 }  /* namespace Inkscape */
972 /*
973   Local Variables:
974   mode:c++
975   c-file-style:"stroustrup"
976   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
977   indent-tabs-mode:nil
978   fill-column:99
979   End:
980 */
981 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :