b407db9a935c8b0f69ca8a25ae84101efcf23fe0
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 return sp_repr_lookup_child(adult, "name", _name);
519 }
521 Inkscape::XML::Node *
522 Parameter::new_child (Inkscape::XML::Node * parent)
523 {
524 Inkscape::XML::Node * retval;
525 retval = sp_repr_new("inkscape:extension-param");
526 retval->setAttribute("name", _name);
528 parent->appendChild(retval);
529 return retval;
530 }
532 Inkscape::XML::Node *
533 Parameter::document_param_node (SPDocument * doc)
534 {
535 Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc));
536 Inkscape::XML::Node * params = NULL;
538 GQuark const name_quark = g_quark_from_string("inkscape:extension-params");
540 for (Inkscape::XML::Node * child = defs->firstChild();
541 child != NULL;
542 child = child->next()) {
543 if ((GQuark)child->code() == name_quark &&
544 !strcmp(child->attribute("extension"), extension->get_id())) {
545 params = child;
546 break;
547 }
548 }
550 if (params == NULL) {
551 params = sp_repr_new("inkscape:extension-param");
552 params->setAttribute("extension", extension->get_id());
553 defs->appendChild(params);
554 }
556 return params;
557 }
559 /** \brief Basically, if there is no widget pass a NULL. */
560 Gtk::Widget *
561 Parameter::get_widget (void)
562 {
563 return NULL;
564 }
566 /** \brief If I'm not sure which it is, just don't return a value. */
567 Glib::ustring *
568 Parameter::string (void)
569 {
570 Glib::ustring * mystring = new Glib::ustring("");
571 return mystring;
572 }
574 /** \brief A class to make an adjustment that uses Extension params */
575 class ParamFloatAdjustment : public Gtk::Adjustment {
576 /** The parameter to adjust */
577 ParamFloat * _pref;
578 public:
579 /** \brief Make the adjustment using an extension and the string
580 describing the parameter. */
581 ParamFloatAdjustment (ParamFloat * param) :
582 Gtk::Adjustment(0.0, param->min(), param->max(), 0.1), _pref(param) {
583 this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
584 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed));
585 return;
586 };
588 void val_changed (void);
589 }; /* class ParamFloatAdjustment */
591 /** \brief A function to respond to the value_changed signal from the
592 adjustment.
594 This function just grabs the value from the adjustment and writes
595 it to the parameter. Very simple, but yet beautiful.
596 */
597 void
598 ParamFloatAdjustment::val_changed (void)
599 {
600 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
601 _pref->set(this->get_value(), NULL /* \todo fix */, NULL);
602 return;
603 }
605 /** \brief A class to make an adjustment that uses Extension params */
606 class ParamIntAdjustment : public Gtk::Adjustment {
607 /** The parameter to adjust */
608 ParamInt * _pref;
609 public:
610 /** \brief Make the adjustment using an extension and the string
611 describing the parameter. */
612 ParamIntAdjustment (ParamInt * param) :
613 Gtk::Adjustment(0.0, param->min(), param->max(), 1.0), _pref(param) {
614 this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
615 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed));
616 return;
617 };
619 void val_changed (void);
620 }; /* class ParamIntAdjustment */
622 /** \brief A function to respond to the value_changed signal from the
623 adjustment.
625 This function just grabs the value from the adjustment and writes
626 it to the parameter. Very simple, but yet beautiful.
627 */
628 void
629 ParamIntAdjustment::val_changed (void)
630 {
631 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
632 _pref->set((int)this->get_value(), NULL /* \todo fix */, NULL);
633 return;
634 }
636 /**
637 \brief Creates a Float Adjustment for a float parameter
639 Builds a hbox with a label and a float adjustment in it.
640 */
641 Gtk::Widget *
642 ParamFloat::get_widget (void)
643 {
644 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
646 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
647 label->show();
648 hbox->pack_start(*label, true, true);
650 ParamFloatAdjustment * fadjust = Gtk::manage(new ParamFloatAdjustment(this));
651 Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 0.1, 1));
652 spin->show();
653 hbox->pack_start(*spin, false, false);
655 hbox->show();
657 return dynamic_cast<Gtk::Widget *>(hbox);
658 }
660 /**
661 \brief Creates a Int Adjustment for a int parameter
663 Builds a hbox with a label and a int adjustment in it.
664 */
665 Gtk::Widget *
666 ParamInt::get_widget (void)
667 {
668 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
670 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
671 label->show();
672 hbox->pack_start(*label, true, true);
674 ParamIntAdjustment * fadjust = Gtk::manage(new ParamIntAdjustment(this));
675 Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 1.0, 0));
676 spin->show();
677 hbox->pack_start(*spin, false, false);
679 hbox->show();
681 return dynamic_cast<Gtk::Widget *>(hbox);
682 }
684 /** \brief A check button which is Param aware. It works with the
685 parameter to change it's value as the check button changes
686 value. */
687 class ParamBoolCheckButton : public Gtk::CheckButton {
688 private:
689 /** \brief Param to change */
690 ParamBool * _pref;
691 public:
692 /** \brief Initialize the check button
693 \param param Which parameter to adjust on changing the check button
695 This function sets the value of the checkbox to be that of the
696 parameter, and then sets up a callback to \c on_toggle.
697 */
698 ParamBoolCheckButton (ParamBool * param) :
699 Gtk::CheckButton(), _pref(param) {
700 this->set_active(_pref->get(NULL, NULL) /**\todo fix */);
701 this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle));
702 return;
703 }
704 void on_toggle (void);
705 };
707 /**
708 \brief A function to respond to the check box changing
710 Adjusts the value of the preference to match that in the check box.
711 */
712 void
713 ParamBoolCheckButton::on_toggle (void)
714 {
715 _pref->set(this->get_active(), NULL /**\todo fix this */, NULL);
716 return;
717 }
719 /**
720 \brief Creates a bool check button for a bool parameter
722 Builds a hbox with a label and a check button in it.
723 */
724 Gtk::Widget *
725 ParamBool::get_widget (void)
726 {
727 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
729 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
730 label->show();
731 hbox->pack_start(*label, true, true);
733 ParamBoolCheckButton * checkbox = new ParamBoolCheckButton(this);
734 checkbox->show();
735 hbox->pack_start(*checkbox, false, false);
737 hbox->show();
739 return dynamic_cast<Gtk::Widget *>(hbox);
740 }
742 /** \brief A special category of Gtk::Entry to handle string parameteres */
743 class ParamStringEntry : public Gtk::Entry {
744 private:
745 ParamString * _pref;
746 public:
747 /** \brief Build a string preference for the given parameter
748 \param pref Where to get the string from, and where to put it
749 when it changes.
750 */
751 ParamStringEntry (ParamString * pref) :
752 Gtk::Entry(), _pref(pref) {
753 if (_pref->get(NULL, NULL) != NULL)
754 this->set_text(Glib::ustring(_pref->get(NULL, NULL)));
755 this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text));
756 };
757 void changed_text (void);
758 };
760 /** \brief Respond to the text box changing
762 This function responds to the box changing by grabbing the value
763 from the text box and putting it in the parameter.
764 */
765 void
766 ParamStringEntry::changed_text (void)
767 {
768 Glib::ustring data = this->get_text();
769 _pref->set(data.c_str(), NULL, NULL);
770 return;
771 }
773 /**
774 \brief Creates a text box for the string parameter
776 Builds a hbox with a label and a text box in it.
777 */
778 Gtk::Widget *
779 ParamString::get_widget (void)
780 {
781 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
783 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
784 label->show();
785 hbox->pack_start(*label, true, true);
787 ParamStringEntry * textbox = new ParamStringEntry(this);
788 textbox->show();
789 hbox->pack_start(*textbox, false, false);
791 hbox->show();
793 return dynamic_cast<Gtk::Widget *>(hbox);
794 }
796 /** \brief Return 'true' or 'false' */
797 Glib::ustring *
798 ParamBool::string (void)
799 {
800 Glib::ustring * mystring;
802 if (_value)
803 mystring = new Glib::ustring("true");
804 else
805 mystring = new Glib::ustring("false");
807 return mystring;
808 }
810 /** \brief Return the value as a string */
811 Glib::ustring *
812 ParamInt::string (void)
813 {
814 char startstring[32];
815 sprintf(startstring, "%d", _value);
816 Glib::ustring * mystring = new Glib::ustring(startstring);
817 return mystring;
818 }
820 /** \brief Return the value as a string */
821 Glib::ustring *
822 ParamFloat::string (void)
823 {
824 char startstring[G_ASCII_DTOSTR_BUF_SIZE];
825 g_ascii_dtostr(startstring, G_ASCII_DTOSTR_BUF_SIZE, _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 ParamString::string (void)
833 {
834 Glib::ustring * mystring = new Glib::ustring("");
835 *mystring += "\"";
836 *mystring += _value;
837 *mystring += "\"";
838 return mystring;
839 }
842 } /* namespace Extension */
843 } /* namespace Inkscape */
845 /*
846 Local Variables:
847 mode:c++
848 c-file-style:"stroustrup"
849 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
850 indent-tabs-mode:nil
851 fill-column:99
852 End:
853 */
854 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :