eda540a9d56d789cf72b115cea19b014a5db1fa7
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 boolean parameter */
42 class ParamBool : public Parameter {
43 private:
44 /** \brief Internal value. */
45 bool _value;
46 public:
47 ParamBool(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
48 /** \brief Returns \c _value */
49 bool get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
50 bool set (bool in, SPDocument * doc, Inkscape::XML::Node * node);
51 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
52 Glib::ustring * string (void);
53 };
55 /** \brief Use the superclass' allocator and set the \c _value */
56 ParamBool::ParamBool (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
57 Parameter(name, guitext, desc, scope, ext), _value(false)
58 {
59 const char * defaultval = NULL;
60 if (sp_repr_children(xml) != NULL)
61 defaultval = sp_repr_children(xml)->content();
63 if (defaultval != NULL && (!strcmp(defaultval, "TRUE") || !strcmp(defaultval, "true") || !strcmp(defaultval, "1"))) {
64 _value = true;
65 } else {
66 _value = false;
67 }
69 gchar * pref_name = this->pref_name();
70 _value = (bool)prefs_get_int_attribute(PREF_DIR, pref_name, _value);
71 g_free(pref_name);
73 return;
74 }
76 class ParamInt : public Parameter {
77 private:
78 /** \brief Internal value. */
79 int _value;
80 int _min;
81 int _max;
82 public:
83 ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
84 /** \brief Returns \c _value */
85 int get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
86 int set (int in, SPDocument * doc, Inkscape::XML::Node * node);
87 int max (void) { return _max; }
88 int min (void) { return _min; }
89 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
90 Glib::ustring * string (void);
91 };
93 /** \brief Use the superclass' allocator and set the \c _value */
94 ParamInt::ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
95 Parameter(name, guitext, desc, scope, ext), _value(0), _min(0), _max(10)
96 {
97 const char * defaultval = NULL;
98 if (sp_repr_children(xml) != NULL)
99 defaultval = sp_repr_children(xml)->content();
100 if (defaultval != NULL) {
101 _value = atoi(defaultval);
102 }
104 const char * maxval = xml->attribute("max");
105 if (maxval != NULL)
106 _max = atoi(maxval);
108 const char * minval = xml->attribute("min");
109 if (minval != NULL)
110 _min = atoi(minval);
112 /* We're handling this by just killing both values */
113 if (_max < _min) {
114 _max = 10;
115 _min = 0;
116 }
118 gchar * pref_name = this->pref_name();
119 _value = prefs_get_int_attribute(PREF_DIR, pref_name, _value);
120 g_free(pref_name);
122 // std::cout << "New Int:: value: " << _value << " max: " << _max << " min: " << _min << std::endl;
124 if (_value > _max) _value = _max;
125 if (_value < _min) _value = _min;
127 return;
128 }
130 class ParamFloat : public Parameter {
131 private:
132 /** \brief Internal value. */
133 float _value;
134 float _min;
135 float _max;
136 public:
137 ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
138 /** \brief Returns \c _value */
139 float get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
140 float set (float in, SPDocument * doc, Inkscape::XML::Node * node);
141 float max (void) { return _max; }
142 float min (void) { return _min; }
143 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
144 Glib::ustring * string (void);
145 };
147 /** \brief Use the superclass' allocator and set the \c _value */
148 ParamFloat::ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
149 Parameter(name, guitext, desc, scope, ext), _value(0.0), _min(0.0), _max(10.0)
150 {
151 const char * defaultval = NULL;
152 if (sp_repr_children(xml) != NULL)
153 defaultval = sp_repr_children(xml)->content();
154 if (defaultval != NULL) {
155 _value = atof(defaultval);
156 }
158 const char * maxval = xml->attribute("max");
159 if (maxval != NULL)
160 _max = atof(maxval);
162 const char * minval = xml->attribute("min");
163 if (minval != NULL)
164 _min = atof(minval);
166 /* We're handling this by just killing both values */
167 if (_max < _min) {
168 _max = 10.0;
169 _min = 0.0;
170 }
172 gchar * pref_name = this->pref_name();
173 _value = prefs_get_double_attribute(PREF_DIR, pref_name, _value);
174 g_free(pref_name);
176 // std::cout << "New Float:: value: " << _value << " max: " << _max << " min: " << _min << std::endl;
178 if (_value > _max) _value = _max;
179 if (_value < _min) _value = _min;
181 return;
182 }
184 class ParamString : public Parameter {
185 private:
186 /** \brief Internal value. This should point to a string that has
187 been allocated in memory. And should be free'd. */
188 gchar * _value;
189 public:
190 ParamString(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
191 ~ParamString(void);
192 /** \brief Returns \c _value, with a \i const to protect it. */
193 const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
194 const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
195 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
196 Glib::ustring * string (void);
197 };
199 /**
200 \return None
201 \brief This function creates a parameter that can be used later. This
202 is typically done in the creation of the extension and defined
203 in the XML file describing the extension (it's private so people
204 have to use the system) :)
205 \param in_repr The XML describing the parameter
207 This function first grabs all of the data out of the Repr and puts
208 it into local variables. Actually, these are just pointers, and the
209 data is not duplicated so we need to be careful with it. If there
210 isn't a name or a type in the XML, then no parameter is created as
211 the function just returns.
213 From this point on, we're pretty committed as we've allocated an
214 object and we're starting to fill it. The name is set first, and
215 is created with a strdup to actually allocate memory for it. Then
216 there is a case statement (roughly because strcmp requires 'ifs')
217 based on what type of parameter this is. Depending which type it
218 is, the value is interpreted differently, but they are relatively
219 straight forward. In all cases the value is set to the default
220 value from the XML and the type is set to the interpreted type.
221 */
222 Parameter *
223 Parameter::make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
224 {
225 const char * name;
226 const char * type;
227 const char * guitext;
228 const char * desc;
229 const char * scope_str;
230 Parameter::_scope_t scope = Parameter::SCOPE_USER;
232 name = in_repr->attribute("name");
233 type = in_repr->attribute("type");
234 guitext = in_repr->attribute("gui-text");
235 if (guitext == NULL)
236 guitext = in_repr->attribute("_gui-text");
237 desc = in_repr->attribute("gui-description");
238 if (desc == NULL)
239 desc = in_repr->attribute("_gui-description");
240 scope_str = in_repr->attribute("scope");
242 /* In this case we just don't have enough information */
243 if (name == NULL || type == NULL) {
244 return NULL;
245 }
247 if (scope_str != NULL) {
248 if (!strcmp(scope_str, "user")) {
249 scope = Parameter::SCOPE_USER;
250 } else if (!strcmp(scope_str, "document")) {
251 scope = Parameter::SCOPE_DOCUMENT;
252 } else if (!strcmp(scope_str, "node")) {
253 scope = Parameter::SCOPE_NODE;
254 }
255 }
257 Parameter * param = NULL;
258 if (!strcmp(type, "boolean")) {
259 param = new ParamBool(name, guitext, desc, scope, in_ext, in_repr);
260 } else if (!strcmp(type, "int")) {
261 param = new ParamInt(name, guitext, desc, scope, in_ext, in_repr);
262 } else if (!strcmp(type, "float")) {
263 param = new ParamFloat(name, guitext, desc, scope, in_ext, in_repr);
264 } else if (!strcmp(type, "string")) {
265 param = new ParamString(name, guitext, desc, scope, in_ext, in_repr);
266 }
268 /* Note: param could equal NULL */
269 return param;
270 }
272 /** \brief A function to set the \c _value
273 \param in The value to set to
274 \param doc A document that should be used to set the value.
275 \param node The node where the value may be placed
277 This function sets the internal value, but it also sets the value
278 in the preferences structure. To put it in the right place, \c PREF_DIR
279 and \c pref_name() are used.
280 */
281 bool
282 ParamBool::set (bool in, SPDocument * doc, Inkscape::XML::Node * node)
283 {
284 _value = in;
286 gchar * prefname = this->pref_name();
287 prefs_set_int_attribute(PREF_DIR, prefname, _value == true ? 1 : 0);
288 g_free(prefname);
290 return _value;
291 }
293 /** \brief A function to set the \c _value
294 \param in The value to set to
295 \param doc A document that should be used to set the value.
296 \param node The node where the value may be placed
298 This function sets the internal value, but it also sets the value
299 in the preferences structure. To put it in the right place, \c PREF_DIR
300 and \c pref_name() are used.
301 */
302 int
303 ParamInt::set (int in, SPDocument * doc, Inkscape::XML::Node * node)
304 {
305 _value = in;
306 if (_value > _max) _value = _max;
307 if (_value < _min) _value = _min;
309 gchar * prefname = this->pref_name();
310 prefs_set_int_attribute(PREF_DIR, prefname, _value);
311 g_free(prefname);
313 return _value;
314 }
316 /** \brief A function to set the \c _value
317 \param in The value to set to
318 \param doc A document that should be used to set the value.
319 \param node The node where the value may be placed
321 This function sets the internal value, but it also sets the value
322 in the preferences structure. To put it in the right place, \c PREF_DIR
323 and \c pref_name() are used.
324 */
325 float
326 ParamFloat::set (float in, SPDocument * doc, Inkscape::XML::Node * node)
327 {
328 _value = in;
329 if (_value > _max) _value = _max;
330 if (_value < _min) _value = _min;
332 gchar * prefname = this->pref_name();
333 prefs_set_double_attribute(PREF_DIR, prefname, _value);
334 g_free(prefname);
336 return _value;
337 }
339 /** \brief A function to set the \c _value
340 \param in The value to set to
341 \param doc A document that should be used to set the value.
342 \param node The node where the value may be placed
344 This function sets the internal value, but it also sets the value
345 in the preferences structure. To put it in the right place, \c PREF_DIR
346 and \c pref_name() are used.
348 To copy the data into _value the old memory must be free'd first.
349 It is important to note that \c g_free handles \c NULL just fine. Then
350 the passed in value is duplicated using \c g_strdup().
351 */
352 const gchar *
353 ParamString::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
354 {
355 if (in == NULL) return NULL; /* Can't have NULL string */
357 if (_value != NULL)
358 g_free(_value);
359 _value = g_strdup(in);
361 gchar * prefname = this->pref_name();
362 prefs_set_string_attribute(PREF_DIR, prefname, _value);
363 g_free(prefname);
365 return _value;
366 }
368 /** \brief Wrapper to cast to the object and use it's function. */
369 bool
370 Parameter::get_bool (const SPDocument * doc, const Inkscape::XML::Node * node)
371 {
372 ParamBool * boolpntr;
373 boolpntr = dynamic_cast<ParamBool *>(this);
374 if (boolpntr == NULL)
375 throw Extension::param_wrong_type();
376 return boolpntr->get(doc, node);
377 }
379 /** \brief Wrapper to cast to the object and use it's function. */
380 int
381 Parameter::get_int (const SPDocument * doc, const Inkscape::XML::Node * node)
382 {
383 ParamInt * intpntr;
384 intpntr = dynamic_cast<ParamInt *>(this);
385 if (intpntr == NULL)
386 throw Extension::param_wrong_type();
387 return intpntr->get(doc, node);
388 }
390 /** \brief Wrapper to cast to the object and use it's function. */
391 float
392 Parameter::get_float (const SPDocument * doc, const Inkscape::XML::Node * node)
393 {
394 ParamFloat * floatpntr;
395 floatpntr = dynamic_cast<ParamFloat *>(this);
396 if (floatpntr == NULL)
397 throw Extension::param_wrong_type();
398 return floatpntr->get(doc, node);
399 }
401 /** \brief Wrapper to cast to the object and use it's function. */
402 const gchar *
403 Parameter::get_string (const SPDocument * doc, const Inkscape::XML::Node * node)
404 {
405 ParamString * stringpntr;
406 stringpntr = dynamic_cast<ParamString *>(this);
407 if (stringpntr == NULL)
408 throw Extension::param_wrong_type();
409 return stringpntr->get(doc, node);
410 }
412 /** \brief Wrapper to cast to the object and use it's function. */
413 bool
414 Parameter::set_bool (bool in, SPDocument * doc, Inkscape::XML::Node * node)
415 {
416 ParamBool * boolpntr;
417 boolpntr = dynamic_cast<ParamBool *>(this);
418 if (boolpntr == NULL)
419 throw Extension::param_wrong_type();
420 return boolpntr->set(in, doc, node);
421 }
423 /** \brief Wrapper to cast to the object and use it's function. */
424 int
425 Parameter::set_int (int in, SPDocument * doc, Inkscape::XML::Node * node)
426 {
427 ParamInt * intpntr;
428 intpntr = dynamic_cast<ParamInt *>(this);
429 if (intpntr == NULL)
430 throw Extension::param_wrong_type();
431 return intpntr->set(in, doc, node);
432 }
434 /** \brief Wrapper to cast to the object and use it's function. */
435 float
436 Parameter::set_float (float in, SPDocument * doc, Inkscape::XML::Node * node)
437 {
438 ParamFloat * floatpntr;
439 floatpntr = dynamic_cast<ParamFloat *>(this);
440 if (floatpntr == NULL)
441 throw Extension::param_wrong_type();
442 return floatpntr->set(in, doc, node);
443 }
445 /** \brief Wrapper to cast to the object and use it's function. */
446 const gchar *
447 Parameter::set_string (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
448 {
449 ParamString * stringpntr;
450 stringpntr = dynamic_cast<ParamString *>(this);
451 if (stringpntr == NULL)
452 throw Extension::param_wrong_type();
453 return stringpntr->set(in, doc, node);
454 }
456 /** \brief Initialize the object, to do that, copy the data. */
457 ParamString::ParamString (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
458 Parameter(name, guitext, desc, scope, ext), _value(NULL)
459 {
460 const char * defaultval = NULL;
461 if (sp_repr_children(xml) != NULL)
462 defaultval = sp_repr_children(xml)->content();
464 gchar * pref_name = this->pref_name();
465 const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
466 g_free(pref_name);
468 if (paramval != NULL)
469 defaultval = paramval;
470 if (defaultval != NULL)
471 _value = g_strdup(defaultval);
473 return;
474 }
476 /** \brief Free the allocated data. */
477 ParamString::~ParamString(void)
478 {
479 g_free(_value);
480 }
482 /** \brief Oop, now that we need a parameter, we need it's name. */
483 Parameter::Parameter (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext) :
484 extension(ext), _name(NULL), _desc(NULL), _scope(scope), _text(NULL)
485 {
486 if (name != NULL)
487 _name = g_strdup(name);
488 if (desc != NULL) {
489 _desc = g_strdup(desc);
490 // printf("Adding description: '%s' on '%s'\n", _desc, _name);
491 }
494 if (guitext != NULL)
495 _text = g_strdup(guitext);
496 else
497 _text = g_strdup(name);
499 return;
500 }
502 /** \brief Just free the allocated name. */
503 Parameter::~Parameter (void)
504 {
505 g_free(_name);
506 g_free(_text);
507 }
509 /** \brief Build the name to write the parameter from the extension's
510 ID and the name of this parameter. */
511 gchar *
512 Parameter::pref_name (void)
513 {
514 return g_strdup_printf("%s.%s", extension->get_id(), _name);
515 }
517 Inkscape::XML::Node *
518 Parameter::find_child (Inkscape::XML::Node * adult)
519 {
520 return sp_repr_lookup_child(adult, "name", _name);
521 }
523 Inkscape::XML::Node *
524 Parameter::new_child (Inkscape::XML::Node * parent)
525 {
526 Inkscape::XML::Node * retval;
527 retval = sp_repr_new("inkscape:extension-param");
528 retval->setAttribute("name", _name);
530 parent->appendChild(retval);
531 return retval;
532 }
534 Inkscape::XML::Node *
535 Parameter::document_param_node (SPDocument * doc)
536 {
537 Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc));
538 Inkscape::XML::Node * params = NULL;
540 GQuark const name_quark = g_quark_from_string("inkscape:extension-params");
542 for (Inkscape::XML::Node * child = defs->firstChild();
543 child != NULL;
544 child = child->next()) {
545 if ((GQuark)child->code() == name_quark &&
546 !strcmp(child->attribute("extension"), extension->get_id())) {
547 params = child;
548 break;
549 }
550 }
552 if (params == NULL) {
553 params = sp_repr_new("inkscape:extension-param");
554 params->setAttribute("extension", extension->get_id());
555 defs->appendChild(params);
556 }
558 return params;
559 }
561 /** \brief Basically, if there is no widget pass a NULL. */
562 Gtk::Widget *
563 Parameter::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
564 {
565 return NULL;
566 }
568 /** \brief If I'm not sure which it is, just don't return a value. */
569 Glib::ustring *
570 Parameter::string (void)
571 {
572 Glib::ustring * mystring = new Glib::ustring("");
573 return mystring;
574 }
576 /** \brief A class to make an adjustment that uses Extension params */
577 class ParamFloatAdjustment : public Gtk::Adjustment {
578 /** The parameter to adjust */
579 ParamFloat * _pref;
580 SPDocument * _doc;
581 Inkscape::XML::Node * _node;
582 public:
583 /** \brief Make the adjustment using an extension and the string
584 describing the parameter. */
585 ParamFloatAdjustment (ParamFloat * param, SPDocument * doc, Inkscape::XML::Node * node) :
586 Gtk::Adjustment(0.0, param->min(), param->max(), 0.1), _pref(param), _doc(doc), _node(node) {
587 this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
588 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed));
589 return;
590 };
592 void val_changed (void);
593 }; /* class ParamFloatAdjustment */
595 /** \brief A function to respond to the value_changed signal from the
596 adjustment.
598 This function just grabs the value from the adjustment and writes
599 it to the parameter. Very simple, but yet beautiful.
600 */
601 void
602 ParamFloatAdjustment::val_changed (void)
603 {
604 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
605 _pref->set(this->get_value(), _doc, _node);
606 return;
607 }
609 /** \brief A class to make an adjustment that uses Extension params */
610 class ParamIntAdjustment : public Gtk::Adjustment {
611 /** The parameter to adjust */
612 ParamInt * _pref;
613 SPDocument * _doc;
614 Inkscape::XML::Node * _node;
615 public:
616 /** \brief Make the adjustment using an extension and the string
617 describing the parameter. */
618 ParamIntAdjustment (ParamInt * param, SPDocument * doc, Inkscape::XML::Node * node) :
619 Gtk::Adjustment(0.0, param->min(), param->max(), 1.0), _pref(param), _doc(doc), _node(node) {
620 this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
621 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed));
622 return;
623 };
625 void val_changed (void);
626 }; /* class ParamIntAdjustment */
628 /** \brief A function to respond to the value_changed signal from the
629 adjustment.
631 This function just grabs the value from the adjustment and writes
632 it to the parameter. Very simple, but yet beautiful.
633 */
634 void
635 ParamIntAdjustment::val_changed (void)
636 {
637 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
638 _pref->set((int)this->get_value(), _doc, _node);
639 return;
640 }
642 /**
643 \brief Creates a Float Adjustment for a float parameter
645 Builds a hbox with a label and a float adjustment in it.
646 */
647 Gtk::Widget *
648 ParamFloat::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
649 {
650 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
652 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
653 label->show();
654 hbox->pack_start(*label, true, true);
656 ParamFloatAdjustment * fadjust = Gtk::manage(new ParamFloatAdjustment(this, doc, node));
657 Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 0.1, 1));
658 spin->show();
659 hbox->pack_start(*spin, false, false);
661 hbox->show();
663 return dynamic_cast<Gtk::Widget *>(hbox);
664 }
666 /**
667 \brief Creates a Int Adjustment for a int parameter
669 Builds a hbox with a label and a int adjustment in it.
670 */
671 Gtk::Widget *
672 ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
673 {
674 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
676 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
677 label->show();
678 hbox->pack_start(*label, true, true);
680 ParamIntAdjustment * fadjust = Gtk::manage(new ParamIntAdjustment(this, doc, node));
681 Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 1.0, 0));
682 spin->show();
683 hbox->pack_start(*spin, false, false);
685 hbox->show();
687 return dynamic_cast<Gtk::Widget *>(hbox);
688 }
690 /** \brief A check button which is Param aware. It works with the
691 parameter to change it's value as the check button changes
692 value. */
693 class ParamBoolCheckButton : public Gtk::CheckButton {
694 private:
695 /** \brief Param to change */
696 ParamBool * _pref;
697 SPDocument * _doc;
698 Inkscape::XML::Node * _node;
699 public:
700 /** \brief Initialize the check button
701 \param param Which parameter to adjust on changing the check button
703 This function sets the value of the checkbox to be that of the
704 parameter, and then sets up a callback to \c on_toggle.
705 */
706 ParamBoolCheckButton (ParamBool * param, SPDocument * doc, Inkscape::XML::Node * node) :
707 Gtk::CheckButton(), _pref(param), _doc(doc), _node(node) {
708 this->set_active(_pref->get(NULL, NULL) /**\todo fix */);
709 this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle));
710 return;
711 }
712 void on_toggle (void);
713 };
715 /**
716 \brief A function to respond to the check box changing
718 Adjusts the value of the preference to match that in the check box.
719 */
720 void
721 ParamBoolCheckButton::on_toggle (void)
722 {
723 _pref->set(this->get_active(), NULL /**\todo fix this */, NULL);
724 return;
725 }
727 /**
728 \brief Creates a bool check button for a bool parameter
730 Builds a hbox with a label and a check button in it.
731 */
732 Gtk::Widget *
733 ParamBool::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
734 {
735 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
737 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
738 label->show();
739 hbox->pack_start(*label, true, true);
741 ParamBoolCheckButton * checkbox = new ParamBoolCheckButton(this, doc, node);
742 checkbox->show();
743 hbox->pack_start(*checkbox, false, false);
745 hbox->show();
747 return dynamic_cast<Gtk::Widget *>(hbox);
748 }
750 /** \brief A special category of Gtk::Entry to handle string parameteres */
751 class ParamStringEntry : public Gtk::Entry {
752 private:
753 ParamString * _pref;
754 SPDocument * _doc;
755 Inkscape::XML::Node * _node;
756 public:
757 /** \brief Build a string preference for the given parameter
758 \param pref Where to get the string from, and where to put it
759 when it changes.
760 */
761 ParamStringEntry (ParamString * pref, SPDocument * doc, Inkscape::XML::Node * node) :
762 Gtk::Entry(), _pref(pref), _doc(doc), _node(node) {
763 if (_pref->get(NULL, NULL) != NULL)
764 this->set_text(Glib::ustring(_pref->get(NULL, NULL)));
765 this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text));
766 };
767 void changed_text (void);
768 };
770 /** \brief Respond to the text box changing
772 This function responds to the box changing by grabbing the value
773 from the text box and putting it in the parameter.
774 */
775 void
776 ParamStringEntry::changed_text (void)
777 {
778 Glib::ustring data = this->get_text();
779 _pref->set(data.c_str(), _doc, _node);
780 return;
781 }
783 /**
784 \brief Creates a text box for the string parameter
786 Builds a hbox with a label and a text box in it.
787 */
788 Gtk::Widget *
789 ParamString::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
790 {
791 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
793 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
794 label->show();
795 hbox->pack_start(*label, true, true);
797 ParamStringEntry * textbox = new ParamStringEntry(this, doc, node);
798 textbox->show();
799 hbox->pack_start(*textbox, false, false);
801 hbox->show();
803 return dynamic_cast<Gtk::Widget *>(hbox);
804 }
806 /** \brief Return 'true' or 'false' */
807 Glib::ustring *
808 ParamBool::string (void)
809 {
810 Glib::ustring * mystring;
812 if (_value)
813 mystring = new Glib::ustring("true");
814 else
815 mystring = new Glib::ustring("false");
817 return mystring;
818 }
820 /** \brief Return the value as a string */
821 Glib::ustring *
822 ParamInt::string (void)
823 {
824 char startstring[32];
825 sprintf(startstring, "%d", _value);
826 Glib::ustring * mystring = new Glib::ustring(startstring);
827 return mystring;
828 }
830 /** \brief Return the value as a string */
831 Glib::ustring *
832 ParamFloat::string (void)
833 {
834 char startstring[G_ASCII_DTOSTR_BUF_SIZE];
835 g_ascii_dtostr(startstring, G_ASCII_DTOSTR_BUF_SIZE, _value);
836 Glib::ustring * mystring = new Glib::ustring(startstring);
837 return mystring;
838 }
840 /** \brief Return the value as a string */
841 Glib::ustring *
842 ParamString::string (void)
843 {
844 Glib::ustring * mystring = new Glib::ustring("");
845 *mystring += "\"";
846 *mystring += _value;
847 *mystring += "\"";
848 return mystring;
849 }
852 } /* namespace Extension */
853 } /* namespace Inkscape */
855 /*
856 Local Variables:
857 mode:c++
858 c-file-style:"stroustrup"
859 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
860 indent-tabs-mode:nil
861 fill-column:99
862 End:
863 */
864 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :