Code

Fixed crash when draw height was zero.
[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"
36 #include "paramradiobutton.h"
38 /** \brief  The root directory in the preferences database for extension
39             related parameters. */
40 #define PREF_DIR "extensions"
42 namespace Inkscape {
43 namespace Extension {
45 /** \brief  A description parameter */
46 class ParamDescription : public Parameter {
47 private:
48     /** \brief  Internal value. */
49     gchar * _value;
50 public:
51     ParamDescription(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
52     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
53 };
55 /** \brief  A boolean parameter */
56 class ParamBool : public Parameter {
57 private:
58     /** \brief  Internal value. */
59     bool _value;
60 public:
61     ParamBool(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
62     /** \brief  Returns \c _value */
63     bool get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
64     bool set (bool in, SPDocument * doc, Inkscape::XML::Node * node);
65     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
66     Glib::ustring * string (void);
67 };
69 /** \brief  Use the superclass' allocator and set the \c _value */
70 ParamBool::ParamBool (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
71         Parameter(name, guitext, desc, scope, ext), _value(false)
72 {
73     const char * defaultval = NULL;
74     if (sp_repr_children(xml) != NULL)
75         defaultval = sp_repr_children(xml)->content();
77     if (defaultval != NULL && (!strcmp(defaultval, "TRUE") || !strcmp(defaultval, "true") || !strcmp(defaultval, "1"))) {
78         _value = true;
79     } else {
80         _value = false;
81     }
83     gchar * pref_name = this->pref_name();
84     _value = (bool)prefs_get_int_attribute(PREF_DIR, pref_name, _value);
85     g_free(pref_name);
87     return;
88 }
90 class ParamInt : public Parameter {
91 private:
92     /** \brief  Internal value. */
93     int _value;
94     int _min;
95     int _max;
96 public:
97     ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
98     /** \brief  Returns \c _value */
99     int get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
100     int set (int in, SPDocument * doc, Inkscape::XML::Node * node);
101     int max (void) { return _max; }
102     int min (void) { return _min; }
103     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
104     Glib::ustring * string (void);
105 };
107 /** \brief  Use the superclass' allocator and set the \c _value */
108 ParamInt::ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
109         Parameter(name, guitext, desc, scope, ext), _value(0), _min(0), _max(10)
111     const char * defaultval = NULL;
112     if (sp_repr_children(xml) != NULL)
113         defaultval = sp_repr_children(xml)->content();
114     if (defaultval != NULL) {
115         _value = atoi(defaultval);
116     }
118     const char * maxval = xml->attribute("max");
119     if (maxval != NULL)
120         _max = atoi(maxval);
122     const char * minval = xml->attribute("min");
123     if (minval != NULL)
124         _min = atoi(minval);
126     /* We're handling this by just killing both values */
127     if (_max < _min) {
128         _max = 10;
129         _min = 0;
130     }
132     gchar * pref_name = this->pref_name();
133     _value = prefs_get_int_attribute(PREF_DIR, pref_name, _value);
134     g_free(pref_name);
136     // std::cout << "New Int::  value: " << _value << "  max: " << _max << "  min: " << _min << std::endl;
138     if (_value > _max) _value = _max;
139     if (_value < _min) _value = _min;
141     return;
144 class ParamFloat : public Parameter {
145 private:
146     /** \brief  Internal value. */
147     float _value;
148     float _min;
149     float _max;
150 public:
151     ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
152     /** \brief  Returns \c _value */
153     float get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
154     float set (float in, SPDocument * doc, Inkscape::XML::Node * node);
155     float max (void) { return _max; }
156     float min (void) { return _min; }
157     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
158     Glib::ustring * string (void);
159 };
161 /** \brief  Use the superclass' allocator and set the \c _value */
162 ParamFloat::ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
163         Parameter(name, guitext, desc, scope, ext), _value(0.0), _min(0.0), _max(10.0)
165     const char * defaultval = NULL;
166     if (sp_repr_children(xml) != NULL)
167         defaultval = sp_repr_children(xml)->content();
168     if (defaultval != NULL) {
169         _value = atof(defaultval);
170     }
172     const char * maxval = xml->attribute("max");
173     if (maxval != NULL)
174         _max = atof(maxval);
176     const char * minval = xml->attribute("min");
177     if (minval != NULL)
178         _min = atof(minval);
180     /* We're handling this by just killing both values */
181     if (_max < _min) {
182         _max = 10.0;
183         _min = 0.0;
184     }
186     gchar * pref_name = this->pref_name();
187     _value = prefs_get_double_attribute(PREF_DIR, pref_name, _value);
188     g_free(pref_name);
190     // std::cout << "New Float::  value: " << _value << "  max: " << _max << "  min: " << _min << std::endl;
192     if (_value > _max) _value = _max;
193     if (_value < _min) _value = _min;
195     return;
198 class ParamString : public Parameter {
199 private:
200     /** \brief  Internal value.  This should point to a string that has
201                 been allocated in memory.  And should be free'd. */
202     gchar * _value;
203 public:
204     ParamString(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
205     ~ParamString(void);
206     /** \brief  Returns \c _value, with a \i const to protect it. */
207     const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
208     const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
209     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
210     Glib::ustring * string (void);
211 };
213 class ParamEnum : public Parameter {
214 private:
215     class Choice {
216     public:
217         gchar * _gui_name;
218         gchar * _value;
219         Choice(gchar * gui_name, gchar * value) : _gui_name(NULL), _value(NULL) {
220             if (gui_name != NULL)
221                 _gui_name = g_strdup(_(gui_name));
222             if (value != NULL)
223                 _value = g_strdup(value);
224             return;
225         };
226         ~Choice (void) {
227             g_free(_gui_name);
228             g_free(_value);
229         };
230     }; /* class Choice */
231     /** \brief  Internal value.  This should point to a string that has
232                 been allocated in memory.  And should be free'd. */
233     Choice * _current_choice;
234     typedef std::list<Choice *> choice_list_t;
235     choice_list_t _choice_list;
236 public:
237     ParamEnum(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
238     ~ParamEnum(void);
239     /** \brief  Returns \c _value, with a \i const to protect it. */
240     const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _current_choice != NULL ? _current_choice->_value : NULL; }
241     const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
242     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
243     Glib::ustring * string (void);
244 }; /* class ParamEnum */
247 /**
248     \return None
249     \brief  This function creates a parameter that can be used later.  This
250             is typically done in the creation of the extension and defined
251             in the XML file describing the extension (it's private so people
252             have to use the system) :)
253     \param  in_repr  The XML describing the parameter
255     This function first grabs all of the data out of the Repr and puts
256     it into local variables.  Actually, these are just pointers, and the
257     data is not duplicated so we need to be careful with it.  If there
258     isn't a name or a type in the XML, then no parameter is created as
259     the function just returns.
261     From this point on, we're pretty committed as we've allocated an
262     object and we're starting to fill it.  The name is set first, and
263     is created with a strdup to actually allocate memory for it.  Then
264     there is a case statement (roughly because strcmp requires 'ifs')
265     based on what type of parameter this is.  Depending which type it
266     is, the value is interpreted differently, but they are relatively
267     straight forward.  In all cases the value is set to the default
268     value from the XML and the type is set to the interpreted type.
269 */
270 Parameter *
271 Parameter::make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
273     const char * name;
274     const char * type;
275     const char * guitext;
276     const char * desc;
277     const char * scope_str;
278     Parameter::_scope_t scope = Parameter::SCOPE_USER;
280     name = in_repr->attribute("name");
281     type = in_repr->attribute("type");
282     guitext = in_repr->attribute("gui-text");
283     if (guitext == NULL)
284         guitext = in_repr->attribute("_gui-text");
285     desc = in_repr->attribute("gui-description");
286     if (desc == NULL)
287         desc = in_repr->attribute("_gui-description");
288     scope_str = in_repr->attribute("scope");
290     /* In this case we just don't have enough information */
291     if (name == NULL || type == NULL) {
292         return NULL;
293     }
295     if (scope_str != NULL) {
296         if (!strcmp(scope_str, "user")) {
297             scope = Parameter::SCOPE_USER;
298         } else if (!strcmp(scope_str, "document")) {
299             scope = Parameter::SCOPE_DOCUMENT;
300         } else if (!strcmp(scope_str, "node")) {
301             scope = Parameter::SCOPE_NODE;
302         }
303     }
305     Parameter * param = NULL;
306     if (!strcmp(type, "boolean")) {
307         param = new ParamBool(name, guitext, desc, scope, in_ext, in_repr);
308     } else if (!strcmp(type, "int")) {
309         param = new ParamInt(name, guitext, desc, scope, in_ext, in_repr);
310     } else if (!strcmp(type, "float")) {
311         param = new ParamFloat(name, guitext, desc, scope, in_ext, in_repr);
312     } else if (!strcmp(type, "string")) {
313         param = new ParamString(name, guitext, desc, scope, in_ext, in_repr);
314     } else if (!strcmp(type, "description")) {
315         param = new ParamDescription(name, guitext, desc, scope, in_ext, in_repr);
316     } else if (!strcmp(type, "enum")) {
317         param = new ParamComboBox(name, guitext, desc, scope, in_ext, in_repr);
318     } else if (!strcmp(type, "notebook")) {
319         param = new ParamNotebook(name, guitext, desc, scope, in_ext, in_repr);
320     } else if (!strcmp(type, "optiongroup")) {
321         param = new ParamRadioButton(name, guitext, desc, scope, in_ext, in_repr);
322     }
324     /* Note: param could equal NULL */
325     return param;
328 /** \brief  A function to set the \c _value
329     \param  in   The value to set to
330     \param  doc  A document that should be used to set the value.
331     \param  node The node where the value may be placed
333     This function sets the internal value, but it also sets the value
334     in the preferences structure.  To put it in the right place, \c PREF_DIR
335     and \c pref_name() are used.
336 */
337 bool
338 ParamBool::set (bool in, SPDocument * doc, Inkscape::XML::Node * node)
340     _value = in;
342     gchar * prefname = this->pref_name();
343     prefs_set_int_attribute(PREF_DIR, prefname, _value == true ? 1 : 0);
344     g_free(prefname);
346     return _value;
349 /** \brief  A function to set the \c _value
350     \param  in   The value to set to
351     \param  doc  A document that should be used to set the value.
352     \param  node The node where the value may be placed
354     This function sets the internal value, but it also sets the value
355     in the preferences structure.  To put it in the right place, \c PREF_DIR
356     and \c pref_name() are used.
357 */
358 int
359 ParamInt::set (int in, SPDocument * doc, Inkscape::XML::Node * node)
361     _value = in;
362     if (_value > _max) _value = _max;
363     if (_value < _min) _value = _min;
365     gchar * prefname = this->pref_name();
366     prefs_set_int_attribute(PREF_DIR, prefname, _value);
367     g_free(prefname);
369     return _value;
372 /** \brief  A function to set the \c _value
373     \param  in   The value to set to
374     \param  doc  A document that should be used to set the value.
375     \param  node The node where the value may be placed
377     This function sets the internal value, but it also sets the value
378     in the preferences structure.  To put it in the right place, \c PREF_DIR
379     and \c pref_name() are used.
380 */
381 float
382 ParamFloat::set (float in, SPDocument * doc, Inkscape::XML::Node * node)
384     _value = in;
385     if (_value > _max) _value = _max;
386     if (_value < _min) _value = _min;
388     gchar * prefname = this->pref_name();
389     prefs_set_double_attribute(PREF_DIR, prefname, _value);
390     g_free(prefname);
392     return _value;
395 /** \brief  A function to set the \c _value
396     \param  in   The value to set to
397     \param  doc  A document that should be used to set the value.
398     \param  node The node where the value may be placed
400     This function sets the internal value, but it also sets the value
401     in the preferences structure.  To put it in the right place, \c PREF_DIR
402     and \c pref_name() are used.
404     To copy the data into _value the old memory must be free'd first.
405     It is important to note that \c g_free handles \c NULL just fine.  Then
406     the passed in value is duplicated using \c g_strdup().
407 */
408 const gchar *
409 ParamString::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
411     if (in == NULL) return NULL; /* Can't have NULL string */
413     if (_value != NULL)
414         g_free(_value);
415     _value = g_strdup(in);
417     gchar * prefname = this->pref_name();
418     prefs_set_string_attribute(PREF_DIR, prefname, _value);
419     g_free(prefname);
421     return _value;
424 /** \brief  Wrapper to cast to the object and use it's function.  */
425 bool
426 Parameter::get_bool (const SPDocument * doc, const Inkscape::XML::Node * node)
428     ParamBool * boolpntr;
429     boolpntr = dynamic_cast<ParamBool *>(this);
430     if (boolpntr == NULL)
431         throw Extension::param_wrong_type();
432     return boolpntr->get(doc, node);
435 /** \brief  Wrapper to cast to the object and use it's function.  */
436 int
437 Parameter::get_int (const SPDocument * doc, const Inkscape::XML::Node * node)
439     ParamInt * intpntr;
440     intpntr = dynamic_cast<ParamInt *>(this);
441     if (intpntr == NULL)
442         throw Extension::param_wrong_type();
443     return intpntr->get(doc, node);
446 /** \brief  Wrapper to cast to the object and use it's function.  */
447 float
448 Parameter::get_float (const SPDocument * doc, const Inkscape::XML::Node * node)
450     ParamFloat * floatpntr;
451     floatpntr = dynamic_cast<ParamFloat *>(this);
452     if (floatpntr == NULL)
453         throw Extension::param_wrong_type();
454     return floatpntr->get(doc, node);
457 /** \brief  Wrapper to cast to the object and use it's function.  */
458 const gchar *
459 Parameter::get_string (const SPDocument * doc, const Inkscape::XML::Node * node)
461     ParamString * stringpntr;
462     stringpntr = dynamic_cast<ParamString *>(this);
463     if (stringpntr == NULL)
464         throw Extension::param_wrong_type();
465     return stringpntr->get(doc, node);
468 /** \brief  Wrapper to cast to the object and use it's function.  */
469 bool
470 Parameter::set_bool (bool in, SPDocument * doc, Inkscape::XML::Node * node)
472     ParamBool * boolpntr;
473     boolpntr = dynamic_cast<ParamBool *>(this);
474     if (boolpntr == NULL)
475         throw Extension::param_wrong_type();
476     return boolpntr->set(in, doc, node);
479 /** \brief  Wrapper to cast to the object and use it's function.  */
480 int
481 Parameter::set_int (int in, SPDocument * doc, Inkscape::XML::Node * node)
483     ParamInt * intpntr;
484     intpntr = dynamic_cast<ParamInt *>(this);
485     if (intpntr == NULL)
486         throw Extension::param_wrong_type();
487     return intpntr->set(in, doc, node);
490 /** \brief  Wrapper to cast to the object and use it's function.  */
491 float
492 Parameter::set_float (float in, SPDocument * doc, Inkscape::XML::Node * node)
494     ParamFloat * floatpntr;
495     floatpntr = dynamic_cast<ParamFloat *>(this);
496     if (floatpntr == NULL)
497         throw Extension::param_wrong_type();
498     return floatpntr->set(in, doc, node);
501 /** \brief  Wrapper to cast to the object and use it's function.  */
502 const gchar *
503 Parameter::set_string (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
505     ParamString * stringpntr;
506     stringpntr = dynamic_cast<ParamString *>(this);
507     if (stringpntr == NULL)
508         throw Extension::param_wrong_type();
509     return stringpntr->set(in, doc, node);
512 /** \brief  Initialize the object, to do that, copy the data. */
513 ParamString::ParamString (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
514     Parameter(name, guitext, desc, scope, ext), _value(NULL)
516     const char * defaultval = NULL;
517     if (sp_repr_children(xml) != NULL)
518         defaultval = sp_repr_children(xml)->content();
520     gchar * pref_name = this->pref_name();
521     const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
522     g_free(pref_name);
524     if (paramval != NULL)
525         defaultval = paramval;
526     if (defaultval != NULL)
527         _value = g_strdup(defaultval);
529     return;
532 /** \brief  Free the allocated data. */
533 ParamString::~ParamString(void)
535     g_free(_value);
538 /** \brief  Oop, now that we need a parameter, we need it's name.  */
539 Parameter::Parameter (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext) :
540     extension(ext), _name(NULL), _desc(NULL), _scope(scope), _text(NULL)
542     if (name != NULL)
543         _name = g_strdup(name);
544     if (desc != NULL) {
545         _desc = g_strdup(desc);
546         // printf("Adding description: '%s' on '%s'\n", _desc, _name);
547     }
550     if (guitext != NULL)
551         _text = g_strdup(guitext);
552     else
553         _text = g_strdup(name);
555     return;
558 /** \brief  Just free the allocated name. */
559 Parameter::~Parameter (void)
561     g_free(_name);
562     g_free(_text);
565 /** \brief  Build the name to write the parameter from the extension's
566             ID and the name of this parameter. */
567 gchar *
568 Parameter::pref_name (void)
570     return g_strdup_printf("%s.%s", extension->get_id(), _name);
573 Inkscape::XML::Node *
574 Parameter::find_child (Inkscape::XML::Node * adult)
576     return sp_repr_lookup_child(adult, "name", _name);
579 Inkscape::XML::Node *
580 Parameter::new_child (Inkscape::XML::Node * parent)
582     Inkscape::XML::Node * retval;
583     retval = parent->document()->createElement("inkscape:extension-param");
584     retval->setAttribute("name", _name);
586     parent->appendChild(retval);
587     return retval;
590 Inkscape::XML::Node *
591 Parameter::document_param_node (SPDocument * doc)
593     Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
594     Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc));
595     Inkscape::XML::Node * params = NULL;
597     GQuark const name_quark = g_quark_from_string("inkscape:extension-params");
599     for (Inkscape::XML::Node * child = defs->firstChild();
600             child != NULL;
601             child = child->next()) {
602         if ((GQuark)child->code() == name_quark &&
603                 !strcmp(child->attribute("extension"), extension->get_id())) {
604             params = child;
605             break;
606         }
607     }
609     if (params == NULL) {
610         params = xml_doc->createElement("inkscape:extension-param");
611         params->setAttribute("extension", extension->get_id());
612         defs->appendChild(params);
613     }
615     return params;
618 /** \brief  Basically, if there is no widget pass a NULL. */
619 Gtk::Widget *
620 Parameter::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
622     return NULL;
625 /** \brief  If I'm not sure which it is, just don't return a value. */
626 Glib::ustring *
627 Parameter::string (void)
629     Glib::ustring * mystring = new Glib::ustring("");
630     return mystring;
633 /** \brief  A class to make an adjustment that uses Extension params */
634 class ParamFloatAdjustment : public Gtk::Adjustment {
635     /** The parameter to adjust */
636     ParamFloat * _pref;
637     SPDocument * _doc;
638     Inkscape::XML::Node * _node;
639 public:
640     /** \brief  Make the adjustment using an extension and the string
641                 describing the parameter. */
642     ParamFloatAdjustment (ParamFloat * param, SPDocument * doc, Inkscape::XML::Node * node) :
643             Gtk::Adjustment(0.0, param->min(), param->max(), 0.1), _pref(param), _doc(doc), _node(node) {
644         this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
645         this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed));
646         return;
647     };
649     void val_changed (void);
650 }; /* class ParamFloatAdjustment */
652 /** \brief  A function to respond to the value_changed signal from the
653             adjustment.
655     This function just grabs the value from the adjustment and writes
656     it to the parameter.  Very simple, but yet beautiful.
657 */
658 void
659 ParamFloatAdjustment::val_changed (void)
661     // std::cout << "Value Changed to: " << this->get_value() << std::endl;
662     _pref->set(this->get_value(), _doc, _node);
663     return;
666 /** \brief  A class to make an adjustment that uses Extension params */
667 class ParamIntAdjustment : public Gtk::Adjustment {
668     /** The parameter to adjust */
669     ParamInt * _pref;
670     SPDocument * _doc;
671     Inkscape::XML::Node * _node;
672 public:
673     /** \brief  Make the adjustment using an extension and the string
674                 describing the parameter. */
675     ParamIntAdjustment (ParamInt * param, SPDocument * doc, Inkscape::XML::Node * node) :
676             Gtk::Adjustment(0.0, param->min(), param->max(), 1.0), _pref(param), _doc(doc), _node(node) {
677         this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
678         this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed));
679         return;
680     };
682     void val_changed (void);
683 }; /* class ParamIntAdjustment */
685 /** \brief  A function to respond to the value_changed signal from the
686             adjustment.
688     This function just grabs the value from the adjustment and writes
689     it to the parameter.  Very simple, but yet beautiful.
690 */
691 void
692 ParamIntAdjustment::val_changed (void)
694     // std::cout << "Value Changed to: " << this->get_value() << std::endl;
695     _pref->set((int)this->get_value(), _doc, _node);
696     return;
699 /**
700     \brief  Creates a Float Adjustment for a float parameter
702     Builds a hbox with a label and a float adjustment in it.
703 */
704 Gtk::Widget *
705 ParamFloat::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
707     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
709     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
710     label->show();
711     hbox->pack_start(*label, true, true);
713     ParamFloatAdjustment * fadjust = Gtk::manage(new ParamFloatAdjustment(this, doc, node));
714     Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 0.1, 1));
715     spin->show();
716     hbox->pack_start(*spin, false, false);
718     hbox->show();
720     return dynamic_cast<Gtk::Widget *>(hbox);
723 /**
724     \brief  Creates a Int Adjustment for a int parameter
726     Builds a hbox with a label and a int adjustment in it.
727 */
728 Gtk::Widget *
729 ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
731     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
733     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
734     label->show();
735     hbox->pack_start(*label, true, true);
737     ParamIntAdjustment * fadjust = Gtk::manage(new ParamIntAdjustment(this, doc, node));
738     Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 1.0, 0));
739     spin->show();
740     hbox->pack_start(*spin, false, false);
742     hbox->show();
744     return dynamic_cast<Gtk::Widget *>(hbox);
747 /** \brief  A check button which is Param aware.  It works with the
748             parameter to change it's value as the check button changes
749             value. */
750 class ParamBoolCheckButton : public Gtk::CheckButton {
751 private:
752     /** \brief  Param to change */
753     ParamBool * _pref;
754     SPDocument * _doc;
755     Inkscape::XML::Node * _node;
756 public:
757     /** \brief  Initialize the check button
758         \param  param  Which parameter to adjust on changing the check button
760         This function sets the value of the checkbox to be that of the
761         parameter, and then sets up a callback to \c on_toggle.
762     */
763     ParamBoolCheckButton (ParamBool * param, SPDocument * doc, Inkscape::XML::Node * node) :
764             Gtk::CheckButton(), _pref(param), _doc(doc), _node(node) {
765         this->set_active(_pref->get(NULL, NULL) /**\todo fix */);
766         this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle));
767         return;
768     }
769     void on_toggle (void);
770 };
772 /**
773     \brief  A function to respond to the check box changing
775     Adjusts the value of the preference to match that in the check box.
776 */
777 void
778 ParamBoolCheckButton::on_toggle (void)
780     _pref->set(this->get_active(), NULL /**\todo fix this */, NULL);
781     return;
784 /**
785     \brief  Creates a bool check button for a bool parameter
787     Builds a hbox with a label and a check button in it.
788 */
789 Gtk::Widget *
790 ParamBool::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
792     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
794     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
795     label->show();
796     hbox->pack_start(*label, true, true);
798     ParamBoolCheckButton * checkbox = new ParamBoolCheckButton(this, doc, node);
799     checkbox->show();
800     hbox->pack_start(*checkbox, false, false);
802     hbox->show();
804     return dynamic_cast<Gtk::Widget *>(hbox);
807 /** \brief  A special category of Gtk::Entry to handle string parameteres */
808 class ParamStringEntry : public Gtk::Entry {
809 private:
810     ParamString * _pref;
811     SPDocument * _doc;
812     Inkscape::XML::Node * _node;
813 public:
814     /** \brief  Build a string preference for the given parameter
815         \param  pref  Where to get the string from, and where to put it
816                       when it changes.
817     */
818     ParamStringEntry (ParamString * pref, SPDocument * doc, Inkscape::XML::Node * node) :
819         Gtk::Entry(), _pref(pref), _doc(doc), _node(node) {
820         if (_pref->get(NULL, NULL) != NULL)
821             this->set_text(Glib::ustring(_pref->get(NULL, NULL)));
822         this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text));
823     };
824     void changed_text (void);
825 };
827 /** \brief  Respond to the text box changing
829     This function responds to the box changing by grabbing the value
830     from the text box and putting it in the parameter.
831 */
832 void
833 ParamStringEntry::changed_text (void)
835     Glib::ustring data = this->get_text();
836     _pref->set(data.c_str(), _doc, _node);
837     return;
840 /**
841     \brief  Creates a text box for the string parameter
843     Builds a hbox with a label and a text box in it.
844 */
845 Gtk::Widget *
846 ParamString::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
848     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
850     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
851     label->show();
852     hbox->pack_start(*label, false, false);
854     ParamStringEntry * textbox = new ParamStringEntry(this, doc, node);
855     textbox->show();
856     hbox->pack_start(*textbox, true, true);
858     hbox->show();
860     return dynamic_cast<Gtk::Widget *>(hbox);
863 /** \brief  Return 'true' or 'false' */
864 Glib::ustring *
865 ParamBool::string (void)
867     Glib::ustring * mystring;
869     if (_value)
870         mystring = new Glib::ustring("true");
871     else
872         mystring = new Glib::ustring("false");
874     return mystring;
877 /** \brief  Return the value as a string */
878 Glib::ustring *
879 ParamInt::string (void)
881     char startstring[32];
882     sprintf(startstring, "%d", _value);
883     Glib::ustring * mystring = new Glib::ustring(startstring);
884     return mystring;
887 /** \brief  Return the value as a string */
888 Glib::ustring *
889 ParamFloat::string (void)
891     char startstring[G_ASCII_DTOSTR_BUF_SIZE];
892     g_ascii_dtostr(startstring, G_ASCII_DTOSTR_BUF_SIZE, _value);
893     Glib::ustring * mystring = new Glib::ustring(startstring);
894     return mystring;
897 /** \brief  Return the value as a string */
898 Glib::ustring *
899 ParamString::string (void)
901     Glib::ustring * mystring = new Glib::ustring("");
902     *mystring += "\"";
903     *mystring += _value;
904     *mystring += "\"";
905     return mystring;
908 /** \brief  Create a label for the description */
909 Gtk::Widget *
910 ParamDescription::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
912     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_value)));
913     label->set_line_wrap();
914     label->show();
916     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
917     hbox->pack_start(*label, true, true, 5);
918     hbox->show();
920     return hbox;
923 /** \brief  Initialize the object, to do that, copy the data. */
924 ParamDescription::ParamDescription (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
925     Parameter(name, guitext, desc, scope, ext), _value(NULL)
927     // printf("Building Description\n");
928     const char * defaultval = NULL;
929     if (sp_repr_children(xml) != NULL)
930         defaultval = sp_repr_children(xml)->content();
932     if (defaultval != NULL)
933         _value = g_strdup(defaultval);
935     return;
938 ParamEnum::ParamEnum (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
939     Parameter(name, guitext, desc, scope, ext), _current_choice(NULL)
941     return;
944 ParamEnum::~ParamEnum (void)
949 /** \brief  Return the value as a string */
950 Glib::ustring *
951 ParamEnum::string (void)
953     Glib::ustring * mystring = new Glib::ustring("");
954     *mystring += "\"";
955     *mystring += this->get(NULL, NULL);
956     *mystring += "\"";
957     return mystring;
960 Gtk::Widget *
961 ParamEnum::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
963     return NULL;
966 const gchar *
967 ParamEnum::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
969     return NULL;
973 }  /* namespace Extension */
974 }  /* namespace Inkscape */
976 /*
977   Local Variables:
978   mode:c++
979   c-file-style:"stroustrup"
980   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
981   indent-tabs-mode:nil
982   fill-column:99
983   End:
984 */
985 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :