Code

Translations. French translation minor update.
[inkscape.git] / src / extension / param / radiobutton.cpp
1 /** \file
2  * extension parameter for radiobuttons.
3  *
4  * It uses a Gtk:ComboBoxText widget in the extension UI.
5  */
7 /*
8  * Author:
9  *   Johan Engelen <johan@shouraizou.nl>
10  *
11  * Copyright (C) 2006-2007 Johan Engelen
12  * Copyright (C) 2008 Jon A. Cruz
13  *
14  * Released under GNU GPL, read the file 'COPYING' for more information
15  */
17 #ifdef HAVE_CONFIG_H
18 # include "config.h"
19 #endif
22 #include <gtkmm/box.h>
23 #include <gtkmm/comboboxtext.h>
24 #include <gtkmm/radiobutton.h>
25 #include <gtkmm/radiobuttongroup.h>
26 #include <gtkmm/tooltips.h>
27 #include <gtkmm/label.h>
28 #include <glibmm/i18n.h>
30 #include "xml/node.h"
31 #include "extension/extension.h"
32 #include "preferences.h"
33 #include "document-private.h"
34 #include "sp-object.h"
36 #include "radiobutton.h"
38 /** \brief  The root directory in the preferences database for extension
39             related parameters. */
40 #define PREF_DIR "extensions"
42 namespace Inkscape {
43 namespace Extension {
45 /* For internal use only.
46      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. */
47 class optionentry {
48 public:
49     optionentry (Glib::ustring * val, Glib::ustring * text) {
50         value = val;
51         guitext = text;
52     }
53     ~optionentry() {
54         delete value;
55         delete guitext;
56     }
58     Glib::ustring * value;
59     Glib::ustring * guitext;
60 };
62 ParamRadioButton::ParamRadioButton (const gchar * name,
63                                     const gchar * guitext,
64                                     const gchar * desc,
65                                     const Parameter::_scope_t scope,
66                                     bool gui_hidden,
67                                     const gchar * gui_tip,
68                                     Inkscape::Extension::Extension * ext,
69                                     Inkscape::XML::Node * xml,
70                                     AppearanceMode mode) :
71     Parameter(name, guitext, desc, scope, gui_hidden, gui_tip, ext),
72     _value(0),
73     _mode(mode),
74     choices(0)
75 {
76     // Read XML tree to add enumeration items:
77     // printf("Extension Constructor: ");
78     if (xml != NULL) {
79         Inkscape::XML::Node *child_repr = sp_repr_children(xml);
80         while (child_repr != NULL) {
81             char const * chname = child_repr->name();
82             if (!strcmp(chname, INKSCAPE_EXTENSION_NS "option") || !strcmp(chname, INKSCAPE_EXTENSION_NS "_option")) {
83                 Glib::ustring * newguitext = NULL;
84                 Glib::ustring * newvalue = NULL;
85                 const char * contents = sp_repr_children(child_repr)->content();
87                 if (contents != NULL) {
88                     // don't translate when 'item' but do translate when '_option'
89                     if (!strcmp(chname, INKSCAPE_EXTENSION_NS "_option")) {
90                         if (child_repr->attribute("msgctxt") != NULL) {
91                             newguitext =  new Glib::ustring(g_dpgettext2(NULL, child_repr->attribute("msgctxt"), contents));
92                         } else {
93                             newguitext =  new Glib::ustring(_(contents));
94                         }
95                     } else {
96                         newguitext =  new Glib::ustring(contents);
97                     }
98                 } else
99                     continue;
103                 const char * val = child_repr->attribute("value");
104                 if (val != NULL)
105                     newvalue = new Glib::ustring(val);
106                 else
107                     newvalue = new Glib::ustring(contents);
109                 if ( (newguitext) && (newvalue) ) {   // logical error if this is not true here
110                     choices = g_slist_append( choices, new optionentry(newvalue, newguitext) );
111                 }
112             }
113             child_repr = sp_repr_next(child_repr);
114         }
115     }
117     // Initialize _value with the default value from xml
118     // for simplicity : default to the contents of the first xml-child
119     const char * defaultval = NULL;
120     if (choices)
121         defaultval = ((optionentry*) choices->data)->value->c_str();
123     gchar * pref_name = this->pref_name();
124     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
125     Glib::ustring paramval = prefs->getString(extension_pref_root + pref_name);
126     g_free(pref_name);
128     if (!paramval.empty())
129         defaultval = paramval.data();
130     if (defaultval != NULL)
131         _value = g_strdup(defaultval);  // allocate space for _value
133     return;
136 ParamRadioButton::~ParamRadioButton (void)
138     //destroy choice strings
139     for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {
140         delete (reinterpret_cast<optionentry *>(list->data));
141     }
142     g_slist_free(choices);
144     g_free(_value);
148 /** \brief  A function to set the \c _value
149     \param  in   The value to set
150     \param  doc  A document that should be used to set the value.
151     \param  node The node where the value may be placed
153     This function sets ONLY the internal value, but it also sets the value
154     in the preferences structure.  To put it in the right place, \c PREF_DIR
155     and \c pref_name() are used.
157     To copy the data into _value the old memory must be free'd first.
158     It is important to note that \c g_free handles \c NULL just fine.  Then
159     the passed in value is duplicated using \c g_strdup().
160 */
161 const gchar *
162 ParamRadioButton::set (const gchar * in, SPDocument * /*doc*/, Inkscape::XML::Node * /*node*/)
164     if (in == NULL) return NULL; /* Can't have NULL string */
166     Glib::ustring * settext = NULL;
167     for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {
168         optionentry * entr = reinterpret_cast<optionentry *>(list->data);
169         if ( !entr->guitext->compare(in) ) {
170             settext = entr->value;
171             break;  // break out of for loop
172         }
173     }
174     if (settext) {
175         if (_value != NULL) g_free(_value);
176         _value = g_strdup(settext->c_str());
177         gchar * prefname = this->pref_name();
178         Inkscape::Preferences *prefs = Inkscape::Preferences::get();
179         prefs->setString(extension_pref_root + prefname, _value);
180         g_free(prefname);
181     }
183     return _value;
187 /**
188     \brief  A function to get the current value of the parameter in a string form
189     \return A string with the 'value' as command line argument
190 */
191 void
192 ParamRadioButton::string (std::string &string)
194     string += _value;
195     return;
198 /** \brief  A special radiobutton class to use in ParamRadioButton */
199 class ParamRadioButtonWdg : public Gtk::RadioButton {
200 private:
201     ParamRadioButton * _pref;
202     SPDocument * _doc;
203     Inkscape::XML::Node * _node;
204     sigc::signal<void> * _changeSignal;
205 public:
206     /** \brief  Build a string preference for the given parameter
207         \param  pref  Where to put the radiobutton's string when it is selected.
208     */
209     ParamRadioButtonWdg ( Gtk::RadioButtonGroup& group, const Glib::ustring& label,
210                           ParamRadioButton * pref, SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal ) :
211         Gtk::RadioButton(group, label), _pref(pref), _doc(doc), _node(node), _changeSignal(changeSignal) {
212         add_changesignal();
213     };
214     ParamRadioButtonWdg ( const Glib::ustring& label,
215                           ParamRadioButton * pref, SPDocument * doc, Inkscape::XML::Node * node , sigc::signal<void> * changeSignal) :
216         Gtk::RadioButton(label), _pref(pref), _doc(doc), _node(node), _changeSignal(changeSignal) {
217         add_changesignal();
218     };
219     void add_changesignal() {
220         this->signal_toggled().connect(sigc::mem_fun(this, &ParamRadioButtonWdg::changed));
221     };
222     void changed (void);
223 };
225 /** \brief  Respond to the selected radiobutton changing
227     This function responds to the radiobutton selection changing by grabbing the value
228     from the text box and putting it in the parameter.
229 */
230 void
231 ParamRadioButtonWdg::changed (void)
233     if (this->get_active()) {
234         Glib::ustring data = this->get_label();
235         _pref->set(data.c_str(), _doc, _node);
236     }
237     if (_changeSignal != NULL) {
238         _changeSignal->emit();
239     }
243 class ComboWdg : public Gtk::ComboBoxText {
244 public:
245     ComboWdg(ParamRadioButton* base, SPDocument * doc, Inkscape::XML::Node * node) :
246         Gtk::ComboBoxText(),
247         base(base),
248         doc(doc),
249         node(node)
250     {
251     }
252     virtual ~ComboWdg() {}
254 protected:
255     ParamRadioButton* base;
256     SPDocument* doc;
257     Inkscape::XML::Node* node;
259     virtual void on_changed() {
260         if ( base ) {
261             base->set(get_active_text().c_str(), doc, node);
262         }
263     }
264 };
266 /**
267     \brief  Creates a combobox widget for an enumeration parameter
268 */
269 Gtk::Widget *
270 ParamRadioButton::get_widget (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal)
272     if (_gui_hidden) return NULL;
274     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
275     Gtk::VBox * vbox = Gtk::manage(new Gtk::VBox(false, 0));
277     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT, Gtk::ALIGN_TOP));
278     label->show();
279     hbox->pack_start(*label, false, false);
281     Gtk::ComboBoxText* cbt = 0;
282     bool comboSet = false;
283     if (_mode == MINIMAL) {
284         cbt = Gtk::manage(new ComboWdg(this, doc, node));
285         cbt->show();
286         vbox->pack_start(*cbt, false, false);
287     }
289     // add choice strings as radiobuttons
290     // and select last selected option (_value)
291     Gtk::RadioButtonGroup group;
292     for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {
293         optionentry * entr = reinterpret_cast<optionentry *>(list->data);
294         Glib::ustring * text = entr->guitext;
295         switch ( _mode ) {
296             case MINIMAL:
297             {
298                 cbt->append_text(*text);
299                 if (!entr->value->compare(_value)) {
300                     cbt->set_active_text(*text);
301                     comboSet = true;
302                 }
303             }
304             break;
305             case COMPACT:
306             case FULL:
307             {
308                 ParamRadioButtonWdg * radio = Gtk::manage(new ParamRadioButtonWdg(group, *text, this, doc, node, changeSignal));
309                 radio->show();
310                 vbox->pack_start(*radio, true, true);
311                 if (!entr->value->compare(_value)) {
312                     radio->set_active();
313                 }
314             }
315             break;
316         }
317     }
319     if ( (_mode == MINIMAL) && !comboSet) {
320         cbt->set_active(0);
321     }
323     vbox->show();
324     hbox->pack_end(*vbox, false, false);
325     hbox->show();
328     return dynamic_cast<Gtk::Widget *>(hbox);
332 }  /* namespace Extension */
333 }  /* namespace Inkscape */
335 /*
336   Local Variables:
337   mode:c++
338   c-file-style:"stroustrup"
339   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
340   indent-tabs-mode:nil
341   fill-column:99
342   End:
343 */
344 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :