Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
prefdialog.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Authors:
4 * Ted Gould <ted@gould.cx>
5 *
6 * Copyright (C) 2005-2008 Authors
7 *
8 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
9 */
10
11#include "prefdialog.h"
12
13#include <cassert>
14#include <glibmm/i18n.h>
15#include <gtkmm/checkbutton.h>
16#include <gtkmm/separator.h>
17
18#include "document.h"
19#include "document-undo.h"
20#include "extension/effect.h"
23#include "inkscape.h" // Used to get SP_ACTIVE_DESKTOP
24#include "parameter.h"
25#include "ui/dialog-events.h"
26#include "ui/pack.h"
27#include "ui/util.h"
28#include "xml/repr.h"
29
30namespace Inkscape::Extension {
31
40PrefDialog::PrefDialog (Glib::ustring name, Gtk::Widget * controls, Effect * effect) :
41 Gtk::Dialog(name, true),
42 _name(name),
43 _button_ok(nullptr),
44 _button_cancel(nullptr),
45 _button_preview(nullptr),
46 _effect(effect)
47{
48 this->set_default_size(0,0); // we want the window to be as small as possible instead of clobbering up space
49
50 auto hbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL);
51 if (controls == nullptr) {
52 if (_effect == nullptr) {
53 std::cerr << "AH!!! No controls and no effect!!!" << std::endl;
54 return;
55 }
56 controls = _effect->get_imp()->prefs_effect(_effect, SP_ACTIVE_DESKTOP, &_signal_param_change, nullptr);
57 _signal_param_change.connect(sigc::mem_fun(*this, &PrefDialog::param_change));
58 }
59
60 UI::pack_start(*hbox, *controls, true, true);
61 hbox->set_visible(true);
62
63 UI::pack_start(*this->get_content_area(), *hbox, true, true);
64
65 _button_cancel = add_button(_effect == nullptr ? _("_Cancel") : _("_Close"), Gtk::ResponseType::CANCEL);
66 _button_ok = add_button(_effect == nullptr ? _("_OK") : _("_Apply"), Gtk::ResponseType::OK);
67 set_default_response(Gtk::ResponseType::OK);
68 _button_ok->grab_focus();
69
70 if (_effect != nullptr && !_effect->no_live_preview) {
71 if (_param_preview == nullptr) {
73 if (doc == nullptr) {
74 std::cerr << "Error encountered loading live parameter XML !!!" << std::endl;
75 return;
76 }
77
79 }
80
81 auto const sep = Gtk::make_managed<Gtk::Separator>();
82 sep->set_visible(true);
83 UI::pack_start(*this->get_content_area(), *sep, false, false, InxWidget::GUI_BOX_SPACING);
84
85 hbox = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL);
86 hbox->set_margin(InxWidget::GUI_BOX_MARGIN);
88 _button_preview->set_visible(true);
89 UI::pack_start(*hbox, *_button_preview, true, true);
90 hbox->set_visible(true);
91
92 UI::pack_start(*this->get_content_area(), *hbox, false, false);
93
94 if (auto const preview_box = dynamic_cast<Gtk::Box *>(_button_preview)) {
95 _checkbox_preview = dynamic_cast<Gtk::CheckButton *>(UI::get_children(*preview_box).at(0));
96 }
97
99 _signal_preview.connect(sigc::mem_fun(*this, &PrefDialog::preview_toggle));
100 }
101
102 // Set window modality for effects that don't use live preview
103 if (_effect != nullptr && _effect->no_live_preview) {
104 set_modal(false);
105 }
106}
107
109{
110 if (_exEnv != nullptr) {
111 _exEnv->cancel();
112 }
113
114 if (_effect != nullptr) {
115 _effect->set_pref_dialog(nullptr);
116 }
117 return;
118}
119
120void
122 // This wrap prevent crashes on fast click
123 // We are on 2 mains process so can triger a crash if you check too fast
124 _button_preview->set_sensitive(false);
125 SPDocument *document = SP_ACTIVE_DOCUMENT;
126 bool modified = document->isModifiedSinceSave();
127
128 assert(_param_preview);
129 if(_param_preview->get_bool()) {
130 if (_exEnv == nullptr) {
131 set_modal(true);
132
133 _exEnv = std::make_unique<ExecutionEnv>(_effect, SP_ACTIVE_DESKTOP, nullptr, false, false);
134 _exEnv->run();
135 }
136 } else {
137 set_modal(false);
138
139 if (_exEnv != nullptr) {
140 _exEnv->cancel();
141 _exEnv->undo();
142 _exEnv->reselect();
143
144 _exEnv.reset();
145 }
146 }
147
148 document->setModifiedSinceSave(modified);
149 _button_preview->set_sensitive(true);
150}
151
152void
154 if (_exEnv != nullptr) {
155 if (!_effect->loaded()) {
157 }
158 _timersig.disconnect();
159 _timersig = Glib::signal_timeout().connect(sigc::mem_fun(*this, &PrefDialog::param_timer_expire),
160 250, /* ms */
161 Glib::PRIORITY_DEFAULT_IDLE);
162 }
163
164 return;
165}
166
167bool
169 if (_exEnv != nullptr) {
170 _exEnv->cancel();
171 _exEnv->undo();
172 _exEnv->reselect();
173 _exEnv->run();
174 }
175
176 return false;
177}
178
179void
181 if (signal == Gtk::ResponseType::OK) {
182 if (_exEnv == nullptr) {
183 if (_effect != nullptr) {
184 _effect->effect(SP_ACTIVE_DESKTOP);
185 } else {
186 // Shutdown run()
187 return;
188 }
189 } else {
190 if (_exEnv->wait()) {
191 _exEnv->commit();
192 } else {
193 _exEnv->undo();
194 _exEnv->reselect();
195 }
196
197 _exEnv.reset();
198 }
199 }
200
201 if (_param_preview != nullptr) {
202 _checkbox_preview->set_active(false);
203 }
204
205 if ((signal == Gtk::ResponseType::CANCEL || signal == Gtk::ResponseType::DELETE_EVENT) && _effect != nullptr) {
206 delete this;
207 }
208}
209
211
212const char * PrefDialog::live_param_xml = "<param name=\"__live_effect__\" type=\"bool\" gui-text=\"" N_("Live preview") "\" gui-description=\"" N_("Is the effect previewed live on canvas?") "\">false</param>";
213
214} // namespace Inkscape::Extension
215
216/*
217 Local Variables:
218 mode:c++
219 c-file-style:"stroustrup"
220 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
221 indent-tabs-mode:nil
222 fill-column:99
223 End:
224*/
225// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
Effects are extensions that take a document and do something to it in place.
Definition effect.h:39
void set_pref_dialog(PrefDialog *prefdialog)
Definition effect.cpp:304
void effect(SPDesktop *desktop, SPDocument *document=nullptr)
The function that 'does' the effect itself.
Definition effect.cpp:233
@ STATE_LOADED
The extension has been loaded successfully.
Definition extension.h:137
Implementation::Implementation * get_imp()
Definition extension.h:191
void set_state(state_t in_state)
A function to set whether the extension should be loaded or unloaded.
bool loaded()
A quick function to test the state of the extension.
virtual Gtk::Widget * prefs_effect(Inkscape::Extension::Effect *module, SPDesktop *desktop, sigc::signal< void()> *changeSignal, ImplementationDocumentCache *docCache)
Find out information about the file.
static InxParameter * make(Inkscape::XML::Node *in_repr, Inkscape::Extension::Extension *in_ext)
Creates a new extension parameter for usage in a prefdialog.
Definition parameter.cpp:66
static constexpr int GUI_BOX_SPACING
Recommended spacing between multiple widgets packed into a box (in px)
Definition widget.h:90
static constexpr int GUI_BOX_MARGIN
Recommended margin of boxes containing multiple widgets (in px)
Definition widget.h:88
static const char * live_param_xml
XML to define the live effects parameter on the dialog.
Definition prefdialog.h:49
void on_response(int signal) override
std::unique_ptr< InxParameter > _param_preview
Parameter to control live preview.
Definition prefdialog.h:46
Gtk::CheckButton * _checkbox_preview
Checkbox for the preview.
Definition prefdialog.h:43
PrefDialog(Glib::ustring name, Gtk::Widget *controls=nullptr, Effect *effect=nullptr)
Creates a new preference dialog for extension preferences.
sigc::signal< void()> _signal_preview
Signal that the user is changing the live effect state.
Definition prefdialog.h:52
Gtk::Button * _button_cancel
A pointer to the CANCEL button.
Definition prefdialog.h:38
Gtk::Button * _button_ok
A pointer to the OK button.
Definition prefdialog.h:36
sigc::connection _timersig
The timer used to make it so that parameters don't respond directly and allows for changes.
Definition prefdialog.h:66
Effect * _effect
If this is the preferences for an effect, the effect that we're working with.
Definition prefdialog.h:58
Gtk::Widget * _button_preview
Button to control live preview.
Definition prefdialog.h:41
std::unique_ptr< ExecutionEnv > _exEnv
If we're executing in preview mode here is the execution environment for the effect.
Definition prefdialog.h:62
sigc::signal< void()> _signal_param_change
Signal that one of the parameters change.
Definition prefdialog.h:54
virtual Node * root()=0
Get the root node of this node's document.
Typed SVG document implementation.
Definition document.h:103
bool isModifiedSinceSave() const
Definition document.h:140
void setModifiedSinceSave(bool const modified=true)
Indicate to the user if the document has been modified since the last save by displaying a "*" in fro...
A way to clear the N_ macro, which is defined as an inline function.
Event handler for dialog windows.
TODO: insert short description here.
Definition desktop.h:50
Extension support.
std::vector< Gtk::Widget * > get_children(Gtk::Widget &widget)
Get a vector of the widgetʼs children, from get_first_child() through each get_next_sibling().
Definition util.cpp:141
void pack_start(Gtk::Box &box, Gtk::Widget &child, bool const expand, bool const fill, unsigned const padding)
Adds child to box, packed with reference to the start of box.
Definition pack.cpp:141
Helpers for using Gtk::Boxes, encapsulating large changes between GTK3 & GTK4.
Document * sp_repr_read_mem(const gchar *buffer, gint length, const gchar *default_ns)
Reads and parses XML from a buffer, returning it as an Document.
Definition repr-io.cpp:324
C facade to Inkscape::XML::Node.
Interface for XML documents.
Definition document.h:43
Glib::ustring name
Definition toolbars.cpp:55