1 /** \file
2 * \brief Editor Implementation class declaration for Inkscape. This
3 * singleton class implements much of the functionality of the former
4 * 'inkscape' object and its services and signals.
5 *
6 * Authors:
7 * Bryce W. Harrington <bryce@bryceharrington.org>
8 * Derek P. Moore <derekm@hackunix.org>
9 * Ralf Stephan <ralf@ark.in-berlin.de>
10 *
11 * Copyright (C) 2004-2005 Authors
12 *
13 * Released under GNU GPL. Read the file 'COPYING' for more information.
14 */
16 #ifdef HAVE_CONFIG_H
17 # include <config.h>
18 #endif
20 /*
21 TODO: Replace SPDocument with the new Inkscape::Document
22 TODO: Change 'desktop's to 'view*'s
23 TODO: Add derivation from Inkscape::Application::RunMode
24 */
27 #include "path-prefix.h"
28 #include "io/sys.h"
29 #include "sp-object-repr.h"
30 #include <desktop-handles.h>
31 #include "document.h"
32 #include "sp-namedview.h"
33 #include "event-context.h"
34 #include "sp-guide.h"
35 #include "selection.h"
36 #include "editor.h"
37 #include "application/application.h"
38 #include "preferences.h"
39 #include "ui/view/edit-widget.h"
41 namespace Inkscape {
42 namespace NSApplication {
44 static Editor *_instance = 0;
45 static void *_window;
47 Editor*
48 Editor::create (gint argc, char **argv)
49 {
50 if (_instance == 0)
51 {
52 _instance = new Editor (argc, argv);
53 _instance->init();
54 }
55 return _instance;
56 }
58 Editor::Editor (gint argc, char **argv)
59 : _documents (0),
60 _desktops (0),
61 _argv0 (argv[0]),
62 _dialogs_toggle (true)
64 {
65 sp_object_type_register ("sodipodi:namedview", SP_TYPE_NAMEDVIEW);
66 sp_object_type_register ("sodipodi:guide", SP_TYPE_GUIDE);
68 Inkscape::Preferences::load();
69 }
71 bool
72 Editor::init()
73 {
74 // Load non-local template until we have everything right
75 // This code formerly lived in file.cpp
76 //
77 gchar const *tmpl = g_build_filename ((INKSCAPE_TEMPLATESDIR), "default.svg", NULL);
78 bool have_default = Inkscape::IO::file_test (tmpl, G_FILE_TEST_IS_REGULAR);
79 SPDocument *doc = sp_document_new (have_default? tmpl:0, true, true);
80 g_return_val_if_fail (doc != 0, false);
81 Inkscape::UI::View::EditWidget *ew = new Inkscape::UI::View::EditWidget (doc);
82 sp_document_unref (doc);
83 _window = ew->getWindow();
84 return ew != 0;
85 }
87 Editor::~Editor()
88 {
89 }
91 /// Returns the Window representation of this application object
92 void*
93 Editor::getWindow()
94 {
95 return _window;
96 }
98 /// Returns the active document
99 SPDocument*
100 Editor::getActiveDocument()
101 {
102 if (getActiveDesktop()) {
103 return SP_DT_DOCUMENT (getActiveDesktop());
104 }
106 return NULL;
107 }
109 void
110 Editor::addDocument (SPDocument *doc)
111 {
112 g_assert (!g_slist_find (_instance->_documents, doc));
113 _instance->_documents = g_slist_append (_instance->_documents, doc);
114 }
116 void
117 Editor::removeDocument (SPDocument *doc)
118 {
119 g_assert (g_slist_find (_instance->_documents, doc));
120 _instance->_documents = g_slist_remove (_instance->_documents, doc);
121 }
123 SPDesktop*
124 Editor::createDesktop (SPDocument* doc)
125 {
126 g_assert (doc != 0);
127 (new Inkscape::UI::View::EditWidget (doc))->present();
128 sp_document_unref (doc);
129 SPDesktop *dt = getActiveDesktop();
130 reactivateDesktop (dt);
131 return dt;
132 }
134 /// Returns the currently active desktop
135 SPDesktop*
136 Editor::getActiveDesktop()
137 {
138 if (_instance->_desktops == NULL) {
139 return NULL;
140 }
142 return (SPDesktop *) _instance->_desktops->data;
143 }
145 /// Add desktop to list of desktops
146 void
147 Editor::addDesktop (SPDesktop *dt)
148 {
149 g_return_if_fail (dt != 0);
150 g_assert (!g_slist_find (_instance->_desktops, dt));
152 _instance->_desktops = g_slist_append (_instance->_desktops, dt);
154 if (isDesktopActive (dt)) {
155 _instance->_desktop_activated_signal.emit (dt);
156 _instance->_event_context_set_signal.emit (SP_DT_EVENTCONTEXT (dt));
157 _instance->_selection_set_signal.emit (SP_DT_SELECTION (dt));
158 _instance->_selection_changed_signal.emit (SP_DT_SELECTION (dt));
159 }
160 }
162 /// Remove desktop from list of desktops
163 void
164 Editor::removeDesktop (SPDesktop *dt)
165 {
166 g_return_if_fail (dt != 0);
167 g_assert (g_slist_find (_instance->_desktops, dt));
169 if (dt == _instance->_desktops->data) { // is it the active desktop?
170 _instance->_desktop_deactivated_signal.emit (dt);
171 if (_instance->_desktops->next != 0) {
172 SPDesktop * new_desktop = (SPDesktop *) _instance->_desktops->next->data;
173 _instance->_desktops = g_slist_remove (_instance->_desktops, new_desktop);
174 _instance->_desktops = g_slist_prepend (_instance->_desktops, new_desktop);
175 _instance->_desktop_activated_signal.emit (new_desktop);
176 _instance->_event_context_set_signal.emit (SP_DT_EVENTCONTEXT (new_desktop));
177 _instance->_selection_set_signal.emit (SP_DT_SELECTION (new_desktop));
178 _instance->_selection_changed_signal.emit (SP_DT_SELECTION (new_desktop));
179 } else {
180 _instance->_event_context_set_signal.emit (0);
181 if (SP_DT_SELECTION(dt))
182 SP_DT_SELECTION(dt)->clear();
183 }
184 }
186 _instance->_desktops = g_slist_remove (_instance->_desktops, dt);
188 // if this was the last desktop, shut down the program
189 if (_instance->_desktops == NULL) {
190 _instance->_shutdown_signal.emit();
191 Inkscape::NSApplication::Application::exit();
192 }
193 }
195 void
196 Editor::activateDesktop (SPDesktop* dt)
197 {
198 g_assert (dt != 0);
199 if (isDesktopActive (dt))
200 return;
202 g_assert (g_slist_find (_instance->_desktops, dt));
203 SPDesktop *curr = (SPDesktop*)_instance->_desktops->data;
204 _instance->_desktop_deactivated_signal.emit (curr);
206 _instance->_desktops = g_slist_remove (_instance->_desktops, dt);
207 _instance->_desktops = g_slist_prepend (_instance->_desktops, dt);
209 _instance->_desktop_activated_signal.emit (dt);
210 _instance->_event_context_set_signal.emit (SP_DT_EVENTCONTEXT(dt));
211 _instance->_selection_set_signal.emit (SP_DT_SELECTION(dt));
212 _instance->_selection_changed_signal.emit (SP_DT_SELECTION(dt));
213 }
215 void
216 Editor::reactivateDesktop (SPDesktop* dt)
217 {
218 g_assert (dt != 0);
219 if (isDesktopActive(dt))
220 _instance->_desktop_activated_signal.emit (dt);
221 }
223 bool
224 Editor::isDuplicatedView (SPDesktop* dt)
225 {
226 SPDocument const* document = dt->doc();
227 if (!document) {
228 return false;
229 }
230 for ( GSList *iter = _instance->_desktops ; iter ; iter = iter->next ) {
231 SPDesktop *other_desktop=(SPDesktop *)iter->data;
232 SPDocument *other_document=other_desktop->doc();
233 if ( other_document == document && other_desktop != dt ) {
234 return true;
235 }
236 }
237 return false;
238 }
240 /// Returns the event context
241 //SPEventContext*
242 //Editor::getEventContext()
243 //{
244 // if (getActiveDesktop()) {
245 // return SP_DT_EVENTCONTEXT (getActiveDesktop());
246 // }
247 //
248 // return NULL;
249 //}
252 void
253 Editor::selectionModified (Inkscape::Selection* sel, guint flags)
254 {
255 g_return_if_fail (sel != NULL);
256 if (isDesktopActive (sel->desktop()))
257 _instance->_selection_modified_signal.emit (sel, flags);
258 }
260 void
261 Editor::selectionChanged (Inkscape::Selection* sel)
262 {
263 g_return_if_fail (sel != NULL);
264 if (isDesktopActive (sel->desktop()))
265 _instance->_selection_changed_signal.emit (sel);
266 }
268 void
269 Editor::subSelectionChanged (SPDesktop* dt)
270 {
271 g_return_if_fail (dt != NULL);
272 if (isDesktopActive (dt))
273 _instance->_subselection_changed_signal.emit (dt);
274 }
276 void
277 Editor::selectionSet (Inkscape::Selection* sel)
278 {
279 g_return_if_fail (sel != NULL);
280 if (isDesktopActive (sel->desktop())) {
281 _instance->_selection_set_signal.emit (sel);
282 _instance->_selection_changed_signal.emit (sel);
283 }
284 }
286 void
287 Editor::eventContextSet (SPEventContext* ec)
288 {
289 g_return_if_fail (ec != NULL);
290 g_return_if_fail (SP_IS_EVENT_CONTEXT (ec));
291 if (isDesktopActive (ec->desktop))
292 _instance->_event_context_set_signal.emit (ec);
293 }
295 void
296 Editor::hideDialogs()
297 {
298 _instance->_dialogs_hidden_signal.emit();
299 _instance->_dialogs_toggle = false;
300 }
302 void
303 Editor::unhideDialogs()
304 {
305 _instance->_dialogs_unhidden_signal.emit();
306 _instance->_dialogs_toggle = true;
307 }
309 void
310 Editor::toggleDialogs()
311 {
312 if (_dialogs_toggle) {
313 hideDialogs();
314 } else {
315 unhideDialogs();
316 }
317 }
319 void
320 Editor::refreshDisplay()
321 {
322 // TODO
323 }
325 void
326 Editor::exit()
327 {
328 //emit shutdown signal so that dialogs could remember layout
329 _shutdown_signal.emit();
330 Inkscape::Preferences::save();
331 }
333 //==================================================================
335 sigc::connection
336 Editor::connectSelectionModified
337 (const sigc::slot<void, Inkscape::Selection*, guint> &slot)
338 {
339 return _instance->_selection_modified_signal.connect (slot);
340 }
342 sigc::connection
343 Editor::connectSelectionChanged
344 (const sigc::slot<void, Inkscape::Selection*> &slot)
345 {
346 return _instance->_selection_changed_signal.connect (slot);
347 }
349 sigc::connection
350 Editor::connectSubselectionChanged (const sigc::slot<void, SPDesktop*> &slot)
351 {
352 return _instance->_subselection_changed_signal.connect (slot);
353 }
355 sigc::connection
356 Editor::connectSelectionSet (const sigc::slot<void, Inkscape::Selection*> &slot)
357 {
358 return _instance->_selection_set_signal.connect (slot);
359 }
361 sigc::connection
362 Editor::connectEventContextSet (const sigc::slot<void, SPEventContext*> &slot)
363 {
364 return _instance->_event_context_set_signal.connect (slot);
365 }
367 sigc::connection
368 Editor::connectDesktopActivated (const sigc::slot<void, SPDesktop*> &slot)
369 {
370 return _instance->_desktop_activated_signal.connect (slot);
371 }
373 sigc::connection
374 Editor::connectDesktopDeactivated (const sigc::slot<void, SPDesktop*> &slot)
375 {
376 return _instance->_desktop_deactivated_signal.connect (slot);
377 }
379 sigc::connection
380 Editor::connectShutdown (const sigc::slot<void> &slot)
381 {
382 return _instance->_shutdown_signal.connect (slot);
383 }
385 sigc::connection
386 Editor::connectDialogsHidden (const sigc::slot<void> &slot)
387 {
388 return _instance->_dialogs_hidden_signal.connect (slot);
389 }
391 sigc::connection
392 Editor::connectDialogsUnhidden (const sigc::slot<void> &slot)
393 {
394 return _instance->_dialogs_unhidden_signal.connect (slot);
395 }
397 sigc::connection
398 Editor::connectExternalChange (const sigc::slot<void> &slot)
399 {
400 return _instance->_external_change_signal.connect (slot);
401 }
404 } // namespace NSApplication
405 } // namespace Inkscape
407 /*
408 Local Variables:
409 mode:c++
410 c-file-style:"stroustrup"
411 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
412 indent-tabs-mode:nil
413 fill-column:99
414 End:
415 */
416 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :