1 /**
2 * \brief This class implements the functionality of the window layout, menus,
3 * and signals.
4 *
5 * This is a reimplementation into C++/Gtkmm of Sodipodi's SPDesktopWidget class.
6 * Both SPDesktopWidget and EditWidget adhere to the EditWidgetInterface, so
7 * they both can serve as widget for the same SPDesktop/Edit class.
8 *
9 * Ideally, this class should only contain the handling of the Window (i.e.,
10 * content construction and window signals) and implement its
11 * EditWidgetInterface.
12 *
13 * Authors:
14 * Ralf Stephan <ralf@ark.in-berlin.de>
15 * Bryce W. Harrington <bryce@bryceharrington.org>
16 * Derek P. Moore <derekm@hackunix.org>
17 * Lauris Kaplinski <lauris@kaplinski.com>
18 * Frank Felfe <innerspace@iname.com>
19 * John Bintz <jcoswell@coswellproductions.org>
20 * Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
21 *
22 * Copyright (C) 2007 Johan Engelen
23 * Copyright (C) 2006 John Bintz
24 * Copyright (C) 1999-2005 Authors
25 * Copyright (C) 2000-2001 Ximian, Inc.
26 *
27 * Released under GNU GPL. Read the file 'COPYING' for more information.
28 */
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
34 #include <gtk/gtkwindow.h>
35 #include <gtk/gtkversion.h>
36 #include <gtk/gtklabel.h>
37 #include <gtkmm/radioaction.h>
38 #include <gtkmm/menubar.h>
39 #include <gtkmm/messagedialog.h>
40 #include <gtkmm/stock.h>
41 #include <gtkmm/accelmap.h>
42 #include <gtkmm/separator.h>
43 #include <gtkmm/base.h>
45 #include <sigc++/functors/mem_fun.h>
47 #include "macros.h"
48 #include "path-prefix.h"
49 #include "preferences.h"
50 #include "file.h"
51 #include "application/editor.h"
52 #include "edit-widget.h"
53 #include "ui/stock.h"
54 #include "ui/stock-items.h"
56 #include "display/sodipodi-ctrlrect.h"
57 #include "helper/units.h"
58 #include "shortcuts.h"
59 #include "widgets/spw-utilities.h"
60 #include "event-context.h"
61 #include "document.h"
62 #include "sp-namedview.h"
63 #include "sp-item.h"
64 #include "interface.h"
65 #include "extension/db.h"
67 #include "ui/dialog/dialog-manager.h"
69 using namespace Inkscape::UI;
70 using namespace Inkscape::UI::Widget;
72 namespace Inkscape {
73 namespace UI {
74 namespace View {
76 EditWidget::EditWidget (SPDocument *doc)
77 : _main_window_table(4),
78 _viewport_table(3,3),
79 _act_grp(Gtk::ActionGroup::create()),
80 _ui_mgr(Gtk::UIManager::create()),
81 _update_s_f(false),
82 _update_a_f(false),
83 _interaction_disabled_counter(0)
84 {
85 g_warning("Creating new EditWidget");
87 _desktop = 0;
88 Stock::init();
89 initActions();
90 initAccelMap();
91 initUIManager();
92 initLayout();
93 initEdit (doc);
94 g_warning("Done creating new EditWidget");
95 }
97 EditWidget::~EditWidget()
98 {
99 destroyEdit();
100 }
102 void
103 EditWidget::initActions()
104 {
105 initMenuActions();
106 initToolbarActions();
107 }
109 void
110 EditWidget::initUIManager()
111 {
112 _ui_mgr->insert_action_group(_act_grp);
113 add_accel_group(_ui_mgr->get_accel_group());
115 gchar *filename_utf8 = g_build_filename(INKSCAPE_UIDIR, "menus-bars.xml", NULL);
116 if (_ui_mgr->add_ui_from_file(filename_utf8) == 0) {
117 g_warning("Error merging ui from file '%s'", filename_utf8);
118 // fixme-charset: What charset should we pass to g_warning?
119 }
120 g_free(filename_utf8);
121 }
123 void
124 EditWidget::initLayout()
125 {
126 set_title("New document 1 - Inkscape");
127 set_resizable();
128 set_default_size(640, 480);
130 // top level window into which all other portions of the UI get inserted
131 add(_main_window_table);
132 // attach box for horizontal toolbars
133 _main_window_table.attach(_toolbars_vbox, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
134 // attach sub-window for viewport and vertical toolbars
135 _main_window_table.attach(_sub_window_hbox, 0, 1, 2, 3);
136 // viewport table with 3 rows by 3 columns
137 _sub_window_hbox.pack_end(_viewport_table);
139 // Menus and Bars
140 initMenuBar();
141 initCommandsBar();
142 initToolControlsBar();
143 initUriBar();
144 initToolsBar();
146 // Canvas Viewport
147 initLeftRuler();
148 initTopRuler();
149 initStickyZoom();
150 initBottomScrollbar();
151 initRightScrollbar();
152 _viewport_table.attach(_svg_canvas.widget(), 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
153 _svg_canvas.widget().show_all();
155 // The statusbar comes last and appears at the bottom of _main_window_table
156 initStatusbar();
158 signal_size_allocate().connect (sigc::mem_fun (*this, &EditWidget::onWindowSizeAllocate), false);
159 signal_realize().connect (sigc::mem_fun (*this, &EditWidget::onWindowRealize));
160 show_all_children();
161 }
163 void
164 EditWidget::onMenuItem()
165 {
166 g_warning("onMenuItem called");
167 }
169 void
170 EditWidget::onActionFileNew()
171 {
172 // g_warning("onActionFileNew called");
173 sp_file_new_default();
174 }
176 void
177 EditWidget::onActionFileOpen()
178 {
179 // g_warning("onActionFileOpen called");
180 sp_file_open_dialog (*this, NULL, NULL);
181 }
183 void
184 EditWidget::onActionFileQuit()
185 {
186 g_warning("onActionFileQuit");
187 sp_ui_close_all();
188 }
190 void
191 EditWidget::onActionFilePrint()
192 {
193 g_warning("onActionFilePrint");
194 }
196 void
197 EditWidget::onToolbarItem()
198 {
199 g_warning("onToolbarItem called");
200 }
202 void
203 EditWidget::onSelectTool()
204 {
205 _tool_ctrl->remove();
206 _tool_ctrl->add(*_select_ctrl);
207 }
209 void
210 EditWidget::onNodeTool()
211 {
212 _tool_ctrl->remove();
213 _tool_ctrl->add(*_node_ctrl);
214 }
216 void
217 EditWidget::onDialogInkscapePreferences()
218 {
219 _dlg_mgr.showDialog("InkscapePreferences");
220 }
222 void
223 EditWidget::onDialogAbout()
224 {
225 }
227 void
228 EditWidget::onDialogAlignAndDistribute()
229 {
230 _dlg_mgr.showDialog("AlignAndDistribute");
231 }
233 void
234 EditWidget::onDialogDocumentProperties()
235 {
236 // manage (Inkscape::UI::Dialog::DocumentPreferences::create());
237 _dlg_mgr.showDialog("DocumentPreferences");
238 }
240 void
241 EditWidget::onDialogExport()
242 {
243 _dlg_mgr.showDialog("Export");
244 }
246 void
247 EditWidget::onDialogExtensionEditor()
248 {
249 _dlg_mgr.showDialog("ExtensionEditor");
250 }
252 void
253 EditWidget::onDialogFillAndStroke()
254 {
255 _dlg_mgr.showDialog("FillAndStroke");
256 }
258 void
259 EditWidget::onDialogFind()
260 {
261 _dlg_mgr.showDialog("Find");
262 }
264 void
265 EditWidget::onDialogLayerEditor()
266 {
267 _dlg_mgr.showDialog("LayerEditor");
268 }
270 void
271 EditWidget::onDialogMessages()
272 {
273 _dlg_mgr.showDialog("Messages");
274 }
276 void
277 EditWidget::onDialogObjectProperties()
278 {
279 _dlg_mgr.showDialog("ObjectProperties");
280 }
282 void
283 EditWidget::onDialogTextProperties()
284 {
285 _dlg_mgr.showDialog("TextProperties");
286 }
288 void
289 EditWidget::onDialogTrace()
290 {
291 }
293 void
294 EditWidget::onDialogTransformation()
295 {
296 _dlg_mgr.showDialog("Transformation");
297 }
299 void
300 EditWidget::onDialogXmlEditor()
301 {
302 _dlg_mgr.showDialog("XmlEditor");
303 }
305 void
306 EditWidget::onUriChanged()
307 {
308 g_message("onUriChanged called");
310 }
312 // FIXME: strings are replaced by placeholders, NOT to be translated until the code is enabled
313 // See http://sourceforge.net/mailarchive/message.php?msg_id=11746016 for details
315 void
316 EditWidget::initMenuActions()
317 {
318 // _act_grp->add(Gtk::Action::create("MenuFile", _("PLACEHOLDER, do not translate")));
319 // _act_grp->add(Gtk::Action::create("MenuEdit", _("PLACEHOLDER, do not translate")));
320 // _act_grp->add(Gtk::Action::create("MenuView", _("PLACEHOLDER, do not translate")));
321 // _act_grp->add(Gtk::Action::create("MenuLayer", _("PLACEHOLDER, do not translate")));
322 // _act_grp->add(Gtk::Action::create("MenuObject", _("PLACEHOLDER, do not translate")));
323 // _act_grp->add(Gtk::Action::create("MenuPath", _("PLACEHOLDER, do not translate")));
324 // _act_grp->add(Gtk::Action::create("MenuText", _("PLACEHOLDER, do not translate")));
325 // _act_grp->add(Gtk::Action::create("MenuHelp", _("PLACEHOLDER, do not translate")));
326 // temporarily replaced with non-gettext version to have a well-sized menu
327 // for testing:
329 _act_grp->add(Gtk::Action::create("MenuFile", "File"));
330 _act_grp->add(Gtk::Action::create("MenuEdit", "Edit"));
331 _act_grp->add(Gtk::Action::create("MenuView", "View"));
332 _act_grp->add(Gtk::Action::create("MenuLayer", "Layer"));
333 _act_grp->add(Gtk::Action::create("MenuObject", "Object"));
334 _act_grp->add(Gtk::Action::create("MenuPath", "Path"));
335 _act_grp->add(Gtk::Action::create("MenuText", "Text"));
336 _act_grp->add(Gtk::Action::create("MenuHelp", "Help"));
338 // File menu
339 _act_grp->add(Gtk::Action::create("New",
340 Gtk::Stock::NEW, Glib::ustring(),
341 _("PLACEHOLDER, do not translate")),
342 sigc::mem_fun(*this, &EditWidget::onActionFileNew));
344 _act_grp->add(Gtk::Action::create("Open",
345 Gtk::Stock::OPEN, Glib::ustring(),
346 _("PLACEHOLDER, do not translate")),
347 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
349 _act_grp->add(Gtk::Action::create("OpenRecent",
350 Stock::OPEN_RECENT));
352 _act_grp->add(Gtk::Action::create("Revert",
353 Gtk::Stock::REVERT_TO_SAVED, Glib::ustring(),
354 _("PLACEHOLDER, do not translate")),
355 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
357 _act_grp->add(Gtk::Action::create("Save",
358 Gtk::Stock::SAVE, Glib::ustring(),
359 _("PLACEHOLDER, do not translate")),
360 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
362 _act_grp->add(Gtk::Action::create("SaveAs",
363 Gtk::Stock::SAVE_AS, Glib::ustring(),
364 _("PLACEHOLDER, do not translate")),
365 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
367 _act_grp->add(Gtk::Action::create("Import",
368 Stock::IMPORT, Glib::ustring(),
369 _("PLACEHOLDER, do not translate")),
370 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
372 _act_grp->add(Gtk::Action::create("Export",
373 Stock::EXPORT, Glib::ustring(),
374 _("PLACEHOLDER, do not translate")),
375 sigc::mem_fun(*this, &EditWidget::onDialogExport));
377 _act_grp->add(Gtk::Action::create("Print",
378 Gtk::Stock::PRINT, Glib::ustring(),
379 _("PLACEHOLDER, do not translate")),
380 sigc::mem_fun(*this, &EditWidget::onActionFilePrint));
382 _act_grp->add(Gtk::Action::create("PrintPreview",
383 Gtk::Stock::PRINT_PREVIEW),
384 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
386 _act_grp->add(Gtk::Action::create("VacuumDefs",
387 Stock::VACUUM_DEFS),
388 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
390 _act_grp->add(Gtk::Action::create("DocumentProperties",
391 Gtk::Stock::PROPERTIES, Glib::ustring(),
392 _("PLACEHOLDER, do not translate")),
393 sigc::mem_fun(*this, &EditWidget::onDialogDocumentProperties));
395 _act_grp->add(Gtk::Action::create("InkscapePreferences",
396 Gtk::Stock::PREFERENCES, Glib::ustring(),
397 _("PLACEHOLDER, do not translate")),
398 sigc::mem_fun(*this, &EditWidget::onDialogInkscapePreferences));
400 _act_grp->add(Gtk::Action::create("Close",
401 Gtk::Stock::CLOSE),
402 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
404 _act_grp->add(Gtk::Action::create("Quit",
405 Gtk::Stock::QUIT),
406 sigc::mem_fun(*this, &EditWidget::onActionFileQuit));
408 // EditWidget menu
409 _act_grp->add(Gtk::Action::create("Undo",
410 Gtk::Stock::UNDO, Glib::ustring(),
411 _("PLACEHOLDER, do not translate")));
413 _act_grp->add(Gtk::Action::create("Redo",
414 Gtk::Stock::REDO, Glib::ustring(),
415 _("PLACEHOLDER, do not translate")));
417 _act_grp->add(Gtk::Action::create("UndoHistory",
418 Stock::UNDO_HISTORY, Glib::ustring(),
419 _("PLACEHOLDER, do not translate")));
421 _act_grp->add(Gtk::Action::create("Cut",
422 Gtk::Stock::CUT, Glib::ustring(),
423 _("PLACEHOLDER, do not translate")));
425 _act_grp->add(Gtk::Action::create("Copy",
426 Gtk::Stock::COPY, Glib::ustring(),
427 _("PLACEHOLDER, do not translate")));
429 _act_grp->add(Gtk::Action::create("Paste",
430 Gtk::Stock::PASTE, Glib::ustring(),
431 _("PLACEHOLDER, do not translate")));
433 _act_grp->add(Gtk::Action::create("PasteInPlace",
434 Stock::PASTE_IN_PLACE));
436 _act_grp->add(Gtk::Action::create("PasteStyle",
437 Stock::PASTE_STYLE));
439 _act_grp->add(Gtk::Action::create("Find",
440 Gtk::Stock::FIND),
441 sigc::mem_fun(*this, &EditWidget::onDialogFind));
443 _act_grp->add(Gtk::Action::create("Duplicate",
444 Stock::DUPLICATE, Glib::ustring(),
445 _("PLACEHOLDER, do not translate")));
447 _act_grp->add(Gtk::Action::create("Clone",
448 Stock::CLONE, Glib::ustring(),
449 _("PLACEHOLDER, do not translate")));
451 _act_grp->add(Gtk::Action::create("CloneUnlink",
452 Stock::CLONE_UNLINK, Glib::ustring(),
453 _("PLACEHOLDER, do not translate")));
455 _act_grp->add(Gtk::Action::create("CloneSelectOrig",
456 Stock::CLONE_SELECT_ORIG));
458 _act_grp->add(Gtk::Action::create("MakeBitmap",
459 Stock::MAKE_BITMAP));
461 _act_grp->add(Gtk::Action::create("Tile",
462 Stock::TILE));
464 _act_grp->add(Gtk::Action::create("Untile",
465 Stock::UNTILE));
467 _act_grp->add(Gtk::Action::create("Delete",
468 Gtk::Stock::DELETE));
470 _act_grp->add(Gtk::Action::create("SelectAll",
471 Stock::SELECT_ALL));
473 _act_grp->add(Gtk::Action::create("SelectAllInAllLayers",
474 Stock::SELECT_ALL_IN_ALL_LAYERS));
476 _act_grp->add(Gtk::Action::create("SelectInvert",
477 Stock::SELECT_INVERT));
479 _act_grp->add(Gtk::Action::create("SelectNone",
480 Stock::SELECT_NONE));
482 _act_grp->add(Gtk::Action::create("XmlEditor",
483 Stock::XML_EDITOR, Glib::ustring(),
484 _("PLACEHOLDER, do not translate")),
485 sigc::mem_fun(*this, &EditWidget::onDialogXmlEditor));
487 // View menu
488 _act_grp->add(Gtk::Action::create("Zoom",
489 Stock::ZOOM));
491 _act_grp->add(Gtk::Action::create("ZoomIn",
492 Stock::ZOOM_IN, Glib::ustring(),
493 _("PLACEHOLDER, do not translate")));
495 _act_grp->add(Gtk::Action::create("ZoomOut",
496 Stock::ZOOM_OUT, Glib::ustring(),
497 _("PLACEHOLDER, do not translate")));
499 _act_grp->add(Gtk::Action::create("Zoom100",
500 Stock::ZOOM_100, Glib::ustring(),
501 _("PLACEHOLDER, do not translate")));
503 _act_grp->add(Gtk::Action::create("Zoom50",
504 Stock::ZOOM_50, Glib::ustring(),
505 _("PLACEHOLDER, do not translate")));
507 _act_grp->add(Gtk::Action::create("Zoom200",
508 Stock::ZOOM_200, Glib::ustring(),
509 _("PLACEHOLDER, do not translate")));
511 _act_grp->add(Gtk::Action::create("ZoomSelection",
512 Stock::ZOOM_SELECTION, Glib::ustring(),
513 _("PLACEHOLDER, do not translate")));
515 _act_grp->add(Gtk::Action::create("ZoomDrawing",
516 Stock::ZOOM_DRAWING, Glib::ustring(),
517 _("PLACEHOLDER, do not translate")));
519 _act_grp->add(Gtk::Action::create("ZoomPage",
520 Stock::ZOOM_PAGE, Glib::ustring(),
521 _("PLACEHOLDER, do not translate")));
523 _act_grp->add(Gtk::Action::create("ZoomWidth",
524 Stock::ZOOM_WIDTH, Glib::ustring(),
525 _("PLACEHOLDER, do not translate")));
527 _act_grp->add(Gtk::Action::create("ZoomPrev",
528 Stock::ZOOM_PREV, Glib::ustring(),
529 _("PLACEHOLDER, do not translate")));
531 _act_grp->add(Gtk::Action::create("ZoomNext",
532 Stock::ZOOM_NEXT, Glib::ustring(),
533 _("PLACEHOLDER, do not translate")));
535 _act_grp->add(Gtk::Action::create("ShowHide",
536 Stock::SHOW_HIDE));
538 _act_grp->add(Gtk::ToggleAction::create("ShowHideCommandsBar",
539 Stock::SHOW_HIDE_COMMANDS_BAR));
541 _act_grp->add(Gtk::ToggleAction::create("ShowHideToolControlsBar",
542 Stock::SHOW_HIDE_TOOL_CONTROLS_BAR));
544 _act_grp->add(Gtk::ToggleAction::create("ShowHideToolsBar",
545 Stock::SHOW_HIDE_TOOLS_BAR));
547 _act_grp->add(Gtk::ToggleAction::create("ShowHideRulers",
548 Stock::SHOW_HIDE_RULERS));
550 _act_grp->add(Gtk::ToggleAction::create("ShowHideScrollbars",
551 Stock::SHOW_HIDE_SCROLLBARS));
553 _act_grp->add(Gtk::ToggleAction::create("ShowHideStatusbar",
554 Stock::SHOW_HIDE_STATUSBAR));
556 _act_grp->add(Gtk::Action::create("ShowHideDialogs",
557 Stock::SHOW_HIDE_DIALOGS));
559 _act_grp->add(Gtk::Action::create("Grid",
560 Stock::GRID));
562 _act_grp->add(Gtk::Action::create("Guides",
563 Stock::GUIDES));
565 _act_grp->add(Gtk::Action::create("Fullscreen",
566 Stock::FULLSCREEN));
568 _act_grp->add(Gtk::Action::create("Messages",
569 Stock::MESSAGES),
570 sigc::mem_fun(*this, &EditWidget::onDialogMessages));
572 _act_grp->add(Gtk::Action::create("Scripts",
573 Stock::SCRIPTS));
575 _act_grp->add(Gtk::Action::create("WindowPrev",
576 Stock::WINDOW_PREV));
578 _act_grp->add(Gtk::Action::create("WindowNext",
579 Stock::WINDOW_NEXT));
581 _act_grp->add(Gtk::Action::create("WindowDuplicate",
582 Stock::WINDOW_DUPLICATE));
584 // Layer menu
585 _act_grp->add(Gtk::Action::create("LayerNew",
586 Stock::LAYER_NEW));
588 _act_grp->add(Gtk::Action::create("LayerRename",
589 Stock::LAYER_RENAME));
591 _act_grp->add(Gtk::Action::create("LayerDuplicate",
592 Stock::LAYER_DUPLICATE));
594 _act_grp->add(Gtk::Action::create("LayerAnchor",
595 Stock::LAYER_ANCHOR));
597 _act_grp->add(Gtk::Action::create("LayerMergeDown",
598 Stock::LAYER_MERGE_DOWN));
600 _act_grp->add(Gtk::Action::create("LayerDelete",
601 Stock::LAYER_DELETE));
603 _act_grp->add(Gtk::Action::create("LayerSelectNext",
604 Stock::LAYER_SELECT_NEXT));
606 _act_grp->add(Gtk::Action::create("LayerSelectPrev",
607 Stock::LAYER_SELECT_PREV));
609 _act_grp->add(Gtk::Action::create("LayerSelectTop",
610 Stock::LAYER_SELECT_TOP));
612 _act_grp->add(Gtk::Action::create("LayerSelectBottom",
613 Stock::LAYER_SELECT_BOTTOM));
615 _act_grp->add(Gtk::Action::create("LayerRaise",
616 Stock::LAYER_RAISE));
618 _act_grp->add(Gtk::Action::create("LayerLower",
619 Stock::LAYER_LOWER));
621 _act_grp->add(Gtk::Action::create("LayerToTop",
622 Stock::LAYER_TO_TOP));
624 _act_grp->add(Gtk::Action::create("LayerToBottom",
625 Stock::LAYER_TO_BOTTOM));
627 // Object menu
628 _act_grp->add(Gtk::Action::create("FillAndStroke",
629 Stock::FILL_STROKE, Glib::ustring(),
630 _("PLACEHOLDER, do not translate")),
631 sigc::mem_fun(*this, &EditWidget::onDialogFillAndStroke));
633 _act_grp->add(Gtk::Action::create("ObjectProperties",
634 Stock::OBJECT_PROPERTIES),
635 sigc::mem_fun(*this, &EditWidget::onDialogObjectProperties));
637 _act_grp->add(Gtk::Action::create("FilterEffects",
638 Stock::FILTER_EFFECTS));
640 _act_grp->add(Gtk::Action::create("Group",
641 Stock::GROUP, Glib::ustring(),
642 _("PLACEHOLDER, do not translate")));
644 _act_grp->add(Gtk::Action::create("Ungroup",
645 Stock::UNGROUP, Glib::ustring(),
646 _("PLACEHOLDER, do not translate")));
648 _act_grp->add(Gtk::Action::create("Raise",
649 Stock::RAISE, Glib::ustring(),
650 _("PLACEHOLDER, do not translate")));
652 _act_grp->add(Gtk::Action::create("Lower",
653 Stock::LOWER, Glib::ustring(),
654 _("PLACEHOLDER, do not translate")));
656 _act_grp->add(Gtk::Action::create("RaiseToTop",
657 Stock::RAISE_TO_TOP, Glib::ustring(),
658 _("PLACEHOLDER, do not translate")));
660 _act_grp->add(Gtk::Action::create("LowerToBottom",
661 Stock::LOWER_TO_BOTTOM, Glib::ustring(),
662 _("PLACEHOLDER, do not translate")));
664 _act_grp->add(Gtk::Action::create("MoveToNewLayer",
665 Stock::MOVE_TO_NEW_LAYER, Glib::ustring(),
666 _("PLACEHOLDER, do not translate")));
668 _act_grp->add(Gtk::Action::create("MoveToNextLayer",
669 Stock::MOVE_TO_NEXT_LAYER, Glib::ustring(),
670 _("PLACEHOLDER, do not translate")));
672 _act_grp->add(Gtk::Action::create("MoveToPrevLayer",
673 Stock::MOVE_TO_PREV_LAYER, Glib::ustring(),
674 _("PLACEHOLDER, do not translate")));
676 _act_grp->add(Gtk::Action::create("MoveToTopLayer",
677 Stock::MOVE_TO_TOP_LAYER, Glib::ustring(),
678 _("PLACEHOLDER, do not translate")));
680 _act_grp->add(Gtk::Action::create("MoveToBottomLayer",
681 Stock::MOVE_TO_BOTTOM_LAYER, Glib::ustring(),
682 _("PLACEHOLDER, do not translate")));
684 _act_grp->add(Gtk::Action::create("Rotate90CW",
685 Stock::ROTATE_90_CW, Glib::ustring(),
686 _("PLACEHOLDER, do not translate")));
688 _act_grp->add(Gtk::Action::create("Rotate90CCW",
689 Stock::ROTATE_90_CCW, Glib::ustring(),
690 _("PLACEHOLDER, do not translate")));
692 _act_grp->add(Gtk::Action::create("FlipHoriz",
693 Stock::FLIP_HORIZ, Glib::ustring(),
694 _("PLACEHOLDER, do not translate")));
696 _act_grp->add(Gtk::Action::create("FlipVert",
697 Stock::FLIP_VERT, Glib::ustring(),
698 _("PLACEHOLDER, do not translate")));
700 _act_grp->add(Gtk::Action::create("Transformation",
701 Stock::TRANSFORMATION, Glib::ustring(),
702 _("PLACEHOLDER, do not translate")),
703 sigc::mem_fun(*this, &EditWidget::onDialogTransformation));
705 _act_grp->add(Gtk::Action::create("AlignAndDistribute",
706 Stock::ALIGN_DISTRIBUTE, Glib::ustring(),
707 _("PLACEHOLDER, do not translate")),
708 sigc::mem_fun(*this, &EditWidget::onDialogAlignAndDistribute));
710 // Path menu
711 _act_grp->add(Gtk::Action::create("ObjectToPath",
712 Stock::OBJECT_TO_PATH, Glib::ustring(),
713 _("PLACEHOLDER, do not translate")));
715 _act_grp->add(Gtk::Action::create("StrokeToPath",
716 Stock::STROKE_TO_PATH, Glib::ustring(),
717 _("PLACEHOLDER, do not translate")));
719 _act_grp->add(Gtk::Action::create("Trace",
720 Stock::TRACE),
721 sigc::mem_fun(*this, &EditWidget::onDialogTrace));
723 _act_grp->add(Gtk::Action::create("Union",
724 Stock::UNION));
726 _act_grp->add(Gtk::Action::create("Difference",
727 Stock::DIFFERENCE));
729 _act_grp->add(Gtk::Action::create("Intersection",
730 Stock::INTERSECTION));
732 _act_grp->add(Gtk::Action::create("Exclusion",
733 Stock::EXCLUSION));
735 _act_grp->add(Gtk::Action::create("Division",
736 Stock::DIVISION));
738 _act_grp->add(Gtk::Action::create("CutPath",
739 Stock::CUT_PATH));
741 _act_grp->add(Gtk::Action::create("Combine",
742 Stock::COMBINE));
744 _act_grp->add(Gtk::Action::create("BreakApart",
745 Stock::BREAK_APART));
747 _act_grp->add(Gtk::Action::create("Inset",
748 Stock::INSET));
750 _act_grp->add(Gtk::Action::create("Outset",
751 Stock::OUTSET));
753 _act_grp->add(Gtk::Action::create("OffsetDynamic",
754 Stock::OFFSET_DYNAMIC));
756 _act_grp->add(Gtk::Action::create("OffsetLinked",
757 Stock::OFFSET_LINKED));
759 _act_grp->add(Gtk::Action::create("Simplify",
760 Stock::SIMPLIFY));
762 _act_grp->add(Gtk::Action::create("Reverse",
763 Stock::REVERSE));
765 _act_grp->add(Gtk::Action::create("Cleanup",
766 Gtk::Stock::CLEAR,
767 _("PLACEHOLDER, do not translate")));
769 // Text menu
770 _act_grp->add(Gtk::Action::create("TextProperties",
771 Gtk::Stock::SELECT_FONT, Glib::ustring(),
772 _("PLACEHOLDER, do not translate")),
773 sigc::mem_fun(*this, &EditWidget::onDialogTextProperties));
775 _act_grp->add(Gtk::Action::create("PutOnPath",
776 Stock::PUT_ON_PATH));
778 _act_grp->add(Gtk::Action::create("RemoveFromPath",
779 Stock::REMOVE_FROM_PATH));
781 _act_grp->add(Gtk::Action::create("RemoveManualKerns",
782 Stock::REMOVE_MANUAL_KERNS));
784 // Whiteboard menu
785 #ifdef WITH_INKBOARD
786 #endif
788 // About menu
789 _act_grp->add(Gtk::Action::create("KeysAndMouse",
790 Stock::KEYS_MOUSE));
792 _act_grp->add(Gtk::Action::create("Tutorials",
793 Stock::TUTORIALS));
795 _act_grp->add(Gtk::Action::create("About",
796 Stock::ABOUT),
797 sigc::mem_fun(*this, &EditWidget::onDialogAbout));
798 }
800 void
801 EditWidget::initToolbarActions()
802 {
803 // Tools bar
804 Gtk::RadioAction::Group tools;
806 _act_grp->add(Gtk::RadioAction::create(tools, "ToolSelect",
807 Stock::TOOL_SELECT, Glib::ustring(),
808 _("PLACEHOLDER, do not translate")),
809 sigc::mem_fun(*this, &EditWidget::onSelectTool));
811 _act_grp->add(Gtk::RadioAction::create(tools, "ToolNode",
812 Stock::TOOL_NODE, Glib::ustring(),
813 _("PLACEHOLDER, do not translate")),
814 sigc::mem_fun(*this, &EditWidget::onNodeTool));
816 _act_grp->add(Gtk::RadioAction::create(tools, "ToolZoom",
817 Stock::TOOL_ZOOM, Glib::ustring(),
818 _("PLACEHOLDER, do not translate")));
820 _act_grp->add(Gtk::RadioAction::create(tools, "ToolRect",
821 Stock::TOOL_RECT, Glib::ustring(),
822 _("PLACEHOLDER, do not translate")));
824 _act_grp->add(Gtk::RadioAction::create(tools, "ToolArc",
825 Stock::TOOL_ARC, Glib::ustring(),
826 _("PLACEHOLDER, do not translate")));
828 _act_grp->add(Gtk::RadioAction::create(tools, "ToolStar",
829 Stock::TOOL_STAR, Glib::ustring(),
830 _("PLACEHOLDER, do not translate")));
832 _act_grp->add(Gtk::RadioAction::create(tools, "ToolSpiral",
833 Stock::TOOL_SPIRAL, Glib::ustring(),
834 _("PLACEHOLDER, do not translate")));
836 _act_grp->add(Gtk::RadioAction::create(tools, "ToolFreehand",
837 Stock::TOOL_FREEHAND, Glib::ustring(),
838 _("PLACEHOLDER, do not translate")));
840 _act_grp->add(Gtk::RadioAction::create(tools, "ToolPen",
841 Stock::TOOL_PEN, Glib::ustring(),
842 _("PLACEHOLDER, do not translate")));
844 _act_grp->add(Gtk::RadioAction::create(tools, "ToolDynaDraw",
845 Stock::TOOL_DYNADRAW, Glib::ustring(),
846 _("PLACEHOLDER, do not translate")));
848 _act_grp->add(Gtk::RadioAction::create(tools, "ToolText",
849 Stock::TOOL_TEXT, Glib::ustring(),
850 _("PLACEHOLDER, do not translate")));
852 _act_grp->add(Gtk::RadioAction::create(tools, "ToolDropper",
853 Stock::TOOL_DROPPER, Glib::ustring(),
854 _("PLACEHOLDER, do not translate")));
856 // Select Controls bar
857 _act_grp->add(Gtk::ToggleAction::create("TransformStroke",
858 Stock::TRANSFORM_STROKE, Glib::ustring(),
859 _("PLACEHOLDER, do not translate")));
861 _act_grp->add(Gtk::ToggleAction::create("TransformCorners",
862 Stock::TRANSFORM_CORNERS, Glib::ustring(),
863 _("PLACEHOLDER, do not translate")));
865 _act_grp->add(Gtk::ToggleAction::create("TransformGradient",
866 Stock::TRANSFORM_GRADIENT, Glib::ustring(),
867 _("PLACEHOLDER, do not translate")));
869 _act_grp->add(Gtk::ToggleAction::create("TransformPattern",
870 Stock::TRANSFORM_PATTERN, Glib::ustring(),
871 _("PLACEHOLDER, do not translate")));
873 // Node Controls bar
874 _act_grp->add(Gtk::Action::create("NodeInsert",
875 Gtk::Stock::ADD, Glib::ustring(),
876 _("PLACEHOLDER, do not translate")));
878 _act_grp->add(Gtk::Action::create("NodeDelete",
879 Gtk::Stock::REMOVE, Glib::ustring(),
880 _("PLACEHOLDER, do not translate")));
882 _act_grp->add(Gtk::Action::create("NodeJoin",
883 Stock::NODE_JOIN, Glib::ustring(),
884 _("PLACEHOLDER, do not translate")));
886 _act_grp->add(Gtk::Action::create("NodeJoinSegment",
887 Stock::NODE_JOIN_SEGMENT, Glib::ustring(),
888 _("PLACEHOLDER, do not translate")));
890 _act_grp->add(Gtk::Action::create("NodeDeleteSegment",
891 Stock::NODE_DELETE_SEGMENT, Glib::ustring(),
892 _("PLACEHOLDER, do not translate")));
894 _act_grp->add(Gtk::Action::create("NodeBreak",
895 Stock::NODE_BREAK, Glib::ustring(),
896 _("PLACEHOLDER, do not translate")));
898 _act_grp->add(Gtk::Action::create("NodeCorner",
899 Stock::NODE_CORNER, Glib::ustring(),
900 _("PLACEHOLDER, do not translate")));
902 _act_grp->add(Gtk::Action::create("NodeSmooth",
903 Stock::NODE_SMOOTH, Glib::ustring(),
904 _("PLACEHOLDER, do not translate")));
906 _act_grp->add(Gtk::Action::create("NodeSymmetric",
907 Stock::NODE_SYMMETRIC, Glib::ustring(),
908 _("PLACEHOLDER, do not translate")));
910 _act_grp->add(Gtk::Action::create("NodeLine",
911 Stock::NODE_LINE, Glib::ustring(),
912 _("PLACEHOLDER, do not translate")));
914 _act_grp->add(Gtk::Action::create("NodeCurve",
915 Stock::NODE_CURVE, Glib::ustring(),
916 _("PLACEHOLDER, do not translate")));
917 }
919 void
920 EditWidget::initAccelMap()
921 {
922 gchar *filename = g_build_filename(INKSCAPE_UIDIR, "keybindings.rc", NULL);
923 Gtk::AccelMap::load(filename);
924 g_free(filename);
926 // One problem is that the keys 1-6 are zoom accelerators which get
927 // caught as accelerator _before_ any Entry input handler receives them,
928 // for example the zoom status. At the moment, the best way seems to
929 // disable them as accelerators when the Entry gets focus, and enable
930 // them when focus goes elsewhere. The code for this belongs here,
931 // and not in zoom-status.cpp .
933 _zoom_status.signal_focus_in_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusIn));
934 _zoom_status.signal_focus_out_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusOut));
935 }
937 bool
938 EditWidget::onEntryFocusIn (GdkEventFocus* /*ev*/)
939 {
940 Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
941 Gtk::AccelMap::change_entry ("<Actions>//Zoom100", 0, m, false);
942 Gtk::AccelMap::change_entry ("<Actions>//Zoom50", 0, m, false);
943 Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", 0, m, false);
944 Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", 0, m, false);
945 Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", 0, m, false);
946 Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", 0, m, false);
947 return false;
948 }
950 bool
951 EditWidget::onEntryFocusOut (GdkEventFocus* /*ev*/)
952 {
953 Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
954 Gtk::AccelMap::change_entry ("<Actions>//Zoom100", '1', m, false);
955 Gtk::AccelMap::change_entry ("<Actions>//Zoom50", '2', m, false);
956 Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", '3', m, false);
957 Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", '4', m, false);
958 Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", '5', m, false);
959 Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", '6', m, false);
960 return false;
961 }
963 void
964 EditWidget::initMenuBar()
965 {
966 g_assert(_ui_mgr);
967 Gtk::MenuBar *menu = static_cast<Gtk::MenuBar*>(_ui_mgr->get_widget("/MenuBar"));
968 g_assert(menu != NULL);
969 _main_window_table.attach(*Gtk::manage(menu), 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
970 }
972 void
973 EditWidget::initCommandsBar()
974 {
975 g_assert(_ui_mgr);
976 Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/CommandsBar")),
977 Gtk::TOOLBAR_ICONS);
978 g_assert(bar != NULL);
979 _toolbars_vbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
980 }
982 void
983 EditWidget::initToolControlsBar()
984 {
985 // TODO: Do UIManager controlled widgets need to be deleted?
986 _select_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/SelectControlsBar"));
987 _node_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/NodeControlsBar"));
989 _tool_ctrl = new Toolbox(_select_ctrl, Gtk::TOOLBAR_ICONS);
991 _toolbars_vbox.pack_start(*Gtk::manage(_tool_ctrl), Gtk::PACK_SHRINK);
992 }
994 void
995 EditWidget::initUriBar()
996 {
997 /// \todo Create an Inkscape::UI::Widget::UriBar class (?)
999 _uri_ctrl = new Gtk::Toolbar();
1001 _uri_label.set_label(_("PLACEHOLDER, do not translate"));
1002 _uri_ctrl->add(_uri_label);
1003 _uri_ctrl->add(_uri_entry);
1005 _uri_entry.signal_activate()
1006 .connect_notify(sigc::mem_fun(*this, &EditWidget::onUriChanged));
1008 _toolbars_vbox.pack_start(*Gtk::manage(_uri_ctrl), Gtk::PACK_SHRINK);
1009 }
1011 void
1012 EditWidget::initToolsBar()
1013 {
1014 Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/ToolsBar")),
1015 Gtk::TOOLBAR_ICONS,
1016 Gtk::ORIENTATION_VERTICAL);
1017 g_assert(bar != NULL);
1018 _sub_window_hbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
1019 }
1021 void
1022 EditWidget::initTopRuler()
1023 {
1024 _viewport_table.attach(_top_ruler, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1026 _tooltips.set_tip (_top_ruler, _top_ruler.get_tip());
1027 }
1029 void
1030 EditWidget::initLeftRuler()
1031 {
1032 _viewport_table.attach(_left_ruler, 0, 1, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1034 _tooltips.set_tip (_left_ruler, _left_ruler.get_tip());
1035 }
1037 void
1038 EditWidget::initBottomScrollbar()
1039 {
1040 _viewport_table.attach(_bottom_scrollbar, 1, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1041 _bottom_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1042 _bottom_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1043 }
1045 void
1046 EditWidget::initRightScrollbar()
1047 {
1048 _viewport_table.attach(_right_scrollbar, 2, 3, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1050 _right_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1051 _right_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1052 }
1054 void
1055 EditWidget::initStickyZoom()
1056 {
1057 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1058 _viewport_table.attach(_sticky_zoom, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
1059 _sticky_zoom.set_active (prefs->getBool("/options/stickyzoom/value"));
1060 _tooltips.set_tip (_sticky_zoom, _("Zoom drawing if window size changes"));
1062 /// \todo icon not implemented
1063 }
1065 void
1066 EditWidget::initStatusbar()
1067 {
1068 _statusbar.pack_start (_selected_style_status, false, false, 1);
1069 _statusbar.pack_start (*new Gtk::VSeparator(), false, false, 0);
1071 _tooltips.set_tip (_zoom_status, _("Zoom"));
1073 _layer_selector.reference();
1074 _statusbar.pack_start (_layer_selector, false, false, 1);
1076 _coord_status.property_n_rows() = 2;
1077 _coord_status.property_n_columns() = 5;
1078 _coord_status.property_row_spacing() = 0;
1079 _coord_status.property_column_spacing() = 2;
1080 _coord_eventbox.add (_coord_status);
1081 _tooltips.set_tip (_coord_eventbox, _("Cursor coordinates"));
1082 _coord_status.attach (*new Gtk::VSeparator(), 0,1, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1083 _coord_status.attach (*new Gtk::Label("X:", 0.0, 0.5), 1,2, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1084 _coord_status.attach (*new Gtk::Label("Y:", 0.0, 0.5), 1,2, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1085 _coord_status_x.set_text ("0.0");
1086 _coord_status_x.set_alignment (0.0, 0.5);
1087 _coord_status_y.set_text ("0.0");
1088 _coord_status_y.set_alignment (0.0, 0.5);
1089 _coord_status.attach (_coord_status_x, 2,3, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1090 _coord_status.attach (_coord_status_y, 2,3, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1091 _coord_status.attach (*new Gtk::Label("Z:", 0.0, 0.5), 3,4, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1092 _coord_status.attach (_zoom_status, 4,5, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1093 sp_set_font_size_smaller (static_cast<GtkWidget*>((void*)_coord_status.gobj()));
1094 _statusbar.pack_end (_coord_eventbox, false, false, 1);
1096 _select_status.property_xalign() = 0.0;
1097 _select_status.property_yalign() = 0.5;
1098 _select_status.set_markup (_("<b>Welcome to Inkscape!</b> Use shape or drawing tools to create objects; use selector (arrow) to move or transform them."));
1099 // include this again with Gtk+-2.6
1100 #if GTK_VERSION_GE(2,6)
1101 gtk_label_set_ellipsize (GTK_LABEL(_select_status.gobj()), PANGO_ELLIPSIZE_END);
1102 #endif
1103 _select_status.set_size_request (1, -1);
1104 _statusbar.pack_start (_select_status, true, true, 0);
1106 _main_window_table.attach(_statusbar, 0, 1, 3, 4, Gtk::FILL, Gtk::SHRINK);
1107 }
1109 //========================================
1110 //----------implements EditWidgetInterface
1112 Gtk::Window *
1113 EditWidget::getWindow()
1114 {
1115 return this;
1116 }
1118 void
1119 EditWidget::setTitle (gchar const* new_title)
1120 {
1121 set_title (new_title);
1122 }
1124 void
1125 EditWidget::layout()
1126 {
1127 show_all_children();
1128 }
1130 void
1131 EditWidget::present()
1132 {
1133 this->Gtk::Window::present();
1134 }
1136 void
1137 EditWidget::getGeometry (gint &x, gint &y, gint &w, gint &h)
1138 {
1139 get_position (x, y);
1140 get_size (w, h);
1141 }
1143 void
1144 EditWidget::setSize (gint w, gint h)
1145 {
1146 resize (w, h);
1147 }
1149 void
1150 EditWidget::setPosition (Geom::Point p)
1151 {
1152 move (int(p[Geom::X]), int(p[Geom::Y]));
1153 }
1155 /// \param p is already gobj()!
1156 void
1157 EditWidget::setTransient (void* p, int i)
1158 {
1159 gtk_window_set_transient_for (static_cast<GtkWindow*>(p), this->gobj());
1160 if (i==2)
1161 this->Gtk::Window::present();
1162 }
1164 Geom::Point
1165 EditWidget::getPointer()
1166 {
1167 int x, y;
1168 get_pointer (x, y);
1169 return Geom::Point (x, y);
1170 }
1172 void
1173 EditWidget::setIconified()
1174 {
1175 iconify();
1176 }
1178 void
1179 EditWidget::setMaximized()
1180 {
1181 maximize();
1182 }
1184 void
1185 EditWidget::setFullscreen()
1186 {
1187 fullscreen();
1188 }
1190 /**
1191 * Shuts down the desktop object for the view being closed. It checks
1192 * to see if the document has been edited, and if so prompts the user
1193 * to save, discard, or cancel. Returns TRUE if the shutdown operation
1194 * is cancelled or if the save is cancelled or fails, FALSE otherwise.
1195 */
1196 bool
1197 EditWidget::shutdown()
1198 {
1199 g_assert (_desktop != NULL);
1200 if (Inkscape::NSApplication::Editor::isDuplicatedView (_desktop))
1201 return false;
1203 SPDocument *doc = _desktop->doc();
1204 if (doc->isModifiedSinceSave()) {
1205 gchar *markup;
1206 /// \todo FIXME !!! obviously this will have problems if the document
1207 /// name contains markup characters
1208 markup = g_strdup_printf(
1209 _("<span weight=\"bold\" size=\"larger\">Save changes to document \"%s\" before closing?</span>\n\n"
1210 "If you close without saving, your changes will be discarded."),
1211 SP_DOCUMENT_NAME(doc));
1213 Gtk::MessageDialog dlg (*this,
1214 markup,
1215 true,
1216 Gtk::MESSAGE_WARNING,
1217 Gtk::BUTTONS_NONE,
1218 true);
1219 g_free(markup);
1220 Gtk::Button close_button (_("Close _without saving"), true);
1221 dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1222 close_button.show();
1223 dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1224 dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1225 dlg.set_default_response (Gtk::RESPONSE_YES);
1227 int response = dlg.run();
1228 switch (response)
1229 {
1230 case Gtk::RESPONSE_YES:
1231 sp_document_ref(doc);
1232 if (sp_file_save_document(*this, doc)) {
1233 sp_document_unref(doc);
1234 } else { // save dialog cancelled or save failed
1235 sp_document_unref(doc);
1236 return TRUE;
1237 }
1238 break;
1239 case Gtk::RESPONSE_NO:
1240 break;
1241 default: // cancel pressed, or dialog was closed
1242 return TRUE;
1243 break;
1244 }
1245 }
1247 /* Code to check data loss */
1248 bool allow_data_loss = FALSE;
1249 while (sp_document_repr_root(doc)->attribute("inkscape:dataloss") != NULL && allow_data_loss == FALSE)
1250 {
1251 gchar *markup;
1252 /// \todo FIXME !!! obviously this will have problems if the document
1253 /// name contains markup characters
1254 markup = g_strdup_printf(
1255 _("<span weight=\"bold\" size=\"larger\">The file \"%s\" was saved with a format (%s) that may cause data loss!</span>\n\n"
1256 "Do you want to save this file as an Inkscape SVG?"),
1257 SP_DOCUMENT_NAME(doc),
1258 Inkscape::Extension::db.get(sp_document_repr_root(doc)->attribute("inkscape:output_extension"))->get_name());
1260 Gtk::MessageDialog dlg (*this,
1261 markup,
1262 true,
1263 Gtk::MESSAGE_WARNING,
1264 Gtk::BUTTONS_NONE,
1265 true);
1266 g_free(markup);
1267 Gtk::Button close_button (_("Close _without saving"), true);
1268 dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1269 close_button.show();
1270 Gtk::Button save_button (_("_Save as SVG"), true);
1271 dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1272 dlg.add_action_widget (save_button, Gtk::RESPONSE_YES);
1273 save_button.show();
1274 dlg.set_default_response (Gtk::RESPONSE_YES);
1276 int response = dlg.run();
1278 switch (response)
1279 {
1280 case Gtk::RESPONSE_YES:
1281 sp_document_ref(doc);
1282 if (sp_file_save_document(*this, doc)) {
1283 sp_document_unref(doc);
1284 } else { // save dialog cancelled or save failed
1285 sp_document_unref(doc);
1286 return TRUE;
1287 }
1288 break;
1289 case Gtk::RESPONSE_NO:
1290 allow_data_loss = TRUE;
1291 break;
1292 default: // cancel pressed, or dialog was closed
1293 return TRUE;
1294 break;
1295 }
1296 }
1298 return false;
1299 }
1302 void
1303 EditWidget::destroy()
1304 {
1305 delete this;
1306 }
1308 void
1309 EditWidget::requestCanvasUpdate()
1310 {
1311 _svg_canvas.widget().queue_draw();
1312 }
1314 void
1315 EditWidget::requestCanvasUpdateAndWait()
1316 {
1317 requestCanvasUpdate();
1319 while (gtk_events_pending())
1320 gtk_main_iteration_do(FALSE);
1321 }
1323 void
1324 EditWidget::enableInteraction()
1325 {
1326 g_return_if_fail(_interaction_disabled_counter > 0);
1328 _interaction_disabled_counter--;
1330 if (_interaction_disabled_counter == 0) {
1331 this->set_sensitive(true);
1332 }
1333 }
1335 void
1336 EditWidget::disableInteraction()
1337 {
1338 if (_interaction_disabled_counter == 0) {
1339 this->set_sensitive(false);
1340 }
1342 _interaction_disabled_counter++;
1343 }
1345 void
1346 EditWidget::activateDesktop()
1347 {
1348 /// \todo active_desktop_indicator not implemented
1349 }
1351 void
1352 EditWidget::deactivateDesktop()
1353 {
1354 /// \todo active_desktop_indicator not implemented
1355 }
1357 void
1358 EditWidget::viewSetPosition (Geom::Point p)
1359 {
1360 // p -= _namedview->gridorigin;
1361 /// \todo Why was the origin corrected for the grid origin? (johan)
1363 double lo, up, pos, max;
1364 _top_ruler.get_range (lo, up, pos, max);
1365 _top_ruler.set_range (lo, up, p[Geom::X], max);
1366 _left_ruler.get_range (lo, up, pos, max);
1367 _left_ruler.set_range (lo, up, p[Geom::Y], max);
1368 }
1370 void
1371 EditWidget::updateRulers()
1372 {
1373 //Geom::Point gridorigin = _namedview->gridorigin;
1374 /// \todo Why was the origin corrected for the grid origin? (johan)
1376 Geom::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1377 double lo, up, pos, max;
1378 double const scale = _desktop->current_zoom();
1379 double s = viewbox.min()[Geom::X] / scale; //- gridorigin[Geom::X];
1380 double e = viewbox.max()[Geom::X] / scale; //- gridorigin[Geom::X];
1381 _top_ruler.get_range(lo, up, pos, max);
1382 _top_ruler.set_range(s, e, pos, e);
1383 s = viewbox.min()[Geom::Y] / -scale; //- gridorigin[Geom::Y];
1384 e = viewbox.max()[Geom::Y] / -scale; //- gridorigin[Geom::Y];
1385 _left_ruler.set_range(s, e, 0 /*gridorigin[Geom::Y]*/, e);
1386 /// \todo is that correct?
1387 }
1389 void
1390 EditWidget::updateScrollbars (double scale)
1391 {
1392 // do not call this function before canvas has its size allocated
1393 if (!is_realized() || _update_s_f) {
1394 return;
1395 }
1397 _update_s_f = true;
1399 /* The desktop region we always show unconditionally */
1400 SPDocument *doc = _desktop->doc();
1401 Geom::Rect darea ( Geom::Point(-sp_document_width(doc), -sp_document_height(doc)),
1402 Geom::Point(2 * sp_document_width(doc), 2 * sp_document_height(doc)) );
1403 SPObject* root = doc->root;
1404 SPItem* item = SP_ITEM(root);
1405 Geom::OptRect deskarea = Geom::unify(darea, sp_item_bbox_desktop(item));
1407 /* Canvas region we always show unconditionally */
1408 Geom::Rect carea( Geom::Point(deskarea->min()[Geom::X] * scale - 64, deskarea->max()[Geom::Y] * -scale - 64),
1409 Geom::Point(deskarea->max()[Geom::X] * scale + 64, deskarea->min()[Geom::Y] * -scale + 64) );
1411 Geom::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1413 /* Viewbox is always included into scrollable region */
1414 carea = Geom::unify(carea, viewbox);
1416 Gtk::Adjustment *adj = _bottom_scrollbar.get_adjustment();
1417 adj->set_value(viewbox.min()[Geom::X]);
1418 adj->set_lower(carea.min()[Geom::X]);
1419 adj->set_upper(carea.max()[Geom::X]);
1420 adj->set_page_increment(viewbox.dimensions()[Geom::X]);
1421 adj->set_step_increment(0.1 * (viewbox.dimensions()[Geom::X]));
1422 adj->set_page_size(viewbox.dimensions()[Geom::X]);
1424 adj = _right_scrollbar.get_adjustment();
1425 adj->set_value(viewbox.min()[Geom::Y]);
1426 adj->set_lower(carea.min()[Geom::Y]);
1427 adj->set_upper(carea.max()[Geom::Y]);
1428 adj->set_page_increment(viewbox.dimensions()[Geom::Y]);
1429 adj->set_step_increment(0.1 * viewbox.dimensions()[Geom::Y]);
1430 adj->set_page_size(viewbox.dimensions()[Geom::Y]);
1432 _update_s_f = false;
1433 }
1435 void
1436 EditWidget::toggleRulers()
1437 {
1438 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1439 if (_top_ruler.is_visible())
1440 {
1441 _top_ruler.hide_all();
1442 _left_ruler.hide_all();
1443 prefs->setBool(_desktop->is_fullscreen() ? "/fullscreen/rulers/state" : "/window/rulers/state", false);
1444 } else {
1445 _top_ruler.show_all();
1446 _left_ruler.show_all();
1447 prefs->setBool(_desktop->is_fullscreen() ? "/fullscreen/rulers/state" : "/window/rulers/state", true);
1448 }
1449 }
1451 void
1452 EditWidget::toggleScrollbars()
1453 {
1454 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1455 if (_bottom_scrollbar.is_visible())
1456 {
1457 _bottom_scrollbar.hide_all();
1458 _right_scrollbar.hide_all();
1459 prefs->setBool(_desktop->is_fullscreen() ? "/fullscreen/scrollbars/state" : "/window/scrollbars/state", false);
1460 } else {
1461 _bottom_scrollbar.show_all();
1462 _right_scrollbar.show_all();
1463 prefs->setBool(_desktop->is_fullscreen() ? "/fullscreen/scrollbars/state" : "/window/scrollbars/state", true);
1464 }
1465 }
1467 void EditWidget::toggleColorProfAdjust()
1468 {
1469 // TODO implement
1470 }
1472 void
1473 EditWidget::updateZoom()
1474 {
1475 _zoom_status.update();
1476 }
1478 void
1479 EditWidget::letZoomGrabFocus()
1480 {
1481 _zoom_status.grab_focus();
1482 }
1484 void
1485 EditWidget::setToolboxFocusTo (const gchar *)
1486 {
1487 /// \todo not implemented
1488 }
1490 void
1491 EditWidget::setToolboxAdjustmentValue (const gchar *, double)
1492 {
1493 /// \todo not implemented
1494 }
1496 void
1497 EditWidget::setToolboxSelectOneValue (const gchar *, gint)
1498 {
1499 /// \todo not implemented
1500 }
1502 bool
1503 EditWidget::isToolboxButtonActive (gchar const*)
1504 {
1505 /// \todo not implemented
1506 return true;
1507 }
1509 void
1510 EditWidget::setCoordinateStatus (Geom::Point p)
1511 {
1512 gchar *cstr = g_strdup_printf ("%6.2f", _dt2r * p[Geom::X]);
1513 _coord_status_x.property_label() = cstr;
1514 g_free (cstr);
1515 cstr = g_strdup_printf ("%6.2f", _dt2r * p[Geom::Y]);
1516 _coord_status_y.property_label() = cstr;
1517 g_free (cstr);
1518 }
1520 void
1521 EditWidget::setMessage (Inkscape::MessageType /*type*/, gchar const* msg)
1522 {
1523 _select_status.set_markup (msg? msg : "");
1524 }
1526 bool
1527 EditWidget::warnDialog (gchar* msg)
1528 {
1529 Gtk::MessageDialog dlg (*this,
1530 msg,
1531 true,
1532 Gtk::MESSAGE_WARNING,
1533 Gtk::BUTTONS_YES_NO,
1534 true);
1535 int r = dlg.run();
1536 return r == Gtk::RESPONSE_YES;
1537 }
1540 Inkscape::UI::Widget::Dock*
1541 EditWidget::getDock ()
1542 {
1543 return &_dock;
1544 }
1546 void EditWidget::_namedview_modified (SPObject *obj, guint flags) {
1547 SPNamedView *nv = static_cast<SPNamedView *>(obj);
1548 if (flags & SP_OBJECT_MODIFIED_FLAG) {
1549 this->_dt2r = 1.0 / nv->doc_units->unittobase;
1550 this->_top_ruler.update_metric();
1551 this->_left_ruler.update_metric();
1552 this->_tooltips.set_tip(this->_top_ruler, this->_top_ruler.get_tip());
1553 this->_tooltips.set_tip(this->_left_ruler, this->_left_ruler.get_tip());
1554 this->updateRulers();
1555 }
1556 }
1558 void
1559 EditWidget::initEdit (SPDocument *doc)
1560 {
1561 _desktop = new SPDesktop();
1562 _desktop->registerEditWidget (this);
1564 _namedview = sp_document_namedview (doc, 0);
1565 _svg_canvas.init (_desktop);
1566 _desktop->init (_namedview, _svg_canvas.spobj());
1567 sp_namedview_window_from_document (_desktop);
1568 sp_namedview_update_layers_from_document (_desktop);
1569 _dt2r = 1.0 / _namedview->doc_units->unittobase;
1571 /// \todo convert to sigc++ when SPObject hierarchy gets converted
1572 /* Listen on namedview modification */
1573 _namedview_modified_connection = _desktop->namedview->connectModified(sigc::mem_fun(*this, &EditWidget::_namedview_modified));
1574 _layer_selector.setDesktop (_desktop);
1575 _selected_style_status.setDesktop (_desktop);
1577 Inkscape::NSApplication::Editor::addDesktop (_desktop);
1579 _zoom_status.init (_desktop);
1580 _top_ruler.init (_desktop, _svg_canvas.widget());
1581 _left_ruler.init (_desktop, _svg_canvas.widget());
1582 updateRulers();
1583 }
1585 void
1586 EditWidget::destroyEdit()
1587 {
1588 if (_desktop) {
1589 _layer_selector.unreference();
1590 Inkscape::NSApplication::Editor::removeDesktop (_desktop); // clears selection too
1591 _namedview_modified_connection.disconnect();
1592 _desktop->destroy();
1593 Inkscape::GC::release (_desktop);
1594 _desktop = 0;
1595 }
1596 }
1598 //----------end of EditWidgetInterface implementation
1600 //----------start of other callbacks
1602 bool
1603 EditWidget::on_key_press_event (GdkEventKey* event)
1604 {
1605 // this is the original code from helper/window.cpp
1607 unsigned int shortcut;
1608 shortcut = get_group0_keyval (event) |
1609 ( event->state & GDK_SHIFT_MASK ?
1610 SP_SHORTCUT_SHIFT_MASK : 0 ) |
1611 ( event->state & GDK_CONTROL_MASK ?
1612 SP_SHORTCUT_CONTROL_MASK : 0 ) |
1613 ( event->state & GDK_MOD1_MASK ?
1614 SP_SHORTCUT_ALT_MASK : 0 );
1615 return sp_shortcut_invoke (shortcut,
1616 Inkscape::NSApplication::Editor::getActiveDesktop());
1617 }
1619 bool
1620 EditWidget::on_delete_event (GdkEventAny*)
1621 {
1622 return shutdown();
1623 }
1625 bool
1626 EditWidget::on_focus_in_event (GdkEventFocus*)
1627 {
1628 Inkscape::NSApplication::Editor::activateDesktop (_desktop);
1629 _svg_canvas.widget().grab_focus();
1631 return false;
1632 }
1634 void
1635 EditWidget::onWindowSizeAllocate (Gtk::Allocation &newall)
1636 {
1637 if (!is_realized()) return;
1639 const Gtk::Allocation& all = get_allocation();
1640 if ((newall.get_x() == all.get_x()) &&
1641 (newall.get_y() == all.get_y()) &&
1642 (newall.get_width() == all.get_width()) &&
1643 (newall.get_height() == all.get_height())) {
1644 return;
1645 }
1647 Geom::Rect const area = _desktop->get_display_area();
1648 double zoom = _desktop->current_zoom();
1650 if (_sticky_zoom.get_active()) {
1651 /* Calculate zoom per pixel */
1652 double const zpsp = zoom / hypot(area.dimensions()[Geom::X], area.dimensions()[Geom::Y]);
1653 /* Find new visible area */
1654 Geom::Rect const newarea = _desktop->get_display_area();
1655 /* Calculate adjusted zoom */
1656 zoom = zpsp * hypot(newarea.dimensions()[Geom::X], newarea.dimensions()[Geom::Y]);
1657 }
1659 _desktop->zoom_absolute(area.midpoint()[Geom::X], area.midpoint()[Geom::Y], zoom);
1660 }
1662 void
1663 EditWidget::onWindowRealize()
1664 {
1666 if ( (sp_document_width(_desktop->doc()) < 1.0) || (sp_document_height(_desktop->doc()) < 1.0) ) {
1667 return;
1668 }
1670 Geom::Rect d( Geom::Point(0, 0),
1671 Geom::Point(sp_document_width(_desktop->doc()), sp_document_height(_desktop->doc())) );
1673 _desktop->set_display_area(d.min()[Geom::X], d.min()[Geom::Y], d.max()[Geom::X], d.max()[Geom::Y], 10);
1674 _namedview_modified(_desktop->namedview, SP_OBJECT_MODIFIED_FLAG);
1675 setTitle (SP_DOCUMENT_NAME(_desktop->doc()));
1676 }
1678 void
1679 EditWidget::onAdjValueChanged()
1680 {
1681 if (_update_a_f) return;
1682 _update_a_f = true;
1684 sp_canvas_scroll_to (_svg_canvas.spobj(),
1685 _bottom_scrollbar.get_value(),
1686 _right_scrollbar.get_value(),
1687 false);
1688 updateRulers();
1690 _update_a_f = false;
1691 }
1694 } // namespace View
1695 } // namespace UI
1696 } // namespace Inkscape
1698 /*
1699 Local Variables:
1700 mode:c++
1701 c-file-style:"stroustrup"
1702 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1703 indent-tabs-mode:nil
1704 fill-column:99
1705 End:
1706 */
1707 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :