Code

add a way to set a radio toggle in aux toolbar via desktop, by the toggles id
[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  *   John Bintz <jcoswell@coswellproductions.org>
20  *   Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
21  *
22  * Copyright (C) 2007 Johan Engelen
23  * Copyright (C) 2006 John Bintz
24  * Copyright (C) 1999-2005 Authors
25  * Copyright (C) 2000-2001 Ximian, Inc.
26  *
27  * Released under GNU GPL.  Read the file 'COPYING' for more information.
28  */
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
34 #include <gtk/gtkwindow.h>
35 #include <gtk/gtkversion.h>
36 #include <gtk/gtklabel.h>
37 #include <gtkmm/radioaction.h>
38 #include <gtkmm/menubar.h>
39 #include <gtkmm/messagedialog.h>
40 #include <gtkmm/stock.h>
41 #include <gtkmm/accelmap.h>
42 #include <gtkmm/separator.h>
43 #include <gtkmm/base.h>
45 #include <sigc++/functors/mem_fun.h>
47 #include "macros.h"
48 #include "path-prefix.h"
49 #include "prefs-utils.h"
50 #include "file.h"
51 #include "application/editor.h"
52 #include "edit-widget.h"
53 #include "ui/stock.h"
54 #include "ui/stock-items.h"
55 #include "ui/icons.h"
57 #include "display/sodipodi-ctrlrect.h"
58 #include "helper/units.h"
59 #include "shortcuts.h"
60 #include "widgets/spw-utilities.h"
61 #include "event-context.h"
62 #include "document.h"
63 #include "sp-namedview.h"
64 #include "sp-item.h"
65 #include "interface.h"
66 #include "extension/db.h"
68 using namespace Inkscape::UI;
69 using namespace Inkscape::UI::Widget;
71 namespace Inkscape {
72 namespace UI {
73 namespace View {
75 EditWidget::EditWidget (SPDocument *doc)
76     : _main_window_table(4),
77       _viewport_table(3,3),
78       _act_grp(Gtk::ActionGroup::create()),
79       _ui_mgr(Gtk::UIManager::create()),
80       _update_s_f(false),
81       _update_a_f(false),
82       _interaction_disabled_counter(0)
83 {
84     g_warning("Creating new EditWidget");
86     _desktop = 0;
87     Icons::init();
88     Stock::init();
89     initActions();
90     initAccelMap();
91     initUIManager();
92     initLayout();
93     initEdit (doc);
94     g_warning("Done creating new EditWidget");
95 }
97 EditWidget::~EditWidget()
98 {
99     destroyEdit();
102 void
103 EditWidget::initActions()
105     initMenuActions();
106     initToolbarActions();
109 void
110 EditWidget::initUIManager()
112     _ui_mgr->insert_action_group(_act_grp);
113     add_accel_group(_ui_mgr->get_accel_group());
115     gchar *filename_utf8 = g_build_filename(INKSCAPE_UIDIR, "menus-bars.xml", NULL);
116     if (_ui_mgr->add_ui_from_file(filename_utf8) == 0) {
117         g_warning("Error merging ui from file '%s'", filename_utf8);
118         // fixme-charset: What charset should we pass to g_warning?
119     }
120     g_free(filename_utf8);
123 void
124 EditWidget::initLayout()
126     set_title("New document 1 - Inkscape");
127     set_resizable();
128     set_default_size(640, 480);
130     // top level window into which all other portions of the UI get inserted
131     add(_main_window_table);
132     // attach box for horizontal toolbars
133     _main_window_table.attach(_toolbars_vbox, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
134     // attach sub-window for viewport and vertical toolbars
135     _main_window_table.attach(_sub_window_hbox, 0, 1, 2, 3);
136     // viewport table with 3 rows by 3 columns
137     _sub_window_hbox.pack_end(_viewport_table);
139     // Menus and Bars
140     initMenuBar();
141     initCommandsBar();
142     initToolControlsBar();
143     initUriBar();
144     initToolsBar();
146     // Canvas Viewport
147     initLeftRuler();
148     initTopRuler();
149     initStickyZoom();
150     initBottomScrollbar();
151     initRightScrollbar();
152     _viewport_table.attach(_svg_canvas.widget(), 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
153     _svg_canvas.widget().show_all();
156     // The statusbar comes last and appears at the bottom of _main_window_table
157     initStatusbar();
159     signal_size_allocate().connect (sigc::mem_fun (*this, &EditWidget::onWindowSizeAllocate), false);
160     signal_realize().connect (sigc::mem_fun (*this, &EditWidget::onWindowRealize));
161     show_all_children();
164 void
165 EditWidget::onMenuItem()
167     g_warning("onMenuItem called");
170 void
171 EditWidget::onActionFileNew()
173 //    g_warning("onActionFileNew called");
174     sp_file_new_default();
177 void
178 EditWidget::onActionFileOpen()
180 //    g_warning("onActionFileOpen called");
181     sp_file_open_dialog (*this, NULL, NULL);
184 void
185 EditWidget::onActionFileQuit()
187     g_warning("onActionFileQuit");
188     sp_ui_close_all();
191 void
192 EditWidget::onActionFilePrint()
194     g_warning("onActionFilePrint");
197 void
198 EditWidget::onToolbarItem()
200     g_warning("onToolbarItem called");
203 void
204 EditWidget::onSelectTool()
206     _tool_ctrl->remove();
207     _tool_ctrl->add(*_select_ctrl);
210 void
211 EditWidget::onNodeTool()
213     _tool_ctrl->remove();
214     _tool_ctrl->add(*_node_ctrl);
217 void
218 EditWidget::onDialogInkscapePreferences()
220     _dlg_mgr.showDialog("InkscapePreferences");
223 void
224 EditWidget::onDialogAbout()
228 void
229 EditWidget::onDialogAlignAndDistribute()
231     _dlg_mgr.showDialog("AlignAndDistribute");
234 void
235 EditWidget::onDialogDocumentProperties()
237 //    manage (Inkscape::UI::Dialog::DocumentPreferences::create());
238     _dlg_mgr.showDialog("DocumentPreferences");
241 void
242 EditWidget::onDialogExport()
244     _dlg_mgr.showDialog("Export");
247 void
248 EditWidget::onDialogExtensionEditor()
250     _dlg_mgr.showDialog("ExtensionEditor");
253 void
254 EditWidget::onDialogFillAndStroke()
256     _dlg_mgr.showDialog("FillAndStroke");
259 void
260 EditWidget::onDialogFind()
262     _dlg_mgr.showDialog("Find");
265 void
266 EditWidget::onDialogLayerEditor()
268     _dlg_mgr.showDialog("LayerEditor");
271 void
272 EditWidget::onDialogMessages()
274     _dlg_mgr.showDialog("Messages");
277 void
278 EditWidget::onDialogObjectProperties()
280     _dlg_mgr.showDialog("ObjectProperties");
283 void
284 EditWidget::onDialogTextProperties()
286     _dlg_mgr.showDialog("TextProperties");
289 void
290 EditWidget::onDialogTrace()
294 void
295 EditWidget::onDialogTransformation()
297     _dlg_mgr.showDialog("Transformation");
300 void
301 EditWidget::onDialogXmlEditor()
303     _dlg_mgr.showDialog("XmlEditor");
306 void
307 EditWidget::onUriChanged()
309     g_message("onUriChanged called");
313 // FIXME: strings are replaced by placeholders, NOT to be translated until the code is enabled
314 // See http://sourceforge.net/mailarchive/message.php?msg_id=11746016 for details
316 void
317 EditWidget::initMenuActions()
319 //    _act_grp->add(Gtk::Action::create("MenuFile",   _("PLACEHOLDER, do not translate")));
320 //    _act_grp->add(Gtk::Action::create("MenuEdit",   _("PLACEHOLDER, do not translate")));
321 //    _act_grp->add(Gtk::Action::create("MenuView",   _("PLACEHOLDER, do not translate")));
322 //    _act_grp->add(Gtk::Action::create("MenuLayer",  _("PLACEHOLDER, do not translate")));
323 //    _act_grp->add(Gtk::Action::create("MenuObject", _("PLACEHOLDER, do not translate")));
324 //    _act_grp->add(Gtk::Action::create("MenuPath",   _("PLACEHOLDER, do not translate")));
325 //    _act_grp->add(Gtk::Action::create("MenuText",   _("PLACEHOLDER, do not translate")));
326 //    _act_grp->add(Gtk::Action::create("MenuHelp",   _("PLACEHOLDER, do not translate")));
327 // temporarily replaced with non-gettext version to have a well-sized menu
328 // for testing:
330     _act_grp->add(Gtk::Action::create("MenuFile",   "File"));
331     _act_grp->add(Gtk::Action::create("MenuEdit",   "Edit"));
332     _act_grp->add(Gtk::Action::create("MenuView",   "View"));
333     _act_grp->add(Gtk::Action::create("MenuLayer",  "Layer"));
334     _act_grp->add(Gtk::Action::create("MenuObject", "Object"));
335     _act_grp->add(Gtk::Action::create("MenuPath",   "Path"));
336     _act_grp->add(Gtk::Action::create("MenuText",   "Text"));
337     _act_grp->add(Gtk::Action::create("MenuHelp",   "Help"));
339     // File menu
340     _act_grp->add(Gtk::Action::create("New",
341                                       Gtk::Stock::NEW, Glib::ustring(),
342                                       _("PLACEHOLDER, do not translate")),
343                   sigc::mem_fun(*this, &EditWidget::onActionFileNew));
345     _act_grp->add(Gtk::Action::create("Open",
346                                       Gtk::Stock::OPEN, Glib::ustring(),
347                                       _("PLACEHOLDER, do not translate")),
348                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
350     _act_grp->add(Gtk::Action::create("OpenRecent",
351                                       Stock::OPEN_RECENT));
353     _act_grp->add(Gtk::Action::create("Revert",
354                                       Gtk::Stock::REVERT_TO_SAVED, Glib::ustring(),
355                                       _("PLACEHOLDER, do not translate")),
356                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
358     _act_grp->add(Gtk::Action::create("Save",
359                                       Gtk::Stock::SAVE, Glib::ustring(),
360                                       _("PLACEHOLDER, do not translate")),
361                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
363     _act_grp->add(Gtk::Action::create("SaveAs",
364                                       Gtk::Stock::SAVE_AS, Glib::ustring(),
365                                       _("PLACEHOLDER, do not translate")),
366                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
368     _act_grp->add(Gtk::Action::create("Import",
369                                       Stock::IMPORT, Glib::ustring(),
370                                       _("PLACEHOLDER, do not translate")),
371                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
373     _act_grp->add(Gtk::Action::create("Export",
374                                       Stock::EXPORT, Glib::ustring(),
375                                       _("PLACEHOLDER, do not translate")),
376                   sigc::mem_fun(*this, &EditWidget::onDialogExport));
378     _act_grp->add(Gtk::Action::create("Print",
379                                       Gtk::Stock::PRINT, Glib::ustring(),
380                                       _("PLACEHOLDER, do not translate")),
381                   sigc::mem_fun(*this, &EditWidget::onActionFilePrint));
383     _act_grp->add(Gtk::Action::create("PrintPreview",
384                                       Gtk::Stock::PRINT_PREVIEW),
385                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
387     _act_grp->add(Gtk::Action::create("VacuumDefs",
388                                       Stock::VACUUM_DEFS),
389                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
391     _act_grp->add(Gtk::Action::create("DocumentProperties",
392                                       Gtk::Stock::PROPERTIES, Glib::ustring(),
393                                       _("PLACEHOLDER, do not translate")),
394                   sigc::mem_fun(*this, &EditWidget::onDialogDocumentProperties));
396     _act_grp->add(Gtk::Action::create("InkscapePreferences",
397                                       Gtk::Stock::PREFERENCES, Glib::ustring(),
398                                       _("PLACEHOLDER, do not translate")),
399                   sigc::mem_fun(*this, &EditWidget::onDialogInkscapePreferences));
401     _act_grp->add(Gtk::Action::create("Close",
402                                       Gtk::Stock::CLOSE),
403                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
405     _act_grp->add(Gtk::Action::create("Quit",
406                                       Gtk::Stock::QUIT),
407                   sigc::mem_fun(*this, &EditWidget::onActionFileQuit));
409     // EditWidget menu
410     _act_grp->add(Gtk::Action::create("Undo",
411                                       Gtk::Stock::UNDO, Glib::ustring(),
412                                       _("PLACEHOLDER, do not translate")));
414     _act_grp->add(Gtk::Action::create("Redo",
415                                       Gtk::Stock::REDO, Glib::ustring(),
416                                       _("PLACEHOLDER, do not translate")));
418     _act_grp->add(Gtk::Action::create("UndoHistory",
419                                       Stock::UNDO_HISTORY, Glib::ustring(),
420                                       _("PLACEHOLDER, do not translate")));
422     _act_grp->add(Gtk::Action::create("Cut",
423                                       Gtk::Stock::CUT, Glib::ustring(),
424                                       _("PLACEHOLDER, do not translate")));
426     _act_grp->add(Gtk::Action::create("Copy",
427                                       Gtk::Stock::COPY, Glib::ustring(),
428                                       _("PLACEHOLDER, do not translate")));
430     _act_grp->add(Gtk::Action::create("Paste",
431                                       Gtk::Stock::PASTE, Glib::ustring(),
432                                       _("PLACEHOLDER, do not translate")));
434     _act_grp->add(Gtk::Action::create("PasteInPlace",
435                                       Stock::PASTE_IN_PLACE));
437     _act_grp->add(Gtk::Action::create("PasteStyle",
438                                       Stock::PASTE_STYLE));
440     _act_grp->add(Gtk::Action::create("Find",
441                                       Gtk::Stock::FIND),
442                   sigc::mem_fun(*this, &EditWidget::onDialogFind));
444     _act_grp->add(Gtk::Action::create("Duplicate",
445                                       Stock::DUPLICATE, Glib::ustring(),
446                                       _("PLACEHOLDER, do not translate")));
448     _act_grp->add(Gtk::Action::create("Clone",
449                                       Stock::CLONE, Glib::ustring(),
450                                       _("PLACEHOLDER, do not translate")));
452     _act_grp->add(Gtk::Action::create("CloneUnlink",
453                                       Stock::CLONE_UNLINK, Glib::ustring(),
454                                       _("PLACEHOLDER, do not translate")));
456     _act_grp->add(Gtk::Action::create("CloneSelectOrig",
457                                       Stock::CLONE_SELECT_ORIG));
459     _act_grp->add(Gtk::Action::create("MakeBitmap",
460                                       Stock::MAKE_BITMAP));
462     _act_grp->add(Gtk::Action::create("Tile",
463                                      Stock::TILE));
465     _act_grp->add(Gtk::Action::create("Untile",
466                                       Stock::UNTILE));
468     _act_grp->add(Gtk::Action::create("Delete",
469                                       Gtk::Stock::DELETE));
471     _act_grp->add(Gtk::Action::create("SelectAll",
472                                       Stock::SELECT_ALL));
474     _act_grp->add(Gtk::Action::create("SelectAllInAllLayers",
475                                       Stock::SELECT_ALL_IN_ALL_LAYERS));
477     _act_grp->add(Gtk::Action::create("SelectInvert",
478                                       Stock::SELECT_INVERT));
480     _act_grp->add(Gtk::Action::create("SelectNone",
481                                       Stock::SELECT_NONE));
483     _act_grp->add(Gtk::Action::create("XmlEditor",
484                                       Stock::XML_EDITOR, Glib::ustring(),
485                                       _("PLACEHOLDER, do not translate")),
486                   sigc::mem_fun(*this, &EditWidget::onDialogXmlEditor));
488     // View menu
489     _act_grp->add(Gtk::Action::create("Zoom",
490                                       Stock::ZOOM));
492     _act_grp->add(Gtk::Action::create("ZoomIn",
493                                       Stock::ZOOM_IN, Glib::ustring(),
494                                       _("PLACEHOLDER, do not translate")));
496     _act_grp->add(Gtk::Action::create("ZoomOut",
497                                       Stock::ZOOM_OUT, Glib::ustring(),
498                                       _("PLACEHOLDER, do not translate")));
500     _act_grp->add(Gtk::Action::create("Zoom100",
501                                       Stock::ZOOM_100, Glib::ustring(),
502                                       _("PLACEHOLDER, do not translate")));
504     _act_grp->add(Gtk::Action::create("Zoom50",
505                                       Stock::ZOOM_50, Glib::ustring(),
506                                       _("PLACEHOLDER, do not translate")));
508     _act_grp->add(Gtk::Action::create("Zoom200",
509                                       Stock::ZOOM_200, Glib::ustring(),
510                                       _("PLACEHOLDER, do not translate")));
512     _act_grp->add(Gtk::Action::create("ZoomSelection",
513                                       Stock::ZOOM_SELECTION, Glib::ustring(),
514                                       _("PLACEHOLDER, do not translate")));
516     _act_grp->add(Gtk::Action::create("ZoomDrawing",
517                                       Stock::ZOOM_DRAWING, Glib::ustring(),
518                                       _("PLACEHOLDER, do not translate")));
520     _act_grp->add(Gtk::Action::create("ZoomPage",
521                                       Stock::ZOOM_PAGE, Glib::ustring(),
522                                       _("PLACEHOLDER, do not translate")));
524     _act_grp->add(Gtk::Action::create("ZoomWidth",
525                                       Stock::ZOOM_WIDTH, Glib::ustring(),
526                                       _("PLACEHOLDER, do not translate")));
528     _act_grp->add(Gtk::Action::create("ZoomPrev",
529                                       Stock::ZOOM_PREV, Glib::ustring(),
530                                       _("PLACEHOLDER, do not translate")));
532     _act_grp->add(Gtk::Action::create("ZoomNext",
533                                       Stock::ZOOM_NEXT, Glib::ustring(),
534                                       _("PLACEHOLDER, do not translate")));
536     _act_grp->add(Gtk::Action::create("ShowHide",
537                                       Stock::SHOW_HIDE));
539     _act_grp->add(Gtk::ToggleAction::create("ShowHideCommandsBar",
540                                             Stock::SHOW_HIDE_COMMANDS_BAR));
542     _act_grp->add(Gtk::ToggleAction::create("ShowHideToolControlsBar",
543                                             Stock::SHOW_HIDE_TOOL_CONTROLS_BAR));
545     _act_grp->add(Gtk::ToggleAction::create("ShowHideToolsBar",
546                                             Stock::SHOW_HIDE_TOOLS_BAR));
548     _act_grp->add(Gtk::ToggleAction::create("ShowHideRulers",
549                                             Stock::SHOW_HIDE_RULERS));
551     _act_grp->add(Gtk::ToggleAction::create("ShowHideScrollbars",
552                                             Stock::SHOW_HIDE_SCROLLBARS));
554     _act_grp->add(Gtk::ToggleAction::create("ShowHideStatusbar",
555                                             Stock::SHOW_HIDE_STATUSBAR));
557     _act_grp->add(Gtk::Action::create("ShowHideDialogs",
558                                       Stock::SHOW_HIDE_DIALOGS));
560     _act_grp->add(Gtk::Action::create("Grid",
561                                       Stock::GRID));
563     _act_grp->add(Gtk::Action::create("Guides",
564                                       Stock::GUIDES));
566     _act_grp->add(Gtk::Action::create("Fullscreen",
567                                       Stock::FULLSCREEN));
569     _act_grp->add(Gtk::Action::create("Messages",
570                                       Stock::MESSAGES),
571                   sigc::mem_fun(*this, &EditWidget::onDialogMessages));
573     _act_grp->add(Gtk::Action::create("Scripts",
574                                       Stock::SCRIPTS));
576     _act_grp->add(Gtk::Action::create("WindowPrev",
577                                       Stock::WINDOW_PREV));
579     _act_grp->add(Gtk::Action::create("WindowNext",
580                                       Stock::WINDOW_NEXT));
582     _act_grp->add(Gtk::Action::create("WindowDuplicate",
583                                       Stock::WINDOW_DUPLICATE));
585     // Layer menu
586     _act_grp->add(Gtk::Action::create("LayerNew",
587                                       Stock::LAYER_NEW));
589     _act_grp->add(Gtk::Action::create("LayerRename",
590                                       Stock::LAYER_RENAME));
592     _act_grp->add(Gtk::Action::create("LayerDuplicate",
593                                       Stock::LAYER_DUPLICATE));
595     _act_grp->add(Gtk::Action::create("LayerAnchor",
596                                       Stock::LAYER_ANCHOR));
598     _act_grp->add(Gtk::Action::create("LayerMergeDown",
599                                       Stock::LAYER_MERGE_DOWN));
601     _act_grp->add(Gtk::Action::create("LayerDelete",
602                                       Stock::LAYER_DELETE));
604     _act_grp->add(Gtk::Action::create("LayerSelectNext",
605                                       Stock::LAYER_SELECT_NEXT));
607     _act_grp->add(Gtk::Action::create("LayerSelectPrev",
608                                       Stock::LAYER_SELECT_PREV));
610     _act_grp->add(Gtk::Action::create("LayerSelectTop",
611                                       Stock::LAYER_SELECT_TOP));
613     _act_grp->add(Gtk::Action::create("LayerSelectBottom",
614                                       Stock::LAYER_SELECT_BOTTOM));
616     _act_grp->add(Gtk::Action::create("LayerRaise",
617                                       Stock::LAYER_RAISE));
619     _act_grp->add(Gtk::Action::create("LayerLower",
620                                       Stock::LAYER_LOWER));
622     _act_grp->add(Gtk::Action::create("LayerToTop",
623                                       Stock::LAYER_TO_TOP));
625     _act_grp->add(Gtk::Action::create("LayerToBottom",
626                                       Stock::LAYER_TO_BOTTOM));
628     // Object menu
629     _act_grp->add(Gtk::Action::create("FillAndStroke",
630                                       Stock::FILL_STROKE, Glib::ustring(),
631                                       _("PLACEHOLDER, do not translate")),
632                   sigc::mem_fun(*this, &EditWidget::onDialogFillAndStroke));
634     _act_grp->add(Gtk::Action::create("ObjectProperties",
635                                       Stock::OBJECT_PROPERTIES),
636                   sigc::mem_fun(*this, &EditWidget::onDialogObjectProperties));
638     _act_grp->add(Gtk::Action::create("FilterEffects",
639                                       Stock::FILTER_EFFECTS));
641     _act_grp->add(Gtk::Action::create("Group",
642                                       Stock::GROUP, Glib::ustring(),
643                                       _("PLACEHOLDER, do not translate")));
645     _act_grp->add(Gtk::Action::create("Ungroup",
646                                       Stock::UNGROUP, Glib::ustring(),
647                                       _("PLACEHOLDER, do not translate")));
649     _act_grp->add(Gtk::Action::create("Raise",
650                                       Stock::RAISE, Glib::ustring(),
651                                       _("PLACEHOLDER, do not translate")));
653     _act_grp->add(Gtk::Action::create("Lower",
654                                       Stock::LOWER, Glib::ustring(),
655                                       _("PLACEHOLDER, do not translate")));
657     _act_grp->add(Gtk::Action::create("RaiseToTop",
658                                       Stock::RAISE_TO_TOP, Glib::ustring(),
659                                       _("PLACEHOLDER, do not translate")));
661     _act_grp->add(Gtk::Action::create("LowerToBottom",
662                                       Stock::LOWER_TO_BOTTOM, Glib::ustring(),
663                                       _("PLACEHOLDER, do not translate")));
665     _act_grp->add(Gtk::Action::create("MoveToNewLayer",
666                                       Stock::MOVE_TO_NEW_LAYER, Glib::ustring(),
667                                       _("PLACEHOLDER, do not translate")));
669     _act_grp->add(Gtk::Action::create("MoveToNextLayer",
670                                       Stock::MOVE_TO_NEXT_LAYER, Glib::ustring(),
671                                       _("PLACEHOLDER, do not translate")));
673     _act_grp->add(Gtk::Action::create("MoveToPrevLayer",
674                                       Stock::MOVE_TO_PREV_LAYER, Glib::ustring(),
675                                       _("PLACEHOLDER, do not translate")));
677     _act_grp->add(Gtk::Action::create("MoveToTopLayer",
678                                       Stock::MOVE_TO_TOP_LAYER, Glib::ustring(),
679                                       _("PLACEHOLDER, do not translate")));
681     _act_grp->add(Gtk::Action::create("MoveToBottomLayer",
682                                       Stock::MOVE_TO_BOTTOM_LAYER, Glib::ustring(),
683                                       _("PLACEHOLDER, do not translate")));
685     _act_grp->add(Gtk::Action::create("Rotate90CW",
686                                       Stock::ROTATE_90_CW, Glib::ustring(),
687                                       _("PLACEHOLDER, do not translate")));
689     _act_grp->add(Gtk::Action::create("Rotate90CCW",
690                                       Stock::ROTATE_90_CCW, Glib::ustring(),
691                                       _("PLACEHOLDER, do not translate")));
693     _act_grp->add(Gtk::Action::create("FlipHoriz",
694                                       Stock::FLIP_HORIZ, Glib::ustring(),
695                                       _("PLACEHOLDER, do not translate")));
697     _act_grp->add(Gtk::Action::create("FlipVert",
698                                       Stock::FLIP_VERT, Glib::ustring(),
699                                       _("PLACEHOLDER, do not translate")));
701     _act_grp->add(Gtk::Action::create("Transformation",
702                                       Stock::TRANSFORMATION, Glib::ustring(),
703                                       _("PLACEHOLDER, do not translate")),
704                   sigc::mem_fun(*this, &EditWidget::onDialogTransformation));
706     _act_grp->add(Gtk::Action::create("AlignAndDistribute",
707                                       Stock::ALIGN_DISTRIBUTE, Glib::ustring(),
708                                       _("PLACEHOLDER, do not translate")),
709                   sigc::mem_fun(*this, &EditWidget::onDialogAlignAndDistribute));
711     // Path menu
712     _act_grp->add(Gtk::Action::create("ObjectToPath",
713                                       Stock::OBJECT_TO_PATH, Glib::ustring(),
714                                       _("PLACEHOLDER, do not translate")));
716     _act_grp->add(Gtk::Action::create("StrokeToPath",
717                                       Stock::STROKE_TO_PATH, Glib::ustring(),
718                                       _("PLACEHOLDER, do not translate")));
720     _act_grp->add(Gtk::Action::create("Trace",
721                                       Stock::TRACE),
722                   sigc::mem_fun(*this, &EditWidget::onDialogTrace));
724     _act_grp->add(Gtk::Action::create("Union",
725                                       Stock::UNION));
727     _act_grp->add(Gtk::Action::create("Difference",
728                                       Stock::DIFFERENCE));
730     _act_grp->add(Gtk::Action::create("Intersection",
731                                       Stock::INTERSECTION));
733     _act_grp->add(Gtk::Action::create("Exclusion",
734                                       Stock::EXCLUSION));
736     _act_grp->add(Gtk::Action::create("Division",
737                                       Stock::DIVISION));
739     _act_grp->add(Gtk::Action::create("CutPath",
740                                       Stock::CUT_PATH));
742     _act_grp->add(Gtk::Action::create("Combine",
743                                       Stock::COMBINE));
745     _act_grp->add(Gtk::Action::create("BreakApart",
746                                       Stock::BREAK_APART));
748     _act_grp->add(Gtk::Action::create("Inset",
749                                       Stock::INSET));
751     _act_grp->add(Gtk::Action::create("Outset",
752                                       Stock::OUTSET));
754     _act_grp->add(Gtk::Action::create("OffsetDynamic",
755                                       Stock::OFFSET_DYNAMIC));
757     _act_grp->add(Gtk::Action::create("OffsetLinked",
758                                       Stock::OFFSET_LINKED));
760     _act_grp->add(Gtk::Action::create("Simplify",
761                                       Stock::SIMPLIFY));
763     _act_grp->add(Gtk::Action::create("Reverse",
764                                       Stock::REVERSE));
766     _act_grp->add(Gtk::Action::create("Cleanup",
767                                       Gtk::Stock::CLEAR,
768                                       _("PLACEHOLDER, do not translate")));
770     // Text menu
771     _act_grp->add(Gtk::Action::create("TextProperties",
772                                       Gtk::Stock::SELECT_FONT, Glib::ustring(),
773                                       _("PLACEHOLDER, do not translate")),
774                   sigc::mem_fun(*this, &EditWidget::onDialogTextProperties));
776     _act_grp->add(Gtk::Action::create("PutOnPath",
777                                       Stock::PUT_ON_PATH));
779     _act_grp->add(Gtk::Action::create("RemoveFromPath",
780                                       Stock::REMOVE_FROM_PATH));
782     _act_grp->add(Gtk::Action::create("RemoveManualKerns",
783                                       Stock::REMOVE_MANUAL_KERNS));
785         // Whiteboard menu
786 #ifdef WITH_INKBOARD
787 #endif
789     // About menu
790     _act_grp->add(Gtk::Action::create("KeysAndMouse",
791                                       Stock::KEYS_MOUSE));
793     _act_grp->add(Gtk::Action::create("Tutorials",
794                                       Stock::TUTORIALS));
796     _act_grp->add(Gtk::Action::create("About",
797                                       Stock::ABOUT),
798                   sigc::mem_fun(*this, &EditWidget::onDialogAbout));
801 void
802 EditWidget::initToolbarActions()
804     // Tools bar
805     Gtk::RadioAction::Group tools;
807     _act_grp->add(Gtk::RadioAction::create(tools, "ToolSelect",
808                                            Stock::TOOL_SELECT, Glib::ustring(),
809                                            _("PLACEHOLDER, do not translate")),
810                   sigc::mem_fun(*this, &EditWidget::onSelectTool));
812     _act_grp->add(Gtk::RadioAction::create(tools, "ToolNode",
813                                            Stock::TOOL_NODE, Glib::ustring(),
814                                            _("PLACEHOLDER, do not translate")),
815                   sigc::mem_fun(*this, &EditWidget::onNodeTool));
817     _act_grp->add(Gtk::RadioAction::create(tools, "ToolZoom",
818                                            Stock::TOOL_ZOOM, Glib::ustring(),
819                                            _("PLACEHOLDER, do not translate")));
821     _act_grp->add(Gtk::RadioAction::create(tools, "ToolRect",
822                                            Stock::TOOL_RECT, Glib::ustring(),
823                                            _("PLACEHOLDER, do not translate")));
825     _act_grp->add(Gtk::RadioAction::create(tools, "ToolArc",
826                                            Stock::TOOL_ARC, Glib::ustring(),
827                                            _("PLACEHOLDER, do not translate")));
829     _act_grp->add(Gtk::RadioAction::create(tools, "ToolStar",
830                                            Stock::TOOL_STAR, Glib::ustring(),
831                                            _("PLACEHOLDER, do not translate")));
833     _act_grp->add(Gtk::RadioAction::create(tools, "ToolSpiral",
834                                            Stock::TOOL_SPIRAL, Glib::ustring(),
835                                            _("PLACEHOLDER, do not translate")));
837     _act_grp->add(Gtk::RadioAction::create(tools, "ToolFreehand",
838                                            Stock::TOOL_FREEHAND, Glib::ustring(),
839                                            _("PLACEHOLDER, do not translate")));
841     _act_grp->add(Gtk::RadioAction::create(tools, "ToolPen",
842                                            Stock::TOOL_PEN, Glib::ustring(),
843                                            _("PLACEHOLDER, do not translate")));
845     _act_grp->add(Gtk::RadioAction::create(tools, "ToolDynaDraw",
846                                            Stock::TOOL_DYNADRAW, Glib::ustring(),
847                                            _("PLACEHOLDER, do not translate")));
849     _act_grp->add(Gtk::RadioAction::create(tools, "ToolText",
850                                            Stock::TOOL_TEXT, Glib::ustring(),
851                                            _("PLACEHOLDER, do not translate")));
853     _act_grp->add(Gtk::RadioAction::create(tools, "ToolDropper",
854                                            Stock::TOOL_DROPPER, Glib::ustring(),
855                                            _("PLACEHOLDER, do not translate")));
857     // Select Controls bar
858     _act_grp->add(Gtk::ToggleAction::create("TransformStroke",
859                                             Stock::TRANSFORM_STROKE, Glib::ustring(),
860                                             _("PLACEHOLDER, do not translate")));
862     _act_grp->add(Gtk::ToggleAction::create("TransformCorners",
863                                             Stock::TRANSFORM_CORNERS, Glib::ustring(),
864                                             _("PLACEHOLDER, do not translate")));
866     _act_grp->add(Gtk::ToggleAction::create("TransformGradient",
867                                             Stock::TRANSFORM_GRADIENT, Glib::ustring(),
868                                             _("PLACEHOLDER, do not translate")));
870     _act_grp->add(Gtk::ToggleAction::create("TransformPattern",
871                                             Stock::TRANSFORM_PATTERN, Glib::ustring(),
872                                             _("PLACEHOLDER, do not translate")));
874     // Node Controls bar
875     _act_grp->add(Gtk::Action::create("NodeInsert",
876                                       Gtk::Stock::ADD, Glib::ustring(),
877                                       _("PLACEHOLDER, do not translate")));
879     _act_grp->add(Gtk::Action::create("NodeDelete",
880                                       Gtk::Stock::REMOVE, Glib::ustring(),
881                                       _("PLACEHOLDER, do not translate")));
883     _act_grp->add(Gtk::Action::create("NodeJoin",
884                                       Stock::NODE_JOIN, Glib::ustring(),
885                                       _("PLACEHOLDER, do not translate")));
887     _act_grp->add(Gtk::Action::create("NodeJoinSegment",
888                                       Stock::NODE_JOIN_SEGMENT, Glib::ustring(),
889                                       _("PLACEHOLDER, do not translate")));
891     _act_grp->add(Gtk::Action::create("NodeDeleteSegment",
892                                       Stock::NODE_DELETE_SEGMENT, Glib::ustring(),
893                                       _("PLACEHOLDER, do not translate")));
895     _act_grp->add(Gtk::Action::create("NodeBreak",
896                                       Stock::NODE_BREAK, Glib::ustring(),
897                                       _("PLACEHOLDER, do not translate")));
899     _act_grp->add(Gtk::Action::create("NodeCorner",
900                                       Stock::NODE_CORNER, Glib::ustring(),
901                                       _("PLACEHOLDER, do not translate")));
903     _act_grp->add(Gtk::Action::create("NodeSmooth",
904                                       Stock::NODE_SMOOTH, Glib::ustring(),
905                                       _("PLACEHOLDER, do not translate")));
907     _act_grp->add(Gtk::Action::create("NodeSymmetric",
908                                       Stock::NODE_SYMMETRIC, Glib::ustring(),
909                                       _("PLACEHOLDER, do not translate")));
911     _act_grp->add(Gtk::Action::create("NodeLine",
912                                       Stock::NODE_LINE, Glib::ustring(),
913                                       _("PLACEHOLDER, do not translate")));
915     _act_grp->add(Gtk::Action::create("NodeCurve",
916                                       Stock::NODE_CURVE, Glib::ustring(),
917                                       _("PLACEHOLDER, do not translate")));
920 void
921 EditWidget::initAccelMap()
923     gchar *filename = g_build_filename(INKSCAPE_UIDIR, "keybindings.rc", NULL);
924     Gtk::AccelMap::load(filename);
925     g_free(filename);
927     // One problem is that the keys 1-6 are zoom accelerators which get
928     // caught as accelerator _before_ any Entry input handler receives them,
929     // for example the zoom status. At the moment, the best way seems to
930     // disable them as accelerators when the Entry gets focus, and enable
931     // them when focus goes elsewhere. The code for this belongs here,
932     // and not in zoom-status.cpp .
934     _zoom_status.signal_focus_in_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusIn));
935     _zoom_status.signal_focus_out_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusOut));
938 bool
939 EditWidget::onEntryFocusIn (GdkEventFocus* ev)
941     Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
942     Gtk::AccelMap::change_entry ("<Actions>//Zoom100", 0, m, false);
943     Gtk::AccelMap::change_entry ("<Actions>//Zoom50", 0, m, false);
944     Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", 0, m, false);
945     Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", 0, m, false);
946     Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", 0, m, false);
947     Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", 0, m, false);
948     return false;
951 bool
952 EditWidget::onEntryFocusOut (GdkEventFocus* ev)
954     Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
955     Gtk::AccelMap::change_entry ("<Actions>//Zoom100", '1', m, false);
956     Gtk::AccelMap::change_entry ("<Actions>//Zoom50", '2', m, false);
957     Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", '3', m, false);
958     Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", '4', m, false);
959     Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", '5', m, false);
960     Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", '6', m, false);
961     return false;
964 void
965 EditWidget::initMenuBar()
967     g_assert(_ui_mgr);
968     Gtk::MenuBar *menu = static_cast<Gtk::MenuBar*>(_ui_mgr->get_widget("/MenuBar"));
969     g_assert(menu != NULL);
970     _main_window_table.attach(*Gtk::manage(menu), 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
973 void
974 EditWidget::initCommandsBar()
976     g_assert(_ui_mgr);
977     Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/CommandsBar")),
978                                Gtk::TOOLBAR_ICONS);
979     g_assert(bar != NULL);
980     _toolbars_vbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
983 void
984 EditWidget::initToolControlsBar()
986     // TODO: Do UIManager controlled widgets need to be deleted?
987     _select_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/SelectControlsBar"));
988     _node_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/NodeControlsBar"));
990     _tool_ctrl = new Toolbox(_select_ctrl, Gtk::TOOLBAR_ICONS);
992     _toolbars_vbox.pack_start(*Gtk::manage(_tool_ctrl), Gtk::PACK_SHRINK);
995 void
996 EditWidget::initUriBar()
998     /// \todo  Create an Inkscape::UI::Widget::UriBar class (?)
1000     _uri_ctrl = new Gtk::Toolbar();
1002     _uri_label.set_label(_("PLACEHOLDER, DO NOT TRANSLATE"));
1003     _uri_ctrl->add(_uri_label);
1004     _uri_ctrl->add(_uri_entry);
1006     _uri_entry.signal_activate()
1007         .connect_notify(sigc::mem_fun(*this, &EditWidget::onUriChanged));
1009     _toolbars_vbox.pack_start(*Gtk::manage(_uri_ctrl), Gtk::PACK_SHRINK);
1012 void
1013 EditWidget::initToolsBar()
1015     Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/ToolsBar")),
1016                                Gtk::TOOLBAR_ICONS,
1017                                Gtk::ORIENTATION_VERTICAL);
1018     g_assert(bar != NULL);
1019     _sub_window_hbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
1022 void
1023 EditWidget::initTopRuler()
1025     _viewport_table.attach(_top_ruler,  1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1027     _tooltips.set_tip (_top_ruler, _top_ruler.get_tip());
1030 void
1031 EditWidget::initLeftRuler()
1033     _viewport_table.attach(_left_ruler, 0, 1, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1035     _tooltips.set_tip (_left_ruler, _left_ruler.get_tip());
1038 void
1039 EditWidget::initBottomScrollbar()
1041     _viewport_table.attach(_bottom_scrollbar, 1, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1042     _bottom_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1043     _bottom_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1046 void
1047 EditWidget::initRightScrollbar()
1049     _viewport_table.attach(_right_scrollbar, 2, 3, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1051     _right_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1052     _right_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1055 void
1056 EditWidget::initStickyZoom()
1058     _viewport_table.attach(_sticky_zoom, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
1060     _sticky_zoom.set_active (prefs_get_int_attribute ("options.stickyzoom", "value", 0) != 0);
1061     _tooltips.set_tip (_sticky_zoom, _("Zoom drawing if window size changes"));
1063     /// \todo icon not implemented
1066 void
1067 EditWidget::initStatusbar()
1069     _statusbar.pack_start (_selected_style_status, false, false, 1);
1070     _statusbar.pack_start (*new Gtk::VSeparator(), false, false, 0);
1072     _tooltips.set_tip (_zoom_status, _("Zoom"));
1074     _layer_selector.reference();
1075     _statusbar.pack_start (_layer_selector, false, false, 1);
1077     _coord_status.property_n_rows() = 2;
1078     _coord_status.property_n_columns() = 5;
1079     _coord_status.property_row_spacing() = 0;
1080     _coord_status.property_column_spacing() = 2;
1081     _coord_eventbox.add (_coord_status);
1082     _tooltips.set_tip (_coord_eventbox, _("Cursor coordinates"));
1083     _coord_status.attach (*new Gtk::VSeparator(), 0,1, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1084     _coord_status.attach (*new Gtk::Label("X:", 0.0, 0.5), 1,2, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1085     _coord_status.attach (*new Gtk::Label("Y:", 0.0, 0.5), 1,2, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1086     _coord_status_x.set_text ("0.0");
1087     _coord_status_x.set_alignment (0.0, 0.5);
1088     _coord_status_y.set_text ("0.0");
1089     _coord_status_y.set_alignment (0.0, 0.5);
1090     _coord_status.attach (_coord_status_x, 2,3, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1091     _coord_status.attach (_coord_status_y, 2,3, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1092     _coord_status.attach (*new Gtk::Label("Z:", 0.0, 0.5), 3,4, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1093     _coord_status.attach (_zoom_status, 4,5, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1094     sp_set_font_size_smaller (static_cast<GtkWidget*>((void*)_coord_status.gobj()));
1095     _statusbar.pack_end (_coord_eventbox, false, false, 1);
1097     _select_status.property_xalign() = 0.0;
1098     _select_status.property_yalign() = 0.5;
1099     _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."));
1100     // include this again with Gtk+-2.6
1101 #if GTK_VERSION_GE(2,6)
1102      gtk_label_set_ellipsize (GTK_LABEL(_select_status.gobj()), PANGO_ELLIPSIZE_END);
1103 #endif
1104     _select_status.set_size_request (1, -1);
1105     _statusbar.pack_start (_select_status, true, true, 0);
1107     _main_window_table.attach(_statusbar, 0, 1, 3, 4, Gtk::FILL, Gtk::SHRINK);
1110 //========================================
1111 //----------implements EditWidgetInterface
1113 Gtk::Window *
1114 EditWidget::getWindow()
1116     return this;
1119 void
1120 EditWidget::setTitle (gchar const* new_title)
1122     set_title (new_title);
1125 void
1126 EditWidget::layout()
1128    show_all_children();
1131 void
1132 EditWidget::present()
1134     this->Gtk::Window::present();
1137 void
1138 EditWidget::getGeometry (gint &x, gint &y, gint &w, gint &h)
1140     get_position (x, y);
1141     get_size (w, h);
1144 void
1145 EditWidget::setSize (gint w, gint h)
1147     resize (w, h);
1150 void
1151 EditWidget::setPosition (NR::Point p)
1153     move (int(p[NR::X]), int(p[NR::Y]));
1156 /// \param p is already gobj()!
1157 void
1158 EditWidget::setTransient (void* p, int i)
1160     gtk_window_set_transient_for (static_cast<GtkWindow*>(p), this->gobj());
1161     if (i==2)
1162         this->Gtk::Window::present();
1165 NR::Point
1166 EditWidget::getPointer()
1168     int x, y;
1169     get_pointer (x, y);
1170     return NR::Point (x, y);
1173 void
1174 EditWidget::setIconified()
1176     iconify();
1179 void
1180 EditWidget::setMaximized()
1182     maximize();
1185 void
1186 EditWidget::setFullscreen()
1188     fullscreen();
1191 /**
1192  *  Shuts down the desktop object for the view being closed.  It checks
1193  *  to see if the document has been edited, and if so prompts the user
1194  *  to save, discard, or cancel.  Returns TRUE if the shutdown operation
1195  *  is cancelled or if the save is cancelled or fails, FALSE otherwise.
1196  */
1197 bool
1198 EditWidget::shutdown()
1200     g_assert (_desktop != NULL);
1201     if (Inkscape::NSApplication::Editor::isDuplicatedView (_desktop))
1202         return false;
1204     SPDocument *doc = _desktop->doc();
1205     if (sp_document_repr_root(doc)->attribute("sodipodi:modified") != NULL)
1206     {
1207         gchar *markup;
1208         /// \todo FIXME !!! obviously this will have problems if the document
1209         /// name contains markup characters
1210         markup = g_strdup_printf(
1211                 _("<span weight=\"bold\" size=\"larger\">Save changes to document \"%s\" before closing?</span>\n\n"
1212                   "If you close without saving, your changes will be discarded."),
1213                 SP_DOCUMENT_NAME(doc));
1215         Gtk::MessageDialog dlg (*this,
1216                        markup,
1217                        true,
1218                        Gtk::MESSAGE_WARNING,
1219                        Gtk::BUTTONS_NONE,
1220                        true);
1221         g_free(markup);
1222         Gtk::Button close_button (_("Close _without saving"), true);
1223         dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1224         close_button.show();
1225         dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1226         dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1227         dlg.set_default_response (Gtk::RESPONSE_YES);
1229         int response = dlg.run();
1230         switch (response)
1231         {
1232             case Gtk::RESPONSE_YES:
1233                 sp_document_ref(doc);
1234                 if (sp_file_save_document(*this, doc)) {
1235                     sp_document_unref(doc);
1236                 } else { // save dialog cancelled or save failed
1237                     sp_document_unref(doc);
1238                     return TRUE;
1239                 }
1240                 break;
1241             case Gtk::RESPONSE_NO:
1242                 break;
1243             default: // cancel pressed, or dialog was closed
1244                 return TRUE;
1245                 break;
1246         }
1247     }
1249     /* Code to check data loss */
1250     bool allow_data_loss = FALSE;
1251     while (sp_document_repr_root(doc)->attribute("inkscape:dataloss") != NULL && allow_data_loss == FALSE)
1252     {
1253         gchar *markup;
1254         /// \todo FIXME !!! obviously this will have problems if the document
1255         /// name contains markup characters
1256         markup = g_strdup_printf(
1257                 _("<span weight=\"bold\" size=\"larger\">The file \"%s\" was saved with a format (%s) that may cause data loss!</span>\n\n"
1258                   "Do you want to save this file in another format?"),
1259                 SP_DOCUMENT_NAME(doc),
1260                 Inkscape::Extension::db.get(sp_document_repr_root(doc)->attribute("inkscape:output_extension"))->get_name());
1262         Gtk::MessageDialog dlg (*this,
1263                        markup,
1264                        true,
1265                        Gtk::MESSAGE_WARNING,
1266                        Gtk::BUTTONS_NONE,
1267                        true);
1268         g_free(markup);
1269         Gtk::Button close_button (_("Close _without saving"), true);
1270         dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1271         close_button.show();
1272         dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1273         dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1274         dlg.set_default_response (Gtk::RESPONSE_YES);
1276         int response = dlg.run();
1278         switch (response)
1279         {
1280             case Gtk::RESPONSE_YES:
1281                 sp_document_ref(doc);
1282                 if (sp_file_save_document(*this, doc)) {
1283                     sp_document_unref(doc);
1284                 } else { // save dialog cancelled or save failed
1285                     sp_document_unref(doc);
1286                     return TRUE;
1287                 }
1288                 break;
1289             case Gtk::RESPONSE_NO:
1290                 allow_data_loss = TRUE;
1291                 break;
1292             default: // cancel pressed, or dialog was closed
1293                 return TRUE;
1294                 break;
1295         }
1296     }
1298     return false;
1302 void
1303 EditWidget::destroy()
1305     delete this;
1308 void
1309 EditWidget::requestCanvasUpdate()
1311     _svg_canvas.widget().queue_draw();
1314 void
1315 EditWidget::requestCanvasUpdateAndWait()
1317     requestCanvasUpdate();
1319     while (gtk_events_pending()) 
1320       gtk_main_iteration_do(FALSE);
1323 void
1324 EditWidget::enableInteraction()
1326   g_return_if_fail(_interaction_disabled_counter > 0);
1327   
1328   _interaction_disabled_counter--;
1329   
1330   if (_interaction_disabled_counter == 0) {
1331     this->set_sensitive(true);
1332   }
1335 void
1336 EditWidget::disableInteraction()
1338   if (_interaction_disabled_counter == 0) {
1339     this->set_sensitive(false);
1340   }
1341   
1342   _interaction_disabled_counter++;
1345 void
1346 EditWidget::activateDesktop()
1348     /// \todo active_desktop_indicator not implemented
1351 void
1352 EditWidget::deactivateDesktop()
1354     /// \todo active_desktop_indicator not implemented
1357 void
1358 EditWidget::viewSetPosition (NR::Point p)
1360     // p -= _namedview->gridorigin;    
1361     /// \todo Why was the origin corrected for the grid origin? (johan)
1362     
1363     double lo, up, pos, max;
1364     _top_ruler.get_range (lo, up, pos, max);
1365     _top_ruler.set_range (lo, up, p[NR::X], max);
1366     _left_ruler.get_range (lo, up, pos, max);
1367     _left_ruler.set_range (lo, up, p[NR::Y], max);
1370 void
1371 EditWidget::updateRulers()
1373     //NR::Point gridorigin = _namedview->gridorigin;
1374     /// \todo Why was the origin corrected for the grid origin? (johan)
1375     
1376     NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1377     double lo, up, pos, max;
1378     double const scale = _desktop->current_zoom();
1379     double s = viewbox.min()[NR::X] / scale; //- gridorigin[NR::X];
1380     double e = viewbox.max()[NR::X] / scale; //- gridorigin[NR::X];
1381     _top_ruler.get_range(lo, up, pos, max);
1382     _top_ruler.set_range(s, e, pos, e);
1383     s = viewbox.min()[NR::Y] / -scale; //- gridorigin[NR::Y];
1384     e = viewbox.max()[NR::Y] / -scale; //- gridorigin[NR::Y];
1385     _left_ruler.set_range(s, e, 0 /*gridorigin[NR::Y]*/, e);
1386     /// \todo is that correct?
1389 void
1390 EditWidget::updateScrollbars (double scale)
1392     // do not call this function before canvas has its size allocated
1393     if (!is_realized() || _update_s_f) {
1394         return;
1395     }
1397     _update_s_f = true;
1399     /* The desktop region we always show unconditionally */
1400     SPDocument *doc = _desktop->doc();
1401     NR::Rect darea = NR::Rect(NR::Point(-sp_document_width(doc),
1402                                         -sp_document_height(doc)),
1403                               NR::Point(2 * sp_document_width(doc),
1404                                         2 * sp_document_height(doc)));
1405     darea = NR::union_bounds(darea, sp_item_bbox_desktop(SP_ITEM(SP_DOCUMENT_ROOT(doc))));
1407     /* Canvas region we always show unconditionally */
1408     NR::Rect carea(NR::Point(darea.min()[NR::X] * scale - 64,
1409                              darea.max()[NR::Y] * -scale - 64),
1410                    NR::Point(darea.max()[NR::X] * scale + 64,
1411                              darea.min()[NR::Y] * -scale + 64));
1413     NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1415     /* Viewbox is always included into scrollable region */
1416     carea = NR::union_bounds(carea, viewbox);
1418     Gtk::Adjustment *adj = _bottom_scrollbar.get_adjustment();
1419     adj->set_value(viewbox.min()[NR::X]);
1420     adj->set_lower(carea.min()[NR::X]);
1421     adj->set_upper(carea.max()[NR::X]);
1422     adj->set_page_increment(viewbox.dimensions()[NR::X]);
1423     adj->set_step_increment(0.1 * (viewbox.dimensions()[NR::X]));
1424     adj->set_page_size(viewbox.dimensions()[NR::X]);
1426     adj = _right_scrollbar.get_adjustment();
1427     adj->set_value(viewbox.min()[NR::Y]);
1428     adj->set_lower(carea.min()[NR::Y]);
1429     adj->set_upper(carea.max()[NR::Y]);
1430     adj->set_page_increment(viewbox.dimensions()[NR::Y]);
1431     adj->set_step_increment(0.1 * viewbox.dimensions()[NR::Y]);
1432     adj->set_page_size(viewbox.dimensions()[NR::Y]);
1434     _update_s_f = false;
1437 void
1438 EditWidget::toggleRulers()
1440     if (_top_ruler.is_visible())
1441     {
1442         _top_ruler.hide_all();
1443         _left_ruler.hide_all();
1444         prefs_set_int_attribute (_desktop->is_fullscreen() ? "fullscreen.rulers" : "window.rulers", "state", 0);
1445     } else {
1446         _top_ruler.show_all();
1447         _left_ruler.show_all();
1448         prefs_set_int_attribute (_desktop->is_fullscreen() ? "fullscreen.rulers" : "window.rulers", "state", 1);
1449     }
1452 void
1453 EditWidget::toggleScrollbars()
1455     if (_bottom_scrollbar.is_visible())
1456     {
1457         _bottom_scrollbar.hide_all();
1458         _right_scrollbar.hide_all();
1459         prefs_set_int_attribute (_desktop->is_fullscreen() ? "fullscreen.scrollbars" : "window.scrollbars", "state", 0);
1460     } else {
1461         _bottom_scrollbar.show_all();
1462         _right_scrollbar.show_all();
1463         prefs_set_int_attribute (_desktop->is_fullscreen() ? "fullscreen.scrollbars" : "window.scrollbars", "state", 1);
1464     }
1467 void
1468 EditWidget::updateZoom()
1470     _zoom_status.update();
1473 void
1474 EditWidget::letZoomGrabFocus()
1476     _zoom_status.grab_focus();
1479 void
1480 EditWidget::setToolboxFocusTo (const gchar *)
1482     /// \todo not implemented
1485 void
1486 EditWidget::setToolboxAdjustmentValue (const gchar *, double)
1488     /// \todo not implemented
1491 void
1492 EditWidget::setToolboxSelectOneValue (const gchar *, gint)
1494     /// \todo not implemented
1497 bool
1498 EditWidget::isToolboxButtonActive (gchar const*)
1500     /// \todo not implemented
1501     return true;
1504 void
1505 EditWidget::setCoordinateStatus (NR::Point p)
1507     gchar *cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::X]);
1508     _coord_status_x.property_label() = cstr;
1509     g_free (cstr);
1510     cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::Y]);
1511     _coord_status_y.property_label() = cstr;
1512     g_free (cstr);
1515 void
1516 EditWidget::setMessage (Inkscape::MessageType type, gchar const* msg)
1518     _select_status.set_markup (msg? msg : "");
1521 bool
1522 EditWidget::warnDialog (gchar* msg)
1524     Gtk::MessageDialog dlg (*this,
1525                        msg,
1526                        true,
1527                        Gtk::MESSAGE_WARNING,
1528                        Gtk::BUTTONS_YES_NO,
1529                        true);
1530     int r = dlg.run();
1531     return r == Gtk::RESPONSE_YES;
1535 void EditWidget::_namedview_modified (SPObject *obj, guint flags) {
1536     SPNamedView *nv = static_cast<SPNamedView *>(obj);
1537     if (flags & SP_OBJECT_MODIFIED_FLAG) {
1538         this->_dt2r = 1.0 / nv->doc_units->unittobase;
1539         this->_top_ruler.update_metric();
1540         this->_left_ruler.update_metric();
1541         this->_tooltips.set_tip(this->_top_ruler, this->_top_ruler.get_tip());
1542         this->_tooltips.set_tip(this->_left_ruler, this->_left_ruler.get_tip());
1543         this->updateRulers();
1544     }
1547 void
1548 EditWidget::initEdit (SPDocument *doc)
1550     _desktop = new SPDesktop();
1551     _desktop->registerEditWidget (this);
1553     _namedview = sp_document_namedview (doc, 0);
1554     _svg_canvas.init (_desktop);
1555     _desktop->init (_namedview, _svg_canvas.spobj());
1556     sp_namedview_window_from_document (_desktop);
1557     sp_namedview_update_layers_from_document (_desktop);
1558     _dt2r = 1.0 / _namedview->doc_units->unittobase;
1560     /// \todo convert to sigc++ when SPObject hierarchy gets converted
1561     /* Listen on namedview modification */
1562     _namedview_modified_connection = _desktop->namedview->connectModified(sigc::mem_fun(*this, &EditWidget::_namedview_modified));
1563     _layer_selector.setDesktop (_desktop);
1564     _selected_style_status.setDesktop (_desktop);
1566     Inkscape::NSApplication::Editor::addDesktop (_desktop);
1568     _zoom_status.init (_desktop);
1569     _top_ruler.init (_desktop, _svg_canvas.widget());
1570     _left_ruler.init (_desktop, _svg_canvas.widget());
1571     updateRulers();
1574 void
1575 EditWidget::destroyEdit()
1577     if (_desktop) {
1578         _layer_selector.unreference();
1579         Inkscape::NSApplication::Editor::removeDesktop (_desktop); // clears selection too
1580         _namedview_modified_connection.disconnect();
1581         _desktop->destroy();
1582         Inkscape::GC::release (_desktop);
1583         _desktop = 0;
1584     }
1587 //----------end of EditWidgetInterface implementation
1589 //----------start of other callbacks
1591 bool
1592 EditWidget::on_key_press_event (GdkEventKey* event)
1594     // this is the original code from helper/window.cpp
1596     unsigned int shortcut;
1597     shortcut = get_group0_keyval (event) |
1598                    ( event->state & GDK_SHIFT_MASK ?
1599                      SP_SHORTCUT_SHIFT_MASK : 0 ) |
1600                    ( event->state & GDK_CONTROL_MASK ?
1601                      SP_SHORTCUT_CONTROL_MASK : 0 ) |
1602                    ( event->state & GDK_MOD1_MASK ?
1603                      SP_SHORTCUT_ALT_MASK : 0 );
1604     return sp_shortcut_invoke (shortcut,
1605                              Inkscape::NSApplication::Editor::getActiveDesktop());
1608 bool
1609 EditWidget::on_delete_event (GdkEventAny*)
1611     return shutdown();
1614 bool
1615 EditWidget::on_focus_in_event (GdkEventFocus*)
1617     Inkscape::NSApplication::Editor::activateDesktop (_desktop);
1618     _svg_canvas.widget().grab_focus();
1620     return false;
1623 void
1624 EditWidget::onWindowSizeAllocate (Gtk::Allocation &newall)
1626     if (!is_realized()) return;
1628     const Gtk::Allocation& all = get_allocation();
1629     if ((newall.get_x() == all.get_x()) &&
1630         (newall.get_y() == all.get_y()) &&
1631         (newall.get_width() == all.get_width()) &&
1632         (newall.get_height() == all.get_height())) {
1633         return;
1634     }
1636     NR::Rect const area = _desktop->get_display_area();
1637     double zoom = _desktop->current_zoom();
1639     if (_sticky_zoom.get_active()) {
1640         /* Calculate zoom per pixel */
1641         double const zpsp = zoom / hypot(area.dimensions()[NR::X], area.dimensions()[NR::Y]);
1642         /* Find new visible area */
1643         NR::Rect const newarea = _desktop->get_display_area();
1644         /* Calculate adjusted zoom */
1645         zoom = zpsp * hypot(newarea.dimensions()[NR::X], newarea.dimensions()[NR::Y]);
1646     }
1648     _desktop->zoom_absolute(area.midpoint()[NR::X], area.midpoint()[NR::Y], zoom);
1651 void
1652 EditWidget::onWindowRealize()
1654     NR::Rect d(NR::Point(0, 0),
1655                NR::Point(sp_document_width(_desktop->doc()), sp_document_height(_desktop->doc())));
1657     if (d.isEmpty(1.0)) {
1658         return;
1659     }
1661     _desktop->set_display_area(d.min()[NR::X], d.min()[NR::Y], d.max()[NR::X], d.max()[NR::Y], 10);
1662     _namedview_modified(_desktop->namedview, SP_OBJECT_MODIFIED_FLAG);
1663     setTitle (SP_DOCUMENT_NAME(_desktop->doc()));
1666 void
1667 EditWidget::onAdjValueChanged()
1669     if (_update_a_f) return;
1670     _update_a_f = true;
1672     sp_canvas_scroll_to (_svg_canvas.spobj(),
1673                          _bottom_scrollbar.get_value(),
1674                          _right_scrollbar.get_value(),
1675                          false);
1676     updateRulers();
1678     _update_a_f = false;
1682 } // namespace View
1683 } // namespace UI
1684 } // namespace Inkscape
1686 /*
1687   Local Variables:
1688   mode:c++
1689   c-file-style:"stroustrup"
1690   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1691   indent-tabs-mode:nil
1692   fill-column:99
1693   End:
1694 */
1695 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :