Code

r10817@tres: ted | 2006-01-29 15:45:22 -0800
[inkscape.git] / src / extension / parameter.cpp
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, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
44     /** \brief  Returns \c _value */
45     bool get (const Inkscape::XML::Document * doc) { return _value; }
46     bool set (bool in, Inkscape::XML::Document * doc);
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, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
53         Parameter(name, guitext, 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, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
80     /** \brief  Returns \c _value */
81     int get (const Inkscape::XML::Document * doc) { return _value; }
82     int set (int in, Inkscape::XML::Document * doc);
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, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
91         Parameter(name, guitext, 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;
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, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml);
134     /** \brief  Returns \c _value */
135     float get (const Inkscape::XML::Document * doc) { return _value; }
136     float set (float in, Inkscape::XML::Document * doc);
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, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
145         Parameter(name, guitext, ext), _value(0.0), _min(0.0), _max(10.0)
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;
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, 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) { return _value; }
190     const gchar * set (const gchar * in, Inkscape::XML::Document * doc);
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)
221     const char * name;
222     const char * type;
223     const char * guitext;
225     name = in_repr->attribute("name");
226     type = in_repr->attribute("type");
227     guitext = in_repr->attribute("gui-text");
228     if (guitext == NULL)
229         guitext = in_repr->attribute("_gui-text");
231     /* In this case we just don't have enough information */
232     if (name == NULL || type == NULL) {
233         return NULL;
234     }
236     Parameter * param = NULL;
237     if (!strcmp(type, "boolean")) {
238         param = new ParamBool(name, guitext, in_ext, in_repr);
239     } else if (!strcmp(type, "int")) { 
240         param = new ParamInt(name, guitext, in_ext, in_repr);
241     } else if (!strcmp(type, "float")) { 
242         param = new ParamFloat(name, guitext, in_ext, in_repr);
243     } else if (!strcmp(type, "string")) { 
244         param = new ParamString(name, guitext, in_ext, in_repr);
245     } 
247     /* Note: param could equal NULL */
248     return param;
251 /** \brief  A function to set the \c _value
252     \param  in   The value to set to
253     \param  doc  A document that should be used to set the value.
255     This function sets the internal value, but it also sets the value
256     in the preferences structure.  To put it in the right place, \c PREF_DIR
257     and \c pref_name() are used.
258 */
259 bool
260 ParamBool::set (bool in, Inkscape::XML::Document * doc)
262     _value = in;
264     gchar * prefname = this->pref_name();
265     prefs_set_int_attribute(PREF_DIR, prefname, _value == true ? 1 : 0);
266     g_free(prefname);
268     return _value;
271 /** \brief  A function to set the \c _value
272     \param  in   The value to set to
273     \param  doc  A document that should be used to set the value.
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 int
280 ParamInt::set (int in, Inkscape::XML::Document * doc)
282     _value = in;
283     if (_value > _max) _value = _max;
284     if (_value < _min) _value = _min;
286     gchar * prefname = this->pref_name();
287     prefs_set_int_attribute(PREF_DIR, prefname, _value);
288     g_free(prefname);
290     return _value;
293 /** \brief  A function to set the \c _value
294     \param  in   The value to set to
295     \param  doc  A document that should be used to set the value.
297     This function sets the internal value, but it also sets the value
298     in the preferences structure.  To put it in the right place, \c PREF_DIR
299     and \c pref_name() are used.
300 */
301 float
302 ParamFloat::set (float in, Inkscape::XML::Document * doc)
304     _value = in;
305     if (_value > _max) _value = _max;
306     if (_value < _min) _value = _min;
308     gchar * prefname = this->pref_name();
309     prefs_set_double_attribute(PREF_DIR, prefname, _value);
310     g_free(prefname);
312     return _value;
315 /** \brief  A function to set the \c _value
316     \param  in   The value to set to
317     \param  doc  A document that should be used to set the value.
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.
323     To copy the data into _value the old memory must be free'd first.
324     It is important to note that \c g_free handles \c NULL just fine.  Then
325     the passed in value is duplicated using \c g_strdup().
326 */
327 const gchar *
328 ParamString::set (const gchar * in, Inkscape::XML::Document * doc)
330     if (in == NULL) return NULL; /* Can't have NULL string */
332     if (_value != NULL)
333         g_free(_value);
334     _value = g_strdup(in);
336     gchar * prefname = this->pref_name();
337     prefs_set_string_attribute(PREF_DIR, prefname, _value);
338     g_free(prefname);
340     return _value;
343 /** \brief  Wrapper to cast to the object and use it's function.  */
344 bool
345 Parameter::get_bool (const Inkscape::XML::Document * doc)
347     ParamBool * boolpntr;
348     boolpntr = dynamic_cast<ParamBool *>(this);
349     if (boolpntr == NULL)
350         throw Extension::param_wrong_type();
351     return boolpntr->get(doc); 
354 /** \brief  Wrapper to cast to the object and use it's function.  */
355 int
356 Parameter::get_int (const Inkscape::XML::Document * doc)
358     ParamInt * intpntr;
359     intpntr = dynamic_cast<ParamInt *>(this);
360     if (intpntr == NULL)
361         throw Extension::param_wrong_type();
362     return intpntr->get(doc); 
365 /** \brief  Wrapper to cast to the object and use it's function.  */
366 float
367 Parameter::get_float (const Inkscape::XML::Document * doc)
369     ParamFloat * floatpntr;
370     floatpntr = dynamic_cast<ParamFloat *>(this);
371     if (floatpntr == NULL)
372         throw Extension::param_wrong_type();
373     return floatpntr->get(doc); 
376 /** \brief  Wrapper to cast to the object and use it's function.  */
377 const gchar *
378 Parameter::get_string (const Inkscape::XML::Document * doc)
380     ParamString * stringpntr;
381     stringpntr = dynamic_cast<ParamString *>(this);
382     if (stringpntr == NULL)
383         throw Extension::param_wrong_type();
384     return stringpntr->get(doc); 
387 /** \brief  Wrapper to cast to the object and use it's function.  */
388 bool
389 Parameter::set_bool (bool in, Inkscape::XML::Document * doc)
391     ParamBool * boolpntr;
392     boolpntr = dynamic_cast<ParamBool *>(this);
393     if (boolpntr == NULL)
394         throw Extension::param_wrong_type();
395     return boolpntr->set(in, doc); 
398 /** \brief  Wrapper to cast to the object and use it's function.  */
399 int
400 Parameter::set_int (int in, Inkscape::XML::Document * doc)
402     ParamInt * intpntr;
403     intpntr = dynamic_cast<ParamInt *>(this);
404     if (intpntr == NULL)
405         throw Extension::param_wrong_type();
406     return intpntr->set(in, doc); 
409 /** \brief  Wrapper to cast to the object and use it's function.  */
410 float
411 Parameter::set_float (float in, Inkscape::XML::Document * doc)
413     ParamFloat * floatpntr;
414     floatpntr = dynamic_cast<ParamFloat *>(this);
415     if (floatpntr == NULL)
416         throw Extension::param_wrong_type();
417     return floatpntr->set(in, doc); 
420 /** \brief  Wrapper to cast to the object and use it's function.  */
421 const gchar *
422 Parameter::set_string (const gchar * in, Inkscape::XML::Document * doc)
424     ParamString * stringpntr;
425     stringpntr = dynamic_cast<ParamString *>(this);
426     if (stringpntr == NULL)
427         throw Extension::param_wrong_type();
428     return stringpntr->set(in, doc); 
431 /** \brief  Initialize the object, to do that, copy the data. */
432 ParamString::ParamString (const gchar * name, const gchar * guitext, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
433     Parameter(name, guitext, ext), _value(NULL)
435     const char * defaultval = NULL;
436     if (sp_repr_children(xml) != NULL)
437         defaultval = sp_repr_children(xml)->content();
439     gchar * pref_name = this->pref_name();
440     const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
441     g_free(pref_name);
443     if (paramval != NULL)
444         defaultval = paramval;
445     if (defaultval != NULL)
446         _value = g_strdup(defaultval);
448     return;
451 /** \brief  Free the allocated data. */
452 ParamString::~ParamString(void)
454     g_free(_value);
457 /** \brief  Oop, now that we need a parameter, we need it's name.  */
458 Parameter::Parameter (const gchar * name, const gchar * guitext, Inkscape::Extension::Extension * ext) :
459     extension(ext), _name(NULL), _text(NULL)
461     _name = g_strdup(name);
462     if (guitext != NULL)
463         _text = g_strdup(guitext);
464     else
465         _text = g_strdup(name);
468 /** \brief  Just free the allocated name. */
469 Parameter::~Parameter (void)
471     g_free(_name);
472     g_free(_text);
475 /** \brief  Build the name to write the parameter from the extension's
476             ID and the name of this parameter. */
477 gchar *
478 Parameter::pref_name (void)
480     return g_strdup_printf("%s.%s", extension->get_id(), _name);
483 /** \brief  Basically, if there is no widget pass a NULL. */
484 Gtk::Widget *
485 Parameter::get_widget (void)
487     return NULL;
490 /** \brief  If I'm not sure which it is, just don't return a value. */
491 Glib::ustring *
492 Parameter::string (void)
494     Glib::ustring * mystring = new Glib::ustring("");
495     return mystring;
498 /** \brief  A class to make an adjustment that uses Extension params */
499 class ParamFloatAdjustment : public Gtk::Adjustment {
500     /** The parameter to adjust */
501     ParamFloat * _pref;
502 public:
503     /** \brief  Make the adjustment using an extension and the string
504                 describing the parameter. */
505     ParamFloatAdjustment (ParamFloat * param) :
506             Gtk::Adjustment(0.0, param->min(), param->max(), 0.1), _pref(param) {
507         this->set_value(_pref->get(NULL) /* \todo fix */); 
508         this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed));
509         return;
510     };
512     void val_changed (void);
513 }; /* class ParamFloatAdjustment */
515 /** \brief  A function to respond to the value_changed signal from the
516             adjustment.
518     This function just grabs the value from the adjustment and writes
519     it to the parameter.  Very simple, but yet beautiful.
520 */
521 void
522 ParamFloatAdjustment::val_changed (void)
524     // std::cout << "Value Changed to: " << this->get_value() << std::endl;
525     _pref->set(this->get_value(), NULL /* \todo fix */);
526     return;
529 /** \brief  A class to make an adjustment that uses Extension params */
530 class ParamIntAdjustment : public Gtk::Adjustment {
531     /** The parameter to adjust */
532     ParamInt * _pref;
533 public:
534     /** \brief  Make the adjustment using an extension and the string
535                 describing the parameter. */
536     ParamIntAdjustment (ParamInt * param) :
537             Gtk::Adjustment(0.0, param->min(), param->max(), 1.0), _pref(param) {
538         this->set_value(_pref->get(NULL) /* \todo fix */); 
539         this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed));
540         return;
541     };
543     void val_changed (void);
544 }; /* class ParamIntAdjustment */
546 /** \brief  A function to respond to the value_changed signal from the
547             adjustment.
549     This function just grabs the value from the adjustment and writes
550     it to the parameter.  Very simple, but yet beautiful.
551 */
552 void
553 ParamIntAdjustment::val_changed (void)
555     // std::cout << "Value Changed to: " << this->get_value() << std::endl;
556     _pref->set((int)this->get_value(), NULL /* \todo fix */);
557     return;
560 /**
561     \brief  Creates a Float Adjustment for a float parameter
562     
563     Builds a hbox with a label and a float adjustment in it.
564 */
565 Gtk::Widget *
566 ParamFloat::get_widget (void)
568     Gtk::HBox * hbox = new Gtk::HBox();
570     Gtk::Label * label = new Gtk::Label(_(_text), Gtk::ALIGN_LEFT);
571     label->show();
572     hbox->pack_start(*label, true, true);
574     ParamFloatAdjustment * fadjust = new ParamFloatAdjustment(this);
575     Gtk::SpinButton * spin = new Gtk::SpinButton(*fadjust, 0.1, 1);
576     spin->show();
577     hbox->pack_start(*spin, false, false);
579     hbox->show();
581     return dynamic_cast<Gtk::Widget *>(hbox);
584 /**
585     \brief  Creates a Int Adjustment for a int parameter
586     
587     Builds a hbox with a label and a int adjustment in it.
588 */
589 Gtk::Widget *
590 ParamInt::get_widget (void)
592     Gtk::HBox * hbox = new Gtk::HBox();
594     Gtk::Label * label = new Gtk::Label(_(_text), Gtk::ALIGN_LEFT);
595     label->show();
596     hbox->pack_start(*label, true, true);
598     ParamIntAdjustment * fadjust = new ParamIntAdjustment(this);
599     Gtk::SpinButton * spin = new Gtk::SpinButton(*fadjust, 1.0, 0);
600     spin->show();
601     hbox->pack_start(*spin, false, false);
603     hbox->show();
605     return dynamic_cast<Gtk::Widget *>(hbox);
608 /** \brief  A check button which is Param aware.  It works with the
609             parameter to change it's value as the check button changes
610             value. */
611 class ParamBoolCheckButton : public Gtk::CheckButton {
612 private:
613     /** \brief  Param to change */
614     ParamBool * _pref;
615 public:
616     /** \brief  Initialize the check button
617         \param  param  Which parameter to adjust on changing the check button
618         
619         This function sets the value of the checkbox to be that of the
620         parameter, and then sets up a callback to \c on_toggle.
621     */
622     ParamBoolCheckButton (ParamBool * param) :
623             Gtk::CheckButton(), _pref(param) {
624         this->set_active(_pref->get(NULL) /**\todo fix */);
625         this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle));
626         return;
627     }
628     void on_toggle (void);
629 };
631 /**
632     \brief  A function to respond to the check box changing
634     Adjusts the value of the preference to match that in the check box.
635 */
636 void
637 ParamBoolCheckButton::on_toggle (void)
639     _pref->set(this->get_active(), NULL /**\todo fix this */);
640     return;
643 /**
644     \brief  Creates a bool check button for a bool parameter
645     
646     Builds a hbox with a label and a check button in it.
647 */
648 Gtk::Widget *
649 ParamBool::get_widget (void)
651     Gtk::HBox * hbox = new Gtk::HBox();
653     Gtk::Label * label = new Gtk::Label(_(_text), Gtk::ALIGN_LEFT);
654     label->show();
655     hbox->pack_start(*label, true, true);
657     ParamBoolCheckButton * checkbox = new ParamBoolCheckButton(this);
658     checkbox->show();
659     hbox->pack_start(*checkbox, false, false);
661     hbox->show();
663     return dynamic_cast<Gtk::Widget *>(hbox);
666 /** \brief  A special category of Gtk::Entry to handle string parameteres */
667 class ParamStringEntry : public Gtk::Entry {
668 private:
669     ParamString * _pref;
670 public:
671     /** \brief  Build a string preference for the given parameter
672         \param  pref  Where to get the string from, and where to put it
673                       when it changes.
674     */
675     ParamStringEntry (ParamString * pref) :
676         Gtk::Entry(), _pref(pref) {
677         if (_pref->get(NULL) != NULL)
678             this->set_text(Glib::ustring(_pref->get(NULL)));
679         this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text));
680     };
681     void changed_text (void);
682 };
684 /** \brief  Respond to the text box changing
686     This function responds to the box changing by grabbing the value
687     from the text box and putting it in the parameter.
688 */
689 void
690 ParamStringEntry::changed_text (void)
692     Glib::ustring data = this->get_text();
693     _pref->set(data.c_str(), NULL);
694     return;
697 /**
698     \brief  Creates a text box for the string parameter
699     
700     Builds a hbox with a label and a text box in it.
701 */
702 Gtk::Widget *
703 ParamString::get_widget (void)
705     Gtk::HBox * hbox = new Gtk::HBox();
707     Gtk::Label * label = new Gtk::Label(_(_text), Gtk::ALIGN_LEFT);
708     label->show();
709     hbox->pack_start(*label, true, true);
711     ParamStringEntry * textbox = new ParamStringEntry(this);
712     textbox->show();
713     hbox->pack_start(*textbox, false, false);
715     hbox->show();
717     return dynamic_cast<Gtk::Widget *>(hbox);
720 /** \brief  Return 'true' or 'false' */
721 Glib::ustring *
722 ParamBool::string (void)
724     Glib::ustring * mystring;
725     
726     if (_value) 
727         mystring = new Glib::ustring("true");
728     else
729         mystring = new Glib::ustring("false");
730     
731     return mystring;
734 /** \brief  Return the value as a string */
735 Glib::ustring *
736 ParamInt::string (void)
738     char startstring[32];
739     sprintf(startstring, "%d", _value);
740     Glib::ustring * mystring = new Glib::ustring(startstring);
741     return mystring;
744 /** \brief  Return the value as a string */
745 Glib::ustring *
746 ParamFloat::string (void)
748     char startstring[G_ASCII_DTOSTR_BUF_SIZE];
749     g_ascii_dtostr(startstring, G_ASCII_DTOSTR_BUF_SIZE, _value);
750     Glib::ustring * mystring = new Glib::ustring(startstring);
751     return mystring;
754 /** \brief  Return the value as a string */
755 Glib::ustring *
756 ParamString::string (void)
758     Glib::ustring * mystring = new Glib::ustring("");
759     *mystring += "\"";
760     *mystring += _value; 
761     *mystring += "\"";
762     return mystring;
766 }  /* namespace Extension */
767 }  /* namespace Inkscape */
769 /*
770   Local Variables:
771   mode:c++
772   c-file-style:"stroustrup"
773   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
774   indent-tabs-mode:nil
775   fill-column:99
776   End:
777 */
778 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :