Code

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