1 /** \file
2 * Parameters for extensions.
3 */
5 /*
6 * Authors:
7 * Ted Gould <ted@gould.cx>
8 *
9 * Copyright (C) 2005-2006 Authors
10 *
11 * Released under GNU GPL, read the file 'COPYING' for more information
12 */
14 #ifdef HAVE_CONFIG_H
15 # include "config.h"
16 #endif
19 #include <gtkmm/adjustment.h>
20 #include <gtkmm/box.h>
21 #include <gtkmm/spinbutton.h>
23 #include <glibmm/i18n.h>
25 #include <xml/node.h>
27 #include "extension.h"
28 #include "prefs-utils.h"
29 #include "document-private.h"
30 #include "sp-object.h"
32 #include "parameter.h"
34 /** \brief The root directory in the preferences database for extension
35 related parameters. */
36 #define PREF_DIR "extensions"
38 namespace Inkscape {
39 namespace Extension {
41 /** \brief A description parameter */
42 class ParamDescription : public Parameter {
43 private:
44 /** \brief Internal value. */
45 gchar * _value;
46 public:
47 ParamDescription(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
48 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
49 };
51 /** \brief A boolean parameter */
52 class ParamBool : public Parameter {
53 private:
54 /** \brief Internal value. */
55 bool _value;
56 public:
57 ParamBool(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
58 /** \brief Returns \c _value */
59 bool get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
60 bool set (bool in, SPDocument * doc, Inkscape::XML::Node * node);
61 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
62 Glib::ustring * string (void);
63 };
65 /** \brief Use the superclass' allocator and set the \c _value */
66 ParamBool::ParamBool (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
67 Parameter(name, guitext, desc, scope, ext), _value(false)
68 {
69 const char * defaultval = NULL;
70 if (sp_repr_children(xml) != NULL)
71 defaultval = sp_repr_children(xml)->content();
73 if (defaultval != NULL && (!strcmp(defaultval, "TRUE") || !strcmp(defaultval, "true") || !strcmp(defaultval, "1"))) {
74 _value = true;
75 } else {
76 _value = false;
77 }
79 gchar * pref_name = this->pref_name();
80 _value = (bool)prefs_get_int_attribute(PREF_DIR, pref_name, _value);
81 g_free(pref_name);
83 return;
84 }
86 class ParamInt : public Parameter {
87 private:
88 /** \brief Internal value. */
89 int _value;
90 int _min;
91 int _max;
92 public:
93 ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
94 /** \brief Returns \c _value */
95 int get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
96 int set (int in, SPDocument * doc, Inkscape::XML::Node * node);
97 int max (void) { return _max; }
98 int min (void) { return _min; }
99 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
100 Glib::ustring * string (void);
101 };
103 /** \brief Use the superclass' allocator and set the \c _value */
104 ParamInt::ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
105 Parameter(name, guitext, desc, scope, ext), _value(0), _min(0), _max(10)
106 {
107 const char * defaultval = NULL;
108 if (sp_repr_children(xml) != NULL)
109 defaultval = sp_repr_children(xml)->content();
110 if (defaultval != NULL) {
111 _value = atoi(defaultval);
112 }
114 const char * maxval = xml->attribute("max");
115 if (maxval != NULL)
116 _max = atoi(maxval);
118 const char * minval = xml->attribute("min");
119 if (minval != NULL)
120 _min = atoi(minval);
122 /* We're handling this by just killing both values */
123 if (_max < _min) {
124 _max = 10;
125 _min = 0;
126 }
128 gchar * pref_name = this->pref_name();
129 _value = prefs_get_int_attribute(PREF_DIR, pref_name, _value);
130 g_free(pref_name);
132 // std::cout << "New Int:: value: " << _value << " max: " << _max << " min: " << _min << std::endl;
134 if (_value > _max) _value = _max;
135 if (_value < _min) _value = _min;
137 return;
138 }
140 class ParamFloat : public Parameter {
141 private:
142 /** \brief Internal value. */
143 float _value;
144 float _min;
145 float _max;
146 public:
147 ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
148 /** \brief Returns \c _value */
149 float get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
150 float set (float in, SPDocument * doc, Inkscape::XML::Node * node);
151 float max (void) { return _max; }
152 float min (void) { return _min; }
153 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
154 Glib::ustring * string (void);
155 };
157 /** \brief Use the superclass' allocator and set the \c _value */
158 ParamFloat::ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
159 Parameter(name, guitext, desc, scope, ext), _value(0.0), _min(0.0), _max(10.0)
160 {
161 const char * defaultval = NULL;
162 if (sp_repr_children(xml) != NULL)
163 defaultval = sp_repr_children(xml)->content();
164 if (defaultval != NULL) {
165 _value = atof(defaultval);
166 }
168 const char * maxval = xml->attribute("max");
169 if (maxval != NULL)
170 _max = atof(maxval);
172 const char * minval = xml->attribute("min");
173 if (minval != NULL)
174 _min = atof(minval);
176 /* We're handling this by just killing both values */
177 if (_max < _min) {
178 _max = 10.0;
179 _min = 0.0;
180 }
182 gchar * pref_name = this->pref_name();
183 _value = prefs_get_double_attribute(PREF_DIR, pref_name, _value);
184 g_free(pref_name);
186 // std::cout << "New Float:: value: " << _value << " max: " << _max << " min: " << _min << std::endl;
188 if (_value > _max) _value = _max;
189 if (_value < _min) _value = _min;
191 return;
192 }
194 class ParamString : public Parameter {
195 private:
196 /** \brief Internal value. This should point to a string that has
197 been allocated in memory. And should be free'd. */
198 gchar * _value;
199 public:
200 ParamString(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
201 ~ParamString(void);
202 /** \brief Returns \c _value, with a \i const to protect it. */
203 const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
204 const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
205 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
206 Glib::ustring * string (void);
207 };
209 class ParamEnum : public Parameter {
210 private:
211 class Choice {
212 public:
213 gchar * _gui_name;
214 gchar * _value;
215 Choice(gchar * gui_name, gchar * value) : _gui_name(NULL), _value(NULL) {
216 if (gui_name != NULL)
217 _gui_name = g_strdup(_(gui_name));
218 if (value != NULL)
219 _value = g_strdup(value);
220 return;
221 };
222 ~Choice (void) {
223 g_free(_gui_name);
224 g_free(_value);
225 };
226 }; /* class Choice */
227 /** \brief Internal value. This should point to a string that has
228 been allocated in memory. And should be free'd. */
229 Choice * _current_choice;
230 typedef std::list<Choice *> choice_list_t;
231 choice_list_t _choice_list;
232 public:
233 ParamEnum(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
234 ~ParamEnum(void);
235 /** \brief Returns \c _value, with a \i const to protect it. */
236 const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _current_choice != NULL ? _current_choice->_value : NULL; }
237 const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
238 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
239 Glib::ustring * string (void);
240 }; /* class ParamEnum */
242 /**
243 \return None
244 \brief This function creates a parameter that can be used later. This
245 is typically done in the creation of the extension and defined
246 in the XML file describing the extension (it's private so people
247 have to use the system) :)
248 \param in_repr The XML describing the parameter
250 This function first grabs all of the data out of the Repr and puts
251 it into local variables. Actually, these are just pointers, and the
252 data is not duplicated so we need to be careful with it. If there
253 isn't a name or a type in the XML, then no parameter is created as
254 the function just returns.
256 From this point on, we're pretty committed as we've allocated an
257 object and we're starting to fill it. The name is set first, and
258 is created with a strdup to actually allocate memory for it. Then
259 there is a case statement (roughly because strcmp requires 'ifs')
260 based on what type of parameter this is. Depending which type it
261 is, the value is interpreted differently, but they are relatively
262 straight forward. In all cases the value is set to the default
263 value from the XML and the type is set to the interpreted type.
264 */
265 Parameter *
266 Parameter::make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
267 {
268 const char * name;
269 const char * type;
270 const char * guitext;
271 const char * desc;
272 const char * scope_str;
273 Parameter::_scope_t scope = Parameter::SCOPE_USER;
275 name = in_repr->attribute("name");
276 type = in_repr->attribute("type");
277 guitext = in_repr->attribute("gui-text");
278 if (guitext == NULL)
279 guitext = in_repr->attribute("_gui-text");
280 desc = in_repr->attribute("gui-description");
281 if (desc == NULL)
282 desc = in_repr->attribute("_gui-description");
283 scope_str = in_repr->attribute("scope");
285 /* In this case we just don't have enough information */
286 if (name == NULL || type == NULL) {
287 return NULL;
288 }
290 if (scope_str != NULL) {
291 if (!strcmp(scope_str, "user")) {
292 scope = Parameter::SCOPE_USER;
293 } else if (!strcmp(scope_str, "document")) {
294 scope = Parameter::SCOPE_DOCUMENT;
295 } else if (!strcmp(scope_str, "node")) {
296 scope = Parameter::SCOPE_NODE;
297 }
298 }
300 Parameter * param = NULL;
301 if (!strcmp(type, "boolean")) {
302 param = new ParamBool(name, guitext, desc, scope, in_ext, in_repr);
303 } else if (!strcmp(type, "int")) {
304 param = new ParamInt(name, guitext, desc, scope, in_ext, in_repr);
305 } else if (!strcmp(type, "float")) {
306 param = new ParamFloat(name, guitext, desc, scope, in_ext, in_repr);
307 } else if (!strcmp(type, "string")) {
308 param = new ParamString(name, guitext, desc, scope, in_ext, in_repr);
309 } else if (!strcmp(type, "description")) {
310 param = new ParamDescription(name, guitext, desc, scope, in_ext, in_repr);
311 } else if (!strcmp(type, "enum")) {
312 param = new ParamEnum(name, guitext, desc, scope, in_ext, in_repr);
313 }
315 /* Note: param could equal NULL */
316 return param;
317 }
319 /** \brief A function to set the \c _value
320 \param in The value to set to
321 \param doc A document that should be used to set the value.
322 \param node The node where the value may be placed
324 This function sets the internal value, but it also sets the value
325 in the preferences structure. To put it in the right place, \c PREF_DIR
326 and \c pref_name() are used.
327 */
328 bool
329 ParamBool::set (bool in, SPDocument * doc, Inkscape::XML::Node * node)
330 {
331 _value = in;
333 gchar * prefname = this->pref_name();
334 prefs_set_int_attribute(PREF_DIR, prefname, _value == true ? 1 : 0);
335 g_free(prefname);
337 return _value;
338 }
340 /** \brief A function to set the \c _value
341 \param in The value to set to
342 \param doc A document that should be used to set the value.
343 \param node The node where the value may be placed
345 This function sets the internal value, but it also sets the value
346 in the preferences structure. To put it in the right place, \c PREF_DIR
347 and \c pref_name() are used.
348 */
349 int
350 ParamInt::set (int in, SPDocument * doc, Inkscape::XML::Node * node)
351 {
352 _value = in;
353 if (_value > _max) _value = _max;
354 if (_value < _min) _value = _min;
356 gchar * prefname = this->pref_name();
357 prefs_set_int_attribute(PREF_DIR, prefname, _value);
358 g_free(prefname);
360 return _value;
361 }
363 /** \brief A function to set the \c _value
364 \param in The value to set to
365 \param doc A document that should be used to set the value.
366 \param node The node where the value may be placed
368 This function sets the internal value, but it also sets the value
369 in the preferences structure. To put it in the right place, \c PREF_DIR
370 and \c pref_name() are used.
371 */
372 float
373 ParamFloat::set (float in, SPDocument * doc, Inkscape::XML::Node * node)
374 {
375 _value = in;
376 if (_value > _max) _value = _max;
377 if (_value < _min) _value = _min;
379 gchar * prefname = this->pref_name();
380 prefs_set_double_attribute(PREF_DIR, prefname, _value);
381 g_free(prefname);
383 return _value;
384 }
386 /** \brief A function to set the \c _value
387 \param in The value to set to
388 \param doc A document that should be used to set the value.
389 \param node The node where the value may be placed
391 This function sets the internal value, but it also sets the value
392 in the preferences structure. To put it in the right place, \c PREF_DIR
393 and \c pref_name() are used.
395 To copy the data into _value the old memory must be free'd first.
396 It is important to note that \c g_free handles \c NULL just fine. Then
397 the passed in value is duplicated using \c g_strdup().
398 */
399 const gchar *
400 ParamString::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
401 {
402 if (in == NULL) return NULL; /* Can't have NULL string */
404 if (_value != NULL)
405 g_free(_value);
406 _value = g_strdup(in);
408 gchar * prefname = this->pref_name();
409 prefs_set_string_attribute(PREF_DIR, prefname, _value);
410 g_free(prefname);
412 return _value;
413 }
415 /** \brief Wrapper to cast to the object and use it's function. */
416 bool
417 Parameter::get_bool (const SPDocument * doc, const Inkscape::XML::Node * node)
418 {
419 ParamBool * boolpntr;
420 boolpntr = dynamic_cast<ParamBool *>(this);
421 if (boolpntr == NULL)
422 throw Extension::param_wrong_type();
423 return boolpntr->get(doc, node);
424 }
426 /** \brief Wrapper to cast to the object and use it's function. */
427 int
428 Parameter::get_int (const SPDocument * doc, const Inkscape::XML::Node * node)
429 {
430 ParamInt * intpntr;
431 intpntr = dynamic_cast<ParamInt *>(this);
432 if (intpntr == NULL)
433 throw Extension::param_wrong_type();
434 return intpntr->get(doc, node);
435 }
437 /** \brief Wrapper to cast to the object and use it's function. */
438 float
439 Parameter::get_float (const SPDocument * doc, const Inkscape::XML::Node * node)
440 {
441 ParamFloat * floatpntr;
442 floatpntr = dynamic_cast<ParamFloat *>(this);
443 if (floatpntr == NULL)
444 throw Extension::param_wrong_type();
445 return floatpntr->get(doc, node);
446 }
448 /** \brief Wrapper to cast to the object and use it's function. */
449 const gchar *
450 Parameter::get_string (const SPDocument * doc, const Inkscape::XML::Node * node)
451 {
452 ParamString * stringpntr;
453 stringpntr = dynamic_cast<ParamString *>(this);
454 if (stringpntr == NULL)
455 throw Extension::param_wrong_type();
456 return stringpntr->get(doc, node);
457 }
459 /** \brief Wrapper to cast to the object and use it's function. */
460 bool
461 Parameter::set_bool (bool in, SPDocument * doc, Inkscape::XML::Node * node)
462 {
463 ParamBool * boolpntr;
464 boolpntr = dynamic_cast<ParamBool *>(this);
465 if (boolpntr == NULL)
466 throw Extension::param_wrong_type();
467 return boolpntr->set(in, doc, node);
468 }
470 /** \brief Wrapper to cast to the object and use it's function. */
471 int
472 Parameter::set_int (int in, SPDocument * doc, Inkscape::XML::Node * node)
473 {
474 ParamInt * intpntr;
475 intpntr = dynamic_cast<ParamInt *>(this);
476 if (intpntr == NULL)
477 throw Extension::param_wrong_type();
478 return intpntr->set(in, doc, node);
479 }
481 /** \brief Wrapper to cast to the object and use it's function. */
482 float
483 Parameter::set_float (float in, SPDocument * doc, Inkscape::XML::Node * node)
484 {
485 ParamFloat * floatpntr;
486 floatpntr = dynamic_cast<ParamFloat *>(this);
487 if (floatpntr == NULL)
488 throw Extension::param_wrong_type();
489 return floatpntr->set(in, doc, node);
490 }
492 /** \brief Wrapper to cast to the object and use it's function. */
493 const gchar *
494 Parameter::set_string (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
495 {
496 ParamString * stringpntr;
497 stringpntr = dynamic_cast<ParamString *>(this);
498 if (stringpntr == NULL)
499 throw Extension::param_wrong_type();
500 return stringpntr->set(in, doc, node);
501 }
503 /** \brief Initialize the object, to do that, copy the data. */
504 ParamString::ParamString (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
505 Parameter(name, guitext, desc, scope, ext), _value(NULL)
506 {
507 const char * defaultval = NULL;
508 if (sp_repr_children(xml) != NULL)
509 defaultval = sp_repr_children(xml)->content();
511 gchar * pref_name = this->pref_name();
512 const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
513 g_free(pref_name);
515 if (paramval != NULL)
516 defaultval = paramval;
517 if (defaultval != NULL)
518 _value = g_strdup(defaultval);
520 return;
521 }
523 /** \brief Free the allocated data. */
524 ParamString::~ParamString(void)
525 {
526 g_free(_value);
527 }
529 /** \brief Oop, now that we need a parameter, we need it's name. */
530 Parameter::Parameter (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext) :
531 extension(ext), _name(NULL), _desc(NULL), _scope(scope), _text(NULL)
532 {
533 if (name != NULL)
534 _name = g_strdup(name);
535 if (desc != NULL) {
536 _desc = g_strdup(desc);
537 // printf("Adding description: '%s' on '%s'\n", _desc, _name);
538 }
541 if (guitext != NULL)
542 _text = g_strdup(guitext);
543 else
544 _text = g_strdup(name);
546 return;
547 }
549 /** \brief Just free the allocated name. */
550 Parameter::~Parameter (void)
551 {
552 g_free(_name);
553 g_free(_text);
554 }
556 /** \brief Build the name to write the parameter from the extension's
557 ID and the name of this parameter. */
558 gchar *
559 Parameter::pref_name (void)
560 {
561 return g_strdup_printf("%s.%s", extension->get_id(), _name);
562 }
564 Inkscape::XML::Node *
565 Parameter::find_child (Inkscape::XML::Node * adult)
566 {
567 return sp_repr_lookup_child(adult, "name", _name);
568 }
570 Inkscape::XML::Node *
571 Parameter::new_child (Inkscape::XML::Node * parent)
572 {
573 Inkscape::XML::Node * retval;
574 retval = sp_repr_new("inkscape:extension-param");
575 retval->setAttribute("name", _name);
577 parent->appendChild(retval);
578 return retval;
579 }
581 Inkscape::XML::Node *
582 Parameter::document_param_node (SPDocument * doc)
583 {
584 Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc));
585 Inkscape::XML::Node * params = NULL;
587 GQuark const name_quark = g_quark_from_string("inkscape:extension-params");
589 for (Inkscape::XML::Node * child = defs->firstChild();
590 child != NULL;
591 child = child->next()) {
592 if ((GQuark)child->code() == name_quark &&
593 !strcmp(child->attribute("extension"), extension->get_id())) {
594 params = child;
595 break;
596 }
597 }
599 if (params == NULL) {
600 params = sp_repr_new("inkscape:extension-param");
601 params->setAttribute("extension", extension->get_id());
602 defs->appendChild(params);
603 }
605 return params;
606 }
608 /** \brief Basically, if there is no widget pass a NULL. */
609 Gtk::Widget *
610 Parameter::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
611 {
612 return NULL;
613 }
615 /** \brief If I'm not sure which it is, just don't return a value. */
616 Glib::ustring *
617 Parameter::string (void)
618 {
619 Glib::ustring * mystring = new Glib::ustring("");
620 return mystring;
621 }
623 /** \brief A class to make an adjustment that uses Extension params */
624 class ParamFloatAdjustment : public Gtk::Adjustment {
625 /** The parameter to adjust */
626 ParamFloat * _pref;
627 SPDocument * _doc;
628 Inkscape::XML::Node * _node;
629 public:
630 /** \brief Make the adjustment using an extension and the string
631 describing the parameter. */
632 ParamFloatAdjustment (ParamFloat * param, SPDocument * doc, Inkscape::XML::Node * node) :
633 Gtk::Adjustment(0.0, param->min(), param->max(), 0.1), _pref(param), _doc(doc), _node(node) {
634 this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
635 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed));
636 return;
637 };
639 void val_changed (void);
640 }; /* class ParamFloatAdjustment */
642 /** \brief A function to respond to the value_changed signal from the
643 adjustment.
645 This function just grabs the value from the adjustment and writes
646 it to the parameter. Very simple, but yet beautiful.
647 */
648 void
649 ParamFloatAdjustment::val_changed (void)
650 {
651 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
652 _pref->set(this->get_value(), _doc, _node);
653 return;
654 }
656 /** \brief A class to make an adjustment that uses Extension params */
657 class ParamIntAdjustment : public Gtk::Adjustment {
658 /** The parameter to adjust */
659 ParamInt * _pref;
660 SPDocument * _doc;
661 Inkscape::XML::Node * _node;
662 public:
663 /** \brief Make the adjustment using an extension and the string
664 describing the parameter. */
665 ParamIntAdjustment (ParamInt * param, SPDocument * doc, Inkscape::XML::Node * node) :
666 Gtk::Adjustment(0.0, param->min(), param->max(), 1.0), _pref(param), _doc(doc), _node(node) {
667 this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
668 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed));
669 return;
670 };
672 void val_changed (void);
673 }; /* class ParamIntAdjustment */
675 /** \brief A function to respond to the value_changed signal from the
676 adjustment.
678 This function just grabs the value from the adjustment and writes
679 it to the parameter. Very simple, but yet beautiful.
680 */
681 void
682 ParamIntAdjustment::val_changed (void)
683 {
684 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
685 _pref->set((int)this->get_value(), _doc, _node);
686 return;
687 }
689 /**
690 \brief Creates a Float Adjustment for a float parameter
692 Builds a hbox with a label and a float adjustment in it.
693 */
694 Gtk::Widget *
695 ParamFloat::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
696 {
697 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
699 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
700 label->show();
701 hbox->pack_start(*label, true, true);
703 ParamFloatAdjustment * fadjust = Gtk::manage(new ParamFloatAdjustment(this, doc, node));
704 Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 0.1, 1));
705 spin->show();
706 hbox->pack_start(*spin, false, false);
708 hbox->show();
710 return dynamic_cast<Gtk::Widget *>(hbox);
711 }
713 /**
714 \brief Creates a Int Adjustment for a int parameter
716 Builds a hbox with a label and a int adjustment in it.
717 */
718 Gtk::Widget *
719 ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
720 {
721 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
723 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
724 label->show();
725 hbox->pack_start(*label, true, true);
727 ParamIntAdjustment * fadjust = Gtk::manage(new ParamIntAdjustment(this, doc, node));
728 Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 1.0, 0));
729 spin->show();
730 hbox->pack_start(*spin, false, false);
732 hbox->show();
734 return dynamic_cast<Gtk::Widget *>(hbox);
735 }
737 /** \brief A check button which is Param aware. It works with the
738 parameter to change it's value as the check button changes
739 value. */
740 class ParamBoolCheckButton : public Gtk::CheckButton {
741 private:
742 /** \brief Param to change */
743 ParamBool * _pref;
744 SPDocument * _doc;
745 Inkscape::XML::Node * _node;
746 public:
747 /** \brief Initialize the check button
748 \param param Which parameter to adjust on changing the check button
750 This function sets the value of the checkbox to be that of the
751 parameter, and then sets up a callback to \c on_toggle.
752 */
753 ParamBoolCheckButton (ParamBool * param, SPDocument * doc, Inkscape::XML::Node * node) :
754 Gtk::CheckButton(), _pref(param), _doc(doc), _node(node) {
755 this->set_active(_pref->get(NULL, NULL) /**\todo fix */);
756 this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle));
757 return;
758 }
759 void on_toggle (void);
760 };
762 /**
763 \brief A function to respond to the check box changing
765 Adjusts the value of the preference to match that in the check box.
766 */
767 void
768 ParamBoolCheckButton::on_toggle (void)
769 {
770 _pref->set(this->get_active(), NULL /**\todo fix this */, NULL);
771 return;
772 }
774 /**
775 \brief Creates a bool check button for a bool parameter
777 Builds a hbox with a label and a check button in it.
778 */
779 Gtk::Widget *
780 ParamBool::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
781 {
782 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
784 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
785 label->show();
786 hbox->pack_start(*label, true, true);
788 ParamBoolCheckButton * checkbox = new ParamBoolCheckButton(this, doc, node);
789 checkbox->show();
790 hbox->pack_start(*checkbox, false, false);
792 hbox->show();
794 return dynamic_cast<Gtk::Widget *>(hbox);
795 }
797 /** \brief A special category of Gtk::Entry to handle string parameteres */
798 class ParamStringEntry : public Gtk::Entry {
799 private:
800 ParamString * _pref;
801 SPDocument * _doc;
802 Inkscape::XML::Node * _node;
803 public:
804 /** \brief Build a string preference for the given parameter
805 \param pref Where to get the string from, and where to put it
806 when it changes.
807 */
808 ParamStringEntry (ParamString * pref, SPDocument * doc, Inkscape::XML::Node * node) :
809 Gtk::Entry(), _pref(pref), _doc(doc), _node(node) {
810 if (_pref->get(NULL, NULL) != NULL)
811 this->set_text(Glib::ustring(_pref->get(NULL, NULL)));
812 this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text));
813 };
814 void changed_text (void);
815 };
817 /** \brief Respond to the text box changing
819 This function responds to the box changing by grabbing the value
820 from the text box and putting it in the parameter.
821 */
822 void
823 ParamStringEntry::changed_text (void)
824 {
825 Glib::ustring data = this->get_text();
826 _pref->set(data.c_str(), _doc, _node);
827 return;
828 }
830 /**
831 \brief Creates a text box for the string parameter
833 Builds a hbox with a label and a text box in it.
834 */
835 Gtk::Widget *
836 ParamString::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
837 {
838 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
840 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
841 label->show();
842 hbox->pack_start(*label, true, true);
844 ParamStringEntry * textbox = new ParamStringEntry(this, doc, node);
845 textbox->show();
846 hbox->pack_start(*textbox, false, false);
848 hbox->show();
850 return dynamic_cast<Gtk::Widget *>(hbox);
851 }
853 /** \brief Return 'true' or 'false' */
854 Glib::ustring *
855 ParamBool::string (void)
856 {
857 Glib::ustring * mystring;
859 if (_value)
860 mystring = new Glib::ustring("true");
861 else
862 mystring = new Glib::ustring("false");
864 return mystring;
865 }
867 /** \brief Return the value as a string */
868 Glib::ustring *
869 ParamInt::string (void)
870 {
871 char startstring[32];
872 sprintf(startstring, "%d", _value);
873 Glib::ustring * mystring = new Glib::ustring(startstring);
874 return mystring;
875 }
877 /** \brief Return the value as a string */
878 Glib::ustring *
879 ParamFloat::string (void)
880 {
881 char startstring[G_ASCII_DTOSTR_BUF_SIZE];
882 g_ascii_dtostr(startstring, G_ASCII_DTOSTR_BUF_SIZE, _value);
883 Glib::ustring * mystring = new Glib::ustring(startstring);
884 return mystring;
885 }
887 /** \brief Return the value as a string */
888 Glib::ustring *
889 ParamString::string (void)
890 {
891 Glib::ustring * mystring = new Glib::ustring("");
892 *mystring += "\"";
893 *mystring += _value;
894 *mystring += "\"";
895 return mystring;
896 }
898 /** \brief Create a label for the description */
899 Gtk::Widget *
900 ParamDescription::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
901 {
902 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_value)));
903 label->set_line_wrap();
904 label->show();
906 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
907 hbox->pack_start(*label, true, true, 5);
908 hbox->show();
910 return hbox;
911 }
913 /** \brief Initialize the object, to do that, copy the data. */
914 ParamDescription::ParamDescription (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
915 Parameter(name, guitext, desc, scope, ext), _value(NULL)
916 {
917 // printf("Building Description\n");
918 const char * defaultval = NULL;
919 if (sp_repr_children(xml) != NULL)
920 defaultval = sp_repr_children(xml)->content();
922 if (defaultval != NULL)
923 _value = g_strdup(defaultval);
925 return;
926 }
928 ParamEnum::ParamEnum (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
929 Parameter(name, guitext, desc, scope, ext), _current_choice(NULL)
930 {
931 return;
932 }
934 ParamEnum::~ParamEnum (void)
935 {
937 }
939 /** \brief Return the value as a string */
940 Glib::ustring *
941 ParamEnum::string (void)
942 {
943 Glib::ustring * mystring = new Glib::ustring("");
944 *mystring += "\"";
945 *mystring += this->get(NULL, NULL);
946 *mystring += "\"";
947 return mystring;
948 }
950 Gtk::Widget *
951 ParamEnum::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
952 {
953 return NULL;
954 }
956 const gchar *
957 ParamEnum::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
958 {
959 return NULL;
960 }
963 } /* namespace Extension */
964 } /* namespace Inkscape */
966 /*
967 Local Variables:
968 mode:c++
969 c-file-style:"stroustrup"
970 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
971 indent-tabs-mode:nil
972 fill-column:99
973 End:
974 */
975 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :