Code

626c3094107116fecb279779930106091382e9a1
[inkscape.git] / src / ui / view / edit-widget.cpp
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  *
20  * Copyright (C) 1999-2005 Authors
21  * Copyright (C) 2000-2001 Ximian, Inc.
22  *
23  * Released under GNU GPL.  Read the file 'COPYING' for more information.
24  */
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
30 #include <gtk/gtkwindow.h>
31 #include <gtk/gtkversion.h>
32 #include <gtk/gtklabel.h>
33 #include <gtkmm/radioaction.h>
34 #include <gtkmm/menubar.h>
35 #include <gtkmm/messagedialog.h>
36 #include <gtkmm/stock.h>
37 #include <gtkmm/accelmap.h>
38 #include <gtkmm/separator.h>
39 #include <gtkmm/base.h>
41 #include <sigc++/functors/mem_fun.h>
43 #include "macros.h"
44 #include "path-prefix.h"
45 #include "prefs-utils.h"
46 #include "file.h"
47 #include "application/editor.h"
48 #include "edit-widget.h"
49 #include "ui/stock.h"
50 #include "ui/stock-items.h"
51 #include "ui/icons.h"
53 #include "display/sodipodi-ctrlrect.h"
54 #include "helper/units.h"
55 #include "shortcuts.h"
56 #include "widgets/spw-utilities.h"
57 #include "event-context.h"
58 #include "document.h"
59 #include "sp-namedview.h"
60 #include "sp-item.h"
61 #include "interface.h"
62 #include "extension/db.h"
64 using namespace Inkscape::UI;
65 using namespace Inkscape::UI::Widget;
67 namespace Inkscape {
68 namespace UI {
69 namespace View {
71 EditWidget::EditWidget (SPDocument *doc)
72     : _main_window_table(4),
73       _viewport_table(3,3),
74       _act_grp(Gtk::ActionGroup::create()),
75       _ui_mgr(Gtk::UIManager::create()),
76       _update_s_f(false),
77       _update_a_f(false)
78 {
79     g_warning("Creating new EditWidget");
81     _desktop = 0;
82     Icons::init();
83     Stock::init();
84     initActions();
85     initAccelMap();
86     initUIManager();
87     initLayout();
88     initEdit (doc);
89     g_warning("Done creating new EditWidget");
90 }
92 EditWidget::~EditWidget()
93 {
94     destroyEdit();
95 }
97 void
98 EditWidget::initActions()
99 {
100     initMenuActions();
101     initToolbarActions();
104 void
105 EditWidget::initUIManager()
107     _ui_mgr->insert_action_group(_act_grp);
108     add_accel_group(_ui_mgr->get_accel_group());
110     gchar *filename_utf8 = g_build_filename(INKSCAPE_UIDIR, "menus-bars.xml", NULL);
111     if (_ui_mgr->add_ui_from_file(filename_utf8) == 0) {
112         g_warning("Error merging ui from file '%s'", filename_utf8);
113         // fixme-charset: What charset should we pass to g_warning?
114     }
115     g_free(filename_utf8);
118 void
119 EditWidget::initLayout()
121     set_title("New document 1 - Inkscape");
122     set_resizable();
123     set_default_size(640, 480);
125     // top level window into which all other portions of the UI get inserted
126     add(_main_window_table);
127     // attach box for horizontal toolbars
128     _main_window_table.attach(_toolbars_vbox, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
129     // attach sub-window for viewport and vertical toolbars
130     _main_window_table.attach(_sub_window_hbox, 0, 1, 2, 3);
131     // viewport table with 3 rows by 3 columns
132     _sub_window_hbox.pack_end(_viewport_table);
134     // Menus and Bars
135     initMenuBar();
136     initCommandsBar();
137     initToolControlsBar();
138     initUriBar();
139     initToolsBar();
141     // Canvas Viewport
142     initLeftRuler();
143     initTopRuler();
144     initStickyZoom();
145     initBottomScrollbar();
146     initRightScrollbar();
147     _viewport_table.attach(_svg_canvas.widget(), 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
148     _svg_canvas.widget().show_all();
151     // The statusbar comes last and appears at the bottom of _main_window_table
152     initStatusbar();
154     signal_size_allocate().connect (sigc::mem_fun (*this, &EditWidget::onWindowSizeAllocate), false);
155     signal_realize().connect (sigc::mem_fun (*this, &EditWidget::onWindowRealize));
156     show_all_children();
159 void
160 EditWidget::onMenuItem()
162     g_warning("onMenuItem called");
165 void
166 EditWidget::onActionFileNew()
168 //    g_warning("onActionFileNew called");
169     sp_file_new_default();
172 void
173 EditWidget::onActionFileOpen()
175 //    g_warning("onActionFileOpen called");
176     sp_file_open_dialog (NULL, NULL);
179 void
180 EditWidget::onActionFileQuit()
182     g_warning("onActionFileQuit");
183     sp_ui_close_all();
186 void
187 EditWidget::onActionFilePrint()
189     g_warning("onActionFilePrint");
192 void
193 EditWidget::onToolbarItem()
195     g_warning("onToolbarItem called");
198 void
199 EditWidget::onSelectTool()
201     _tool_ctrl->remove();
202     _tool_ctrl->add(*_select_ctrl);
205 void
206 EditWidget::onNodeTool()
208     _tool_ctrl->remove();
209     _tool_ctrl->add(*_node_ctrl);
212 void
213 EditWidget::onDialogInkscapePreferences()
215     _dlg_mgr.showDialog("InkscapePreferences");
218 void
219 EditWidget::onDialogAbout()
223 void
224 EditWidget::onDialogAlignAndDistribute()
226     _dlg_mgr.showDialog("AlignAndDistribute");
229 void
230 EditWidget::onDialogDocumentProperties()
232 //    manage (Inkscape::UI::Dialog::DocumentPreferences::create());
233     _dlg_mgr.showDialog("DocumentPreferences");
236 void
237 EditWidget::onDialogExport()
239     _dlg_mgr.showDialog("Export");
242 void
243 EditWidget::onDialogExtensionEditor()
245     _dlg_mgr.showDialog("ExtensionEditor");
248 void
249 EditWidget::onDialogFillAndStroke()
251     _dlg_mgr.showDialog("FillAndStroke");
254 void
255 EditWidget::onDialogFind()
257     _dlg_mgr.showDialog("Find");
260 void
261 EditWidget::onDialogLayerEditor()
263     _dlg_mgr.showDialog("LayerEditor");
266 void
267 EditWidget::onDialogMessages()
269     _dlg_mgr.showDialog("Messages");
272 void
273 EditWidget::onDialogObjectProperties()
275     _dlg_mgr.showDialog("ObjectProperties");
278 void
279 EditWidget::onDialogTextProperties()
281     _dlg_mgr.showDialog("TextProperties");
284 void
285 EditWidget::onDialogTrace()
289 void
290 EditWidget::onDialogTransformation()
292     _dlg_mgr.showDialog("Transformation");
295 void
296 EditWidget::onDialogXmlEditor()
298     _dlg_mgr.showDialog("XmlEditor");
301 void
302 EditWidget::onUriChanged()
304     g_message("onUriChanged called");
308 // FIXME: strings are replaced by placeholders, NOT to be translated until the code is enabled
309 // See http://sourceforge.net/mailarchive/message.php?msg_id=11746016 for details
311 void
312 EditWidget::initMenuActions()
314 //    _act_grp->add(Gtk::Action::create("MenuFile",   _("PLACEHOLDER, do not translate")));
315 //    _act_grp->add(Gtk::Action::create("MenuEdit",   _("PLACEHOLDER, do not translate")));
316 //    _act_grp->add(Gtk::Action::create("MenuView",   _("PLACEHOLDER, do not translate")));
317 //    _act_grp->add(Gtk::Action::create("MenuLayer",  _("PLACEHOLDER, do not translate")));
318 //    _act_grp->add(Gtk::Action::create("MenuObject", _("PLACEHOLDER, do not translate")));
319 //    _act_grp->add(Gtk::Action::create("MenuPath",   _("PLACEHOLDER, do not translate")));
320 //    _act_grp->add(Gtk::Action::create("MenuText",   _("PLACEHOLDER, do not translate")));
321 //    _act_grp->add(Gtk::Action::create("MenuHelp",   _("PLACEHOLDER, do not translate")));
322 // temporarily replaced with non-gettext version to have a well-sized menu
323 // for testing:
325     _act_grp->add(Gtk::Action::create("MenuFile",   "File"));
326     _act_grp->add(Gtk::Action::create("MenuEdit",   "Edit"));
327     _act_grp->add(Gtk::Action::create("MenuView",   "View"));
328     _act_grp->add(Gtk::Action::create("MenuLayer",  "Layer"));
329     _act_grp->add(Gtk::Action::create("MenuObject", "Object"));
330     _act_grp->add(Gtk::Action::create("MenuPath",   "Path"));
331     _act_grp->add(Gtk::Action::create("MenuText",   "Text"));
332     _act_grp->add(Gtk::Action::create("MenuHelp",   "Help"));
334     // File menu
335     _act_grp->add(Gtk::Action::create("New",
336                                       Gtk::Stock::NEW, Glib::ustring(),
337                                       _("PLACEHOLDER, do not translate")),
338                   sigc::mem_fun(*this, &EditWidget::onActionFileNew));
340     _act_grp->add(Gtk::Action::create("Open",
341                                       Gtk::Stock::OPEN, Glib::ustring(),
342                                       _("PLACEHOLDER, do not translate")),
343                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
345     _act_grp->add(Gtk::Action::create("OpenRecent",
346                                       Stock::OPEN_RECENT));
348     _act_grp->add(Gtk::Action::create("Revert",
349                                       Gtk::Stock::REVERT_TO_SAVED, Glib::ustring(),
350                                       _("PLACEHOLDER, do not translate")),
351                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
353     _act_grp->add(Gtk::Action::create("Save",
354                                       Gtk::Stock::SAVE, Glib::ustring(),
355                                       _("PLACEHOLDER, do not translate")),
356                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
358     _act_grp->add(Gtk::Action::create("SaveAs",
359                                       Gtk::Stock::SAVE_AS, Glib::ustring(),
360                                       _("PLACEHOLDER, do not translate")),
361                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
363     _act_grp->add(Gtk::Action::create("Import",
364                                       Stock::IMPORT, Glib::ustring(),
365                                       _("PLACEHOLDER, do not translate")),
366                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
368     _act_grp->add(Gtk::Action::create("Export",
369                                       Stock::EXPORT, Glib::ustring(),
370                                       _("PLACEHOLDER, do not translate")),
371                   sigc::mem_fun(*this, &EditWidget::onDialogExport));
373     _act_grp->add(Gtk::Action::create("Print",
374                                       Gtk::Stock::PRINT, Glib::ustring(),
375                                       _("PLACEHOLDER, do not translate")),
376                   sigc::mem_fun(*this, &EditWidget::onActionFilePrint));
378     _act_grp->add(Gtk::Action::create("PrintPreview",
379                                       Gtk::Stock::PRINT_PREVIEW),
380                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
382     _act_grp->add(Gtk::Action::create("VacuumDefs",
383                                       Stock::VACUUM_DEFS),
384                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
386     _act_grp->add(Gtk::Action::create("DocumentProperties",
387                                       Gtk::Stock::PROPERTIES, Glib::ustring(),
388                                       _("PLACEHOLDER, do not translate")),
389                   sigc::mem_fun(*this, &EditWidget::onDialogDocumentProperties));
391     _act_grp->add(Gtk::Action::create("InkscapePreferences",
392                                       Gtk::Stock::PREFERENCES, Glib::ustring(),
393                                       _("PLACEHOLDER, do not translate")),
394                   sigc::mem_fun(*this, &EditWidget::onDialogInkscapePreferences));
396     _act_grp->add(Gtk::Action::create("Close",
397                                       Gtk::Stock::CLOSE),
398                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
400     _act_grp->add(Gtk::Action::create("Quit",
401                                       Gtk::Stock::QUIT),
402                   sigc::mem_fun(*this, &EditWidget::onActionFileQuit));
404     // EditWidget menu
405     _act_grp->add(Gtk::Action::create("Undo",
406                                       Gtk::Stock::UNDO, Glib::ustring(),
407                                       _("PLACEHOLDER, do not translate")));
409     _act_grp->add(Gtk::Action::create("Redo",
410                                       Gtk::Stock::REDO, Glib::ustring(),
411                                       _("PLACEHOLDER, do not translate")));
413     _act_grp->add(Gtk::Action::create("UndoHistory",
414                                       Stock::UNDO_HISTORY, Glib::ustring(),
415                                       _("PLACEHOLDER, do not translate")));
417     _act_grp->add(Gtk::Action::create("Cut",
418                                       Gtk::Stock::CUT, Glib::ustring(),
419                                       _("PLACEHOLDER, do not translate")));
421     _act_grp->add(Gtk::Action::create("Copy",
422                                       Gtk::Stock::COPY, Glib::ustring(),
423                                       _("PLACEHOLDER, do not translate")));
425     _act_grp->add(Gtk::Action::create("Paste",
426                                       Gtk::Stock::PASTE, Glib::ustring(),
427                                       _("PLACEHOLDER, do not translate")));
429     _act_grp->add(Gtk::Action::create("PasteInPlace",
430                                       Stock::PASTE_IN_PLACE));
432     _act_grp->add(Gtk::Action::create("PasteStyle",
433                                       Stock::PASTE_STYLE));
435     _act_grp->add(Gtk::Action::create("Find",
436                                       Gtk::Stock::FIND),
437                   sigc::mem_fun(*this, &EditWidget::onDialogFind));
439     _act_grp->add(Gtk::Action::create("Duplicate",
440                                       Stock::DUPLICATE, Glib::ustring(),
441                                       _("PLACEHOLDER, do not translate")));
443     _act_grp->add(Gtk::Action::create("Clone",
444                                       Stock::CLONE, Glib::ustring(),
445                                       _("PLACEHOLDER, do not translate")));
447     _act_grp->add(Gtk::Action::create("CloneUnlink",
448                                       Stock::CLONE_UNLINK, Glib::ustring(),
449                                       _("PLACEHOLDER, do not translate")));
451     _act_grp->add(Gtk::Action::create("CloneSelectOrig",
452                                       Stock::CLONE_SELECT_ORIG));
454     _act_grp->add(Gtk::Action::create("MakeBitmap",
455                                       Stock::MAKE_BITMAP));
457     _act_grp->add(Gtk::Action::create("Tile",
458                                      Stock::TILE));
460     _act_grp->add(Gtk::Action::create("Untile",
461                                       Stock::UNTILE));
463     _act_grp->add(Gtk::Action::create("Delete",
464                                       Gtk::Stock::DELETE));
466     _act_grp->add(Gtk::Action::create("SelectAll",
467                                       Stock::SELECT_ALL));
469     _act_grp->add(Gtk::Action::create("SelectAllInAllLayers",
470                                       Stock::SELECT_ALL_IN_ALL_LAYERS));
472     _act_grp->add(Gtk::Action::create("SelectInvert",
473                                       Stock::SELECT_INVERT));
475     _act_grp->add(Gtk::Action::create("SelectNone",
476                                       Stock::SELECT_NONE));
478     _act_grp->add(Gtk::Action::create("XmlEditor",
479                                       Stock::XML_EDITOR, Glib::ustring(),
480                                       _("PLACEHOLDER, do not translate")),
481                   sigc::mem_fun(*this, &EditWidget::onDialogXmlEditor));
483     // View menu
484     _act_grp->add(Gtk::Action::create("Zoom",
485                                       Stock::ZOOM));
487     _act_grp->add(Gtk::Action::create("ZoomIn",
488                                       Stock::ZOOM_IN, Glib::ustring(),
489                                       _("PLACEHOLDER, do not translate")));
491     _act_grp->add(Gtk::Action::create("ZoomOut",
492                                       Stock::ZOOM_OUT, Glib::ustring(),
493                                       _("PLACEHOLDER, do not translate")));
495     _act_grp->add(Gtk::Action::create("Zoom100",
496                                       Stock::ZOOM_100, Glib::ustring(),
497                                       _("PLACEHOLDER, do not translate")));
499     _act_grp->add(Gtk::Action::create("Zoom50",
500                                       Stock::ZOOM_50, Glib::ustring(),
501                                       _("PLACEHOLDER, do not translate")));
503     _act_grp->add(Gtk::Action::create("Zoom200",
504                                       Stock::ZOOM_200, Glib::ustring(),
505                                       _("PLACEHOLDER, do not translate")));
507     _act_grp->add(Gtk::Action::create("ZoomSelection",
508                                       Stock::ZOOM_SELECTION, Glib::ustring(),
509                                       _("PLACEHOLDER, do not translate")));
511     _act_grp->add(Gtk::Action::create("ZoomDrawing",
512                                       Stock::ZOOM_DRAWING, Glib::ustring(),
513                                       _("PLACEHOLDER, do not translate")));
515     _act_grp->add(Gtk::Action::create("ZoomPage",
516                                       Stock::ZOOM_PAGE, Glib::ustring(),
517                                       _("PLACEHOLDER, do not translate")));
519     _act_grp->add(Gtk::Action::create("ZoomWidth",
520                                       Stock::ZOOM_WIDTH, Glib::ustring(),
521                                       _("PLACEHOLDER, do not translate")));
523     _act_grp->add(Gtk::Action::create("ZoomPrev",
524                                       Stock::ZOOM_PREV, Glib::ustring(),
525                                       _("PLACEHOLDER, do not translate")));
527     _act_grp->add(Gtk::Action::create("ZoomNext",
528                                       Stock::ZOOM_NEXT, Glib::ustring(),
529                                       _("PLACEHOLDER, do not translate")));
531     _act_grp->add(Gtk::Action::create("ShowHide",
532                                       Stock::SHOW_HIDE));
534     _act_grp->add(Gtk::ToggleAction::create("ShowHideCommandsBar",
535                                             Stock::SHOW_HIDE_COMMANDS_BAR));
537     _act_grp->add(Gtk::ToggleAction::create("ShowHideToolControlsBar",
538                                             Stock::SHOW_HIDE_TOOL_CONTROLS_BAR));
540     _act_grp->add(Gtk::ToggleAction::create("ShowHideToolsBar",
541                                             Stock::SHOW_HIDE_TOOLS_BAR));
543     _act_grp->add(Gtk::ToggleAction::create("ShowHideRulers",
544                                             Stock::SHOW_HIDE_RULERS));
546     _act_grp->add(Gtk::ToggleAction::create("ShowHideScrollbars",
547                                             Stock::SHOW_HIDE_SCROLLBARS));
549     _act_grp->add(Gtk::ToggleAction::create("ShowHideStatusbar",
550                                             Stock::SHOW_HIDE_STATUSBAR));
552     _act_grp->add(Gtk::Action::create("ShowHideDialogs",
553                                       Stock::SHOW_HIDE_DIALOGS));
555     _act_grp->add(Gtk::Action::create("Grid",
556                                       Stock::GRID));
558     _act_grp->add(Gtk::Action::create("Guides",
559                                       Stock::GUIDES));
561     _act_grp->add(Gtk::Action::create("Fullscreen",
562                                       Stock::FULLSCREEN));
564     _act_grp->add(Gtk::Action::create("Messages",
565                                       Stock::MESSAGES),
566                   sigc::mem_fun(*this, &EditWidget::onDialogMessages));
568     _act_grp->add(Gtk::Action::create("Scripts",
569                                       Stock::SCRIPTS));
571     _act_grp->add(Gtk::Action::create("WindowPrev",
572                                       Stock::WINDOW_PREV));
574     _act_grp->add(Gtk::Action::create("WindowNext",
575                                       Stock::WINDOW_NEXT));
577     _act_grp->add(Gtk::Action::create("WindowDuplicate",
578                                       Stock::WINDOW_DUPLICATE));
580     // Layer menu
581     _act_grp->add(Gtk::Action::create("LayerNew",
582                                       Stock::LAYER_NEW));
584     _act_grp->add(Gtk::Action::create("LayerRename",
585                                       Stock::LAYER_RENAME));
587     _act_grp->add(Gtk::Action::create("LayerDuplicate",
588                                       Stock::LAYER_DUPLICATE));
590     _act_grp->add(Gtk::Action::create("LayerAnchor",
591                                       Stock::LAYER_ANCHOR));
593     _act_grp->add(Gtk::Action::create("LayerMergeDown",
594                                       Stock::LAYER_MERGE_DOWN));
596     _act_grp->add(Gtk::Action::create("LayerDelete",
597                                       Stock::LAYER_DELETE));
599     _act_grp->add(Gtk::Action::create("LayerSelectNext",
600                                       Stock::LAYER_SELECT_NEXT));
602     _act_grp->add(Gtk::Action::create("LayerSelectPrev",
603                                       Stock::LAYER_SELECT_PREV));
605     _act_grp->add(Gtk::Action::create("LayerSelectTop",
606                                       Stock::LAYER_SELECT_TOP));
608     _act_grp->add(Gtk::Action::create("LayerSelectBottom",
609                                       Stock::LAYER_SELECT_BOTTOM));
611     _act_grp->add(Gtk::Action::create("LayerRaise",
612                                       Stock::LAYER_RAISE));
614     _act_grp->add(Gtk::Action::create("LayerLower",
615                                       Stock::LAYER_LOWER));
617     _act_grp->add(Gtk::Action::create("LayerToTop",
618                                       Stock::LAYER_TO_TOP));
620     _act_grp->add(Gtk::Action::create("LayerToBottom",
621                                       Stock::LAYER_TO_BOTTOM));
623     // Object menu
624     _act_grp->add(Gtk::Action::create("FillAndStroke",
625                                       Stock::FILL_STROKE, Glib::ustring(),
626                                       _("PLACEHOLDER, do not translate")),
627                   sigc::mem_fun(*this, &EditWidget::onDialogFillAndStroke));
629     _act_grp->add(Gtk::Action::create("ObjectProperties",
630                                       Stock::OBJECT_PROPERTIES),
631                   sigc::mem_fun(*this, &EditWidget::onDialogObjectProperties));
633     _act_grp->add(Gtk::Action::create("Group",
634                                       Stock::GROUP, Glib::ustring(),
635                                       _("PLACEHOLDER, do not translate")));
637     _act_grp->add(Gtk::Action::create("Ungroup",
638                                       Stock::UNGROUP, Glib::ustring(),
639                                       _("PLACEHOLDER, do not translate")));
641     _act_grp->add(Gtk::Action::create("Raise",
642                                       Stock::RAISE, Glib::ustring(),
643                                       _("PLACEHOLDER, do not translate")));
645     _act_grp->add(Gtk::Action::create("Lower",
646                                       Stock::LOWER, Glib::ustring(),
647                                       _("PLACEHOLDER, do not translate")));
649     _act_grp->add(Gtk::Action::create("RaiseToTop",
650                                       Stock::RAISE_TO_TOP, Glib::ustring(),
651                                       _("PLACEHOLDER, do not translate")));
653     _act_grp->add(Gtk::Action::create("LowerToBottom",
654                                       Stock::LOWER_TO_BOTTOM, Glib::ustring(),
655                                       _("PLACEHOLDER, do not translate")));
657     _act_grp->add(Gtk::Action::create("MoveToNewLayer",
658                                       Stock::MOVE_TO_NEW_LAYER, Glib::ustring(),
659                                       _("PLACEHOLDER, do not translate")));
661     _act_grp->add(Gtk::Action::create("MoveToNextLayer",
662                                       Stock::MOVE_TO_NEXT_LAYER, Glib::ustring(),
663                                       _("PLACEHOLDER, do not translate")));
665     _act_grp->add(Gtk::Action::create("MoveToPrevLayer",
666                                       Stock::MOVE_TO_PREV_LAYER, Glib::ustring(),
667                                       _("PLACEHOLDER, do not translate")));
669     _act_grp->add(Gtk::Action::create("MoveToTopLayer",
670                                       Stock::MOVE_TO_TOP_LAYER, Glib::ustring(),
671                                       _("PLACEHOLDER, do not translate")));
673     _act_grp->add(Gtk::Action::create("MoveToBottomLayer",
674                                       Stock::MOVE_TO_BOTTOM_LAYER, Glib::ustring(),
675                                       _("PLACEHOLDER, do not translate")));
677     _act_grp->add(Gtk::Action::create("Rotate90CW",
678                                       Stock::ROTATE_90_CW, Glib::ustring(),
679                                       _("PLACEHOLDER, do not translate")));
681     _act_grp->add(Gtk::Action::create("Rotate90CCW",
682                                       Stock::ROTATE_90_CCW, Glib::ustring(),
683                                       _("PLACEHOLDER, do not translate")));
685     _act_grp->add(Gtk::Action::create("FlipHoriz",
686                                       Stock::FLIP_HORIZ, Glib::ustring(),
687                                       _("PLACEHOLDER, do not translate")));
689     _act_grp->add(Gtk::Action::create("FlipVert",
690                                       Stock::FLIP_VERT, Glib::ustring(),
691                                       _("PLACEHOLDER, do not translate")));
693     _act_grp->add(Gtk::Action::create("Transformation",
694                                       Stock::TRANSFORMATION, Glib::ustring(),
695                                       _("PLACEHOLDER, do not translate")),
696                   sigc::mem_fun(*this, &EditWidget::onDialogTransformation));
698     _act_grp->add(Gtk::Action::create("AlignAndDistribute",
699                                       Stock::ALIGN_DISTRIBUTE, Glib::ustring(),
700                                       _("PLACEHOLDER, do not translate")),
701                   sigc::mem_fun(*this, &EditWidget::onDialogAlignAndDistribute));
703     // Path menu
704     _act_grp->add(Gtk::Action::create("ObjectToPath",
705                                       Stock::OBJECT_TO_PATH, Glib::ustring(),
706                                       _("PLACEHOLDER, do not translate")));
708     _act_grp->add(Gtk::Action::create("StrokeToPath",
709                                       Stock::STROKE_TO_PATH, Glib::ustring(),
710                                       _("PLACEHOLDER, do not translate")));
712     _act_grp->add(Gtk::Action::create("Trace",
713                                       Stock::TRACE),
714                   sigc::mem_fun(*this, &EditWidget::onDialogTrace));
716     _act_grp->add(Gtk::Action::create("Union",
717                                       Stock::UNION));
719     _act_grp->add(Gtk::Action::create("Difference",
720                                       Stock::DIFFERENCE));
722     _act_grp->add(Gtk::Action::create("Intersection",
723                                       Stock::INTERSECTION));
725     _act_grp->add(Gtk::Action::create("Exclusion",
726                                       Stock::EXCLUSION));
728     _act_grp->add(Gtk::Action::create("Division",
729                                       Stock::DIVISION));
731     _act_grp->add(Gtk::Action::create("CutPath",
732                                       Stock::CUT_PATH));
734     _act_grp->add(Gtk::Action::create("Combine",
735                                       Stock::COMBINE));
737     _act_grp->add(Gtk::Action::create("BreakApart",
738                                       Stock::BREAK_APART));
740     _act_grp->add(Gtk::Action::create("Inset",
741                                       Stock::INSET));
743     _act_grp->add(Gtk::Action::create("Outset",
744                                       Stock::OUTSET));
746     _act_grp->add(Gtk::Action::create("OffsetDynamic",
747                                       Stock::OFFSET_DYNAMIC));
749     _act_grp->add(Gtk::Action::create("OffsetLinked",
750                                       Stock::OFFSET_LINKED));
752     _act_grp->add(Gtk::Action::create("Simplify",
753                                       Stock::SIMPLIFY));
755     _act_grp->add(Gtk::Action::create("Reverse",
756                                       Stock::REVERSE));
758     _act_grp->add(Gtk::Action::create("Cleanup",
759                                       Gtk::Stock::CLEAR,
760                                       _("PLACEHOLDER, do not translate")));
762     // Text menu
763     _act_grp->add(Gtk::Action::create("TextProperties",
764                                       Gtk::Stock::SELECT_FONT, Glib::ustring(),
765                                       _("PLACEHOLDER, do not translate")),
766                   sigc::mem_fun(*this, &EditWidget::onDialogTextProperties));
768     _act_grp->add(Gtk::Action::create("PutOnPath",
769                                       Stock::PUT_ON_PATH));
771     _act_grp->add(Gtk::Action::create("RemoveFromPath",
772                                       Stock::REMOVE_FROM_PATH));
774     _act_grp->add(Gtk::Action::create("RemoveManualKerns",
775                                       Stock::REMOVE_MANUAL_KERNS));
777         // Whiteboard menu
778 #ifdef WITH_INKBOARD
779 #endif
781     // About menu
782     _act_grp->add(Gtk::Action::create("KeysAndMouse",
783                                       Stock::KEYS_MOUSE));
785     _act_grp->add(Gtk::Action::create("Tutorials",
786                                       Stock::TUTORIALS));
788     _act_grp->add(Gtk::Action::create("About",
789                                       Stock::ABOUT),
790                   sigc::mem_fun(*this, &EditWidget::onDialogAbout));
793 void
794 EditWidget::initToolbarActions()
796     // Tools bar
797     Gtk::RadioAction::Group tools;
799     _act_grp->add(Gtk::RadioAction::create(tools, "ToolSelect",
800                                            Stock::TOOL_SELECT, Glib::ustring(),
801                                            _("PLACEHOLDER, do not translate")),
802                   sigc::mem_fun(*this, &EditWidget::onSelectTool));
804     _act_grp->add(Gtk::RadioAction::create(tools, "ToolNode",
805                                            Stock::TOOL_NODE, Glib::ustring(),
806                                            _("PLACEHOLDER, do not translate")),
807                   sigc::mem_fun(*this, &EditWidget::onNodeTool));
809     _act_grp->add(Gtk::RadioAction::create(tools, "ToolZoom",
810                                            Stock::TOOL_ZOOM, Glib::ustring(),
811                                            _("PLACEHOLDER, do not translate")));
813     _act_grp->add(Gtk::RadioAction::create(tools, "ToolRect",
814                                            Stock::TOOL_RECT, Glib::ustring(),
815                                            _("PLACEHOLDER, do not translate")));
817     _act_grp->add(Gtk::RadioAction::create(tools, "ToolArc",
818                                            Stock::TOOL_ARC, Glib::ustring(),
819                                            _("PLACEHOLDER, do not translate")));
821     _act_grp->add(Gtk::RadioAction::create(tools, "ToolStar",
822                                            Stock::TOOL_STAR, Glib::ustring(),
823                                            _("PLACEHOLDER, do not translate")));
825     _act_grp->add(Gtk::RadioAction::create(tools, "ToolSpiral",
826                                            Stock::TOOL_SPIRAL, Glib::ustring(),
827                                            _("PLACEHOLDER, do not translate")));
829     _act_grp->add(Gtk::RadioAction::create(tools, "ToolFreehand",
830                                            Stock::TOOL_FREEHAND, Glib::ustring(),
831                                            _("PLACEHOLDER, do not translate")));
833     _act_grp->add(Gtk::RadioAction::create(tools, "ToolPen",
834                                            Stock::TOOL_PEN, Glib::ustring(),
835                                            _("PLACEHOLDER, do not translate")));
837     _act_grp->add(Gtk::RadioAction::create(tools, "ToolDynaDraw",
838                                            Stock::TOOL_DYNADRAW, Glib::ustring(),
839                                            _("PLACEHOLDER, do not translate")));
841     _act_grp->add(Gtk::RadioAction::create(tools, "ToolText",
842                                            Stock::TOOL_TEXT, Glib::ustring(),
843                                            _("PLACEHOLDER, do not translate")));
845     _act_grp->add(Gtk::RadioAction::create(tools, "ToolDropper",
846                                            Stock::TOOL_DROPPER, Glib::ustring(),
847                                            _("PLACEHOLDER, do not translate")));
849     // Select Controls bar
850     _act_grp->add(Gtk::ToggleAction::create("TransformStroke",
851                                             Stock::TRANSFORM_STROKE, Glib::ustring(),
852                                             _("PLACEHOLDER, do not translate")));
854     _act_grp->add(Gtk::ToggleAction::create("TransformCorners",
855                                             Stock::TRANSFORM_CORNERS, Glib::ustring(),
856                                             _("PLACEHOLDER, do not translate")));
858     _act_grp->add(Gtk::ToggleAction::create("TransformGradient",
859                                             Stock::TRANSFORM_GRADIENT, Glib::ustring(),
860                                             _("PLACEHOLDER, do not translate")));
862     _act_grp->add(Gtk::ToggleAction::create("TransformPattern",
863                                             Stock::TRANSFORM_PATTERN, Glib::ustring(),
864                                             _("PLACEHOLDER, do not translate")));
866     // Node Controls bar
867     _act_grp->add(Gtk::Action::create("NodeInsert",
868                                       Gtk::Stock::ADD, Glib::ustring(),
869                                       _("PLACEHOLDER, do not translate")));
871     _act_grp->add(Gtk::Action::create("NodeDelete",
872                                       Gtk::Stock::REMOVE, Glib::ustring(),
873                                       _("PLACEHOLDER, do not translate")));
875     _act_grp->add(Gtk::Action::create("NodeJoin",
876                                       Stock::NODE_JOIN, Glib::ustring(),
877                                       _("PLACEHOLDER, do not translate")));
879     _act_grp->add(Gtk::Action::create("NodeJoinSegment",
880                                       Stock::NODE_JOIN_SEGMENT, Glib::ustring(),
881                                       _("PLACEHOLDER, do not translate")));
883     _act_grp->add(Gtk::Action::create("NodeDeleteSegment",
884                                       Stock::NODE_DELETE_SEGMENT, Glib::ustring(),
885                                       _("PLACEHOLDER, do not translate")));
887     _act_grp->add(Gtk::Action::create("NodeBreak",
888                                       Stock::NODE_BREAK, Glib::ustring(),
889                                       _("PLACEHOLDER, do not translate")));
891     _act_grp->add(Gtk::Action::create("NodeCorner",
892                                       Stock::NODE_CORNER, Glib::ustring(),
893                                       _("PLACEHOLDER, do not translate")));
895     _act_grp->add(Gtk::Action::create("NodeSmooth",
896                                       Stock::NODE_SMOOTH, Glib::ustring(),
897                                       _("PLACEHOLDER, do not translate")));
899     _act_grp->add(Gtk::Action::create("NodeSymmetric",
900                                       Stock::NODE_SYMMETRIC, Glib::ustring(),
901                                       _("PLACEHOLDER, do not translate")));
903     _act_grp->add(Gtk::Action::create("NodeLine",
904                                       Stock::NODE_LINE, Glib::ustring(),
905                                       _("PLACEHOLDER, do not translate")));
907     _act_grp->add(Gtk::Action::create("NodeCurve",
908                                       Stock::NODE_CURVE, Glib::ustring(),
909                                       _("PLACEHOLDER, do not translate")));
912 void
913 EditWidget::initAccelMap()
915     gchar *filename = g_build_filename(INKSCAPE_UIDIR, "keybindings.rc", NULL);
916     Gtk::AccelMap::load(filename);
917     g_free(filename);
919     // One problem is that the keys 1-6 are zoom accelerators which get
920     // caught as accelerator _before_ any Entry input handler receives them,
921     // for example the zoom status. At the moment, the best way seems to
922     // disable them as accelerators when the Entry gets focus, and enable
923     // them when focus goes elsewhere. The code for this belongs here,
924     // and not in zoom-status.cpp .
926     _zoom_status.signal_focus_in_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusIn));
927     _zoom_status.signal_focus_out_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusOut));
930 bool
931 EditWidget::onEntryFocusIn (GdkEventFocus* ev)
933     Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
934     Gtk::AccelMap::change_entry ("<Actions>//Zoom100", 0, m, false);
935     Gtk::AccelMap::change_entry ("<Actions>//Zoom50", 0, m, false);
936     Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", 0, m, false);
937     Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", 0, m, false);
938     Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", 0, m, false);
939     Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", 0, m, false);
940     return false;
943 bool
944 EditWidget::onEntryFocusOut (GdkEventFocus* ev)
946     Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
947     Gtk::AccelMap::change_entry ("<Actions>//Zoom100", '1', m, false);
948     Gtk::AccelMap::change_entry ("<Actions>//Zoom50", '2', m, false);
949     Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", '3', m, false);
950     Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", '4', m, false);
951     Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", '5', m, false);
952     Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", '6', m, false);
953     return false;
956 void
957 EditWidget::initMenuBar()
959     g_assert(_ui_mgr);
960     Gtk::MenuBar *menu = static_cast<Gtk::MenuBar*>(_ui_mgr->get_widget("/MenuBar"));
961     g_assert(menu != NULL);
962     _main_window_table.attach(*Gtk::manage(menu), 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
965 void
966 EditWidget::initCommandsBar()
968     g_assert(_ui_mgr);
969     Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/CommandsBar")),
970                                Gtk::TOOLBAR_ICONS);
971     g_assert(bar != NULL);
972     _toolbars_vbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
975 void
976 EditWidget::initToolControlsBar()
978     // TODO: Do UIManager controlled widgets need to be deleted?
979     _select_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/SelectControlsBar"));
980     _node_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/NodeControlsBar"));
982     _tool_ctrl = new Toolbox(_select_ctrl, Gtk::TOOLBAR_ICONS);
984     _toolbars_vbox.pack_start(*Gtk::manage(_tool_ctrl), Gtk::PACK_SHRINK);
987 void
988 EditWidget::initUriBar()
990     /// \todo  Create an Inkscape::UI::Widget::UriBar class (?)
992     _uri_ctrl = new Gtk::Toolbar();
994     _uri_label.set_label(_("PLACEHOLDER, DO NOT TRANSLATE"));
995     _uri_ctrl->add(_uri_label);
996     _uri_ctrl->add(_uri_entry);
998     _uri_entry.signal_activate()
999         .connect_notify(sigc::mem_fun(*this, &EditWidget::onUriChanged));
1001     _toolbars_vbox.pack_start(*Gtk::manage(_uri_ctrl), Gtk::PACK_SHRINK);
1004 void
1005 EditWidget::initToolsBar()
1007     Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/ToolsBar")),
1008                                Gtk::TOOLBAR_ICONS,
1009                                Gtk::ORIENTATION_VERTICAL);
1010     g_assert(bar != NULL);
1011     _sub_window_hbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
1014 void
1015 EditWidget::initTopRuler()
1017     _viewport_table.attach(_top_ruler,  1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1019     _tooltips.set_tip (_top_ruler, _top_ruler.get_tip());
1022 void
1023 EditWidget::initLeftRuler()
1025     _viewport_table.attach(_left_ruler, 0, 1, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1027     _tooltips.set_tip (_left_ruler, _left_ruler.get_tip());
1030 void
1031 EditWidget::initBottomScrollbar()
1033     _viewport_table.attach(_bottom_scrollbar, 1, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1034     _bottom_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1035     _bottom_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1038 void
1039 EditWidget::initRightScrollbar()
1041     _viewport_table.attach(_right_scrollbar, 2, 3, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1043     _right_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1044     _right_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1047 void
1048 EditWidget::initStickyZoom()
1050     _viewport_table.attach(_sticky_zoom, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
1052     _sticky_zoom.set_active (prefs_get_int_attribute ("options.stickyzoom", "value", 0) != 0);
1053     _tooltips.set_tip (_sticky_zoom, _("Zoom drawing if window size changes"));
1055     /// \todo icon not implemented
1058 void
1059 EditWidget::initStatusbar()
1061     _statusbar.pack_start (_selected_style_status, false, false, 1);
1062     _statusbar.pack_start (*new Gtk::VSeparator(), false, false, 0);
1064     _tooltips.set_tip (_zoom_status, _("Zoom"));
1066     _layer_selector.reference();
1067     _statusbar.pack_start (_layer_selector, false, false, 1);
1069     _coord_status.property_n_rows() = 2;
1070     _coord_status.property_n_columns() = 5;
1071     _coord_status.property_row_spacing() = 0;
1072     _coord_status.property_column_spacing() = 2;
1073     _coord_eventbox.add (_coord_status);
1074     _tooltips.set_tip (_coord_eventbox, _("Cursor coordinates"));
1075     _coord_status.attach (*new Gtk::VSeparator(), 0,1, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1076     _coord_status.attach (*new Gtk::Label("X:", 0.0, 0.5), 1,2, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1077     _coord_status.attach (*new Gtk::Label("Y:", 0.0, 0.5), 1,2, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1078     _coord_status_x.set_text ("0.0");
1079     _coord_status_x.set_alignment (0.0, 0.5);
1080     _coord_status_y.set_text ("0.0");
1081     _coord_status_y.set_alignment (0.0, 0.5);
1082     _coord_status.attach (_coord_status_x, 2,3, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1083     _coord_status.attach (_coord_status_y, 2,3, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1084     _coord_status.attach (*new Gtk::Label("Z:", 0.0, 0.5), 3,4, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1085     _coord_status.attach (_zoom_status, 4,5, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1086     sp_set_font_size_smaller (static_cast<GtkWidget*>((void*)_coord_status.gobj()));
1087     _statusbar.pack_end (_coord_eventbox, false, false, 1);
1089     _select_status.property_xalign() = 0.0;
1090     _select_status.property_yalign() = 0.5;
1091     _select_status.set_markup (_("<b>Welcome to Inkscape!</b> Use shape or freehand tools to create objects; use selector (arrow) to move or transform them."));
1092     // include this again with Gtk+-2.6
1093 #if GTK_VERSION_GE(2,6)
1094      gtk_label_set_ellipsize (GTK_LABEL(_select_status.gobj()), PANGO_ELLIPSIZE_END);
1095 #endif
1096     _select_status.set_size_request (1, -1);
1097     _statusbar.pack_start (_select_status, true, true, 0);
1099     _main_window_table.attach(_statusbar, 0, 1, 3, 4, Gtk::FILL, Gtk::SHRINK);
1102 //========================================
1103 //----------implements EditWidgetInterface
1105 void *
1106 EditWidget::getWindow()
1108     return this;
1111 void
1112 EditWidget::setTitle (gchar const* new_title)
1114     set_title (new_title);
1117 void
1118 EditWidget::layout()
1120    show_all_children();
1123 void
1124 EditWidget::present()
1126     this->Gtk::Window::present();
1129 void
1130 EditWidget::getGeometry (gint &x, gint &y, gint &w, gint &h)
1132     get_position (x, y);
1133     get_size (w, h);
1136 void
1137 EditWidget::setSize (gint w, gint h)
1139     resize (w, h);
1142 void
1143 EditWidget::setPosition (NR::Point p)
1145     move (int(p[NR::X]), int(p[NR::Y]));
1148 /// \param p is already gobj()!
1149 void
1150 EditWidget::setTransient (void* p, int i)
1152 #ifndef WIN32
1153     gtk_window_set_transient_for (static_cast<GtkWindow*>(p), this->gobj());
1154     if (i==2)
1155         this->Gtk::Window::present();
1156 #endif
1159 NR::Point
1160 EditWidget::getPointer()
1162     int x, y;
1163     get_pointer (x, y);
1164     return NR::Point (x, y);
1167 void
1168 EditWidget::setFullscreen()
1170     fullscreen();
1173 /**
1174  *  Shuts down the desktop object for the view being closed.  It checks
1175  *  to see if the document has been edited, and if so prompts the user
1176  *  to save, discard, or cancel.  Returns TRUE if the shutdown operation
1177  *  is cancelled or if the save is cancelled or fails, FALSE otherwise.
1178  */
1179 bool
1180 EditWidget::shutdown()
1182     g_assert (_desktop != NULL);
1183     if (Inkscape::NSApplication::Editor::isDuplicatedView (_desktop))
1184         return false;
1186     SPDocument *doc = _desktop->doc();
1187     if (sp_document_repr_root(doc)->attribute("sodipodi:modified") != NULL)
1188     {
1189         gchar *markup;
1190         /// \todo FIXME !!! obviously this will have problems if the document
1191         /// name contains markup characters
1192         markup = g_strdup_printf(
1193                 _("<span weight=\"bold\" size=\"larger\">Save changes to document \"%s\" before closing?</span>\n\n"
1194                   "If you close without saving, your changes will be discarded."),
1195                 SP_DOCUMENT_NAME(doc));
1197         Gtk::MessageDialog dlg (*this,
1198                        markup,
1199                        true,
1200                        Gtk::MESSAGE_WARNING,
1201                        Gtk::BUTTONS_NONE,
1202                        true);
1203         g_free(markup);
1204         Gtk::Button close_button (_("Close _without saving"), true);
1205         dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1206         close_button.show();
1207         dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1208         dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1209         dlg.set_default_response (Gtk::RESPONSE_YES);
1211         int response = dlg.run();
1212         switch (response)
1213         {
1214             case Gtk::RESPONSE_YES:
1215                 sp_document_ref(doc);
1216                 if (sp_file_save_document(doc)) {
1217                     sp_document_unref(doc);
1218                 } else { // save dialog cancelled or save failed
1219                     sp_document_unref(doc);
1220                     return TRUE;
1221                 }
1222                 break;
1223             case Gtk::RESPONSE_NO:
1224                 break;
1225             default: // cancel pressed, or dialog was closed
1226                 return TRUE;
1227                 break;
1228         }
1229     }
1231     /* Code to check data loss */
1232     bool allow_data_loss = FALSE;
1233     while (sp_document_repr_root(doc)->attribute("inkscape:dataloss") != NULL && allow_data_loss == FALSE)
1234     {
1235         gchar *markup;
1236         /// \todo FIXME !!! obviously this will have problems if the document
1237         /// name contains markup characters
1238         markup = g_strdup_printf(
1239                 _("<span weight=\"bold\" size=\"larger\">The file \"%s\" was saved with a format (%s) that may cause data loss!</span>\n\n"
1240                   "Do you want to save this file in another format?"),
1241                 SP_DOCUMENT_NAME(doc),
1242                 Inkscape::Extension::db.get(sp_document_repr_root(doc)->attribute("inkscape:output_extension"))->get_name());
1244         Gtk::MessageDialog dlg (*this,
1245                        markup,
1246                        true,
1247                        Gtk::MESSAGE_WARNING,
1248                        Gtk::BUTTONS_NONE,
1249                        true);
1250         g_free(markup);
1251         Gtk::Button close_button (_("Close _without saving"), true);
1252         dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1253         close_button.show();
1254         dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1255         dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1256         dlg.set_default_response (Gtk::RESPONSE_YES);
1258         int response = dlg.run();
1260         switch (response)
1261         {
1262             case Gtk::RESPONSE_YES:
1263                 sp_document_ref(doc);
1264                 if (sp_file_save_document(doc)) {
1265                     sp_document_unref(doc);
1266                 } else { // save dialog cancelled or save failed
1267                     sp_document_unref(doc);
1268                     return TRUE;
1269                 }
1270                 break;
1271             case Gtk::RESPONSE_NO:
1272                 allow_data_loss = TRUE;
1273                 break;
1274             default: // cancel pressed, or dialog was closed
1275                 return TRUE;
1276                 break;
1277         }
1278     }
1280     return false;
1284 void
1285 EditWidget::destroy()
1287     delete this;
1290 void
1291 EditWidget::requestCanvasUpdate()
1293     _svg_canvas.widget().queue_draw();
1296 void
1297 EditWidget::activateDesktop()
1299     /// \todo active_desktop_indicator not implemented
1302 void
1303 EditWidget::deactivateDesktop()
1305     /// \todo active_desktop_indicator not implemented
1308 void
1309 EditWidget::viewSetPosition (NR::Point p)
1311     p -= _namedview->gridorigin;
1312     double lo, up, pos, max;
1313     _top_ruler.get_range (lo, up, pos, max);
1314     _top_ruler.set_range (lo, up, p[NR::X], max);
1315     _left_ruler.get_range (lo, up, pos, max);
1316     _left_ruler.set_range (lo, up, p[NR::Y], max);
1319 void
1320 EditWidget::updateRulers()
1322     NR::Point origin = _namedview->gridorigin;
1324     NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1325     double lo, up, pos, max;
1326     double const scale = _desktop->current_zoom();
1327     double s = viewbox.min()[NR::X] / scale - origin[NR::X];
1328     double e = viewbox.max()[NR::X] / scale - origin[NR::X];
1329     _top_ruler.get_range(lo, up, pos, max);
1330     _top_ruler.set_range(s, e, pos, e);
1331     s = viewbox.min()[NR::Y] / -scale - origin[NR::Y];
1332     e = viewbox.max()[NR::Y] / -scale - origin[NR::Y];
1333     _left_ruler.set_range(s, e, origin[NR::Y], e);
1334     /// \todo is that correct?
1337 void
1338 EditWidget::updateScrollbars (double scale)
1340     // do not call this function before canvas has its size allocated
1341     if (!is_realized() || _update_s_f) {
1342         return;
1343     }
1345     _update_s_f = true;
1347     /* The desktop region we always show unconditionally */
1348     SPDocument *doc = _desktop->doc();
1349     NR::Rect const r = sp_item_bbox_desktop(SP_ITEM(SP_DOCUMENT_ROOT(doc)));
1350     NR::Rect darea(NR::Point(MIN(r.min()[NR::X], -sp_document_width(doc)),
1351                              MIN(r.min()[NR::Y], -sp_document_height(doc))),
1352                    NR::Point(MAX(r.max()[NR::X], 2 * sp_document_width(doc)),
1353                              MAX(r.max()[NR::Y], 2 * sp_document_height(doc))));
1355     /* Canvas region we always show unconditionally */
1356     NR::Rect carea(NR::Point(darea.min()[NR::X] * scale - 64,
1357                              darea.max()[NR::Y] * -scale - 64),
1358                    NR::Point(darea.max()[NR::X] * scale + 64,
1359                              darea.min()[NR::Y] * -scale + 64));
1361     NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1363     /* Viewbox is always included into scrollable region */
1364     carea = NR::Rect::union_bounds(carea, viewbox);
1366     Gtk::Adjustment *adj = _bottom_scrollbar.get_adjustment();
1367     adj->set_value(viewbox.min()[NR::X]);
1368     adj->set_lower(carea.min()[NR::X]);
1369     adj->set_upper(carea.max()[NR::X]);
1370     adj->set_page_increment(viewbox.dimensions()[NR::X]);
1371     adj->set_step_increment(0.1 * (viewbox.dimensions()[NR::X]));
1372     adj->set_page_size(viewbox.dimensions()[NR::X]);
1374     adj = _right_scrollbar.get_adjustment();
1375     adj->set_value(viewbox.min()[NR::Y]);
1376     adj->set_lower(carea.min()[NR::Y]);
1377     adj->set_upper(carea.max()[NR::Y]);
1378     adj->set_page_increment(viewbox.dimensions()[NR::Y]);
1379     adj->set_step_increment(0.1 * viewbox.dimensions()[NR::Y]);
1380     adj->set_page_size(viewbox.dimensions()[NR::Y]);
1382     _update_s_f = false;
1385 void
1386 EditWidget::toggleRulers()
1388     if (_top_ruler.is_visible())
1389     {
1390         _top_ruler.hide_all();
1391         _left_ruler.hide_all();
1392         prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 0);
1393     } else {
1394         _top_ruler.show_all();
1395         _left_ruler.show_all();
1396         prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 1);
1397     }
1400 void
1401 EditWidget::toggleScrollbars()
1403     if (_bottom_scrollbar.is_visible())
1404     {
1405         _bottom_scrollbar.hide_all();
1406         _right_scrollbar.hide_all();
1407         prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 0);
1408     } else {
1409         _bottom_scrollbar.show_all();
1410         _right_scrollbar.show_all();
1411         prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 1);
1412     }
1415 void
1416 EditWidget::updateZoom()
1418     _zoom_status.update();
1421 void
1422 EditWidget::letZoomGrabFocus()
1424     _zoom_status.grab_focus();
1427 void
1428 EditWidget::setToolboxFocusTo (const gchar *)
1430     /// \todo not implemented
1433 void
1434 EditWidget::setToolboxAdjustmentValue (const gchar *, double)
1436     /// \todo not implemented
1439 bool
1440 EditWidget::isToolboxButtonActive (gchar const*)
1442     /// \todo not implemented
1443     return true;
1446 void
1447 EditWidget::setCoordinateStatus (NR::Point p)
1449     gchar *cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::X]);
1450     _coord_status_x.property_label() = cstr;
1451     g_free (cstr);
1452     cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::Y]);
1453     _coord_status_y.property_label() = cstr;
1454     g_free (cstr);
1457 void
1458 EditWidget::setMessage (Inkscape::MessageType type, gchar const* msg)
1460     _select_status.set_markup (msg? msg : "");
1463 bool
1464 EditWidget::warnDialog (gchar* msg)
1466     Gtk::MessageDialog dlg (*this,
1467                        msg,
1468                        true,
1469                        Gtk::MESSAGE_WARNING,
1470                        Gtk::BUTTONS_YES_NO,
1471                        true);
1472     int r = dlg.run();
1473     return r == Gtk::RESPONSE_YES;
1477 void EditWidget::_namedview_modified (SPObject *obj, guint flags) {
1478     SPNamedView *nv = static_cast<SPNamedView *>(obj);
1479     if (flags & SP_OBJECT_MODIFIED_FLAG) {
1480         this->_dt2r = 1.0 / nv->doc_units->unittobase;
1481         this->_top_ruler.update_metric();
1482         this->_left_ruler.update_metric();
1483         this->_tooltips.set_tip(this->_top_ruler, this->_top_ruler.get_tip());
1484         this->_tooltips.set_tip(this->_left_ruler, this->_left_ruler.get_tip());
1485         this->updateRulers();
1486     }
1489 void
1490 EditWidget::initEdit (SPDocument *doc)
1492     _desktop = new SPDesktop();
1493     _desktop->registerEditWidget (this);
1495     _namedview = sp_document_namedview (doc, 0);
1496     _svg_canvas.init (_desktop);
1497     _desktop->init (_namedview, _svg_canvas.spobj());
1498     sp_namedview_window_from_document (_desktop);
1499     _dt2r = 1.0 / _namedview->doc_units->unittobase;
1501     /// \todo convert to sigc++ when SPObject hierarchy gets converted
1502     /* Listen on namedview modification */
1503     _namedview_modified_connection = _desktop->namedview->connectModified(sigc::mem_fun(*this, &EditWidget::_namedview_modified));
1504     _layer_selector.setDesktop (_desktop);
1505     _selected_style_status.setDesktop (_desktop);
1507     Inkscape::NSApplication::Editor::addDesktop (_desktop);
1509     _zoom_status.init (_desktop);
1510     _top_ruler.init (_desktop, _svg_canvas.widget());
1511     _left_ruler.init (_desktop, _svg_canvas.widget());
1512     updateRulers();
1515 void
1516 EditWidget::destroyEdit()
1518     if (_desktop) {
1519         _layer_selector.unreference();
1520         Inkscape::NSApplication::Editor::removeDesktop (_desktop); // clears selection too
1521         _namedview_modified_connection.disconnect();
1522         _desktop->destroy();
1523         Inkscape::GC::release (_desktop);
1524         _desktop = 0;
1525     }
1528 //----------end of EditWidgetInterface implementation
1530 //----------start of other callbacks
1532 bool
1533 EditWidget::on_key_press_event (GdkEventKey* event)
1535     // this is the original code from helper/window.cpp
1537     unsigned int shortcut;
1538     shortcut = get_group0_keyval (event) |
1539                    ( event->state & GDK_SHIFT_MASK ?
1540                      SP_SHORTCUT_SHIFT_MASK : 0 ) |
1541                    ( event->state & GDK_CONTROL_MASK ?
1542                      SP_SHORTCUT_CONTROL_MASK : 0 ) |
1543                    ( event->state & GDK_MOD1_MASK ?
1544                      SP_SHORTCUT_ALT_MASK : 0 );
1545     return sp_shortcut_invoke (shortcut,
1546                              Inkscape::NSApplication::Editor::getActiveDesktop());
1549 bool
1550 EditWidget::on_delete_event (GdkEventAny*)
1552     return shutdown();
1555 bool
1556 EditWidget::on_focus_in_event (GdkEventFocus*)
1558     Inkscape::NSApplication::Editor::activateDesktop (_desktop);
1559     _svg_canvas.widget().grab_focus();
1561     return false;
1564 void
1565 EditWidget::onWindowSizeAllocate (Gtk::Allocation &newall)
1567     if (!is_realized()) return;
1569     const Gtk::Allocation& all = get_allocation();
1570     if ((newall.get_x() == all.get_x()) &&
1571         (newall.get_y() == all.get_y()) &&
1572         (newall.get_width() == all.get_width()) &&
1573         (newall.get_height() == all.get_height())) {
1574         return;
1575     }
1577     NR::Rect const area = _desktop->get_display_area();
1578     double zoom = _desktop->current_zoom();
1580     if (_sticky_zoom.get_active()) {
1581         /* Calculate zoom per pixel */
1582         double const zpsp = zoom / hypot(area.dimensions()[NR::X], area.dimensions()[NR::Y]);
1583         /* Find new visible area */
1584         NR::Rect const newarea = _desktop->get_display_area();
1585         /* Calculate adjusted zoom */
1586         zoom = zpsp * hypot(newarea.dimensions()[NR::X], newarea.dimensions()[NR::Y]);
1587     }
1589     _desktop->zoom_absolute(area.midpoint()[NR::X], area.midpoint()[NR::Y], zoom);
1592 void
1593 EditWidget::onWindowRealize()
1595     NR::Rect d(NR::Point(0, 0),
1596                NR::Point(sp_document_width(_desktop->doc()), sp_document_height(_desktop->doc())));
1598     if (fabs(d.dimensions()[NR::X]) < 1.0 || fabs(d.dimensions()[NR::Y]) < 1.0) {
1599         return;
1600     }
1602     _desktop->set_display_area(d.min()[NR::X], d.min()[NR::Y], d.max()[NR::X], d.max()[NR::Y], 10);
1603     _namedview_modified(_desktop->namedview, SP_OBJECT_MODIFIED_FLAG);
1604     setTitle (SP_DOCUMENT_NAME(_desktop->doc()));
1607 void
1608 EditWidget::onAdjValueChanged()
1610     if (_update_a_f) return;
1611     _update_a_f = true;
1613     sp_canvas_scroll_to (_svg_canvas.spobj(),
1614                          _bottom_scrollbar.get_value(),
1615                          _right_scrollbar.get_value(),
1616                          false);
1617     updateRulers();
1619     _update_a_f = false;
1623 } // namespace View
1624 } // namespace UI
1625 } // namespace Inkscape
1627 /*
1628   Local Variables:
1629   mode:c++
1630   c-file-style:"stroustrup"
1631   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1632   indent-tabs-mode:nil
1633   fill-column:99
1634   End:
1635 */
1636 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :