Code

Merge from fe-moved
[inkscape.git] / src / application / editor.cpp
1 /** @file
2  * @brief Editor class declaration.  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()
102     if (getActiveDesktop()) {
103         return sp_desktop_document (getActiveDesktop());
104     }
106     return NULL;
109 void
110 Editor::addDocument (SPDocument *doc)
112     if ( _instance->_document_set.find(doc) == _instance->_document_set.end() ) {
113         _instance->_documents = g_slist_append (_instance->_documents, doc);
114     }
115     _instance->_document_set.insert(doc);
118 void
119 Editor::removeDocument (SPDocument *doc)
121     _instance->_document_set.erase(doc);
122     if ( _instance->_document_set.find(doc) == _instance->_document_set.end() ) {
123         _instance->_documents = g_slist_remove (_instance->_documents, doc);
124     }
127 SPDesktop* 
128 Editor::createDesktop (SPDocument* doc)
130     g_assert (doc != 0);
131     (new Inkscape::UI::View::EditWidget (doc))->present();
132     sp_document_unref (doc);
133     SPDesktop *dt = getActiveDesktop();
134     reactivateDesktop (dt);
135     return dt;
138 /// Returns the currently active desktop
139 SPDesktop*
140 Editor::getActiveDesktop()
142     if (_instance->_desktops == NULL) {
143         return NULL;
144     }
146     return (SPDesktop *) _instance->_desktops->data;
149 /// Add desktop to list of desktops
150 void
151 Editor::addDesktop (SPDesktop *dt)
153     g_return_if_fail (dt != 0);
154     g_assert (!g_slist_find (_instance->_desktops, dt));
156     _instance->_desktops = g_slist_append (_instance->_desktops, dt);
158     if (isDesktopActive (dt)) {
159         _instance->_desktop_activated_signal.emit (dt);
160         _instance->_event_context_set_signal.emit (sp_desktop_event_context (dt));
161         _instance->_selection_set_signal.emit (sp_desktop_selection (dt));
162         _instance->_selection_changed_signal.emit (sp_desktop_selection (dt));
163     }
166 /// Remove desktop from list of desktops
167 void
168 Editor::removeDesktop (SPDesktop *dt)
170     g_return_if_fail (dt != 0);
171     g_assert (g_slist_find (_instance->_desktops, dt));
173     if (dt == _instance->_desktops->data) {  // is it the active desktop?
174         _instance->_desktop_deactivated_signal.emit (dt);
175         if (_instance->_desktops->next != 0) {
176             SPDesktop * new_desktop = (SPDesktop *) _instance->_desktops->next->data;
177             _instance->_desktops = g_slist_remove (_instance->_desktops, new_desktop);
178             _instance->_desktops = g_slist_prepend (_instance->_desktops, new_desktop);
179             _instance->_desktop_activated_signal.emit (new_desktop);
180             _instance->_event_context_set_signal.emit (sp_desktop_event_context (new_desktop));
181             _instance->_selection_set_signal.emit (sp_desktop_selection (new_desktop));
182             _instance->_selection_changed_signal.emit (sp_desktop_selection (new_desktop));
183         } else {
184             _instance->_event_context_set_signal.emit (0);
185             if (sp_desktop_selection(dt))
186                 sp_desktop_selection(dt)->clear();
187         }
188     }
190     _instance->_desktops = g_slist_remove (_instance->_desktops, dt);
192     // if this was the last desktop, shut down the program
193     if (_instance->_desktops == NULL) {
194         _instance->_shutdown_signal.emit();
195         Inkscape::NSApplication::Application::exit();
196     }
199 void 
200 Editor::activateDesktop (SPDesktop* dt)
202     g_assert (dt != 0);
203     if (isDesktopActive (dt))
204         return;
206     g_assert (g_slist_find (_instance->_desktops, dt));
207     SPDesktop *curr = (SPDesktop*)_instance->_desktops->data;
208     _instance->_desktop_deactivated_signal.emit (curr);
210     _instance->_desktops = g_slist_remove (_instance->_desktops, dt);
211     _instance->_desktops = g_slist_prepend (_instance->_desktops, dt);
213     _instance->_desktop_activated_signal.emit (dt);
214     _instance->_event_context_set_signal.emit (sp_desktop_event_context(dt));
215     _instance->_selection_set_signal.emit (sp_desktop_selection(dt));
216     _instance->_selection_changed_signal.emit (sp_desktop_selection(dt));
219 void 
220 Editor::reactivateDesktop (SPDesktop* dt)
222     g_assert (dt != 0);
223     if (isDesktopActive(dt))
224         _instance->_desktop_activated_signal.emit (dt);
227 bool
228 Editor::isDuplicatedView (SPDesktop* dt)
230     SPDocument const* document = dt->doc();
231     if (!document) {
232         return false;
233     }
234     for ( GSList *iter = _instance->_desktops ; iter ; iter = iter->next ) {
235         SPDesktop *other_desktop=(SPDesktop *)iter->data;
236         SPDocument *other_document=other_desktop->doc();
237         if ( other_document == document && other_desktop != dt ) {
238             return true;
239         }
240     }
241     return false;
244  /// Returns the event context
245 //SPEventContext*
246 //Editor::getEventContext()
247 //{
248 //    if (getActiveDesktop()) {
249 //        return sp_desktop_event_context (getActiveDesktop());
250 //    }
251 //
252 //    return NULL;
253 //}
256 void 
257 Editor::selectionModified (Inkscape::Selection* sel, guint flags)
259     g_return_if_fail (sel != NULL);
260     if (isDesktopActive (sel->desktop()))
261         _instance->_selection_modified_signal.emit (sel, flags);
264 void 
265 Editor::selectionChanged (Inkscape::Selection* sel)
267     g_return_if_fail (sel != NULL);
268     if (isDesktopActive (sel->desktop()))
269         _instance->_selection_changed_signal.emit (sel);
272 void 
273 Editor::subSelectionChanged (SPDesktop* dt)
275     g_return_if_fail (dt != NULL);
276     if (isDesktopActive (dt)) 
277         _instance->_subselection_changed_signal.emit (dt);
280 void 
281 Editor::selectionSet (Inkscape::Selection* sel)
283     g_return_if_fail (sel != NULL);
284     if (isDesktopActive (sel->desktop())) {
285         _instance->_selection_set_signal.emit (sel);
286         _instance->_selection_changed_signal.emit (sel);
287     }
290 void 
291 Editor::eventContextSet (SPEventContext* ec)
293     g_return_if_fail (ec != NULL);
294     g_return_if_fail (SP_IS_EVENT_CONTEXT (ec));
295     if (isDesktopActive (ec->desktop))
296         _instance->_event_context_set_signal.emit (ec);
299 void
300 Editor::hideDialogs()
302     _instance->_dialogs_hidden_signal.emit();
303     _instance->_dialogs_toggle = false;
306 void
307 Editor::unhideDialogs()
309     _instance->_dialogs_unhidden_signal.emit();
310     _instance->_dialogs_toggle = true;
313 void
314 Editor::toggleDialogs()
316     if (_dialogs_toggle) {
317         hideDialogs();
318     } else {
319         unhideDialogs();
320     }
323 void
324 Editor::refreshDisplay()
326     // TODO
329 void
330 Editor::exit()
332     //emit shutdown signal so that dialogs could remember layout
333     _shutdown_signal.emit();
334     Inkscape::Preferences::unload();
337 //==================================================================
339 sigc::connection 
340 Editor::connectSelectionModified 
341 (const sigc::slot<void, Inkscape::Selection*, guint> &slot)
343     return _instance->_selection_modified_signal.connect (slot);
346 sigc::connection 
347 Editor::connectSelectionChanged 
348 (const sigc::slot<void, Inkscape::Selection*> &slot)
350     return _instance->_selection_changed_signal.connect (slot);
353 sigc::connection 
354 Editor::connectSubselectionChanged (const sigc::slot<void, SPDesktop*> &slot)
356     return _instance->_subselection_changed_signal.connect (slot);
359 sigc::connection 
360 Editor::connectSelectionSet (const sigc::slot<void, Inkscape::Selection*> &slot)
362     return _instance->_selection_set_signal.connect (slot);
365 sigc::connection 
366 Editor::connectEventContextSet (const sigc::slot<void, SPEventContext*> &slot)
368     return _instance->_event_context_set_signal.connect (slot);
371 sigc::connection 
372 Editor::connectDesktopActivated (const sigc::slot<void, SPDesktop*> &slot)
374     return _instance->_desktop_activated_signal.connect (slot);
377 sigc::connection 
378 Editor::connectDesktopDeactivated (const sigc::slot<void, SPDesktop*> &slot)
380     return _instance->_desktop_deactivated_signal.connect (slot);
382     
383 sigc::connection 
384 Editor::connectShutdown (const sigc::slot<void> &slot)
386     return _instance->_shutdown_signal.connect (slot);
389 sigc::connection 
390 Editor::connectDialogsHidden (const sigc::slot<void> &slot)
392     return _instance->_dialogs_hidden_signal.connect (slot);
395 sigc::connection 
396 Editor::connectDialogsUnhidden (const sigc::slot<void> &slot)
398     return _instance->_dialogs_unhidden_signal.connect (slot);
401 sigc::connection 
402 Editor::connectExternalChange (const sigc::slot<void> &slot)
404     return _instance->_external_change_signal.connect (slot);
408 } // namespace NSApplication
409 } // namespace Inkscape
411 /*
412   Local Variables:
413   mode:c++
414   c-file-style:"stroustrup"
415   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
416   indent-tabs-mode:nil
417   fill-column:99
418   End:
419 */
420 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :