Code

Menu item to toggle CMS adjustment on and off
[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 #include "ui/dialog/dialog-manager.h"
70 using namespace Inkscape::UI;
71 using namespace Inkscape::UI::Widget;
73 namespace Inkscape {
74 namespace UI {
75 namespace View {
77 EditWidget::EditWidget (SPDocument *doc)
78     : _main_window_table(4),
79       _viewport_table(3,3),
80       _act_grp(Gtk::ActionGroup::create()),
81       _ui_mgr(Gtk::UIManager::create()),
82       _update_s_f(false),
83       _update_a_f(false),
84       _interaction_disabled_counter(0)
85 {
86     g_warning("Creating new EditWidget");
88     _desktop = 0;
89     Icons::init();
90     Stock::init();
91     initActions();
92     initAccelMap();
93     initUIManager();
94     initLayout();
95     initEdit (doc);
96     g_warning("Done creating new EditWidget");
97 }
99 EditWidget::~EditWidget()
101     destroyEdit();
104 void
105 EditWidget::initActions()
107     initMenuActions();
108     initToolbarActions();
111 void
112 EditWidget::initUIManager()
114     _ui_mgr->insert_action_group(_act_grp);
115     add_accel_group(_ui_mgr->get_accel_group());
117     gchar *filename_utf8 = g_build_filename(INKSCAPE_UIDIR, "menus-bars.xml", NULL);
118     if (_ui_mgr->add_ui_from_file(filename_utf8) == 0) {
119         g_warning("Error merging ui from file '%s'", filename_utf8);
120         // fixme-charset: What charset should we pass to g_warning?
121     }
122     g_free(filename_utf8);
125 void
126 EditWidget::initLayout()
128     set_title("New document 1 - Inkscape");
129     set_resizable();
130     set_default_size(640, 480);
132     // top level window into which all other portions of the UI get inserted
133     add(_main_window_table);
134     // attach box for horizontal toolbars
135     _main_window_table.attach(_toolbars_vbox, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
136     // attach sub-window for viewport and vertical toolbars
137     _main_window_table.attach(_sub_window_hbox, 0, 1, 2, 3);
138     // viewport table with 3 rows by 3 columns
139     _sub_window_hbox.pack_end(_viewport_table);
141     // Menus and Bars
142     initMenuBar();
143     initCommandsBar();
144     initToolControlsBar();
145     initUriBar();
146     initToolsBar();
148     // Canvas Viewport
149     initLeftRuler();
150     initTopRuler();
151     initStickyZoom();
152     initBottomScrollbar();
153     initRightScrollbar();
154     _viewport_table.attach(_svg_canvas.widget(), 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
155     _svg_canvas.widget().show_all();
157     // The statusbar comes last and appears at the bottom of _main_window_table
158     initStatusbar();
160     signal_size_allocate().connect (sigc::mem_fun (*this, &EditWidget::onWindowSizeAllocate), false);
161     signal_realize().connect (sigc::mem_fun (*this, &EditWidget::onWindowRealize));
162     show_all_children();
165 void
166 EditWidget::onMenuItem()
168     g_warning("onMenuItem called");
171 void
172 EditWidget::onActionFileNew()
174 //    g_warning("onActionFileNew called");
175     sp_file_new_default();
178 void
179 EditWidget::onActionFileOpen()
181 //    g_warning("onActionFileOpen called");
182     sp_file_open_dialog (*this, NULL, NULL);
185 void
186 EditWidget::onActionFileQuit()
188     g_warning("onActionFileQuit");
189     sp_ui_close_all();
192 void
193 EditWidget::onActionFilePrint()
195     g_warning("onActionFilePrint");
198 void
199 EditWidget::onToolbarItem()
201     g_warning("onToolbarItem called");
204 void
205 EditWidget::onSelectTool()
207     _tool_ctrl->remove();
208     _tool_ctrl->add(*_select_ctrl);
211 void
212 EditWidget::onNodeTool()
214     _tool_ctrl->remove();
215     _tool_ctrl->add(*_node_ctrl);
218 void
219 EditWidget::onDialogInkscapePreferences()
221     _dlg_mgr.showDialog("InkscapePreferences");
224 void
225 EditWidget::onDialogAbout()
229 void
230 EditWidget::onDialogAlignAndDistribute()
232     _dlg_mgr.showDialog("AlignAndDistribute");
235 void
236 EditWidget::onDialogDocumentProperties()
238 //    manage (Inkscape::UI::Dialog::DocumentPreferences::create());
239     _dlg_mgr.showDialog("DocumentPreferences");
242 void
243 EditWidget::onDialogExport()
245     _dlg_mgr.showDialog("Export");
248 void
249 EditWidget::onDialogExtensionEditor()
251     _dlg_mgr.showDialog("ExtensionEditor");
254 void
255 EditWidget::onDialogFillAndStroke()
257     _dlg_mgr.showDialog("FillAndStroke");
260 void
261 EditWidget::onDialogFind()
263     _dlg_mgr.showDialog("Find");
266 void
267 EditWidget::onDialogLayerEditor()
269     _dlg_mgr.showDialog("LayerEditor");
272 void
273 EditWidget::onDialogMessages()
275     _dlg_mgr.showDialog("Messages");
278 void
279 EditWidget::onDialogObjectProperties()
281     _dlg_mgr.showDialog("ObjectProperties");
284 void
285 EditWidget::onDialogTextProperties()
287     _dlg_mgr.showDialog("TextProperties");
290 void
291 EditWidget::onDialogTrace()
295 void
296 EditWidget::onDialogTransformation()
298     _dlg_mgr.showDialog("Transformation");
301 void
302 EditWidget::onDialogXmlEditor()
304     _dlg_mgr.showDialog("XmlEditor");
307 void
308 EditWidget::onUriChanged()
310     g_message("onUriChanged called");
314 // FIXME: strings are replaced by placeholders, NOT to be translated until the code is enabled
315 // See http://sourceforge.net/mailarchive/message.php?msg_id=11746016 for details
317 void
318 EditWidget::initMenuActions()
320 //    _act_grp->add(Gtk::Action::create("MenuFile",   _("PLACEHOLDER, do not translate")));
321 //    _act_grp->add(Gtk::Action::create("MenuEdit",   _("PLACEHOLDER, do not translate")));
322 //    _act_grp->add(Gtk::Action::create("MenuView",   _("PLACEHOLDER, do not translate")));
323 //    _act_grp->add(Gtk::Action::create("MenuLayer",  _("PLACEHOLDER, do not translate")));
324 //    _act_grp->add(Gtk::Action::create("MenuObject", _("PLACEHOLDER, do not translate")));
325 //    _act_grp->add(Gtk::Action::create("MenuPath",   _("PLACEHOLDER, do not translate")));
326 //    _act_grp->add(Gtk::Action::create("MenuText",   _("PLACEHOLDER, do not translate")));
327 //    _act_grp->add(Gtk::Action::create("MenuHelp",   _("PLACEHOLDER, do not translate")));
328 // temporarily replaced with non-gettext version to have a well-sized menu
329 // for testing:
331     _act_grp->add(Gtk::Action::create("MenuFile",   "File"));
332     _act_grp->add(Gtk::Action::create("MenuEdit",   "Edit"));
333     _act_grp->add(Gtk::Action::create("MenuView",   "View"));
334     _act_grp->add(Gtk::Action::create("MenuLayer",  "Layer"));
335     _act_grp->add(Gtk::Action::create("MenuObject", "Object"));
336     _act_grp->add(Gtk::Action::create("MenuPath",   "Path"));
337     _act_grp->add(Gtk::Action::create("MenuText",   "Text"));
338     _act_grp->add(Gtk::Action::create("MenuHelp",   "Help"));
340     // File menu
341     _act_grp->add(Gtk::Action::create("New",
342                                       Gtk::Stock::NEW, Glib::ustring(),
343                                       _("PLACEHOLDER, do not translate")),
344                   sigc::mem_fun(*this, &EditWidget::onActionFileNew));
346     _act_grp->add(Gtk::Action::create("Open",
347                                       Gtk::Stock::OPEN, Glib::ustring(),
348                                       _("PLACEHOLDER, do not translate")),
349                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
351     _act_grp->add(Gtk::Action::create("OpenRecent",
352                                       Stock::OPEN_RECENT));
354     _act_grp->add(Gtk::Action::create("Revert",
355                                       Gtk::Stock::REVERT_TO_SAVED, Glib::ustring(),
356                                       _("PLACEHOLDER, do not translate")),
357                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
359     _act_grp->add(Gtk::Action::create("Save",
360                                       Gtk::Stock::SAVE, Glib::ustring(),
361                                       _("PLACEHOLDER, do not translate")),
362                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
364     _act_grp->add(Gtk::Action::create("SaveAs",
365                                       Gtk::Stock::SAVE_AS, Glib::ustring(),
366                                       _("PLACEHOLDER, do not translate")),
367                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
369     _act_grp->add(Gtk::Action::create("Import",
370                                       Stock::IMPORT, Glib::ustring(),
371                                       _("PLACEHOLDER, do not translate")),
372                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
374     _act_grp->add(Gtk::Action::create("Export",
375                                       Stock::EXPORT, Glib::ustring(),
376                                       _("PLACEHOLDER, do not translate")),
377                   sigc::mem_fun(*this, &EditWidget::onDialogExport));
379     _act_grp->add(Gtk::Action::create("Print",
380                                       Gtk::Stock::PRINT, Glib::ustring(),
381                                       _("PLACEHOLDER, do not translate")),
382                   sigc::mem_fun(*this, &EditWidget::onActionFilePrint));
384     _act_grp->add(Gtk::Action::create("PrintPreview",
385                                       Gtk::Stock::PRINT_PREVIEW),
386                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
388     _act_grp->add(Gtk::Action::create("VacuumDefs",
389                                       Stock::VACUUM_DEFS),
390                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
392     _act_grp->add(Gtk::Action::create("DocumentProperties",
393                                       Gtk::Stock::PROPERTIES, Glib::ustring(),
394                                       _("PLACEHOLDER, do not translate")),
395                   sigc::mem_fun(*this, &EditWidget::onDialogDocumentProperties));
397     _act_grp->add(Gtk::Action::create("InkscapePreferences",
398                                       Gtk::Stock::PREFERENCES, Glib::ustring(),
399                                       _("PLACEHOLDER, do not translate")),
400                   sigc::mem_fun(*this, &EditWidget::onDialogInkscapePreferences));
402     _act_grp->add(Gtk::Action::create("Close",
403                                       Gtk::Stock::CLOSE),
404                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
406     _act_grp->add(Gtk::Action::create("Quit",
407                                       Gtk::Stock::QUIT),
408                   sigc::mem_fun(*this, &EditWidget::onActionFileQuit));
410     // EditWidget menu
411     _act_grp->add(Gtk::Action::create("Undo",
412                                       Gtk::Stock::UNDO, Glib::ustring(),
413                                       _("PLACEHOLDER, do not translate")));
415     _act_grp->add(Gtk::Action::create("Redo",
416                                       Gtk::Stock::REDO, Glib::ustring(),
417                                       _("PLACEHOLDER, do not translate")));
419     _act_grp->add(Gtk::Action::create("UndoHistory",
420                                       Stock::UNDO_HISTORY, Glib::ustring(),
421                                       _("PLACEHOLDER, do not translate")));
423     _act_grp->add(Gtk::Action::create("Cut",
424                                       Gtk::Stock::CUT, Glib::ustring(),
425                                       _("PLACEHOLDER, do not translate")));
427     _act_grp->add(Gtk::Action::create("Copy",
428                                       Gtk::Stock::COPY, Glib::ustring(),
429                                       _("PLACEHOLDER, do not translate")));
431     _act_grp->add(Gtk::Action::create("Paste",
432                                       Gtk::Stock::PASTE, Glib::ustring(),
433                                       _("PLACEHOLDER, do not translate")));
435     _act_grp->add(Gtk::Action::create("PasteInPlace",
436                                       Stock::PASTE_IN_PLACE));
438     _act_grp->add(Gtk::Action::create("PasteStyle",
439                                       Stock::PASTE_STYLE));
441     _act_grp->add(Gtk::Action::create("Find",
442                                       Gtk::Stock::FIND),
443                   sigc::mem_fun(*this, &EditWidget::onDialogFind));
445     _act_grp->add(Gtk::Action::create("Duplicate",
446                                       Stock::DUPLICATE, Glib::ustring(),
447                                       _("PLACEHOLDER, do not translate")));
449     _act_grp->add(Gtk::Action::create("Clone",
450                                       Stock::CLONE, Glib::ustring(),
451                                       _("PLACEHOLDER, do not translate")));
453     _act_grp->add(Gtk::Action::create("CloneUnlink",
454                                       Stock::CLONE_UNLINK, Glib::ustring(),
455                                       _("PLACEHOLDER, do not translate")));
457     _act_grp->add(Gtk::Action::create("CloneSelectOrig",
458                                       Stock::CLONE_SELECT_ORIG));
460     _act_grp->add(Gtk::Action::create("MakeBitmap",
461                                       Stock::MAKE_BITMAP));
463     _act_grp->add(Gtk::Action::create("Tile",
464                                      Stock::TILE));
466     _act_grp->add(Gtk::Action::create("Untile",
467                                       Stock::UNTILE));
469     _act_grp->add(Gtk::Action::create("Delete",
470                                       Gtk::Stock::DELETE));
472     _act_grp->add(Gtk::Action::create("SelectAll",
473                                       Stock::SELECT_ALL));
475     _act_grp->add(Gtk::Action::create("SelectAllInAllLayers",
476                                       Stock::SELECT_ALL_IN_ALL_LAYERS));
478     _act_grp->add(Gtk::Action::create("SelectInvert",
479                                       Stock::SELECT_INVERT));
481     _act_grp->add(Gtk::Action::create("SelectNone",
482                                       Stock::SELECT_NONE));
484     _act_grp->add(Gtk::Action::create("XmlEditor",
485                                       Stock::XML_EDITOR, Glib::ustring(),
486                                       _("PLACEHOLDER, do not translate")),
487                   sigc::mem_fun(*this, &EditWidget::onDialogXmlEditor));
489     // View menu
490     _act_grp->add(Gtk::Action::create("Zoom",
491                                       Stock::ZOOM));
493     _act_grp->add(Gtk::Action::create("ZoomIn",
494                                       Stock::ZOOM_IN, Glib::ustring(),
495                                       _("PLACEHOLDER, do not translate")));
497     _act_grp->add(Gtk::Action::create("ZoomOut",
498                                       Stock::ZOOM_OUT, Glib::ustring(),
499                                       _("PLACEHOLDER, do not translate")));
501     _act_grp->add(Gtk::Action::create("Zoom100",
502                                       Stock::ZOOM_100, Glib::ustring(),
503                                       _("PLACEHOLDER, do not translate")));
505     _act_grp->add(Gtk::Action::create("Zoom50",
506                                       Stock::ZOOM_50, Glib::ustring(),
507                                       _("PLACEHOLDER, do not translate")));
509     _act_grp->add(Gtk::Action::create("Zoom200",
510                                       Stock::ZOOM_200, Glib::ustring(),
511                                       _("PLACEHOLDER, do not translate")));
513     _act_grp->add(Gtk::Action::create("ZoomSelection",
514                                       Stock::ZOOM_SELECTION, Glib::ustring(),
515                                       _("PLACEHOLDER, do not translate")));
517     _act_grp->add(Gtk::Action::create("ZoomDrawing",
518                                       Stock::ZOOM_DRAWING, Glib::ustring(),
519                                       _("PLACEHOLDER, do not translate")));
521     _act_grp->add(Gtk::Action::create("ZoomPage",
522                                       Stock::ZOOM_PAGE, Glib::ustring(),
523                                       _("PLACEHOLDER, do not translate")));
525     _act_grp->add(Gtk::Action::create("ZoomWidth",
526                                       Stock::ZOOM_WIDTH, Glib::ustring(),
527                                       _("PLACEHOLDER, do not translate")));
529     _act_grp->add(Gtk::Action::create("ZoomPrev",
530                                       Stock::ZOOM_PREV, Glib::ustring(),
531                                       _("PLACEHOLDER, do not translate")));
533     _act_grp->add(Gtk::Action::create("ZoomNext",
534                                       Stock::ZOOM_NEXT, Glib::ustring(),
535                                       _("PLACEHOLDER, do not translate")));
537     _act_grp->add(Gtk::Action::create("ShowHide",
538                                       Stock::SHOW_HIDE));
540     _act_grp->add(Gtk::ToggleAction::create("ShowHideCommandsBar",
541                                             Stock::SHOW_HIDE_COMMANDS_BAR));
543     _act_grp->add(Gtk::ToggleAction::create("ShowHideToolControlsBar",
544                                             Stock::SHOW_HIDE_TOOL_CONTROLS_BAR));
546     _act_grp->add(Gtk::ToggleAction::create("ShowHideToolsBar",
547                                             Stock::SHOW_HIDE_TOOLS_BAR));
549     _act_grp->add(Gtk::ToggleAction::create("ShowHideRulers",
550                                             Stock::SHOW_HIDE_RULERS));
552     _act_grp->add(Gtk::ToggleAction::create("ShowHideScrollbars",
553                                             Stock::SHOW_HIDE_SCROLLBARS));
555     _act_grp->add(Gtk::ToggleAction::create("ShowHideStatusbar",
556                                             Stock::SHOW_HIDE_STATUSBAR));
558     _act_grp->add(Gtk::Action::create("ShowHideDialogs",
559                                       Stock::SHOW_HIDE_DIALOGS));
561     _act_grp->add(Gtk::Action::create("Grid",
562                                       Stock::GRID));
564     _act_grp->add(Gtk::Action::create("Guides",
565                                       Stock::GUIDES));
567     _act_grp->add(Gtk::Action::create("Fullscreen",
568                                       Stock::FULLSCREEN));
570     _act_grp->add(Gtk::Action::create("Messages",
571                                       Stock::MESSAGES),
572                   sigc::mem_fun(*this, &EditWidget::onDialogMessages));
574     _act_grp->add(Gtk::Action::create("Scripts",
575                                       Stock::SCRIPTS));
577     _act_grp->add(Gtk::Action::create("WindowPrev",
578                                       Stock::WINDOW_PREV));
580     _act_grp->add(Gtk::Action::create("WindowNext",
581                                       Stock::WINDOW_NEXT));
583     _act_grp->add(Gtk::Action::create("WindowDuplicate",
584                                       Stock::WINDOW_DUPLICATE));
586     // Layer menu
587     _act_grp->add(Gtk::Action::create("LayerNew",
588                                       Stock::LAYER_NEW));
590     _act_grp->add(Gtk::Action::create("LayerRename",
591                                       Stock::LAYER_RENAME));
593     _act_grp->add(Gtk::Action::create("LayerDuplicate",
594                                       Stock::LAYER_DUPLICATE));
596     _act_grp->add(Gtk::Action::create("LayerAnchor",
597                                       Stock::LAYER_ANCHOR));
599     _act_grp->add(Gtk::Action::create("LayerMergeDown",
600                                       Stock::LAYER_MERGE_DOWN));
602     _act_grp->add(Gtk::Action::create("LayerDelete",
603                                       Stock::LAYER_DELETE));
605     _act_grp->add(Gtk::Action::create("LayerSelectNext",
606                                       Stock::LAYER_SELECT_NEXT));
608     _act_grp->add(Gtk::Action::create("LayerSelectPrev",
609                                       Stock::LAYER_SELECT_PREV));
611     _act_grp->add(Gtk::Action::create("LayerSelectTop",
612                                       Stock::LAYER_SELECT_TOP));
614     _act_grp->add(Gtk::Action::create("LayerSelectBottom",
615                                       Stock::LAYER_SELECT_BOTTOM));
617     _act_grp->add(Gtk::Action::create("LayerRaise",
618                                       Stock::LAYER_RAISE));
620     _act_grp->add(Gtk::Action::create("LayerLower",
621                                       Stock::LAYER_LOWER));
623     _act_grp->add(Gtk::Action::create("LayerToTop",
624                                       Stock::LAYER_TO_TOP));
626     _act_grp->add(Gtk::Action::create("LayerToBottom",
627                                       Stock::LAYER_TO_BOTTOM));
629     // Object menu
630     _act_grp->add(Gtk::Action::create("FillAndStroke",
631                                       Stock::FILL_STROKE, Glib::ustring(),
632                                       _("PLACEHOLDER, do not translate")),
633                   sigc::mem_fun(*this, &EditWidget::onDialogFillAndStroke));
635     _act_grp->add(Gtk::Action::create("ObjectProperties",
636                                       Stock::OBJECT_PROPERTIES),
637                   sigc::mem_fun(*this, &EditWidget::onDialogObjectProperties));
639     _act_grp->add(Gtk::Action::create("FilterEffects",
640                                       Stock::FILTER_EFFECTS));
642     _act_grp->add(Gtk::Action::create("Group",
643                                       Stock::GROUP, Glib::ustring(),
644                                       _("PLACEHOLDER, do not translate")));
646     _act_grp->add(Gtk::Action::create("Ungroup",
647                                       Stock::UNGROUP, Glib::ustring(),
648                                       _("PLACEHOLDER, do not translate")));
650     _act_grp->add(Gtk::Action::create("Raise",
651                                       Stock::RAISE, Glib::ustring(),
652                                       _("PLACEHOLDER, do not translate")));
654     _act_grp->add(Gtk::Action::create("Lower",
655                                       Stock::LOWER, Glib::ustring(),
656                                       _("PLACEHOLDER, do not translate")));
658     _act_grp->add(Gtk::Action::create("RaiseToTop",
659                                       Stock::RAISE_TO_TOP, Glib::ustring(),
660                                       _("PLACEHOLDER, do not translate")));
662     _act_grp->add(Gtk::Action::create("LowerToBottom",
663                                       Stock::LOWER_TO_BOTTOM, Glib::ustring(),
664                                       _("PLACEHOLDER, do not translate")));
666     _act_grp->add(Gtk::Action::create("MoveToNewLayer",
667                                       Stock::MOVE_TO_NEW_LAYER, Glib::ustring(),
668                                       _("PLACEHOLDER, do not translate")));
670     _act_grp->add(Gtk::Action::create("MoveToNextLayer",
671                                       Stock::MOVE_TO_NEXT_LAYER, Glib::ustring(),
672                                       _("PLACEHOLDER, do not translate")));
674     _act_grp->add(Gtk::Action::create("MoveToPrevLayer",
675                                       Stock::MOVE_TO_PREV_LAYER, Glib::ustring(),
676                                       _("PLACEHOLDER, do not translate")));
678     _act_grp->add(Gtk::Action::create("MoveToTopLayer",
679                                       Stock::MOVE_TO_TOP_LAYER, Glib::ustring(),
680                                       _("PLACEHOLDER, do not translate")));
682     _act_grp->add(Gtk::Action::create("MoveToBottomLayer",
683                                       Stock::MOVE_TO_BOTTOM_LAYER, Glib::ustring(),
684                                       _("PLACEHOLDER, do not translate")));
686     _act_grp->add(Gtk::Action::create("Rotate90CW",
687                                       Stock::ROTATE_90_CW, Glib::ustring(),
688                                       _("PLACEHOLDER, do not translate")));
690     _act_grp->add(Gtk::Action::create("Rotate90CCW",
691                                       Stock::ROTATE_90_CCW, Glib::ustring(),
692                                       _("PLACEHOLDER, do not translate")));
694     _act_grp->add(Gtk::Action::create("FlipHoriz",
695                                       Stock::FLIP_HORIZ, Glib::ustring(),
696                                       _("PLACEHOLDER, do not translate")));
698     _act_grp->add(Gtk::Action::create("FlipVert",
699                                       Stock::FLIP_VERT, Glib::ustring(),
700                                       _("PLACEHOLDER, do not translate")));
702     _act_grp->add(Gtk::Action::create("Transformation",
703                                       Stock::TRANSFORMATION, Glib::ustring(),
704                                       _("PLACEHOLDER, do not translate")),
705                   sigc::mem_fun(*this, &EditWidget::onDialogTransformation));
707     _act_grp->add(Gtk::Action::create("AlignAndDistribute",
708                                       Stock::ALIGN_DISTRIBUTE, Glib::ustring(),
709                                       _("PLACEHOLDER, do not translate")),
710                   sigc::mem_fun(*this, &EditWidget::onDialogAlignAndDistribute));
712     // Path menu
713     _act_grp->add(Gtk::Action::create("ObjectToPath",
714                                       Stock::OBJECT_TO_PATH, Glib::ustring(),
715                                       _("PLACEHOLDER, do not translate")));
717     _act_grp->add(Gtk::Action::create("StrokeToPath",
718                                       Stock::STROKE_TO_PATH, Glib::ustring(),
719                                       _("PLACEHOLDER, do not translate")));
721     _act_grp->add(Gtk::Action::create("Trace",
722                                       Stock::TRACE),
723                   sigc::mem_fun(*this, &EditWidget::onDialogTrace));
725     _act_grp->add(Gtk::Action::create("Union",
726                                       Stock::UNION));
728     _act_grp->add(Gtk::Action::create("Difference",
729                                       Stock::DIFFERENCE));
731     _act_grp->add(Gtk::Action::create("Intersection",
732                                       Stock::INTERSECTION));
734     _act_grp->add(Gtk::Action::create("Exclusion",
735                                       Stock::EXCLUSION));
737     _act_grp->add(Gtk::Action::create("Division",
738                                       Stock::DIVISION));
740     _act_grp->add(Gtk::Action::create("CutPath",
741                                       Stock::CUT_PATH));
743     _act_grp->add(Gtk::Action::create("Combine",
744                                       Stock::COMBINE));
746     _act_grp->add(Gtk::Action::create("BreakApart",
747                                       Stock::BREAK_APART));
749     _act_grp->add(Gtk::Action::create("Inset",
750                                       Stock::INSET));
752     _act_grp->add(Gtk::Action::create("Outset",
753                                       Stock::OUTSET));
755     _act_grp->add(Gtk::Action::create("OffsetDynamic",
756                                       Stock::OFFSET_DYNAMIC));
758     _act_grp->add(Gtk::Action::create("OffsetLinked",
759                                       Stock::OFFSET_LINKED));
761     _act_grp->add(Gtk::Action::create("Simplify",
762                                       Stock::SIMPLIFY));
764     _act_grp->add(Gtk::Action::create("Reverse",
765                                       Stock::REVERSE));
767     _act_grp->add(Gtk::Action::create("Cleanup",
768                                       Gtk::Stock::CLEAR,
769                                       _("PLACEHOLDER, do not translate")));
771     // Text menu
772     _act_grp->add(Gtk::Action::create("TextProperties",
773                                       Gtk::Stock::SELECT_FONT, Glib::ustring(),
774                                       _("PLACEHOLDER, do not translate")),
775                   sigc::mem_fun(*this, &EditWidget::onDialogTextProperties));
777     _act_grp->add(Gtk::Action::create("PutOnPath",
778                                       Stock::PUT_ON_PATH));
780     _act_grp->add(Gtk::Action::create("RemoveFromPath",
781                                       Stock::REMOVE_FROM_PATH));
783     _act_grp->add(Gtk::Action::create("RemoveManualKerns",
784                                       Stock::REMOVE_MANUAL_KERNS));
786         // Whiteboard menu
787 #ifdef WITH_INKBOARD
788 #endif
790     // About menu
791     _act_grp->add(Gtk::Action::create("KeysAndMouse",
792                                       Stock::KEYS_MOUSE));
794     _act_grp->add(Gtk::Action::create("Tutorials",
795                                       Stock::TUTORIALS));
797     _act_grp->add(Gtk::Action::create("About",
798                                       Stock::ABOUT),
799                   sigc::mem_fun(*this, &EditWidget::onDialogAbout));
802 void
803 EditWidget::initToolbarActions()
805     // Tools bar
806     Gtk::RadioAction::Group tools;
808     _act_grp->add(Gtk::RadioAction::create(tools, "ToolSelect",
809                                            Stock::TOOL_SELECT, Glib::ustring(),
810                                            _("PLACEHOLDER, do not translate")),
811                   sigc::mem_fun(*this, &EditWidget::onSelectTool));
813     _act_grp->add(Gtk::RadioAction::create(tools, "ToolNode",
814                                            Stock::TOOL_NODE, Glib::ustring(),
815                                            _("PLACEHOLDER, do not translate")),
816                   sigc::mem_fun(*this, &EditWidget::onNodeTool));
818     _act_grp->add(Gtk::RadioAction::create(tools, "ToolZoom",
819                                            Stock::TOOL_ZOOM, Glib::ustring(),
820                                            _("PLACEHOLDER, do not translate")));
822     _act_grp->add(Gtk::RadioAction::create(tools, "ToolRect",
823                                            Stock::TOOL_RECT, Glib::ustring(),
824                                            _("PLACEHOLDER, do not translate")));
826     _act_grp->add(Gtk::RadioAction::create(tools, "ToolArc",
827                                            Stock::TOOL_ARC, Glib::ustring(),
828                                            _("PLACEHOLDER, do not translate")));
830     _act_grp->add(Gtk::RadioAction::create(tools, "ToolStar",
831                                            Stock::TOOL_STAR, Glib::ustring(),
832                                            _("PLACEHOLDER, do not translate")));
834     _act_grp->add(Gtk::RadioAction::create(tools, "ToolSpiral",
835                                            Stock::TOOL_SPIRAL, Glib::ustring(),
836                                            _("PLACEHOLDER, do not translate")));
838     _act_grp->add(Gtk::RadioAction::create(tools, "ToolFreehand",
839                                            Stock::TOOL_FREEHAND, Glib::ustring(),
840                                            _("PLACEHOLDER, do not translate")));
842     _act_grp->add(Gtk::RadioAction::create(tools, "ToolPen",
843                                            Stock::TOOL_PEN, Glib::ustring(),
844                                            _("PLACEHOLDER, do not translate")));
846     _act_grp->add(Gtk::RadioAction::create(tools, "ToolDynaDraw",
847                                            Stock::TOOL_DYNADRAW, Glib::ustring(),
848                                            _("PLACEHOLDER, do not translate")));
850     _act_grp->add(Gtk::RadioAction::create(tools, "ToolText",
851                                            Stock::TOOL_TEXT, Glib::ustring(),
852                                            _("PLACEHOLDER, do not translate")));
854     _act_grp->add(Gtk::RadioAction::create(tools, "ToolDropper",
855                                            Stock::TOOL_DROPPER, Glib::ustring(),
856                                            _("PLACEHOLDER, do not translate")));
858     // Select Controls bar
859     _act_grp->add(Gtk::ToggleAction::create("TransformStroke",
860                                             Stock::TRANSFORM_STROKE, Glib::ustring(),
861                                             _("PLACEHOLDER, do not translate")));
863     _act_grp->add(Gtk::ToggleAction::create("TransformCorners",
864                                             Stock::TRANSFORM_CORNERS, Glib::ustring(),
865                                             _("PLACEHOLDER, do not translate")));
867     _act_grp->add(Gtk::ToggleAction::create("TransformGradient",
868                                             Stock::TRANSFORM_GRADIENT, Glib::ustring(),
869                                             _("PLACEHOLDER, do not translate")));
871     _act_grp->add(Gtk::ToggleAction::create("TransformPattern",
872                                             Stock::TRANSFORM_PATTERN, Glib::ustring(),
873                                             _("PLACEHOLDER, do not translate")));
875     // Node Controls bar
876     _act_grp->add(Gtk::Action::create("NodeInsert",
877                                       Gtk::Stock::ADD, Glib::ustring(),
878                                       _("PLACEHOLDER, do not translate")));
880     _act_grp->add(Gtk::Action::create("NodeDelete",
881                                       Gtk::Stock::REMOVE, Glib::ustring(),
882                                       _("PLACEHOLDER, do not translate")));
884     _act_grp->add(Gtk::Action::create("NodeJoin",
885                                       Stock::NODE_JOIN, Glib::ustring(),
886                                       _("PLACEHOLDER, do not translate")));
888     _act_grp->add(Gtk::Action::create("NodeJoinSegment",
889                                       Stock::NODE_JOIN_SEGMENT, Glib::ustring(),
890                                       _("PLACEHOLDER, do not translate")));
892     _act_grp->add(Gtk::Action::create("NodeDeleteSegment",
893                                       Stock::NODE_DELETE_SEGMENT, Glib::ustring(),
894                                       _("PLACEHOLDER, do not translate")));
896     _act_grp->add(Gtk::Action::create("NodeBreak",
897                                       Stock::NODE_BREAK, Glib::ustring(),
898                                       _("PLACEHOLDER, do not translate")));
900     _act_grp->add(Gtk::Action::create("NodeCorner",
901                                       Stock::NODE_CORNER, Glib::ustring(),
902                                       _("PLACEHOLDER, do not translate")));
904     _act_grp->add(Gtk::Action::create("NodeSmooth",
905                                       Stock::NODE_SMOOTH, Glib::ustring(),
906                                       _("PLACEHOLDER, do not translate")));
908     _act_grp->add(Gtk::Action::create("NodeSymmetric",
909                                       Stock::NODE_SYMMETRIC, Glib::ustring(),
910                                       _("PLACEHOLDER, do not translate")));
912     _act_grp->add(Gtk::Action::create("NodeLine",
913                                       Stock::NODE_LINE, Glib::ustring(),
914                                       _("PLACEHOLDER, do not translate")));
916     _act_grp->add(Gtk::Action::create("NodeCurve",
917                                       Stock::NODE_CURVE, Glib::ustring(),
918                                       _("PLACEHOLDER, do not translate")));
921 void
922 EditWidget::initAccelMap()
924     gchar *filename = g_build_filename(INKSCAPE_UIDIR, "keybindings.rc", NULL);
925     Gtk::AccelMap::load(filename);
926     g_free(filename);
928     // One problem is that the keys 1-6 are zoom accelerators which get
929     // caught as accelerator _before_ any Entry input handler receives them,
930     // for example the zoom status. At the moment, the best way seems to
931     // disable them as accelerators when the Entry gets focus, and enable
932     // them when focus goes elsewhere. The code for this belongs here,
933     // and not in zoom-status.cpp .
935     _zoom_status.signal_focus_in_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusIn));
936     _zoom_status.signal_focus_out_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusOut));
939 bool
940 EditWidget::onEntryFocusIn (GdkEventFocus* /*ev*/)
942     Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
943     Gtk::AccelMap::change_entry ("<Actions>//Zoom100", 0, m, false);
944     Gtk::AccelMap::change_entry ("<Actions>//Zoom50", 0, m, false);
945     Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", 0, m, false);
946     Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", 0, m, false);
947     Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", 0, m, false);
948     Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", 0, m, false);
949     return false;
952 bool
953 EditWidget::onEntryFocusOut (GdkEventFocus* /*ev*/)
955     Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
956     Gtk::AccelMap::change_entry ("<Actions>//Zoom100", '1', m, false);
957     Gtk::AccelMap::change_entry ("<Actions>//Zoom50", '2', m, false);
958     Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", '3', m, false);
959     Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", '4', m, false);
960     Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", '5', m, false);
961     Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", '6', m, false);
962     return false;
965 void
966 EditWidget::initMenuBar()
968     g_assert(_ui_mgr);
969     Gtk::MenuBar *menu = static_cast<Gtk::MenuBar*>(_ui_mgr->get_widget("/MenuBar"));
970     g_assert(menu != NULL);
971     _main_window_table.attach(*Gtk::manage(menu), 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
974 void
975 EditWidget::initCommandsBar()
977     g_assert(_ui_mgr);
978     Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/CommandsBar")),
979                                Gtk::TOOLBAR_ICONS);
980     g_assert(bar != NULL);
981     _toolbars_vbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
984 void
985 EditWidget::initToolControlsBar()
987     // TODO: Do UIManager controlled widgets need to be deleted?
988     _select_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/SelectControlsBar"));
989     _node_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/NodeControlsBar"));
991     _tool_ctrl = new Toolbox(_select_ctrl, Gtk::TOOLBAR_ICONS);
993     _toolbars_vbox.pack_start(*Gtk::manage(_tool_ctrl), Gtk::PACK_SHRINK);
996 void
997 EditWidget::initUriBar()
999     /// \todo  Create an Inkscape::UI::Widget::UriBar class (?)
1001     _uri_ctrl = new Gtk::Toolbar();
1003     _uri_label.set_label(_("PLACEHOLDER, DO NOT TRANSLATE"));
1004     _uri_ctrl->add(_uri_label);
1005     _uri_ctrl->add(_uri_entry);
1007     _uri_entry.signal_activate()
1008         .connect_notify(sigc::mem_fun(*this, &EditWidget::onUriChanged));
1010     _toolbars_vbox.pack_start(*Gtk::manage(_uri_ctrl), Gtk::PACK_SHRINK);
1013 void
1014 EditWidget::initToolsBar()
1016     Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/ToolsBar")),
1017                                Gtk::TOOLBAR_ICONS,
1018                                Gtk::ORIENTATION_VERTICAL);
1019     g_assert(bar != NULL);
1020     _sub_window_hbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
1023 void
1024 EditWidget::initTopRuler()
1026     _viewport_table.attach(_top_ruler,  1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1028     _tooltips.set_tip (_top_ruler, _top_ruler.get_tip());
1031 void
1032 EditWidget::initLeftRuler()
1034     _viewport_table.attach(_left_ruler, 0, 1, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1036     _tooltips.set_tip (_left_ruler, _left_ruler.get_tip());
1039 void
1040 EditWidget::initBottomScrollbar()
1042     _viewport_table.attach(_bottom_scrollbar, 1, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1043     _bottom_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1044     _bottom_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1047 void
1048 EditWidget::initRightScrollbar()
1050     _viewport_table.attach(_right_scrollbar, 2, 3, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1052     _right_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1053     _right_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1056 void
1057 EditWidget::initStickyZoom()
1059     _viewport_table.attach(_sticky_zoom, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
1061     _sticky_zoom.set_active (prefs_get_int_attribute ("options.stickyzoom", "value", 0) != 0);
1062     _tooltips.set_tip (_sticky_zoom, _("Zoom drawing if window size changes"));
1064     /// \todo icon not implemented
1067 void
1068 EditWidget::initStatusbar()
1070     _statusbar.pack_start (_selected_style_status, false, false, 1);
1071     _statusbar.pack_start (*new Gtk::VSeparator(), false, false, 0);
1073     _tooltips.set_tip (_zoom_status, _("Zoom"));
1075     _layer_selector.reference();
1076     _statusbar.pack_start (_layer_selector, false, false, 1);
1078     _coord_status.property_n_rows() = 2;
1079     _coord_status.property_n_columns() = 5;
1080     _coord_status.property_row_spacing() = 0;
1081     _coord_status.property_column_spacing() = 2;
1082     _coord_eventbox.add (_coord_status);
1083     _tooltips.set_tip (_coord_eventbox, _("Cursor coordinates"));
1084     _coord_status.attach (*new Gtk::VSeparator(), 0,1, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1085     _coord_status.attach (*new Gtk::Label("X:", 0.0, 0.5), 1,2, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1086     _coord_status.attach (*new Gtk::Label("Y:", 0.0, 0.5), 1,2, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1087     _coord_status_x.set_text ("0.0");
1088     _coord_status_x.set_alignment (0.0, 0.5);
1089     _coord_status_y.set_text ("0.0");
1090     _coord_status_y.set_alignment (0.0, 0.5);
1091     _coord_status.attach (_coord_status_x, 2,3, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1092     _coord_status.attach (_coord_status_y, 2,3, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1093     _coord_status.attach (*new Gtk::Label("Z:", 0.0, 0.5), 3,4, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1094     _coord_status.attach (_zoom_status, 4,5, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1095     sp_set_font_size_smaller (static_cast<GtkWidget*>((void*)_coord_status.gobj()));
1096     _statusbar.pack_end (_coord_eventbox, false, false, 1);
1098     _select_status.property_xalign() = 0.0;
1099     _select_status.property_yalign() = 0.5;
1100     _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."));
1101     // include this again with Gtk+-2.6
1102 #if GTK_VERSION_GE(2,6)
1103      gtk_label_set_ellipsize (GTK_LABEL(_select_status.gobj()), PANGO_ELLIPSIZE_END);
1104 #endif
1105     _select_status.set_size_request (1, -1);
1106     _statusbar.pack_start (_select_status, true, true, 0);
1108     _main_window_table.attach(_statusbar, 0, 1, 3, 4, Gtk::FILL, Gtk::SHRINK);
1111 //========================================
1112 //----------implements EditWidgetInterface
1114 Gtk::Window *
1115 EditWidget::getWindow()
1117     return this;
1120 void
1121 EditWidget::setTitle (gchar const* new_title)
1123     set_title (new_title);
1126 void
1127 EditWidget::layout()
1129    show_all_children();
1132 void
1133 EditWidget::present()
1135     this->Gtk::Window::present();
1138 void
1139 EditWidget::getGeometry (gint &x, gint &y, gint &w, gint &h)
1141     get_position (x, y);
1142     get_size (w, h);
1145 void
1146 EditWidget::setSize (gint w, gint h)
1148     resize (w, h);
1151 void
1152 EditWidget::setPosition (NR::Point p)
1154     move (int(p[NR::X]), int(p[NR::Y]));
1157 /// \param p is already gobj()!
1158 void
1159 EditWidget::setTransient (void* p, int i)
1161     gtk_window_set_transient_for (static_cast<GtkWindow*>(p), this->gobj());
1162     if (i==2)
1163         this->Gtk::Window::present();
1166 NR::Point
1167 EditWidget::getPointer()
1169     int x, y;
1170     get_pointer (x, y);
1171     return NR::Point (x, y);
1174 void
1175 EditWidget::setIconified()
1177     iconify();
1180 void
1181 EditWidget::setMaximized()
1183     maximize();
1186 void
1187 EditWidget::setFullscreen()
1189     fullscreen();
1192 /**
1193  *  Shuts down the desktop object for the view being closed.  It checks
1194  *  to see if the document has been edited, and if so prompts the user
1195  *  to save, discard, or cancel.  Returns TRUE if the shutdown operation
1196  *  is cancelled or if the save is cancelled or fails, FALSE otherwise.
1197  */
1198 bool
1199 EditWidget::shutdown()
1201     g_assert (_desktop != NULL);
1202     if (Inkscape::NSApplication::Editor::isDuplicatedView (_desktop))
1203         return false;
1205     SPDocument *doc = _desktop->doc();
1206     if (sp_document_repr_root(doc)->attribute("sodipodi:modified") != NULL)
1207     {
1208         gchar *markup;
1209         /// \todo FIXME !!! obviously this will have problems if the document
1210         /// name contains markup characters
1211         markup = g_strdup_printf(
1212                 _("<span weight=\"bold\" size=\"larger\">Save changes to document \"%s\" before closing?</span>\n\n"
1213                   "If you close without saving, your changes will be discarded."),
1214                 SP_DOCUMENT_NAME(doc));
1216         Gtk::MessageDialog dlg (*this,
1217                        markup,
1218                        true,
1219                        Gtk::MESSAGE_WARNING,
1220                        Gtk::BUTTONS_NONE,
1221                        true);
1222         g_free(markup);
1223         Gtk::Button close_button (_("Close _without saving"), true);
1224         dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1225         close_button.show();
1226         dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1227         dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1228         dlg.set_default_response (Gtk::RESPONSE_YES);
1230         int response = dlg.run();
1231         switch (response)
1232         {
1233             case Gtk::RESPONSE_YES:
1234                 sp_document_ref(doc);
1235                 if (sp_file_save_document(*this, doc)) {
1236                     sp_document_unref(doc);
1237                 } else { // save dialog cancelled or save failed
1238                     sp_document_unref(doc);
1239                     return TRUE;
1240                 }
1241                 break;
1242             case Gtk::RESPONSE_NO:
1243                 break;
1244             default: // cancel pressed, or dialog was closed
1245                 return TRUE;
1246                 break;
1247         }
1248     }
1250     /* Code to check data loss */
1251     bool allow_data_loss = FALSE;
1252     while (sp_document_repr_root(doc)->attribute("inkscape:dataloss") != NULL && allow_data_loss == FALSE)
1253     {
1254         gchar *markup;
1255         /// \todo FIXME !!! obviously this will have problems if the document
1256         /// name contains markup characters
1257         markup = g_strdup_printf(
1258                 _("<span weight=\"bold\" size=\"larger\">The file \"%s\" was saved with a format (%s) that may cause data loss!</span>\n\n"
1259                   "Do you want to save this file in another format?"),
1260                 SP_DOCUMENT_NAME(doc),
1261                 Inkscape::Extension::db.get(sp_document_repr_root(doc)->attribute("inkscape:output_extension"))->get_name());
1263         Gtk::MessageDialog dlg (*this,
1264                        markup,
1265                        true,
1266                        Gtk::MESSAGE_WARNING,
1267                        Gtk::BUTTONS_NONE,
1268                        true);
1269         g_free(markup);
1270         Gtk::Button close_button (_("Close _without saving"), true);
1271         dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1272         close_button.show();
1273         dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1274         dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1275         dlg.set_default_response (Gtk::RESPONSE_YES);
1277         int response = dlg.run();
1279         switch (response)
1280         {
1281             case Gtk::RESPONSE_YES:
1282                 sp_document_ref(doc);
1283                 if (sp_file_save_document(*this, doc)) {
1284                     sp_document_unref(doc);
1285                 } else { // save dialog cancelled or save failed
1286                     sp_document_unref(doc);
1287                     return TRUE;
1288                 }
1289                 break;
1290             case Gtk::RESPONSE_NO:
1291                 allow_data_loss = TRUE;
1292                 break;
1293             default: // cancel pressed, or dialog was closed
1294                 return TRUE;
1295                 break;
1296         }
1297     }
1299     return false;
1303 void
1304 EditWidget::destroy()
1306     delete this;
1309 void
1310 EditWidget::requestCanvasUpdate()
1312     _svg_canvas.widget().queue_draw();
1315 void
1316 EditWidget::requestCanvasUpdateAndWait()
1318     requestCanvasUpdate();
1320     while (gtk_events_pending()) 
1321       gtk_main_iteration_do(FALSE);
1324 void
1325 EditWidget::enableInteraction()
1327   g_return_if_fail(_interaction_disabled_counter > 0);
1328   
1329   _interaction_disabled_counter--;
1330   
1331   if (_interaction_disabled_counter == 0) {
1332     this->set_sensitive(true);
1333   }
1336 void
1337 EditWidget::disableInteraction()
1339   if (_interaction_disabled_counter == 0) {
1340     this->set_sensitive(false);
1341   }
1342   
1343   _interaction_disabled_counter++;
1346 void
1347 EditWidget::activateDesktop()
1349     /// \todo active_desktop_indicator not implemented
1352 void
1353 EditWidget::deactivateDesktop()
1355     /// \todo active_desktop_indicator not implemented
1358 void
1359 EditWidget::viewSetPosition (NR::Point p)
1361     // p -= _namedview->gridorigin;    
1362     /// \todo Why was the origin corrected for the grid origin? (johan)
1363     
1364     double lo, up, pos, max;
1365     _top_ruler.get_range (lo, up, pos, max);
1366     _top_ruler.set_range (lo, up, p[NR::X], max);
1367     _left_ruler.get_range (lo, up, pos, max);
1368     _left_ruler.set_range (lo, up, p[NR::Y], max);
1371 void
1372 EditWidget::updateRulers()
1374     //NR::Point gridorigin = _namedview->gridorigin;
1375     /// \todo Why was the origin corrected for the grid origin? (johan)
1376     
1377     NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1378     double lo, up, pos, max;
1379     double const scale = _desktop->current_zoom();
1380     double s = viewbox.min()[NR::X] / scale; //- gridorigin[NR::X];
1381     double e = viewbox.max()[NR::X] / scale; //- gridorigin[NR::X];
1382     _top_ruler.get_range(lo, up, pos, max);
1383     _top_ruler.set_range(s, e, pos, e);
1384     s = viewbox.min()[NR::Y] / -scale; //- gridorigin[NR::Y];
1385     e = viewbox.max()[NR::Y] / -scale; //- gridorigin[NR::Y];
1386     _left_ruler.set_range(s, e, 0 /*gridorigin[NR::Y]*/, e);
1387     /// \todo is that correct?
1390 void
1391 EditWidget::updateScrollbars (double scale)
1393     // do not call this function before canvas has its size allocated
1394     if (!is_realized() || _update_s_f) {
1395         return;
1396     }
1398     _update_s_f = true;
1400     /* The desktop region we always show unconditionally */
1401     SPDocument *doc = _desktop->doc();
1402     NR::Rect darea = NR::Rect(NR::Point(-sp_document_width(doc),
1403                                         -sp_document_height(doc)),
1404                               NR::Point(2 * sp_document_width(doc),
1405                                         2 * sp_document_height(doc)));
1406     darea = NR::union_bounds(darea, sp_item_bbox_desktop(SP_ITEM(SP_DOCUMENT_ROOT(doc))));
1408     /* Canvas region we always show unconditionally */
1409     NR::Rect carea(NR::Point(darea.min()[NR::X] * scale - 64,
1410                              darea.max()[NR::Y] * -scale - 64),
1411                    NR::Point(darea.max()[NR::X] * scale + 64,
1412                              darea.min()[NR::Y] * -scale + 64));
1414     NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1416     /* Viewbox is always included into scrollable region */
1417     carea = NR::union_bounds(carea, viewbox);
1419     Gtk::Adjustment *adj = _bottom_scrollbar.get_adjustment();
1420     adj->set_value(viewbox.min()[NR::X]);
1421     adj->set_lower(carea.min()[NR::X]);
1422     adj->set_upper(carea.max()[NR::X]);
1423     adj->set_page_increment(viewbox.dimensions()[NR::X]);
1424     adj->set_step_increment(0.1 * (viewbox.dimensions()[NR::X]));
1425     adj->set_page_size(viewbox.dimensions()[NR::X]);
1427     adj = _right_scrollbar.get_adjustment();
1428     adj->set_value(viewbox.min()[NR::Y]);
1429     adj->set_lower(carea.min()[NR::Y]);
1430     adj->set_upper(carea.max()[NR::Y]);
1431     adj->set_page_increment(viewbox.dimensions()[NR::Y]);
1432     adj->set_step_increment(0.1 * viewbox.dimensions()[NR::Y]);
1433     adj->set_page_size(viewbox.dimensions()[NR::Y]);
1435     _update_s_f = false;
1438 void
1439 EditWidget::toggleRulers()
1441     if (_top_ruler.is_visible())
1442     {
1443         _top_ruler.hide_all();
1444         _left_ruler.hide_all();
1445         prefs_set_int_attribute (_desktop->is_fullscreen() ? "fullscreen.rulers" : "window.rulers", "state", 0);
1446     } else {
1447         _top_ruler.show_all();
1448         _left_ruler.show_all();
1449         prefs_set_int_attribute (_desktop->is_fullscreen() ? "fullscreen.rulers" : "window.rulers", "state", 1);
1450     }
1453 void
1454 EditWidget::toggleScrollbars()
1456     if (_bottom_scrollbar.is_visible())
1457     {
1458         _bottom_scrollbar.hide_all();
1459         _right_scrollbar.hide_all();
1460         prefs_set_int_attribute (_desktop->is_fullscreen() ? "fullscreen.scrollbars" : "window.scrollbars", "state", 0);
1461     } else {
1462         _bottom_scrollbar.show_all();
1463         _right_scrollbar.show_all();
1464         prefs_set_int_attribute (_desktop->is_fullscreen() ? "fullscreen.scrollbars" : "window.scrollbars", "state", 1);
1465     }
1468 void EditWidget::toggleColorProfAdjust()
1470     // TODO implement
1473 void
1474 EditWidget::updateZoom()
1476     _zoom_status.update();
1479 void
1480 EditWidget::letZoomGrabFocus()
1482     _zoom_status.grab_focus();
1485 void
1486 EditWidget::setToolboxFocusTo (const gchar *)
1488     /// \todo not implemented
1491 void
1492 EditWidget::setToolboxAdjustmentValue (const gchar *, double)
1494     /// \todo not implemented
1497 void
1498 EditWidget::setToolboxSelectOneValue (const gchar *, gint)
1500     /// \todo not implemented
1503 bool
1504 EditWidget::isToolboxButtonActive (gchar const*)
1506     /// \todo not implemented
1507     return true;
1510 void
1511 EditWidget::setCoordinateStatus (NR::Point p)
1513     gchar *cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::X]);
1514     _coord_status_x.property_label() = cstr;
1515     g_free (cstr);
1516     cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::Y]);
1517     _coord_status_y.property_label() = cstr;
1518     g_free (cstr);
1521 void
1522 EditWidget::setMessage (Inkscape::MessageType /*type*/, gchar const* msg)
1524     _select_status.set_markup (msg? msg : "");
1527 bool
1528 EditWidget::warnDialog (gchar* msg)
1530     Gtk::MessageDialog dlg (*this,
1531                        msg,
1532                        true,
1533                        Gtk::MESSAGE_WARNING,
1534                        Gtk::BUTTONS_YES_NO,
1535                        true);
1536     int r = dlg.run();
1537     return r == Gtk::RESPONSE_YES;
1541 Inkscape::UI::Widget::Dock*
1542 EditWidget::getDock ()
1544     return &_dock;
1547 void EditWidget::_namedview_modified (SPObject *obj, guint flags) {
1548     SPNamedView *nv = static_cast<SPNamedView *>(obj);
1549     if (flags & SP_OBJECT_MODIFIED_FLAG) {
1550         this->_dt2r = 1.0 / nv->doc_units->unittobase;
1551         this->_top_ruler.update_metric();
1552         this->_left_ruler.update_metric();
1553         this->_tooltips.set_tip(this->_top_ruler, this->_top_ruler.get_tip());
1554         this->_tooltips.set_tip(this->_left_ruler, this->_left_ruler.get_tip());
1555         this->updateRulers();
1556     }
1559 void
1560 EditWidget::initEdit (SPDocument *doc)
1562     _desktop = new SPDesktop();
1563     _desktop->registerEditWidget (this);
1565     _namedview = sp_document_namedview (doc, 0);
1566     _svg_canvas.init (_desktop);
1567     _desktop->init (_namedview, _svg_canvas.spobj());
1568     sp_namedview_window_from_document (_desktop);
1569     sp_namedview_update_layers_from_document (_desktop);
1570     _dt2r = 1.0 / _namedview->doc_units->unittobase;
1572     /// \todo convert to sigc++ when SPObject hierarchy gets converted
1573     /* Listen on namedview modification */
1574     _namedview_modified_connection = _desktop->namedview->connectModified(sigc::mem_fun(*this, &EditWidget::_namedview_modified));
1575     _layer_selector.setDesktop (_desktop);
1576     _selected_style_status.setDesktop (_desktop);
1578     Inkscape::NSApplication::Editor::addDesktop (_desktop);
1580     _zoom_status.init (_desktop);
1581     _top_ruler.init (_desktop, _svg_canvas.widget());
1582     _left_ruler.init (_desktop, _svg_canvas.widget());
1583     updateRulers();
1586 void
1587 EditWidget::destroyEdit()
1589     if (_desktop) {
1590         _layer_selector.unreference();
1591         Inkscape::NSApplication::Editor::removeDesktop (_desktop); // clears selection too
1592         _namedview_modified_connection.disconnect();
1593         _desktop->destroy();
1594         Inkscape::GC::release (_desktop);
1595         _desktop = 0;
1596     }
1599 //----------end of EditWidgetInterface implementation
1601 //----------start of other callbacks
1603 bool
1604 EditWidget::on_key_press_event (GdkEventKey* event)
1606     // this is the original code from helper/window.cpp
1608     unsigned int shortcut;
1609     shortcut = get_group0_keyval (event) |
1610                    ( event->state & GDK_SHIFT_MASK ?
1611                      SP_SHORTCUT_SHIFT_MASK : 0 ) |
1612                    ( event->state & GDK_CONTROL_MASK ?
1613                      SP_SHORTCUT_CONTROL_MASK : 0 ) |
1614                    ( event->state & GDK_MOD1_MASK ?
1615                      SP_SHORTCUT_ALT_MASK : 0 );
1616     return sp_shortcut_invoke (shortcut,
1617                              Inkscape::NSApplication::Editor::getActiveDesktop());
1620 bool
1621 EditWidget::on_delete_event (GdkEventAny*)
1623     return shutdown();
1626 bool
1627 EditWidget::on_focus_in_event (GdkEventFocus*)
1629     Inkscape::NSApplication::Editor::activateDesktop (_desktop);
1630     _svg_canvas.widget().grab_focus();
1632     return false;
1635 void
1636 EditWidget::onWindowSizeAllocate (Gtk::Allocation &newall)
1638     if (!is_realized()) return;
1640     const Gtk::Allocation& all = get_allocation();
1641     if ((newall.get_x() == all.get_x()) &&
1642         (newall.get_y() == all.get_y()) &&
1643         (newall.get_width() == all.get_width()) &&
1644         (newall.get_height() == all.get_height())) {
1645         return;
1646     }
1648     NR::Rect const area = _desktop->get_display_area();
1649     double zoom = _desktop->current_zoom();
1651     if (_sticky_zoom.get_active()) {
1652         /* Calculate zoom per pixel */
1653         double const zpsp = zoom / hypot(area.dimensions()[NR::X], area.dimensions()[NR::Y]);
1654         /* Find new visible area */
1655         NR::Rect const newarea = _desktop->get_display_area();
1656         /* Calculate adjusted zoom */
1657         zoom = zpsp * hypot(newarea.dimensions()[NR::X], newarea.dimensions()[NR::Y]);
1658     }
1660     _desktop->zoom_absolute(area.midpoint()[NR::X], area.midpoint()[NR::Y], zoom);
1663 void
1664 EditWidget::onWindowRealize()
1666     NR::Rect d(NR::Point(0, 0),
1667                NR::Point(sp_document_width(_desktop->doc()), sp_document_height(_desktop->doc())));
1669     if (d.isEmpty(1.0)) {
1670         return;
1671     }
1673     _desktop->set_display_area(d.min()[NR::X], d.min()[NR::Y], d.max()[NR::X], d.max()[NR::Y], 10);
1674     _namedview_modified(_desktop->namedview, SP_OBJECT_MODIFIED_FLAG);
1675     setTitle (SP_DOCUMENT_NAME(_desktop->doc()));
1678 void
1679 EditWidget::onAdjValueChanged()
1681     if (_update_a_f) return;
1682     _update_a_f = true;
1684     sp_canvas_scroll_to (_svg_canvas.spobj(),
1685                          _bottom_scrollbar.get_value(),
1686                          _right_scrollbar.get_value(),
1687                          false);
1688     updateRulers();
1690     _update_a_f = false;
1694 } // namespace View
1695 } // namespace UI
1696 } // namespace Inkscape
1698 /*
1699   Local Variables:
1700   mode:c++
1701   c-file-style:"stroustrup"
1702   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1703   indent-tabs-mode:nil
1704   fill-column:99
1705   End:
1706 */
1707 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :