Code

fix crash, allow combine to work transparently on groups
[inkscape.git] / src / extension / execution-env.cpp
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;
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;
148 void
149 ExecutionEnv::workingCanceled( const int /*resp*/) {
150     cancel();
151     undo();
152     return;
155 void
156 ExecutionEnv::cancel (void) {
157     _effect->get_imp()->cancelProcessing();
158     return;
161 void
162 ExecutionEnv::undo (void) {
163     sp_document_cancel(_doc->doc());
164     reselect();
165     return;
168 void
169 ExecutionEnv::commit (void) {
170     sp_document_done(_doc->doc(), SP_VERB_NONE, _(_effect->get_name()));
171     Effect::set_last_effect(_effect);
172     _effect->get_imp()->commitDocument();
173     killDocCache();
174     return;
177 void
178 ExecutionEnv::reselect (void) {
179     if (_doc == NULL) { return; }
180     SPDocument * doc = _doc->doc();
181     if (doc == NULL) { return; }
183     SPDesktop *desktop = (SPDesktop *)_doc;
184     sp_namedview_document_from_window(desktop);
186     if (desktop == NULL) { return; }
188     Inkscape::Selection * selection = sp_desktop_selection(desktop);
190     for (std::list<Glib::ustring>::iterator i = _selected.begin(); i != _selected.end(); i++) {
191         SPObject * obj = doc->getObjectById(i->c_str());
192         if (obj != NULL) {
193             selection->add(obj);
194         }
195     }
197     return;
200 void
201 ExecutionEnv::run (void) {
202     _state = ExecutionEnv::RUNNING;
203     if (_show_working) {
204         createWorkingDialog();
205     }
206     _effect->get_imp()->effect(_effect, _doc, _docCache);
207     _state = ExecutionEnv::COMPLETE;
208     // _runComplete.signal();
209     return;
212 void
213 ExecutionEnv::runComplete (void) {
214     _mainloop->quit();
217 bool
218 ExecutionEnv::wait (void) {
219     if (_state != ExecutionEnv::COMPLETE) {
220         if (_mainloop) {
221             _mainloop = Glib::MainLoop::create(false);
222         }
224         sigc::connection conn = _runComplete.connect(sigc::mem_fun(this, &ExecutionEnv::runComplete));
225         _mainloop->run();
227         conn.disconnect();
228     }
230     return true;
235 } }  /* namespace Inkscape, Extension */
239 /*
240   Local Variables:
241   mode:c++
242   c-file-style:"stroustrup"
243   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
244   indent-tabs-mode:nil
245   fill-column:99
246   End:
247 */
248 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :