Code

Added notebook (tabs) support for Effects. Now you can specify a notebook parameter...
[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"
36 /** \brief  The root directory in the preferences database for extension
37             related parameters. */
38 #define PREF_DIR "extensions"
40 namespace Inkscape {
41 namespace Extension {
43 /** \brief  A description parameter */
44 class ParamDescription : public Parameter {
45 private:
46     /** \brief  Internal value. */
47     gchar * _value;
48 public:
49     ParamDescription(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
50     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
51 };
53 /** \brief  A boolean parameter */
54 class ParamBool : public Parameter {
55 private:
56     /** \brief  Internal value. */
57     bool _value;
58 public:
59     ParamBool(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
60     /** \brief  Returns \c _value */
61     bool get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
62     bool set (bool in, SPDocument * doc, Inkscape::XML::Node * node);
63     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
64     Glib::ustring * string (void);
65 };
67 /** \brief  Use the superclass' allocator and set the \c _value */
68 ParamBool::ParamBool (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
69         Parameter(name, guitext, desc, scope, ext), _value(false)
70 {
71     const char * defaultval = NULL;
72     if (sp_repr_children(xml) != NULL)
73         defaultval = sp_repr_children(xml)->content();
75     if (defaultval != NULL && (!strcmp(defaultval, "TRUE") || !strcmp(defaultval, "true") || !strcmp(defaultval, "1"))) {
76         _value = true;
77     } else {
78         _value = false;
79     }
81     gchar * pref_name = this->pref_name();
82     _value = (bool)prefs_get_int_attribute(PREF_DIR, pref_name, _value);
83     g_free(pref_name);
85     return;
86 }
88 class ParamInt : public Parameter {
89 private:
90     /** \brief  Internal value. */
91     int _value;
92     int _min;
93     int _max;
94 public:
95     ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
96     /** \brief  Returns \c _value */
97     int get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
98     int set (int in, SPDocument * doc, Inkscape::XML::Node * node);
99     int max (void) { return _max; }
100     int min (void) { return _min; }
101     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
102     Glib::ustring * string (void);
103 };
105 /** \brief  Use the superclass' allocator and set the \c _value */
106 ParamInt::ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
107         Parameter(name, guitext, desc, scope, ext), _value(0), _min(0), _max(10)
109     const char * defaultval = NULL;
110     if (sp_repr_children(xml) != NULL)
111         defaultval = sp_repr_children(xml)->content();
112     if (defaultval != NULL) {
113         _value = atoi(defaultval);
114     }
116     const char * maxval = xml->attribute("max");
117     if (maxval != NULL)
118         _max = atoi(maxval);
120     const char * minval = xml->attribute("min");
121     if (minval != NULL)
122         _min = atoi(minval);
124     /* We're handling this by just killing both values */
125     if (_max < _min) {
126         _max = 10;
127         _min = 0;
128     }
130     gchar * pref_name = this->pref_name();
131     _value = prefs_get_int_attribute(PREF_DIR, pref_name, _value);
132     g_free(pref_name);
134     // std::cout << "New Int::  value: " << _value << "  max: " << _max << "  min: " << _min << std::endl;
136     if (_value > _max) _value = _max;
137     if (_value < _min) _value = _min;
139     return;
142 class ParamFloat : public Parameter {
143 private:
144     /** \brief  Internal value. */
145     float _value;
146     float _min;
147     float _max;
148 public:
149     ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
150     /** \brief  Returns \c _value */
151     float get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
152     float set (float in, SPDocument * doc, Inkscape::XML::Node * node);
153     float max (void) { return _max; }
154     float min (void) { return _min; }
155     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
156     Glib::ustring * string (void);
157 };
159 /** \brief  Use the superclass' allocator and set the \c _value */
160 ParamFloat::ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
161         Parameter(name, guitext, desc, scope, ext), _value(0.0), _min(0.0), _max(10.0)
163     const char * defaultval = NULL;
164     if (sp_repr_children(xml) != NULL)
165         defaultval = sp_repr_children(xml)->content();
166     if (defaultval != NULL) {
167         _value = atof(defaultval);
168     }
170     const char * maxval = xml->attribute("max");
171     if (maxval != NULL)
172         _max = atof(maxval);
174     const char * minval = xml->attribute("min");
175     if (minval != NULL)
176         _min = atof(minval);
178     /* We're handling this by just killing both values */
179     if (_max < _min) {
180         _max = 10.0;
181         _min = 0.0;
182     }
184     gchar * pref_name = this->pref_name();
185     _value = prefs_get_double_attribute(PREF_DIR, pref_name, _value);
186     g_free(pref_name);
188     // std::cout << "New Float::  value: " << _value << "  max: " << _max << "  min: " << _min << std::endl;
190     if (_value > _max) _value = _max;
191     if (_value < _min) _value = _min;
193     return;
196 class ParamString : public Parameter {
197 private:
198     /** \brief  Internal value.  This should point to a string that has
199                 been allocated in memory.  And should be free'd. */
200     gchar * _value;
201 public:
202     ParamString(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
203     ~ParamString(void);
204     /** \brief  Returns \c _value, with a \i const to protect it. */
205     const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
206     const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
207     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
208     Glib::ustring * string (void);
209 };
211 class ParamEnum : public Parameter {
212 private:
213     class Choice {
214     public:
215         gchar * _gui_name;
216         gchar * _value;
217         Choice(gchar * gui_name, gchar * value) : _gui_name(NULL), _value(NULL) {
218             if (gui_name != NULL)
219                 _gui_name = g_strdup(_(gui_name));
220             if (value != NULL)
221                 _value = g_strdup(value);
222             return;
223         };
224         ~Choice (void) {
225             g_free(_gui_name);
226             g_free(_value);
227         };
228     }; /* class Choice */
229     /** \brief  Internal value.  This should point to a string that has
230                 been allocated in memory.  And should be free'd. */
231     Choice * _current_choice;
232     typedef std::list<Choice *> choice_list_t;
233     choice_list_t _choice_list;
234 public:
235     ParamEnum(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
236     ~ParamEnum(void);
237     /** \brief  Returns \c _value, with a \i const to protect it. */
238     const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _current_choice != NULL ? _current_choice->_value : NULL; }
239     const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
240     Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
241     Glib::ustring * string (void);
242 }; /* class ParamEnum */
245 /**
246     \return None
247     \brief  This function creates a parameter that can be used later.  This
248             is typically done in the creation of the extension and defined
249             in the XML file describing the extension (it's private so people
250             have to use the system) :)
251     \param  in_repr  The XML describing the parameter
253     This function first grabs all of the data out of the Repr and puts
254     it into local variables.  Actually, these are just pointers, and the
255     data is not duplicated so we need to be careful with it.  If there
256     isn't a name or a type in the XML, then no parameter is created as
257     the function just returns.
259     From this point on, we're pretty committed as we've allocated an
260     object and we're starting to fill it.  The name is set first, and
261     is created with a strdup to actually allocate memory for it.  Then
262     there is a case statement (roughly because strcmp requires 'ifs')
263     based on what type of parameter this is.  Depending which type it
264     is, the value is interpreted differently, but they are relatively
265     straight forward.  In all cases the value is set to the default
266     value from the XML and the type is set to the interpreted type.
267 */
268 Parameter *
269 Parameter::make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
271     const char * name;
272     const char * type;
273     const char * guitext;
274     const char * desc;
275     const char * scope_str;
276     Parameter::_scope_t scope = Parameter::SCOPE_USER;
278     name = in_repr->attribute("name");
279     type = in_repr->attribute("type");
280     guitext = in_repr->attribute("gui-text");
281     if (guitext == NULL)
282         guitext = in_repr->attribute("_gui-text");
283     desc = in_repr->attribute("gui-description");
284     if (desc == NULL)
285         desc = in_repr->attribute("_gui-description");
286     scope_str = in_repr->attribute("scope");
288     /* In this case we just don't have enough information */
289     if (name == NULL || type == NULL) {
290         return NULL;
291     }
293     if (scope_str != NULL) {
294         if (!strcmp(scope_str, "user")) {
295             scope = Parameter::SCOPE_USER;
296         } else if (!strcmp(scope_str, "document")) {
297             scope = Parameter::SCOPE_DOCUMENT;
298         } else if (!strcmp(scope_str, "node")) {
299             scope = Parameter::SCOPE_NODE;
300         }
301     }
303     Parameter * param = NULL;
304     if (!strcmp(type, "boolean")) {
305         param = new ParamBool(name, guitext, desc, scope, in_ext, in_repr);
306     } else if (!strcmp(type, "int")) {
307         param = new ParamInt(name, guitext, desc, scope, in_ext, in_repr);
308     } else if (!strcmp(type, "float")) {
309         param = new ParamFloat(name, guitext, desc, scope, in_ext, in_repr);
310     } else if (!strcmp(type, "string")) {
311         param = new ParamString(name, guitext, desc, scope, in_ext, in_repr);
312     } else if (!strcmp(type, "description")) {
313         param = new ParamDescription(name, guitext, desc, scope, in_ext, in_repr);
314     } else if (!strcmp(type, "enum")) {
315         param = new ParamEnum(name, guitext, desc, scope, in_ext, in_repr);
316     } else if (!strcmp(type, "notebook")) {
317         param = new ParamNotebook(name, guitext, desc, scope, in_ext, in_repr);
318     }
320     /* Note: param could equal NULL */
321     return param;
324 /** \brief  A function to set the \c _value
325     \param  in   The value to set to
326     \param  doc  A document that should be used to set the value.
327     \param  node The node where the value may be placed
329     This function sets the internal value, but it also sets the value
330     in the preferences structure.  To put it in the right place, \c PREF_DIR
331     and \c pref_name() are used.
332 */
333 bool
334 ParamBool::set (bool in, SPDocument * doc, Inkscape::XML::Node * node)
336     _value = in;
338     gchar * prefname = this->pref_name();
339     prefs_set_int_attribute(PREF_DIR, prefname, _value == true ? 1 : 0);
340     g_free(prefname);
342     return _value;
345 /** \brief  A function to set the \c _value
346     \param  in   The value to set to
347     \param  doc  A document that should be used to set the value.
348     \param  node The node where the value may be placed
350     This function sets the internal value, but it also sets the value
351     in the preferences structure.  To put it in the right place, \c PREF_DIR
352     and \c pref_name() are used.
353 */
354 int
355 ParamInt::set (int in, SPDocument * doc, Inkscape::XML::Node * node)
357     _value = in;
358     if (_value > _max) _value = _max;
359     if (_value < _min) _value = _min;
361     gchar * prefname = this->pref_name();
362     prefs_set_int_attribute(PREF_DIR, prefname, _value);
363     g_free(prefname);
365     return _value;
368 /** \brief  A function to set the \c _value
369     \param  in   The value to set to
370     \param  doc  A document that should be used to set the value.
371     \param  node The node where the value may be placed
373     This function sets the internal value, but it also sets the value
374     in the preferences structure.  To put it in the right place, \c PREF_DIR
375     and \c pref_name() are used.
376 */
377 float
378 ParamFloat::set (float in, SPDocument * doc, Inkscape::XML::Node * node)
380     _value = in;
381     if (_value > _max) _value = _max;
382     if (_value < _min) _value = _min;
384     gchar * prefname = this->pref_name();
385     prefs_set_double_attribute(PREF_DIR, prefname, _value);
386     g_free(prefname);
388     return _value;
391 /** \brief  A function to set the \c _value
392     \param  in   The value to set to
393     \param  doc  A document that should be used to set the value.
394     \param  node The node where the value may be placed
396     This function sets the internal value, but it also sets the value
397     in the preferences structure.  To put it in the right place, \c PREF_DIR
398     and \c pref_name() are used.
400     To copy the data into _value the old memory must be free'd first.
401     It is important to note that \c g_free handles \c NULL just fine.  Then
402     the passed in value is duplicated using \c g_strdup().
403 */
404 const gchar *
405 ParamString::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
407     if (in == NULL) return NULL; /* Can't have NULL string */
409     if (_value != NULL)
410         g_free(_value);
411     _value = g_strdup(in);
413     gchar * prefname = this->pref_name();
414     prefs_set_string_attribute(PREF_DIR, prefname, _value);
415     g_free(prefname);
417     return _value;
420 /** \brief  Wrapper to cast to the object and use it's function.  */
421 bool
422 Parameter::get_bool (const SPDocument * doc, const Inkscape::XML::Node * node)
424     ParamBool * boolpntr;
425     boolpntr = dynamic_cast<ParamBool *>(this);
426     if (boolpntr == NULL)
427         throw Extension::param_wrong_type();
428     return boolpntr->get(doc, node);
431 /** \brief  Wrapper to cast to the object and use it's function.  */
432 int
433 Parameter::get_int (const SPDocument * doc, const Inkscape::XML::Node * node)
435     ParamInt * intpntr;
436     intpntr = dynamic_cast<ParamInt *>(this);
437     if (intpntr == NULL)
438         throw Extension::param_wrong_type();
439     return intpntr->get(doc, node);
442 /** \brief  Wrapper to cast to the object and use it's function.  */
443 float
444 Parameter::get_float (const SPDocument * doc, const Inkscape::XML::Node * node)
446     ParamFloat * floatpntr;
447     floatpntr = dynamic_cast<ParamFloat *>(this);
448     if (floatpntr == NULL)
449         throw Extension::param_wrong_type();
450     return floatpntr->get(doc, node);
453 /** \brief  Wrapper to cast to the object and use it's function.  */
454 const gchar *
455 Parameter::get_string (const SPDocument * doc, const Inkscape::XML::Node * node)
457     ParamString * stringpntr;
458     stringpntr = dynamic_cast<ParamString *>(this);
459     if (stringpntr == NULL)
460         throw Extension::param_wrong_type();
461     return stringpntr->get(doc, node);
464 /** \brief  Wrapper to cast to the object and use it's function.  */
465 bool
466 Parameter::set_bool (bool in, SPDocument * doc, Inkscape::XML::Node * node)
468     ParamBool * boolpntr;
469     boolpntr = dynamic_cast<ParamBool *>(this);
470     if (boolpntr == NULL)
471         throw Extension::param_wrong_type();
472     return boolpntr->set(in, doc, node);
475 /** \brief  Wrapper to cast to the object and use it's function.  */
476 int
477 Parameter::set_int (int in, SPDocument * doc, Inkscape::XML::Node * node)
479     ParamInt * intpntr;
480     intpntr = dynamic_cast<ParamInt *>(this);
481     if (intpntr == NULL)
482         throw Extension::param_wrong_type();
483     return intpntr->set(in, doc, node);
486 /** \brief  Wrapper to cast to the object and use it's function.  */
487 float
488 Parameter::set_float (float in, SPDocument * doc, Inkscape::XML::Node * node)
490     ParamFloat * floatpntr;
491     floatpntr = dynamic_cast<ParamFloat *>(this);
492     if (floatpntr == NULL)
493         throw Extension::param_wrong_type();
494     return floatpntr->set(in, doc, node);
497 /** \brief  Wrapper to cast to the object and use it's function.  */
498 const gchar *
499 Parameter::set_string (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
501     ParamString * stringpntr;
502     stringpntr = dynamic_cast<ParamString *>(this);
503     if (stringpntr == NULL)
504         throw Extension::param_wrong_type();
505     return stringpntr->set(in, doc, node);
508 /** \brief  Initialize the object, to do that, copy the data. */
509 ParamString::ParamString (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
510     Parameter(name, guitext, desc, scope, ext), _value(NULL)
512     const char * defaultval = NULL;
513     if (sp_repr_children(xml) != NULL)
514         defaultval = sp_repr_children(xml)->content();
516     gchar * pref_name = this->pref_name();
517     const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
518     g_free(pref_name);
520     if (paramval != NULL)
521         defaultval = paramval;
522     if (defaultval != NULL)
523         _value = g_strdup(defaultval);
525     return;
528 /** \brief  Free the allocated data. */
529 ParamString::~ParamString(void)
531     g_free(_value);
534 /** \brief  Oop, now that we need a parameter, we need it's name.  */
535 Parameter::Parameter (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext) :
536     extension(ext), _name(NULL), _desc(NULL), _scope(scope), _text(NULL)
538     if (name != NULL)
539         _name = g_strdup(name);
540     if (desc != NULL) {
541         _desc = g_strdup(desc);
542         // printf("Adding description: '%s' on '%s'\n", _desc, _name);
543     }
546     if (guitext != NULL)
547         _text = g_strdup(guitext);
548     else
549         _text = g_strdup(name);
551     return;
554 /** \brief  Just free the allocated name. */
555 Parameter::~Parameter (void)
557     g_free(_name);
558     g_free(_text);
561 /** \brief  Build the name to write the parameter from the extension's
562             ID and the name of this parameter. */
563 gchar *
564 Parameter::pref_name (void)
566     return g_strdup_printf("%s.%s", extension->get_id(), _name);
569 Inkscape::XML::Node *
570 Parameter::find_child (Inkscape::XML::Node * adult)
572     return sp_repr_lookup_child(adult, "name", _name);
575 Inkscape::XML::Node *
576 Parameter::new_child (Inkscape::XML::Node * parent)
578     Inkscape::XML::Node * retval;
579     retval = sp_repr_new("inkscape:extension-param");
580     retval->setAttribute("name", _name);
582     parent->appendChild(retval);
583     return retval;
586 Inkscape::XML::Node *
587 Parameter::document_param_node (SPDocument * doc)
589     Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc));
590     Inkscape::XML::Node * params = NULL;
592     GQuark const name_quark = g_quark_from_string("inkscape:extension-params");
594     for (Inkscape::XML::Node * child = defs->firstChild();
595             child != NULL;
596             child = child->next()) {
597         if ((GQuark)child->code() == name_quark &&
598                 !strcmp(child->attribute("extension"), extension->get_id())) {
599             params = child;
600             break;
601         }
602     }
604     if (params == NULL) {
605         params = sp_repr_new("inkscape:extension-param");
606         params->setAttribute("extension", extension->get_id());
607         defs->appendChild(params);
608     }
610     return params;
613 /** \brief  Basically, if there is no widget pass a NULL. */
614 Gtk::Widget *
615 Parameter::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
617     return NULL;
620 /** \brief  If I'm not sure which it is, just don't return a value. */
621 Glib::ustring *
622 Parameter::string (void)
624     Glib::ustring * mystring = new Glib::ustring("");
625     return mystring;
628 /** \brief  A class to make an adjustment that uses Extension params */
629 class ParamFloatAdjustment : public Gtk::Adjustment {
630     /** The parameter to adjust */
631     ParamFloat * _pref;
632     SPDocument * _doc;
633     Inkscape::XML::Node * _node;
634 public:
635     /** \brief  Make the adjustment using an extension and the string
636                 describing the parameter. */
637     ParamFloatAdjustment (ParamFloat * param, SPDocument * doc, Inkscape::XML::Node * node) :
638             Gtk::Adjustment(0.0, param->min(), param->max(), 0.1), _pref(param), _doc(doc), _node(node) {
639         this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
640         this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed));
641         return;
642     };
644     void val_changed (void);
645 }; /* class ParamFloatAdjustment */
647 /** \brief  A function to respond to the value_changed signal from the
648             adjustment.
650     This function just grabs the value from the adjustment and writes
651     it to the parameter.  Very simple, but yet beautiful.
652 */
653 void
654 ParamFloatAdjustment::val_changed (void)
656     // std::cout << "Value Changed to: " << this->get_value() << std::endl;
657     _pref->set(this->get_value(), _doc, _node);
658     return;
661 /** \brief  A class to make an adjustment that uses Extension params */
662 class ParamIntAdjustment : public Gtk::Adjustment {
663     /** The parameter to adjust */
664     ParamInt * _pref;
665     SPDocument * _doc;
666     Inkscape::XML::Node * _node;
667 public:
668     /** \brief  Make the adjustment using an extension and the string
669                 describing the parameter. */
670     ParamIntAdjustment (ParamInt * param, SPDocument * doc, Inkscape::XML::Node * node) :
671             Gtk::Adjustment(0.0, param->min(), param->max(), 1.0), _pref(param), _doc(doc), _node(node) {
672         this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
673         this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed));
674         return;
675     };
677     void val_changed (void);
678 }; /* class ParamIntAdjustment */
680 /** \brief  A function to respond to the value_changed signal from the
681             adjustment.
683     This function just grabs the value from the adjustment and writes
684     it to the parameter.  Very simple, but yet beautiful.
685 */
686 void
687 ParamIntAdjustment::val_changed (void)
689     // std::cout << "Value Changed to: " << this->get_value() << std::endl;
690     _pref->set((int)this->get_value(), _doc, _node);
691     return;
694 /**
695     \brief  Creates a Float Adjustment for a float parameter
697     Builds a hbox with a label and a float adjustment in it.
698 */
699 Gtk::Widget *
700 ParamFloat::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
702     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
704     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
705     label->show();
706     hbox->pack_start(*label, true, true);
708     ParamFloatAdjustment * fadjust = Gtk::manage(new ParamFloatAdjustment(this, doc, node));
709     Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 0.1, 1));
710     spin->show();
711     hbox->pack_start(*spin, false, false);
713     hbox->show();
715     return dynamic_cast<Gtk::Widget *>(hbox);
718 /**
719     \brief  Creates a Int Adjustment for a int parameter
721     Builds a hbox with a label and a int adjustment in it.
722 */
723 Gtk::Widget *
724 ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
726     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
728     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
729     label->show();
730     hbox->pack_start(*label, true, true);
732     ParamIntAdjustment * fadjust = Gtk::manage(new ParamIntAdjustment(this, doc, node));
733     Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 1.0, 0));
734     spin->show();
735     hbox->pack_start(*spin, false, false);
737     hbox->show();
739     return dynamic_cast<Gtk::Widget *>(hbox);
742 /** \brief  A check button which is Param aware.  It works with the
743             parameter to change it's value as the check button changes
744             value. */
745 class ParamBoolCheckButton : public Gtk::CheckButton {
746 private:
747     /** \brief  Param to change */
748     ParamBool * _pref;
749     SPDocument * _doc;
750     Inkscape::XML::Node * _node;
751 public:
752     /** \brief  Initialize the check button
753         \param  param  Which parameter to adjust on changing the check button
755         This function sets the value of the checkbox to be that of the
756         parameter, and then sets up a callback to \c on_toggle.
757     */
758     ParamBoolCheckButton (ParamBool * param, SPDocument * doc, Inkscape::XML::Node * node) :
759             Gtk::CheckButton(), _pref(param), _doc(doc), _node(node) {
760         this->set_active(_pref->get(NULL, NULL) /**\todo fix */);
761         this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle));
762         return;
763     }
764     void on_toggle (void);
765 };
767 /**
768     \brief  A function to respond to the check box changing
770     Adjusts the value of the preference to match that in the check box.
771 */
772 void
773 ParamBoolCheckButton::on_toggle (void)
775     _pref->set(this->get_active(), NULL /**\todo fix this */, NULL);
776     return;
779 /**
780     \brief  Creates a bool check button for a bool parameter
782     Builds a hbox with a label and a check button in it.
783 */
784 Gtk::Widget *
785 ParamBool::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
787     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
789     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
790     label->show();
791     hbox->pack_start(*label, true, true);
793     ParamBoolCheckButton * checkbox = new ParamBoolCheckButton(this, doc, node);
794     checkbox->show();
795     hbox->pack_start(*checkbox, false, false);
797     hbox->show();
799     return dynamic_cast<Gtk::Widget *>(hbox);
802 /** \brief  A special category of Gtk::Entry to handle string parameteres */
803 class ParamStringEntry : public Gtk::Entry {
804 private:
805     ParamString * _pref;
806     SPDocument * _doc;
807     Inkscape::XML::Node * _node;
808 public:
809     /** \brief  Build a string preference for the given parameter
810         \param  pref  Where to get the string from, and where to put it
811                       when it changes.
812     */
813     ParamStringEntry (ParamString * pref, SPDocument * doc, Inkscape::XML::Node * node) :
814         Gtk::Entry(), _pref(pref), _doc(doc), _node(node) {
815         if (_pref->get(NULL, NULL) != NULL)
816             this->set_text(Glib::ustring(_pref->get(NULL, NULL)));
817         this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text));
818     };
819     void changed_text (void);
820 };
822 /** \brief  Respond to the text box changing
824     This function responds to the box changing by grabbing the value
825     from the text box and putting it in the parameter.
826 */
827 void
828 ParamStringEntry::changed_text (void)
830     Glib::ustring data = this->get_text();
831     _pref->set(data.c_str(), _doc, _node);
832     return;
835 /**
836     \brief  Creates a text box for the string parameter
838     Builds a hbox with a label and a text box in it.
839 */
840 Gtk::Widget *
841 ParamString::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
843     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
845     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
846     label->show();
847     hbox->pack_start(*label, false, false);
849     ParamStringEntry * textbox = new ParamStringEntry(this, doc, node);
850     textbox->show();
851     hbox->pack_start(*textbox, true, true);
853     hbox->show();
855     return dynamic_cast<Gtk::Widget *>(hbox);
858 /** \brief  Return 'true' or 'false' */
859 Glib::ustring *
860 ParamBool::string (void)
862     Glib::ustring * mystring;
864     if (_value)
865         mystring = new Glib::ustring("true");
866     else
867         mystring = new Glib::ustring("false");
869     return mystring;
872 /** \brief  Return the value as a string */
873 Glib::ustring *
874 ParamInt::string (void)
876     char startstring[32];
877     sprintf(startstring, "%d", _value);
878     Glib::ustring * mystring = new Glib::ustring(startstring);
879     return mystring;
882 /** \brief  Return the value as a string */
883 Glib::ustring *
884 ParamFloat::string (void)
886     char startstring[G_ASCII_DTOSTR_BUF_SIZE];
887     g_ascii_dtostr(startstring, G_ASCII_DTOSTR_BUF_SIZE, _value);
888     Glib::ustring * mystring = new Glib::ustring(startstring);
889     return mystring;
892 /** \brief  Return the value as a string */
893 Glib::ustring *
894 ParamString::string (void)
896     Glib::ustring * mystring = new Glib::ustring("");
897     *mystring += "\"";
898     *mystring += _value;
899     *mystring += "\"";
900     return mystring;
903 /** \brief  Create a label for the description */
904 Gtk::Widget *
905 ParamDescription::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
907     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_value)));
908     label->set_line_wrap();
909     label->show();
911     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
912     hbox->pack_start(*label, true, true, 5);
913     hbox->show();
915     return hbox;
918 /** \brief  Initialize the object, to do that, copy the data. */
919 ParamDescription::ParamDescription (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
920     Parameter(name, guitext, desc, scope, ext), _value(NULL)
922     // printf("Building Description\n");
923     const char * defaultval = NULL;
924     if (sp_repr_children(xml) != NULL)
925         defaultval = sp_repr_children(xml)->content();
927     if (defaultval != NULL)
928         _value = g_strdup(defaultval);
930     return;
933 ParamEnum::ParamEnum (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
934     Parameter(name, guitext, desc, scope, ext), _current_choice(NULL)
936     return;
939 ParamEnum::~ParamEnum (void)
944 /** \brief  Return the value as a string */
945 Glib::ustring *
946 ParamEnum::string (void)
948     Glib::ustring * mystring = new Glib::ustring("");
949     *mystring += "\"";
950     *mystring += this->get(NULL, NULL);
951     *mystring += "\"";
952     return mystring;
955 Gtk::Widget *
956 ParamEnum::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
958     return NULL;
961 const gchar *
962 ParamEnum::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
964     return NULL;
968 }  /* namespace Extension */
969 }  /* namespace Inkscape */
971 /*
972   Local Variables:
973   mode:c++
974   c-file-style:"stroustrup"
975   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
976   indent-tabs-mode:nil
977   fill-column:99
978   End:
979 */
980 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :