ce6c8c272634a19baadfe1558c19da1c3fd270d0
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"
28 #include "parameter.h"
30 /** \brief The root directory in the preferences database for extension
31 related parameters. */
32 #define PREF_DIR "extensions"
34 namespace Inkscape {
35 namespace Extension {
37 /** \brief A boolean parameter */
38 class ParamBool : public Parameter {
39 private:
40 /** \brief Internal value. */
41 bool _value;
42 public:
43 ParamBool(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
44 /** \brief Returns \c _value */
45 bool get (const Inkscape::XML::Document * doc, const Inkscape::XML::Node * node) { return _value; }
46 bool set (bool in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node);
47 Gtk::Widget * get_widget(void);
48 Glib::ustring * string (void);
49 };
51 /** \brief Use the superclass' allocator and set the \c _value */
52 ParamBool::ParamBool (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
53 Parameter(name, guitext, desc, scope, ext), _value(false)
54 {
55 const char * defaultval = NULL;
56 if (sp_repr_children(xml) != NULL)
57 defaultval = sp_repr_children(xml)->content();
59 if (defaultval != NULL && (!strcmp(defaultval, "TRUE") || !strcmp(defaultval, "true") || !strcmp(defaultval, "1"))) {
60 _value = true;
61 } else {
62 _value = false;
63 }
65 gchar * pref_name = this->pref_name();
66 _value = (bool)prefs_get_int_attribute(PREF_DIR, pref_name, _value);
67 g_free(pref_name);
69 return;
70 }
72 class ParamInt : public Parameter {
73 private:
74 /** \brief Internal value. */
75 int _value;
76 int _min;
77 int _max;
78 public:
79 ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
80 /** \brief Returns \c _value */
81 int get (const Inkscape::XML::Document * doc, const Inkscape::XML::Node * node) { return _value; }
82 int set (int in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node);
83 int max (void) { return _max; }
84 int min (void) { return _min; }
85 Gtk::Widget * get_widget(void);
86 Glib::ustring * string (void);
87 };
89 /** \brief Use the superclass' allocator and set the \c _value */
90 ParamInt::ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
91 Parameter(name, guitext, desc, scope, ext), _value(0), _min(0), _max(10)
92 {
93 const char * defaultval = NULL;
94 if (sp_repr_children(xml) != NULL)
95 defaultval = sp_repr_children(xml)->content();
96 if (defaultval != NULL) {
97 _value = atoi(defaultval);
98 }
100 const char * maxval = xml->attribute("max");
101 if (maxval != NULL)
102 _max = atoi(maxval);
104 const char * minval = xml->attribute("min");
105 if (minval != NULL)
106 _min = atoi(minval);
108 /* We're handling this by just killing both values */
109 if (_max < _min) {
110 _max = 10;
111 _min = 0;
112 }
114 gchar * pref_name = this->pref_name();
115 _value = prefs_get_int_attribute(PREF_DIR, pref_name, _value);
116 g_free(pref_name);
118 // std::cout << "New Int:: value: " << _value << " max: " << _max << " min: " << _min << std::endl;
120 if (_value > _max) _value = _max;
121 if (_value < _min) _value = _min;
123 return;
124 }
126 class ParamFloat : public Parameter {
127 private:
128 /** \brief Internal value. */
129 float _value;
130 float _min;
131 float _max;
132 public:
133 ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
134 /** \brief Returns \c _value */
135 float get (const Inkscape::XML::Document * doc, const Inkscape::XML::Node * node) { return _value; }
136 float set (float in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node);
137 float max (void) { return _max; }
138 float min (void) { return _min; }
139 Gtk::Widget * get_widget(void);
140 Glib::ustring * string (void);
141 };
143 /** \brief Use the superclass' allocator and set the \c _value */
144 ParamFloat::ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
145 Parameter(name, guitext, desc, scope, ext), _value(0.0), _min(0.0), _max(10.0)
146 {
147 const char * defaultval = NULL;
148 if (sp_repr_children(xml) != NULL)
149 defaultval = sp_repr_children(xml)->content();
150 if (defaultval != NULL) {
151 _value = atof(defaultval);
152 }
154 const char * maxval = xml->attribute("max");
155 if (maxval != NULL)
156 _max = atof(maxval);
158 const char * minval = xml->attribute("min");
159 if (minval != NULL)
160 _min = atof(minval);
162 /* We're handling this by just killing both values */
163 if (_max < _min) {
164 _max = 10.0;
165 _min = 0.0;
166 }
168 gchar * pref_name = this->pref_name();
169 _value = prefs_get_double_attribute(PREF_DIR, pref_name, _value);
170 g_free(pref_name);
172 // std::cout << "New Float:: value: " << _value << " max: " << _max << " min: " << _min << std::endl;
174 if (_value > _max) _value = _max;
175 if (_value < _min) _value = _min;
177 return;
178 }
180 class ParamString : public Parameter {
181 private:
182 /** \brief Internal value. This should point to a string that has
183 been allocated in memory. And should be free'd. */
184 gchar * _value;
185 public:
186 ParamString(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
187 ~ParamString(void);
188 /** \brief Returns \c _value, with a \i const to protect it. */
189 const gchar * get (const Inkscape::XML::Document * doc, const Inkscape::XML::Node * node) { return _value; }
190 const gchar * set (const gchar * in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node);
191 Gtk::Widget * get_widget(void);
192 Glib::ustring * string (void);
193 };
195 /**
196 \return None
197 \brief This function creates a parameter that can be used later. This
198 is typically done in the creation of the extension and defined
199 in the XML file describing the extension (it's private so people
200 have to use the system) :)
201 \param in_repr The XML describing the parameter
203 This function first grabs all of the data out of the Repr and puts
204 it into local variables. Actually, these are just pointers, and the
205 data is not duplicated so we need to be careful with it. If there
206 isn't a name or a type in the XML, then no parameter is created as
207 the function just returns.
209 From this point on, we're pretty committed as we've allocated an
210 object and we're starting to fill it. The name is set first, and
211 is created with a strdup to actually allocate memory for it. Then
212 there is a case statement (roughly because strcmp requires 'ifs')
213 based on what type of parameter this is. Depending which type it
214 is, the value is interpreted differently, but they are relatively
215 straight forward. In all cases the value is set to the default
216 value from the XML and the type is set to the interpreted type.
217 */
218 Parameter *
219 Parameter::make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
220 {
221 const char * name;
222 const char * type;
223 const char * guitext;
224 const char * desc;
225 const char * scope_str;
226 Parameter::_scope_t scope = Parameter::SCOPE_USER;
228 name = in_repr->attribute("name");
229 type = in_repr->attribute("type");
230 guitext = in_repr->attribute("gui-text");
231 if (guitext == NULL)
232 guitext = in_repr->attribute("_gui-text");
233 desc = in_repr->attribute("gui-description");
234 if (desc == NULL)
235 desc = in_repr->attribute("_gui-description");
236 scope_str = in_repr->attribute("scope");
238 /* In this case we just don't have enough information */
239 if (name == NULL || type == NULL) {
240 return NULL;
241 }
243 if (scope_str != NULL) {
244 if (!strcmp(scope_str, "user")) {
245 scope = Parameter::SCOPE_USER;
246 } else if (!strcmp(scope_str, "document")) {
247 scope = Parameter::SCOPE_DOCUMENT;
248 } else if (!strcmp(scope_str, "node")) {
249 scope = Parameter::SCOPE_NODE;
250 }
251 }
253 Parameter * param = NULL;
254 if (!strcmp(type, "boolean")) {
255 param = new ParamBool(name, guitext, desc, scope, in_ext, in_repr);
256 } else if (!strcmp(type, "int")) {
257 param = new ParamInt(name, guitext, desc, scope, in_ext, in_repr);
258 } else if (!strcmp(type, "float")) {
259 param = new ParamFloat(name, guitext, desc, scope, in_ext, in_repr);
260 } else if (!strcmp(type, "string")) {
261 param = new ParamString(name, guitext, desc, scope, in_ext, in_repr);
262 }
264 /* Note: param could equal NULL */
265 return param;
266 }
268 /** \brief A function to set the \c _value
269 \param in The value to set to
270 \param doc A document that should be used to set the value.
271 \param node The node where the value may be placed
273 This function sets the internal value, but it also sets the value
274 in the preferences structure. To put it in the right place, \c PREF_DIR
275 and \c pref_name() are used.
276 */
277 bool
278 ParamBool::set (bool in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node)
279 {
280 _value = in;
282 gchar * prefname = this->pref_name();
283 prefs_set_int_attribute(PREF_DIR, prefname, _value == true ? 1 : 0);
284 g_free(prefname);
286 return _value;
287 }
289 /** \brief A function to set the \c _value
290 \param in The value to set to
291 \param doc A document that should be used to set the value.
292 \param node The node where the value may be placed
294 This function sets the internal value, but it also sets the value
295 in the preferences structure. To put it in the right place, \c PREF_DIR
296 and \c pref_name() are used.
297 */
298 int
299 ParamInt::set (int in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node)
300 {
301 _value = in;
302 if (_value > _max) _value = _max;
303 if (_value < _min) _value = _min;
305 gchar * prefname = this->pref_name();
306 prefs_set_int_attribute(PREF_DIR, prefname, _value);
307 g_free(prefname);
309 return _value;
310 }
312 /** \brief A function to set the \c _value
313 \param in The value to set to
314 \param doc A document that should be used to set the value.
315 \param node The node where the value may be placed
317 This function sets the internal value, but it also sets the value
318 in the preferences structure. To put it in the right place, \c PREF_DIR
319 and \c pref_name() are used.
320 */
321 float
322 ParamFloat::set (float in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node)
323 {
324 _value = in;
325 if (_value > _max) _value = _max;
326 if (_value < _min) _value = _min;
328 gchar * prefname = this->pref_name();
329 prefs_set_double_attribute(PREF_DIR, prefname, _value);
330 g_free(prefname);
332 return _value;
333 }
335 /** \brief A function to set the \c _value
336 \param in The value to set to
337 \param doc A document that should be used to set the value.
338 \param node The node where the value may be placed
340 This function sets the internal value, but it also sets the value
341 in the preferences structure. To put it in the right place, \c PREF_DIR
342 and \c pref_name() are used.
344 To copy the data into _value the old memory must be free'd first.
345 It is important to note that \c g_free handles \c NULL just fine. Then
346 the passed in value is duplicated using \c g_strdup().
347 */
348 const gchar *
349 ParamString::set (const gchar * in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node)
350 {
351 if (in == NULL) return NULL; /* Can't have NULL string */
353 if (_value != NULL)
354 g_free(_value);
355 _value = g_strdup(in);
357 gchar * prefname = this->pref_name();
358 prefs_set_string_attribute(PREF_DIR, prefname, _value);
359 g_free(prefname);
361 return _value;
362 }
364 /** \brief Wrapper to cast to the object and use it's function. */
365 bool
366 Parameter::get_bool (const Inkscape::XML::Document * doc, const Inkscape::XML::Node * node)
367 {
368 ParamBool * boolpntr;
369 boolpntr = dynamic_cast<ParamBool *>(this);
370 if (boolpntr == NULL)
371 throw Extension::param_wrong_type();
372 return boolpntr->get(doc, node);
373 }
375 /** \brief Wrapper to cast to the object and use it's function. */
376 int
377 Parameter::get_int (const Inkscape::XML::Document * doc, const Inkscape::XML::Node * node)
378 {
379 ParamInt * intpntr;
380 intpntr = dynamic_cast<ParamInt *>(this);
381 if (intpntr == NULL)
382 throw Extension::param_wrong_type();
383 return intpntr->get(doc, node);
384 }
386 /** \brief Wrapper to cast to the object and use it's function. */
387 float
388 Parameter::get_float (const Inkscape::XML::Document * doc, const Inkscape::XML::Node * node)
389 {
390 ParamFloat * floatpntr;
391 floatpntr = dynamic_cast<ParamFloat *>(this);
392 if (floatpntr == NULL)
393 throw Extension::param_wrong_type();
394 return floatpntr->get(doc, node);
395 }
397 /** \brief Wrapper to cast to the object and use it's function. */
398 const gchar *
399 Parameter::get_string (const Inkscape::XML::Document * doc, const Inkscape::XML::Node * node)
400 {
401 ParamString * stringpntr;
402 stringpntr = dynamic_cast<ParamString *>(this);
403 if (stringpntr == NULL)
404 throw Extension::param_wrong_type();
405 return stringpntr->get(doc, node);
406 }
408 /** \brief Wrapper to cast to the object and use it's function. */
409 bool
410 Parameter::set_bool (bool in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node)
411 {
412 ParamBool * boolpntr;
413 boolpntr = dynamic_cast<ParamBool *>(this);
414 if (boolpntr == NULL)
415 throw Extension::param_wrong_type();
416 return boolpntr->set(in, doc, node);
417 }
419 /** \brief Wrapper to cast to the object and use it's function. */
420 int
421 Parameter::set_int (int in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node)
422 {
423 ParamInt * intpntr;
424 intpntr = dynamic_cast<ParamInt *>(this);
425 if (intpntr == NULL)
426 throw Extension::param_wrong_type();
427 return intpntr->set(in, doc, node);
428 }
430 /** \brief Wrapper to cast to the object and use it's function. */
431 float
432 Parameter::set_float (float in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node)
433 {
434 ParamFloat * floatpntr;
435 floatpntr = dynamic_cast<ParamFloat *>(this);
436 if (floatpntr == NULL)
437 throw Extension::param_wrong_type();
438 return floatpntr->set(in, doc, node);
439 }
441 /** \brief Wrapper to cast to the object and use it's function. */
442 const gchar *
443 Parameter::set_string (const gchar * in, Inkscape::XML::Document * doc, Inkscape::XML::Node * node)
444 {
445 ParamString * stringpntr;
446 stringpntr = dynamic_cast<ParamString *>(this);
447 if (stringpntr == NULL)
448 throw Extension::param_wrong_type();
449 return stringpntr->set(in, doc, node);
450 }
452 /** \brief Initialize the object, to do that, copy the data. */
453 ParamString::ParamString (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
454 Parameter(name, guitext, desc, scope, ext), _value(NULL)
455 {
456 const char * defaultval = NULL;
457 if (sp_repr_children(xml) != NULL)
458 defaultval = sp_repr_children(xml)->content();
460 gchar * pref_name = this->pref_name();
461 const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
462 g_free(pref_name);
464 if (paramval != NULL)
465 defaultval = paramval;
466 if (defaultval != NULL)
467 _value = g_strdup(defaultval);
469 return;
470 }
472 /** \brief Free the allocated data. */
473 ParamString::~ParamString(void)
474 {
475 g_free(_value);
476 }
478 /** \brief Oop, now that we need a parameter, we need it's name. */
479 Parameter::Parameter (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext) :
480 extension(ext), _name(NULL), _desc(NULL), _scope(scope), _text(NULL)
481 {
482 if (name != NULL)
483 _name = g_strdup(name);
484 if (desc != NULL) {
485 _desc = g_strdup(desc);
486 // printf("Adding description: '%s' on '%s'\n", _desc, _name);
487 }
490 if (guitext != NULL)
491 _text = g_strdup(guitext);
492 else
493 _text = g_strdup(name);
495 return;
496 }
498 /** \brief Just free the allocated name. */
499 Parameter::~Parameter (void)
500 {
501 g_free(_name);
502 g_free(_text);
503 }
505 /** \brief Build the name to write the parameter from the extension's
506 ID and the name of this parameter. */
507 gchar *
508 Parameter::pref_name (void)
509 {
510 return g_strdup_printf("%s.%s", extension->get_id(), _name);
511 }
513 /** \brief Basically, if there is no widget pass a NULL. */
514 Gtk::Widget *
515 Parameter::get_widget (void)
516 {
517 return NULL;
518 }
520 /** \brief If I'm not sure which it is, just don't return a value. */
521 Glib::ustring *
522 Parameter::string (void)
523 {
524 Glib::ustring * mystring = new Glib::ustring("");
525 return mystring;
526 }
528 /** \brief A class to make an adjustment that uses Extension params */
529 class ParamFloatAdjustment : public Gtk::Adjustment {
530 /** The parameter to adjust */
531 ParamFloat * _pref;
532 public:
533 /** \brief Make the adjustment using an extension and the string
534 describing the parameter. */
535 ParamFloatAdjustment (ParamFloat * param) :
536 Gtk::Adjustment(0.0, param->min(), param->max(), 0.1), _pref(param) {
537 this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
538 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed));
539 return;
540 };
542 void val_changed (void);
543 }; /* class ParamFloatAdjustment */
545 /** \brief A function to respond to the value_changed signal from the
546 adjustment.
548 This function just grabs the value from the adjustment and writes
549 it to the parameter. Very simple, but yet beautiful.
550 */
551 void
552 ParamFloatAdjustment::val_changed (void)
553 {
554 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
555 _pref->set(this->get_value(), NULL /* \todo fix */, NULL);
556 return;
557 }
559 /** \brief A class to make an adjustment that uses Extension params */
560 class ParamIntAdjustment : public Gtk::Adjustment {
561 /** The parameter to adjust */
562 ParamInt * _pref;
563 public:
564 /** \brief Make the adjustment using an extension and the string
565 describing the parameter. */
566 ParamIntAdjustment (ParamInt * param) :
567 Gtk::Adjustment(0.0, param->min(), param->max(), 1.0), _pref(param) {
568 this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
569 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed));
570 return;
571 };
573 void val_changed (void);
574 }; /* class ParamIntAdjustment */
576 /** \brief A function to respond to the value_changed signal from the
577 adjustment.
579 This function just grabs the value from the adjustment and writes
580 it to the parameter. Very simple, but yet beautiful.
581 */
582 void
583 ParamIntAdjustment::val_changed (void)
584 {
585 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
586 _pref->set((int)this->get_value(), NULL /* \todo fix */, NULL);
587 return;
588 }
590 /**
591 \brief Creates a Float Adjustment for a float parameter
593 Builds a hbox with a label and a float adjustment in it.
594 */
595 Gtk::Widget *
596 ParamFloat::get_widget (void)
597 {
598 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
600 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
601 label->show();
602 hbox->pack_start(*label, true, true);
604 ParamFloatAdjustment * fadjust = new ParamFloatAdjustment(this);
605 Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 0.1, 1));
606 spin->show();
607 hbox->pack_start(*spin, false, false);
609 hbox->show();
611 return dynamic_cast<Gtk::Widget *>(hbox);
612 }
614 /**
615 \brief Creates a Int Adjustment for a int parameter
617 Builds a hbox with a label and a int adjustment in it.
618 */
619 Gtk::Widget *
620 ParamInt::get_widget (void)
621 {
622 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
624 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
625 label->show();
626 hbox->pack_start(*label, true, true);
628 ParamIntAdjustment * fadjust = new ParamIntAdjustment(this);
629 Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 1.0, 0));
630 spin->show();
631 hbox->pack_start(*spin, false, false);
633 hbox->show();
635 return dynamic_cast<Gtk::Widget *>(hbox);
636 }
638 /** \brief A check button which is Param aware. It works with the
639 parameter to change it's value as the check button changes
640 value. */
641 class ParamBoolCheckButton : public Gtk::CheckButton {
642 private:
643 /** \brief Param to change */
644 ParamBool * _pref;
645 public:
646 /** \brief Initialize the check button
647 \param param Which parameter to adjust on changing the check button
649 This function sets the value of the checkbox to be that of the
650 parameter, and then sets up a callback to \c on_toggle.
651 */
652 ParamBoolCheckButton (ParamBool * param) :
653 Gtk::CheckButton(), _pref(param) {
654 this->set_active(_pref->get(NULL, NULL) /**\todo fix */);
655 this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle));
656 return;
657 }
658 void on_toggle (void);
659 };
661 /**
662 \brief A function to respond to the check box changing
664 Adjusts the value of the preference to match that in the check box.
665 */
666 void
667 ParamBoolCheckButton::on_toggle (void)
668 {
669 _pref->set(this->get_active(), NULL /**\todo fix this */, NULL);
670 return;
671 }
673 /**
674 \brief Creates a bool check button for a bool parameter
676 Builds a hbox with a label and a check button in it.
677 */
678 Gtk::Widget *
679 ParamBool::get_widget (void)
680 {
681 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox());
683 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
684 label->show();
685 hbox->pack_start(*label, true, true);
687 ParamBoolCheckButton * checkbox = new ParamBoolCheckButton(this);
688 checkbox->show();
689 hbox->pack_start(*checkbox, false, false);
691 hbox->show();
693 return dynamic_cast<Gtk::Widget *>(hbox);
694 }
696 /** \brief A special category of Gtk::Entry to handle string parameteres */
697 class ParamStringEntry : public Gtk::Entry {
698 private:
699 ParamString * _pref;
700 public:
701 /** \brief Build a string preference for the given parameter
702 \param pref Where to get the string from, and where to put it
703 when it changes.
704 */
705 ParamStringEntry (ParamString * pref) :
706 Gtk::Entry(), _pref(pref) {
707 if (_pref->get(NULL, NULL) != NULL)
708 this->set_text(Glib::ustring(_pref->get(NULL, NULL)));
709 this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text));
710 };
711 void changed_text (void);
712 };
714 /** \brief Respond to the text box changing
716 This function responds to the box changing by grabbing the value
717 from the text box and putting it in the parameter.
718 */
719 void
720 ParamStringEntry::changed_text (void)
721 {
722 Glib::ustring data = this->get_text();
723 _pref->set(data.c_str(), NULL, NULL);
724 return;
725 }
727 /**
728 \brief Creates a text box for the string parameter
730 Builds a hbox with a label and a text box in it.
731 */
732 Gtk::Widget *
733 ParamString::get_widget (void)
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 ParamStringEntry * textbox = new ParamStringEntry(this);
742 textbox->show();
743 hbox->pack_start(*textbox, false, false);
745 hbox->show();
747 return dynamic_cast<Gtk::Widget *>(hbox);
748 }
750 /** \brief Return 'true' or 'false' */
751 Glib::ustring *
752 ParamBool::string (void)
753 {
754 Glib::ustring * mystring;
756 if (_value)
757 mystring = new Glib::ustring("true");
758 else
759 mystring = new Glib::ustring("false");
761 return mystring;
762 }
764 /** \brief Return the value as a string */
765 Glib::ustring *
766 ParamInt::string (void)
767 {
768 char startstring[32];
769 sprintf(startstring, "%d", _value);
770 Glib::ustring * mystring = new Glib::ustring(startstring);
771 return mystring;
772 }
774 /** \brief Return the value as a string */
775 Glib::ustring *
776 ParamFloat::string (void)
777 {
778 char startstring[G_ASCII_DTOSTR_BUF_SIZE];
779 g_ascii_dtostr(startstring, G_ASCII_DTOSTR_BUF_SIZE, _value);
780 Glib::ustring * mystring = new Glib::ustring(startstring);
781 return mystring;
782 }
784 /** \brief Return the value as a string */
785 Glib::ustring *
786 ParamString::string (void)
787 {
788 Glib::ustring * mystring = new Glib::ustring("");
789 *mystring += "\"";
790 *mystring += _value;
791 *mystring += "\"";
792 return mystring;
793 }
796 } /* namespace Extension */
797 } /* namespace Inkscape */
799 /*
800 Local Variables:
801 mode:c++
802 c-file-style:"stroustrup"
803 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
804 indent-tabs-mode:nil
805 fill-column:99
806 End:
807 */
808 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :