1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2005-2007 Authors:
4  *   Ted Gould <ted@gould.cx>
5  *   Johan Engelen <johan@shouraizou.nl> *
6  *   Jon A. Cruz <jon@joncruz.org>
7  * Released under GNU GPL v2+, read the file 'COPYING' for more information.
8  */
9 
10 #include "parameter-int.h"
11 
12 #include <gtkmm/adjustment.h>
13 #include <gtkmm/box.h>
14 
15 #include "preferences.h"
16 
17 #include "extension/extension.h"
18 
19 #include "ui/widget/spinbutton.h"
20 #include "ui/widget/spin-scale.h"
21 
22 #include "xml/node.h"
23 
24 
25 namespace Inkscape {
26 namespace Extension {
27 
28 
ParamInt(Inkscape::XML::Node * xml,Inkscape::Extension::Extension * ext)29 ParamInt::ParamInt(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext)
30     : InxParameter(xml, ext)
31 {
32     // get value
33     if (xml->firstChild()) {
34         const char *value = xml->firstChild()->content();
35         if (value) {
36             _value = strtol(value, nullptr, 0);
37         }
38     }
39 
40     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
41     _value = prefs->getInt(pref_name(), _value);
42 
43     // parse and apply limits
44     const char *min = xml->attribute("min");
45     if (min) {
46         _min = strtol(min, nullptr, 0);
47     }
48 
49     const char *max = xml->attribute("max");
50     if (max) {
51         _max = strtol(max, nullptr, 0);
52     }
53 
54     if (_value < _min) {
55         _value = _min;
56     }
57 
58     if (_value > _max) {
59         _value = _max;
60     }
61 
62     // parse appearance
63     if (_appearance) {
64         if (!strcmp(_appearance, "full")) {
65             _mode = FULL;
66         } else {
67             g_warning("Invalid value ('%s') for appearance of parameter '%s' in extension '%s'",
68                       _appearance, _name, _extension->get_id());
69         }
70     }
71 }
72 
73 /**
74  * A function to set the \c _value.
75  * This function sets the internal value, but it also sets the value
76  * in the preferences structure.  To put it in the right place \c pref_name() is used.
77  *
78  * @param  in   The value to set to.
79  */
set(int in)80 int ParamInt::set(int in)
81 {
82     _value = in;
83     if (_value > _max) {
84         _value = _max;
85     }
86     if (_value < _min) {
87         _value = _min;
88     }
89 
90     Inkscape::Preferences *prefs = Inkscape::Preferences::get();
91     prefs->setInt(pref_name(), _value);
92 
93     return _value;
94 }
95 
96 /** A class to make an adjustment that uses Extension params. */
97 class ParamIntAdjustment : public Gtk::Adjustment {
98     /** The parameter to adjust. */
99     ParamInt *_pref;
100     sigc::signal<void> *_changeSignal;
101 public:
102     /** Make the adjustment using an extension and the string describing the parameter. */
ParamIntAdjustment(ParamInt * param,sigc::signal<void> * changeSignal)103     ParamIntAdjustment(ParamInt *param, sigc::signal<void> *changeSignal)
104         : Gtk::Adjustment(0.0, param->min(), param->max(), 1.0, 10.0, 0)
105         , _pref(param)
106         , _changeSignal(changeSignal)
107     {
108         this->set_value(_pref->get());
109         this->signal_value_changed().connect(sigc::mem_fun(this, &ParamIntAdjustment::val_changed));
110     };
111 
112     void val_changed ();
113 }; /* class ParamIntAdjustment */
114 
115 /**
116  * A function to respond to the value_changed signal from the adjustment.
117  *
118  * This function just grabs the value from the adjustment and writes
119  * it to the parameter.  Very simple, but yet beautiful.
120  */
val_changed()121 void ParamIntAdjustment::val_changed()
122 {
123     _pref->set((int)this->get_value());
124     if (_changeSignal != nullptr) {
125         _changeSignal->emit();
126     }
127 }
128 
129 /**
130  * Creates a Int Adjustment for a int parameter.
131  *
132  * Builds a hbox with a label and a int adjustment in it.
133  */
134 Gtk::Widget *
get_widget(sigc::signal<void> * changeSignal)135 ParamInt::get_widget(sigc::signal<void> *changeSignal)
136 {
137     if (_hidden) {
138         return nullptr;
139     }
140 
141     Gtk::Box *hbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, GUI_PARAM_WIDGETS_SPACING));
142 
143     auto pia = new ParamIntAdjustment(this, changeSignal);
144     Glib::RefPtr<Gtk::Adjustment> fadjust(pia);
145 
146     if (_mode == FULL) {
147 
148         Glib::ustring text;
149         if (_text != nullptr)
150             text = _text;
151         UI::Widget::SpinScale *scale = Gtk::manage(new UI::Widget::SpinScale(text, fadjust, 0));
152         scale->set_size_request(400, -1);
153         scale->show();
154         hbox->pack_start(*scale, true, true);
155     } else if (_mode == DEFAULT) {
156         Gtk::Label *label = Gtk::manage(new Gtk::Label(_text, Gtk::ALIGN_START));
157         label->show();
158         hbox->pack_start(*label, true, true);
159 
160         auto spin = Gtk::manage(new Inkscape::UI::Widget::SpinButton(fadjust, 1.0, 0));
161         spin->show();
162         hbox->pack_start(*spin, false, false);
163     }
164 
165     hbox->show();
166 
167     return dynamic_cast<Gtk::Widget *>(hbox);
168 }
169 
value_to_string() const170 std::string ParamInt::value_to_string() const
171 {
172     char value_string[32];
173     snprintf(value_string, 32, "%d", _value);
174     return value_string;
175 }
176 
177 }  // namespace Extension
178 }  // namespace Inkscape
179 
180 /*
181   Local Variables:
182   mode:c++
183   c-file-style:"stroustrup"
184   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
185   indent-tabs-mode:nil
186   fill-column:99
187   End:
188 */
189 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
190