1 /*
2 * Authors:
3 * Ted Gould <ted@gould.cx>
4 *
5 * Copyright (C) 2007-2008 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"
25 #include "display/sp-canvas.h"
27 #include "util/glib-list-iterators.h"
29 namespace Inkscape {
30 namespace Extension {
32 /** \brief Create an execution environment that will allow the effect
33 to execute independently.
34 \param effect The effect that we should execute
35 \param doc The Document to execute on
36 \param docCache The cache created for that document
37 \param show_working Show the working dialog
38 \param show_error Show the error dialog (not working)
40 Grabs the selection of the current document so that it can get
41 restored. Will generate a document cache if one isn't provided.
42 */
43 ExecutionEnv::ExecutionEnv (Effect * effect, Inkscape::UI::View::View * doc, Implementation::ImplementationDocumentCache * docCache, bool show_working, bool show_errors) :
44 _state(ExecutionEnv::INIT),
45 _visibleDialog(NULL),
46 _mainloop(NULL),
47 _doc(doc),
48 _docCache(docCache),
49 _effect(effect),
50 _show_working(show_working),
51 _show_errors(show_errors)
52 {
53 SPDesktop *desktop = (SPDesktop *)_doc;
54 sp_namedview_document_from_window(desktop);
56 if (desktop != NULL) {
57 Inkscape::Util::GSListConstIterator<SPItem *> selected =
58 sp_desktop_selection(desktop)->itemList();
59 while ( selected != NULL ) {
60 Glib::ustring selected_id;
61 selected_id = SP_OBJECT_ID(*selected);
62 _selected.insert(_selected.end(), selected_id);
63 //std::cout << "Selected: " << selected_id << std::endl;
64 ++selected;
65 }
66 }
68 genDocCache();
70 return;
71 }
73 /** \brief Destroy an execution environment
75 Destroys the dialog if created and the document cache.
76 */
77 ExecutionEnv::~ExecutionEnv (void) {
78 if (_visibleDialog != NULL) {
79 _visibleDialog->hide();
80 delete _visibleDialog;
81 _visibleDialog = NULL;
82 }
83 killDocCache();
84 return;
85 }
87 /** \brief Generate a document cache if needed
89 If there isn't one we create a new one from the implementation
90 from the effect's implementation.
91 */
92 void
93 ExecutionEnv::genDocCache (void) {
94 if (_docCache == NULL) {
95 // printf("Gen Doc Cache\n");
96 _docCache = _effect->get_imp()->newDocCache(_effect, _doc);
97 }
98 return;
99 }
101 /** \brief Destory a document cache
103 Just delete it.
104 */
105 void
106 ExecutionEnv::killDocCache (void) {
107 if (_docCache != NULL) {
108 // printf("Killed Doc Cache\n");
109 delete _docCache;
110 _docCache = NULL;
111 }
112 return;
113 }
115 /** \brief Create the working dialog
117 Builds the dialog with a message saying that the effect is working.
118 And make sure to connect to the cancel.
119 */
120 void
121 ExecutionEnv::createWorkingDialog (void) {
122 if (_visibleDialog != NULL) {
123 _visibleDialog->hide();
124 delete _visibleDialog;
125 _visibleDialog = NULL;
126 }
128 SPDesktop *desktop = (SPDesktop *)_doc;
129 GtkWidget *toplevel = gtk_widget_get_toplevel(&(desktop->canvas->widget));
130 if (!toplevel || !GTK_WIDGET_TOPLEVEL (toplevel))
131 return;
132 Gtk::Window *window = Glib::wrap(GTK_WINDOW(toplevel), false);
134 gchar * dlgmessage = g_strdup_printf(_("'%s' working, please wait..."), _(_effect->get_name()));
135 _visibleDialog = new Gtk::MessageDialog(*window,
136 dlgmessage,
137 false, // use markup
138 Gtk::MESSAGE_INFO,
139 Gtk::BUTTONS_CANCEL,
140 true); // modal
141 _visibleDialog->signal_response().connect(sigc::mem_fun(this, &ExecutionEnv::workingCanceled));
142 g_free(dlgmessage);
143 _visibleDialog->show();
145 return;
146 }
148 void
149 ExecutionEnv::workingCanceled( const int /*resp*/) {
150 cancel();
151 undo();
152 return;
153 }
155 void
156 ExecutionEnv::cancel (void) {
157 SPDesktop *desktop = (SPDesktop *)_doc;
158 desktop->clearWaitingCursor();
159 _effect->get_imp()->cancelProcessing();
160 return;
161 }
163 void
164 ExecutionEnv::undo (void) {
165 sp_document_cancel(_doc->doc());
166 reselect();
167 return;
168 }
170 void
171 ExecutionEnv::commit (void) {
172 sp_document_done(_doc->doc(), SP_VERB_NONE, _(_effect->get_name()));
173 Effect::set_last_effect(_effect);
174 _effect->get_imp()->commitDocument();
175 killDocCache();
176 return;
177 }
179 void
180 ExecutionEnv::reselect (void) {
181 if (_doc == NULL) { return; }
182 SPDocument * doc = _doc->doc();
183 if (doc == NULL) { return; }
185 SPDesktop *desktop = (SPDesktop *)_doc;
186 sp_namedview_document_from_window(desktop);
188 if (desktop == NULL) { return; }
190 Inkscape::Selection * selection = sp_desktop_selection(desktop);
192 for (std::list<Glib::ustring>::iterator i = _selected.begin(); i != _selected.end(); i++) {
193 SPObject * obj = doc->getObjectById(i->c_str());
194 if (obj != NULL) {
195 selection->add(obj);
196 }
197 }
199 return;
200 }
202 void
203 ExecutionEnv::run (void) {
204 _state = ExecutionEnv::RUNNING;
205 if (_show_working) {
206 createWorkingDialog();
207 }
208 SPDesktop *desktop = (SPDesktop *)_doc;
209 desktop->setWaitingCursor();
210 _effect->get_imp()->effect(_effect, _doc, _docCache);
211 desktop->clearWaitingCursor();
212 _state = ExecutionEnv::COMPLETE;
213 // _runComplete.signal();
214 return;
215 }
217 void
218 ExecutionEnv::runComplete (void) {
219 _mainloop->quit();
220 }
222 bool
223 ExecutionEnv::wait (void) {
224 if (_state != ExecutionEnv::COMPLETE) {
225 if (_mainloop) {
226 _mainloop = Glib::MainLoop::create(false);
227 }
229 sigc::connection conn = _runComplete.connect(sigc::mem_fun(this, &ExecutionEnv::runComplete));
230 _mainloop->run();
232 conn.disconnect();
233 }
235 return true;
236 }
240 } } /* namespace Inkscape, Extension */
244 /*
245 Local Variables:
246 mode:c++
247 c-file-style:"stroustrup"
248 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
249 indent-tabs-mode:nil
250 fill-column:99
251 End:
252 */
253 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :