enum.cpp revision 05599a3f1fae49d54a2102c41c31271a158410de
2521N/A/** \file
2521N/A * extension parameter for enumerations.
2521N/A *
2521N/A * It uses a Gtk:ComboBoxText widget in the extension UI.
2521N/A */
2521N/A
2521N/A/*
2521N/A * Author:
2521N/A * Johan Engelen <johan@shouraizou.nl>
2521N/A *
2521N/A * Copyright (C) 2006-2007 Johan Engelen
2521N/A *
2521N/A * Released under GNU GPL, read the file 'COPYING' for more information
2521N/A */
2521N/A
2521N/A#ifdef HAVE_CONFIG_H
2521N/A# include "config.h"
2521N/A#endif
2521N/A
2521N/A
2521N/A#include <gtkmm/box.h>
2521N/A#include <gtkmm/comboboxtext.h>
5403N/A#include <gtkmm/tooltips.h>
2521N/A#include <gtkmm/label.h>
2521N/A#include <glibmm/i18n.h>
2521N/A
2521N/A#include "xml/node.h"
2968N/A#include "extension/extension.h"
2521N/A#include "document-private.h"
2521N/A#include "sp-object.h"
6850N/A#include "enum.h"
2521N/A#include "preferences.h"
2899N/A
2521N/Anamespace Inkscape {
2521N/Anamespace Extension {
2521N/A
2521N/A/* For internal use only.
2521N/A 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. */
2521N/Aclass enumentry {
2521N/Apublic:
2521N/A enumentry (Glib::ustring &val, Glib::ustring &text) :
3998N/A value(val),
2892N/A guitext(text)
6850N/A {}
6850N/A
2521N/A Glib::ustring value;
3998N/A Glib::ustring guitext;
2521N/A};
2521N/A
2892N/A
2521N/AParamComboBox::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) :
2892N/A Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext), _indent(0)
3163N/A{
2892N/A choices = NULL;
5403N/A _value = NULL;
5403N/A
2521N/A // Read XML tree to add enumeration items:
2892N/A // printf("Extension Constructor: ");
2892N/A if (xml != NULL) {
2892N/A for (Inkscape::XML::Node *node = xml->firstChild(); node; node = node->next()) {
2521N/A char const * chname = node->name();
2892N/A if (!strcmp(chname, INKSCAPE_EXTENSION_NS "item") || !strcmp(chname, INKSCAPE_EXTENSION_NS "_item")) {
3998N/A Glib::ustring newguitext, newvalue;
3998N/A const char * contents = NULL;
3998N/A if (node->firstChild()) {
6850N/A contents = node->firstChild()->content();
6850N/A }
6850N/A if (contents != NULL) {
6850N/A // don't translate when 'item' but do translate when '_item'
6850N/A // NOTE: internal extensions use build_from_mem and don't need _item but
6850N/A // still need to include if are to be localized
6850N/A if (!strcmp(chname, INKSCAPE_EXTENSION_NS "_item")) {
6850N/A if (node->attribute("msgctxt") != NULL) {
6850N/A newguitext = g_dpgettext2(NULL, node->attribute("msgctxt"), contents);
6850N/A } else {
6850N/A newguitext = _(contents);
6850N/A }
3998N/A } else {
3998N/A newguitext = contents;
3998N/A }
3998N/A } else
3998N/A continue;
3998N/A
3998N/A const char * val = node->attribute("value");
3998N/A if (val != NULL) {
3998N/A newvalue = val;
6850N/A } else {
6850N/A newvalue = contents;
6850N/A }
6850N/A
6850N/A if ( (!newguitext.empty()) && (!newvalue.empty()) ) { // logical error if this is not true here
6850N/A choices = g_slist_append( choices, new enumentry(newvalue, newguitext) );
3998N/A }
3998N/A }
3998N/A }
3998N/A }
3998N/A
3998N/A // Initialize _value with the default value from xml
3998N/A // for simplicity : default to the contents of the first xml-child
3998N/A const char * defaultval = NULL;
3998N/A if (xml->firstChild() && xml->firstChild()->firstChild()) {
3998N/A defaultval = xml->firstChild()->attribute("value");
3998N/A }
3998N/A
5403N/A const char * indent = xml->attribute("indent");
5403N/A if (indent != NULL) {
5403N/A _indent = atoi(indent) * 12;
3998N/A }
3998N/A
3998N/A gchar * pref_name = this->pref_name();
3998N/A Inkscape::Preferences *prefs = Inkscape::Preferences::get();
3998N/A Glib::ustring paramval = prefs->getString(extension_pref_root + pref_name);
3998N/A g_free(pref_name);
3998N/A
3998N/A if (!paramval.empty()) {
3998N/A defaultval = paramval.data();
3998N/A }
3998N/A if (defaultval != NULL) {
3998N/A _value = g_strdup(defaultval);
3998N/A }
3998N/A
3998N/A return;
5403N/A}
5403N/A
5403N/AParamComboBox::~ParamComboBox (void)
5403N/A{
5403N/A //destroy choice strings
5403N/A for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {
3998N/A delete (reinterpret_cast<enumentry *>(list->data));
3998N/A }
3998N/A g_slist_free(choices);
3998N/A
3998N/A g_free(_value);
3998N/A}
3998N/A
3998N/A
3998N/A/** \brief A function to set the \c _value
3998N/A \param in The value to set
3998N/A \param doc A document that should be used to set the value.
3998N/A \param node The node where the value may be placed
5403N/A
5403N/A This function sets ONLY the internal value, but it also sets the value
5403N/A in the preferences structure. To put it in the right place, \c PREF_DIR
5403N/A and \c pref_name() are used.
5403N/A
5403N/A To copy the data into _value the old memory must be free'd first.
5403N/A It is important to note that \c g_free handles \c NULL just fine. Then
5403N/A the passed in value is duplicated using \c g_strdup().
5403N/A*/
5403N/Aconst gchar *
5403N/AParamComboBox::set (const gchar * in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/)
5403N/A{
6850N/A if (in == NULL) {
6850N/A return NULL; /* Can't have NULL string */
6850N/A }
6850N/A
6850N/A Glib::ustring settext;
2521N/A for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {
2892N/A enumentry * entr = reinterpret_cast<enumentry *>(list->data);
3998N/A if ( !entr->guitext.compare(in) ) {
3998N/A settext = entr->value;
3998N/A break; // break out of for loop
3998N/A }
3998N/A }
3998N/A if (!settext.empty()) {
2521N/A if (_value != NULL) {
6850N/A g_free(_value);
2521N/A }
2521N/A _value = g_strdup(settext.data());
2521N/A gchar * prefname = this->pref_name();
2521N/A Inkscape::Preferences *prefs = Inkscape::Preferences::get();
2521N/A prefs->setString(extension_pref_root + prefname, _value);
2521N/A g_free(prefname);
3998N/A }
3998N/A
2521N/A return _value;
2521N/A}
2521N/A
3998N/Avoid
3998N/AParamComboBox::changed (void) {
2521N/A
2521N/A}
2521N/A
3998N/A
2521N/A/**
2521N/A \brief A function to get the value of the parameter in string form
2521N/A \return A string with the 'value' as command line argument
2521N/A*/
2521N/Avoid
2521N/AParamComboBox::string (std::string &string)
2521N/A{
2521N/A string += _value;
2521N/A return;
6850N/A}
2521N/A
2521N/A
2521N/A
2521N/A
2521N/A/** \brief A special category of Gtk::Entry to handle string parameteres */
2892N/Aclass ParamComboBoxEntry : public Gtk::ComboBoxText {
2892N/Aprivate:
3998N/A ParamComboBox * _pref;
2521N/A SPDocument * _doc;
2521N/A Inkscape::XML::Node * _node;
2521N/A sigc::signal<void> * _changeSignal;
2521N/Apublic:
2521N/A /** \brief Build a string preference for the given parameter
2521N/A \param pref Where to get the string from, and where to put it
2521N/A when it changes.
6850N/A */
6850N/A ParamComboBoxEntry (ParamComboBox * pref, SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal) :
6850N/A Gtk::ComboBoxText(), _pref(pref), _doc(doc), _node(node), _changeSignal(changeSignal) {
6850N/A this->signal_changed().connect(sigc::mem_fun(this, &ParamComboBoxEntry::changed));
6850N/A };
2521N/A void changed (void);
2521N/A};
2521N/A
2521N/A/** \brief Respond to the text box changing
2892N/A
2521N/A This function responds to the box changing by grabbing the value
2521N/A from the text box and putting it in the parameter.
2892N/A*/
2521N/Avoid
2521N/AParamComboBoxEntry::changed (void)
2521N/A{
2521N/A Glib::ustring data = this->get_active_text();
2521N/A _pref->set(data.c_str(), _doc, _node);
2521N/A if (_changeSignal != NULL) {
2892N/A _changeSignal->emit();
2521N/A }
5403N/A}
2521N/A
2521N/A/**
2521N/A \brief Creates a combobox widget for an enumeration parameter
2521N/A*/
3998N/AGtk::Widget *
3998N/AParamComboBox::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal)
3998N/A{
3998N/A if (_gui_hidden) {
5403N/A return NULL;
3998N/A }
3998N/A
3998N/A Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
3998N/A
3998N/A Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT));
3998N/A label->show();
5403N/A hbox->pack_start(*label, false, false, _indent);
2521N/A
2521N/A ParamComboBoxEntry * combo = Gtk::manage(new ParamComboBoxEntry(this, doc, node, changeSignal));
3998N/A // add choice strings:
6850N/A Glib::ustring settext;
6850N/A for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {
2521N/A enumentry * entr = reinterpret_cast<enumentry *>(list->data);
3998N/A Glib::ustring text = entr->guitext;
5403N/A combo->append_text(text);
5403N/A if ( _value && !entr->value.compare(_value) ) {
5403N/A settext = entr->guitext;
5403N/A }
6850N/A }
5403N/A if (!settext.empty()) {
5403N/A combo->set_active_text(settext);
2892N/A }
3998N/A
6850N/A combo->show();
5403N/A hbox->pack_start(*combo, true, true);
6850N/A
2892N/A hbox->show();
6850N/A
6850N/A return dynamic_cast<Gtk::Widget *>(hbox);
6850N/A}
3998N/A
3998N/A
5403N/A} /* namespace Extension */
2892N/A} /* namespace Inkscape */
2892N/A