1 /** \file
2 * Parameters for extensions.
3 */
5 /*
6 * Author:
7 * Ted Gould <ted@gould.cx>
8 *
9 * Copyright (C) 2006 Johan Engelen <johan@shouraizou.nl>
10 * Copyright (C) 2005-2006 Author
11 *
12 * Released under GNU GPL, read the file 'COPYING' for more information
13 */
15 #ifdef HAVE_CONFIG_H
16 # include "config.h"
17 #endif
20 #include <gtkmm/adjustment.h>
21 #include <gtkmm/box.h>
22 #include <gtkmm/spinbutton.h>
24 #include <glibmm/i18n.h>
26 #include <xml/node.h>
28 #include "extension.h"
29 #include "prefs-utils.h"
30 #include "document-private.h"
31 #include "sp-object.h"
33 #include "parameter.h"
34 #include "paramnotebook.h"
35 #include "paramenum.h"
37 /** \brief The root directory in the preferences database for extension
38 related parameters. */
39 #define PREF_DIR "extensions"
41 namespace Inkscape {
42 namespace Extension {
44 /** \brief A description parameter */
45 class ParamDescription : public Parameter {
46 private:
47 /** \brief Internal value. */
48 gchar * _value;
49 public:
50 ParamDescription(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
51 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
52 };
54 /** \brief A boolean parameter */
55 class ParamBool : public Parameter {
56 private:
57 /** \brief Internal value. */
58 bool _value;
59 public:
60 ParamBool(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
61 /** \brief Returns \c _value */
62 bool get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
63 bool set (bool in, SPDocument * doc, Inkscape::XML::Node * node);
64 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
65 Glib::ustring * string (void);
66 };
68 /** \brief Use the superclass' allocator and set the \c _value */
69 ParamBool::ParamBool (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
70 Parameter(name, guitext, desc, scope, ext), _value(false)
71 {
72 const char * defaultval = NULL;
73 if (sp_repr_children(xml) != NULL)
74 defaultval = sp_repr_children(xml)->content();
76 if (defaultval != NULL && (!strcmp(defaultval, "TRUE") || !strcmp(defaultval, "true") || !strcmp(defaultval, "1"))) {
77 _value = true;
78 } else {
79 _value = false;
80 }
82 gchar * pref_name = this->pref_name();
83 _value = (bool)prefs_get_int_attribute(PREF_DIR, pref_name, _value);
84 g_free(pref_name);
86 return;
87 }
89 class ParamInt : public Parameter {
90 private:
91 /** \brief Internal value. */
92 int _value;
93 int _min;
94 int _max;
95 public:
96 ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
97 /** \brief Returns \c _value */
98 int get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
99 int set (int in, SPDocument * doc, Inkscape::XML::Node * node);
100 int max (void) { return _max; }
101 int min (void) { return _min; }
102 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
103 Glib::ustring * string (void);
104 };
106 /** \brief Use the superclass' allocator and set the \c _value */
107 ParamInt::ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
108 Parameter(name, guitext, desc, scope, ext), _value(0), _min(0), _max(10)
109 {
110 const char * defaultval = NULL;
111 if (sp_repr_children(xml) != NULL)
112 defaultval = sp_repr_children(xml)->content();
113 if (defaultval != NULL) {
114 _value = atoi(defaultval);
115 }
117 const char * maxval = xml->attribute("max");
118 if (maxval != NULL)
119 _max = atoi(maxval);
121 const char * minval = xml->attribute("min");
122 if (minval != NULL)
123 _min = atoi(minval);
125 /* We're handling this by just killing both values */
126 if (_max < _min) {
127 _max = 10;
128 _min = 0;
129 }
131 gchar * pref_name = this->pref_name();
132 _value = prefs_get_int_attribute(PREF_DIR, pref_name, _value);
133 g_free(pref_name);
135 // std::cout << "New Int:: value: " << _value << " max: " << _max << " min: " << _min << std::endl;
137 if (_value > _max) _value = _max;
138 if (_value < _min) _value = _min;
140 return;
141 }
143 class ParamFloat : public Parameter {
144 private:
145 /** \brief Internal value. */
146 float _value;
147 float _min;
148 float _max;
149 public:
150 ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
151 /** \brief Returns \c _value */
152 float get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
153 float set (float in, SPDocument * doc, Inkscape::XML::Node * node);
154 float max (void) { return _max; }
155 float min (void) { return _min; }
156 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
157 Glib::ustring * string (void);
158 };
160 /** \brief Use the superclass' allocator and set the \c _value */
161 ParamFloat::ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
162 Parameter(name, guitext, desc, scope, ext), _value(0.0), _min(0.0), _max(10.0)
163 {
164 const char * defaultval = NULL;
165 if (sp_repr_children(xml) != NULL)
166 defaultval = sp_repr_children(xml)->content();
167 if (defaultval != NULL) {
168 _value = atof(defaultval);
169 }
171 const char * maxval = xml->attribute("max");
172 if (maxval != NULL)
173 _max = atof(maxval);
175 const char * minval = xml->attribute("min");
176 if (minval != NULL)
177 _min = atof(minval);
179 /* We're handling this by just killing both values */
180 if (_max < _min) {
181 _max = 10.0;
182 _min = 0.0;
183 }
185 gchar * pref_name = this->pref_name();
186 _value = prefs_get_double_attribute(PREF_DIR, pref_name, _value);
187 g_free(pref_name);
189 // std::cout << "New Float:: value: " << _value << " max: " << _max << " min: " << _min << std::endl;
191 if (_value > _max) _value = _max;
192 if (_value < _min) _value = _min;
194 return;
195 }
197 class ParamString : public Parameter {
198 private:
199 /** \brief Internal value. This should point to a string that has
200 been allocated in memory. And should be free'd. */
201 gchar * _value;
202 public:
203 ParamString(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
204 ~ParamString(void);
205 /** \brief Returns \c _value, with a \i const to protect it. */
206 const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
207 const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
208 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
209 Glib::ustring * string (void);
210 };
212 class ParamEnum : public Parameter {
213 private:
214 class Choice {
215 public:
216 gchar * _gui_name;
217 gchar * _value;
218 Choice(gchar * gui_name, gchar * value) : _gui_name(NULL), _value(NULL) {
219 if (gui_name != NULL)
220 _gui_name = g_strdup(_(gui_name));
221 if (value != NULL)
222 _value = g_strdup(value);
223 return;
224 };
225 ~Choice (void) {
226 g_free(_gui_name);
227 g_free(_value);
228 };
229 }; /* class Choice */
230 /** \brief Internal value. This should point to a string that has
231 been allocated in memory. And should be free'd. */
232 Choice * _current_choice;
233 typedef std::list<Choice *> choice_list_t;
234 choice_list_t _choice_list;
235 public:
236 ParamEnum(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
237 ~ParamEnum(void);
238 /** \brief Returns \c _value, with a \i const to protect it. */
239 const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _current_choice != NULL ? _current_choice->_value : NULL; }
240 const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
241 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
242 Glib::ustring * string (void);
243 }; /* class ParamEnum */
246 /**
247 \return None
248 \brief This function creates a parameter that can be used later. This
249 is typically done in the creation of the extension and defined
250 in the XML file describing the extension (it's private so people
251 have to use the system) :)
252 \param in_repr The XML describing the parameter
254 This function first grabs all of the data out of the Repr and puts
255 it into local variables. Actually, these are just pointers, and the
256 data is not duplicated so we need to be careful with it. If there
257 isn't a name or a type in the XML, then no parameter is created as
258 the function just returns.
260 From this point on, we're pretty committed as we've allocated an
261 object and we're starting to fill it. The name is set first, and
262 is created with a strdup to actually allocate memory for it. Then
263 there is a case statement (roughly because strcmp requires 'ifs')
264 based on what type of parameter this is. Depending which type it
265 is, the value is interpreted differently, but they are relatively
266 straight forward. In all cases the value is set to the default
267 value from the XML and the type is set to the interpreted type.
268 */
269 Parameter *
270 Parameter::make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
271 {
272 const char * name;
273 const char * type;
274 const char * guitext;
275 const char * desc;
276 const char * scope_str;
277 Parameter::_scope_t scope = Parameter::SCOPE_USER;
279 name = in_repr->attribute("name");
280 type = in_repr->attribute("type");
281 guitext = in_repr->attribute("gui-text");
282 if (guitext == NULL)
283 guitext = in_repr->attribute("_gui-text");
284 desc = in_repr->attribute("gui-description");
285 if (desc == NULL)
286 desc = in_repr->attribute("_gui-description");
287 scope_str = in_repr->attribute("scope");
289 /* In this case we just don't have enough information */
290 if (name == NULL || type == NULL) {
291 return NULL;
292 }
294 if (scope_str != NULL) {
295 if (!strcmp(scope_str, "user")) {
296 scope = Parameter::SCOPE_USER;
297 } else if (!strcmp(scope_str, "document")) {
298 scope = Parameter::SCOPE_DOCUMENT;
299 } else if (!strcmp(scope_str, "node")) {
300 scope = Parameter::SCOPE_NODE;
301 }
302 }
304 Parameter * param = NULL;
305 if (!strcmp(type, "boolean")) {
306 param = new ParamBool(name, guitext, desc, scope, in_ext, in_repr);
307 } else if (!strcmp(type, "int")) {
308 param = new ParamInt(name, guitext, desc, scope, in_ext, in_repr);
309 } else if (!strcmp(type, "float")) {
310 param = new ParamFloat(name, guitext, desc, scope, in_ext, in_repr);
311 } else if (!strcmp(type, "string")) {
312 param = new ParamString(name, guitext, desc, scope, in_ext, in_repr);
313 } else if (!strcmp(type, "description")) {
314 param = new ParamDescription(name, guitext, desc, scope, in_ext, in_repr);
315 } else if (!strcmp(type, "enum")) {
316 param = new ParamComboBox(name, guitext, desc, scope, in_ext, in_repr);
317 } else if (!strcmp(type, "notebook")) {
318 param = new ParamNotebook(name, guitext, desc, scope, in_ext, in_repr);
319 }
321 /* Note: param could equal NULL */
322 return param;
323 }
325 /** \brief A function to set the \c _value
326 \param in The value to set to
327 \param doc A document that should be used to set the value.
328 \param node The node where the value may be placed
330 This function sets the internal value, but it also sets the value
331 in the preferences structure. To put it in the right place, \c PREF_DIR
332 and \c pref_name() are used.
333 */
334 bool
335 ParamBool::set (bool in, SPDocument * doc, Inkscape::XML::Node * node)
336 {
337 _value = in;
339 gchar * prefname = this->pref_name();
340 prefs_set_int_attribute(PREF_DIR, prefname, _value == true ? 1 : 0);
341 g_free(prefname);
343 return _value;
344 }
346 /** \brief A function to set the \c _value
347 \param in The value to set to
348 \param doc A document that should be used to set the value.
349 \param node The node where the value may be placed
351 This function sets the internal value, but it also sets the value
352 in the preferences structure. To put it in the right place, \c PREF_DIR
353 and \c pref_name() are used.
354 */
355 int
356 ParamInt::set (int in, SPDocument * doc, Inkscape::XML::Node * node)
357 {
358 _value = in;
359 if (_value > _max) _value = _max;
360 if (_value < _min) _value = _min;
362 gchar * prefname = this->pref_name();
363 prefs_set_int_attribute(PREF_DIR, prefname, _value);
364 g_free(prefname);
366 return _value;
367 }
369 /** \brief A function to set the \c _value
370 \param in The value to set to
371 \param doc A document that should be used to set the value.
372 \param node The node where the value may be placed
374 This function sets the internal value, but it also sets the value
375 in the preferences structure. To put it in the right place, \c PREF_DIR
376 and \c pref_name() are used.
377 */
378 float
379 ParamFloat::set (float in, SPDocument * doc, Inkscape::XML::Node * node)
380 {
381 _value = in;
382 if (_value > _max) _value = _max;
383 if (_value < _min) _value = _min;
385 gchar * prefname = this->pref_name();
386 prefs_set_double_attribute(PREF_DIR, prefname, _value);
387 g_free(prefname);
389 return _value;
390 }
392 /** \brief A function to set the \c _value
393 \param in The value to set to
394 \param doc A document that should be used to set the value.
395 \param node The node where the value may be placed
397 This function sets the internal value, but it also sets the value
398 in the preferences structure. To put it in the right place, \c PREF_DIR
399 and \c pref_name() are used.
401 To copy the data into _value the old memory must be free'd first.
402 It is important to note that \c g_free handles \c NULL just fine. Then
403 the passed in value is duplicated using \c g_strdup().
404 */
405 const gchar *
406 ParamString::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
407 {
408 if (in == NULL) return NULL; /* Can't have NULL string */
410 if (_value != NULL)
411 g_free(_value);
412 _value = g_strdup(in);
414 gchar * prefname = this->pref_name();
415 prefs_set_string_attribute(PREF_DIR, prefname, _value);
416 g_free(prefname);
418 return _value;
419 }
421 /** \brief Wrapper to cast to the object and use it's function. */
422 bool
423 Parameter::get_bool (const SPDocument * doc, const Inkscape::XML::Node * node)
424 {
425 ParamBool * boolpntr;
426 boolpntr = dynamic_cast<ParamBool *>(this);
427 if (boolpntr == NULL)
428 throw Extension::param_wrong_type();
429 return boolpntr->get(doc, node);
430 }
432 /** \brief Wrapper to cast to the object and use it's function. */
433 int
434 Parameter::get_int (const SPDocument * doc, const Inkscape::XML::Node * node)
435 {
436 ParamInt * intpntr;
437 intpntr = dynamic_cast<ParamInt *>(this);
438 if (intpntr == NULL)
439 throw Extension::param_wrong_type();
440 return intpntr->get(doc, node);
441 }
443 /** \brief Wrapper to cast to the object and use it's function. */
444 float
445 Parameter::get_float (const SPDocument * doc, const Inkscape::XML::Node * node)
446 {
447 ParamFloat * floatpntr;
448 floatpntr = dynamic_cast<ParamFloat *>(this);
449 if (floatpntr == NULL)
450 throw Extension::param_wrong_type();
451 return floatpntr->get(doc, node);
452 }
454 /** \brief Wrapper to cast to the object and use it's function. */
455 const gchar *
456 Parameter::get_string (const SPDocument * doc, const Inkscape::XML::Node * node)
457 {
458 ParamString * stringpntr;
459 stringpntr = dynamic_cast<ParamString *>(this);
460 if (stringpntr == NULL)
461 throw Extension::param_wrong_type();
462 return stringpntr->get(doc, node);
463 }
465 /** \brief Wrapper to cast to the object and use it's function. */
466 bool
467 Parameter::set_bool (bool in, SPDocument * doc, Inkscape::XML::Node * node)
468 {
469 ParamBool * boolpntr;
470 boolpntr = dynamic_cast<ParamBool *>(this);
471 if (boolpntr == NULL)
472 throw Extension::param_wrong_type();
473 return boolpntr->set(in, doc, node);
474 }
476 /** \brief Wrapper to cast to the object and use it's function. */
477 int
478 Parameter::set_int (int in, SPDocument * doc, Inkscape::XML::Node * node)
479 {
480 ParamInt * intpntr;
481 intpntr = dynamic_cast<ParamInt *>(this);
482 if (intpntr == NULL)
483 throw Extension::param_wrong_type();
484 return intpntr->set(in, doc, node);
485 }
487 /** \brief Wrapper to cast to the object and use it's function. */
488 float
489 Parameter::set_float (float in, SPDocument * doc, Inkscape::XML::Node * node)
490 {
491 ParamFloat * floatpntr;
492 floatpntr = dynamic_cast<ParamFloat *>(this);
493 if (floatpntr == NULL)
494 throw Extension::param_wrong_type();
495 return floatpntr->set(in, doc, node);
496 }
498 /** \brief Wrapper to cast to the object and use it's function. */
499 const gchar *
500 Parameter::set_string (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
501 {
502 ParamString * stringpntr;
503 stringpntr = dynamic_cast<ParamString *>(this);
504 if (stringpntr == NULL)
505 throw Extension::param_wrong_type();
506 return stringpntr->set(in, doc, node);
507 }
509 /** \brief Initialize the object, to do that, copy the data. */
510 ParamString::ParamString (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
511 Parameter(name, guitext, desc, scope, ext), _value(NULL)
512 {
513 const char * defaultval = NULL;
514 if (sp_repr_children(xml) != NULL)
515 defaultval = sp_repr_children(xml)->content();
517 gchar * pref_name = this->pref_name();
518 const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
519 g_free(pref_name);
521 if (paramval != NULL)
522 defaultval = paramval;
523 if (defaultval != NULL)
524 _value = g_strdup(defaultval);
526 return;
527 }
529 /** \brief Free the allocated data. */
530 ParamString::~ParamString(void)
531 {
532 g_free(_value);
533 }
535 /** \brief Oop, now that we need a parameter, we need it's name. */
536 Parameter::Parameter (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext) :
537 extension(ext), _name(NULL), _desc(NULL), _scope(scope), _text(NULL)
538 {
539 if (name != NULL)
540 _name = g_strdup(name);
541 if (desc != NULL) {
542 _desc = g_strdup(desc);
543 // printf("Adding description: '%s' on '%s'\n", _desc, _name);
544 }
547 if (guitext != NULL)
548 _text = g_strdup(guitext);
549 else
550 _text = g_strdup(name);
552 return;
553 }
555 /** \brief Just free the allocated name. */
556 Parameter::~Parameter (void)
557 {
558 g_free(_name);
559 g_free(_text);
560 }
562 /** \brief Build the name to write the parameter from the extension's
563 ID and the name of this parameter. */
564 gchar *
565 Parameter::pref_name (void)
566 {
567 return g_strdup_printf("%s.%s", extension->get_id(), _name);
568 }
570 Inkscape::XML::Node *
571 Parameter::find_child (Inkscape::XML::Node * adult)
572 {
573 return sp_repr_lookup_child(adult, "name", _name);
574 }
576 Inkscape::XML::Node *
577 Parameter::new_child (Inkscape::XML::Node * parent)
578 {
579 Inkscape::XML::Node * retval;
580 retval = sp_repr_new("inkscape:extension-param");
581 retval->setAttribute("name", _name);
583 parent->appendChild(retval);
584 return retval;
585 }
587 Inkscape::XML::Node *
588 Parameter::document_param_node (SPDocument * doc)
589 {
590 Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc));
591 Inkscape::XML::Node * params = NULL;
593 GQuark const name_quark = g_quark_from_string("inkscape:extension-params");
595 for (Inkscape::XML::Node * child = defs->firstChild();
596 child != NULL;
597 child = child->next()) {
598 if ((GQuark)child->code() == name_quark &&
599 !strcmp(child->attribute("extension"), extension->get_id())) {
600 params = child;
601 break;
602 }
603 }
605 if (params == NULL) {
606 params = sp_repr_new("inkscape:extension-param");
607 params->setAttribute("extension", extension->get_id());
608 defs->appendChild(params);
609 }
611 return params;
612 }
614 /** \brief Basically, if there is no widget pass a NULL. */
615 Gtk::Widget *
616 Parameter::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
617 {
618 return NULL;
619 }
621 /** \brief If I'm not sure which it is, just don't return a value. */
622 Glib::ustring *
623 Parameter::string (void)
624 {
625 Glib::ustring * mystring = new Glib::ustring("");
626 return mystring;
627 }
629 /** \brief A class to make an adjustment that uses Extension params */
630 class ParamFloatAdjustment : public Gtk::Adjustment {
631 /** The parameter to adjust */
632 ParamFloat * _pref;
633 SPDocument * _doc;
634 Inkscape::XML::Node * _node;
635 public:
636 /** \brief Make the adjustment using an extension and the string
637 describing the parameter. */
638 ParamFloatAdjustment (ParamFloat * param, SPDocument * doc, Inkscape::XML::Node * node) :
639 Gtk::Adjustment(0.0, param->min(), param->max(), 0.1), _pref(param), _doc(doc), _node(node) {
640 this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
641 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed));
642 return;
643 };
645 void val_changed (void);
646 }; /* class ParamFloatAdjustment */
648 /** \brief A function to respond to the value_changed signal from the
649 adjustment.
651 This function just grabs the value from the adjustment and writes
652 it to the parameter. Very simple, but yet beautiful.
653 */
654 void
655 ParamFloatAdjustment::val_changed (void)
656 {
657 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
658 _pref->set(this->get_value(), _doc, _node);
659 return;
660 }
662 /** \brief A class to make an adjustment that uses Extension params */
663 class ParamIntAdjustment : public Gtk::Adjustment {
664 /** The parameter to adjust */
665 ParamInt * _pref;
666 SPDocument * _doc;
667 Inkscape::XML::Node * _node;
668 public:
669 /** \brief Make the adjustment using an extension and the string
670 describing the parameter. */
671 ParamIntAdjustment (ParamInt * param, SPDocument * doc, Inkscape::XML::Node * node) :
672 Gtk::Adjustment(0.0, param->min(), param->max(), 1.0), _pref(param), _doc(doc), _node(node) {
673 this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
674 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed));
675 return;
676 };
678 void val_changed (void);
679 }; /* class ParamIntAdjustment */
681 /** \brief A function to respond to the value_changed signal from the
682 adjustment.
684 This function just grabs the value from the adjustment and writes
685 it to the parameter. Very simple, but yet beautiful.
686 */
687 void
688 ParamIntAdjustment::val_changed (void)
689 {
690 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
691 _pref->set((int)this->get_value(), _doc, _node);
692 return;
693 }
695 /**
696 \brief Creates a Float Adjustment for a float parameter
698 Builds a hbox with a label and a float adjustment in it.
699 */
700 Gtk::Widget *
701 ParamFloat::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
702 {
703 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
705 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
706 label->show();
707 hbox->pack_start(*label, true, true);
709 ParamFloatAdjustment * fadjust = Gtk::manage(new ParamFloatAdjustment(this, doc, node));
710 Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 0.1, 1));
711 spin->show();
712 hbox->pack_start(*spin, false, false);
714 hbox->show();
716 return dynamic_cast<Gtk::Widget *>(hbox);
717 }
719 /**
720 \brief Creates a Int Adjustment for a int parameter
722 Builds a hbox with a label and a int adjustment in it.
723 */
724 Gtk::Widget *
725 ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
726 {
727 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
729 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
730 label->show();
731 hbox->pack_start(*label, true, true);
733 ParamIntAdjustment * fadjust = Gtk::manage(new ParamIntAdjustment(this, doc, node));
734 Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 1.0, 0));
735 spin->show();
736 hbox->pack_start(*spin, false, false);
738 hbox->show();
740 return dynamic_cast<Gtk::Widget *>(hbox);
741 }
743 /** \brief A check button which is Param aware. It works with the
744 parameter to change it's value as the check button changes
745 value. */
746 class ParamBoolCheckButton : public Gtk::CheckButton {
747 private:
748 /** \brief Param to change */
749 ParamBool * _pref;
750 SPDocument * _doc;
751 Inkscape::XML::Node * _node;
752 public:
753 /** \brief Initialize the check button
754 \param param Which parameter to adjust on changing the check button
756 This function sets the value of the checkbox to be that of the
757 parameter, and then sets up a callback to \c on_toggle.
758 */
759 ParamBoolCheckButton (ParamBool * param, SPDocument * doc, Inkscape::XML::Node * node) :
760 Gtk::CheckButton(), _pref(param), _doc(doc), _node(node) {
761 this->set_active(_pref->get(NULL, NULL) /**\todo fix */);
762 this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle));
763 return;
764 }
765 void on_toggle (void);
766 };
768 /**
769 \brief A function to respond to the check box changing
771 Adjusts the value of the preference to match that in the check box.
772 */
773 void
774 ParamBoolCheckButton::on_toggle (void)
775 {
776 _pref->set(this->get_active(), NULL /**\todo fix this */, NULL);
777 return;
778 }
780 /**
781 \brief Creates a bool check button for a bool parameter
783 Builds a hbox with a label and a check button in it.
784 */
785 Gtk::Widget *
786 ParamBool::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
787 {
788 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
790 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
791 label->show();
792 hbox->pack_start(*label, true, true);
794 ParamBoolCheckButton * checkbox = new ParamBoolCheckButton(this, doc, node);
795 checkbox->show();
796 hbox->pack_start(*checkbox, false, false);
798 hbox->show();
800 return dynamic_cast<Gtk::Widget *>(hbox);
801 }
803 /** \brief A special category of Gtk::Entry to handle string parameteres */
804 class ParamStringEntry : public Gtk::Entry {
805 private:
806 ParamString * _pref;
807 SPDocument * _doc;
808 Inkscape::XML::Node * _node;
809 public:
810 /** \brief Build a string preference for the given parameter
811 \param pref Where to get the string from, and where to put it
812 when it changes.
813 */
814 ParamStringEntry (ParamString * pref, SPDocument * doc, Inkscape::XML::Node * node) :
815 Gtk::Entry(), _pref(pref), _doc(doc), _node(node) {
816 if (_pref->get(NULL, NULL) != NULL)
817 this->set_text(Glib::ustring(_pref->get(NULL, NULL)));
818 this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text));
819 };
820 void changed_text (void);
821 };
823 /** \brief Respond to the text box changing
825 This function responds to the box changing by grabbing the value
826 from the text box and putting it in the parameter.
827 */
828 void
829 ParamStringEntry::changed_text (void)
830 {
831 Glib::ustring data = this->get_text();
832 _pref->set(data.c_str(), _doc, _node);
833 return;
834 }
836 /**
837 \brief Creates a text box for the string parameter
839 Builds a hbox with a label and a text box in it.
840 */
841 Gtk::Widget *
842 ParamString::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
843 {
844 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
846 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
847 label->show();
848 hbox->pack_start(*label, false, false);
850 ParamStringEntry * textbox = new ParamStringEntry(this, doc, node);
851 textbox->show();
852 hbox->pack_start(*textbox, true, true);
854 hbox->show();
856 return dynamic_cast<Gtk::Widget *>(hbox);
857 }
859 /** \brief Return 'true' or 'false' */
860 Glib::ustring *
861 ParamBool::string (void)
862 {
863 Glib::ustring * mystring;
865 if (_value)
866 mystring = new Glib::ustring("true");
867 else
868 mystring = new Glib::ustring("false");
870 return mystring;
871 }
873 /** \brief Return the value as a string */
874 Glib::ustring *
875 ParamInt::string (void)
876 {
877 char startstring[32];
878 sprintf(startstring, "%d", _value);
879 Glib::ustring * mystring = new Glib::ustring(startstring);
880 return mystring;
881 }
883 /** \brief Return the value as a string */
884 Glib::ustring *
885 ParamFloat::string (void)
886 {
887 char startstring[G_ASCII_DTOSTR_BUF_SIZE];
888 g_ascii_dtostr(startstring, G_ASCII_DTOSTR_BUF_SIZE, _value);
889 Glib::ustring * mystring = new Glib::ustring(startstring);
890 return mystring;
891 }
893 /** \brief Return the value as a string */
894 Glib::ustring *
895 ParamString::string (void)
896 {
897 Glib::ustring * mystring = new Glib::ustring("");
898 *mystring += "\"";
899 *mystring += _value;
900 *mystring += "\"";
901 return mystring;
902 }
904 /** \brief Create a label for the description */
905 Gtk::Widget *
906 ParamDescription::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
907 {
908 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_value)));
909 label->set_line_wrap();
910 label->show();
912 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
913 hbox->pack_start(*label, true, true, 5);
914 hbox->show();
916 return hbox;
917 }
919 /** \brief Initialize the object, to do that, copy the data. */
920 ParamDescription::ParamDescription (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
921 Parameter(name, guitext, desc, scope, ext), _value(NULL)
922 {
923 // printf("Building Description\n");
924 const char * defaultval = NULL;
925 if (sp_repr_children(xml) != NULL)
926 defaultval = sp_repr_children(xml)->content();
928 if (defaultval != NULL)
929 _value = g_strdup(defaultval);
931 return;
932 }
934 ParamEnum::ParamEnum (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
935 Parameter(name, guitext, desc, scope, ext), _current_choice(NULL)
936 {
937 return;
938 }
940 ParamEnum::~ParamEnum (void)
941 {
943 }
945 /** \brief Return the value as a string */
946 Glib::ustring *
947 ParamEnum::string (void)
948 {
949 Glib::ustring * mystring = new Glib::ustring("");
950 *mystring += "\"";
951 *mystring += this->get(NULL, NULL);
952 *mystring += "\"";
953 return mystring;
954 }
956 Gtk::Widget *
957 ParamEnum::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
958 {
959 return NULL;
960 }
962 const gchar *
963 ParamEnum::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
964 {
965 return NULL;
966 }
969 } /* namespace Extension */
970 } /* namespace Inkscape */
972 /*
973 Local Variables:
974 mode:c++
975 c-file-style:"stroustrup"
976 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
977 indent-tabs-mode:nil
978 fill-column:99
979 End:
980 */
981 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :