Code

r11676@tres: ted | 2006-05-05 21:45:20 -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     Glib::ustring * string (void);
50 };
52 /** \brief  A boolean parameter */
53 class ParamBool : public Parameter {
54 private:
55     /** \brief  Internal value. */
56     bool _value;
57 public:
58     ParamBool(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
59     /** \brief  Returns \c _value */
60     bool get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
61     bool set (bool in, SPDocument * doc, Inkscape::XML::Node * node);
62     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
63     Glib::ustring * string (void);
64 };
66 /** \brief  Use the superclass' allocator and set the \c _value */
67 ParamBool::ParamBool (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
68         Parameter(name, guitext, desc, scope, ext), _value(false)
69 {
70     const char * defaultval = NULL;
71     if (sp_repr_children(xml) != NULL)
72         defaultval = sp_repr_children(xml)->content();
74     if (defaultval != NULL && (!strcmp(defaultval, "TRUE") || !strcmp(defaultval, "true") || !strcmp(defaultval, "1"))) {
75         _value = true;
76     } else {
77         _value = false;
78     }
80     gchar * pref_name = this->pref_name();
81     _value = (bool)prefs_get_int_attribute(PREF_DIR, pref_name, _value);
82     g_free(pref_name);
84     return;
85 }
87 class ParamInt : public Parameter {
88 private:
89     /** \brief  Internal value. */
90     int _value;
91     int _min;
92     int _max;
93 public:
94     ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
95     /** \brief  Returns \c _value */
96     int get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
97     int set (int in, SPDocument * doc, Inkscape::XML::Node * node);
98     int max (void) { return _max; }
99     int min (void) { return _min; }
100     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
101     Glib::ustring * string (void);
102 };
104 /** \brief  Use the superclass' allocator and set the \c _value */
105 ParamInt::ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
106         Parameter(name, guitext, desc, scope, ext), _value(0), _min(0), _max(10)
108     const char * defaultval = NULL;
109     if (sp_repr_children(xml) != NULL)
110         defaultval = sp_repr_children(xml)->content();
111     if (defaultval != NULL) {
112         _value = atoi(defaultval);
113     }
115     const char * maxval = xml->attribute("max");
116     if (maxval != NULL)
117         _max = atoi(maxval);
119     const char * minval = xml->attribute("min");
120     if (minval != NULL)
121         _min = atoi(minval);
123     /* We're handling this by just killing both values */
124     if (_max < _min) {
125         _max = 10;
126         _min = 0;
127     }
129     gchar * pref_name = this->pref_name();
130     _value = prefs_get_int_attribute(PREF_DIR, pref_name, _value);
131     g_free(pref_name);
133     // std::cout << "New Int::  value: " << _value << "  max: " << _max << "  min: " << _min << std::endl;
135     if (_value > _max) _value = _max;
136     if (_value < _min) _value = _min;
138     return;
141 class ParamFloat : public Parameter {
142 private:
143     /** \brief  Internal value. */
144     float _value;
145     float _min;
146     float _max;
147 public:
148     ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
149     /** \brief  Returns \c _value */
150     float get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
151     float set (float in, SPDocument * doc, Inkscape::XML::Node * node);
152     float max (void) { return _max; }
153     float min (void) { return _min; }
154     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
155     Glib::ustring * string (void);
156 };
158 /** \brief  Use the superclass' allocator and set the \c _value */
159 ParamFloat::ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
160         Parameter(name, guitext, desc, scope, ext), _value(0.0), _min(0.0), _max(10.0)
162     const char * defaultval = NULL;
163     if (sp_repr_children(xml) != NULL)
164         defaultval = sp_repr_children(xml)->content();
165     if (defaultval != NULL) {
166         _value = atof(defaultval);
167     }
169     const char * maxval = xml->attribute("max");
170     if (maxval != NULL)
171         _max = atof(maxval);
173     const char * minval = xml->attribute("min");
174     if (minval != NULL)
175         _min = atof(minval);
177     /* We're handling this by just killing both values */
178     if (_max < _min) {
179         _max = 10.0;
180         _min = 0.0;
181     }
183     gchar * pref_name = this->pref_name();
184     _value = prefs_get_double_attribute(PREF_DIR, pref_name, _value);
185     g_free(pref_name);
187     // std::cout << "New Float::  value: " << _value << "  max: " << _max << "  min: " << _min << std::endl;
189     if (_value > _max) _value = _max;
190     if (_value < _min) _value = _min;
192     return;
195 class ParamString : public Parameter {
196 private:
197     /** \brief  Internal value.  This should point to a string that has
198                 been allocated in memory.  And should be free'd. */
199     gchar * _value;
200 public:
201     ParamString(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
202     ~ParamString(void);
203     /** \brief  Returns \c _value, with a \i const to protect it. */
204     const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
205     const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
206     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
207     Glib::ustring * string (void);
208 };
210 /**
211     \return None
212     \brief  This function creates a parameter that can be used later.  This
213             is typically done in the creation of the extension and defined
214             in the XML file describing the extension (it's private so people
215             have to use the system) :)
216     \param  in_repr  The XML describing the parameter
218     This function first grabs all of the data out of the Repr and puts
219     it into local variables.  Actually, these are just pointers, and the
220     data is not duplicated so we need to be careful with it.  If there
221     isn't a name or a type in the XML, then no parameter is created as
222     the function just returns.
224     From this point on, we're pretty committed as we've allocated an
225     object and we're starting to fill it.  The name is set first, and
226     is created with a strdup to actually allocate memory for it.  Then
227     there is a case statement (roughly because strcmp requires 'ifs')
228     based on what type of parameter this is.  Depending which type it
229     is, the value is interpreted differently, but they are relatively
230     straight forward.  In all cases the value is set to the default
231     value from the XML and the type is set to the interpreted type.
232 */
233 Parameter *
234 Parameter::make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
236     const char * name;
237     const char * type;
238     const char * guitext;
239     const char * desc;
240     const char * scope_str;
241     Parameter::_scope_t scope = Parameter::SCOPE_USER;
243     name = in_repr->attribute("name");
244     type = in_repr->attribute("type");
245     guitext = in_repr->attribute("gui-text");
246     if (guitext == NULL)
247         guitext = in_repr->attribute("_gui-text");
248     desc = in_repr->attribute("gui-description");
249     if (desc == NULL)
250         desc = in_repr->attribute("_gui-description");
251     scope_str = in_repr->attribute("scope");
253     /* In this case we just don't have enough information */
254     if (name == NULL || type == NULL) {
255         return NULL;
256     }
258     if (scope_str != NULL) {
259         if (!strcmp(scope_str, "user")) {
260             scope = Parameter::SCOPE_USER;
261         } else if (!strcmp(scope_str, "document")) {
262             scope = Parameter::SCOPE_DOCUMENT;
263         } else if (!strcmp(scope_str, "node")) {
264             scope = Parameter::SCOPE_NODE;
265         }
266     }
268     Parameter * param = NULL;
269     if (!strcmp(type, "boolean")) {
270         param = new ParamBool(name, guitext, desc, scope, in_ext, in_repr);
271     } else if (!strcmp(type, "int")) {
272         param = new ParamInt(name, guitext, desc, scope, in_ext, in_repr);
273     } else if (!strcmp(type, "float")) {
274         param = new ParamFloat(name, guitext, desc, scope, in_ext, in_repr);
275     } else if (!strcmp(type, "string")) {
276         param = new ParamString(name, guitext, desc, scope, in_ext, in_repr);
277     } else if (!strcmp(type, "description")) {
278         param = new ParamDescription(name, guitext, desc, scope, in_ext, in_repr);
279     }
281     /* Note: param could equal NULL */
282     return param;
285 /** \brief  A function to set the \c _value
286     \param  in   The value to set to
287     \param  doc  A document that should be used to set the value.
288     \param  node The node where the value may be placed
290     This function sets the internal value, but it also sets the value
291     in the preferences structure.  To put it in the right place, \c PREF_DIR
292     and \c pref_name() are used.
293 */
294 bool
295 ParamBool::set (bool in, SPDocument * doc, Inkscape::XML::Node * node)
297     _value = in;
299     gchar * prefname = this->pref_name();
300     prefs_set_int_attribute(PREF_DIR, prefname, _value == true ? 1 : 0);
301     g_free(prefname);
303     return _value;
306 /** \brief  A function to set the \c _value
307     \param  in   The value to set to
308     \param  doc  A document that should be used to set the value.
309     \param  node The node where the value may be placed
311     This function sets the internal value, but it also sets the value
312     in the preferences structure.  To put it in the right place, \c PREF_DIR
313     and \c pref_name() are used.
314 */
315 int
316 ParamInt::set (int in, SPDocument * doc, Inkscape::XML::Node * node)
318     _value = in;
319     if (_value > _max) _value = _max;
320     if (_value < _min) _value = _min;
322     gchar * prefname = this->pref_name();
323     prefs_set_int_attribute(PREF_DIR, prefname, _value);
324     g_free(prefname);
326     return _value;
329 /** \brief  A function to set the \c _value
330     \param  in   The value to set to
331     \param  doc  A document that should be used to set the value.
332     \param  node The node where the value may be placed
334     This function sets the internal value, but it also sets the value
335     in the preferences structure.  To put it in the right place, \c PREF_DIR
336     and \c pref_name() are used.
337 */
338 float
339 ParamFloat::set (float in, SPDocument * doc, Inkscape::XML::Node * node)
341     _value = in;
342     if (_value > _max) _value = _max;
343     if (_value < _min) _value = _min;
345     gchar * prefname = this->pref_name();
346     prefs_set_double_attribute(PREF_DIR, prefname, _value);
347     g_free(prefname);
349     return _value;
352 /** \brief  A function to set the \c _value
353     \param  in   The value to set to
354     \param  doc  A document that should be used to set the value.
355     \param  node The node where the value may be placed
357     This function sets the internal value, but it also sets the value
358     in the preferences structure.  To put it in the right place, \c PREF_DIR
359     and \c pref_name() are used.
361     To copy the data into _value the old memory must be free'd first.
362     It is important to note that \c g_free handles \c NULL just fine.  Then
363     the passed in value is duplicated using \c g_strdup().
364 */
365 const gchar *
366 ParamString::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
368     if (in == NULL) return NULL; /* Can't have NULL string */
370     if (_value != NULL)
371         g_free(_value);
372     _value = g_strdup(in);
374     gchar * prefname = this->pref_name();
375     prefs_set_string_attribute(PREF_DIR, prefname, _value);
376     g_free(prefname);
378     return _value;
381 /** \brief  Wrapper to cast to the object and use it's function.  */
382 bool
383 Parameter::get_bool (const SPDocument * doc, const Inkscape::XML::Node * node)
385     ParamBool * boolpntr;
386     boolpntr = dynamic_cast<ParamBool *>(this);
387     if (boolpntr == NULL)
388         throw Extension::param_wrong_type();
389     return boolpntr->get(doc, node);
392 /** \brief  Wrapper to cast to the object and use it's function.  */
393 int
394 Parameter::get_int (const SPDocument * doc, const Inkscape::XML::Node * node)
396     ParamInt * intpntr;
397     intpntr = dynamic_cast<ParamInt *>(this);
398     if (intpntr == NULL)
399         throw Extension::param_wrong_type();
400     return intpntr->get(doc, node);
403 /** \brief  Wrapper to cast to the object and use it's function.  */
404 float
405 Parameter::get_float (const SPDocument * doc, const Inkscape::XML::Node * node)
407     ParamFloat * floatpntr;
408     floatpntr = dynamic_cast<ParamFloat *>(this);
409     if (floatpntr == NULL)
410         throw Extension::param_wrong_type();
411     return floatpntr->get(doc, node);
414 /** \brief  Wrapper to cast to the object and use it's function.  */
415 const gchar *
416 Parameter::get_string (const SPDocument * doc, const Inkscape::XML::Node * node)
418     ParamString * stringpntr;
419     stringpntr = dynamic_cast<ParamString *>(this);
420     if (stringpntr == NULL)
421         throw Extension::param_wrong_type();
422     return stringpntr->get(doc, node);
425 /** \brief  Wrapper to cast to the object and use it's function.  */
426 bool
427 Parameter::set_bool (bool in, SPDocument * doc, Inkscape::XML::Node * node)
429     ParamBool * boolpntr;
430     boolpntr = dynamic_cast<ParamBool *>(this);
431     if (boolpntr == NULL)
432         throw Extension::param_wrong_type();
433     return boolpntr->set(in, doc, node);
436 /** \brief  Wrapper to cast to the object and use it's function.  */
437 int
438 Parameter::set_int (int in, SPDocument * doc, Inkscape::XML::Node * node)
440     ParamInt * intpntr;
441     intpntr = dynamic_cast<ParamInt *>(this);
442     if (intpntr == NULL)
443         throw Extension::param_wrong_type();
444     return intpntr->set(in, doc, node);
447 /** \brief  Wrapper to cast to the object and use it's function.  */
448 float
449 Parameter::set_float (float in, SPDocument * doc, Inkscape::XML::Node * node)
451     ParamFloat * floatpntr;
452     floatpntr = dynamic_cast<ParamFloat *>(this);
453     if (floatpntr == NULL)
454         throw Extension::param_wrong_type();
455     return floatpntr->set(in, doc, node);
458 /** \brief  Wrapper to cast to the object and use it's function.  */
459 const gchar *
460 Parameter::set_string (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
462     ParamString * stringpntr;
463     stringpntr = dynamic_cast<ParamString *>(this);
464     if (stringpntr == NULL)
465         throw Extension::param_wrong_type();
466     return stringpntr->set(in, doc, node);
469 /** \brief  Initialize the object, to do that, copy the data. */
470 ParamString::ParamString (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
471     Parameter(name, guitext, desc, scope, ext), _value(NULL)
473     const char * defaultval = NULL;
474     if (sp_repr_children(xml) != NULL)
475         defaultval = sp_repr_children(xml)->content();
477     gchar * pref_name = this->pref_name();
478     const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
479     g_free(pref_name);
481     if (paramval != NULL)
482         defaultval = paramval;
483     if (defaultval != NULL)
484         _value = g_strdup(defaultval);
486     return;
489 /** \brief  Free the allocated data. */
490 ParamString::~ParamString(void)
492     g_free(_value);
495 /** \brief  Oop, now that we need a parameter, we need it's name.  */
496 Parameter::Parameter (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext) :
497     extension(ext), _name(NULL), _desc(NULL), _scope(scope), _text(NULL)
499     if (name != NULL)
500         _name = g_strdup(name);
501     if (desc != NULL) {
502         _desc = g_strdup(desc);
503         // printf("Adding description: '%s' on '%s'\n", _desc, _name);
504     }
507     if (guitext != NULL)
508         _text = g_strdup(guitext);
509     else
510         _text = g_strdup(name);
512     return;
515 /** \brief  Just free the allocated name. */
516 Parameter::~Parameter (void)
518     g_free(_name);
519     g_free(_text);
522 /** \brief  Build the name to write the parameter from the extension's
523             ID and the name of this parameter. */
524 gchar *
525 Parameter::pref_name (void)
527     return g_strdup_printf("%s.%s", extension->get_id(), _name);
530 Inkscape::XML::Node *
531 Parameter::find_child (Inkscape::XML::Node * adult)
533     return sp_repr_lookup_child(adult, "name", _name);
536 Inkscape::XML::Node *
537 Parameter::new_child (Inkscape::XML::Node * parent)
539     Inkscape::XML::Node * retval;
540     retval = sp_repr_new("inkscape:extension-param");
541     retval->setAttribute("name", _name);
543     parent->appendChild(retval);
544     return retval;
547 Inkscape::XML::Node *
548 Parameter::document_param_node (SPDocument * doc)
550     Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc));
551     Inkscape::XML::Node * params = NULL;
553     GQuark const name_quark = g_quark_from_string("inkscape:extension-params");
555     for (Inkscape::XML::Node * child = defs->firstChild();
556             child != NULL;
557             child = child->next()) {
558         if ((GQuark)child->code() == name_quark &&
559                 !strcmp(child->attribute("extension"), extension->get_id())) {
560             params = child;
561             break;
562         }
563     }
565     if (params == NULL) {
566         params = sp_repr_new("inkscape:extension-param");
567         params->setAttribute("extension", extension->get_id());
568         defs->appendChild(params);
569     }
571     return params;
574 /** \brief  Basically, if there is no widget pass a NULL. */
575 Gtk::Widget *
576 Parameter::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
578     return NULL;
581 /** \brief  If I'm not sure which it is, just don't return a value. */
582 Glib::ustring *
583 Parameter::string (void)
585     Glib::ustring * mystring = new Glib::ustring("");
586     return mystring;
589 /** \brief  A class to make an adjustment that uses Extension params */
590 class ParamFloatAdjustment : public Gtk::Adjustment {
591     /** The parameter to adjust */
592     ParamFloat * _pref;
593     SPDocument * _doc;
594     Inkscape::XML::Node * _node;
595 public:
596     /** \brief  Make the adjustment using an extension and the string
597                 describing the parameter. */
598     ParamFloatAdjustment (ParamFloat * param, SPDocument * doc, Inkscape::XML::Node * node) :
599             Gtk::Adjustment(0.0, param->min(), param->max(), 0.1), _pref(param), _doc(doc), _node(node) {
600         this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
601         this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed));
602         return;
603     };
605     void val_changed (void);
606 }; /* class ParamFloatAdjustment */
608 /** \brief  A function to respond to the value_changed signal from the
609             adjustment.
611     This function just grabs the value from the adjustment and writes
612     it to the parameter.  Very simple, but yet beautiful.
613 */
614 void
615 ParamFloatAdjustment::val_changed (void)
617     // std::cout << "Value Changed to: " << this->get_value() << std::endl;
618     _pref->set(this->get_value(), _doc, _node);
619     return;
622 /** \brief  A class to make an adjustment that uses Extension params */
623 class ParamIntAdjustment : public Gtk::Adjustment {
624     /** The parameter to adjust */
625     ParamInt * _pref;
626     SPDocument * _doc;
627     Inkscape::XML::Node * _node;
628 public:
629     /** \brief  Make the adjustment using an extension and the string
630                 describing the parameter. */
631     ParamIntAdjustment (ParamInt * param, SPDocument * doc, Inkscape::XML::Node * node) :
632             Gtk::Adjustment(0.0, param->min(), param->max(), 1.0), _pref(param), _doc(doc), _node(node) {
633         this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
634         this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed));
635         return;
636     };
638     void val_changed (void);
639 }; /* class ParamIntAdjustment */
641 /** \brief  A function to respond to the value_changed signal from the
642             adjustment.
644     This function just grabs the value from the adjustment and writes
645     it to the parameter.  Very simple, but yet beautiful.
646 */
647 void
648 ParamIntAdjustment::val_changed (void)
650     // std::cout << "Value Changed to: " << this->get_value() << std::endl;
651     _pref->set((int)this->get_value(), _doc, _node);
652     return;
655 /**
656     \brief  Creates a Float Adjustment for a float parameter
658     Builds a hbox with a label and a float adjustment in it.
659 */
660 Gtk::Widget *
661 ParamFloat::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
663     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
665     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
666     label->show();
667     hbox->pack_start(*label, true, true);
669     ParamFloatAdjustment * fadjust = Gtk::manage(new ParamFloatAdjustment(this, doc, node));
670     Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 0.1, 1));
671     spin->show();
672     hbox->pack_start(*spin, false, false);
674     hbox->show();
676     return dynamic_cast<Gtk::Widget *>(hbox);
679 /**
680     \brief  Creates a Int Adjustment for a int parameter
682     Builds a hbox with a label and a int adjustment in it.
683 */
684 Gtk::Widget *
685 ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
687     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
689     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
690     label->show();
691     hbox->pack_start(*label, true, true);
693     ParamIntAdjustment * fadjust = Gtk::manage(new ParamIntAdjustment(this, doc, node));
694     Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 1.0, 0));
695     spin->show();
696     hbox->pack_start(*spin, false, false);
698     hbox->show();
700     return dynamic_cast<Gtk::Widget *>(hbox);
703 /** \brief  A check button which is Param aware.  It works with the
704             parameter to change it's value as the check button changes
705             value. */
706 class ParamBoolCheckButton : public Gtk::CheckButton {
707 private:
708     /** \brief  Param to change */
709     ParamBool * _pref;
710     SPDocument * _doc;
711     Inkscape::XML::Node * _node;
712 public:
713     /** \brief  Initialize the check button
714         \param  param  Which parameter to adjust on changing the check button
716         This function sets the value of the checkbox to be that of the
717         parameter, and then sets up a callback to \c on_toggle.
718     */
719     ParamBoolCheckButton (ParamBool * param, SPDocument * doc, Inkscape::XML::Node * node) :
720             Gtk::CheckButton(), _pref(param), _doc(doc), _node(node) {
721         this->set_active(_pref->get(NULL, NULL) /**\todo fix */);
722         this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle));
723         return;
724     }
725     void on_toggle (void);
726 };
728 /**
729     \brief  A function to respond to the check box changing
731     Adjusts the value of the preference to match that in the check box.
732 */
733 void
734 ParamBoolCheckButton::on_toggle (void)
736     _pref->set(this->get_active(), NULL /**\todo fix this */, NULL);
737     return;
740 /**
741     \brief  Creates a bool check button for a bool parameter
743     Builds a hbox with a label and a check button in it.
744 */
745 Gtk::Widget *
746 ParamBool::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
748     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
750     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
751     label->show();
752     hbox->pack_start(*label, true, true);
754     ParamBoolCheckButton * checkbox = new ParamBoolCheckButton(this, doc, node);
755     checkbox->show();
756     hbox->pack_start(*checkbox, false, false);
758     hbox->show();
760     return dynamic_cast<Gtk::Widget *>(hbox);
763 /** \brief  A special category of Gtk::Entry to handle string parameteres */
764 class ParamStringEntry : public Gtk::Entry {
765 private:
766     ParamString * _pref;
767     SPDocument * _doc;
768     Inkscape::XML::Node * _node;
769 public:
770     /** \brief  Build a string preference for the given parameter
771         \param  pref  Where to get the string from, and where to put it
772                       when it changes.
773     */
774     ParamStringEntry (ParamString * pref, SPDocument * doc, Inkscape::XML::Node * node) :
775         Gtk::Entry(), _pref(pref), _doc(doc), _node(node) {
776         if (_pref->get(NULL, NULL) != NULL)
777             this->set_text(Glib::ustring(_pref->get(NULL, NULL)));
778         this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text));
779     };
780     void changed_text (void);
781 };
783 /** \brief  Respond to the text box changing
785     This function responds to the box changing by grabbing the value
786     from the text box and putting it in the parameter.
787 */
788 void
789 ParamStringEntry::changed_text (void)
791     Glib::ustring data = this->get_text();
792     _pref->set(data.c_str(), _doc, _node);
793     return;
796 /**
797     \brief  Creates a text box for the string parameter
799     Builds a hbox with a label and a text box in it.
800 */
801 Gtk::Widget *
802 ParamString::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
804     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
806     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
807     label->show();
808     hbox->pack_start(*label, true, true);
810     ParamStringEntry * textbox = new ParamStringEntry(this, doc, node);
811     textbox->show();
812     hbox->pack_start(*textbox, false, false);
814     hbox->show();
816     return dynamic_cast<Gtk::Widget *>(hbox);
819 /** \brief  Return 'true' or 'false' */
820 Glib::ustring *
821 ParamBool::string (void)
823     Glib::ustring * mystring;
825     if (_value)
826         mystring = new Glib::ustring("true");
827     else
828         mystring = new Glib::ustring("false");
830     return mystring;
833 /** \brief  Return the value as a string */
834 Glib::ustring *
835 ParamInt::string (void)
837     char startstring[32];
838     sprintf(startstring, "%d", _value);
839     Glib::ustring * mystring = new Glib::ustring(startstring);
840     return mystring;
843 /** \brief  Return the value as a string */
844 Glib::ustring *
845 ParamFloat::string (void)
847     char startstring[G_ASCII_DTOSTR_BUF_SIZE];
848     g_ascii_dtostr(startstring, G_ASCII_DTOSTR_BUF_SIZE, _value);
849     Glib::ustring * mystring = new Glib::ustring(startstring);
850     return mystring;
853 /** \brief  Return the value as a string */
854 Glib::ustring *
855 ParamString::string (void)
857     Glib::ustring * mystring = new Glib::ustring("");
858     *mystring += "\"";
859     *mystring += _value;
860     *mystring += "\"";
861     return mystring;
864 /** \brief  Return the value as a string */
865 Glib::ustring *
866 ParamDescription::string (void)
868     Glib::ustring * mystring = new Glib::ustring("");
869     *mystring += "\"";
870     *mystring += _value;
871     *mystring += "\"";
872     return mystring;
875 /** \brief  Create a label for the description */
876 Gtk::Widget *
877 ParamDescription::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
879     Gtk::Label * label = Gtk::manage(new Gtk::Label(_value));
880     label->set_line_wrap();
881     label->show();
883     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
884     hbox->pack_start(*label, true, true, 5);
885     hbox->show();
887     return hbox;
890 /** \brief  Initialize the object, to do that, copy the data. */
891 ParamDescription::ParamDescription (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
892     Parameter(name, guitext, desc, scope, ext), _value(NULL)
894     // printf("Building Description\n");
895     const char * defaultval = NULL;
896     if (sp_repr_children(xml) != NULL)
897         defaultval = sp_repr_children(xml)->content();
899     if (defaultval != NULL)
900         _value = g_strdup(defaultval);
902     return;
906 }  /* namespace Extension */
907 }  /* namespace Inkscape */
909 /*
910   Local Variables:
911   mode:c++
912   c-file-style:"stroustrup"
913   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
914   indent-tabs-mode:nil
915   fill-column:99
916   End:
917 */
918 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :