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()
102 {
103 if (getActiveDesktop()) {
104 return sp_desktop_document (getActiveDesktop());
105 }
107 return NULL;
108 }
110 void
111 Editor::addDocument (SPDocument *doc)
112 {
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);
117 }
119 void
120 Editor::removeDocument (SPDocument *doc)
121 {
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 }
126 }
128 SPDesktop*
129 Editor::createDesktop (SPDocument* doc)
130 {
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;
137 }
139 /// Returns the currently active desktop
140 SPDesktop*
141 Editor::getActiveDesktop()
142 {
143 if (_instance->_desktops == NULL) {
144 return NULL;
145 }
147 return (SPDesktop *) _instance->_desktops->data;
148 }
150 /// Add desktop to list of desktops
151 void
152 Editor::addDesktop (SPDesktop *dt)
153 {
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 }
165 }
167 /// Remove desktop from list of desktops
168 void
169 Editor::removeDesktop (SPDesktop *dt)
170 {
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 }
198 }
200 void
201 Editor::activateDesktop (SPDesktop* dt)
202 {
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));
218 }
220 void
221 Editor::reactivateDesktop (SPDesktop* dt)
222 {
223 g_assert (dt != 0);
224 if (isDesktopActive(dt))
225 _instance->_desktop_activated_signal.emit (dt);
226 }
228 bool
229 Editor::isDuplicatedView (SPDesktop* dt)
230 {
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;
243 }
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)
259 {
260 g_return_if_fail (sel != NULL);
261 if (isDesktopActive (sel->desktop()))
262 _instance->_selection_modified_signal.emit (sel, flags);
263 }
265 void
266 Editor::selectionChanged (Inkscape::Selection* sel)
267 {
268 g_return_if_fail (sel != NULL);
269 if (isDesktopActive (sel->desktop()))
270 _instance->_selection_changed_signal.emit (sel);
271 }
273 void
274 Editor::subSelectionChanged (SPDesktop* dt)
275 {
276 g_return_if_fail (dt != NULL);
277 if (isDesktopActive (dt))
278 _instance->_subselection_changed_signal.emit (dt);
279 }
281 void
282 Editor::selectionSet (Inkscape::Selection* sel)
283 {
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 }
289 }
291 void
292 Editor::eventContextSet (SPEventContext* ec)
293 {
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);
298 }
300 void
301 Editor::hideDialogs()
302 {
303 _instance->_dialogs_hidden_signal.emit();
304 _instance->_dialogs_toggle = false;
305 }
307 void
308 Editor::unhideDialogs()
309 {
310 _instance->_dialogs_unhidden_signal.emit();
311 _instance->_dialogs_toggle = true;
312 }
314 void
315 Editor::toggleDialogs()
316 {
317 if (_dialogs_toggle) {
318 hideDialogs();
319 } else {
320 unhideDialogs();
321 }
322 }
324 void
325 Editor::refreshDisplay()
326 {
327 // TODO
328 }
330 void
331 Editor::exit()
332 {
333 //emit shutdown signal so that dialogs could remember layout
334 _shutdown_signal.emit();
335 Inkscape::Preferences::unload();
336 }
338 //==================================================================
340 sigc::connection
341 Editor::connectSelectionModified
342 (const sigc::slot<void, Inkscape::Selection*, guint> &slot)
343 {
344 return _instance->_selection_modified_signal.connect (slot);
345 }
347 sigc::connection
348 Editor::connectSelectionChanged
349 (const sigc::slot<void, Inkscape::Selection*> &slot)
350 {
351 return _instance->_selection_changed_signal.connect (slot);
352 }
354 sigc::connection
355 Editor::connectSubselectionChanged (const sigc::slot<void, SPDesktop*> &slot)
356 {
357 return _instance->_subselection_changed_signal.connect (slot);
358 }
360 sigc::connection
361 Editor::connectSelectionSet (const sigc::slot<void, Inkscape::Selection*> &slot)
362 {
363 return _instance->_selection_set_signal.connect (slot);
364 }
366 sigc::connection
367 Editor::connectEventContextSet (const sigc::slot<void, SPEventContext*> &slot)
368 {
369 return _instance->_event_context_set_signal.connect (slot);
370 }
372 sigc::connection
373 Editor::connectDesktopActivated (const sigc::slot<void, SPDesktop*> &slot)
374 {
375 return _instance->_desktop_activated_signal.connect (slot);
376 }
378 sigc::connection
379 Editor::connectDesktopDeactivated (const sigc::slot<void, SPDesktop*> &slot)
380 {
381 return _instance->_desktop_deactivated_signal.connect (slot);
382 }
384 sigc::connection
385 Editor::connectShutdown (const sigc::slot<void> &slot)
386 {
387 return _instance->_shutdown_signal.connect (slot);
388 }
390 sigc::connection
391 Editor::connectDialogsHidden (const sigc::slot<void> &slot)
392 {
393 return _instance->_dialogs_hidden_signal.connect (slot);
394 }
396 sigc::connection
397 Editor::connectDialogsUnhidden (const sigc::slot<void> &slot)
398 {
399 return _instance->_dialogs_unhidden_signal.connect (slot);
400 }
402 sigc::connection
403 Editor::connectExternalChange (const sigc::slot<void> &slot)
404 {
405 return _instance->_external_change_signal.connect (slot);
406 }
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 :