1 /*
2 * Authors:
3 * Ted Gould <ted@gould.cx>
4 *
5 * Copyright (C) 2007 Authors
6 *
7 * Released under GNU GPL, read the file 'COPYING' for more information
8 */
10 #include <config.h>
12 #include "gtkmm/messagedialog.h"
14 #include "execution-env.h"
15 #include "prefdialog.h"
16 #include "implementation/implementation.h"
18 #include "selection.h"
19 #include "effect.h"
20 #include "document.h"
21 #include "desktop.h"
22 #include "ui/view/view.h"
23 #include "sp-namedview.h"
24 #include "desktop-handles.h"
26 #include "util/glib-list-iterators.h"
28 namespace Inkscape {
29 namespace Extension {
32 ExecutionEnv::ExecutionEnv (Effect * effect, Inkscape::UI::View::View * doc, Gtk::Widget * controls, sigc::signal<void> * changeSignal, Gtk::Dialog * prefDialog, Implementation::ImplementationDocumentCache * docCache) :
33 _visibleDialog(NULL),
34 _prefsVisible(false),
35 _finished(false),
36 _humanWait(false),
37 _canceled(false),
38 _prefsChanged(false),
39 _livePreview(true),
40 _shutdown(false),
41 _selfdelete(false),
42 _changeSignal(changeSignal),
43 _doc(doc),
44 _docCache(docCache),
45 _effect(effect)
46 {
47 SPDesktop *desktop = (SPDesktop *)_doc;
48 sp_namedview_document_from_window(desktop);
50 if (desktop != NULL) {
51 Inkscape::Util::GSListConstIterator<SPItem *> selected =
52 sp_desktop_selection(desktop)->itemList();
53 while ( selected != NULL ) {
54 Glib::ustring selected_id;
55 selected_id = SP_OBJECT_ID(*selected);
56 _selected.insert(_selected.end(), selected_id);
57 //std::cout << "Selected: " << selected_id << std::endl;
58 ++selected;
59 }
60 }
62 _mainloop = Glib::MainLoop::create(false);
64 if (prefDialog == NULL) {
65 if (controls != NULL) {
66 createPrefsDialog(controls);
67 } else {
68 createWorkingDialog();
69 }
70 } else {
71 _visibleDialog = prefDialog;
72 _prefsVisible = true;
73 _dialogsig = _visibleDialog->signal_response().connect(sigc::mem_fun(this, &ExecutionEnv::preferencesResponse));
75 // We came from a dialog, we'll need to die by ourselves.
76 _selfdelete = true;
77 }
79 if (_changeSignal != NULL) {
80 _changesig = _changeSignal->connect(sigc::mem_fun(this, &ExecutionEnv::preferencesChange));
81 }
83 return;
84 }
86 ExecutionEnv::~ExecutionEnv (void) {
87 _dialogsig.disconnect();
88 _timersig.disconnect();
89 if (_prefsVisible) {
90 _changesig.disconnect();
91 }
92 if (_visibleDialog != NULL && !_shutdown) {
93 delete _visibleDialog;
94 }
95 if (_changeSignal != NULL && !_shutdown) {
96 delete _changeSignal;
97 }
98 killDocCache();
99 return;
100 }
102 void
103 ExecutionEnv::genDocCache (void) {
104 if (_docCache == NULL) {
105 // printf("Gen Doc Cache\n");
106 _docCache = _effect->get_imp()->newDocCache(_effect, _doc);
107 }
108 return;
109 }
111 void
112 ExecutionEnv::killDocCache (void) {
113 if (_docCache != NULL) {
114 // printf("Killed Doc Cache\n");
115 delete _docCache;
116 _docCache = NULL;
117 }
118 return;
119 }
121 void
122 ExecutionEnv::preferencesChange (void) {
123 _timersig.disconnect();
124 _timersig = Glib::signal_timeout().connect(sigc::mem_fun(this, &ExecutionEnv::preferencesTimer), 100, Glib::PRIORITY_DEFAULT_IDLE);
125 return;
126 }
128 bool
129 ExecutionEnv::preferencesTimer (void) {
130 //std::cout << "Preferences are a changin'" << std::endl;
131 _prefsChanged = true;
132 if (_humanWait) {
133 _mainloop->quit();
134 documentCancel();
135 _humanWait = false;
136 } else {
137 processingCancel();
138 documentCancel();
139 }
140 return false;
141 }
143 void
144 ExecutionEnv::createPrefsDialog (Gtk::Widget * controls) {
145 _visibleDialog = new PrefDialog(_effect->get_name(), _effect->get_help(), controls, this, _effect, _changeSignal);
146 _visibleDialog->show();
147 _dialogsig = _visibleDialog->signal_response().connect(sigc::mem_fun(this, &ExecutionEnv::preferencesResponse));
149 _prefsVisible = true;
150 return;
151 }
153 void
154 ExecutionEnv::createWorkingDialog (void) {
155 if (_visibleDialog != NULL) {
156 delete _visibleDialog;
157 }
158 if (_changeSignal != NULL) {
159 delete _changeSignal;
160 _changeSignal = NULL;
161 }
163 gchar * dlgmessage = g_strdup_printf(_("'%s' working, please wait..."), _effect->get_name());
164 _visibleDialog = new Gtk::MessageDialog(dlgmessage,
165 false, // use markup
166 Gtk::MESSAGE_INFO,
167 Gtk::BUTTONS_CANCEL,
168 true); // modal
169 _dialogsig = _visibleDialog->signal_response().connect(sigc::mem_fun(this, &ExecutionEnv::workingCanceled));
170 g_free(dlgmessage);
171 _visibleDialog->show();
173 _prefsVisible = false;
174 return;
175 }
177 void
178 ExecutionEnv::workingCanceled( const int /*resp*/ ) {
179 processingCancel();
180 documentCancel();
181 _finished = true;
182 return;
183 }
185 void
186 ExecutionEnv::preferencesResponse (const int resp) {
187 if (resp == Gtk::RESPONSE_OK) {
188 if (_humanWait && _livePreview) {
189 documentCommit();
190 _mainloop->quit();
191 _finished = true;
192 } else {
193 createWorkingDialog();
194 if (!_livePreview) {
195 _mainloop->quit();
196 _humanWait = false;
197 }
198 }
199 } else {
200 if (_humanWait) {
201 _mainloop->quit();
202 } else {
203 processingCancel();
204 }
205 documentCancel();
206 _finished = true;
207 }
208 return;
209 }
211 void
212 ExecutionEnv::processingComplete(void) {
213 //std::cout << "Processing Complete" << std::endl;
214 if (_prefsChanged) { return; } // do it all again
215 if (_prefsVisible) {
216 _humanWait = true;
217 } else {
218 documentCommit();
219 _finished = true;
220 }
221 return;
222 }
224 void
225 ExecutionEnv::processingCancel (void) {
226 _effect->get_imp()->cancelProcessing();
227 return;
228 }
230 void
231 ExecutionEnv::documentCancel (void) {
232 _canceled = true;
233 return;
234 }
236 void
237 ExecutionEnv::documentCommit (void) {
238 sp_document_done(_doc->doc(), SP_VERB_NONE, _(_effect->get_name()));
239 Effect::set_last_effect(_effect);
240 _effect->get_imp()->commitDocument();
241 return;
242 }
244 void
245 ExecutionEnv::reselect (void) {
246 if (_doc == NULL) { return; }
247 SPDocument * doc = _doc->doc();
248 if (doc == NULL) { return; }
250 SPDesktop *desktop = (SPDesktop *)_doc;
251 sp_namedview_document_from_window(desktop);
253 if (desktop == NULL) { return; }
255 Inkscape::Selection * selection = sp_desktop_selection(desktop);
257 for (std::list<Glib::ustring>::iterator i = _selected.begin(); i != _selected.end(); i++) {
258 SPObject * obj = doc->getObjectById(i->c_str());
259 if (obj != NULL) {
260 selection->add(obj);
261 }
262 }
264 return;
265 }
267 void
268 ExecutionEnv::run (void) {
269 while (!_finished) {
270 _canceled = false;
271 if (_humanWait) {
272 _mainloop->run();
273 } else {
274 _prefsChanged = false;
275 genDocCache();
276 _effect->get_imp()->effect(_effect, _doc, _docCache);
277 processingComplete();
278 }
279 if (_canceled) {
280 sp_document_cancel(_doc->doc());
281 reselect();
282 }
283 }
284 if (_selfdelete) {
285 delete this;
286 }
287 return;
288 }
290 /** \brief Set the state of live preview
291 \param state The current state
293 This will cancel the document preview and and configure
294 whether we should be waiting on the human. It will also
295 clear the document cache.
296 */
297 void
298 ExecutionEnv::livePreview (bool state) {
299 _mainloop->quit();
300 if (_livePreview && !state) {
301 documentCancel();
302 _humanWait = true;
303 }
304 if (!_livePreview && state) {
305 _humanWait = false;
306 }
307 _livePreview = state;
308 if (!_livePreview) {
309 killDocCache();
310 }
311 return;
312 }
314 void
315 ExecutionEnv::shutdown (bool del) {
316 if (_humanWait) {
317 _mainloop->quit();
318 } else {
319 processingCancel();
320 }
321 documentCancel();
323 _finished = true;
324 _shutdown = true;
325 _selfdelete = del;
327 return;
328 }
330 } } /* namespace Inkscape, Extension */
334 /*
335 Local Variables:
336 mode:c++
337 c-file-style:"stroustrup"
338 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
339 indent-tabs-mode:nil
340 fill-column:99
341 End:
342 */
343 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :