a821a626dfec18909790205504af6d35b1496974
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"
36 /** \brief The root directory in the preferences database for extension
37 related parameters. */
38 #define PREF_DIR "extensions"
40 namespace Inkscape {
41 namespace Extension {
43 /** \brief A description parameter */
44 class ParamDescription : public Parameter {
45 private:
46 /** \brief Internal value. */
47 gchar * _value;
48 public:
49 ParamDescription(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
50 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
51 };
53 /** \brief A boolean parameter */
54 class ParamBool : public Parameter {
55 private:
56 /** \brief Internal value. */
57 bool _value;
58 public:
59 ParamBool(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
60 /** \brief Returns \c _value */
61 bool get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
62 bool set (bool in, SPDocument * doc, Inkscape::XML::Node * node);
63 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
64 Glib::ustring * string (void);
65 };
67 /** \brief Use the superclass' allocator and set the \c _value */
68 ParamBool::ParamBool (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
69 Parameter(name, guitext, desc, scope, ext), _value(false)
70 {
71 const char * defaultval = NULL;
72 if (sp_repr_children(xml) != NULL)
73 defaultval = sp_repr_children(xml)->content();
75 if (defaultval != NULL && (!strcmp(defaultval, "TRUE") || !strcmp(defaultval, "true") || !strcmp(defaultval, "1"))) {
76 _value = true;
77 } else {
78 _value = false;
79 }
81 gchar * pref_name = this->pref_name();
82 _value = (bool)prefs_get_int_attribute(PREF_DIR, pref_name, _value);
83 g_free(pref_name);
85 return;
86 }
88 class ParamInt : public Parameter {
89 private:
90 /** \brief Internal value. */
91 int _value;
92 int _min;
93 int _max;
94 public:
95 ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
96 /** \brief Returns \c _value */
97 int get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
98 int set (int in, SPDocument * doc, Inkscape::XML::Node * node);
99 int max (void) { return _max; }
100 int min (void) { return _min; }
101 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
102 Glib::ustring * string (void);
103 };
105 /** \brief Use the superclass' allocator and set the \c _value */
106 ParamInt::ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
107 Parameter(name, guitext, desc, scope, ext), _value(0), _min(0), _max(10)
108 {
109 const char * defaultval = NULL;
110 if (sp_repr_children(xml) != NULL)
111 defaultval = sp_repr_children(xml)->content();
112 if (defaultval != NULL) {
113 _value = atoi(defaultval);
114 }
116 const char * maxval = xml->attribute("max");
117 if (maxval != NULL)
118 _max = atoi(maxval);
120 const char * minval = xml->attribute("min");
121 if (minval != NULL)
122 _min = atoi(minval);
124 /* We're handling this by just killing both values */
125 if (_max < _min) {
126 _max = 10;
127 _min = 0;
128 }
130 gchar * pref_name = this->pref_name();
131 _value = prefs_get_int_attribute(PREF_DIR, pref_name, _value);
132 g_free(pref_name);
134 // std::cout << "New Int:: value: " << _value << " max: " << _max << " min: " << _min << std::endl;
136 if (_value > _max) _value = _max;
137 if (_value < _min) _value = _min;
139 return;
140 }
142 class ParamFloat : public Parameter {
143 private:
144 /** \brief Internal value. */
145 float _value;
146 float _min;
147 float _max;
148 public:
149 ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
150 /** \brief Returns \c _value */
151 float get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
152 float set (float in, SPDocument * doc, Inkscape::XML::Node * node);
153 float max (void) { return _max; }
154 float min (void) { return _min; }
155 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
156 Glib::ustring * string (void);
157 };
159 /** \brief Use the superclass' allocator and set the \c _value */
160 ParamFloat::ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
161 Parameter(name, guitext, desc, scope, ext), _value(0.0), _min(0.0), _max(10.0)
162 {
163 const char * defaultval = NULL;
164 if (sp_repr_children(xml) != NULL)
165 defaultval = sp_repr_children(xml)->content();
166 if (defaultval != NULL) {
167 _value = atof(defaultval);
168 }
170 const char * maxval = xml->attribute("max");
171 if (maxval != NULL)
172 _max = atof(maxval);
174 const char * minval = xml->attribute("min");
175 if (minval != NULL)
176 _min = atof(minval);
178 /* We're handling this by just killing both values */
179 if (_max < _min) {
180 _max = 10.0;
181 _min = 0.0;
182 }
184 gchar * pref_name = this->pref_name();
185 _value = prefs_get_double_attribute(PREF_DIR, pref_name, _value);
186 g_free(pref_name);
188 // std::cout << "New Float:: value: " << _value << " max: " << _max << " min: " << _min << std::endl;
190 if (_value > _max) _value = _max;
191 if (_value < _min) _value = _min;
193 return;
194 }
196 class ParamString : public Parameter {
197 private:
198 /** \brief Internal value. This should point to a string that has
199 been allocated in memory. And should be free'd. */
200 gchar * _value;
201 public:
202 ParamString(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
203 ~ParamString(void);
204 /** \brief Returns \c _value, with a \i const to protect it. */
205 const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _value; }
206 const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
207 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
208 Glib::ustring * string (void);
209 };
211 class ParamEnum : public Parameter {
212 private:
213 class Choice {
214 public:
215 gchar * _gui_name;
216 gchar * _value;
217 Choice(gchar * gui_name, gchar * value) : _gui_name(NULL), _value(NULL) {
218 if (gui_name != NULL)
219 _gui_name = g_strdup(_(gui_name));
220 if (value != NULL)
221 _value = g_strdup(value);
222 return;
223 };
224 ~Choice (void) {
225 g_free(_gui_name);
226 g_free(_value);
227 };
228 }; /* class Choice */
229 /** \brief Internal value. This should point to a string that has
230 been allocated in memory. And should be free'd. */
231 Choice * _current_choice;
232 typedef std::list<Choice *> choice_list_t;
233 choice_list_t _choice_list;
234 public:
235 ParamEnum(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
236 ~ParamEnum(void);
237 /** \brief Returns \c _value, with a \i const to protect it. */
238 const gchar * get (const SPDocument * doc, const Inkscape::XML::Node * node) { return _current_choice != NULL ? _current_choice->_value : NULL; }
239 const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node);
240 Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node);
241 Glib::ustring * string (void);
242 }; /* class ParamEnum */
245 /**
246 \return None
247 \brief This function creates a parameter that can be used later. This
248 is typically done in the creation of the extension and defined
249 in the XML file describing the extension (it's private so people
250 have to use the system) :)
251 \param in_repr The XML describing the parameter
253 This function first grabs all of the data out of the Repr and puts
254 it into local variables. Actually, these are just pointers, and the
255 data is not duplicated so we need to be careful with it. If there
256 isn't a name or a type in the XML, then no parameter is created as
257 the function just returns.
259 From this point on, we're pretty committed as we've allocated an
260 object and we're starting to fill it. The name is set first, and
261 is created with a strdup to actually allocate memory for it. Then
262 there is a case statement (roughly because strcmp requires 'ifs')
263 based on what type of parameter this is. Depending which type it
264 is, the value is interpreted differently, but they are relatively
265 straight forward. In all cases the value is set to the default
266 value from the XML and the type is set to the interpreted type.
267 */
268 Parameter *
269 Parameter::make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext)
270 {
271 const char * name;
272 const char * type;
273 const char * guitext;
274 const char * desc;
275 const char * scope_str;
276 Parameter::_scope_t scope = Parameter::SCOPE_USER;
278 name = in_repr->attribute("name");
279 type = in_repr->attribute("type");
280 guitext = in_repr->attribute("gui-text");
281 if (guitext == NULL)
282 guitext = in_repr->attribute("_gui-text");
283 desc = in_repr->attribute("gui-description");
284 if (desc == NULL)
285 desc = in_repr->attribute("_gui-description");
286 scope_str = in_repr->attribute("scope");
288 /* In this case we just don't have enough information */
289 if (name == NULL || type == NULL) {
290 return NULL;
291 }
293 if (scope_str != NULL) {
294 if (!strcmp(scope_str, "user")) {
295 scope = Parameter::SCOPE_USER;
296 } else if (!strcmp(scope_str, "document")) {
297 scope = Parameter::SCOPE_DOCUMENT;
298 } else if (!strcmp(scope_str, "node")) {
299 scope = Parameter::SCOPE_NODE;
300 }
301 }
303 Parameter * param = NULL;
304 if (!strcmp(type, "boolean")) {
305 param = new ParamBool(name, guitext, desc, scope, in_ext, in_repr);
306 } else if (!strcmp(type, "int")) {
307 param = new ParamInt(name, guitext, desc, scope, in_ext, in_repr);
308 } else if (!strcmp(type, "float")) {
309 param = new ParamFloat(name, guitext, desc, scope, in_ext, in_repr);
310 } else if (!strcmp(type, "string")) {
311 param = new ParamString(name, guitext, desc, scope, in_ext, in_repr);
312 } else if (!strcmp(type, "description")) {
313 param = new ParamDescription(name, guitext, desc, scope, in_ext, in_repr);
314 } else if (!strcmp(type, "enum")) {
315 param = new ParamEnum(name, guitext, desc, scope, in_ext, in_repr);
316 } else if (!strcmp(type, "notebook")) {
317 param = new ParamNotebook(name, guitext, desc, scope, in_ext, in_repr);
318 }
320 /* Note: param could equal NULL */
321 return param;
322 }
324 /** \brief A function to set the \c _value
325 \param in The value to set to
326 \param doc A document that should be used to set the value.
327 \param node The node where the value may be placed
329 This function sets the internal value, but it also sets the value
330 in the preferences structure. To put it in the right place, \c PREF_DIR
331 and \c pref_name() are used.
332 */
333 bool
334 ParamBool::set (bool in, SPDocument * doc, Inkscape::XML::Node * node)
335 {
336 _value = in;
338 gchar * prefname = this->pref_name();
339 prefs_set_int_attribute(PREF_DIR, prefname, _value == true ? 1 : 0);
340 g_free(prefname);
342 return _value;
343 }
345 /** \brief A function to set the \c _value
346 \param in The value to set to
347 \param doc A document that should be used to set the value.
348 \param node The node where the value may be placed
350 This function sets the internal value, but it also sets the value
351 in the preferences structure. To put it in the right place, \c PREF_DIR
352 and \c pref_name() are used.
353 */
354 int
355 ParamInt::set (int in, SPDocument * doc, Inkscape::XML::Node * node)
356 {
357 _value = in;
358 if (_value > _max) _value = _max;
359 if (_value < _min) _value = _min;
361 gchar * prefname = this->pref_name();
362 prefs_set_int_attribute(PREF_DIR, prefname, _value);
363 g_free(prefname);
365 return _value;
366 }
368 /** \brief A function to set the \c _value
369 \param in The value to set to
370 \param doc A document that should be used to set the value.
371 \param node The node where the value may be placed
373 This function sets the internal value, but it also sets the value
374 in the preferences structure. To put it in the right place, \c PREF_DIR
375 and \c pref_name() are used.
376 */
377 float
378 ParamFloat::set (float in, SPDocument * doc, Inkscape::XML::Node * node)
379 {
380 _value = in;
381 if (_value > _max) _value = _max;
382 if (_value < _min) _value = _min;
384 gchar * prefname = this->pref_name();
385 prefs_set_double_attribute(PREF_DIR, prefname, _value);
386 g_free(prefname);
388 return _value;
389 }
391 /** \brief A function to set the \c _value
392 \param in The value to set to
393 \param doc A document that should be used to set the value.
394 \param node The node where the value may be placed
396 This function sets the internal value, but it also sets the value
397 in the preferences structure. To put it in the right place, \c PREF_DIR
398 and \c pref_name() are used.
400 To copy the data into _value the old memory must be free'd first.
401 It is important to note that \c g_free handles \c NULL just fine. Then
402 the passed in value is duplicated using \c g_strdup().
403 */
404 const gchar *
405 ParamString::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
406 {
407 if (in == NULL) return NULL; /* Can't have NULL string */
409 if (_value != NULL)
410 g_free(_value);
411 _value = g_strdup(in);
413 gchar * prefname = this->pref_name();
414 prefs_set_string_attribute(PREF_DIR, prefname, _value);
415 g_free(prefname);
417 return _value;
418 }
420 /** \brief Wrapper to cast to the object and use it's function. */
421 bool
422 Parameter::get_bool (const SPDocument * doc, const Inkscape::XML::Node * node)
423 {
424 ParamBool * boolpntr;
425 boolpntr = dynamic_cast<ParamBool *>(this);
426 if (boolpntr == NULL)
427 throw Extension::param_wrong_type();
428 return boolpntr->get(doc, node);
429 }
431 /** \brief Wrapper to cast to the object and use it's function. */
432 int
433 Parameter::get_int (const SPDocument * doc, const Inkscape::XML::Node * node)
434 {
435 ParamInt * intpntr;
436 intpntr = dynamic_cast<ParamInt *>(this);
437 if (intpntr == NULL)
438 throw Extension::param_wrong_type();
439 return intpntr->get(doc, node);
440 }
442 /** \brief Wrapper to cast to the object and use it's function. */
443 float
444 Parameter::get_float (const SPDocument * doc, const Inkscape::XML::Node * node)
445 {
446 ParamFloat * floatpntr;
447 floatpntr = dynamic_cast<ParamFloat *>(this);
448 if (floatpntr == NULL)
449 throw Extension::param_wrong_type();
450 return floatpntr->get(doc, node);
451 }
453 /** \brief Wrapper to cast to the object and use it's function. */
454 const gchar *
455 Parameter::get_string (const SPDocument * doc, const Inkscape::XML::Node * node)
456 {
457 ParamString * stringpntr;
458 stringpntr = dynamic_cast<ParamString *>(this);
459 if (stringpntr == NULL)
460 throw Extension::param_wrong_type();
461 return stringpntr->get(doc, node);
462 }
464 /** \brief Wrapper to cast to the object and use it's function. */
465 bool
466 Parameter::set_bool (bool in, SPDocument * doc, Inkscape::XML::Node * node)
467 {
468 ParamBool * boolpntr;
469 boolpntr = dynamic_cast<ParamBool *>(this);
470 if (boolpntr == NULL)
471 throw Extension::param_wrong_type();
472 return boolpntr->set(in, doc, node);
473 }
475 /** \brief Wrapper to cast to the object and use it's function. */
476 int
477 Parameter::set_int (int in, SPDocument * doc, Inkscape::XML::Node * node)
478 {
479 ParamInt * intpntr;
480 intpntr = dynamic_cast<ParamInt *>(this);
481 if (intpntr == NULL)
482 throw Extension::param_wrong_type();
483 return intpntr->set(in, doc, node);
484 }
486 /** \brief Wrapper to cast to the object and use it's function. */
487 float
488 Parameter::set_float (float in, SPDocument * doc, Inkscape::XML::Node * node)
489 {
490 ParamFloat * floatpntr;
491 floatpntr = dynamic_cast<ParamFloat *>(this);
492 if (floatpntr == NULL)
493 throw Extension::param_wrong_type();
494 return floatpntr->set(in, doc, node);
495 }
497 /** \brief Wrapper to cast to the object and use it's function. */
498 const gchar *
499 Parameter::set_string (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
500 {
501 ParamString * stringpntr;
502 stringpntr = dynamic_cast<ParamString *>(this);
503 if (stringpntr == NULL)
504 throw Extension::param_wrong_type();
505 return stringpntr->set(in, doc, node);
506 }
508 /** \brief Initialize the object, to do that, copy the data. */
509 ParamString::ParamString (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
510 Parameter(name, guitext, desc, scope, ext), _value(NULL)
511 {
512 const char * defaultval = NULL;
513 if (sp_repr_children(xml) != NULL)
514 defaultval = sp_repr_children(xml)->content();
516 gchar * pref_name = this->pref_name();
517 const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
518 g_free(pref_name);
520 if (paramval != NULL)
521 defaultval = paramval;
522 if (defaultval != NULL)
523 _value = g_strdup(defaultval);
525 return;
526 }
528 /** \brief Free the allocated data. */
529 ParamString::~ParamString(void)
530 {
531 g_free(_value);
532 }
534 /** \brief Oop, now that we need a parameter, we need it's name. */
535 Parameter::Parameter (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext) :
536 extension(ext), _name(NULL), _desc(NULL), _scope(scope), _text(NULL)
537 {
538 if (name != NULL)
539 _name = g_strdup(name);
540 if (desc != NULL) {
541 _desc = g_strdup(desc);
542 // printf("Adding description: '%s' on '%s'\n", _desc, _name);
543 }
546 if (guitext != NULL)
547 _text = g_strdup(guitext);
548 else
549 _text = g_strdup(name);
551 return;
552 }
554 /** \brief Just free the allocated name. */
555 Parameter::~Parameter (void)
556 {
557 g_free(_name);
558 g_free(_text);
559 }
561 /** \brief Build the name to write the parameter from the extension's
562 ID and the name of this parameter. */
563 gchar *
564 Parameter::pref_name (void)
565 {
566 return g_strdup_printf("%s.%s", extension->get_id(), _name);
567 }
569 Inkscape::XML::Node *
570 Parameter::find_child (Inkscape::XML::Node * adult)
571 {
572 return sp_repr_lookup_child(adult, "name", _name);
573 }
575 Inkscape::XML::Node *
576 Parameter::new_child (Inkscape::XML::Node * parent)
577 {
578 Inkscape::XML::Node * retval;
579 retval = sp_repr_new("inkscape:extension-param");
580 retval->setAttribute("name", _name);
582 parent->appendChild(retval);
583 return retval;
584 }
586 Inkscape::XML::Node *
587 Parameter::document_param_node (SPDocument * doc)
588 {
589 Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc));
590 Inkscape::XML::Node * params = NULL;
592 GQuark const name_quark = g_quark_from_string("inkscape:extension-params");
594 for (Inkscape::XML::Node * child = defs->firstChild();
595 child != NULL;
596 child = child->next()) {
597 if ((GQuark)child->code() == name_quark &&
598 !strcmp(child->attribute("extension"), extension->get_id())) {
599 params = child;
600 break;
601 }
602 }
604 if (params == NULL) {
605 params = sp_repr_new("inkscape:extension-param");
606 params->setAttribute("extension", extension->get_id());
607 defs->appendChild(params);
608 }
610 return params;
611 }
613 /** \brief Basically, if there is no widget pass a NULL. */
614 Gtk::Widget *
615 Parameter::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
616 {
617 return NULL;
618 }
620 /** \brief If I'm not sure which it is, just don't return a value. */
621 Glib::ustring *
622 Parameter::string (void)
623 {
624 Glib::ustring * mystring = new Glib::ustring("");
625 return mystring;
626 }
628 /** \brief A class to make an adjustment that uses Extension params */
629 class ParamFloatAdjustment : public Gtk::Adjustment {
630 /** The parameter to adjust */
631 ParamFloat * _pref;
632 SPDocument * _doc;
633 Inkscape::XML::Node * _node;
634 public:
635 /** \brief Make the adjustment using an extension and the string
636 describing the parameter. */
637 ParamFloatAdjustment (ParamFloat * param, SPDocument * doc, Inkscape::XML::Node * node) :
638 Gtk::Adjustment(0.0, param->min(), param->max(), 0.1), _pref(param), _doc(doc), _node(node) {
639 this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
640 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed));
641 return;
642 };
644 void val_changed (void);
645 }; /* class ParamFloatAdjustment */
647 /** \brief A function to respond to the value_changed signal from the
648 adjustment.
650 This function just grabs the value from the adjustment and writes
651 it to the parameter. Very simple, but yet beautiful.
652 */
653 void
654 ParamFloatAdjustment::val_changed (void)
655 {
656 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
657 _pref->set(this->get_value(), _doc, _node);
658 return;
659 }
661 /** \brief A class to make an adjustment that uses Extension params */
662 class ParamIntAdjustment : public Gtk::Adjustment {
663 /** The parameter to adjust */
664 ParamInt * _pref;
665 SPDocument * _doc;
666 Inkscape::XML::Node * _node;
667 public:
668 /** \brief Make the adjustment using an extension and the string
669 describing the parameter. */
670 ParamIntAdjustment (ParamInt * param, SPDocument * doc, Inkscape::XML::Node * node) :
671 Gtk::Adjustment(0.0, param->min(), param->max(), 1.0), _pref(param), _doc(doc), _node(node) {
672 this->set_value(_pref->get(NULL, NULL) /* \todo fix */);
673 this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed));
674 return;
675 };
677 void val_changed (void);
678 }; /* class ParamIntAdjustment */
680 /** \brief A function to respond to the value_changed signal from the
681 adjustment.
683 This function just grabs the value from the adjustment and writes
684 it to the parameter. Very simple, but yet beautiful.
685 */
686 void
687 ParamIntAdjustment::val_changed (void)
688 {
689 // std::cout << "Value Changed to: " << this->get_value() << std::endl;
690 _pref->set((int)this->get_value(), _doc, _node);
691 return;
692 }
694 /**
695 \brief Creates a Float Adjustment for a float parameter
697 Builds a hbox with a label and a float adjustment in it.
698 */
699 Gtk::Widget *
700 ParamFloat::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
701 {
702 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
704 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
705 label->show();
706 hbox->pack_start(*label, true, true);
708 ParamFloatAdjustment * fadjust = Gtk::manage(new ParamFloatAdjustment(this, doc, node));
709 Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 0.1, 1));
710 spin->show();
711 hbox->pack_start(*spin, false, false);
713 hbox->show();
715 return dynamic_cast<Gtk::Widget *>(hbox);
716 }
718 /**
719 \brief Creates a Int Adjustment for a int parameter
721 Builds a hbox with a label and a int adjustment in it.
722 */
723 Gtk::Widget *
724 ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
725 {
726 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
728 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
729 label->show();
730 hbox->pack_start(*label, true, true);
732 ParamIntAdjustment * fadjust = Gtk::manage(new ParamIntAdjustment(this, doc, node));
733 Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 1.0, 0));
734 spin->show();
735 hbox->pack_start(*spin, false, false);
737 hbox->show();
739 return dynamic_cast<Gtk::Widget *>(hbox);
740 }
742 /** \brief A check button which is Param aware. It works with the
743 parameter to change it's value as the check button changes
744 value. */
745 class ParamBoolCheckButton : public Gtk::CheckButton {
746 private:
747 /** \brief Param to change */
748 ParamBool * _pref;
749 SPDocument * _doc;
750 Inkscape::XML::Node * _node;
751 public:
752 /** \brief Initialize the check button
753 \param param Which parameter to adjust on changing the check button
755 This function sets the value of the checkbox to be that of the
756 parameter, and then sets up a callback to \c on_toggle.
757 */
758 ParamBoolCheckButton (ParamBool * param, SPDocument * doc, Inkscape::XML::Node * node) :
759 Gtk::CheckButton(), _pref(param), _doc(doc), _node(node) {
760 this->set_active(_pref->get(NULL, NULL) /**\todo fix */);
761 this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle));
762 return;
763 }
764 void on_toggle (void);
765 };
767 /**
768 \brief A function to respond to the check box changing
770 Adjusts the value of the preference to match that in the check box.
771 */
772 void
773 ParamBoolCheckButton::on_toggle (void)
774 {
775 _pref->set(this->get_active(), NULL /**\todo fix this */, NULL);
776 return;
777 }
779 /**
780 \brief Creates a bool check button for a bool parameter
782 Builds a hbox with a label and a check button in it.
783 */
784 Gtk::Widget *
785 ParamBool::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
786 {
787 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
789 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
790 label->show();
791 hbox->pack_start(*label, true, true);
793 ParamBoolCheckButton * checkbox = new ParamBoolCheckButton(this, doc, node);
794 checkbox->show();
795 hbox->pack_start(*checkbox, false, false);
797 hbox->show();
799 return dynamic_cast<Gtk::Widget *>(hbox);
800 }
802 /** \brief A special category of Gtk::Entry to handle string parameteres */
803 class ParamStringEntry : public Gtk::Entry {
804 private:
805 ParamString * _pref;
806 SPDocument * _doc;
807 Inkscape::XML::Node * _node;
808 public:
809 /** \brief Build a string preference for the given parameter
810 \param pref Where to get the string from, and where to put it
811 when it changes.
812 */
813 ParamStringEntry (ParamString * pref, SPDocument * doc, Inkscape::XML::Node * node) :
814 Gtk::Entry(), _pref(pref), _doc(doc), _node(node) {
815 if (_pref->get(NULL, NULL) != NULL)
816 this->set_text(Glib::ustring(_pref->get(NULL, NULL)));
817 this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text));
818 };
819 void changed_text (void);
820 };
822 /** \brief Respond to the text box changing
824 This function responds to the box changing by grabbing the value
825 from the text box and putting it in the parameter.
826 */
827 void
828 ParamStringEntry::changed_text (void)
829 {
830 Glib::ustring data = this->get_text();
831 _pref->set(data.c_str(), _doc, _node);
832 return;
833 }
835 /**
836 \brief Creates a text box for the string parameter
838 Builds a hbox with a label and a text box in it.
839 */
840 Gtk::Widget *
841 ParamString::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
842 {
843 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
845 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
846 label->show();
847 hbox->pack_start(*label, false, false);
849 ParamStringEntry * textbox = new ParamStringEntry(this, doc, node);
850 textbox->show();
851 hbox->pack_start(*textbox, true, true);
853 hbox->show();
855 return dynamic_cast<Gtk::Widget *>(hbox);
856 }
858 /** \brief Return 'true' or 'false' */
859 Glib::ustring *
860 ParamBool::string (void)
861 {
862 Glib::ustring * mystring;
864 if (_value)
865 mystring = new Glib::ustring("true");
866 else
867 mystring = new Glib::ustring("false");
869 return mystring;
870 }
872 /** \brief Return the value as a string */
873 Glib::ustring *
874 ParamInt::string (void)
875 {
876 char startstring[32];
877 sprintf(startstring, "%d", _value);
878 Glib::ustring * mystring = new Glib::ustring(startstring);
879 return mystring;
880 }
882 /** \brief Return the value as a string */
883 Glib::ustring *
884 ParamFloat::string (void)
885 {
886 char startstring[G_ASCII_DTOSTR_BUF_SIZE];
887 g_ascii_dtostr(startstring, G_ASCII_DTOSTR_BUF_SIZE, _value);
888 Glib::ustring * mystring = new Glib::ustring(startstring);
889 return mystring;
890 }
892 /** \brief Return the value as a string */
893 Glib::ustring *
894 ParamString::string (void)
895 {
896 Glib::ustring * mystring = new Glib::ustring("");
897 *mystring += "\"";
898 *mystring += _value;
899 *mystring += "\"";
900 return mystring;
901 }
903 /** \brief Create a label for the description */
904 Gtk::Widget *
905 ParamDescription::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
906 {
907 Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_value)));
908 label->set_line_wrap();
909 label->show();
911 Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
912 hbox->pack_start(*label, true, true, 5);
913 hbox->show();
915 return hbox;
916 }
918 /** \brief Initialize the object, to do that, copy the data. */
919 ParamDescription::ParamDescription (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
920 Parameter(name, guitext, desc, scope, ext), _value(NULL)
921 {
922 // printf("Building Description\n");
923 const char * defaultval = NULL;
924 if (sp_repr_children(xml) != NULL)
925 defaultval = sp_repr_children(xml)->content();
927 if (defaultval != NULL)
928 _value = g_strdup(defaultval);
930 return;
931 }
933 ParamEnum::ParamEnum (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
934 Parameter(name, guitext, desc, scope, ext), _current_choice(NULL)
935 {
936 return;
937 }
939 ParamEnum::~ParamEnum (void)
940 {
942 }
944 /** \brief Return the value as a string */
945 Glib::ustring *
946 ParamEnum::string (void)
947 {
948 Glib::ustring * mystring = new Glib::ustring("");
949 *mystring += "\"";
950 *mystring += this->get(NULL, NULL);
951 *mystring += "\"";
952 return mystring;
953 }
955 Gtk::Widget *
956 ParamEnum::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
957 {
958 return NULL;
959 }
961 const gchar *
962 ParamEnum::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
963 {
964 return NULL;
965 }
968 } /* namespace Extension */
969 } /* namespace Inkscape */
971 /*
972 Local Variables:
973 mode:c++
974 c-file-style:"stroustrup"
975 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
976 indent-tabs-mode:nil
977 fill-column:99
978 End:
979 */
980 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :