Code

r11769@tres: ted | 2006-05-06 09:09:59 -0700
[inkscape.git] / src / extension / parameter.cpp
1 /** \file
2  * Parameters for extensions.
3  */
5 /*
6  * Authors:
7  *   Ted Gould <ted@gould.cx>
8  *
9  * Copyright (C) 2005-2006 Authors
10  *
11  * Released under GNU GPL, read the file 'COPYING' for more information
12  */
14 #ifdef HAVE_CONFIG_H
15 # include "config.h"
16 #endif
19 #include <gtkmm/adjustment.h>
20 #include <gtkmm/box.h>
21 #include <gtkmm/spinbutton.h>
23 #include <glibmm/i18n.h>
25 #include <xml/node.h>
27 #include "extension.h"
28 #include "prefs-utils.h"
29 #include "document-private.h"
30 #include "sp-object.h"
32 #include "parameter.h"
34 /** \brief  The root directory in the preferences database for extension
35             related parameters. */
36 #define PREF_DIR "extensions"
38 namespace Inkscape {
39 namespace Extension {
41 /** \brief  A description parameter */
42 class ParamDescription : public Parameter {
43 private:
44     /** \brief  Internal value. */
45     gchar * _value;
46 public:
47     ParamDescription(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
48     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
49 };
51 /** \brief  A boolean parameter */
52 class ParamBool : public Parameter {
53 private:
54     /** \brief  Internal value. */
55     bool _value;
56 public:
57     ParamBool(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
58     /** \brief  Returns \c _value */
59     bool get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
60     bool set (bool in, SPDocument * doc, Inkscape::XML::Node * node);
61     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
62     Glib::ustring * string (void);
63 };
65 /** \brief  Use the superclass' allocator and set the \c _value */
66 ParamBool::ParamBool (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
67         Parameter(name, guitext, desc, scope, ext), _value(false)
68 {
69     const char * defaultval = NULL;
70     if (sp_repr_children(xml) != NULL)
71         defaultval = sp_repr_children(xml)->content();
73     if (defaultval != NULL && (!strcmp(defaultval, "TRUE") || !strcmp(defaultval, "true") || !strcmp(defaultval, "1"))) {
74         _value = true;
75     } else {
76         _value = false;
77     }
79     gchar * pref_name = this->pref_name();
80     _value = (bool)prefs_get_int_attribute(PREF_DIR, pref_name, _value);
81     g_free(pref_name);
83     return;
84 }
86 class ParamInt : public Parameter {
87 private:
88     /** \brief  Internal value. */
89     int _value;
90     int _min;
91     int _max;
92 public:
93     ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
94     /** \brief  Returns \c _value */
95     int get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
96     int set (int in, SPDocument * doc, Inkscape::XML::Node * node);
97     int max (void) { return _max; }
98     int min (void) { return _min; }
99     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
100     Glib::ustring * string (void);
101 };
103 /** \brief  Use the superclass' allocator and set the \c _value */
104 ParamInt::ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
105         Parameter(name, guitext, desc, scope, ext), _value(0), _min(0), _max(10)
107     const char * defaultval = NULL;
108     if (sp_repr_children(xml) != NULL)
109         defaultval = sp_repr_children(xml)->content();
110     if (defaultval != NULL) {
111         _value = atoi(defaultval);
112     }
114     const char * maxval = xml->attribute("max");
115     if (maxval != NULL)
116         _max = atoi(maxval);
118     const char * minval = xml->attribute("min");
119     if (minval != NULL)
120         _min = atoi(minval);
122     /* We're handling this by just killing both values */
123     if (_max < _min) {
124         _max = 10;
125         _min = 0;
126     }
128     gchar * pref_name = this->pref_name();
129     _value = prefs_get_int_attribute(PREF_DIR, pref_name, _value);
130     g_free(pref_name);
132     // std::cout << "New Int::  value: " << _value << "  max: " << _max << "  min: " << _min << std::endl;
134     if (_value > _max) _value = _max;
135     if (_value < _min) _value = _min;
137     return;
140 class ParamFloat : public Parameter {
141 private:
142     /** \brief  Internal value. */
143     float _value;
144     float _min;
145     float _max;
146 public:
147     ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
148     /** \brief  Returns \c _value */
149     float get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
150     float set (float in, SPDocument * doc, Inkscape::XML::Node * node);
151     float max (void) { return _max; }
152     float min (void) { return _min; }
153     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
154     Glib::ustring * string (void);
155 };
157 /** \brief  Use the superclass' allocator and set the \c _value */
158 ParamFloat::ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
159         Parameter(name, guitext, desc, scope, ext), _value(0.0), _min(0.0), _max(10.0)
161     const char * defaultval = NULL;
162     if (sp_repr_children(xml) != NULL)
163         defaultval = sp_repr_children(xml)->content();
164     if (defaultval != NULL) {
165         _value = atof(defaultval);
166     }
168     const char * maxval = xml->attribute("max");
169     if (maxval != NULL)
170         _max = atof(maxval);
172     const char * minval = xml->attribute("min");
173     if (minval != NULL)
174         _min = atof(minval);
176     /* We're handling this by just killing both values */
177     if (_max < _min) {
178         _max = 10.0;
179         _min = 0.0;
180     }
182     gchar * pref_name = this->pref_name();
183     _value = prefs_get_double_attribute(PREF_DIR, pref_name, _value);
184     g_free(pref_name);
186     // std::cout << "New Float::  value: " << _value << "  max: " << _max << "  min: " << _min << std::endl;
188     if (_value > _max) _value = _max;
189     if (_value < _min) _value = _min;
191     return;
194 class ParamString : public Parameter {
195 private:
196     /** \brief  Internal value.  This should point to a string that has
197                 been allocated in memory.  And should be free'd. */
198     gchar * _value;
199 public:
200     ParamString(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
201     ~ParamString(void);
202     /** \brief  Returns \c _value, with a \i const to protect it. */
203     const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
204     const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
205     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
206     Glib::ustring * string (void);
207 };
209 /**
210     \return None
211     \brief  This function creates a parameter that can be used later.  This
212             is typically done in the creation of the extension and defined
213             in the XML file describing the extension (it's private so people
214             have to use the system) :)
215     \param  in_repr  The XML describing the parameter
217     This function first grabs all of the data out of the Repr and puts
218     it into local variables.  Actually, these are just pointers, and the
219     data is not duplicated so we need to be careful with it.  If there
220     isn't a name or a type in the XML, then no parameter is created as
221     the function just returns.
223     From this point on, we're pretty committed as we've allocated an
224     object and we're starting to fill it.  The name is set first, and
225     is created with a strdup to actually allocate memory for it.  Then
226     there is a case statement (roughly because strcmp requires 'ifs')
227     based on what type of parameter this is.  Depending which type it
228     is, the value is interpreted differently, but they are relatively
229     straight forward.  In all cases the value is set to the default
230     value from the XML and the type is set to the interpreted type.
231 */
232 Parameter *
233 Parameter::make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
235     const char * name;
236     const char * type;
237     const char * guitext;
238     const char * desc;
239     const char * scope_str;
240     Parameter::_scope_t scope = Parameter::SCOPE_USER;
242     name = in_repr->attribute("name");
243     type = in_repr->attribute("type");
244     guitext = in_repr->attribute("gui-text");
245     if (guitext == NULL)
246         guitext = in_repr->attribute("_gui-text");
247     desc = in_repr->attribute("gui-description");
248     if (desc == NULL)
249         desc = in_repr->attribute("_gui-description");
250     scope_str = in_repr->attribute("scope");
252     /* In this case we just don't have enough information */
253     if (name == NULL || type == NULL) {
254         return NULL;
255     }
257     if (scope_str != NULL) {
258         if (!strcmp(scope_str, "user")) {
259             scope = Parameter::SCOPE_USER;
260         } else if (!strcmp(scope_str, "document")) {
261             scope = Parameter::SCOPE_DOCUMENT;
262         } else if (!strcmp(scope_str, "node")) {
263             scope = Parameter::SCOPE_NODE;
264         }
265     }
267     Parameter * param = NULL;
268     if (!strcmp(type, "boolean")) {
269         param = new ParamBool(name, guitext, desc, scope, in_ext, in_repr);
270     } else if (!strcmp(type, "int")) {
271         param = new ParamInt(name, guitext, desc, scope, in_ext, in_repr);
272     } else if (!strcmp(type, "float")) {
273         param = new ParamFloat(name, guitext, desc, scope, in_ext, in_repr);
274     } else if (!strcmp(type, "string")) {
275         param = new ParamString(name, guitext, desc, scope, in_ext, in_repr);
276     } else if (!strcmp(type, "description")) {
277         param = new ParamDescription(name, guitext, desc, scope, in_ext, in_repr);
278     }
280     /* Note: param could equal NULL */
281     return param;
284 /** \brief  A function to set the \c _value
285     \param  in   The value to set to
286     \param  doc  A document that should be used to set the value.
287     \param  node The node where the value may be placed
289     This function sets the internal value, but it also sets the value
290     in the preferences structure.  To put it in the right place, \c PREF_DIR
291     and \c pref_name() are used.
292 */
293 bool
294 ParamBool::set (bool in, SPDocument * doc, Inkscape::XML::Node * node)
296     _value = in;
298     gchar * prefname = this->pref_name();
299     prefs_set_int_attribute(PREF_DIR, prefname, _value == true ? 1 : 0);
300     g_free(prefname);
302     return _value;
305 /** \brief  A function to set the \c _value
306     \param  in   The value to set to
307     \param  doc  A document that should be used to set the value.
308     \param  node The node where the value may be placed
310     This function sets the internal value, but it also sets the value
311     in the preferences structure.  To put it in the right place, \c PREF_DIR
312     and \c pref_name() are used.
313 */
314 int
315 ParamInt::set (int in, SPDocument * doc, Inkscape::XML::Node * node)
317     _value = in;
318     if (_value > _max) _value = _max;
319     if (_value < _min) _value = _min;
321     gchar * prefname = this->pref_name();
322     prefs_set_int_attribute(PREF_DIR, prefname, _value);
323     g_free(prefname);
325     return _value;
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 float
338 ParamFloat::set (float in, SPDocument * doc, Inkscape::XML::Node * node)
340     _value = in;
341     if (_value > _max) _value = _max;
342     if (_value < _min) _value = _min;
344     gchar * prefname = this->pref_name();
345     prefs_set_double_attribute(PREF_DIR, prefname, _value);
346     g_free(prefname);
348     return _value;
351 /** \brief  A function to set the \c _value
352     \param  in   The value to set to
353     \param  doc  A document that should be used to set the value.
354     \param  node The node where the value may be placed
356     This function sets the internal value, but it also sets the value
357     in the preferences structure.  To put it in the right place, \c PREF_DIR
358     and \c pref_name() are used.
360     To copy the data into _value the old memory must be free'd first.
361     It is important to note that \c g_free handles \c NULL just fine.  Then
362     the passed in value is duplicated using \c g_strdup().
363 */
364 const gchar *
365 ParamString::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
367     if (in == NULL) return NULL; /* Can't have NULL string */
369     if (_value != NULL)
370         g_free(_value);
371     _value = g_strdup(in);
373     gchar * prefname = this->pref_name();
374     prefs_set_string_attribute(PREF_DIR, prefname, _value);
375     g_free(prefname);
377     return _value;
380 /** \brief  Wrapper to cast to the object and use it's function.  */
381 bool
382 Parameter::get_bool (const SPDocument * doc, const Inkscape::XML::Node * node)
384     ParamBool * boolpntr;
385     boolpntr = dynamic_cast<ParamBool *>(this);
386     if (boolpntr == NULL)
387         throw Extension::param_wrong_type();
388     return boolpntr->get(doc, node);
391 /** \brief  Wrapper to cast to the object and use it's function.  */
392 int
393 Parameter::get_int (const SPDocument * doc, const Inkscape::XML::Node * node)
395     ParamInt * intpntr;
396     intpntr = dynamic_cast<ParamInt *>(this);
397     if (intpntr == NULL)
398         throw Extension::param_wrong_type();
399     return intpntr->get(doc, node);
402 /** \brief  Wrapper to cast to the object and use it's function.  */
403 float
404 Parameter::get_float (const SPDocument * doc, const Inkscape::XML::Node * node)
406     ParamFloat * floatpntr;
407     floatpntr = dynamic_cast<ParamFloat *>(this);
408     if (floatpntr == NULL)
409         throw Extension::param_wrong_type();
410     return floatpntr->get(doc, node);
413 /** \brief  Wrapper to cast to the object and use it's function.  */
414 const gchar *
415 Parameter::get_string (const SPDocument * doc, const Inkscape::XML::Node * node)
417     ParamString * stringpntr;
418     stringpntr = dynamic_cast<ParamString *>(this);
419     if (stringpntr == NULL)
420         throw Extension::param_wrong_type();
421     return stringpntr->get(doc, node);
424 /** \brief  Wrapper to cast to the object and use it's function.  */
425 bool
426 Parameter::set_bool (bool in, SPDocument * doc, 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->set(in, doc, node);
435 /** \brief  Wrapper to cast to the object and use it's function.  */
436 int
437 Parameter::set_int (int in, SPDocument * doc, 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->set(in, doc, node);
446 /** \brief  Wrapper to cast to the object and use it's function.  */
447 float
448 Parameter::set_float (float in, SPDocument * doc, 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->set(in, doc, node);
457 /** \brief  Wrapper to cast to the object and use it's function.  */
458 const gchar *
459 Parameter::set_string (const gchar * in, SPDocument * doc, 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->set(in, doc, node);
468 /** \brief  Initialize the object, to do that, copy the data. */
469 ParamString::ParamString (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
470     Parameter(name, guitext, desc, scope, ext), _value(NULL)
472     const char * defaultval = NULL;
473     if (sp_repr_children(xml) != NULL)
474         defaultval = sp_repr_children(xml)->content();
476     gchar * pref_name = this->pref_name();
477     const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
478     g_free(pref_name);
480     if (paramval != NULL)
481         defaultval = paramval;
482     if (defaultval != NULL)
483         _value = g_strdup(defaultval);
485     return;
488 /** \brief  Free the allocated data. */
489 ParamString::~ParamString(void)
491     g_free(_value);
494 /** \brief  Oop, now that we need a parameter, we need it's name.  */
495 Parameter::Parameter (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext) :
496     extension(ext), _name(NULL), _desc(NULL), _scope(scope), _text(NULL)
498     if (name != NULL)
499         _name = g_strdup(name);
500     if (desc != NULL) {
501         _desc = g_strdup(desc);
502         // printf("Adding description: '%s' on '%s'\n", _desc, _name);
503     }
506     if (guitext != NULL)
507         _text = g_strdup(guitext);
508     else
509         _text = g_strdup(name);
511     return;
514 /** \brief  Just free the allocated name. */
515 Parameter::~Parameter (void)
517     g_free(_name);
518     g_free(_text);
521 /** \brief  Build the name to write the parameter from the extension's
522             ID and the name of this parameter. */
523 gchar *
524 Parameter::pref_name (void)
526     return g_strdup_printf("%s.%s", extension->get_id(), _name);
529 Inkscape::XML::Node *
530 Parameter::find_child (Inkscape::XML::Node * adult)
532     return sp_repr_lookup_child(adult, "name", _name);
535 Inkscape::XML::Node *
536 Parameter::new_child (Inkscape::XML::Node * parent)
538     Inkscape::XML::Node * retval;
539     retval = sp_repr_new("inkscape:extension-param");
540     retval->setAttribute("name", _name);
542     parent->appendChild(retval);
543     return retval;
546 Inkscape::XML::Node *
547 Parameter::document_param_node (SPDocument * doc)
549     Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc));
550     Inkscape::XML::Node * params = NULL;
552     GQuark const name_quark = g_quark_from_string("inkscape:extension-params");
554     for (Inkscape::XML::Node * child = defs->firstChild();
555             child != NULL;
556             child = child->next()) {
557         if ((GQuark)child->code() == name_quark &&
558                 !strcmp(child->attribute("extension"), extension->get_id())) {
559             params = child;
560             break;
561         }
562     }
564     if (params == NULL) {
565         params = sp_repr_new("inkscape:extension-param");
566         params->setAttribute("extension", extension->get_id());
567         defs->appendChild(params);
568     }
570     return params;
573 /** \brief  Basically, if there is no widget pass a NULL. */
574 Gtk::Widget *
575 Parameter::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
577     return NULL;
580 /** \brief  If I'm not sure which it is, just don't return a value. */
581 Glib::ustring *
582 Parameter::string (void)
584     Glib::ustring * mystring = new Glib::ustring("");
585     return mystring;
588 /** \brief  A class to make an adjustment that uses Extension params */
589 class ParamFloatAdjustment : public Gtk::Adjustment {
590     /** The parameter to adjust */
591     ParamFloat * _pref;
592     SPDocument * _doc;
593     Inkscape::XML::Node * _node;
594 public:
595     /** \brief  Make the adjustment using an extension and the string
596                 describing the parameter. */
597     ParamFloatAdjustment (ParamFloat * param, SPDocument * doc, Inkscape::XML::Node * node) :
598             Gtk::Adjustment(0.0, param->min(), param->max(), 0.1), _pref(param), _doc(doc), _node(node) {
599         this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
600         this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed));
601         return;
602     };
604     void val_changed (void);
605 }; /* class ParamFloatAdjustment */
607 /** \brief  A function to respond to the value_changed signal from the
608             adjustment.
610     This function just grabs the value from the adjustment and writes
611     it to the parameter.  Very simple, but yet beautiful.
612 */
613 void
614 ParamFloatAdjustment::val_changed (void)
616     // std::cout << "Value Changed to: " << this->get_value() << std::endl;
617     _pref->set(this->get_value(), _doc, _node);
618     return;
621 /** \brief  A class to make an adjustment that uses Extension params */
622 class ParamIntAdjustment : public Gtk::Adjustment {
623     /** The parameter to adjust */
624     ParamInt * _pref;
625     SPDocument * _doc;
626     Inkscape::XML::Node * _node;
627 public:
628     /** \brief  Make the adjustment using an extension and the string
629                 describing the parameter. */
630     ParamIntAdjustment (ParamInt * param, SPDocument * doc, Inkscape::XML::Node * node) :
631             Gtk::Adjustment(0.0, param->min(), param->max(), 1.0), _pref(param), _doc(doc), _node(node) {
632         this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
633         this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed));
634         return;
635     };
637     void val_changed (void);
638 }; /* class ParamIntAdjustment */
640 /** \brief  A function to respond to the value_changed signal from the
641             adjustment.
643     This function just grabs the value from the adjustment and writes
644     it to the parameter.  Very simple, but yet beautiful.
645 */
646 void
647 ParamIntAdjustment::val_changed (void)
649     // std::cout << "Value Changed to: " << this->get_value() << std::endl;
650     _pref->set((int)this->get_value(), _doc, _node);
651     return;
654 /**
655     \brief  Creates a Float Adjustment for a float parameter
657     Builds a hbox with a label and a float adjustment in it.
658 */
659 Gtk::Widget *
660 ParamFloat::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
662     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
664     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
665     label->show();
666     hbox->pack_start(*label, true, true);
668     ParamFloatAdjustment * fadjust = Gtk::manage(new ParamFloatAdjustment(this, doc, node));
669     Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 0.1, 1));
670     spin->show();
671     hbox->pack_start(*spin, false, false);
673     hbox->show();
675     return dynamic_cast<Gtk::Widget *>(hbox);
678 /**
679     \brief  Creates a Int Adjustment for a int parameter
681     Builds a hbox with a label and a int adjustment in it.
682 */
683 Gtk::Widget *
684 ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
686     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
688     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
689     label->show();
690     hbox->pack_start(*label, true, true);
692     ParamIntAdjustment * fadjust = Gtk::manage(new ParamIntAdjustment(this, doc, node));
693     Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 1.0, 0));
694     spin->show();
695     hbox->pack_start(*spin, false, false);
697     hbox->show();
699     return dynamic_cast<Gtk::Widget *>(hbox);
702 /** \brief  A check button which is Param aware.  It works with the
703             parameter to change it's value as the check button changes
704             value. */
705 class ParamBoolCheckButton : public Gtk::CheckButton {
706 private:
707     /** \brief  Param to change */
708     ParamBool * _pref;
709     SPDocument * _doc;
710     Inkscape::XML::Node * _node;
711 public:
712     /** \brief  Initialize the check button
713         \param  param  Which parameter to adjust on changing the check button
715         This function sets the value of the checkbox to be that of the
716         parameter, and then sets up a callback to \c on_toggle.
717     */
718     ParamBoolCheckButton (ParamBool * param, SPDocument * doc, Inkscape::XML::Node * node) :
719             Gtk::CheckButton(), _pref(param), _doc(doc), _node(node) {
720         this->set_active(_pref->get(NULL, NULL) /**\todo fix */);
721         this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle));
722         return;
723     }
724     void on_toggle (void);
725 };
727 /**
728     \brief  A function to respond to the check box changing
730     Adjusts the value of the preference to match that in the check box.
731 */
732 void
733 ParamBoolCheckButton::on_toggle (void)
735     _pref->set(this->get_active(), NULL /**\todo fix this */, NULL);
736     return;
739 /**
740     \brief  Creates a bool check button for a bool parameter
742     Builds a hbox with a label and a check button in it.
743 */
744 Gtk::Widget *
745 ParamBool::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
747     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
749     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
750     label->show();
751     hbox->pack_start(*label, true, true);
753     ParamBoolCheckButton * checkbox = new ParamBoolCheckButton(this, doc, node);
754     checkbox->show();
755     hbox->pack_start(*checkbox, false, false);
757     hbox->show();
759     return dynamic_cast<Gtk::Widget *>(hbox);
762 /** \brief  A special category of Gtk::Entry to handle string parameteres */
763 class ParamStringEntry : public Gtk::Entry {
764 private:
765     ParamString * _pref;
766     SPDocument * _doc;
767     Inkscape::XML::Node * _node;
768 public:
769     /** \brief  Build a string preference for the given parameter
770         \param  pref  Where to get the string from, and where to put it
771                       when it changes.
772     */
773     ParamStringEntry (ParamString * pref, SPDocument * doc, Inkscape::XML::Node * node) :
774         Gtk::Entry(), _pref(pref), _doc(doc), _node(node) {
775         if (_pref->get(NULL, NULL) != NULL)
776             this->set_text(Glib::ustring(_pref->get(NULL, NULL)));
777         this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text));
778     };
779     void changed_text (void);
780 };
782 /** \brief  Respond to the text box changing
784     This function responds to the box changing by grabbing the value
785     from the text box and putting it in the parameter.
786 */
787 void
788 ParamStringEntry::changed_text (void)
790     Glib::ustring data = this->get_text();
791     _pref->set(data.c_str(), _doc, _node);
792     return;
795 /**
796     \brief  Creates a text box for the string parameter
798     Builds a hbox with a label and a text box in it.
799 */
800 Gtk::Widget *
801 ParamString::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
803     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
805     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
806     label->show();
807     hbox->pack_start(*label, true, true);
809     ParamStringEntry * textbox = new ParamStringEntry(this, doc, node);
810     textbox->show();
811     hbox->pack_start(*textbox, false, false);
813     hbox->show();
815     return dynamic_cast<Gtk::Widget *>(hbox);
818 /** \brief  Return 'true' or 'false' */
819 Glib::ustring *
820 ParamBool::string (void)
822     Glib::ustring * mystring;
824     if (_value)
825         mystring = new Glib::ustring("true");
826     else
827         mystring = new Glib::ustring("false");
829     return mystring;
832 /** \brief  Return the value as a string */
833 Glib::ustring *
834 ParamInt::string (void)
836     char startstring[32];
837     sprintf(startstring, "%d", _value);
838     Glib::ustring * mystring = new Glib::ustring(startstring);
839     return mystring;
842 /** \brief  Return the value as a string */
843 Glib::ustring *
844 ParamFloat::string (void)
846     char startstring[G_ASCII_DTOSTR_BUF_SIZE];
847     g_ascii_dtostr(startstring, G_ASCII_DTOSTR_BUF_SIZE, _value);
848     Glib::ustring * mystring = new Glib::ustring(startstring);
849     return mystring;
852 /** \brief  Return the value as a string */
853 Glib::ustring *
854 ParamString::string (void)
856     Glib::ustring * mystring = new Glib::ustring("");
857     *mystring += "\"";
858     *mystring += _value;
859     *mystring += "\"";
860     return mystring;
863 /** \brief  Create a label for the description */
864 Gtk::Widget *
865 ParamDescription::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
867     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_value)));
868     label->set_line_wrap();
869     label->show();
871     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
872     hbox->pack_start(*label, true, true, 5);
873     hbox->show();
875     return hbox;
878 /** \brief  Initialize the object, to do that, copy the data. */
879 ParamDescription::ParamDescription (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
880     Parameter(name, guitext, desc, scope, ext), _value(NULL)
882     // printf("Building Description\n");
883     const char * defaultval = NULL;
884     if (sp_repr_children(xml) != NULL)
885         defaultval = sp_repr_children(xml)->content();
887     if (defaultval != NULL)
888         _value = g_strdup(defaultval);
890     return;
894 }  /* namespace Extension */
895 }  /* namespace Inkscape */
897 /*
898   Local Variables:
899   mode:c++
900   c-file-style:"stroustrup"
901   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
902   indent-tabs-mode:nil
903   fill-column:99
904   End:
905 */
906 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :