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 && !_prefsVisible) {
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 if (_livePreview) {
125 _timersig = Glib::signal_timeout().connect(sigc::mem_fun(this, &ExecutionEnv::preferencesTimer), 100, Glib::PRIORITY_DEFAULT_IDLE);
126 }
127 return;
128 }
130 bool
131 ExecutionEnv::preferencesTimer (void) {
132 //std::cout << "Preferences are a changin'" << std::endl;
133 _prefsChanged = true;
134 if (_humanWait) {
135 _mainloop->quit();
136 documentCancel();
137 _humanWait = false;
138 } else {
139 processingCancel();
140 documentCancel();
141 }
142 return false;
143 }
145 void
146 ExecutionEnv::createPrefsDialog (Gtk::Widget * controls) {
147 _visibleDialog = new PrefDialog(_effect->get_name(), _effect->get_help(), controls, this, _effect, _changeSignal);
148 _visibleDialog->show();
149 _dialogsig = _visibleDialog->signal_response().connect(sigc::mem_fun(this, &ExecutionEnv::preferencesResponse));
151 _prefsVisible = true;
152 return;
153 }
155 void
156 ExecutionEnv::createWorkingDialog (void) {
157 if (_visibleDialog != NULL) {
158 delete _visibleDialog;
159 }
160 if (_changeSignal != NULL) {
161 delete _changeSignal;
162 _changeSignal = NULL;
163 }
165 gchar * dlgmessage = g_strdup_printf(_("'%s' working, please wait..."), _effect->get_name());
166 _visibleDialog = new Gtk::MessageDialog(dlgmessage,
167 false, // use markup
168 Gtk::MESSAGE_INFO,
169 Gtk::BUTTONS_CANCEL,
170 true); // modal
171 _dialogsig = _visibleDialog->signal_response().connect(sigc::mem_fun(this, &ExecutionEnv::workingCanceled));
172 g_free(dlgmessage);
173 _visibleDialog->show();
175 _prefsVisible = false;
176 return;
177 }
179 void
180 ExecutionEnv::workingCanceled( const int /*resp*/ ) {
181 printf("Working Canceled\n");
182 processingCancel();
183 documentCancel();
184 _finished = true;
185 return;
186 }
188 void
189 ExecutionEnv::preferencesResponse (const int resp) {
190 if (resp == Gtk::RESPONSE_OK) {
191 if (_humanWait && _livePreview) {
192 documentCommit();
193 _mainloop->quit();
194 _finished = true;
195 } else {
196 createWorkingDialog();
197 if (!_livePreview) {
198 _mainloop->quit();
199 _humanWait = false;
200 }
201 }
202 } else {
203 if (_humanWait) {
204 _mainloop->quit();
205 } else {
206 processingCancel();
207 }
208 documentCancel();
209 _finished = true;
210 }
211 return;
212 }
214 void
215 ExecutionEnv::processingComplete(void) {
216 //std::cout << "Processing Complete" << std::endl;
217 if (_prefsChanged) { return; } // do it all again
218 if (_prefsVisible) {
219 _humanWait = true;
220 } else {
221 documentCommit();
222 _finished = true;
223 }
224 return;
225 }
227 void
228 ExecutionEnv::processingCancel (void) {
229 _effect->get_imp()->cancelProcessing();
230 return;
231 }
233 void
234 ExecutionEnv::documentCancel (void) {
235 _canceled = true;
236 return;
237 }
239 void
240 ExecutionEnv::documentCommit (void) {
241 sp_document_done(_doc->doc(), SP_VERB_NONE, _(_effect->get_name()));
242 Effect::set_last_effect(_effect);
243 _effect->get_imp()->commitDocument();
244 return;
245 }
247 void
248 ExecutionEnv::reselect (void) {
249 if (_doc == NULL) { return; }
250 SPDocument * doc = _doc->doc();
251 if (doc == NULL) { return; }
253 SPDesktop *desktop = (SPDesktop *)_doc;
254 sp_namedview_document_from_window(desktop);
256 if (desktop == NULL) { return; }
258 Inkscape::Selection * selection = sp_desktop_selection(desktop);
260 for (std::list<Glib::ustring>::iterator i = _selected.begin(); i != _selected.end(); i++) {
261 SPObject * obj = doc->getObjectById(i->c_str());
262 if (obj != NULL) {
263 selection->add(obj);
264 }
265 }
267 return;
268 }
270 void
271 ExecutionEnv::run (void) {
272 while (!_finished) {
273 _canceled = false;
274 if (_humanWait) {
275 _mainloop->run();
276 } else {
277 _prefsChanged = false;
278 genDocCache();
279 _effect->get_imp()->effect(_effect, _doc, _docCache);
280 processingComplete();
281 }
282 if (_canceled) {
283 sp_document_cancel(_doc->doc());
284 reselect();
285 }
286 }
287 if (_selfdelete) {
288 delete this;
289 }
290 return;
291 }
293 /** \brief Set the state of live preview
294 \param state The current state
296 This will cancel the document preview and and configure
297 whether we should be waiting on the human. It will also
298 clear the document cache.
299 */
300 void
301 ExecutionEnv::livePreview (bool state) {
302 _mainloop->quit();
303 if (_livePreview && !state) {
304 documentCancel();
305 _humanWait = true;
306 }
307 if (!_livePreview && state) {
308 _humanWait = false;
309 }
310 _livePreview = state;
311 if (!_livePreview) {
312 killDocCache();
313 }
314 return;
315 }
317 void
318 ExecutionEnv::shutdown (bool del) {
319 if (_humanWait) {
320 _mainloop->quit();
321 } else {
322 processingCancel();
323 }
324 documentCancel();
326 _finished = true;
327 _shutdown = true;
328 _selfdelete = del;
330 return;
331 }
333 } } /* namespace Inkscape, Extension */
337 /*
338 Local Variables:
339 mode:c++
340 c-file-style:"stroustrup"
341 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
342 indent-tabs-mode:nil
343 fill-column:99
344 End:
345 */
346 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :