1 /** \file
2 * Parameters for extensions.
3 */
5 /*
6 * Authors:
7 * Ted Gould <ted@gould.cx>
8 *
9 * Copyright (C) 2005 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 /** \brief Build the name to write the parameter in a node object. This
516 requires the inkscape namespace and the other info. */
517 gchar *
518 Parameter::node_name (void)
519 {
520 return g_strdup_printf("inkscape:extension-param-%s-%s", extension->get_id(), _name);
521 }
523 Inkscape::XML::Node *
524 Parameter::document_param_node (SPDocument * doc)
525 {
526 Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc));
527 Inkscape::XML::Node * params = NULL;
529 for (Inkscape::XML::Node * child = defs->firstChild();
530 child != NULL;
531 child = child->next()) {
532 if (!strcmp(child->name(), "inkscape:extension-param")) {
533 params = child;
534 break;
535 }
536 }
538 if (params == NULL) {
539 params = sp_repr_new("inkscape:extension-param");
540 defs->appendChild(params);
541 }
543 return params;
544 }
546 /** \brief Basically, if there is no widget pass a NULL. */
547 Gtk::Widget *
548 Parameter::get_widget (void)
549 {
550 return NULL;
551 }
553 /** \brief If I'm not sure which it is, just don't return a value. */
554 Glib::ustring *
555 Parameter::string (void)
556 {
557 Glib::ustring * mystring = new Glib::ustring("");
558 return mystring;
559 }
561 /** \brief A class to make an adjustment that uses Extension params */
562 class ParamFloatAdjustment : public Gtk::Adjustment {
563 /** The parameter to adjust */
564 ParamFloat * _pref;
565 public:
566 /** \brief Make the adjustment using an extension and the string
567 describing the parameter. */
568 ParamFloatAdjustment (ParamFloat * param) :
569 Gtk::Adjustment(0.0, param->min(), param->max(), 0.1), _pref(param) {
570 this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
571 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed));
572 return;
573 };
575 void val_changed (void);
576 }; /* class ParamFloatAdjustment */
578 /** \brief A function to respond to the value_changed signal from the
579 adjustment.
581 This function just grabs the value from the adjustment and writes
582 it to the parameter. Very simple, but yet beautiful.
583 */
584 void
585 ParamFloatAdjustment::val_changed (void)
586 {
587 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
588 _pref->set(this->get_value(), NULL /* \todo fix */, NULL);
589 return;
590 }
592 /** \brief A class to make an adjustment that uses Extension params */
593 class ParamIntAdjustment : public Gtk::Adjustment {
594 /** The parameter to adjust */
595 ParamInt * _pref;
596 public:
597 /** \brief Make the adjustment using an extension and the string
598 describing the parameter. */
599 ParamIntAdjustment (ParamInt * param) :
600 Gtk::Adjustment(0.0, param->min(), param->max(), 1.0), _pref(param) {
601 this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
602 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed));
603 return;
604 };
606 void val_changed (void);
607 }; /* class ParamIntAdjustment */
609 /** \brief A function to respond to the value_changed signal from the
610 adjustment.
612 This function just grabs the value from the adjustment and writes
613 it to the parameter. Very simple, but yet beautiful.
614 */
615 void
616 ParamIntAdjustment::val_changed (void)
617 {
618 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
619 _pref->set((int)this->get_value(), NULL /* \todo fix */, NULL);
620 return;
621 }
623 /**
624 \brief Creates a Float Adjustment for a float parameter
626 Builds a hbox with a label and a float adjustment in it.
627 */
628 Gtk::Widget *
629 ParamFloat::get_widget (void)
630 {
631 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
633 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
634 label->show();
635 hbox->pack_start(*label, true, true);
637 ParamFloatAdjustment * fadjust = Gtk::manage(new ParamFloatAdjustment(this));
638 Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 0.1, 1));
639 spin->show();
640 hbox->pack_start(*spin, false, false);
642 hbox->show();
644 return dynamic_cast<Gtk::Widget *>(hbox);
645 }
647 /**
648 \brief Creates a Int Adjustment for a int parameter
650 Builds a hbox with a label and a int adjustment in it.
651 */
652 Gtk::Widget *
653 ParamInt::get_widget (void)
654 {
655 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
657 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
658 label->show();
659 hbox->pack_start(*label, true, true);
661 ParamIntAdjustment * fadjust = Gtk::manage(new ParamIntAdjustment(this));
662 Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 1.0, 0));
663 spin->show();
664 hbox->pack_start(*spin, false, false);
666 hbox->show();
668 return dynamic_cast<Gtk::Widget *>(hbox);
669 }
671 /** \brief A check button which is Param aware. It works with the
672 parameter to change it's value as the check button changes
673 value. */
674 class ParamBoolCheckButton : public Gtk::CheckButton {
675 private:
676 /** \brief Param to change */
677 ParamBool * _pref;
678 public:
679 /** \brief Initialize the check button
680 \param param Which parameter to adjust on changing the check button
682 This function sets the value of the checkbox to be that of the
683 parameter, and then sets up a callback to \c on_toggle.
684 */
685 ParamBoolCheckButton (ParamBool * param) :
686 Gtk::CheckButton(), _pref(param) {
687 this->set_active(_pref->get(NULL, NULL) /**\todo fix */);
688 this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle));
689 return;
690 }
691 void on_toggle (void);
692 };
694 /**
695 \brief A function to respond to the check box changing
697 Adjusts the value of the preference to match that in the check box.
698 */
699 void
700 ParamBoolCheckButton::on_toggle (void)
701 {
702 _pref->set(this->get_active(), NULL /**\todo fix this */, NULL);
703 return;
704 }
706 /**
707 \brief Creates a bool check button for a bool parameter
709 Builds a hbox with a label and a check button in it.
710 */
711 Gtk::Widget *
712 ParamBool::get_widget (void)
713 {
714 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
716 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
717 label->show();
718 hbox->pack_start(*label, true, true);
720 ParamBoolCheckButton * checkbox = new ParamBoolCheckButton(this);
721 checkbox->show();
722 hbox->pack_start(*checkbox, false, false);
724 hbox->show();
726 return dynamic_cast<Gtk::Widget *>(hbox);
727 }
729 /** \brief A special category of Gtk::Entry to handle string parameteres */
730 class ParamStringEntry : public Gtk::Entry {
731 private:
732 ParamString * _pref;
733 public:
734 /** \brief Build a string preference for the given parameter
735 \param pref Where to get the string from, and where to put it
736 when it changes.
737 */
738 ParamStringEntry (ParamString * pref) :
739 Gtk::Entry(), _pref(pref) {
740 if (_pref->get(NULL, NULL) != NULL)
741 this->set_text(Glib::ustring(_pref->get(NULL, NULL)));
742 this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text));
743 };
744 void changed_text (void);
745 };
747 /** \brief Respond to the text box changing
749 This function responds to the box changing by grabbing the value
750 from the text box and putting it in the parameter.
751 */
752 void
753 ParamStringEntry::changed_text (void)
754 {
755 Glib::ustring data = this->get_text();
756 _pref->set(data.c_str(), NULL, NULL);
757 return;
758 }
760 /**
761 \brief Creates a text box for the string parameter
763 Builds a hbox with a label and a text box in it.
764 */
765 Gtk::Widget *
766 ParamString::get_widget (void)
767 {
768 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
770 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
771 label->show();
772 hbox->pack_start(*label, true, true);
774 ParamStringEntry * textbox = new ParamStringEntry(this);
775 textbox->show();
776 hbox->pack_start(*textbox, false, false);
778 hbox->show();
780 return dynamic_cast<Gtk::Widget *>(hbox);
781 }
783 /** \brief Return 'true' or 'false' */
784 Glib::ustring *
785 ParamBool::string (void)
786 {
787 Glib::ustring * mystring;
789 if (_value)
790 mystring = new Glib::ustring("true");
791 else
792 mystring = new Glib::ustring("false");
794 return mystring;
795 }
797 /** \brief Return the value as a string */
798 Glib::ustring *
799 ParamInt::string (void)
800 {
801 char startstring[32];
802 sprintf(startstring, "%d", _value);
803 Glib::ustring * mystring = new Glib::ustring(startstring);
804 return mystring;
805 }
807 /** \brief Return the value as a string */
808 Glib::ustring *
809 ParamFloat::string (void)
810 {
811 char startstring[G_ASCII_DTOSTR_BUF_SIZE];
812 g_ascii_dtostr(startstring, G_ASCII_DTOSTR_BUF_SIZE, _value);
813 Glib::ustring * mystring = new Glib::ustring(startstring);
814 return mystring;
815 }
817 /** \brief Return the value as a string */
818 Glib::ustring *
819 ParamString::string (void)
820 {
821 Glib::ustring * mystring = new Glib::ustring("");
822 *mystring += "\"";
823 *mystring += _value;
824 *mystring += "\"";
825 return mystring;
826 }
829 } /* namespace Extension */
830 } /* namespace Inkscape */
832 /*
833 Local Variables:
834 mode:c++
835 c-file-style:"stroustrup"
836 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
837 indent-tabs-mode:nil
838 fill-column:99
839 End:
840 */
841 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :