Code

more unreffing temporary styles properly
[inkscape.git] / src / extension / paramradiobutton.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  *
13  * Released under GNU GPL, read the file 'COPYING' for more information
14  */
16 #ifdef HAVE_CONFIG_H
17 # include "config.h"
18 #endif
21 #include <gtkmm/box.h>
22 #include <gtkmm/radiobutton.h>
23 #include <gtkmm/radiobuttongroup.h>
24 #include <gtkmm/tooltips.h>
25 #include <gtkmm/label.h>
27 #include <glibmm/i18n.h>
29 #include <xml/node.h>
31 #include "extension.h"
32 #include "prefs-utils.h"
33 #include "document-private.h"
34 #include "sp-object.h"
36 #include "paramradiobutton.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, const gchar * guitext, const gchar * desc, const Parameter::_scope_t scope, Inkscape::Extension::Extension * ext, Inkscape::XML::Node * xml) :
63     Parameter(name, guitext, desc, scope, ext)
64 {
65     choices = NULL;
66     _value = NULL;
68     // Read XML tree to add enumeration items:
69     // printf("Extension Constructor: ");
70     if (xml != NULL) {
71         Inkscape::XML::Node *child_repr = sp_repr_children(xml);
72         while (child_repr != NULL) {
73             char const * chname = child_repr->name();
74             if (!strcmp(chname, "option")) {
75                 Glib::ustring * newguitext = NULL;
76                 Glib::ustring * newvalue = NULL;
77                 const char * contents = sp_repr_children(child_repr)->content();
78                 if (contents != NULL)
79                      newguitext = new Glib::ustring(contents);
80                 else
81                     continue;  
82                     
83                 const char * val = child_repr->attribute("value");
84                 if (val != NULL)
85                     newvalue = new Glib::ustring(val);
86                 else
87                     newvalue = new Glib::ustring(*newguitext);
88                             
89                 if ( (newguitext) && (newvalue) ) {   // logical error if this is not true here
90                     choices = g_slist_append( choices, new optionentry(newvalue, newguitext) );
91                 }
92             }
93             child_repr = sp_repr_next(child_repr);
94         }
95     }
97     // Initialize _value with the default value from xml
98     // for simplicity : default to the contents of the first xml-child
99     const char * defaultval = NULL;
100     if (choices)
101         defaultval = ((optionentry*) choices->data)->value->c_str();
103     gchar * pref_name = this->pref_name();
104     const gchar * paramval = prefs_get_string_attribute(PREF_DIR, pref_name);
105     g_free(pref_name);
107     if (paramval != NULL)
108         defaultval = paramval;
109     if (defaultval != NULL)
110         _value = g_strdup(defaultval);  // allocate space for _value
112     return;
115 ParamRadioButton::~ParamRadioButton (void)
117     //destroy choice strings
118     for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {
119         delete (reinterpret_cast<optionentry *>(list->data));
120     }
121     g_slist_free(choices);
123     g_free(_value);
127 /** \brief  A function to set the \c _value
128     \param  in   The value to set
129     \param  doc  A document that should be used to set the value.
130     \param  node The node where the value may be placed
132     This function sets ONLY the internal value, but it also sets the value
133     in the preferences structure.  To put it in the right place, \c PREF_DIR
134     and \c pref_name() are used.
136     To copy the data into _value the old memory must be free'd first.
137     It is important to note that \c g_free handles \c NULL just fine.  Then
138     the passed in value is duplicated using \c g_strdup().
139 */
140 const gchar *
141 ParamRadioButton::set (const gchar * in, SPDocument * doc, Inkscape::XML::Node * node)
143     if (in == NULL) return NULL; /* Can't have NULL string */
145     Glib::ustring * settext = NULL;
146     for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {
147         optionentry * entr = reinterpret_cast<optionentry *>(list->data);
148         if ( !entr->guitext->compare(in) ) {
149             settext = entr->value;
150             break;  // break out of for loop
151         }
152     }
153     if (settext) {
154         if (_value != NULL) g_free(_value);
155         _value = g_strdup(settext->c_str());
156         gchar * prefname = this->pref_name();
157         prefs_set_string_attribute(PREF_DIR, prefname, _value);
158         g_free(prefname);
159     }
161     return _value;
165 /**
166     \brief  A function to get the current value of the parameter in a string form
167     \return A string with the 'value' as command line argument
168 */
169 Glib::ustring *
170 ParamRadioButton::string (void)
172     Glib::ustring * param_string = new Glib::ustring("");
174     *param_string += "\"";
175     *param_string += _value;
176     *param_string += "\"";
178     return param_string;
181 /** \brief  A special radiobutton class to use in ParamRadioButton */
182 class ParamRadioButtonWdg : public Gtk::RadioButton {
183 private:
184     ParamRadioButton * _pref;
185     SPDocument * _doc;
186     Inkscape::XML::Node * _node;
187 public:
188     /** \brief  Build a string preference for the given parameter
189         \param  pref  Where to put the radiobutton's string when it is selected.
190     */
191     ParamRadioButtonWdg ( Gtk::RadioButtonGroup& group, const Glib::ustring& label,
192                           ParamRadioButton * pref, SPDocument * doc, Inkscape::XML::Node * node ) :
193         Gtk::RadioButton(group, label), _pref(pref), _doc(doc), _node(node) {
194         add_changesignal();
195     };
196     ParamRadioButtonWdg ( const Glib::ustring& label,
197                           ParamRadioButton * pref, SPDocument * doc, Inkscape::XML::Node * node ) :
198         Gtk::RadioButton(label), _pref(pref), _doc(doc), _node(node) {
199         add_changesignal();
200     };
201     void add_changesignal() {
202         this->signal_toggled().connect(sigc::mem_fun(this, &ParamRadioButtonWdg::changed));
203     };
204     void changed (void);
205 };
207 /** \brief  Respond to the selected radiobutton changing
209     This function responds to the radiobutton selection changing by grabbing the value
210     from the text box and putting it in the parameter.
211 */
212 void
213 ParamRadioButtonWdg::changed (void)
215     if (this->get_active()) {
216         Glib::ustring data = this->get_label();
217         _pref->set(data.c_str(), _doc, _node);
218     }
223 /**
224     \brief  Creates a combobox widget for an enumeration parameter
225 */
226 Gtk::Widget *
227 ParamRadioButton::get_widget (SPDocument * doc, Inkscape::XML::Node * node)
229     Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false, 4));
230     Gtk::VBox * vbox = Gtk::manage(new Gtk::VBox(false, 0));
232     Gtk::Label * label = Gtk::manage(new Gtk::Label(_(_text), Gtk::ALIGN_LEFT, Gtk::ALIGN_TOP));
233     label->show();
234     hbox->pack_start(*label, false, false);
236     // add choice strings as radiobuttons
237     // and select last selected option (_value)
238     bool first = true;
239     ParamRadioButtonWdg * radio;
240     Gtk::RadioButtonGroup group;
241     for (GSList * list = choices; list != NULL; list = g_slist_next(list)) {
242         optionentry * entr = reinterpret_cast<optionentry *>(list->data);
243         Glib::ustring * text = entr->guitext;
244         if (first) {
245             radio = Gtk::manage(new ParamRadioButtonWdg(*text, this, doc, node));
246             group = radio->get_group();
247             first = false;
248         } else {
249             radio = Gtk::manage(new ParamRadioButtonWdg(group, *text, this, doc, node));
250         }
251         radio->show();
252         vbox->pack_start(*radio, true, true);
253         if (!entr->value->compare(_value)) {
254             radio->set_active();
255         }
256     }
258     vbox->show();
259     hbox->pack_end(*vbox, false, false);
260     hbox->show();
263     return dynamic_cast<Gtk::Widget *>(hbox);
267 }  /* namespace Extension */
268 }  /* namespace Inkscape */