Code

Change the way preferences are loaded to simplify unit testing
[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 *prefs = Inkscape::Preferences::get();
69     prefs->load(true, false);
70 }
72 bool
73 Editor::init()
74 {
75     // Load non-local template until we have everything right
76     // This code formerly lived in file.cpp
77     //
78     gchar const *tmpl = g_build_filename ((INKSCAPE_TEMPLATESDIR), "default.svg", NULL);
79     bool have_default = Inkscape::IO::file_test (tmpl, G_FILE_TEST_IS_REGULAR);
80     SPDocument *doc = sp_document_new (have_default? tmpl:0, true, true);
81     g_return_val_if_fail (doc != 0, false);
82     Inkscape::UI::View::EditWidget *ew = new Inkscape::UI::View::EditWidget (doc);
83     sp_document_unref (doc);
84     _window = ew->getWindow();
85     return ew != 0;
86 }
88 Editor::~Editor()
89 {
90 }
92 /// Returns the Window representation of this application object
93 void*
94 Editor::getWindow()
95 {
96     return _window;
97 }
99 /// Returns the active document
100 SPDocument*
101 Editor::getActiveDocument()
103     if (getActiveDesktop()) {
104         return sp_desktop_document (getActiveDesktop());
105     }
107     return NULL;
110 void
111 Editor::addDocument (SPDocument *doc)
113     if ( _instance->_document_set.find(doc) == _instance->_document_set.end() ) {
114         _instance->_documents = g_slist_append (_instance->_documents, doc);
115     }
116     _instance->_document_set.insert(doc);
119 void
120 Editor::removeDocument (SPDocument *doc)
122     _instance->_document_set.erase(doc);
123     if ( _instance->_document_set.find(doc) == _instance->_document_set.end() ) {
124         _instance->_documents = g_slist_remove (_instance->_documents, doc);
125     }
128 SPDesktop* 
129 Editor::createDesktop (SPDocument* doc)
131     g_assert (doc != 0);
132     (new Inkscape::UI::View::EditWidget (doc))->present();
133     sp_document_unref (doc);
134     SPDesktop *dt = getActiveDesktop();
135     reactivateDesktop (dt);
136     return dt;
139 /// Returns the currently active desktop
140 SPDesktop*
141 Editor::getActiveDesktop()
143     if (_instance->_desktops == NULL) {
144         return NULL;
145     }
147     return (SPDesktop *) _instance->_desktops->data;
150 /// Add desktop to list of desktops
151 void
152 Editor::addDesktop (SPDesktop *dt)
154     g_return_if_fail (dt != 0);
155     g_assert (!g_slist_find (_instance->_desktops, dt));
157     _instance->_desktops = g_slist_append (_instance->_desktops, dt);
159     if (isDesktopActive (dt)) {
160         _instance->_desktop_activated_signal.emit (dt);
161         _instance->_event_context_set_signal.emit (sp_desktop_event_context (dt));
162         _instance->_selection_set_signal.emit (sp_desktop_selection (dt));
163         _instance->_selection_changed_signal.emit (sp_desktop_selection (dt));
164     }
167 /// Remove desktop from list of desktops
168 void
169 Editor::removeDesktop (SPDesktop *dt)
171     g_return_if_fail (dt != 0);
172     g_assert (g_slist_find (_instance->_desktops, dt));
174     if (dt == _instance->_desktops->data) {  // is it the active desktop?
175         _instance->_desktop_deactivated_signal.emit (dt);
176         if (_instance->_desktops->next != 0) {
177             SPDesktop * new_desktop = (SPDesktop *) _instance->_desktops->next->data;
178             _instance->_desktops = g_slist_remove (_instance->_desktops, new_desktop);
179             _instance->_desktops = g_slist_prepend (_instance->_desktops, new_desktop);
180             _instance->_desktop_activated_signal.emit (new_desktop);
181             _instance->_event_context_set_signal.emit (sp_desktop_event_context (new_desktop));
182             _instance->_selection_set_signal.emit (sp_desktop_selection (new_desktop));
183             _instance->_selection_changed_signal.emit (sp_desktop_selection (new_desktop));
184         } else {
185             _instance->_event_context_set_signal.emit (0);
186             if (sp_desktop_selection(dt))
187                 sp_desktop_selection(dt)->clear();
188         }
189     }
191     _instance->_desktops = g_slist_remove (_instance->_desktops, dt);
193     // if this was the last desktop, shut down the program
194     if (_instance->_desktops == NULL) {
195         _instance->_shutdown_signal.emit();
196         Inkscape::NSApplication::Application::exit();
197     }
200 void 
201 Editor::activateDesktop (SPDesktop* dt)
203     g_assert (dt != 0);
204     if (isDesktopActive (dt))
205         return;
207     g_assert (g_slist_find (_instance->_desktops, dt));
208     SPDesktop *curr = (SPDesktop*)_instance->_desktops->data;
209     _instance->_desktop_deactivated_signal.emit (curr);
211     _instance->_desktops = g_slist_remove (_instance->_desktops, dt);
212     _instance->_desktops = g_slist_prepend (_instance->_desktops, dt);
214     _instance->_desktop_activated_signal.emit (dt);
215     _instance->_event_context_set_signal.emit (sp_desktop_event_context(dt));
216     _instance->_selection_set_signal.emit (sp_desktop_selection(dt));
217     _instance->_selection_changed_signal.emit (sp_desktop_selection(dt));
220 void 
221 Editor::reactivateDesktop (SPDesktop* dt)
223     g_assert (dt != 0);
224     if (isDesktopActive(dt))
225         _instance->_desktop_activated_signal.emit (dt);
228 bool
229 Editor::isDuplicatedView (SPDesktop* dt)
231     SPDocument const* document = dt->doc();
232     if (!document) {
233         return false;
234     }
235     for ( GSList *iter = _instance->_desktops ; iter ; iter = iter->next ) {
236         SPDesktop *other_desktop=(SPDesktop *)iter->data;
237         SPDocument *other_document=other_desktop->doc();
238         if ( other_document == document && other_desktop != dt ) {
239             return true;
240         }
241     }
242     return false;
245  /// Returns the event context
246 //SPEventContext*
247 //Editor::getEventContext()
248 //{
249 //    if (getActiveDesktop()) {
250 //        return sp_desktop_event_context (getActiveDesktop());
251 //    }
252 //
253 //    return NULL;
254 //}
257 void 
258 Editor::selectionModified (Inkscape::Selection* sel, guint flags)
260     g_return_if_fail (sel != NULL);
261     if (isDesktopActive (sel->desktop()))
262         _instance->_selection_modified_signal.emit (sel, flags);
265 void 
266 Editor::selectionChanged (Inkscape::Selection* sel)
268     g_return_if_fail (sel != NULL);
269     if (isDesktopActive (sel->desktop()))
270         _instance->_selection_changed_signal.emit (sel);
273 void 
274 Editor::subSelectionChanged (SPDesktop* dt)
276     g_return_if_fail (dt != NULL);
277     if (isDesktopActive (dt)) 
278         _instance->_subselection_changed_signal.emit (dt);
281 void 
282 Editor::selectionSet (Inkscape::Selection* sel)
284     g_return_if_fail (sel != NULL);
285     if (isDesktopActive (sel->desktop())) {
286         _instance->_selection_set_signal.emit (sel);
287         _instance->_selection_changed_signal.emit (sel);
288     }
291 void 
292 Editor::eventContextSet (SPEventContext* ec)
294     g_return_if_fail (ec != NULL);
295     g_return_if_fail (SP_IS_EVENT_CONTEXT (ec));
296     if (isDesktopActive (ec->desktop))
297         _instance->_event_context_set_signal.emit (ec);
300 void
301 Editor::hideDialogs()
303     _instance->_dialogs_hidden_signal.emit();
304     _instance->_dialogs_toggle = false;
307 void
308 Editor::unhideDialogs()
310     _instance->_dialogs_unhidden_signal.emit();
311     _instance->_dialogs_toggle = true;
314 void
315 Editor::toggleDialogs()
317     if (_dialogs_toggle) {
318         hideDialogs();
319     } else {
320         unhideDialogs();
321     }
324 void
325 Editor::refreshDisplay()
327     // TODO
330 void
331 Editor::exit()
333     //emit shutdown signal so that dialogs could remember layout
334     _shutdown_signal.emit();
335     Inkscape::Preferences::unload();
338 //==================================================================
340 sigc::connection 
341 Editor::connectSelectionModified 
342 (const sigc::slot<void, Inkscape::Selection*, guint> &slot)
344     return _instance->_selection_modified_signal.connect (slot);
347 sigc::connection 
348 Editor::connectSelectionChanged 
349 (const sigc::slot<void, Inkscape::Selection*> &slot)
351     return _instance->_selection_changed_signal.connect (slot);
354 sigc::connection 
355 Editor::connectSubselectionChanged (const sigc::slot<void, SPDesktop*> &slot)
357     return _instance->_subselection_changed_signal.connect (slot);
360 sigc::connection 
361 Editor::connectSelectionSet (const sigc::slot<void, Inkscape::Selection*> &slot)
363     return _instance->_selection_set_signal.connect (slot);
366 sigc::connection 
367 Editor::connectEventContextSet (const sigc::slot<void, SPEventContext*> &slot)
369     return _instance->_event_context_set_signal.connect (slot);
372 sigc::connection 
373 Editor::connectDesktopActivated (const sigc::slot<void, SPDesktop*> &slot)
375     return _instance->_desktop_activated_signal.connect (slot);
378 sigc::connection 
379 Editor::connectDesktopDeactivated (const sigc::slot<void, SPDesktop*> &slot)
381     return _instance->_desktop_deactivated_signal.connect (slot);
383     
384 sigc::connection 
385 Editor::connectShutdown (const sigc::slot<void> &slot)
387     return _instance->_shutdown_signal.connect (slot);
390 sigc::connection 
391 Editor::connectDialogsHidden (const sigc::slot<void> &slot)
393     return _instance->_dialogs_hidden_signal.connect (slot);
396 sigc::connection 
397 Editor::connectDialogsUnhidden (const sigc::slot<void> &slot)
399     return _instance->_dialogs_unhidden_signal.connect (slot);
402 sigc::connection 
403 Editor::connectExternalChange (const sigc::slot<void> &slot)
405     return _instance->_external_change_signal.connect (slot);
409 } // namespace NSApplication
410 } // namespace Inkscape
412 /*
413   Local Variables:
414   mode:c++
415   c-file-style:"stroustrup"
416   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
417   indent-tabs-mode:nil
418   fill-column:99
419   End:
420 */
421 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :