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)
110 {
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;
142 }
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)
164 {
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;
196 }
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)
272 {
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;
326 }
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)
339 {
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;
347 }
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)
360 {
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;
370 }
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)
383 {
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;
393 }
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)
410 {
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;
422 }
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)
427 {
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);
433 }
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)
438 {
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);
444 }
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)
449 {
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);
455 }
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)
460 {
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);
466 }
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)
471 {
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);
477 }
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)
482 {
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);
488 }
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)
493 {
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);
499 }
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)
504 {
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);
510 }
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)
515 {
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;
530 }
532 /** \brief Free the allocated data. */
533 ParamString::~ParamString(void)
534 {
535 g_free(_value);
536 }
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)
541 {
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;
556 }
558 /** \brief Just free the allocated name. */
559 Parameter::~Parameter (void)
560 {
561 g_free(_name);
562 g_free(_text);
563 }
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)
569 {
570 return g_strdup_printf("%s.%s", extension->get_id(), _name);
571 }
573 Inkscape::XML::Node *
574 Parameter::find_child (Inkscape::XML::Node * adult)
575 {
576 return sp_repr_lookup_child(adult, "name", _name);
577 }
579 Inkscape::XML::Node *
580 Parameter::new_child (Inkscape::XML::Node * parent)
581 {
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;
588 }
590 Inkscape::XML::Node *
591 Parameter::document_param_node (SPDocument * doc)
592 {
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;
615 }
617 /** \brief Basically, if there is no widget pass a NULL. */
618 Gtk::Widget *
619 Parameter::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
620 {
621 return NULL;
622 }
624 /** \brief If I'm not sure which it is, just don't return a value. */
625 Glib::ustring *
626 Parameter::string (void)
627 {
628 Glib::ustring * mystring = new Glib::ustring("");
629 return mystring;
630 }
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)
659 {
660 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
661 _pref->set(this->get_value(), _doc, _node);
662 return;
663 }
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)
692 {
693 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
694 _pref->set((int)this->get_value(), _doc, _node);
695 return;
696 }
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)
705 {
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);
720 }
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)
729 {
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);
744 }
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)
778 {
779 _pref->set(this->get_active(), NULL /**\todo fix this */, NULL);
780 return;
781 }
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)
790 {
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);
804 }
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)
833 {
834 Glib::ustring data = this->get_text();
835 _pref->set(data.c_str(), _doc, _node);
836 return;
837 }
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)
846 {
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);
860 }
862 /** \brief Return 'true' or 'false' */
863 Glib::ustring *
864 ParamBool::string (void)
865 {
866 Glib::ustring * mystring;
868 if (_value)
869 mystring = new Glib::ustring("true");
870 else
871 mystring = new Glib::ustring("false");
873 return mystring;
874 }
876 /** \brief Return the value as a string */
877 Glib::ustring *
878 ParamInt::string (void)
879 {
880 char startstring[32];
881 sprintf(startstring, "%d", _value);
882 Glib::ustring * mystring = new Glib::ustring(startstring);
883 return mystring;
884 }
886 /** \brief Return the value as a string */
887 Glib::ustring *
888 ParamFloat::string (void)
889 {
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;
894 }
896 /** \brief Return the value as a string */
897 Glib::ustring *
898 ParamString::string (void)
899 {
900 Glib::ustring * mystring = new Glib::ustring("");
901 *mystring += "\"";
902 *mystring += _value;
903 *mystring += "\"";
904 return mystring;
905 }
907 /** \brief Create a label for the description */
908 Gtk::Widget *
909 ParamDescription::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
910 {
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;
920 }
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)
925 {
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;
935 }
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)
939 {
940 return;
941 }
943 ParamEnum::~ParamEnum (void)
944 {
946 }
948 /** \brief Return the value as a string */
949 Glib::ustring *
950 ParamEnum::string (void)
951 {
952 Glib::ustring * mystring = new Glib::ustring("");
953 *mystring += "\"";
954 *mystring += this->get(NULL, NULL);
955 *mystring += "\"";
956 return mystring;
957 }
959 Gtk::Widget *
960 ParamEnum::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
961 {
962 return NULL;
963 }
965 const gchar *
966 ParamEnum::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
967 {
968 return NULL;
969 }
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 :