Code

manually merging the INKBOARD_PEDRO branch into trunk
[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 "macros.h"
42 #include "path-prefix.h"
43 #include "prefs-utils.h"
44 #include "file.h"
45 #include "application/editor.h"
46 #include "edit-widget.h"
47 #include "ui/stock.h"
48 #include "ui/stock-items.h"
49 #include "ui/icons.h"
51 #include "display/sodipodi-ctrlrect.h"
52 #include "helper/units.h"
53 #include "shortcuts.h"
54 #include "widgets/spw-utilities.h"
55 #include "event-context.h"
56 #include "document.h"
57 #include "sp-namedview.h"
58 #include "sp-item.h"
59 #include "interface.h"
60 #include "extension/db.h"
62 using namespace Inkscape::UI;
63 using namespace Inkscape::UI::Widget;
65 namespace Inkscape {
66 namespace UI {
67 namespace View {
69 EditWidget::EditWidget (SPDocument *doc)
70     : _main_window_table(4),
71       _viewport_table(3,3),
72       _act_grp(Gtk::ActionGroup::create()),
73       _ui_mgr(Gtk::UIManager::create()),
74       _update_s_f(false),
75       _update_a_f(false)
76 {
77     g_warning("Creating new EditWidget");
79     _desktop = 0;
80     Icons::init();
81     Stock::init();
82     initActions();
83     initAccelMap();
84     initUIManager();
85     initLayout();
86     initEdit (doc);
87     g_warning("Done creating new EditWidget");
88 }
90 EditWidget::~EditWidget()
91 {
92     destroyEdit();
93 }
95 void
96 EditWidget::initActions()
97 {
98     initMenuActions();
99     initToolbarActions();
102 void
103 EditWidget::initUIManager()
105     _ui_mgr->insert_action_group(_act_grp);
106     add_accel_group(_ui_mgr->get_accel_group());
108     gchar *filename_utf8 = g_build_filename(INKSCAPE_UIDIR, "menus-bars.xml", NULL);
109     if (_ui_mgr->add_ui_from_file(filename_utf8) == 0) {
110         g_warning("Error merging ui from file '%s'", filename_utf8);
111         // fixme-charset: What charset should we pass to g_warning?
112     }
113     g_free(filename_utf8);
116 void
117 EditWidget::initLayout()
119     set_title("New document 1 - Inkscape");
120     set_resizable();
121     set_default_size(640, 480);
123     // top level window into which all other portions of the UI get inserted
124     add(_main_window_table);
125     // attach box for horizontal toolbars
126     _main_window_table.attach(_toolbars_vbox, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
127     // attach sub-window for viewport and vertical toolbars
128     _main_window_table.attach(_sub_window_hbox, 0, 1, 2, 3);
129     // viewport table with 3 rows by 3 columns
130     _sub_window_hbox.pack_end(_viewport_table);
132     // Menus and Bars
133     initMenuBar();
134     initCommandsBar();
135     initToolControlsBar();
136     initUriBar();
137     initToolsBar();
139     // Canvas Viewport
140     initLeftRuler();
141     initTopRuler();
142     initStickyZoom();
143     initBottomScrollbar();
144     initRightScrollbar();
145     _viewport_table.attach(_svg_canvas.widget(), 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
146     _svg_canvas.widget().show_all();
149     // The statusbar comes last and appears at the bottom of _main_window_table
150     initStatusbar();
152     signal_size_allocate().connect (sigc::mem_fun (*this, &EditWidget::onWindowSizeAllocate), false);
153     signal_realize().connect (sigc::mem_fun (*this, &EditWidget::onWindowRealize));
154     show_all_children();
157 void
158 EditWidget::onMenuItem()
160     g_warning("onMenuItem called");
163 void
164 EditWidget::onActionFileNew()
166 //    g_warning("onActionFileNew called");
167     sp_file_new_default();
170 void
171 EditWidget::onActionFileOpen()
173 //    g_warning("onActionFileOpen called");
174     sp_file_open_dialog (NULL, NULL);
177 void
178 EditWidget::onActionFileQuit()
180     g_warning("onActionFileQuit");
181     sp_ui_close_all();
184 void
185 EditWidget::onActionFilePrint()
187     g_warning("onActionFilePrint");
190 void
191 EditWidget::onToolbarItem()
193     g_warning("onToolbarItem called");
196 void
197 EditWidget::onSelectTool()
199     _tool_ctrl->remove();
200     _tool_ctrl->add(*_select_ctrl);
203 void
204 EditWidget::onNodeTool()
206     _tool_ctrl->remove();
207     _tool_ctrl->add(*_node_ctrl);
210 void
211 EditWidget::onDialogInkscapePreferences()
213     _dlg_mgr.showDialog("InkscapePreferences");
216 void
217 EditWidget::onDialogAbout()
221 void
222 EditWidget::onDialogAlignAndDistribute()
224     _dlg_mgr.showDialog("AlignAndDistribute");
227 void
228 EditWidget::onDialogDocumentProperties()
230 //    manage (Inkscape::UI::Dialog::DocumentPreferences::create());
231     _dlg_mgr.showDialog("DocumentPreferences");
234 void
235 EditWidget::onDialogExport()
237     _dlg_mgr.showDialog("Export");
240 void
241 EditWidget::onDialogExtensionEditor()
243     _dlg_mgr.showDialog("ExtensionEditor");
246 void
247 EditWidget::onDialogFillAndStroke()
249     _dlg_mgr.showDialog("FillAndStroke");
252 void
253 EditWidget::onDialogFind()
255     _dlg_mgr.showDialog("Find");
258 void
259 EditWidget::onDialogLayerEditor()
261     _dlg_mgr.showDialog("LayerEditor");
264 void
265 EditWidget::onDialogMessages()
267     _dlg_mgr.showDialog("Messages");
270 void
271 EditWidget::onDialogObjectProperties()
273     _dlg_mgr.showDialog("ObjectProperties");
276 void
277 EditWidget::onDialogTextProperties()
279     _dlg_mgr.showDialog("TextProperties");
282 void
283 EditWidget::onDialogTrace()
287 void
288 EditWidget::onDialogTransformation()
290     _dlg_mgr.showDialog("Transformation");
293 void
294 EditWidget::onDialogXmlEditor()
296     _dlg_mgr.showDialog("XmlEditor");
299 void
300 EditWidget::onUriChanged()
302     g_message("onUriChanged called");
306 // FIXME: strings are replaced by placeholders, NOT to be translated until the code is enabled
307 // See http://sourceforge.net/mailarchive/message.php?msg_id=11746016 for details
309 void
310 EditWidget::initMenuActions()
312 //    _act_grp->add(Gtk::Action::create("MenuFile",   _("PLACEHOLDER, do not translate")));
313 //    _act_grp->add(Gtk::Action::create("MenuEdit",   _("PLACEHOLDER, do not translate")));
314 //    _act_grp->add(Gtk::Action::create("MenuView",   _("PLACEHOLDER, do not translate")));
315 //    _act_grp->add(Gtk::Action::create("MenuLayer",  _("PLACEHOLDER, do not translate")));
316 //    _act_grp->add(Gtk::Action::create("MenuObject", _("PLACEHOLDER, do not translate")));
317 //    _act_grp->add(Gtk::Action::create("MenuPath",   _("PLACEHOLDER, do not translate")));
318 //    _act_grp->add(Gtk::Action::create("MenuText",   _("PLACEHOLDER, do not translate")));
319 //    _act_grp->add(Gtk::Action::create("MenuHelp",   _("PLACEHOLDER, do not translate")));
320 // temporarily replaced with non-gettext version to have a well-sized menu
321 // for testing:
323     _act_grp->add(Gtk::Action::create("MenuFile",   "File"));
324     _act_grp->add(Gtk::Action::create("MenuEdit",   "Edit"));
325     _act_grp->add(Gtk::Action::create("MenuView",   "View"));
326     _act_grp->add(Gtk::Action::create("MenuLayer",  "Layer"));
327     _act_grp->add(Gtk::Action::create("MenuObject", "Object"));
328     _act_grp->add(Gtk::Action::create("MenuPath",   "Path"));
329     _act_grp->add(Gtk::Action::create("MenuText",   "Text"));
330     _act_grp->add(Gtk::Action::create("MenuHelp",   "Help"));
332     // File menu
333     _act_grp->add(Gtk::Action::create("New",
334                                       Gtk::Stock::NEW, Glib::ustring(),
335                                       _("PLACEHOLDER, do not translate")),
336                   sigc::mem_fun(*this, &EditWidget::onActionFileNew));
338     _act_grp->add(Gtk::Action::create("Open",
339                                       Gtk::Stock::OPEN, Glib::ustring(),
340                                       _("PLACEHOLDER, do not translate")),
341                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
343     _act_grp->add(Gtk::Action::create("OpenRecent",
344                                       Stock::OPEN_RECENT));
346     _act_grp->add(Gtk::Action::create("Revert",
347                                       Gtk::Stock::REVERT_TO_SAVED, Glib::ustring(),
348                                       _("PLACEHOLDER, do not translate")),
349                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
351     _act_grp->add(Gtk::Action::create("Save",
352                                       Gtk::Stock::SAVE, Glib::ustring(),
353                                       _("PLACEHOLDER, do not translate")),
354                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
356     _act_grp->add(Gtk::Action::create("SaveAs",
357                                       Gtk::Stock::SAVE_AS, Glib::ustring(),
358                                       _("PLACEHOLDER, do not translate")),
359                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
361     _act_grp->add(Gtk::Action::create("Import",
362                                       Stock::IMPORT, Glib::ustring(),
363                                       _("PLACEHOLDER, do not translate")),
364                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
366     _act_grp->add(Gtk::Action::create("Export",
367                                       Stock::EXPORT, Glib::ustring(),
368                                       _("PLACEHOLDER, do not translate")),
369                   sigc::mem_fun(*this, &EditWidget::onDialogExport));
371     _act_grp->add(Gtk::Action::create("Print",
372                                       Gtk::Stock::PRINT, Glib::ustring(),
373                                       _("PLACEHOLDER, do not translate")),
374                   sigc::mem_fun(*this, &EditWidget::onActionFilePrint));
376     _act_grp->add(Gtk::Action::create("PrintPreview",
377                                       Gtk::Stock::PRINT_PREVIEW),
378                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
380     _act_grp->add(Gtk::Action::create("VacuumDefs",
381                                       Stock::VACUUM_DEFS),
382                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
384     _act_grp->add(Gtk::Action::create("DocumentProperties",
385                                       Gtk::Stock::PROPERTIES, Glib::ustring(),
386                                       _("PLACEHOLDER, do not translate")),
387                   sigc::mem_fun(*this, &EditWidget::onDialogDocumentProperties));
389     _act_grp->add(Gtk::Action::create("InkscapePreferences",
390                                       Gtk::Stock::PREFERENCES, Glib::ustring(),
391                                       _("PLACEHOLDER, do not translate")),
392                   sigc::mem_fun(*this, &EditWidget::onDialogInkscapePreferences));
394     _act_grp->add(Gtk::Action::create("Close",
395                                       Gtk::Stock::CLOSE),
396                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
398     _act_grp->add(Gtk::Action::create("Quit",
399                                       Gtk::Stock::QUIT),
400                   sigc::mem_fun(*this, &EditWidget::onActionFileQuit));
402     // EditWidget menu
403     _act_grp->add(Gtk::Action::create("Undo",
404                                       Gtk::Stock::UNDO, Glib::ustring(),
405                                       _("PLACEHOLDER, do not translate")));
407     _act_grp->add(Gtk::Action::create("Redo",
408                                       Gtk::Stock::REDO, Glib::ustring(),
409                                       _("PLACEHOLDER, do not translate")));
411     _act_grp->add(Gtk::Action::create("Cut",
412                                       Gtk::Stock::CUT, Glib::ustring(),
413                                       _("PLACEHOLDER, do not translate")));
415     _act_grp->add(Gtk::Action::create("Copy",
416                                       Gtk::Stock::COPY, Glib::ustring(),
417                                       _("PLACEHOLDER, do not translate")));
419     _act_grp->add(Gtk::Action::create("Paste",
420                                       Gtk::Stock::PASTE, Glib::ustring(),
421                                       _("PLACEHOLDER, do not translate")));
423     _act_grp->add(Gtk::Action::create("PasteInPlace",
424                                       Stock::PASTE_IN_PLACE));
426     _act_grp->add(Gtk::Action::create("PasteStyle",
427                                       Stock::PASTE_STYLE));
429     _act_grp->add(Gtk::Action::create("Find",
430                                       Gtk::Stock::FIND),
431                   sigc::mem_fun(*this, &EditWidget::onDialogFind));
433     _act_grp->add(Gtk::Action::create("Duplicate",
434                                       Stock::DUPLICATE, Glib::ustring(),
435                                       _("PLACEHOLDER, do not translate")));
437     _act_grp->add(Gtk::Action::create("Clone",
438                                       Stock::CLONE, Glib::ustring(),
439                                       _("PLACEHOLDER, do not translate")));
441     _act_grp->add(Gtk::Action::create("CloneUnlink",
442                                       Stock::CLONE_UNLINK, Glib::ustring(),
443                                       _("PLACEHOLDER, do not translate")));
445     _act_grp->add(Gtk::Action::create("CloneSelectOrig",
446                                       Stock::CLONE_SELECT_ORIG));
448     _act_grp->add(Gtk::Action::create("MakeBitmap",
449                                       Stock::MAKE_BITMAP));
451     _act_grp->add(Gtk::Action::create("Tile",
452                                      Stock::TILE));
454     _act_grp->add(Gtk::Action::create("Untile",
455                                       Stock::UNTILE));
457     _act_grp->add(Gtk::Action::create("Delete",
458                                       Gtk::Stock::DELETE));
460     _act_grp->add(Gtk::Action::create("SelectAll",
461                                       Stock::SELECT_ALL));
463     _act_grp->add(Gtk::Action::create("SelectAllInAllLayers",
464                                       Stock::SELECT_ALL_IN_ALL_LAYERS));
466     _act_grp->add(Gtk::Action::create("SelectInvert",
467                                       Stock::SELECT_INVERT));
469     _act_grp->add(Gtk::Action::create("SelectNone",
470                                       Stock::SELECT_NONE));
472     _act_grp->add(Gtk::Action::create("XmlEditor",
473                                       Stock::XML_EDITOR, Glib::ustring(),
474                                       _("PLACEHOLDER, do not translate")),
475                   sigc::mem_fun(*this, &EditWidget::onDialogXmlEditor));
477     // View menu
478     _act_grp->add(Gtk::Action::create("Zoom",
479                                       Stock::ZOOM));
481     _act_grp->add(Gtk::Action::create("ZoomIn",
482                                       Stock::ZOOM_IN, Glib::ustring(),
483                                       _("PLACEHOLDER, do not translate")));
485     _act_grp->add(Gtk::Action::create("ZoomOut",
486                                       Stock::ZOOM_OUT, Glib::ustring(),
487                                       _("PLACEHOLDER, do not translate")));
489     _act_grp->add(Gtk::Action::create("Zoom100",
490                                       Stock::ZOOM_100, Glib::ustring(),
491                                       _("PLACEHOLDER, do not translate")));
493     _act_grp->add(Gtk::Action::create("Zoom50",
494                                       Stock::ZOOM_50, Glib::ustring(),
495                                       _("PLACEHOLDER, do not translate")));
497     _act_grp->add(Gtk::Action::create("Zoom200",
498                                       Stock::ZOOM_200, Glib::ustring(),
499                                       _("PLACEHOLDER, do not translate")));
501     _act_grp->add(Gtk::Action::create("ZoomSelection",
502                                       Stock::ZOOM_SELECTION, Glib::ustring(),
503                                       _("PLACEHOLDER, do not translate")));
505     _act_grp->add(Gtk::Action::create("ZoomDrawing",
506                                       Stock::ZOOM_DRAWING, Glib::ustring(),
507                                       _("PLACEHOLDER, do not translate")));
509     _act_grp->add(Gtk::Action::create("ZoomPage",
510                                       Stock::ZOOM_PAGE, Glib::ustring(),
511                                       _("PLACEHOLDER, do not translate")));
513     _act_grp->add(Gtk::Action::create("ZoomWidth",
514                                       Stock::ZOOM_WIDTH, Glib::ustring(),
515                                       _("PLACEHOLDER, do not translate")));
517     _act_grp->add(Gtk::Action::create("ZoomPrev",
518                                       Stock::ZOOM_PREV, Glib::ustring(),
519                                       _("PLACEHOLDER, do not translate")));
521     _act_grp->add(Gtk::Action::create("ZoomNext",
522                                       Stock::ZOOM_NEXT, Glib::ustring(),
523                                       _("PLACEHOLDER, do not translate")));
525     _act_grp->add(Gtk::Action::create("ShowHide",
526                                       Stock::SHOW_HIDE));
528     _act_grp->add(Gtk::ToggleAction::create("ShowHideCommandsBar",
529                                             Stock::SHOW_HIDE_COMMANDS_BAR));
531     _act_grp->add(Gtk::ToggleAction::create("ShowHideToolControlsBar",
532                                             Stock::SHOW_HIDE_TOOL_CONTROLS_BAR));
534     _act_grp->add(Gtk::ToggleAction::create("ShowHideToolsBar",
535                                             Stock::SHOW_HIDE_TOOLS_BAR));
537     _act_grp->add(Gtk::ToggleAction::create("ShowHideRulers",
538                                             Stock::SHOW_HIDE_RULERS));
540     _act_grp->add(Gtk::ToggleAction::create("ShowHideScrollbars",
541                                             Stock::SHOW_HIDE_SCROLLBARS));
543     _act_grp->add(Gtk::ToggleAction::create("ShowHideStatusbar",
544                                             Stock::SHOW_HIDE_STATUSBAR));
546     _act_grp->add(Gtk::Action::create("ShowHideDialogs",
547                                       Stock::SHOW_HIDE_DIALOGS));
549     _act_grp->add(Gtk::Action::create("Grid",
550                                       Stock::GRID));
552     _act_grp->add(Gtk::Action::create("Guides",
553                                       Stock::GUIDES));
555     _act_grp->add(Gtk::Action::create("Fullscreen",
556                                       Stock::FULLSCREEN));
558     _act_grp->add(Gtk::Action::create("Messages",
559                                       Stock::MESSAGES),
560                   sigc::mem_fun(*this, &EditWidget::onDialogMessages));
562     _act_grp->add(Gtk::Action::create("Scripts",
563                                       Stock::SCRIPTS));
565     _act_grp->add(Gtk::Action::create("WindowPrev",
566                                       Stock::WINDOW_PREV));
568     _act_grp->add(Gtk::Action::create("WindowNext",
569                                       Stock::WINDOW_NEXT));
571     _act_grp->add(Gtk::Action::create("WindowDuplicate",
572                                       Stock::WINDOW_DUPLICATE));
574     // Layer menu
575     _act_grp->add(Gtk::Action::create("LayerNew",
576                                       Stock::LAYER_NEW));
578     _act_grp->add(Gtk::Action::create("LayerRename",
579                                       Stock::LAYER_RENAME));
581     _act_grp->add(Gtk::Action::create("LayerDuplicate",
582                                       Stock::LAYER_DUPLICATE));
584     _act_grp->add(Gtk::Action::create("LayerAnchor",
585                                       Stock::LAYER_ANCHOR));
587     _act_grp->add(Gtk::Action::create("LayerMergeDown",
588                                       Stock::LAYER_MERGE_DOWN));
590     _act_grp->add(Gtk::Action::create("LayerDelete",
591                                       Stock::LAYER_DELETE));
593     _act_grp->add(Gtk::Action::create("LayerSelectNext",
594                                       Stock::LAYER_SELECT_NEXT));
596     _act_grp->add(Gtk::Action::create("LayerSelectPrev",
597                                       Stock::LAYER_SELECT_PREV));
599     _act_grp->add(Gtk::Action::create("LayerSelectTop",
600                                       Stock::LAYER_SELECT_TOP));
602     _act_grp->add(Gtk::Action::create("LayerSelectBottom",
603                                       Stock::LAYER_SELECT_BOTTOM));
605     _act_grp->add(Gtk::Action::create("LayerRaise",
606                                       Stock::LAYER_RAISE));
608     _act_grp->add(Gtk::Action::create("LayerLower",
609                                       Stock::LAYER_LOWER));
611     _act_grp->add(Gtk::Action::create("LayerToTop",
612                                       Stock::LAYER_TO_TOP));
614     _act_grp->add(Gtk::Action::create("LayerToBottom",
615                                       Stock::LAYER_TO_BOTTOM));
617     // Object menu
618     _act_grp->add(Gtk::Action::create("FillAndStroke",
619                                       Stock::FILL_STROKE, Glib::ustring(),
620                                       _("PLACEHOLDER, do not translate")),
621                   sigc::mem_fun(*this, &EditWidget::onDialogFillAndStroke));
623     _act_grp->add(Gtk::Action::create("ObjectProperties",
624                                       Stock::OBJECT_PROPERTIES),
625                   sigc::mem_fun(*this, &EditWidget::onDialogObjectProperties));
627     _act_grp->add(Gtk::Action::create("Group",
628                                       Stock::GROUP, Glib::ustring(),
629                                       _("PLACEHOLDER, do not translate")));
631     _act_grp->add(Gtk::Action::create("Ungroup",
632                                       Stock::UNGROUP, Glib::ustring(),
633                                       _("PLACEHOLDER, do not translate")));
635     _act_grp->add(Gtk::Action::create("Raise",
636                                       Stock::RAISE, Glib::ustring(),
637                                       _("PLACEHOLDER, do not translate")));
639     _act_grp->add(Gtk::Action::create("Lower",
640                                       Stock::LOWER, Glib::ustring(),
641                                       _("PLACEHOLDER, do not translate")));
643     _act_grp->add(Gtk::Action::create("RaiseToTop",
644                                       Stock::RAISE_TO_TOP, Glib::ustring(),
645                                       _("PLACEHOLDER, do not translate")));
647     _act_grp->add(Gtk::Action::create("LowerToBottom",
648                                       Stock::LOWER_TO_BOTTOM, Glib::ustring(),
649                                       _("PLACEHOLDER, do not translate")));
651     _act_grp->add(Gtk::Action::create("MoveToNewLayer",
652                                       Stock::MOVE_TO_NEW_LAYER, Glib::ustring(),
653                                       _("PLACEHOLDER, do not translate")));
655     _act_grp->add(Gtk::Action::create("MoveToNextLayer",
656                                       Stock::MOVE_TO_NEXT_LAYER, Glib::ustring(),
657                                       _("PLACEHOLDER, do not translate")));
659     _act_grp->add(Gtk::Action::create("MoveToPrevLayer",
660                                       Stock::MOVE_TO_PREV_LAYER, Glib::ustring(),
661                                       _("PLACEHOLDER, do not translate")));
663     _act_grp->add(Gtk::Action::create("MoveToTopLayer",
664                                       Stock::MOVE_TO_TOP_LAYER, Glib::ustring(),
665                                       _("PLACEHOLDER, do not translate")));
667     _act_grp->add(Gtk::Action::create("MoveToBottomLayer",
668                                       Stock::MOVE_TO_BOTTOM_LAYER, Glib::ustring(),
669                                       _("PLACEHOLDER, do not translate")));
671     _act_grp->add(Gtk::Action::create("Rotate90CW",
672                                       Stock::ROTATE_90_CW, Glib::ustring(),
673                                       _("PLACEHOLDER, do not translate")));
675     _act_grp->add(Gtk::Action::create("Rotate90CCW",
676                                       Stock::ROTATE_90_CCW, Glib::ustring(),
677                                       _("PLACEHOLDER, do not translate")));
679     _act_grp->add(Gtk::Action::create("FlipHoriz",
680                                       Stock::FLIP_HORIZ, Glib::ustring(),
681                                       _("PLACEHOLDER, do not translate")));
683     _act_grp->add(Gtk::Action::create("FlipVert",
684                                       Stock::FLIP_VERT, Glib::ustring(),
685                                       _("PLACEHOLDER, do not translate")));
687     _act_grp->add(Gtk::Action::create("Transformation",
688                                       Stock::TRANSFORMATION, Glib::ustring(),
689                                       _("PLACEHOLDER, do not translate")),
690                   sigc::mem_fun(*this, &EditWidget::onDialogTransformation));
692     _act_grp->add(Gtk::Action::create("AlignAndDistribute",
693                                       Stock::ALIGN_DISTRIBUTE, Glib::ustring(),
694                                       _("PLACEHOLDER, do not translate")),
695                   sigc::mem_fun(*this, &EditWidget::onDialogAlignAndDistribute));
697     // Path menu
698     _act_grp->add(Gtk::Action::create("ObjectToPath",
699                                       Stock::OBJECT_TO_PATH, Glib::ustring(),
700                                       _("PLACEHOLDER, do not translate")));
702     _act_grp->add(Gtk::Action::create("StrokeToPath",
703                                       Stock::STROKE_TO_PATH, Glib::ustring(),
704                                       _("PLACEHOLDER, do not translate")));
706     _act_grp->add(Gtk::Action::create("Trace",
707                                       Stock::TRACE),
708                   sigc::mem_fun(*this, &EditWidget::onDialogTrace));
710     _act_grp->add(Gtk::Action::create("Union",
711                                       Stock::UNION));
713     _act_grp->add(Gtk::Action::create("Difference",
714                                       Stock::DIFFERENCE));
716     _act_grp->add(Gtk::Action::create("Intersection",
717                                       Stock::INTERSECTION));
719     _act_grp->add(Gtk::Action::create("Exclusion",
720                                       Stock::EXCLUSION));
722     _act_grp->add(Gtk::Action::create("Division",
723                                       Stock::DIVISION));
725     _act_grp->add(Gtk::Action::create("CutPath",
726                                       Stock::CUT_PATH));
728     _act_grp->add(Gtk::Action::create("Combine",
729                                       Stock::COMBINE));
731     _act_grp->add(Gtk::Action::create("BreakApart",
732                                       Stock::BREAK_APART));
734     _act_grp->add(Gtk::Action::create("Inset",
735                                       Stock::INSET));
737     _act_grp->add(Gtk::Action::create("Outset",
738                                       Stock::OUTSET));
740     _act_grp->add(Gtk::Action::create("OffsetDynamic",
741                                       Stock::OFFSET_DYNAMIC));
743     _act_grp->add(Gtk::Action::create("OffsetLinked",
744                                       Stock::OFFSET_LINKED));
746     _act_grp->add(Gtk::Action::create("Simplify",
747                                       Stock::SIMPLIFY));
749     _act_grp->add(Gtk::Action::create("Reverse",
750                                       Stock::REVERSE));
752     _act_grp->add(Gtk::Action::create("Cleanup",
753                                       Gtk::Stock::CLEAR,
754                                       _("PLACEHOLDER, do not translate")));
756     // Text menu
757     _act_grp->add(Gtk::Action::create("TextProperties",
758                                       Gtk::Stock::SELECT_FONT, Glib::ustring(),
759                                       _("PLACEHOLDER, do not translate")),
760                   sigc::mem_fun(*this, &EditWidget::onDialogTextProperties));
762     _act_grp->add(Gtk::Action::create("PutOnPath",
763                                       Stock::PUT_ON_PATH));
765     _act_grp->add(Gtk::Action::create("RemoveFromPath",
766                                       Stock::REMOVE_FROM_PATH));
768     _act_grp->add(Gtk::Action::create("RemoveManualKerns",
769                                       Stock::REMOVE_MANUAL_KERNS));
771         // Whiteboard menu
772 #ifdef WITH_INKBOARD
773 #endif
775     // About menu
776     _act_grp->add(Gtk::Action::create("KeysAndMouse",
777                                       Stock::KEYS_MOUSE));
779     _act_grp->add(Gtk::Action::create("Tutorials",
780                                       Stock::TUTORIALS));
782     _act_grp->add(Gtk::Action::create("About",
783                                       Stock::ABOUT),
784                   sigc::mem_fun(*this, &EditWidget::onDialogAbout));
787 void
788 EditWidget::initToolbarActions()
790     // Tools bar
791     Gtk::RadioAction::Group tools;
793     _act_grp->add(Gtk::RadioAction::create(tools, "ToolSelect",
794                                            Stock::TOOL_SELECT, Glib::ustring(),
795                                            _("PLACEHOLDER, do not translate")),
796                   sigc::mem_fun(*this, &EditWidget::onSelectTool));
798     _act_grp->add(Gtk::RadioAction::create(tools, "ToolNode",
799                                            Stock::TOOL_NODE, Glib::ustring(),
800                                            _("PLACEHOLDER, do not translate")),
801                   sigc::mem_fun(*this, &EditWidget::onNodeTool));
803     _act_grp->add(Gtk::RadioAction::create(tools, "ToolZoom",
804                                            Stock::TOOL_ZOOM, Glib::ustring(),
805                                            _("PLACEHOLDER, do not translate")));
807     _act_grp->add(Gtk::RadioAction::create(tools, "ToolRect",
808                                            Stock::TOOL_RECT, Glib::ustring(),
809                                            _("PLACEHOLDER, do not translate")));
811     _act_grp->add(Gtk::RadioAction::create(tools, "ToolArc",
812                                            Stock::TOOL_ARC, Glib::ustring(),
813                                            _("PLACEHOLDER, do not translate")));
815     _act_grp->add(Gtk::RadioAction::create(tools, "ToolStar",
816                                            Stock::TOOL_STAR, Glib::ustring(),
817                                            _("PLACEHOLDER, do not translate")));
819     _act_grp->add(Gtk::RadioAction::create(tools, "ToolSpiral",
820                                            Stock::TOOL_SPIRAL, Glib::ustring(),
821                                            _("PLACEHOLDER, do not translate")));
823     _act_grp->add(Gtk::RadioAction::create(tools, "ToolFreehand",
824                                            Stock::TOOL_FREEHAND, Glib::ustring(),
825                                            _("PLACEHOLDER, do not translate")));
827     _act_grp->add(Gtk::RadioAction::create(tools, "ToolPen",
828                                            Stock::TOOL_PEN, Glib::ustring(),
829                                            _("PLACEHOLDER, do not translate")));
831     _act_grp->add(Gtk::RadioAction::create(tools, "ToolDynaDraw",
832                                            Stock::TOOL_DYNADRAW, Glib::ustring(),
833                                            _("PLACEHOLDER, do not translate")));
835     _act_grp->add(Gtk::RadioAction::create(tools, "ToolText",
836                                            Stock::TOOL_TEXT, Glib::ustring(),
837                                            _("PLACEHOLDER, do not translate")));
839     _act_grp->add(Gtk::RadioAction::create(tools, "ToolDropper",
840                                            Stock::TOOL_DROPPER, Glib::ustring(),
841                                            _("PLACEHOLDER, do not translate")));
843     // Select Controls bar
844     _act_grp->add(Gtk::ToggleAction::create("TransformStroke",
845                                             Stock::TRANSFORM_STROKE, Glib::ustring(),
846                                             _("PLACEHOLDER, do not translate")));
848     _act_grp->add(Gtk::ToggleAction::create("TransformCorners",
849                                             Stock::TRANSFORM_CORNERS, Glib::ustring(),
850                                             _("PLACEHOLDER, do not translate")));
852     _act_grp->add(Gtk::ToggleAction::create("TransformGradient",
853                                             Stock::TRANSFORM_GRADIENT, Glib::ustring(),
854                                             _("PLACEHOLDER, do not translate")));
856     _act_grp->add(Gtk::ToggleAction::create("TransformPattern",
857                                             Stock::TRANSFORM_PATTERN, Glib::ustring(),
858                                             _("PLACEHOLDER, do not translate")));
860     // Node Controls bar
861     _act_grp->add(Gtk::Action::create("NodeInsert",
862                                       Gtk::Stock::ADD, Glib::ustring(),
863                                       _("PLACEHOLDER, do not translate")));
865     _act_grp->add(Gtk::Action::create("NodeDelete",
866                                       Gtk::Stock::REMOVE, Glib::ustring(),
867                                       _("PLACEHOLDER, do not translate")));
869     _act_grp->add(Gtk::Action::create("NodeJoin",
870                                       Stock::NODE_JOIN, Glib::ustring(),
871                                       _("PLACEHOLDER, do not translate")));
873     _act_grp->add(Gtk::Action::create("NodeJoinSegment",
874                                       Stock::NODE_JOIN_SEGMENT, Glib::ustring(),
875                                       _("PLACEHOLDER, do not translate")));
877     _act_grp->add(Gtk::Action::create("NodeDeleteSegment",
878                                       Stock::NODE_DELETE_SEGMENT, Glib::ustring(),
879                                       _("PLACEHOLDER, do not translate")));
881     _act_grp->add(Gtk::Action::create("NodeBreak",
882                                       Stock::NODE_BREAK, Glib::ustring(),
883                                       _("PLACEHOLDER, do not translate")));
885     _act_grp->add(Gtk::Action::create("NodeCorner",
886                                       Stock::NODE_CORNER, Glib::ustring(),
887                                       _("PLACEHOLDER, do not translate")));
889     _act_grp->add(Gtk::Action::create("NodeSmooth",
890                                       Stock::NODE_SMOOTH, Glib::ustring(),
891                                       _("PLACEHOLDER, do not translate")));
893     _act_grp->add(Gtk::Action::create("NodeSymmetric",
894                                       Stock::NODE_SYMMETRIC, Glib::ustring(),
895                                       _("PLACEHOLDER, do not translate")));
897     _act_grp->add(Gtk::Action::create("NodeLine",
898                                       Stock::NODE_LINE, Glib::ustring(),
899                                       _("PLACEHOLDER, do not translate")));
901     _act_grp->add(Gtk::Action::create("NodeCurve",
902                                       Stock::NODE_CURVE, Glib::ustring(),
903                                       _("PLACEHOLDER, do not translate")));
906 void
907 EditWidget::initAccelMap()
909     gchar *filename = g_build_filename(INKSCAPE_UIDIR, "keybindings.rc", NULL);
910     Gtk::AccelMap::load(filename);
911     g_free(filename);
913     // One problem is that the keys 1-6 are zoom accelerators which get
914     // caught as accelerator _before_ any Entry input handler receives them,
915     // for example the zoom status. At the moment, the best way seems to
916     // disable them as accelerators when the Entry gets focus, and enable
917     // them when focus goes elsewhere. The code for this belongs here,
918     // and not in zoom-status.cpp .
920     _zoom_status.signal_focus_in_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusIn));
921     _zoom_status.signal_focus_out_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusOut));
924 bool
925 EditWidget::onEntryFocusIn (GdkEventFocus* ev)
927     Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
928     Gtk::AccelMap::change_entry ("<Actions>//Zoom100", 0, m, false);
929     Gtk::AccelMap::change_entry ("<Actions>//Zoom50", 0, m, false);
930     Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", 0, m, false);
931     Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", 0, m, false);
932     Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", 0, m, false);
933     Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", 0, m, false);
934     return false;
937 bool
938 EditWidget::onEntryFocusOut (GdkEventFocus* ev)
940     Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
941     Gtk::AccelMap::change_entry ("<Actions>//Zoom100", '1', m, false);
942     Gtk::AccelMap::change_entry ("<Actions>//Zoom50", '2', m, false);
943     Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", '3', m, false);
944     Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", '4', m, false);
945     Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", '5', m, false);
946     Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", '6', m, false);
947     return false;
950 void
951 EditWidget::initMenuBar()
953     g_assert(_ui_mgr);
954     Gtk::MenuBar *menu = static_cast<Gtk::MenuBar*>(_ui_mgr->get_widget("/MenuBar"));
955     g_assert(menu != NULL);
956     _main_window_table.attach(*Gtk::manage(menu), 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
959 void
960 EditWidget::initCommandsBar()
962     g_assert(_ui_mgr);
963     Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/CommandsBar")),
964                                Gtk::TOOLBAR_ICONS);
965     g_assert(bar != NULL);
966     _toolbars_vbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
969 void
970 EditWidget::initToolControlsBar()
972     // TODO: Do UIManager controlled widgets need to be deleted?
973     _select_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/SelectControlsBar"));
974     _node_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/NodeControlsBar"));
976     _tool_ctrl = new Toolbox(_select_ctrl, Gtk::TOOLBAR_ICONS);
978     _toolbars_vbox.pack_start(*Gtk::manage(_tool_ctrl), Gtk::PACK_SHRINK);
981 void
982 EditWidget::initUriBar()
984     /// \todo  Create an Inkscape::UI::Widget::UriBar class (?)
986     _uri_ctrl = new Gtk::Toolbar();
988     _uri_label.set_label(_("PLACEHOLDER, DO NOT TRANSLATE"));
989     _uri_ctrl->add(_uri_label);
990     _uri_ctrl->add(_uri_entry);
992     _uri_entry.signal_activate()
993         .connect_notify(sigc::mem_fun(*this, &EditWidget::onUriChanged));
995     _toolbars_vbox.pack_start(*Gtk::manage(_uri_ctrl), Gtk::PACK_SHRINK);
998 void
999 EditWidget::initToolsBar()
1001     Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/ToolsBar")),
1002                                Gtk::TOOLBAR_ICONS,
1003                                Gtk::ORIENTATION_VERTICAL);
1004     g_assert(bar != NULL);
1005     _sub_window_hbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
1008 void
1009 EditWidget::initTopRuler()
1011     _viewport_table.attach(_top_ruler,  1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1013     _tooltips.set_tip (_top_ruler, _top_ruler.get_tip());
1016 void
1017 EditWidget::initLeftRuler()
1019     _viewport_table.attach(_left_ruler, 0, 1, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1021     _tooltips.set_tip (_left_ruler, _left_ruler.get_tip());
1024 void
1025 EditWidget::initBottomScrollbar()
1027     _viewport_table.attach(_bottom_scrollbar, 1, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1028     _bottom_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1029     _bottom_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1032 void
1033 EditWidget::initRightScrollbar()
1035     _viewport_table.attach(_right_scrollbar, 2, 3, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1037     _right_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1038     _right_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1041 void
1042 EditWidget::initStickyZoom()
1044     _viewport_table.attach(_sticky_zoom, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
1046     _sticky_zoom.set_active (prefs_get_int_attribute ("options.stickyzoom", "value", 0) != 0);
1047     _tooltips.set_tip (_sticky_zoom, _("Zoom drawing if window size changes"));
1049     /// \todo icon not implemented
1052 void
1053 EditWidget::initStatusbar()
1055     _statusbar.pack_start (_selected_style_status, false, false, 1);
1056     _statusbar.pack_start (*new Gtk::VSeparator(), false, false, 0);
1058     _tooltips.set_tip (_zoom_status, _("Zoom"));
1060     _layer_selector.reference();
1061     _statusbar.pack_start (_layer_selector, false, false, 1);
1063     _coord_status.property_n_rows() = 2;
1064     _coord_status.property_n_columns() = 5;
1065     _coord_status.property_row_spacing() = 0;
1066     _coord_status.property_column_spacing() = 2;
1067     _coord_eventbox.add (_coord_status);
1068     _tooltips.set_tip (_coord_eventbox, _("Cursor coordinates"));
1069     _coord_status.attach (*new Gtk::VSeparator(), 0,1, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1070     _coord_status.attach (*new Gtk::Label("X:", 0.0, 0.5), 1,2, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1071     _coord_status.attach (*new Gtk::Label("Y:", 0.0, 0.5), 1,2, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1072     _coord_status_x.set_text ("0.0");
1073     _coord_status_x.set_alignment (0.0, 0.5);
1074     _coord_status_y.set_text ("0.0");
1075     _coord_status_y.set_alignment (0.0, 0.5);
1076     _coord_status.attach (_coord_status_x, 2,3, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1077     _coord_status.attach (_coord_status_y, 2,3, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1078     _coord_status.attach (*new Gtk::Label("Z:", 0.0, 0.5), 3,4, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1079     _coord_status.attach (_zoom_status, 4,5, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1080     sp_set_font_size_smaller (static_cast<GtkWidget*>((void*)_coord_status.gobj()));
1081     _statusbar.pack_end (_coord_eventbox, false, false, 1);
1083     _select_status.property_xalign() = 0.0;
1084     _select_status.property_yalign() = 0.5;
1085     _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."));
1086     // include this again with Gtk+-2.6
1087 #if GTK_VERSION_GE(2,6)
1088      gtk_label_set_ellipsize (GTK_LABEL(_select_status.gobj()), PANGO_ELLIPSIZE_END);
1089 #endif
1090     _select_status.set_size_request (1, -1);
1091     _statusbar.pack_start (_select_status, true, true, 0);
1093     _main_window_table.attach(_statusbar, 0, 1, 3, 4, Gtk::FILL, Gtk::SHRINK);
1096 //========================================
1097 //----------implements EditWidgetInterface
1099 void *
1100 EditWidget::getWindow()
1102     return this;
1105 void
1106 EditWidget::setTitle (gchar const* new_title)
1108     set_title (new_title);
1111 void
1112 EditWidget::layout()
1114    show_all_children();
1117 void
1118 EditWidget::present()
1120     this->Gtk::Window::present();
1123 void
1124 EditWidget::getGeometry (gint &x, gint &y, gint &w, gint &h)
1126     get_position (x, y);
1127     get_size (w, h);
1130 void
1131 EditWidget::setSize (gint w, gint h)
1133     resize (w, h);
1136 void
1137 EditWidget::setPosition (NR::Point p)
1139     move (int(p[NR::X]), int(p[NR::Y]));
1142 /// \param p is already gobj()!
1143 void
1144 EditWidget::setTransient (void* p, int i)
1146 #ifndef WIN32
1147     gtk_window_set_transient_for (static_cast<GtkWindow*>(p), this->gobj());
1148     if (i==2)
1149         this->Gtk::Window::present();
1150 #endif
1153 NR::Point
1154 EditWidget::getPointer()
1156     int x, y;
1157     get_pointer (x, y);
1158     return NR::Point (x, y);
1161 void
1162 EditWidget::setFullscreen()
1164     fullscreen();
1167 /**
1168  *  Shuts down the desktop object for the view being closed.  It checks
1169  *  to see if the document has been edited, and if so prompts the user
1170  *  to save, discard, or cancel.  Returns TRUE if the shutdown operation
1171  *  is cancelled or if the save is cancelled or fails, FALSE otherwise.
1172  */
1173 bool
1174 EditWidget::shutdown()
1176     g_assert (_desktop != NULL);
1177     if (Inkscape::NSApplication::Editor::isDuplicatedView (_desktop))
1178         return false;
1180     SPDocument *doc = _desktop->doc();
1181     if (sp_document_repr_root(doc)->attribute("sodipodi:modified") != NULL)
1182     {
1183         gchar *markup;
1184         /// \todo FIXME !!! obviously this will have problems if the document
1185         /// name contains markup characters
1186         markup = g_strdup_printf(
1187                 _("<span weight=\"bold\" size=\"larger\">Save changes to document \"%s\" before closing?</span>\n\n"
1188                   "If you close without saving, your changes will be discarded."),
1189                 SP_DOCUMENT_NAME(doc));
1191         Gtk::MessageDialog dlg (*this,
1192                        markup,
1193                        true,
1194                        Gtk::MESSAGE_WARNING,
1195                        Gtk::BUTTONS_NONE,
1196                        true);
1197         g_free(markup);
1198         Gtk::Button close_button (_("Close _without saving"), true);
1199         dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1200         close_button.show();
1201         dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1202         dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1203         dlg.set_default_response (Gtk::RESPONSE_YES);
1205         int response = dlg.run();
1206         switch (response)
1207         {
1208             case Gtk::RESPONSE_YES:
1209                 sp_document_ref(doc);
1210                 if (sp_file_save_document(doc)) {
1211                     sp_document_unref(doc);
1212                 } else { // save dialog cancelled or save failed
1213                     sp_document_unref(doc);
1214                     return TRUE;
1215                 }
1216                 break;
1217             case Gtk::RESPONSE_NO:
1218                 break;
1219             default: // cancel pressed, or dialog was closed
1220                 return TRUE;
1221                 break;
1222         }
1223     }
1225     /* Code to check data loss */
1226     bool allow_data_loss = FALSE;
1227     while (sp_document_repr_root(doc)->attribute("inkscape:dataloss") != NULL && allow_data_loss == FALSE)
1228     {
1229         gchar *markup;
1230         /// \todo FIXME !!! obviously this will have problems if the document
1231         /// name contains markup characters
1232         markup = g_strdup_printf(
1233                 _("<span weight=\"bold\" size=\"larger\">The file \"%s\" was saved with a format (%s) that may cause data loss!</span>\n\n"
1234                   "Do you want to save this file in another format?"),
1235                 SP_DOCUMENT_NAME(doc),
1236                 Inkscape::Extension::db.get(sp_document_repr_root(doc)->attribute("inkscape:output_extension"))->get_name());
1238         Gtk::MessageDialog dlg (*this,
1239                        markup,
1240                        true,
1241                        Gtk::MESSAGE_WARNING,
1242                        Gtk::BUTTONS_NONE,
1243                        true);
1244         g_free(markup);
1245         Gtk::Button close_button (_("Close _without saving"), true);
1246         dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1247         close_button.show();
1248         dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1249         dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1250         dlg.set_default_response (Gtk::RESPONSE_YES);
1252         int response = dlg.run();
1254         switch (response)
1255         {
1256             case Gtk::RESPONSE_YES:
1257                 sp_document_ref(doc);
1258                 if (sp_file_save_document(doc)) {
1259                     sp_document_unref(doc);
1260                 } else { // save dialog cancelled or save failed
1261                     sp_document_unref(doc);
1262                     return TRUE;
1263                 }
1264                 break;
1265             case Gtk::RESPONSE_NO:
1266                 allow_data_loss = TRUE;
1267                 break;
1268             default: // cancel pressed, or dialog was closed
1269                 return TRUE;
1270                 break;
1271         }
1272     }
1274     return false;
1278 void
1279 EditWidget::destroy()
1281     delete this;
1284 void
1285 EditWidget::requestCanvasUpdate()
1287     _svg_canvas.widget().queue_draw();
1290 void
1291 EditWidget::activateDesktop()
1293     /// \todo active_desktop_indicator not implemented
1296 void
1297 EditWidget::deactivateDesktop()
1299     /// \todo active_desktop_indicator not implemented
1302 void
1303 EditWidget::viewSetPosition (NR::Point p)
1305     p -= _namedview->gridorigin;
1306     double lo, up, pos, max;
1307     _top_ruler.get_range (lo, up, pos, max);
1308     _top_ruler.set_range (lo, up, p[NR::X], max);
1309     _left_ruler.get_range (lo, up, pos, max);
1310     _left_ruler.set_range (lo, up, p[NR::Y], max);
1313 void
1314 EditWidget::updateRulers()
1316     NR::Point origin = _namedview->gridorigin;
1318     NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1319     double lo, up, pos, max;
1320     double const scale = _desktop->current_zoom();
1321     double s = viewbox.min()[NR::X] / scale - origin[NR::X];
1322     double e = viewbox.max()[NR::X] / scale - origin[NR::X];
1323     _top_ruler.get_range(lo, up, pos, max);
1324     _top_ruler.set_range(s, e, pos, e);
1325     s = viewbox.min()[NR::Y] / -scale - origin[NR::Y];
1326     e = viewbox.max()[NR::Y] / -scale - origin[NR::Y];
1327     _left_ruler.set_range(s, e, origin[NR::Y], e);
1328     /// \todo is that correct?
1331 void
1332 EditWidget::updateScrollbars (double scale)
1334     // do not call this function before canvas has its size allocated
1335     if (!is_realized() || _update_s_f) {
1336         return;
1337     }
1339     _update_s_f = true;
1341     /* The desktop region we always show unconditionally */
1342     SPDocument *doc = _desktop->doc();
1343     NR::Rect const r = sp_item_bbox_desktop(SP_ITEM(SP_DOCUMENT_ROOT(doc)));
1344     NR::Rect darea(NR::Point(MIN(r.min()[NR::X], -sp_document_width(doc)),
1345                              MIN(r.min()[NR::Y], -sp_document_height(doc))),
1346                    NR::Point(MAX(r.max()[NR::X], 2 * sp_document_width(doc)),
1347                              MAX(r.max()[NR::Y], 2 * sp_document_height(doc))));
1349     /* Canvas region we always show unconditionally */
1350     NR::Rect carea(NR::Point(darea.min()[NR::X] * scale - 64,
1351                              darea.max()[NR::Y] * -scale - 64),
1352                    NR::Point(darea.max()[NR::X] * scale + 64,
1353                              darea.min()[NR::Y] * -scale + 64));
1355     NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1357     /* Viewbox is always included into scrollable region */
1358     carea = NR::Rect::union_bounds(carea, viewbox);
1360     Gtk::Adjustment *adj = _bottom_scrollbar.get_adjustment();
1361     adj->set_value(viewbox.min()[NR::X]);
1362     adj->set_lower(carea.min()[NR::X]);
1363     adj->set_upper(carea.max()[NR::X]);
1364     adj->set_page_increment(viewbox.dimensions()[NR::X]);
1365     adj->set_step_increment(0.1 * (viewbox.dimensions()[NR::X]));
1366     adj->set_page_size(viewbox.dimensions()[NR::X]);
1368     adj = _right_scrollbar.get_adjustment();
1369     adj->set_value(viewbox.min()[NR::Y]);
1370     adj->set_lower(carea.min()[NR::Y]);
1371     adj->set_upper(carea.max()[NR::Y]);
1372     adj->set_page_increment(viewbox.dimensions()[NR::Y]);
1373     adj->set_step_increment(0.1 * viewbox.dimensions()[NR::Y]);
1374     adj->set_page_size(viewbox.dimensions()[NR::Y]);
1376     _update_s_f = false;
1379 void
1380 EditWidget::toggleRulers()
1382     if (_top_ruler.is_visible())
1383     {
1384         _top_ruler.hide_all();
1385         _left_ruler.hide_all();
1386         prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 0);
1387     } else {
1388         _top_ruler.show_all();
1389         _left_ruler.show_all();
1390         prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 1);
1391     }
1394 void
1395 EditWidget::toggleScrollbars()
1397     if (_bottom_scrollbar.is_visible())
1398     {
1399         _bottom_scrollbar.hide_all();
1400         _right_scrollbar.hide_all();
1401         prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 0);
1402     } else {
1403         _bottom_scrollbar.show_all();
1404         _right_scrollbar.show_all();
1405         prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 1);
1406     }
1409 void
1410 EditWidget::updateZoom()
1412     _zoom_status.update();
1415 void
1416 EditWidget::letZoomGrabFocus()
1418     _zoom_status.grab_focus();
1421 void
1422 EditWidget::setToolboxFocusTo (const gchar *)
1424     /// \todo not implemented
1427 void
1428 EditWidget::setToolboxAdjustmentValue (const gchar *, double)
1430     /// \todo not implemented
1433 bool
1434 EditWidget::isToolboxButtonActive (gchar const*)
1436     /// \todo not implemented
1437     return true;
1440 void
1441 EditWidget::setCoordinateStatus (NR::Point p)
1443     gchar *cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::X]);
1444     _coord_status_x.property_label() = cstr;
1445     g_free (cstr);
1446     cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::Y]);
1447     _coord_status_y.property_label() = cstr;
1448     g_free (cstr);
1451 void
1452 EditWidget::setMessage (Inkscape::MessageType type, gchar const* msg)
1454     _select_status.set_markup (msg? msg : "");
1457 bool
1458 EditWidget::warnDialog (gchar* msg)
1460     Gtk::MessageDialog dlg (*this,
1461                        msg,
1462                        true,
1463                        Gtk::MESSAGE_WARNING,
1464                        Gtk::BUTTONS_YES_NO,
1465                        true);
1466     int r = dlg.run();
1467     return r == Gtk::RESPONSE_YES;
1471 /// \todo make this a member function when the signal is a sigc++ signal
1472 void _namedview_modified (SPNamedView* nv, guint flags, EditWidget* ew)
1474     if (flags & SP_OBJECT_MODIFIED_FLAG)
1475     {
1476         ew->_dt2r = 1.0 / nv->doc_units->unittobase;
1477         ew->_top_ruler.update_metric();
1478         ew->_left_ruler.update_metric();
1479         ew->_tooltips.set_tip (ew->_top_ruler, ew->_top_ruler.get_tip());
1480         ew->_tooltips.set_tip (ew->_left_ruler, ew->_left_ruler.get_tip());
1481         ew->updateRulers();
1482     }
1485 void
1486 EditWidget::initEdit (SPDocument *doc)
1488     _desktop = new SPDesktop();
1489     _desktop->registerEditWidget (this);
1491     _namedview = sp_document_namedview (doc, 0);
1492     _svg_canvas.init (_desktop);
1493     _desktop->init (_namedview, _svg_canvas.spobj());
1494     sp_namedview_window_from_document (_desktop);
1495     _dt2r = 1.0 / _namedview->doc_units->unittobase;
1497     /// \todo convert to sigc++ when SPObject hierarchy gets converted
1498     /* Listen on namedview modification */
1499     g_signal_connect (G_OBJECT (_desktop->namedview), "modified",
1500         G_CALLBACK (_namedview_modified), this);
1501     _layer_selector.setDesktop (_desktop);
1502     _selected_style_status.setDesktop (_desktop);
1504     Inkscape::NSApplication::Editor::addDesktop (_desktop);
1506     _zoom_status.init (_desktop);
1507     _top_ruler.init (_desktop, _svg_canvas.widget());
1508     _left_ruler.init (_desktop, _svg_canvas.widget());
1509     updateRulers();
1512 void
1513 EditWidget::destroyEdit()
1515     if (_desktop) {
1516         _layer_selector.unreference();
1517         Inkscape::NSApplication::Editor::removeDesktop (_desktop); // clears selection too
1518         sp_signal_disconnect_by_data (G_OBJECT (_desktop->namedview), this);
1519         _desktop->destroy();
1520         Inkscape::GC::release (_desktop);
1521         _desktop = 0;
1522     }
1525 //----------end of EditWidgetInterface implementation
1527 //----------start of other callbacks
1529 bool
1530 EditWidget::on_key_press_event (GdkEventKey* event)
1532     // this is the original code from helper/window.cpp
1534     unsigned int shortcut;
1535     shortcut = get_group0_keyval (event) |
1536                    ( event->state & GDK_SHIFT_MASK ?
1537                      SP_SHORTCUT_SHIFT_MASK : 0 ) |
1538                    ( event->state & GDK_CONTROL_MASK ?
1539                      SP_SHORTCUT_CONTROL_MASK : 0 ) |
1540                    ( event->state & GDK_MOD1_MASK ?
1541                      SP_SHORTCUT_ALT_MASK : 0 );
1542     return sp_shortcut_invoke (shortcut,
1543                              Inkscape::NSApplication::Editor::getActiveDesktop());
1546 bool
1547 EditWidget::on_delete_event (GdkEventAny*)
1549     return shutdown();
1552 bool
1553 EditWidget::on_focus_in_event (GdkEventFocus*)
1555     Inkscape::NSApplication::Editor::activateDesktop (_desktop);
1556     _svg_canvas.widget().grab_focus();
1558     return false;
1561 void
1562 EditWidget::onWindowSizeAllocate (Gtk::Allocation &newall)
1564     if (!is_realized()) return;
1566     const Gtk::Allocation& all = get_allocation();
1567     if ((newall.get_x() == all.get_x()) &&
1568         (newall.get_y() == all.get_y()) &&
1569         (newall.get_width() == all.get_width()) &&
1570         (newall.get_height() == all.get_height())) {
1571         return;
1572     }
1574     NR::Rect const area = _desktop->get_display_area();
1575     double zoom = _desktop->current_zoom();
1577     if (_sticky_zoom.get_active()) {
1578         /* Calculate zoom per pixel */
1579         double const zpsp = zoom / hypot(area.dimensions()[NR::X], area.dimensions()[NR::Y]);
1580         /* Find new visible area */
1581         NR::Rect const newarea = _desktop->get_display_area();
1582         /* Calculate adjusted zoom */
1583         zoom = zpsp * hypot(newarea.dimensions()[NR::X], newarea.dimensions()[NR::Y]);
1584     }
1586     _desktop->zoom_absolute(area.midpoint()[NR::X], area.midpoint()[NR::Y], zoom);
1589 void
1590 EditWidget::onWindowRealize()
1592     NR::Rect d(NR::Point(0, 0),
1593                NR::Point(sp_document_width(_desktop->doc()), sp_document_height(_desktop->doc())));
1595     if (fabs(d.dimensions()[NR::X]) < 1.0 || fabs(d.dimensions()[NR::Y]) < 1.0) {
1596         return;
1597     }
1599     _desktop->set_display_area(d.min()[NR::X], d.min()[NR::Y], d.max()[NR::X], d.max()[NR::Y], 10);
1600     _namedview_modified(_desktop->namedview, SP_OBJECT_MODIFIED_FLAG, this);
1601     setTitle (SP_DOCUMENT_NAME(_desktop->doc()));
1604 void
1605 EditWidget::onAdjValueChanged()
1607     if (_update_a_f) return;
1608     _update_a_f = true;
1610     sp_canvas_scroll_to (_svg_canvas.spobj(),
1611                          _bottom_scrollbar.get_value(),
1612                          _right_scrollbar.get_value(),
1613                          false);
1614     updateRulers();
1616     _update_a_f = false;
1620 } // namespace View
1621 } // namespace UI
1622 } // namespace Inkscape
1624 /*
1625   Local Variables:
1626   mode:c++
1627   c-file-style:"stroustrup"
1628   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1629   indent-tabs-mode:nil
1630   fill-column:99
1631   End:
1632 */
1633 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :