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 "extension.h"
26 #include "prefs-utils.h"
27 #include "document-private.h"
28 #include "sp-object.h"
30 #include "parameter.h"
32 /** \brief The root directory in the preferences database for extension
33 related parameters. */
34 #define PREF_DIR "extensions"
36 namespace Inkscape {
37 namespace Extension {
39 /** \brief A boolean parameter */
40 class ParamBool : public Parameter {
41 private:
42 /** \brief Internal value. */
43 bool _value;
44 public:
45 ParamBool(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
46 /** \brief Returns \c _value */
47 bool get (const Inkscape::XML::Document * doc, const Inkscape::XML::Node * node) { return _value; }
48 bool set (bool in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node);
49 Gtk::Widget * get_widget(void);
50 Glib::ustring * string (void);
51 };
53 /** \brief Use the superclass' allocator and set the \c _value */
54 ParamBool::ParamBool (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
55 Parameter(name, guitext, desc, scope, ext), _value(false)
56 {
57 const char * defaultval = NULL;
58 if (sp_repr_children(xml) != NULL)
59 defaultval = sp_repr_children(xml)->content();
61 if (defaultval != NULL && (!strcmp(defaultval, "TRUE") || !strcmp(defaultval, "true") || !strcmp(defaultval, "1"))) {
62 _value = true;
63 } else {
64 _value = false;
65 }
67 gchar * pref_name = this->pref_name();
68 _value = (bool)prefs_get_int_attribute(PREF_DIR, pref_name, _value);
69 g_free(pref_name);
71 return;
72 }
74 class ParamInt : public Parameter {
75 private:
76 /** \brief Internal value. */
77 int _value;
78 int _min;
79 int _max;
80 public:
81 ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
82 /** \brief Returns \c _value */
83 int get (const Inkscape::XML::Document * doc, const Inkscape::XML::Node * node) { return _value; }
84 int set (int in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node);
85 int max (void) { return _max; }
86 int min (void) { return _min; }
87 Gtk::Widget * get_widget(void);
88 Glib::ustring * string (void);
89 };
91 /** \brief Use the superclass' allocator and set the \c _value */
92 ParamInt::ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
93 Parameter(name, guitext, desc, scope, ext), _value(0), _min(0), _max(10)
94 {
95 const char * defaultval = NULL;
96 if (sp_repr_children(xml) != NULL)
97 defaultval = sp_repr_children(xml)->content();
98 if (defaultval != NULL) {
99 _value = atoi(defaultval);
100 }
102 const char * maxval = xml->attribute("max");
103 if (maxval != NULL)
104 _max = atoi(maxval);
106 const char * minval = xml->attribute("min");
107 if (minval != NULL)
108 _min = atoi(minval);
110 /* We're handling this by just killing both values */
111 if (_max < _min) {
112 _max = 10;
113 _min = 0;
114 }
116 gchar * pref_name = this->pref_name();
117 _value = prefs_get_int_attribute(PREF_DIR, pref_name, _value);
118 g_free(pref_name);
120 // std::cout << "New Int:: value: " << _value << " max: " << _max << " min: " << _min << std::endl;
122 if (_value > _max) _value = _max;
123 if (_value < _min) _value = _min;
125 return;
126 }
128 class ParamFloat : public Parameter {
129 private:
130 /** \brief Internal value. */
131 float _value;
132 float _min;
133 float _max;
134 public:
135 ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
136 /** \brief Returns \c _value */
137 float get (const Inkscape::XML::Document * doc, const Inkscape::XML::Node * node) { return _value; }
138 float set (float in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node);
139 float max (void) { return _max; }
140 float min (void) { return _min; }
141 Gtk::Widget * get_widget(void);
142 Glib::ustring * string (void);
143 };
145 /** \brief Use the superclass' allocator and set the \c _value */
146 ParamFloat::ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
147 Parameter(name, guitext, desc, scope, ext), _value(0.0), _min(0.0), _max(10.0)
148 {
149 const char * defaultval = NULL;
150 if (sp_repr_children(xml) != NULL)
151 defaultval = sp_repr_children(xml)->content();
152 if (defaultval != NULL) {
153 _value = atof(defaultval);
154 }
156 const char * maxval = xml->attribute("max");
157 if (maxval != NULL)
158 _max = atof(maxval);
160 const char * minval = xml->attribute("min");
161 if (minval != NULL)
162 _min = atof(minval);
164 /* We're handling this by just killing both values */
165 if (_max < _min) {
166 _max = 10.0;
167 _min = 0.0;
168 }
170 gchar * pref_name = this->pref_name();
171 _value = prefs_get_double_attribute(PREF_DIR, pref_name, _value);
172 g_free(pref_name);
174 // std::cout << "New Float:: value: " << _value << " max: " << _max << " min: " << _min << std::endl;
176 if (_value > _max) _value = _max;
177 if (_value < _min) _value = _min;
179 return;
180 }
182 class ParamString : public Parameter {
183 private:
184 /** \brief Internal value. This should point to a string that has
185 been allocated in memory. And should be free'd. */
186 gchar * _value;
187 public:
188 ParamString(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
189 ~ParamString(void);
190 /** \brief Returns \c _value, with a \i const to protect it. */
191 const gchar * get (const Inkscape::XML::Document * doc, const Inkscape::XML::Node * node) { return _value; }
192 const gchar * set (const gchar * in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node);
193 Gtk::Widget * get_widget(void);
194 Glib::ustring * string (void);
195 };
197 /**
198 \return None
199 \brief This function creates a parameter that can be used later. This
200 is typically done in the creation of the extension and defined
201 in the XML file describing the extension (it's private so people
202 have to use the system) :)
203 \param in_repr The XML describing the parameter
205 This function first grabs all of the data out of the Repr and puts
206 it into local variables. Actually, these are just pointers, and the
207 data is not duplicated so we need to be careful with it. If there
208 isn't a name or a type in the XML, then no parameter is created as
209 the function just returns.
211 From this point on, we're pretty committed as we've allocated an
212 object and we're starting to fill it. The name is set first, and
213 is created with a strdup to actually allocate memory for it. Then
214 there is a case statement (roughly because strcmp requires 'ifs')
215 based on what type of parameter this is. Depending which type it
216 is, the value is interpreted differently, but they are relatively
217 straight forward. In all cases the value is set to the default
218 value from the XML and the type is set to the interpreted type.
219 */
220 Parameter *
221 Parameter::make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
222 {
223 const char * name;
224 const char * type;
225 const char * guitext;
226 const char * desc;
227 const char * scope_str;
228 Parameter::_scope_t scope = Parameter::SCOPE_USER;
230 name = in_repr->attribute("name");
231 type = in_repr->attribute("type");
232 guitext = in_repr->attribute("gui-text");
233 if (guitext == NULL)
234 guitext = in_repr->attribute("_gui-text");
235 desc = in_repr->attribute("gui-description");
236 if (desc == NULL)
237 desc = in_repr->attribute("_gui-description");
238 scope_str = in_repr->attribute("scope");
240 /* In this case we just don't have enough information */
241 if (name == NULL || type == NULL) {
242 return NULL;
243 }
245 if (scope_str != NULL) {
246 if (!strcmp(scope_str, "user")) {
247 scope = Parameter::SCOPE_USER;
248 } else if (!strcmp(scope_str, "document")) {
249 scope = Parameter::SCOPE_DOCUMENT;
250 } else if (!strcmp(scope_str, "node")) {
251 scope = Parameter::SCOPE_NODE;
252 }
253 }
255 Parameter * param = NULL;
256 if (!strcmp(type, "boolean")) {
257 param = new ParamBool(name, guitext, desc, scope, in_ext, in_repr);
258 } else if (!strcmp(type, "int")) {
259 param = new ParamInt(name, guitext, desc, scope, in_ext, in_repr);
260 } else if (!strcmp(type, "float")) {
261 param = new ParamFloat(name, guitext, desc, scope, in_ext, in_repr);
262 } else if (!strcmp(type, "string")) {
263 param = new ParamString(name, guitext, desc, scope, in_ext, in_repr);
264 }
266 /* Note: param could equal NULL */
267 return param;
268 }
270 /** \brief A function to set the \c _value
271 \param in The value to set to
272 \param doc A document that should be used to set the value.
273 \param node The node where the value may be placed
275 This function sets the internal value, but it also sets the value
276 in the preferences structure. To put it in the right place, \c PREF_DIR
277 and \c pref_name() are used.
278 */
279 bool
280 ParamBool::set (bool in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node)
281 {
282 _value = in;
284 gchar * prefname = this->pref_name();
285 prefs_set_int_attribute(PREF_DIR, prefname, _value == true ? 1 : 0);
286 g_free(prefname);
288 return _value;
289 }
291 /** \brief A function to set the \c _value
292 \param in The value to set to
293 \param doc A document that should be used to set the value.
294 \param node The node where the value may be placed
296 This function sets the internal value, but it also sets the value
297 in the preferences structure. To put it in the right place, \c PREF_DIR
298 and \c pref_name() are used.
299 */
300 int
301 ParamInt::set (int in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node)
302 {
303 _value = in;
304 if (_value > _max) _value = _max;
305 if (_value < _min) _value = _min;
307 gchar * prefname = this->pref_name();
308 prefs_set_int_attribute(PREF_DIR, prefname, _value);
309 g_free(prefname);
311 return _value;
312 }
314 /** \brief A function to set the \c _value
315 \param in The value to set to
316 \param doc A document that should be used to set the value.
317 \param node The node where the value may be placed
319 This function sets the internal value, but it also sets the value
320 in the preferences structure. To put it in the right place, \c PREF_DIR
321 and \c pref_name() are used.
322 */
323 float
324 ParamFloat::set (float in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node)
325 {
326 _value = in;
327 if (_value > _max) _value = _max;
328 if (_value < _min) _value = _min;
330 gchar * prefname = this->pref_name();
331 prefs_set_double_attribute(PREF_DIR, prefname, _value);
332 g_free(prefname);
334 return _value;
335 }
337 /** \brief A function to set the \c _value
338 \param in The value to set to
339 \param doc A document that should be used to set the value.
340 \param node The node where the value may be placed
342 This function sets the internal value, but it also sets the value
343 in the preferences structure. To put it in the right place, \c PREF_DIR
344 and \c pref_name() are used.
346 To copy the data into _value the old memory must be free'd first.
347 It is important to note that \c g_free handles \c NULL just fine. Then
348 the passed in value is duplicated using \c g_strdup().
349 */
350 const gchar *
351 ParamString::set (const gchar * in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node)
352 {
353 if (in == NULL) return NULL; /* Can't have NULL string */
355 if (_value != NULL)
356 g_free(_value);
357 _value = g_strdup(in);
359 gchar * prefname = this->pref_name();
360 prefs_set_string_attribute(PREF_DIR, prefname, _value);
361 g_free(prefname);
363 return _value;
364 }
366 /** \brief Wrapper to cast to the object and use it's function. */
367 bool
368 Parameter::get_bool (const Inkscape::XML::Document * doc, const Inkscape::XML::Node * node)
369 {
370 ParamBool * boolpntr;
371 boolpntr = dynamic_cast<ParamBool *>(this);
372 if (boolpntr == NULL)
373 throw Extension::param_wrong_type();
374 return boolpntr->get(doc, node);
375 }
377 /** \brief Wrapper to cast to the object and use it's function. */
378 int
379 Parameter::get_int (const Inkscape::XML::Document * doc, const Inkscape::XML::Node * node)
380 {
381 ParamInt * intpntr;
382 intpntr = dynamic_cast<ParamInt *>(this);
383 if (intpntr == NULL)
384 throw Extension::param_wrong_type();
385 return intpntr->get(doc, node);
386 }
388 /** \brief Wrapper to cast to the object and use it's function. */
389 float
390 Parameter::get_float (const Inkscape::XML::Document * doc, const Inkscape::XML::Node * node)
391 {
392 ParamFloat * floatpntr;
393 floatpntr = dynamic_cast<ParamFloat *>(this);
394 if (floatpntr == NULL)
395 throw Extension::param_wrong_type();
396 return floatpntr->get(doc, node);
397 }
399 /** \brief Wrapper to cast to the object and use it's function. */
400 const gchar *
401 Parameter::get_string (const Inkscape::XML::Document * doc, const Inkscape::XML::Node * node)
402 {
403 ParamString * stringpntr;
404 stringpntr = dynamic_cast<ParamString *>(this);
405 if (stringpntr == NULL)
406 throw Extension::param_wrong_type();
407 return stringpntr->get(doc, node);
408 }
410 /** \brief Wrapper to cast to the object and use it's function. */
411 bool
412 Parameter::set_bool (bool in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node)
413 {
414 ParamBool * boolpntr;
415 boolpntr = dynamic_cast<ParamBool *>(this);
416 if (boolpntr == NULL)
417 throw Extension::param_wrong_type();
418 return boolpntr->set(in, doc, node);
419 }
421 /** \brief Wrapper to cast to the object and use it's function. */
422 int
423 Parameter::set_int (int in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node)
424 {
425 ParamInt * intpntr;
426 intpntr = dynamic_cast<ParamInt *>(this);
427 if (intpntr == NULL)
428 throw Extension::param_wrong_type();
429 return intpntr->set(in, doc, node);
430 }
432 /** \brief Wrapper to cast to the object and use it's function. */
433 float
434 Parameter::set_float (float in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node)
435 {
436 ParamFloat * floatpntr;
437 floatpntr = dynamic_cast<ParamFloat *>(this);
438 if (floatpntr == NULL)
439 throw Extension::param_wrong_type();
440 return floatpntr->set(in, doc, node);
441 }
443 /** \brief Wrapper to cast to the object and use it's function. */
444 const gchar *
445 Parameter::set_string (const gchar * in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node)
446 {
447 ParamString * stringpntr;
448 stringpntr = dynamic_cast<ParamString *>(this);
449 if (stringpntr == NULL)
450 throw Extension::param_wrong_type();
451 return stringpntr->set(in, doc, node);
452 }
454 /** \brief Initialize the object, to do that, copy the data. */
455 ParamString::ParamString (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
456 Parameter(name, guitext, desc, scope, ext), _value(NULL)
457 {
458 const char * defaultval = NULL;
459 if (sp_repr_children(xml) != NULL)
460 defaultval = sp_repr_children(xml)->content();
462 gchar * pref_name = this->pref_name();
463 const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
464 g_free(pref_name);
466 if (paramval != NULL)
467 defaultval = paramval;
468 if (defaultval != NULL)
469 _value = g_strdup(defaultval);
471 return;
472 }
474 /** \brief Free the allocated data. */
475 ParamString::~ParamString(void)
476 {
477 g_free(_value);
478 }
480 /** \brief Oop, now that we need a parameter, we need it's name. */
481 Parameter::Parameter (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext) :
482 extension(ext), _name(NULL), _desc(NULL), _scope(scope), _text(NULL)
483 {
484 if (name != NULL)
485 _name = g_strdup(name);
486 if (desc != NULL) {
487 _desc = g_strdup(desc);
488 // printf("Adding description: '%s' on '%s'\n", _desc, _name);
489 }
492 if (guitext != NULL)
493 _text = g_strdup(guitext);
494 else
495 _text = g_strdup(name);
497 return;
498 }
500 /** \brief Just free the allocated name. */
501 Parameter::~Parameter (void)
502 {
503 g_free(_name);
504 g_free(_text);
505 }
507 /** \brief Build the name to write the parameter from the extension's
508 ID and the name of this parameter. */
509 gchar *
510 Parameter::pref_name (void)
511 {
512 return g_strdup_printf("%s.%s", extension->get_id(), _name);
513 }
515 Inkscape::XML::Node *
516 Parameter::find_child (Inkscape::XML::Node * adult)
517 {
518 Inkscape::XML::Node * retval = NULL;
519 for (retval = adult->firstChild();
520 retval != NULL;
521 retval = retval->next()) {
522 gchar const * name = retval->attribute("name");
523 if (name == NULL) continue;
524 if (!strcmp(name, _name))
525 break;
526 }
528 return retval;
529 }
531 Inkscape::XML::Node *
532 Parameter::new_child (Inkscape::XML::Node * parent)
533 {
534 Inkscape::XML::Node * retval;
535 retval = sp_repr_new("inkscape:extension-param");
536 retval->setAttribute("extension", extension->get_id());
537 retval->setAttribute("name", _name);
539 parent->appendChild(retval);
540 return retval;
541 }
543 Inkscape::XML::Node *
544 Parameter::document_param_node (SPDocument * doc)
545 {
546 Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc));
547 Inkscape::XML::Node * params = NULL;
549 for (Inkscape::XML::Node * child = defs->firstChild();
550 child != NULL;
551 child = child->next()) {
552 if (!strcmp(child->name(), "inkscape:extension-param")) {
553 params = child;
554 break;
555 }
556 }
558 if (params == NULL) {
559 params = sp_repr_new("inkscape:extension-param");
560 defs->appendChild(params);
561 }
563 return params;
564 }
566 /** \brief Basically, if there is no widget pass a NULL. */
567 Gtk::Widget *
568 Parameter::get_widget (void)
569 {
570 return NULL;
571 }
573 /** \brief If I'm not sure which it is, just don't return a value. */
574 Glib::ustring *
575 Parameter::string (void)
576 {
577 Glib::ustring * mystring = new Glib::ustring("");
578 return mystring;
579 }
581 /** \brief A class to make an adjustment that uses Extension params */
582 class ParamFloatAdjustment : public Gtk::Adjustment {
583 /** The parameter to adjust */
584 ParamFloat * _pref;
585 public:
586 /** \brief Make the adjustment using an extension and the string
587 describing the parameter. */
588 ParamFloatAdjustment (ParamFloat * param) :
589 Gtk::Adjustment(0.0, param->min(), param->max(), 0.1), _pref(param) {
590 this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
591 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed));
592 return;
593 };
595 void val_changed (void);
596 }; /* class ParamFloatAdjustment */
598 /** \brief A function to respond to the value_changed signal from the
599 adjustment.
601 This function just grabs the value from the adjustment and writes
602 it to the parameter. Very simple, but yet beautiful.
603 */
604 void
605 ParamFloatAdjustment::val_changed (void)
606 {
607 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
608 _pref->set(this->get_value(), NULL /* \todo fix */, NULL);
609 return;
610 }
612 /** \brief A class to make an adjustment that uses Extension params */
613 class ParamIntAdjustment : public Gtk::Adjustment {
614 /** The parameter to adjust */
615 ParamInt * _pref;
616 public:
617 /** \brief Make the adjustment using an extension and the string
618 describing the parameter. */
619 ParamIntAdjustment (ParamInt * param) :
620 Gtk::Adjustment(0.0, param->min(), param->max(), 1.0), _pref(param) {
621 this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
622 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed));
623 return;
624 };
626 void val_changed (void);
627 }; /* class ParamIntAdjustment */
629 /** \brief A function to respond to the value_changed signal from the
630 adjustment.
632 This function just grabs the value from the adjustment and writes
633 it to the parameter. Very simple, but yet beautiful.
634 */
635 void
636 ParamIntAdjustment::val_changed (void)
637 {
638 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
639 _pref->set((int)this->get_value(), NULL /* \todo fix */, NULL);
640 return;
641 }
643 /**
644 \brief Creates a Float Adjustment for a float parameter
646 Builds a hbox with a label and a float adjustment in it.
647 */
648 Gtk::Widget *
649 ParamFloat::get_widget (void)
650 {
651 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
653 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
654 label->show();
655 hbox->pack_start(*label, true, true);
657 ParamFloatAdjustment * fadjust = Gtk::manage(new ParamFloatAdjustment(this));
658 Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 0.1, 1));
659 spin->show();
660 hbox->pack_start(*spin, false, false);
662 hbox->show();
664 return dynamic_cast<Gtk::Widget *>(hbox);
665 }
667 /**
668 \brief Creates a Int Adjustment for a int parameter
670 Builds a hbox with a label and a int adjustment in it.
671 */
672 Gtk::Widget *
673 ParamInt::get_widget (void)
674 {
675 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
677 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
678 label->show();
679 hbox->pack_start(*label, true, true);
681 ParamIntAdjustment * fadjust = Gtk::manage(new ParamIntAdjustment(this));
682 Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 1.0, 0));
683 spin->show();
684 hbox->pack_start(*spin, false, false);
686 hbox->show();
688 return dynamic_cast<Gtk::Widget *>(hbox);
689 }
691 /** \brief A check button which is Param aware. It works with the
692 parameter to change it's value as the check button changes
693 value. */
694 class ParamBoolCheckButton : public Gtk::CheckButton {
695 private:
696 /** \brief Param to change */
697 ParamBool * _pref;
698 public:
699 /** \brief Initialize the check button
700 \param param Which parameter to adjust on changing the check button
702 This function sets the value of the checkbox to be that of the
703 parameter, and then sets up a callback to \c on_toggle.
704 */
705 ParamBoolCheckButton (ParamBool * param) :
706 Gtk::CheckButton(), _pref(param) {
707 this->set_active(_pref->get(NULL, NULL) /**\todo fix */);
708 this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle));
709 return;
710 }
711 void on_toggle (void);
712 };
714 /**
715 \brief A function to respond to the check box changing
717 Adjusts the value of the preference to match that in the check box.
718 */
719 void
720 ParamBoolCheckButton::on_toggle (void)
721 {
722 _pref->set(this->get_active(), NULL /**\todo fix this */, NULL);
723 return;
724 }
726 /**
727 \brief Creates a bool check button for a bool parameter
729 Builds a hbox with a label and a check button in it.
730 */
731 Gtk::Widget *
732 ParamBool::get_widget (void)
733 {
734 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
736 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
737 label->show();
738 hbox->pack_start(*label, true, true);
740 ParamBoolCheckButton * checkbox = new ParamBoolCheckButton(this);
741 checkbox->show();
742 hbox->pack_start(*checkbox, false, false);
744 hbox->show();
746 return dynamic_cast<Gtk::Widget *>(hbox);
747 }
749 /** \brief A special category of Gtk::Entry to handle string parameteres */
750 class ParamStringEntry : public Gtk::Entry {
751 private:
752 ParamString * _pref;
753 public:
754 /** \brief Build a string preference for the given parameter
755 \param pref Where to get the string from, and where to put it
756 when it changes.
757 */
758 ParamStringEntry (ParamString * pref) :
759 Gtk::Entry(), _pref(pref) {
760 if (_pref->get(NULL, NULL) != NULL)
761 this->set_text(Glib::ustring(_pref->get(NULL, NULL)));
762 this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text));
763 };
764 void changed_text (void);
765 };
767 /** \brief Respond to the text box changing
769 This function responds to the box changing by grabbing the value
770 from the text box and putting it in the parameter.
771 */
772 void
773 ParamStringEntry::changed_text (void)
774 {
775 Glib::ustring data = this->get_text();
776 _pref->set(data.c_str(), NULL, NULL);
777 return;
778 }
780 /**
781 \brief Creates a text box for the string parameter
783 Builds a hbox with a label and a text box in it.
784 */
785 Gtk::Widget *
786 ParamString::get_widget (void)
787 {
788 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
790 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
791 label->show();
792 hbox->pack_start(*label, true, true);
794 ParamStringEntry * textbox = new ParamStringEntry(this);
795 textbox->show();
796 hbox->pack_start(*textbox, false, false);
798 hbox->show();
800 return dynamic_cast<Gtk::Widget *>(hbox);
801 }
803 /** \brief Return 'true' or 'false' */
804 Glib::ustring *
805 ParamBool::string (void)
806 {
807 Glib::ustring * mystring;
809 if (_value)
810 mystring = new Glib::ustring("true");
811 else
812 mystring = new Glib::ustring("false");
814 return mystring;
815 }
817 /** \brief Return the value as a string */
818 Glib::ustring *
819 ParamInt::string (void)
820 {
821 char startstring[32];
822 sprintf(startstring, "%d", _value);
823 Glib::ustring * mystring = new Glib::ustring(startstring);
824 return mystring;
825 }
827 /** \brief Return the value as a string */
828 Glib::ustring *
829 ParamFloat::string (void)
830 {
831 char startstring[G_ASCII_DTOSTR_BUF_SIZE];
832 g_ascii_dtostr(startstring, G_ASCII_DTOSTR_BUF_SIZE, _value);
833 Glib::ustring * mystring = new Glib::ustring(startstring);
834 return mystring;
835 }
837 /** \brief Return the value as a string */
838 Glib::ustring *
839 ParamString::string (void)
840 {
841 Glib::ustring * mystring = new Glib::ustring("");
842 *mystring += "\"";
843 *mystring += _value;
844 *mystring += "\"";
845 return mystring;
846 }
849 } /* namespace Extension */
850 } /* namespace Inkscape */
852 /*
853 Local Variables:
854 mode:c++
855 c-file-style:"stroustrup"
856 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
857 indent-tabs-mode:nil
858 fill-column:99
859 End:
860 */
861 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :