1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /** @file
3 * Parameters for extensions.
4 */
5 /* Author:
6 * Ted Gould <ted@gould.cx>
7 * Johan Engelen <johan@shouraizou.nl>
8 * Jon A. Cruz <jon@joncruz.org>
9 *
10 * Copyright (C) 2005-2007 Authors
11 *
12 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
13 */
14
15 #include <cstring>
16 #include <list>
17
18 #include <glibmm/i18n.h>
19 #include <sigc++/sigc++.h>
20
21 #include "parameter.h"
22 #include "parameter-bool.h"
23 #include "parameter-color.h"
24 #include "parameter-float.h"
25 #include "parameter-int.h"
26 #include "parameter-notebook.h"
27 #include "parameter-optiongroup.h"
28 #include "parameter-path.h"
29 #include "parameter-string.h"
30 #include "widget.h"
31 #include "widget-label.h"
32
33 #include "extension/extension.h"
34
35 #include "object/sp-defs.h"
36
37 #include "ui/widget/color-notebook.h"
38
39 #include "xml/node.h"
40
41
42 namespace Inkscape {
43 namespace Extension {
44
45
46 // Re-implement ParamDescription for backwards-compatibility, deriving from both, WidgetLabel and InxParameter.
47 // TODO: Should go away eventually...
48 class ParamDescription : public virtual WidgetLabel, public virtual InxParameter {
49 public:
ParamDescription(Inkscape::XML::Node * xml,Inkscape::Extension::Extension * ext)50 ParamDescription(Inkscape::XML::Node *xml, Inkscape::Extension::Extension *ext)
51 : WidgetLabel(xml, ext)
52 , InxParameter(xml, ext)
53 {}
54
get_widget(sigc::signal<void> * changeSignal)55 Gtk::Widget *get_widget(sigc::signal<void> *changeSignal) override
56 {
57 return this->WidgetLabel::get_widget(changeSignal);
58 }
59
60 // Well, no, I don't have a value! That's why I should not be an InxParameter!
value_to_string() const61 std::string value_to_string() const override { return ""; }
62 };
63
64
65
make(Inkscape::XML::Node * in_repr,Inkscape::Extension::Extension * in_ext)66 InxParameter *InxParameter::make(Inkscape::XML::Node *in_repr, Inkscape::Extension::Extension *in_ext)
67 {
68 InxParameter *param = nullptr;
69
70 try {
71 const char *type = in_repr->attribute("type");
72 if (!type) {
73 // we can't create a parameter without type
74 g_warning("Parameter without type in extension '%s'.", in_ext->get_id());
75 } else if(!strcmp(type, "bool") || !strcmp(type, "boolean")) { // support "boolean" for backwards-compatibility
76 param = new ParamBool(in_repr, in_ext);
77 } else if (!strcmp(type, "int")) {
78 param = new ParamInt(in_repr, in_ext);
79 } else if (!strcmp(type, "float")) {
80 param = new ParamFloat(in_repr, in_ext);
81 } else if (!strcmp(type, "string")) {
82 param = new ParamString(in_repr, in_ext);
83 } else if (!strcmp(type, "path")) {
84 param = new ParamPath(in_repr, in_ext);
85 } else if (!strcmp(type, "description")) {
86 // support deprecated "description" for backwards-compatibility
87 in_repr->setAttribute("gui-text", "description"); // TODO: hack to allow descriptions to be parameters
88 param = new ParamDescription(in_repr, in_ext);
89 } else if (!strcmp(type, "notebook")) {
90 in_repr->setAttribute("gui-text", "notebook"); // notebooks have no 'gui-text' (but Parameters need one)
91 param = new ParamNotebook(in_repr, in_ext);
92 } else if (!strcmp(type, "optiongroup")) {
93 param = new ParamOptionGroup(in_repr, in_ext);
94 } else if (!strcmp(type, "enum")) { // support deprecated "enum" for backwards-compatibility
95 in_repr->setAttribute("appearance", "combo");
96 param = new ParamOptionGroup(in_repr, in_ext);
97 } else if (!strcmp(type, "color")) {
98 param = new ParamColor(in_repr, in_ext);
99 } else {
100 g_warning("Unknown parameter type ('%s') in extension '%s'", type, in_ext->get_id());
101 }
102 } catch (const param_no_name&) {
103 } catch (const param_no_text&) {
104 }
105
106 // Note: param could equal nullptr
107 return param;
108 }
109
get_bool() const110 bool InxParameter::get_bool() const
111 {
112 ParamBool const *boolpntr = dynamic_cast<ParamBool const *>(this);
113 if (!boolpntr) {
114 throw param_not_bool_param();
115 }
116 return boolpntr->get();
117 }
118
get_int() const119 int InxParameter::get_int() const
120 {
121 ParamInt const *intpntr = dynamic_cast<ParamInt const *>(this);
122 if (!intpntr) {
123 throw param_not_int_param();
124 }
125 return intpntr->get();
126 }
127
get_float() const128 float InxParameter::get_float() const
129 {
130 ParamFloat const *floatpntr = dynamic_cast<ParamFloat const *>(this);
131 if (!floatpntr) {
132 throw param_not_float_param();
133 }
134 return floatpntr->get();
135 }
136
get_string() const137 const char *InxParameter::get_string() const
138 {
139 ParamString const *stringpntr = dynamic_cast<ParamString const *>(this);
140 if (!stringpntr) {
141 throw param_not_string_param();
142 }
143 return stringpntr->get().c_str();
144 }
145
get_optiongroup() const146 const char *InxParameter::get_optiongroup() const
147 {
148 ParamOptionGroup const *param = dynamic_cast<ParamOptionGroup const *>(this);
149 if (!param) {
150 throw param_not_optiongroup_param();
151 }
152 return param->get().c_str();
153 }
154
get_optiongroup_contains(const char * value) const155 bool InxParameter::get_optiongroup_contains(const char *value) const
156 {
157 ParamOptionGroup const *param = dynamic_cast<ParamOptionGroup const *>(this);
158 if (!param) {
159 throw param_not_optiongroup_param();
160 }
161 return param->contains(value);
162 }
163
get_color() const164 unsigned int InxParameter::get_color() const
165 {
166 ParamColor const *param = dynamic_cast<ParamColor const *>(this);
167 if (!param) {
168 throw param_not_color_param();
169 }
170 return param->get();
171 }
172
set_bool(bool in)173 bool InxParameter::set_bool(bool in)
174 {
175 ParamBool * boolpntr = dynamic_cast<ParamBool *>(this);
176 if (boolpntr == nullptr)
177 throw param_not_bool_param();
178 return boolpntr->set(in);
179 }
180
set_int(int in)181 int InxParameter::set_int(int in)
182 {
183 ParamInt *intpntr = dynamic_cast<ParamInt *>(this);
184 if (intpntr == nullptr)
185 throw param_not_int_param();
186 return intpntr->set(in);
187 }
188
set_float(float in)189 float InxParameter::set_float(float in)
190 {
191 ParamFloat * floatpntr;
192 floatpntr = dynamic_cast<ParamFloat *>(this);
193 if (floatpntr == nullptr)
194 throw param_not_float_param();
195 return floatpntr->set(in);
196 }
197
set_string(const char * in)198 const char *InxParameter::set_string(const char *in)
199 {
200 ParamString * stringpntr = dynamic_cast<ParamString *>(this);
201 if (stringpntr == nullptr)
202 throw param_not_string_param();
203 return stringpntr->set(in).c_str();
204 }
205
set_optiongroup(const char * in)206 const char *InxParameter::set_optiongroup(const char *in)
207 {
208 ParamOptionGroup *param = dynamic_cast<ParamOptionGroup *>(this);
209 if (!param) {
210 throw param_not_optiongroup_param();
211 }
212 return param->set(in).c_str();
213 }
214
set_color(unsigned int in)215 unsigned int InxParameter::set_color(unsigned int in)
216 {
217 ParamColor*param = dynamic_cast<ParamColor *>(this);
218 if (param == nullptr)
219 throw param_not_color_param();
220 return param->set(in);
221 }
222
223
InxParameter(Inkscape::XML::Node * in_repr,Inkscape::Extension::Extension * ext)224 InxParameter::InxParameter(Inkscape::XML::Node *in_repr, Inkscape::Extension::Extension *ext)
225 : InxWidget(in_repr, ext)
226 {
227 // name (mandatory for all parameters)
228 const char *name = in_repr->attribute("name");
229 if (name) {
230 _name = g_strstrip(g_strdup(name));
231 }
232 if (!_name || !strcmp(_name, "")) {
233 g_warning("Parameter without name in extension '%s'.", _extension->get_id());
234 throw param_no_name();
235 }
236
237 // gui-text
238 const char *gui_text = in_repr->attribute("gui-text");
239 if (!gui_text) {
240 gui_text = in_repr->attribute("_gui-text"); // backwards-compatibility with underscored variants
241 }
242 if (gui_text) {
243 if (_translatable != NO) { // translate unless explicitly marked untranslatable
244 gui_text = get_translation(gui_text);
245 }
246 _text = g_strdup(gui_text);
247 }
248 if (!_text && !_hidden) {
249 g_warning("Parameter '%s' in extension '%s' is visible but does not have a 'gui-text'.",
250 _name, _extension->get_id());
251 throw param_no_text();
252 }
253
254 // gui-description (optional)
255 const char *gui_description = in_repr->attribute("gui-description");
256 if (!gui_description) {
257 gui_description = in_repr->attribute("_gui-description"); // backwards-compatibility with underscored variants
258 }
259 if (gui_description) {
260 if (_translatable != NO) { // translate unless explicitly marked untranslatable
261 gui_description = get_translation(gui_description);
262 }
263 _description = g_strdup(gui_description);
264 }
265 }
266
~InxParameter()267 InxParameter::~InxParameter()
268 {
269 g_free(_name);
270 _name = nullptr;
271
272 g_free(_text);
273 _text = nullptr;
274
275 g_free(_description);
276 _description = nullptr;
277 }
278
pref_name() const279 Glib::ustring InxParameter::pref_name() const
280 {
281 return Glib::ustring::compose("/extensions/%1.%2", _extension->get_id(), _name);
282 }
283
value_to_string() const284 std::string InxParameter::value_to_string() const
285 {
286 // if we end up here we're missing a definition of ::string() in one of the subclasses
287 g_critical("InxParameter::value_to_string called from parameter '%s' in extension '%s'", _name, _extension->get_id());
288 g_assert_not_reached();
289 return "";
290 }
291
292 } // namespace Extension
293 } // namespace Inkscape
294
295 /*
296 Local Variables:
297 mode:c++
298 c-file-style:"stroustrup"
299 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
300 indent-tabs-mode:nil
301 fill-column:99
302 End:
303 */
304 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
305