diff options
| author | Ted Gould <ted@gould.cx> | 2008-04-04 04:55:24 +0000 |
|---|---|---|
| committer | gouldtj <gouldtj@users.sourceforge.net> | 2008-04-04 04:55:24 +0000 |
| commit | 8a2ba4f29d0304fef7631e0efec8b10a2dc99121 (patch) | |
| tree | 0eb2b0987084a55191da506c6c7e870bbe2d903d /src/extension/param | |
| parent | * packaging/macosx/ScriptExec/main.c: Add a comment to clarify what looks (diff) | |
| download | inkscape-8a2ba4f29d0304fef7631e0efec8b10a2dc99121.tar.gz inkscape-8a2ba4f29d0304fef7631e0efec8b10a2dc99121.zip | |
r18381@shi: ted | 2008-03-07 20:11:34 -0800
New work branch
r18391@shi: ted | 2008-03-08 21:36:03 -0800
Moving the parameters around to clean up the directories.
r18392@shi: ted | 2008-03-08 21:57:14 -0800
Moving the 'get' function to cpp
r18870@shi: ted | 2008-04-03 21:10:20 -0700
Adding in to the parameter prototype the ability to have a gui-tip and a gui-hidden parameter
r18871@shi: ted | 2008-04-03 21:17:39 -0700
Using the _gui-hidden parameter to block the creation of the widget if set.
r18890@shi: ted | 2008-04-03 21:53:55 -0700
Merge from r18024 which got lost in the shuffle.
(bzr r5322)
Diffstat (limited to 'src/extension/param')
| -rw-r--r-- | src/extension/param/bool.cpp | 152 | ||||
| -rw-r--r-- | src/extension/param/bool.h | 45 | ||||
| -rw-r--r-- | src/extension/param/color.cpp | 124 | ||||
| -rw-r--r-- | src/extension/param/color.h | 36 | ||||
| -rw-r--r-- | src/extension/param/description.cpp | 69 | ||||
| -rw-r--r-- | src/extension/param/description.h | 43 | ||||
| -rw-r--r-- | src/extension/param/enum.cpp | 258 | ||||
| -rw-r--r-- | src/extension/param/enum.h | 69 | ||||
| -rw-r--r-- | src/extension/param/float.cpp | 165 | ||||
| -rw-r--r-- | src/extension/param/float.h | 52 | ||||
| -rw-r--r-- | src/extension/param/int.cpp | 159 | ||||
| -rw-r--r-- | src/extension/param/int.h | 50 | ||||
| -rw-r--r-- | src/extension/param/notebook.cpp | 430 | ||||
| -rw-r--r-- | src/extension/param/notebook.h | 68 | ||||
| -rw-r--r-- | src/extension/param/parameter.cpp | 389 | ||||
| -rw-r--r-- | src/extension/param/parameter.h | 131 | ||||
| -rw-r--r-- | src/extension/param/radiobutton.cpp | 271 | ||||
| -rw-r--r-- | src/extension/param/radiobutton.h | 57 | ||||
| -rw-r--r-- | src/extension/param/string.cpp | 155 | ||||
| -rw-r--r-- | src/extension/param/string.h | 49 |
20 files changed, 2772 insertions, 0 deletions
diff --git a/src/extension/param/bool.cpp b/src/extension/param/bool.cpp new file mode 100644 index 000000000..509ded032 --- /dev/null +++ b/src/extension/param/bool.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2005-2007 Authors: + * Ted Gould <ted@gould.cx> + * Johan Engelen <johan@shouraizou.nl> * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <gtkmm/adjustment.h> +#include <gtkmm/box.h> +#include <gtkmm/spinbutton.h> + +#include <xml/node.h> + +#include "../extension.h" +#include "bool.h" + +namespace Inkscape { +namespace Extension { + +/** \brief Use the superclass' allocator and set the \c _value */ +ParamBool::ParamBool (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) : + Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext), _value(false) +{ + const char * defaultval = NULL; + if (sp_repr_children(xml) != NULL) + defaultval = sp_repr_children(xml)->content(); + + if (defaultval != NULL && (!strcmp(defaultval, "TRUE") || !strcmp(defaultval, "true") || !strcmp(defaultval, "1"))) { + _value = true; + } else { + _value = false; + } + + gchar * pref_name = this->pref_name(); + _value = (bool)prefs_get_int_attribute(PREF_DIR, pref_name, _value); + g_free(pref_name); + + return; +} + +/** \brief A function to set the \c _value + \param in The value to set to + \param doc A document that should be used to set the value. + \param node The node where the value may be placed + + This function sets the internal value, but it also sets the value + in the preferences structure. To put it in the right place, \c PREF_DIR + and \c pref_name() are used. +*/ +bool +ParamBool::set( bool in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/ ) +{ + _value = in; + + gchar * prefname = this->pref_name(); + prefs_set_int_attribute(PREF_DIR, prefname, _value == true ? 1 : 0); + g_free(prefname); + + return _value; +} + +/** \brief Returns \c _value */ +bool +ParamBool::get (const SPDocument * doc, const Inkscape::XML::Node * node) +{ + return _value; +} + +/** \brief A check button which is Param aware. It works with the + parameter to change it's value as the check button changes + value. */ +class ParamBoolCheckButton : public Gtk::CheckButton { +private: + /** \brief Param to change */ + ParamBool * _pref; + SPDocument * _doc; + Inkscape::XML::Node * _node; + sigc::signal<void> * _changeSignal; +public: + /** \brief Initialize the check button + \param param Which parameter to adjust on changing the check button + + This function sets the value of the checkbox to be that of the + parameter, and then sets up a callback to \c on_toggle. + */ + ParamBoolCheckButton (ParamBool * param, SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) : + Gtk::CheckButton(), _pref(param), _doc(doc), _node(node), _changeSignal(changeSignal) { + this->set_active(_pref->get(NULL, NULL) /**\todo fix */); + this->signal_toggled().connect(sigc::mem_fun(this, &ParamBoolCheckButton::on_toggle)); + return; + } + void on_toggle (void); +}; + +/** + \brief A function to respond to the check box changing + + Adjusts the value of the preference to match that in the check box. +*/ +void +ParamBoolCheckButton::on_toggle (void) +{ + _pref->set(this->get_active(), NULL /**\todo fix this */, NULL); + if (_changeSignal != NULL) { + _changeSignal->emit(); + } + return; +} + +/** \brief Return 'true' or 'false' */ +void +ParamBool::string (std::string &string) +{ + if (_value) { + string += "true"; + } else { + string += "false"; + } + + return; +} + +/** + \brief Creates a bool check button for a bool parameter + + Builds a hbox with a label and a check button in it. +*/ +Gtk::Widget * +ParamBool::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) +{ + if (_gui_hidden) return NULL; + Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4)); + + Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT)); + label->show(); + hbox->pack_start(*label, true, true); + + ParamBoolCheckButton * checkbox = new ParamBoolCheckButton(this, doc, node, changeSignal); + checkbox->show(); + hbox->pack_start(*checkbox, false, false); + + hbox->show(); + + return dynamic_cast<Gtk::Widget *>(hbox); +} + +} /* namespace Extension */ +} /* namespace Inkscape */ diff --git a/src/extension/param/bool.h b/src/extension/param/bool.h new file mode 100644 index 000000000..a1cd4ce4a --- /dev/null +++ b/src/extension/param/bool.h @@ -0,0 +1,45 @@ +#ifndef __INK_EXTENSION_PARAMBOOL_H__ +#define __INK_EXTENSION_PARAMBOOL_H__ +/* + * Copyright (C) 2005-2007 Authors: + * Ted Gould <ted@gould.cx> + * Johan Engelen <johan@shouraizou.nl> * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gtkmm/widget.h> +#include <xml/node.h> +#include <document.h> +#include "parameter.h" + +namespace Inkscape { +namespace Extension { + +/** \brief A boolean parameter */ +class ParamBool : public Parameter { +private: + /** \brief Internal value. */ + bool _value; +public: + ParamBool(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml); + bool get (const SPDocument * doc, const Inkscape::XML::Node * node); + bool set (bool in, SPDocument * doc, Inkscape::XML::Node * node); + Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal); + void string (std::string &string); +}; + +} /* namespace Extension */ +} /* namespace Inkscape */ + +#endif /* __INK_EXTENSION_PARAMBOOL_H__ */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/extension/param/color.cpp b/src/extension/param/color.cpp new file mode 100644 index 000000000..845a04824 --- /dev/null +++ b/src/extension/param/color.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2005-2007 Authors: + * Ted Gould <ted@gould.cx> + * Johan Engelen <johan@shouraizou.nl> + * Christopher Brown <audiere@gmail.com> + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <iostream> +#include <sstream> + +#include <gtkmm/adjustment.h> +#include <gtkmm/box.h> +#include <gtkmm/spinbutton.h> + +#include <xml/node.h> + +#include "../extension.h" +#include "color.h" + +#include <color.h> +#include "widgets/sp-color-selector.h" +#include "widgets/sp-color-notebook.h" + + +namespace Inkscape { +namespace Extension { + +void sp_color_param_changed(SPColorSelector *csel, GObject *cp); + + +/** \brief Free the allocated data. */ +ParamColor::~ParamColor(void) +{ + +} + +guint32 +ParamColor::set( guint32 in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/ ) +{ + _value = in; + + gchar * prefname = this->pref_name(); + std::string value; + string(value); + prefs_set_string_attribute(PREF_DIR, prefname, value.c_str()); + g_free(prefname); + + return _value; +} + +/** \brief Initialize the object, to do that, copy the data. */ +ParamColor::ParamColor (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) : + Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext) +{ + const char * defaulthex = NULL; + if (sp_repr_children(xml) != NULL) + defaulthex = sp_repr_children(xml)->content(); + + gchar * pref_name = this->pref_name(); + const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name); + g_free(pref_name); + + if (paramval != NULL) + defaulthex = paramval; + + _value = atoi(defaulthex); + + return; +} + +void +ParamColor::string (std::string &string) +{ + char str[16]; + sprintf(str, "%i", _value); + string += str; + return; +} + +Gtk::Widget * +ParamColor::get_widget( SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/, sigc::signal<void> * changeSignal ) +{ + if (_gui_hidden) return NULL; + + _changeSignal = new sigc::signal<void>(*changeSignal); + Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4)); + SPColorSelector* spColorSelector = (SPColorSelector*)sp_color_selector_new(SP_TYPE_COLOR_NOTEBOOK); + + ColorSelector* colorSelector = spColorSelector->base; + if (_value < 1) { + _value = 0xFF000000; + } + SPColor *color = new SPColor( _value ); + float alpha = (_value & 0xff) / 255.0F; + colorSelector->setColorAlpha(*color, alpha); + + hbox->pack_start (*Glib::wrap(&spColorSelector->vbox), true, true, 0); + g_signal_connect(G_OBJECT(spColorSelector), "changed", G_CALLBACK(sp_color_param_changed), (void*)this); + + gtk_widget_show(GTK_WIDGET(spColorSelector)); + hbox->show(); + + return dynamic_cast<Gtk::Widget *>(hbox); +} + +void +sp_color_param_changed(SPColorSelector *csel, GObject *obj) +{ + const SPColor color = csel->base->getColor(); + float alpha = csel->base->getAlpha(); + + ParamColor* ptr = (ParamColor*)obj; + ptr->set(color.toRGBA32( alpha ), NULL, NULL); + + ptr->_changeSignal->emit(); +} + +}; /* namespace Extension */ +}; /* namespace Inkscape */ diff --git a/src/extension/param/color.h b/src/extension/param/color.h new file mode 100644 index 000000000..6836442a1 --- /dev/null +++ b/src/extension/param/color.h @@ -0,0 +1,36 @@ +#ifndef __INK_EXTENSION_PARAMCOLOR_H__ +#define __INK_EXTENSION_PARAMCOLOR_H__ +/* + * Copyright (C) 2005-2007 Authors: + * Ted Gould <ted@gould.cx> + * Johan Engelen <johan@shouraizou.nl> * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gtkmm/widget.h> +#include <xml/node.h> +#include <document.h> +#include <color.h> +#include "parameter.h" + +namespace Inkscape { +namespace Extension { + +class ParamColor : public Parameter { +private: + guint32 _value; +public: + ParamColor(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml); + virtual ~ParamColor(void); + /** \brief Returns \c _value, with a \i const to protect it. */ + guint32 get( const SPDocument * /*doc*/, const Inkscape::XML::Node * /*node*/ ) { return _value; } + guint32 set (guint32 in, SPDocument * doc, Inkscape::XML::Node * node); + Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal); + void string (std::string &string); + sigc::signal<void> * _changeSignal; +}; /* class ParamColor */ + +} /* namespace Extension */ +} /* namespace Inkscape */ + +#endif /* __INK_EXTENSION_PARAMCOLOR_H__ */ diff --git a/src/extension/param/description.cpp b/src/extension/param/description.cpp new file mode 100644 index 000000000..61bfa9f5a --- /dev/null +++ b/src/extension/param/description.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2005-2007 Authors: + * Ted Gould <ted@gould.cx> + * Johan Engelen <johan@shouraizou.nl> * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef linux // does the dollar sign need escaping when passed as string parameter? +# define ESCAPE_DOLLAR_COMMANDLINE +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +#include "description.h" + +#include <gtkmm/adjustment.h> +#include <gtkmm/box.h> +#include <gtkmm/spinbutton.h> +#include <sstream> + + +#include <glibmm/i18n.h> + +#include <xml/node.h> + +#include <extension/extension.h> +#include <prefs-utils.h> + +namespace Inkscape { +namespace Extension { + + +/** \brief Initialize the object, to do that, copy the data. */ +ParamDescription::ParamDescription (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) : + Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext), _value(NULL) +{ + // printf("Building Description\n"); + const char * defaultval = NULL; + if (sp_repr_children(xml) != NULL) + defaultval = sp_repr_children(xml)->content(); + + if (defaultval != NULL) + _value = g_strdup(defaultval); + + return; +} + +/** \brief Create a label for the description */ +Gtk::Widget * +ParamDescription::get_widget (SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/, sigc::signal<void> * /*changeSignal*/) +{ + if (_gui_hidden) return NULL; + + Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_value))); + label->set_line_wrap(); + label->show(); + + Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4)); + hbox->pack_start(*label, true, true, 5); + hbox->show(); + + return hbox; +} + +} /* namespace Extension */ +} /* namespace Inkscape */ diff --git a/src/extension/param/description.h b/src/extension/param/description.h new file mode 100644 index 000000000..c305ea6df --- /dev/null +++ b/src/extension/param/description.h @@ -0,0 +1,43 @@ +#ifndef __INK_EXTENSION_PARAMDESCRIPTION_H__ +#define __INK_EXTENSION_PARAMDESCRIPTION_H__ + +/* + * Copyright (C) 2005-2007 Authors: + * Ted Gould <ted@gould.cx> + * Johan Engelen <johan@shouraizou.nl> * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gtkmm/widget.h> +#include <xml/node.h> +#include <document.h> +#include "parameter.h" + +namespace Inkscape { +namespace Extension { + +/** \brief A description parameter */ +class ParamDescription : public Parameter { +private: + /** \brief Internal value. */ + gchar * _value; +public: + ParamDescription(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml); + Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal); +}; + +} /* namespace Extension */ +} /* namespace Inkscape */ + +#endif /* __INK_EXTENSION_PARAMDESCRIPTION_H__ */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/extension/param/enum.cpp b/src/extension/param/enum.cpp new file mode 100644 index 000000000..274220699 --- /dev/null +++ b/src/extension/param/enum.cpp @@ -0,0 +1,258 @@ +/** \file + * extension parameter for enumerations. + * + * It uses a Gtk:ComboBoxText widget in the extension UI. + */ + +/* + * Author: + * Johan Engelen <johan@shouraizou.nl> + * + * Copyright (C) 2006-2007 Johan Engelen + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +#include <gtkmm/box.h> +#include <gtkmm/comboboxtext.h> +#include <gtkmm/tooltips.h> +#include <gtkmm/label.h> + +#include <glibmm/i18n.h> + +#include <xml/node.h> + +#include <extension/extension.h> +#include <prefs-utils.h> +#include <document-private.h> +#include <sp-object.h> + +#include "enum.h" + +/** \brief The root directory in the preferences database for extension + related parameters. */ +#define PREF_DIR "extensions" + +namespace Inkscape { +namespace Extension { + +/* For internal use only. + Note that value and guitext MUST be non-NULL. This is ensured by newing only at one location in the code where non-NULL checks are made. */ +class enumentry { +public: + enumentry (Glib::ustring * val, Glib::ustring * text) { + value = val; + guitext = text; + } + ~enumentry() { + delete value; + delete guitext; + } + + Glib::ustring * value; + Glib::ustring * guitext; +}; + + +ParamComboBox::ParamComboBox (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) : + Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext) +{ + choices = NULL; + _value = NULL; + + // Read XML tree to add enumeration items: + // printf("Extension Constructor: "); + if (xml != NULL) { + Inkscape::XML::Node *child_repr = sp_repr_children(xml); + while (child_repr != NULL) { + char const * chname = child_repr->name(); + if (!strcmp(chname, "item") || !strcmp(chname, "_item")) { + Glib::ustring * newguitext = NULL; + Glib::ustring * newvalue = NULL; + const char * contents = sp_repr_children(child_repr)->content(); + if (contents != NULL) + // don't translate when 'item' but do translate when '_item' + // NOTE: internal extensions use build_from_mem and don't need _item but + // still need to include if are to be localized + newguitext = new Glib::ustring( !strcmp(chname, "_item") ? _(contents) : contents ); + else + continue; + + const char * val = child_repr->attribute("value"); + if (val != NULL) + newvalue = new Glib::ustring(val); + else + newvalue = new Glib::ustring(contents); + + if ( (newguitext) && (newvalue) ) { // logical error if this is not true here + choices = g_slist_append( choices, new enumentry(newvalue, newguitext) ); + } + } + child_repr = sp_repr_next(child_repr); + } + } + + // Initialize _value with the default value from xml + // for simplicity : default to the contents of the first xml-child + const char * defaultval = NULL; + if (sp_repr_children(sp_repr_children(xml)) != NULL) + defaultval = sp_repr_children(xml)->attribute("value"); + + gchar * pref_name = this->pref_name(); + const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name); + g_free(pref_name); + + if (paramval != NULL) + defaultval = paramval; + if (defaultval != NULL) + _value = g_strdup(defaultval); // allocate space for _value + + return; +} + +ParamComboBox::~ParamComboBox (void) +{ + //destroy choice strings + for (GSList * list = choices; list != NULL; list = g_slist_next(list)) { + delete (reinterpret_cast<enumentry *>(list->data)); + } + g_slist_free(choices); + + g_free(_value); +} + + +/** \brief A function to set the \c _value + \param in The value to set + \param doc A document that should be used to set the value. + \param node The node where the value may be placed + + This function sets ONLY the internal value, but it also sets the value + in the preferences structure. To put it in the right place, \c PREF_DIR + and \c pref_name() are used. + + To copy the data into _value the old memory must be free'd first. + It is important to note that \c g_free handles \c NULL just fine. Then + the passed in value is duplicated using \c g_strdup(). +*/ +const gchar * +ParamComboBox::set (const gchar * in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/) +{ + if (in == NULL) return NULL; /* Can't have NULL string */ + + Glib::ustring * settext = NULL; + for (GSList * list = choices; list != NULL; list = g_slist_next(list)) { + enumentry * entr = reinterpret_cast<enumentry *>(list->data); + if ( !entr->guitext->compare(in) ) { + settext = entr->value; + break; // break out of for loop + } + } + if (settext) { + if (_value != NULL) g_free(_value); + _value = g_strdup(settext->c_str()); + gchar * prefname = this->pref_name(); + prefs_set_string_attribute(PREF_DIR, prefname, _value); + g_free(prefname); + } + + return _value; +} + +void +ParamComboBox::changed (void) { + +} + + +/** + \brief A function to get the value of the parameter in string form + \return A string with the 'value' as command line argument +*/ +void +ParamComboBox::string (std::string &string) +{ + string += _value; + return; +} + + + + +/** \brief A special category of Gtk::Entry to handle string parameteres */ +class ParamComboBoxEntry : public Gtk::ComboBoxText { +private: + ParamComboBox * _pref; + SPDocument * _doc; + Inkscape::XML::Node * _node; + sigc::signal<void> * _changeSignal; +public: + /** \brief Build a string preference for the given parameter + \param pref Where to get the string from, and where to put it + when it changes. + */ + ParamComboBoxEntry (ParamComboBox * pref, SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) : + Gtk::ComboBoxText(), _pref(pref), _doc(doc), _node(node), _changeSignal(changeSignal) { + this->signal_changed().connect(sigc::mem_fun(this, &ParamComboBoxEntry::changed)); + }; + void changed (void); +}; + +/** \brief Respond to the text box changing + + This function responds to the box changing by grabbing the value + from the text box and putting it in the parameter. +*/ +void +ParamComboBoxEntry::changed (void) +{ + Glib::ustring data = this->get_active_text(); + _pref->set(data.c_str(), _doc, _node); + if (_changeSignal != NULL) { + _changeSignal->emit(); + } +} + +/** + \brief Creates a combobox widget for an enumeration parameter +*/ +Gtk::Widget * +ParamComboBox::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) +{ + if (_gui_hidden) return NULL; + + Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4)); + + Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT)); + label->show(); + hbox->pack_start(*label, false, false); + + ParamComboBoxEntry * combo = Gtk::manage(new ParamComboBoxEntry(this, doc, node, changeSignal)); + // add choice strings: + Glib::ustring * settext = 0; + for (GSList * list = choices; list != NULL; list = g_slist_next(list)) { + enumentry * entr = reinterpret_cast<enumentry *>(list->data); + Glib::ustring * text = entr->guitext; + combo->append_text(*text); + if ( !entr->value->compare(_value) ) { + settext = entr->guitext; + } + } + if (settext) combo->set_active_text(*settext); + + combo->show(); + hbox->pack_start(*combo, true, true); + + hbox->show(); + + return dynamic_cast<Gtk::Widget *>(hbox); +} + + +} /* namespace Extension */ +} /* namespace Inkscape */ diff --git a/src/extension/param/enum.h b/src/extension/param/enum.h new file mode 100644 index 000000000..3f9707c34 --- /dev/null +++ b/src/extension/param/enum.h @@ -0,0 +1,69 @@ +#ifndef INK_EXTENSION_PARAMENUM_H_SEEN +#define INK_EXTENSION_PARAMENUM_H_SEEN + +/** \file + * Enumeration parameter for extensions. + */ + +/* + * Author: + * Johan Engelen <johan@shouraizou.nl> + * + * Copyright (C) 2006-2007 Johan Engelen + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gtkmm/widget.h> + +#include "xml/document.h" +#include <extension/extension-forward.h> + +#include "parameter.h" + +namespace Inkscape { +namespace Extension { + + + +// \brief A class to represent a notebookparameter of an extension +class ParamComboBox : public Parameter { +private: + /** \brief Internal value. This should point to a string that has + been allocated in memory. And should be free'd. + It is the value of the current selected string */ + gchar * _value; + + GSList * choices; /**< A table to store the choice strings */ + +public: + ParamComboBox(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml); + virtual ~ParamComboBox(void); + Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal); + void string (std::string &string); + + const gchar * get (const SPDocument * /*doc*/, const Inkscape::XML::Node * /*node*/) { return _value; } + const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node); + + void changed (void); +}; /* class ParamComboBox */ + + + + + +} /* namespace Extension */ +} /* namespace Inkscape */ + +#endif /* INK_EXTENSION_PARAMENUM_H_SEEN */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/extension/param/float.cpp b/src/extension/param/float.cpp new file mode 100644 index 000000000..1225648d6 --- /dev/null +++ b/src/extension/param/float.cpp @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2005-2007 Authors: + * Ted Gould <ted@gould.cx> + * Johan Engelen <johan@shouraizou.nl> * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <gtkmm/adjustment.h> +#include <gtkmm/box.h> +#include <gtkmm/spinbutton.h> + +#include <xml/node.h> + +#include <extension/extension.h> +#include "float.h" + +namespace Inkscape { +namespace Extension { + + +/** \brief Use the superclass' allocator and set the \c _value */ +ParamFloat::ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) : + Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext), _value(0.0), _min(0.0), _max(10.0) +{ + const char * defaultval = NULL; + if (sp_repr_children(xml) != NULL) + defaultval = sp_repr_children(xml)->content(); + if (defaultval != NULL) { + _value = atof(defaultval); + } + + const char * maxval = xml->attribute("max"); + if (maxval != NULL) + _max = atof(maxval); + + const char * minval = xml->attribute("min"); + if (minval != NULL) + _min = atof(minval); + + _precision = 1; + const char * precision = xml->attribute("precision"); + if (precision != NULL) + _precision = atoi(precision); + + /* We're handling this by just killing both values */ + if (_max < _min) { + _max = 10.0; + _min = 0.0; + } + + gchar * pref_name = this->pref_name(); + _value = prefs_get_double_attribute(PREF_DIR, pref_name, _value); + g_free(pref_name); + + // std::cout << "New Float:: value: " << _value << " max: " << _max << " min: " << _min << std::endl; + + if (_value > _max) _value = _max; + if (_value < _min) _value = _min; + + return; +} + +/** \brief A function to set the \c _value + \param in The value to set to + \param doc A document that should be used to set the value. + \param node The node where the value may be placed + + This function sets the internal value, but it also sets the value + in the preferences structure. To put it in the right place, \c PREF_DIR + and \c pref_name() are used. +*/ +float +ParamFloat::set (float in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/) +{ + _value = in; + if (_value > _max) _value = _max; + if (_value < _min) _value = _min; + + gchar * prefname = this->pref_name(); + prefs_set_double_attribute(PREF_DIR, prefname, _value); + g_free(prefname); + + return _value; +} + +/** \brief Return the value as a string */ +void +ParamFloat::string (std::string &string) +{ + char startstring[G_ASCII_DTOSTR_BUF_SIZE]; + g_ascii_dtostr(startstring, G_ASCII_DTOSTR_BUF_SIZE, _value); + string += startstring; + return; +} + +/** \brief A class to make an adjustment that uses Extension params */ +class ParamFloatAdjustment : public Gtk::Adjustment { + /** The parameter to adjust */ + ParamFloat * _pref; + SPDocument * _doc; + Inkscape::XML::Node * _node; + sigc::signal<void> * _changeSignal; +public: + /** \brief Make the adjustment using an extension and the string + describing the parameter. */ + ParamFloatAdjustment (ParamFloat * param, SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) : + Gtk::Adjustment(0.0, param->min(), param->max(), 0.1), _pref(param), _doc(doc), _node(node), _changeSignal(changeSignal) { + this->set_value(_pref->get(NULL, NULL) /* \todo fix */); + this->signal_value_changed().connect(sigc::mem_fun(this, &ParamFloatAdjustment::val_changed)); + return; + }; + + void val_changed (void); +}; /* class ParamFloatAdjustment */ + +/** \brief A function to respond to the value_changed signal from the + adjustment. + + This function just grabs the value from the adjustment and writes + it to the parameter. Very simple, but yet beautiful. +*/ +void +ParamFloatAdjustment::val_changed (void) +{ + //std::cout << "Value Changed to: " << this->get_value() << std::endl; + _pref->set(this->get_value(), _doc, _node); + if (_changeSignal != NULL) { + _changeSignal->emit(); + } + return; +} + +/** + \brief Creates a Float Adjustment for a float parameter + + Builds a hbox with a label and a float adjustment in it. +*/ +Gtk::Widget * +ParamFloat::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) +{ + if (_gui_hidden) return NULL; + + Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4)); + + Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT)); + label->show(); + hbox->pack_start(*label, true, true); + + ParamFloatAdjustment * fadjust = Gtk::manage(new ParamFloatAdjustment(this, doc, node, changeSignal)); + Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 0.1, _precision)); + spin->show(); + hbox->pack_start(*spin, false, false); + + hbox->show(); + + return dynamic_cast<Gtk::Widget *>(hbox); +} + + +} /* namespace Extension */ +} /* namespace Inkscape */ diff --git a/src/extension/param/float.h b/src/extension/param/float.h new file mode 100644 index 000000000..f105d8f0e --- /dev/null +++ b/src/extension/param/float.h @@ -0,0 +1,52 @@ +#ifndef INK_EXTENSION_PARAMFLOAT_H_SEEN +#define INK_EXTENSION_PARAMFLOAT_H_SEEN + +/* + * Copyright (C) 2005-2007 Authors: + * Ted Gould <ted@gould.cx> + * Johan Engelen <johan@shouraizou.nl> * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gtkmm/widget.h> +#include <xml/node.h> +#include <document.h> +#include "parameter.h" + +namespace Inkscape { +namespace Extension { + +class ParamFloat : public Parameter { +private: + /** \brief Internal value. */ + float _value; + float _min; + float _max; + int _precision; +public: + ParamFloat (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml); + /** \brief Returns \c _value */ + float get (const SPDocument * /*doc*/, const Inkscape::XML::Node * /*node*/) { return _value; } + float set (float in, SPDocument * doc, Inkscape::XML::Node * node); + float max (void) { return _max; } + float min (void) { return _min; } + float precision (void) { return _precision; } + Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal); + void string (std::string &string); +}; + +} /* namespace Extension */ +} /* namespace Inkscape */ + +#endif /* INK_EXTENSION_PARAMFLOAT_H_SEEN */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/extension/param/int.cpp b/src/extension/param/int.cpp new file mode 100644 index 000000000..dc523435e --- /dev/null +++ b/src/extension/param/int.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2005-2007 Authors: + * Ted Gould <ted@gould.cx> + * Johan Engelen <johan@shouraizou.nl> * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <gtkmm/adjustment.h> +#include <gtkmm/box.h> +#include <gtkmm/spinbutton.h> + +#include <xml/node.h> + +#include <extension/extension.h> +#include "int.h" + +namespace Inkscape { +namespace Extension { + + +/** \brief Use the superclass' allocator and set the \c _value */ +ParamInt::ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) : + Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext), _value(0), _min(0), _max(10) +{ + const char * defaultval = NULL; + if (sp_repr_children(xml) != NULL) + defaultval = sp_repr_children(xml)->content(); + if (defaultval != NULL) { + _value = atoi(defaultval); + } + + const char * maxval = xml->attribute("max"); + if (maxval != NULL) + _max = atoi(maxval); + + const char * minval = xml->attribute("min"); + if (minval != NULL) + _min = atoi(minval); + + /* We're handling this by just killing both values */ + if (_max < _min) { + _max = 10; + _min = 0; + } + + gchar * pref_name = this->pref_name(); + _value = prefs_get_int_attribute(PREF_DIR, pref_name, _value); + g_free(pref_name); + + // std::cout << "New Int:: value: " << _value << " max: " << _max << " min: " << _min << std::endl; + + if (_value > _max) _value = _max; + if (_value < _min) _value = _min; + + return; +} + +/** \brief A function to set the \c _value + \param in The value to set to + \param doc A document that should be used to set the value. + \param node The node where the value may be placed + + This function sets the internal value, but it also sets the value + in the preferences structure. To put it in the right place, \c PREF_DIR + and \c pref_name() are used. +*/ +int +ParamInt::set (int in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/) +{ + _value = in; + if (_value > _max) _value = _max; + if (_value < _min) _value = _min; + + gchar * prefname = this->pref_name(); + prefs_set_int_attribute(PREF_DIR, prefname, _value); + g_free(prefname); + + return _value; +} + +/** \brief A class to make an adjustment that uses Extension params */ +class ParamIntAdjustment : public Gtk::Adjustment { + /** The parameter to adjust */ + ParamInt * _pref; + SPDocument * _doc; + Inkscape::XML::Node * _node; + sigc::signal<void> * _changeSignal; +public: + /** \brief Make the adjustment using an extension and the string + describing the parameter. */ + ParamIntAdjustment (ParamInt * param, SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) : + Gtk::Adjustment(0.0, param->min(), param->max(), 1.0), _pref(param), _doc(doc), _node(node), _changeSignal(changeSignal) { + this->set_value(_pref->get(NULL, NULL) /* \todo fix */); + this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed)); + return; + }; + + void val_changed (void); +}; /* class ParamIntAdjustment */ + +/** \brief A function to respond to the value_changed signal from the + adjustment. + + This function just grabs the value from the adjustment and writes + it to the parameter. Very simple, but yet beautiful. +*/ +void +ParamIntAdjustment::val_changed (void) +{ + //std::cout << "Value Changed to: " << this->get_value() << std::endl; + _pref->set((int)this->get_value(), _doc, _node); + if (_changeSignal != NULL) { + _changeSignal->emit(); + } + return; +} + +/** + \brief Creates a Int Adjustment for a int parameter + + Builds a hbox with a label and a int adjustment in it. +*/ +Gtk::Widget * +ParamInt::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) +{ + if (_gui_hidden) return NULL; + + Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4)); + + Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT)); + label->show(); + hbox->pack_start(*label, true, true); + + ParamIntAdjustment * fadjust = Gtk::manage(new ParamIntAdjustment(this, doc, node, changeSignal)); + Gtk::SpinButton * spin = Gtk::manage(new Gtk::SpinButton(*fadjust, 1.0, 0)); + spin->show(); + hbox->pack_start(*spin, false, false); + + hbox->show(); + + return dynamic_cast<Gtk::Widget *>(hbox); +} + +/** \brief Return the value as a string */ +void +ParamInt::string (std::string &string) +{ + char startstring[32]; + sprintf(startstring, "%d", _value); + string += startstring; + return; +} + +} /* namespace Extension */ +} /* namespace Inkscape */ diff --git a/src/extension/param/int.h b/src/extension/param/int.h new file mode 100644 index 000000000..a4eb54c81 --- /dev/null +++ b/src/extension/param/int.h @@ -0,0 +1,50 @@ +#ifndef INK_EXTENSION_PARAMINT_H_SEEN +#define INK_EXTENSION_PARAMINT_H_SEEN + +/* + * Copyright (C) 2005-2007 Authors: + * Ted Gould <ted@gould.cx> + * Johan Engelen <johan@shouraizou.nl> * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gtkmm/widget.h> +#include <xml/node.h> +#include <document.h> +#include "parameter.h" + +namespace Inkscape { +namespace Extension { + +class ParamInt : public Parameter { +private: + /** \brief Internal value. */ + int _value; + int _min; + int _max; +public: + ParamInt (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml); + /** \brief Returns \c _value */ + int get (const SPDocument * /*doc*/, const Inkscape::XML::Node * /*node*/) { return _value; } + int set (int in, SPDocument * doc, Inkscape::XML::Node * node); + int max (void) { return _max; } + int min (void) { return _min; } + Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal); + void string (std::string &string); +}; + +} /* namespace Extension */ +} /* namespace Inkscape */ + +#endif /* INK_EXTENSION_PARAMINT_H_SEEN */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/extension/param/notebook.cpp b/src/extension/param/notebook.cpp new file mode 100644 index 000000000..5c4f96759 --- /dev/null +++ b/src/extension/param/notebook.cpp @@ -0,0 +1,430 @@ +/** \file + * Notebook and NotebookPage parameters for extensions. + */ + +/* + * Author: + * Johan Engelen <johan@shouraizou.nl> + * + * Copyright (C) 2006 Author + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +#include <gtkmm/adjustment.h> +#include <gtkmm/box.h> +#include <gtkmm/spinbutton.h> +#include <gtkmm/notebook.h> +#include <gtkmm/tooltips.h> + +#include <glibmm/i18n.h> + +#include <xml/node.h> + +#include <extension/extension.h> +#include "prefs-utils.h" +#include "document-private.h" +#include "sp-object.h" + +#include "notebook.h" + +/** \brief The root directory in the preferences database for extension + related parameters. */ +#define PREF_DIR "extensions" + +namespace Inkscape { +namespace Extension { + + +// \brief A class to represent the pages of a notebookparameter of an extension +class ParamNotebookPage : public Parameter { +private: + GSList * parameters; /**< A table to store the parameters for this page. + This only gets created if there are parameters on this + page */ + Gtk::Tooltips * _tooltips; + +public: + static ParamNotebookPage * makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext); + + ParamNotebookPage(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml); + ~ParamNotebookPage(void); + Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal); + void paramString (std::list <std::string> &list); + gchar * get_guitext (void) {return _text;}; + +}; /* class ParamNotebookPage */ + + +ParamNotebookPage::ParamNotebookPage (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) : + Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext) +{ + parameters = NULL; + + // Read XML to build page + if (xml != NULL) { + Inkscape::XML::Node *child_repr = sp_repr_children(xml); + while (child_repr != NULL) { + char const * chname = child_repr->name(); + if (chname[0] == '_') // Allow _ for translation of tags + chname++; + if (!strcmp(chname, "param") || !strcmp(chname, "_param")) { + Parameter * param; + param = Parameter::make(child_repr, ext); + if (param != NULL) parameters = g_slist_append(parameters, param); + } + child_repr = sp_repr_next(child_repr); + } + } + + return; +} + +ParamNotebookPage::~ParamNotebookPage (void) +{ + if (_tooltips) delete _tooltips; + //destroy parameters + for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) { + Parameter * param = reinterpret_cast<Parameter *>(list->data); + delete param; + } + g_slist_free(parameters); +} + +/** \brief Return the value as a string */ +void +ParamNotebookPage::paramString (std::list <std::string> &list) +{ + for (GSList * plist = parameters; plist != NULL; plist = g_slist_next(plist)) { + Parameter * param = reinterpret_cast<Parameter *>(plist->data); + param->string(list); + } + + return; +} + + +/** + \return None + \brief This function creates a page that can be used later. This + is typically done in the creation of the notebook and defined + in the XML file describing the extension (it's private so people + have to use the system) :) + \param in_repr The XML describing the page + + This function first grabs all of the data out of the Repr and puts + it into local variables. Actually, these are just pointers, and the + data is not duplicated so we need to be careful with it. If there + isn't a name in the XML, then no page is created as + the function just returns. + + From this point on, we're pretty committed as we've allocated an + object and we're starting to fill it. The name is set first, and + is created with a strdup to actually allocate memory for it. Then + there is a case statement (roughly because strcmp requires 'ifs') + based on what type of parameter this is. Depending which type it + is, the value is interpreted differently, but they are relatively + straight forward. In all cases the value is set to the default + value from the XML and the type is set to the interpreted type. +*/ +ParamNotebookPage * +ParamNotebookPage::makepage (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext) +{ + const char * name; + const char * guitext; + const char * desc; + const char * scope_str; + Parameter::_scope_t scope = Parameter::SCOPE_USER; + bool gui_hidden = false; + const char * gui_hide; + const char * gui_tip; + + name = in_repr->attribute("name"); + guitext = in_repr->attribute("gui-text"); + if (guitext == NULL) + guitext = in_repr->attribute("_gui-text"); + gui_tip = in_repr->attribute("gui-tip"); + if (gui_tip == NULL) + gui_tip = in_repr->attribute("_gui-tip"); + desc = in_repr->attribute("gui-description"); + if (desc == NULL) + desc = in_repr->attribute("_gui-description"); + scope_str = in_repr->attribute("scope"); + gui_hide = in_repr->attribute("gui-hidden"); + if (gui_hide != NULL) { + if (strcmp(gui_hide, "1") == 0 || + strcmp(gui_hide, "true") == 0) { + gui_hidden = true; + } + /* else stays false */ + } + + /* In this case we just don't have enough information */ + if (name == NULL) { + return NULL; + } + + if (scope_str != NULL) { + if (!strcmp(scope_str, "user")) { + scope = Parameter::SCOPE_USER; + } else if (!strcmp(scope_str, "document")) { + scope = Parameter::SCOPE_DOCUMENT; + } else if (!strcmp(scope_str, "node")) { + scope = Parameter::SCOPE_NODE; + } + } + + ParamNotebookPage * page = new ParamNotebookPage(name, guitext, desc, scope, gui_hide, gui_tip, in_ext, in_repr); + + /* Note: page could equal NULL */ + return page; +} + + + +/** + \brief Creates a notebookpage widget for a notebook + + Builds a notebook page (a vbox) and puts parameters on it. +*/ +Gtk::Widget * +ParamNotebookPage::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) +{ + if (_gui_hidden) return NULL; + + if (!_tooltips) _tooltips = new Gtk::Tooltips(); + + Gtk::VBox * vbox = Gtk::manage(new Gtk::VBox); + vbox->set_border_width(5); + + // add parameters onto page (if any) + for (GSList * list = parameters; list != NULL; list = g_slist_next(list)) { + Parameter * param = reinterpret_cast<Parameter *>(list->data); + Gtk::Widget * widg = param->get_widget(doc, node, changeSignal); + gchar const * tip = param->get_tooltip(); + + vbox->pack_start(*widg, true, true, 2); + if (tip != NULL) { + _tooltips->set_tip(*widg, Glib::ustring(tip)); + } + } + + vbox->show(); + + return dynamic_cast<Gtk::Widget *>(vbox); +} + + + + + + + + + +ParamNotebook::ParamNotebook (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) : + Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext) +{ + pages = NULL; + + // Read XML tree to add pages: + if (xml != NULL) { + Inkscape::XML::Node *child_repr = sp_repr_children(xml); + while (child_repr != NULL) { + char const * chname = child_repr->name(); + if (chname[0] == '_') // Allow _ for translation of tags + chname++; + if (!strcmp(chname, "page")) { + ParamNotebookPage * page; + page = ParamNotebookPage::makepage(child_repr, ext); + if (page != NULL) pages = g_slist_append(pages, page); + } + child_repr = sp_repr_next(child_repr); + } + } + + // Initialize _value with the current page + const char * defaultval = NULL; + // set first page as default + if (pages != NULL) { + ParamNotebookPage * defpage = reinterpret_cast<ParamNotebookPage *>(pages->data); + defaultval = defpage->name(); + } + + gchar * pref_name = this->pref_name(); + const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name); + g_free(pref_name); + + if (paramval != NULL) + defaultval = paramval; + if (defaultval != NULL) + _value = g_strdup(defaultval); // allocate space for _value + + return; +} + +ParamNotebook::~ParamNotebook (void) +{ + //destroy pages + for (GSList * list = pages; list != NULL; list = g_slist_next(list)) { + ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data); + delete page; + } + g_slist_free(pages); + + g_free(_value); +} + + +/** \brief A function to set the \c _value + \param in The number of the page which value must be set + \param doc A document that should be used to set the value. + \param node The node where the value may be placed + + This function sets the internal value, but it also sets the value + in the preferences structure. To put it in the right place, \c PREF_DIR + and \c pref_name() are used. + + To copy the data into _value the old memory must be free'd first. + It is important to note that \c g_free handles \c NULL just fine. Then + the passed in value is duplicated using \c g_strdup(). +*/ +const gchar * +ParamNotebook::set (const int in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/) +{ + ParamNotebookPage * page = NULL; + int i = 0; + for (GSList * list = pages; (list != NULL) && (i <= in); list = g_slist_next(list)) { + page = reinterpret_cast<ParamNotebookPage *>(list->data); + i++; + } + + if (page == NULL) return _value; + + if (_value != NULL) g_free(_value); + _value = g_strdup(page->name()); + + gchar * prefname = this->pref_name(); + prefs_set_string_attribute(PREF_DIR, prefname, _value); + g_free(prefname); + + return _value; +} + + +/** + \brief A function to get the currentpage and the parameters in a string form + \return A string with the 'value' and all the parameters on all pages as command line arguments +*/ +void +ParamNotebook::string (std::list <std::string> &list) +{ + std::string param_string; + param_string += "--"; + param_string += name(); + param_string += "="; + + param_string += "\""; + param_string += _value; // the name of the current page + param_string += "\""; + list.insert(list.end(), param_string); + + for (GSList * pglist = pages; pglist != NULL; pglist = g_slist_next(pglist)) { + ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(pglist->data); + page->paramString(list); + } + + return; +} + +/** \brief A special category of Gtk::Notebook to handle notebook parameters */ +class ParamNotebookWdg : public Gtk::Notebook { +private: + ParamNotebook * _pref; + SPDocument * _doc; + Inkscape::XML::Node * _node; +public: + /** \brief Build a notebookpage preference for the given parameter + \param pref Where to get the string (pagename) from, and where to put it + when it changes. + */ + ParamNotebookWdg (ParamNotebook * pref, SPDocument * doc, Inkscape::XML::Node * node) : + Gtk::Notebook(), _pref(pref), _doc(doc), _node(node), activated(false) { + // don't have to set the correct page: this is done in ParamNotebook::get_widget. + // hook function + this->signal_switch_page().connect(sigc::mem_fun(this, &ParamNotebookWdg::changed_page)); + return; + }; + void changed_page(GtkNotebookPage *page, guint pagenum); + bool activated; +}; + +/** \brief Respond to the selected page of notebook changing + This function responds to the changing by reporting it to + ParamNotebook. The change is only reported when the notebook + is actually visible. This to exclude 'fake' changes when the + notebookpages are added or removed. +*/ +void +ParamNotebookWdg::changed_page(GtkNotebookPage */*page*/, + guint pagenum) +{ + if (is_visible()) { + _pref->set((int)pagenum, _doc, _node); + } + return; +} + + + +/** + \brief Creates a Notebook widget for a notebook parameter + + Builds a notebook and puts pages in it. +*/ +Gtk::Widget * +ParamNotebook::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) +{ + if (_gui_hidden) return NULL; + + ParamNotebookWdg * nb = Gtk::manage(new ParamNotebookWdg(this, doc, node)); + + // add pages (if any) + int i = -1; + int pagenr = i; + for (GSList * list = pages; list != NULL; list = g_slist_next(list)) { + i++; + ParamNotebookPage * page = reinterpret_cast<ParamNotebookPage *>(list->data); + Gtk::Widget * widg = page->get_widget(doc, node, changeSignal); + nb->append_page(*widg, _(page->get_guitext())); + if (!strcmp(_value, page->name())) { + pagenr = i; // this is the page to be displayed? + } + } + + nb->show(); + + if (pagenr >= 0) nb->set_current_page(pagenr); + + return dynamic_cast<Gtk::Widget *>(nb); +} + + +} /* namespace Extension */ +} /* namespace Inkscape */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/extension/param/notebook.h b/src/extension/param/notebook.h new file mode 100644 index 000000000..24d4ebfc1 --- /dev/null +++ b/src/extension/param/notebook.h @@ -0,0 +1,68 @@ +#ifndef INK_EXTENSION_PARAMNOTEBOOK_H_SEEN +#define INK_EXTENSION_PARAMNOTEBOOK_H_SEEN + +/** \file + * Notebook parameter for extensions. + */ + +/* + * Author: + * Johan Engelen <johan@shouraizou.nl> + * + * Copyright (C) 2006 Author + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gtkmm/widget.h> + +#include "xml/document.h" +#include <extension/extension-forward.h> + +#include "parameter.h" + +namespace Inkscape { +namespace Extension { + + + +// \brief A class to represent a notebookparameter of an extension +class ParamNotebook : public Parameter { +private: + /** \brief Internal value. This should point to a string that has + been allocated in memory. And should be free'd. + It is the name of the current page. */ + gchar * _value; + + GSList * pages; /**< A table to store the pages with parameters for this notebook. + This only gets created if there are pages in this + notebook */ +public: + ParamNotebook(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml); + virtual ~ParamNotebook(void); + Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal); + void string (std::list <std::string> &list); + + const gchar * get (const SPDocument * /*doc*/, const Inkscape::XML::Node * /*node*/) { return _value; } + const gchar * set (const int in, SPDocument * doc, Inkscape::XML::Node * node); +}; /* class ParamNotebook */ + + + + + +} /* namespace Extension */ +} /* namespace Inkscape */ + +#endif /* INK_EXTENSION_PARAMNOTEBOOK_H_SEEN */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/extension/param/parameter.cpp b/src/extension/param/parameter.cpp new file mode 100644 index 000000000..7e071e7e3 --- /dev/null +++ b/src/extension/param/parameter.cpp @@ -0,0 +1,389 @@ +/** \file + * Parameters for extensions. + */ + +/* + * Author: + * Ted Gould <ted@gould.cx> + * Johan Engelen <johan@shouraizou.nl> + * + * Copyright (C) 2005-2007 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef linux // does the dollar sign need escaping when passed as string parameter? +# define ESCAPE_DOLLAR_COMMANDLINE +#endif + +#include <gtkmm/adjustment.h> +#include <gtkmm/box.h> +#include <gtkmm/spinbutton.h> + +#include <xml/node.h> + +#include <extension/extension.h> +#include "document-private.h" +#include "sp-object.h" +#include <color.h> +#include "widgets/sp-color-selector.h" +#include "widgets/sp-color-notebook.h" + +#include "parameter.h" +#include "bool.h" +#include "color.h" +#include "description.h" +#include "enum.h" +#include "float.h" +#include "int.h" +#include "notebook.h" +#include "radiobutton.h" +#include "string.h" + +namespace Inkscape { +namespace Extension { + +/** + \return None + \brief This function creates a parameter that can be used later. This + is typically done in the creation of the extension and defined + in the XML file describing the extension (it's private so people + have to use the system) :) + \param in_repr The XML describing the parameter + + This function first grabs all of the data out of the Repr and puts + it into local variables. Actually, these are just pointers, and the + data is not duplicated so we need to be careful with it. If there + isn't a name or a type in the XML, then no parameter is created as + the function just returns. + + From this point on, we're pretty committed as we've allocated an + object and we're starting to fill it. The name is set first, and + is created with a strdup to actually allocate memory for it. Then + there is a case statement (roughly because strcmp requires 'ifs') + based on what type of parameter this is. Depending which type it + is, the value is interpreted differently, but they are relatively + straight forward. In all cases the value is set to the default + value from the XML and the type is set to the interpreted type. +*/ +Parameter * +Parameter::make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext) +{ + const char * name; + const char * type; + const char * guitext; + const char * desc; + const char * scope_str; + Parameter::_scope_t scope = Parameter::SCOPE_USER; + bool gui_hidden = false; + const char * gui_hide; + const char * gui_tip; + + name = in_repr->attribute("name"); + type = in_repr->attribute("type"); + guitext = in_repr->attribute("gui-text"); + if (guitext == NULL) + guitext = in_repr->attribute("_gui-text"); + gui_tip = in_repr->attribute("gui-tip"); + if (gui_tip == NULL) + gui_tip = in_repr->attribute("_gui-tip"); + desc = in_repr->attribute("gui-description"); + if (desc == NULL) + desc = in_repr->attribute("_gui-description"); + scope_str = in_repr->attribute("scope"); + gui_hide = in_repr->attribute("gui-hidden"); + if (gui_hide != NULL) { + if (strcmp(gui_hide, "1") == 0 || + strcmp(gui_hide, "true") == 0) { + gui_hidden = true; + } + /* else stays false */ + } + + /* In this case we just don't have enough information */ + if (name == NULL || type == NULL) { + return NULL; + } + + if (scope_str != NULL) { + if (!strcmp(scope_str, "user")) { + scope = Parameter::SCOPE_USER; + } else if (!strcmp(scope_str, "document")) { + scope = Parameter::SCOPE_DOCUMENT; + } else if (!strcmp(scope_str, "node")) { + scope = Parameter::SCOPE_NODE; + } + } + + Parameter * param = NULL; + if (!strcmp(type, "boolean")) { + param = new ParamBool(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr); + } else if (!strcmp(type, "int")) { + param = new ParamInt(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr); + } else if (!strcmp(type, "float")) { + param = new ParamFloat(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr); + } else if (!strcmp(type, "string")) { + param = new ParamString(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr); + } else if (!strcmp(type, "description")) { + param = new ParamDescription(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr); + } else if (!strcmp(type, "enum")) { + param = new ParamComboBox(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr); + } else if (!strcmp(type, "notebook")) { + param = new ParamNotebook(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr); + } else if (!strcmp(type, "optiongroup")) { + param = new ParamRadioButton(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr); + } else if (!strcmp(type, "color")) { + param = new ParamColor(name, guitext, desc, scope, gui_hidden, gui_tip, in_ext, in_repr); + } + + /* Note: param could equal NULL */ + return param; +} + + + +/** \brief Wrapper to cast to the object and use it's function. */ +bool +Parameter::get_bool (const SPDocument * doc, const Inkscape::XML::Node * node) +{ + ParamBool * boolpntr = dynamic_cast<ParamBool *>(this); + if (boolpntr == NULL) + throw Extension::param_not_bool_param(); + return boolpntr->get(doc, node); +} + +/** \brief Wrapper to cast to the object and use it's function. */ +int +Parameter::get_int (const SPDocument * doc, const Inkscape::XML::Node * node) +{ + ParamInt * intpntr = dynamic_cast<ParamInt *>(this); + if (intpntr == NULL) + throw Extension::param_not_int_param(); + return intpntr->get(doc, node); +} + +/** \brief Wrapper to cast to the object and use it's function. */ +float +Parameter::get_float (const SPDocument * doc, const Inkscape::XML::Node * node) +{ + ParamFloat * floatpntr = dynamic_cast<ParamFloat *>(this); + if (floatpntr == NULL) + throw Extension::param_not_float_param(); + return floatpntr->get(doc, node); +} + +/** \brief Wrapper to cast to the object and use it's function. */ +const gchar * +Parameter::get_string (const SPDocument * doc, const Inkscape::XML::Node * node) +{ + ParamString * stringpntr = dynamic_cast<ParamString *>(this); + if (stringpntr == NULL) + throw Extension::param_not_string_param(); + return stringpntr->get(doc, node); +} + +/** \brief Wrapper to cast to the object and use it's function. */ +const gchar * +Parameter::get_enum (const SPDocument * doc, const Inkscape::XML::Node * node) +{ + ParamComboBox * param = dynamic_cast<ParamComboBox *>(this); + if (param == NULL) + throw Extension::param_not_enum_param(); + return param->get(doc, node); +} + +guint32 +Parameter::get_color(const SPDocument* doc, const Inkscape::XML::Node* node) +{ + ParamColor* param = dynamic_cast<ParamColor *>(this); + if (param == NULL) + throw Extension::param_not_color_param(); + return param->get(doc, node); +} + +/** \brief Wrapper to cast to the object and use it's function. */ +bool +Parameter::set_bool (bool in, SPDocument * doc, Inkscape::XML::Node * node) +{ + ParamBool * boolpntr = dynamic_cast<ParamBool *>(this); + if (boolpntr == NULL) + throw Extension::param_not_bool_param(); + return boolpntr->set(in, doc, node); +} + +/** \brief Wrapper to cast to the object and use it's function. */ +int +Parameter::set_int (int in, SPDocument * doc, Inkscape::XML::Node * node) +{ + ParamInt * intpntr = dynamic_cast<ParamInt *>(this); + if (intpntr == NULL) + throw Extension::param_not_int_param(); + return intpntr->set(in, doc, node); +} + +/** \brief Wrapper to cast to the object and use it's function. */ +float +Parameter::set_float (float in, SPDocument * doc, Inkscape::XML::Node * node) +{ + ParamFloat * floatpntr; + floatpntr = dynamic_cast<ParamFloat *>(this); + if (floatpntr == NULL) + throw Extension::param_not_float_param(); + return floatpntr->set(in, doc, node); +} + +/** \brief Wrapper to cast to the object and use it's function. */ +const gchar * +Parameter::set_string (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node) +{ + ParamString * stringpntr = dynamic_cast<ParamString *>(this); + if (stringpntr == NULL) + throw Extension::param_not_string_param(); + return stringpntr->set(in, doc, node); +} +/** \brief Wrapper to cast to the object and use it's function. */ +guint32 +Parameter::set_color (guint32 in, SPDocument * doc, Inkscape::XML::Node * node) +{ + ParamColor* param = dynamic_cast<ParamColor *>(this); + if (param == NULL) + throw Extension::param_not_color_param(); + return param->set(in, doc, node); +} + + +/** \brief Oop, now that we need a parameter, we need it's name. */ +Parameter::Parameter (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext) : + extension(ext), _name(NULL), _desc(NULL), _scope(scope), _text(NULL), _gui_hidden(gui_hidden), _gui_tip(NULL) +{ + if (name != NULL) { + _name = g_strdup(name); + } + if (desc != NULL) { + _desc = g_strdup(desc); + // printf("Adding description: '%s' on '%s'\n", _desc, _name); + } + if (gui_tip != NULL) { + _gui_tip = g_strdup(gui_tip); + } + + + if (guitext != NULL) + _text = g_strdup(guitext); + else + _text = g_strdup(name); + + return; +} + +/** \brief Just free the allocated name. */ +Parameter::~Parameter (void) +{ + g_free(_name); + g_free(_text); + g_free(_gui_tip); +} + +/** \brief Build the name to write the parameter from the extension's + ID and the name of this parameter. */ +gchar * +Parameter::pref_name (void) +{ + return g_strdup_printf("%s.%s", extension->get_id(), _name); +} + +Inkscape::XML::Node * +Parameter::find_child (Inkscape::XML::Node * adult) +{ + return sp_repr_lookup_child(adult, "name", _name); +} + +Inkscape::XML::Node * +Parameter::new_child (Inkscape::XML::Node * parent) +{ + Inkscape::XML::Node * retval; + retval = parent->document()->createElement("inkscape:extension-param"); + retval->setAttribute("name", _name); + + parent->appendChild(retval); + return retval; +} + +Inkscape::XML::Node * +Parameter::document_param_node (SPDocument * doc) +{ + Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); + Inkscape::XML::Node * defs = SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc)); + Inkscape::XML::Node * params = NULL; + + GQuark const name_quark = g_quark_from_string("inkscape:extension-params"); + + for (Inkscape::XML::Node * child = defs->firstChild(); + child != NULL; + child = child->next()) { + if ((GQuark)child->code() == name_quark && + !strcmp(child->attribute("extension"), extension->get_id())) { + params = child; + break; + } + } + + if (params == NULL) { + params = xml_doc->createElement("inkscape:extension-param"); + params->setAttribute("extension", extension->get_id()); + defs->appendChild(params); + } + + return params; +} + +/** \brief Basically, if there is no widget pass a NULL. */ +Gtk::Widget * +Parameter::get_widget (SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/, sigc::signal<void> * /*changeSignal*/) +{ + return NULL; +} + +/** \brief If I'm not sure which it is, just don't return a value. */ +void +Parameter::string (std::string &/*string*/) +{ + return; +} + +void +Parameter::string (std::list <std::string> &list) +{ + std::string value; + string(value); + if (value == "") { + return; + } + + std::string final; + final += "--"; + final += name(); + final += "="; + final += value; + + list.insert(list.end(), final); + return; +} + +} /* namespace Extension */ +} /* namespace Inkscape */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/extension/param/parameter.h b/src/extension/param/parameter.h new file mode 100644 index 000000000..ca3a2a0d4 --- /dev/null +++ b/src/extension/param/parameter.h @@ -0,0 +1,131 @@ +#ifndef __INK_EXTENSION_PARAM_H__ +#define __INK_EXTENSION_PARAM_H__ + +/** \file + * Parameters for extensions. + */ + +/* + * Authors: + * Ted Gould <ted@gould.cx> + * + * Copyright (C) 2005-2006 Authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +/** \brief The root directory in the preferences database for extension-related parameters. */ +#define PREF_DIR "extensions" + +#include <gtkmm/widget.h> + +#include "xml/document.h" +#include "xml/node.h" +#include "document.h" +#include <extension/extension-forward.h> +#include "prefs-utils.h" + +#include <glibmm/i18n.h> + +#include <color.h> + +namespace Inkscape { +namespace Extension { + +/** \brief A class to represent the parameter of an extension + + This is really a super class that allows them to abstract all + the different types of parameters into some that can be passed + around. There is also a few functions that are used by all the + different parameters. +*/ +class Parameter { +private: + /** \brief Which extension is this parameter attached to? */ + Inkscape::Extension::Extension * extension; + /** \brief The name of this parameter. */ + gchar * _name; + +protected: + /** \brief Description of the parameter. */ + gchar * _desc; + /** \brief List of possible scopes. */ + typedef enum { + SCOPE_USER, /**< Parameter value is saved in the user's configuration file. (default) */ + SCOPE_DOCUMENT, /**< Parameter value is saved in the document. */ + SCOPE_NODE /**< Parameter value is attached to the node. */ + } _scope_t; + /** \brief Scope of the parameter. */ + _scope_t _scope; + /** \brief Text for the GUI selection of this. */ + gchar * _text; + /** \brief Whether the GUI is visible */ + bool _gui_hidden; + /** \brief A tip for the GUI if there is one */ + gchar * _gui_tip; + + + /* **** funcs **** */ + gchar * pref_name (void); + Inkscape::XML::Node * find_child (Inkscape::XML::Node * adult); + Inkscape::XML::Node * document_param_node (SPDocument * doc); + Inkscape::XML::Node * new_child (Inkscape::XML::Node * parent); + +public: + Parameter (const gchar * name, + const gchar * guitext, + const gchar * desc, + const Parameter::_scope_t scope, + bool gui_hidden, + const gchar * gui_tip, + Inkscape::Extension::Extension * ext); + Parameter (const gchar * name, + const gchar * guitext, + Inkscape::Extension::Extension * ext) { + Parameter(name, guitext, NULL, Parameter::SCOPE_USER, false, NULL, ext); + }; + virtual ~Parameter (void); + bool get_bool (const SPDocument * doc, + const Inkscape::XML::Node * node); + int get_int (const SPDocument * doc, + const Inkscape::XML::Node * node); + float get_float (const SPDocument * doc, + const Inkscape::XML::Node * node); + const gchar * get_string (const SPDocument * doc, + const Inkscape::XML::Node * node); + guint32 get_color (const SPDocument * doc, + const Inkscape::XML::Node * node); + const gchar * get_enum (const SPDocument * doc, + const Inkscape::XML::Node * node); + + bool set_bool (bool in, SPDocument * doc, Inkscape::XML::Node * node); + int set_int (int in, SPDocument * doc, Inkscape::XML::Node * node); + float set_float (float in, SPDocument * doc, Inkscape::XML::Node * node); + const gchar * set_string (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node); + guint32 set_color (guint32 in, SPDocument * doc, Inkscape::XML::Node * node); + + const gchar * name (void) {return _name;} + + static Parameter * make (Inkscape::XML::Node * in_repr, Inkscape::Extension::Extension * in_ext); + virtual Gtk::Widget * get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal); + gchar const * get_tooltip (void) { return _desc; } + + virtual void string (std::list <std::string> &list); + virtual void string (std::string &string); +}; + +} /* namespace Extension */ +} /* namespace Inkscape */ + +#endif /* __INK_EXTENSION_PARAM_H__ */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/extension/param/radiobutton.cpp b/src/extension/param/radiobutton.cpp new file mode 100644 index 000000000..1ab526d19 --- /dev/null +++ b/src/extension/param/radiobutton.cpp @@ -0,0 +1,271 @@ +/** \file + * extension parameter for radiobuttons. + * + * It uses a Gtk:ComboBoxText widget in the extension UI. + */ + +/* + * Author: + * Johan Engelen <johan@shouraizou.nl> + * + * Copyright (C) 2006-2007 Johan Engelen + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + + +#include <gtkmm/box.h> +#include <gtkmm/radiobutton.h> +#include <gtkmm/radiobuttongroup.h> +#include <gtkmm/tooltips.h> +#include <gtkmm/label.h> + +#include <glibmm/i18n.h> + +#include <xml/node.h> + +#include <extension/extension.h> +#include "prefs-utils.h" +#include "document-private.h" +#include "sp-object.h" + +#include "radiobutton.h" + +/** \brief The root directory in the preferences database for extension + related parameters. */ +#define PREF_DIR "extensions" + +namespace Inkscape { +namespace Extension { + +/* For internal use only. + Note that value and guitext MUST be non-NULL. This is ensured by newing only at one location in the code where non-NULL checks are made. */ +class optionentry { +public: + optionentry (Glib::ustring * val, Glib::ustring * text) { + value = val; + guitext = text; + } + ~optionentry() { + delete value; + delete guitext; + } + + Glib::ustring * value; + Glib::ustring * guitext; +}; + +ParamRadioButton::ParamRadioButton (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) : + Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext) +{ + choices = NULL; + _value = NULL; + + // Read XML tree to add enumeration items: + // printf("Extension Constructor: "); + if (xml != NULL) { + Inkscape::XML::Node *child_repr = sp_repr_children(xml); + while (child_repr != NULL) { + char const * chname = child_repr->name(); + if (!strcmp(chname, "option") || !strcmp(chname, "_option")) { + Glib::ustring * newguitext = NULL; + Glib::ustring * newvalue = NULL; + const char * contents = sp_repr_children(child_repr)->content(); + if (contents != NULL) + // don't translate when 'option' but do translate when '_option' + newguitext = new Glib::ustring( !strcmp(chname, "_option") ? _(contents) : contents ); + else + continue; + + const char * val = child_repr->attribute("value"); + if (val != NULL) + newvalue = new Glib::ustring(val); + else + newvalue = new Glib::ustring(contents); + + if ( (newguitext) && (newvalue) ) { // logical error if this is not true here + choices = g_slist_append( choices, new optionentry(newvalue, newguitext) ); + } + } + child_repr = sp_repr_next(child_repr); + } + } + + // Initialize _value with the default value from xml + // for simplicity : default to the contents of the first xml-child + const char * defaultval = NULL; + if (choices) + defaultval = ((optionentry*) choices->data)->value->c_str(); + + gchar * pref_name = this->pref_name(); + const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name); + g_free(pref_name); + + if (paramval != NULL) + defaultval = paramval; + if (defaultval != NULL) + _value = g_strdup(defaultval); // allocate space for _value + + return; +} + +ParamRadioButton::~ParamRadioButton (void) +{ + //destroy choice strings + for (GSList * list = choices; list != NULL; list = g_slist_next(list)) { + delete (reinterpret_cast<optionentry *>(list->data)); + } + g_slist_free(choices); + + g_free(_value); +} + + +/** \brief A function to set the \c _value + \param in The value to set + \param doc A document that should be used to set the value. + \param node The node where the value may be placed + + This function sets ONLY the internal value, but it also sets the value + in the preferences structure. To put it in the right place, \c PREF_DIR + and \c pref_name() are used. + + To copy the data into _value the old memory must be free'd first. + It is important to note that \c g_free handles \c NULL just fine. Then + the passed in value is duplicated using \c g_strdup(). +*/ +const gchar * +ParamRadioButton::set (const gchar * in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/) +{ + if (in == NULL) return NULL; /* Can't have NULL string */ + + Glib::ustring * settext = NULL; + for (GSList * list = choices; list != NULL; list = g_slist_next(list)) { + optionentry * entr = reinterpret_cast<optionentry *>(list->data); + if ( !entr->guitext->compare(in) ) { + settext = entr->value; + break; // break out of for loop + } + } + if (settext) { + if (_value != NULL) g_free(_value); + _value = g_strdup(settext->c_str()); + gchar * prefname = this->pref_name(); + prefs_set_string_attribute(PREF_DIR, prefname, _value); + g_free(prefname); + } + + return _value; +} + + +/** + \brief A function to get the current value of the parameter in a string form + \return A string with the 'value' as command line argument +*/ +void +ParamRadioButton::string (std::string &string) +{ + string += _value; + return; +} + +/** \brief A special radiobutton class to use in ParamRadioButton */ +class ParamRadioButtonWdg : public Gtk::RadioButton { +private: + ParamRadioButton * _pref; + SPDocument * _doc; + Inkscape::XML::Node * _node; + sigc::signal<void> * _changeSignal; +public: + /** \brief Build a string preference for the given parameter + \param pref Where to put the radiobutton's string when it is selected. + */ + ParamRadioButtonWdg ( Gtk::RadioButtonGroup& group, const Glib::ustring& label, + ParamRadioButton * pref, SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal ) : + Gtk::RadioButton(group, label), _pref(pref), _doc(doc), _node(node), _changeSignal(changeSignal) { + add_changesignal(); + }; + ParamRadioButtonWdg ( const Glib::ustring& label, + ParamRadioButton * pref, SPDocument * doc, Inkscape::XML::Node * node , sigc::signal<void> * changeSignal) : + Gtk::RadioButton(label), _pref(pref), _doc(doc), _node(node), _changeSignal(changeSignal) { + add_changesignal(); + }; + void add_changesignal() { + this->signal_toggled().connect(sigc::mem_fun(this, &ParamRadioButtonWdg::changed)); + }; + void changed (void); +}; + +/** \brief Respond to the selected radiobutton changing + + This function responds to the radiobutton selection changing by grabbing the value + from the text box and putting it in the parameter. +*/ +void +ParamRadioButtonWdg::changed (void) +{ + if (this->get_active()) { + Glib::ustring data = this->get_label(); + _pref->set(data.c_str(), _doc, _node); + } + if (_changeSignal != NULL) { + _changeSignal->emit(); + } +} + + + +/** + \brief Creates a combobox widget for an enumeration parameter +*/ +Gtk::Widget * +ParamRadioButton::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) +{ + if (_gui_hidden) return NULL; + + Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4)); + Gtk::VBox * vbox = Gtk::manage(new Gtk::VBox(false, 0)); + + Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT, Gtk::ALIGN_TOP)); + label->show(); + hbox->pack_start(*label, false, false); + + // add choice strings as radiobuttons + // and select last selected option (_value) + bool first = true; + ParamRadioButtonWdg * radio; + Gtk::RadioButtonGroup group; + for (GSList * list = choices; list != NULL; list = g_slist_next(list)) { + optionentry * entr = reinterpret_cast<optionentry *>(list->data); + Glib::ustring * text = entr->guitext; + if (first) { + radio = Gtk::manage(new ParamRadioButtonWdg(*text, this, doc, node, changeSignal)); + group = radio->get_group(); + first = false; + } else { + radio = Gtk::manage(new ParamRadioButtonWdg(group, *text, this, doc, node, changeSignal)); + } + radio->show(); + vbox->pack_start(*radio, true, true); + if (!entr->value->compare(_value)) { + radio->set_active(); + } + } + + vbox->show(); + hbox->pack_end(*vbox, false, false); + hbox->show(); + + + return dynamic_cast<Gtk::Widget *>(hbox); +} + + +} /* namespace Extension */ +} /* namespace Inkscape */ + diff --git a/src/extension/param/radiobutton.h b/src/extension/param/radiobutton.h new file mode 100644 index 000000000..4bf596e4f --- /dev/null +++ b/src/extension/param/radiobutton.h @@ -0,0 +1,57 @@ +#ifndef INK_EXTENSION_PARAMRADIOBUTTON_H_SEEN +#define INK_EXTENSION_PARAMRADIOBUTTON_H_SEEN + +/** \file + * Radiobutton parameter for extensions. + */ + +/* + * Author: + * Johan Engelen <johan@shouraizou.nl> + * + * Copyright (C) 2006-2007 Johan Engelen + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gtkmm/widget.h> + +#include "xml/document.h" +#include <extension/extension-forward.h> + +#include "parameter.h" + +namespace Inkscape { +namespace Extension { + + + +// \brief A class to represent a radiobutton parameter of an extension +class ParamRadioButton : public Parameter { +private: + /** \brief Internal value. This should point to a string that has + been allocated in memory. And should be free'd. + It is the value of the current selected string */ + gchar * _value; + + GSList * choices; /**< A table to store the choice strings */ + +public: + ParamRadioButton(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml); + virtual ~ParamRadioButton(void); + Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal); + void string (std::string &string); + + const gchar * get (const SPDocument * /*doc*/, const Inkscape::XML::Node * /*node*/) { return _value; } + const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node); +}; /* class ParamRadioButton */ + + + + + +} /* namespace Extension */ +} /* namespace Inkscape */ + +#endif /* INK_EXTENSION_PARAMRADIOBUTTON_H_SEEN */ + diff --git a/src/extension/param/string.cpp b/src/extension/param/string.cpp new file mode 100644 index 000000000..36c3ce115 --- /dev/null +++ b/src/extension/param/string.cpp @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2005-2007 Authors: + * Ted Gould <ted@gould.cx> + * Johan Engelen <johan@shouraizou.nl> * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <gtkmm/adjustment.h> +#include <gtkmm/box.h> +#include <gtkmm/spinbutton.h> + +#include <xml/node.h> + +#include <extension/extension.h> +#include "string.h" + +namespace Inkscape { +namespace Extension { + + +/** \brief Free the allocated data. */ +ParamString::~ParamString(void) +{ + g_free(_value); +} + +/** \brief A function to set the \c _value + \param in The value to set to + \param doc A document that should be used to set the value. + \param node The node where the value may be placed + + This function sets the internal value, but it also sets the value + in the preferences structure. To put it in the right place, \c PREF_DIR + and \c pref_name() are used. + + To copy the data into _value the old memory must be free'd first. + It is important to note that \c g_free handles \c NULL just fine. Then + the passed in value is duplicated using \c g_strdup(). +*/ +const gchar * +ParamString::set (const gchar * in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/) +{ + if (in == NULL) return NULL; /* Can't have NULL string */ + + if (_value != NULL) + g_free(_value); + _value = g_strdup(in); + + gchar * prefname = this->pref_name(); + prefs_set_string_attribute(PREF_DIR, prefname, _value); + g_free(prefname); + + return _value; +} + +/** \brief Return the value as a string */ +void +ParamString::string (std::string &string) +{ + if (_value == NULL) + return; + + string += _value; + return; +} + +/** \brief Initialize the object, to do that, copy the data. */ +ParamString::ParamString (const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) : + Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext), _value(NULL) +{ + const char * defaultval = NULL; + if (sp_repr_children(xml) != NULL) + defaultval = sp_repr_children(xml)->content(); + + gchar * pref_name = this->pref_name(); + const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name); + g_free(pref_name); + + if (paramval != NULL) + defaultval = paramval; + if (defaultval != NULL) + _value = g_strdup(defaultval); + + return; +} + +/** \brief A special category of Gtk::Entry to handle string parameteres */ +class ParamStringEntry : public Gtk::Entry { +private: + ParamString * _pref; + SPDocument * _doc; + Inkscape::XML::Node * _node; + sigc::signal<void> * _changeSignal; +public: + /** \brief Build a string preference for the given parameter + \param pref Where to get the string from, and where to put it + when it changes. + */ + ParamStringEntry (ParamString * pref, SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) : + Gtk::Entry(), _pref(pref), _doc(doc), _node(node), _changeSignal(changeSignal) { + if (_pref->get(NULL, NULL) != NULL) + this->set_text(Glib::ustring(_pref->get(NULL, NULL))); + this->signal_changed().connect(sigc::mem_fun(this, &ParamStringEntry::changed_text)); + }; + void changed_text (void); +}; + + +/** \brief Respond to the text box changing + + This function responds to the box changing by grabbing the value + from the text box and putting it in the parameter. +*/ +void +ParamStringEntry::changed_text (void) +{ + Glib::ustring data = this->get_text(); + _pref->set(data.c_str(), _doc, _node); + if (_changeSignal != NULL) { + _changeSignal->emit(); + } + return; +} + +/** + \brief Creates a text box for the string parameter + + Builds a hbox with a label and a text box in it. +*/ +Gtk::Widget * +ParamString::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) +{ + if (_gui_hidden) return NULL; + + Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4)); + + Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT)); + label->show(); + hbox->pack_start(*label, false, false); + + ParamStringEntry * textbox = new ParamStringEntry(this, doc, node, changeSignal); + textbox->show(); + hbox->pack_start(*textbox, true, true); + + hbox->show(); + + return dynamic_cast<Gtk::Widget *>(hbox); +} + +} /* namespace Extension */ +} /* namespace Inkscape */ diff --git a/src/extension/param/string.h b/src/extension/param/string.h new file mode 100644 index 000000000..0a1a0f2a3 --- /dev/null +++ b/src/extension/param/string.h @@ -0,0 +1,49 @@ +#ifndef INK_EXTENSION_PARAMSTRING_H_SEEN +#define INK_EXTENSION_PARAMSTRING_H_SEEN + +/* + * Copyright (C) 2005-2007 Authors: + * Ted Gould <ted@gould.cx> + * Johan Engelen <johan@shouraizou.nl> * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gtkmm/widget.h> +#include <xml/node.h> +#include <document.h> +#include "parameter.h" + +namespace Inkscape { +namespace Extension { + +class ParamString : public Parameter { +private: + /** \brief Internal value. This should point to a string that has + been allocated in memory. And should be free'd. */ + gchar * _value; +public: + ParamString(const gchar * name, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, bool gui_hidden, const gchar * gui_tip, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml); + virtual ~ParamString(void); + /** \brief Returns \c _value, with a \i const to protect it. */ + const gchar * get (const SPDocument * /*doc*/, const Inkscape::XML::Node * /*node*/) { return _value; } + const gchar * set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node); + Gtk::Widget * get_widget(SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal); + void string (std::string &string); +}; + + +} /* namespace Extension */ +} /* namespace Inkscape */ + +#endif /* INK_EXTENSION_PARAMSTRING_H_SEEN */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : |
