Code

separate updating window from updating layers
[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  *
21  * Copyright (C) 2006 John Bintz
22  * Copyright (C) 1999-2005 Authors
23  * Copyright (C) 2000-2001 Ximian, Inc.
24  *
25  * Released under GNU GPL.  Read the file 'COPYING' for more information.
26  */
28 #ifdef HAVE_CONFIG_H
29 # include <config.h>
30 #endif
32 #include <gtk/gtkwindow.h>
33 #include <gtk/gtkversion.h>
34 #include <gtk/gtklabel.h>
35 #include <gtkmm/radioaction.h>
36 #include <gtkmm/menubar.h>
37 #include <gtkmm/messagedialog.h>
38 #include <gtkmm/stock.h>
39 #include <gtkmm/accelmap.h>
40 #include <gtkmm/separator.h>
41 #include <gtkmm/base.h>
43 #include <sigc++/functors/mem_fun.h>
45 #include "macros.h"
46 #include "path-prefix.h"
47 #include "prefs-utils.h"
48 #include "file.h"
49 #include "application/editor.h"
50 #include "edit-widget.h"
51 #include "ui/stock.h"
52 #include "ui/stock-items.h"
53 #include "ui/icons.h"
55 #include "display/sodipodi-ctrlrect.h"
56 #include "helper/units.h"
57 #include "shortcuts.h"
58 #include "widgets/spw-utilities.h"
59 #include "event-context.h"
60 #include "document.h"
61 #include "sp-namedview.h"
62 #include "sp-item.h"
63 #include "interface.h"
64 #include "extension/db.h"
66 using namespace Inkscape::UI;
67 using namespace Inkscape::UI::Widget;
69 namespace Inkscape {
70 namespace UI {
71 namespace View {
73 EditWidget::EditWidget (SPDocument *doc)
74     : _main_window_table(4),
75       _viewport_table(3,3),
76       _act_grp(Gtk::ActionGroup::create()),
77       _ui_mgr(Gtk::UIManager::create()),
78       _update_s_f(false),
79       _update_a_f(false),
80       _interaction_disabled_counter(0)
81 {
82     g_warning("Creating new EditWidget");
84     _desktop = 0;
85     Icons::init();
86     Stock::init();
87     initActions();
88     initAccelMap();
89     initUIManager();
90     initLayout();
91     initEdit (doc);
92     g_warning("Done creating new EditWidget");
93 }
95 EditWidget::~EditWidget()
96 {
97     destroyEdit();
98 }
100 void
101 EditWidget::initActions()
103     initMenuActions();
104     initToolbarActions();
107 void
108 EditWidget::initUIManager()
110     _ui_mgr->insert_action_group(_act_grp);
111     add_accel_group(_ui_mgr->get_accel_group());
113     gchar *filename_utf8 = g_build_filename(INKSCAPE_UIDIR, "menus-bars.xml", NULL);
114     if (_ui_mgr->add_ui_from_file(filename_utf8) == 0) {
115         g_warning("Error merging ui from file '%s'", filename_utf8);
116         // fixme-charset: What charset should we pass to g_warning?
117     }
118     g_free(filename_utf8);
121 void
122 EditWidget::initLayout()
124     set_title("New document 1 - Inkscape");
125     set_resizable();
126     set_default_size(640, 480);
128     // top level window into which all other portions of the UI get inserted
129     add(_main_window_table);
130     // attach box for horizontal toolbars
131     _main_window_table.attach(_toolbars_vbox, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
132     // attach sub-window for viewport and vertical toolbars
133     _main_window_table.attach(_sub_window_hbox, 0, 1, 2, 3);
134     // viewport table with 3 rows by 3 columns
135     _sub_window_hbox.pack_end(_viewport_table);
137     // Menus and Bars
138     initMenuBar();
139     initCommandsBar();
140     initToolControlsBar();
141     initUriBar();
142     initToolsBar();
144     // Canvas Viewport
145     initLeftRuler();
146     initTopRuler();
147     initStickyZoom();
148     initBottomScrollbar();
149     initRightScrollbar();
150     _viewport_table.attach(_svg_canvas.widget(), 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
151     _svg_canvas.widget().show_all();
154     // The statusbar comes last and appears at the bottom of _main_window_table
155     initStatusbar();
157     signal_size_allocate().connect (sigc::mem_fun (*this, &EditWidget::onWindowSizeAllocate), false);
158     signal_realize().connect (sigc::mem_fun (*this, &EditWidget::onWindowRealize));
159     show_all_children();
162 void
163 EditWidget::onMenuItem()
165     g_warning("onMenuItem called");
168 void
169 EditWidget::onActionFileNew()
171 //    g_warning("onActionFileNew called");
172     sp_file_new_default();
175 void
176 EditWidget::onActionFileOpen()
178 //    g_warning("onActionFileOpen called");
179     sp_file_open_dialog (NULL, NULL);
182 void
183 EditWidget::onActionFileQuit()
185     g_warning("onActionFileQuit");
186     sp_ui_close_all();
189 void
190 EditWidget::onActionFilePrint()
192     g_warning("onActionFilePrint");
195 void
196 EditWidget::onToolbarItem()
198     g_warning("onToolbarItem called");
201 void
202 EditWidget::onSelectTool()
204     _tool_ctrl->remove();
205     _tool_ctrl->add(*_select_ctrl);
208 void
209 EditWidget::onNodeTool()
211     _tool_ctrl->remove();
212     _tool_ctrl->add(*_node_ctrl);
215 void
216 EditWidget::onDialogInkscapePreferences()
218     _dlg_mgr.showDialog("InkscapePreferences");
221 void
222 EditWidget::onDialogAbout()
226 void
227 EditWidget::onDialogAlignAndDistribute()
229     _dlg_mgr.showDialog("AlignAndDistribute");
232 void
233 EditWidget::onDialogDocumentProperties()
235 //    manage (Inkscape::UI::Dialog::DocumentPreferences::create());
236     _dlg_mgr.showDialog("DocumentPreferences");
239 void
240 EditWidget::onDialogExport()
242     _dlg_mgr.showDialog("Export");
245 void
246 EditWidget::onDialogExtensionEditor()
248     _dlg_mgr.showDialog("ExtensionEditor");
251 void
252 EditWidget::onDialogFillAndStroke()
254     _dlg_mgr.showDialog("FillAndStroke");
257 void
258 EditWidget::onDialogFind()
260     _dlg_mgr.showDialog("Find");
263 void
264 EditWidget::onDialogLayerEditor()
266     _dlg_mgr.showDialog("LayerEditor");
269 void
270 EditWidget::onDialogMessages()
272     _dlg_mgr.showDialog("Messages");
275 void
276 EditWidget::onDialogObjectProperties()
278     _dlg_mgr.showDialog("ObjectProperties");
281 void
282 EditWidget::onDialogTextProperties()
284     _dlg_mgr.showDialog("TextProperties");
287 void
288 EditWidget::onDialogTrace()
292 void
293 EditWidget::onDialogTransformation()
295     _dlg_mgr.showDialog("Transformation");
298 void
299 EditWidget::onDialogXmlEditor()
301     _dlg_mgr.showDialog("XmlEditor");
304 void
305 EditWidget::onUriChanged()
307     g_message("onUriChanged called");
311 // FIXME: strings are replaced by placeholders, NOT to be translated until the code is enabled
312 // See http://sourceforge.net/mailarchive/message.php?msg_id=11746016 for details
314 void
315 EditWidget::initMenuActions()
317 //    _act_grp->add(Gtk::Action::create("MenuFile",   _("PLACEHOLDER, do not translate")));
318 //    _act_grp->add(Gtk::Action::create("MenuEdit",   _("PLACEHOLDER, do not translate")));
319 //    _act_grp->add(Gtk::Action::create("MenuView",   _("PLACEHOLDER, do not translate")));
320 //    _act_grp->add(Gtk::Action::create("MenuLayer",  _("PLACEHOLDER, do not translate")));
321 //    _act_grp->add(Gtk::Action::create("MenuObject", _("PLACEHOLDER, do not translate")));
322 //    _act_grp->add(Gtk::Action::create("MenuPath",   _("PLACEHOLDER, do not translate")));
323 //    _act_grp->add(Gtk::Action::create("MenuText",   _("PLACEHOLDER, do not translate")));
324 //    _act_grp->add(Gtk::Action::create("MenuHelp",   _("PLACEHOLDER, do not translate")));
325 // temporarily replaced with non-gettext version to have a well-sized menu
326 // for testing:
328     _act_grp->add(Gtk::Action::create("MenuFile",   "File"));
329     _act_grp->add(Gtk::Action::create("MenuEdit",   "Edit"));
330     _act_grp->add(Gtk::Action::create("MenuView",   "View"));
331     _act_grp->add(Gtk::Action::create("MenuLayer",  "Layer"));
332     _act_grp->add(Gtk::Action::create("MenuObject", "Object"));
333     _act_grp->add(Gtk::Action::create("MenuPath",   "Path"));
334     _act_grp->add(Gtk::Action::create("MenuText",   "Text"));
335     _act_grp->add(Gtk::Action::create("MenuHelp",   "Help"));
337     // File menu
338     _act_grp->add(Gtk::Action::create("New",
339                                       Gtk::Stock::NEW, Glib::ustring(),
340                                       _("PLACEHOLDER, do not translate")),
341                   sigc::mem_fun(*this, &EditWidget::onActionFileNew));
343     _act_grp->add(Gtk::Action::create("Open",
344                                       Gtk::Stock::OPEN, Glib::ustring(),
345                                       _("PLACEHOLDER, do not translate")),
346                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
348     _act_grp->add(Gtk::Action::create("OpenRecent",
349                                       Stock::OPEN_RECENT));
351     _act_grp->add(Gtk::Action::create("Revert",
352                                       Gtk::Stock::REVERT_TO_SAVED, Glib::ustring(),
353                                       _("PLACEHOLDER, do not translate")),
354                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
356     _act_grp->add(Gtk::Action::create("Save",
357                                       Gtk::Stock::SAVE, Glib::ustring(),
358                                       _("PLACEHOLDER, do not translate")),
359                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
361     _act_grp->add(Gtk::Action::create("SaveAs",
362                                       Gtk::Stock::SAVE_AS, Glib::ustring(),
363                                       _("PLACEHOLDER, do not translate")),
364                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
366     _act_grp->add(Gtk::Action::create("Import",
367                                       Stock::IMPORT, Glib::ustring(),
368                                       _("PLACEHOLDER, do not translate")),
369                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
371     _act_grp->add(Gtk::Action::create("Export",
372                                       Stock::EXPORT, Glib::ustring(),
373                                       _("PLACEHOLDER, do not translate")),
374                   sigc::mem_fun(*this, &EditWidget::onDialogExport));
376     _act_grp->add(Gtk::Action::create("Print",
377                                       Gtk::Stock::PRINT, Glib::ustring(),
378                                       _("PLACEHOLDER, do not translate")),
379                   sigc::mem_fun(*this, &EditWidget::onActionFilePrint));
381     _act_grp->add(Gtk::Action::create("PrintPreview",
382                                       Gtk::Stock::PRINT_PREVIEW),
383                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
385     _act_grp->add(Gtk::Action::create("VacuumDefs",
386                                       Stock::VACUUM_DEFS),
387                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
389     _act_grp->add(Gtk::Action::create("DocumentProperties",
390                                       Gtk::Stock::PROPERTIES, Glib::ustring(),
391                                       _("PLACEHOLDER, do not translate")),
392                   sigc::mem_fun(*this, &EditWidget::onDialogDocumentProperties));
394     _act_grp->add(Gtk::Action::create("InkscapePreferences",
395                                       Gtk::Stock::PREFERENCES, Glib::ustring(),
396                                       _("PLACEHOLDER, do not translate")),
397                   sigc::mem_fun(*this, &EditWidget::onDialogInkscapePreferences));
399     _act_grp->add(Gtk::Action::create("Close",
400                                       Gtk::Stock::CLOSE),
401                   sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
403     _act_grp->add(Gtk::Action::create("Quit",
404                                       Gtk::Stock::QUIT),
405                   sigc::mem_fun(*this, &EditWidget::onActionFileQuit));
407     // EditWidget menu
408     _act_grp->add(Gtk::Action::create("Undo",
409                                       Gtk::Stock::UNDO, Glib::ustring(),
410                                       _("PLACEHOLDER, do not translate")));
412     _act_grp->add(Gtk::Action::create("Redo",
413                                       Gtk::Stock::REDO, Glib::ustring(),
414                                       _("PLACEHOLDER, do not translate")));
416     _act_grp->add(Gtk::Action::create("UndoHistory",
417                                       Stock::UNDO_HISTORY, Glib::ustring(),
418                                       _("PLACEHOLDER, do not translate")));
420     _act_grp->add(Gtk::Action::create("Cut",
421                                       Gtk::Stock::CUT, Glib::ustring(),
422                                       _("PLACEHOLDER, do not translate")));
424     _act_grp->add(Gtk::Action::create("Copy",
425                                       Gtk::Stock::COPY, Glib::ustring(),
426                                       _("PLACEHOLDER, do not translate")));
428     _act_grp->add(Gtk::Action::create("Paste",
429                                       Gtk::Stock::PASTE, Glib::ustring(),
430                                       _("PLACEHOLDER, do not translate")));
432     _act_grp->add(Gtk::Action::create("PasteInPlace",
433                                       Stock::PASTE_IN_PLACE));
435     _act_grp->add(Gtk::Action::create("PasteStyle",
436                                       Stock::PASTE_STYLE));
438     _act_grp->add(Gtk::Action::create("Find",
439                                       Gtk::Stock::FIND),
440                   sigc::mem_fun(*this, &EditWidget::onDialogFind));
442     _act_grp->add(Gtk::Action::create("Duplicate",
443                                       Stock::DUPLICATE, Glib::ustring(),
444                                       _("PLACEHOLDER, do not translate")));
446     _act_grp->add(Gtk::Action::create("Clone",
447                                       Stock::CLONE, Glib::ustring(),
448                                       _("PLACEHOLDER, do not translate")));
450     _act_grp->add(Gtk::Action::create("CloneUnlink",
451                                       Stock::CLONE_UNLINK, Glib::ustring(),
452                                       _("PLACEHOLDER, do not translate")));
454     _act_grp->add(Gtk::Action::create("CloneSelectOrig",
455                                       Stock::CLONE_SELECT_ORIG));
457     _act_grp->add(Gtk::Action::create("MakeBitmap",
458                                       Stock::MAKE_BITMAP));
460     _act_grp->add(Gtk::Action::create("Tile",
461                                      Stock::TILE));
463     _act_grp->add(Gtk::Action::create("Untile",
464                                       Stock::UNTILE));
466     _act_grp->add(Gtk::Action::create("Delete",
467                                       Gtk::Stock::DELETE));
469     _act_grp->add(Gtk::Action::create("SelectAll",
470                                       Stock::SELECT_ALL));
472     _act_grp->add(Gtk::Action::create("SelectAllInAllLayers",
473                                       Stock::SELECT_ALL_IN_ALL_LAYERS));
475     _act_grp->add(Gtk::Action::create("SelectInvert",
476                                       Stock::SELECT_INVERT));
478     _act_grp->add(Gtk::Action::create("SelectNone",
479                                       Stock::SELECT_NONE));
481     _act_grp->add(Gtk::Action::create("XmlEditor",
482                                       Stock::XML_EDITOR, Glib::ustring(),
483                                       _("PLACEHOLDER, do not translate")),
484                   sigc::mem_fun(*this, &EditWidget::onDialogXmlEditor));
486     // View menu
487     _act_grp->add(Gtk::Action::create("Zoom",
488                                       Stock::ZOOM));
490     _act_grp->add(Gtk::Action::create("ZoomIn",
491                                       Stock::ZOOM_IN, Glib::ustring(),
492                                       _("PLACEHOLDER, do not translate")));
494     _act_grp->add(Gtk::Action::create("ZoomOut",
495                                       Stock::ZOOM_OUT, Glib::ustring(),
496                                       _("PLACEHOLDER, do not translate")));
498     _act_grp->add(Gtk::Action::create("Zoom100",
499                                       Stock::ZOOM_100, Glib::ustring(),
500                                       _("PLACEHOLDER, do not translate")));
502     _act_grp->add(Gtk::Action::create("Zoom50",
503                                       Stock::ZOOM_50, Glib::ustring(),
504                                       _("PLACEHOLDER, do not translate")));
506     _act_grp->add(Gtk::Action::create("Zoom200",
507                                       Stock::ZOOM_200, Glib::ustring(),
508                                       _("PLACEHOLDER, do not translate")));
510     _act_grp->add(Gtk::Action::create("ZoomSelection",
511                                       Stock::ZOOM_SELECTION, Glib::ustring(),
512                                       _("PLACEHOLDER, do not translate")));
514     _act_grp->add(Gtk::Action::create("ZoomDrawing",
515                                       Stock::ZOOM_DRAWING, Glib::ustring(),
516                                       _("PLACEHOLDER, do not translate")));
518     _act_grp->add(Gtk::Action::create("ZoomPage",
519                                       Stock::ZOOM_PAGE, Glib::ustring(),
520                                       _("PLACEHOLDER, do not translate")));
522     _act_grp->add(Gtk::Action::create("ZoomWidth",
523                                       Stock::ZOOM_WIDTH, Glib::ustring(),
524                                       _("PLACEHOLDER, do not translate")));
526     _act_grp->add(Gtk::Action::create("ZoomPrev",
527                                       Stock::ZOOM_PREV, Glib::ustring(),
528                                       _("PLACEHOLDER, do not translate")));
530     _act_grp->add(Gtk::Action::create("ZoomNext",
531                                       Stock::ZOOM_NEXT, Glib::ustring(),
532                                       _("PLACEHOLDER, do not translate")));
534     _act_grp->add(Gtk::Action::create("ShowHide",
535                                       Stock::SHOW_HIDE));
537     _act_grp->add(Gtk::ToggleAction::create("ShowHideCommandsBar",
538                                             Stock::SHOW_HIDE_COMMANDS_BAR));
540     _act_grp->add(Gtk::ToggleAction::create("ShowHideToolControlsBar",
541                                             Stock::SHOW_HIDE_TOOL_CONTROLS_BAR));
543     _act_grp->add(Gtk::ToggleAction::create("ShowHideToolsBar",
544                                             Stock::SHOW_HIDE_TOOLS_BAR));
546     _act_grp->add(Gtk::ToggleAction::create("ShowHideRulers",
547                                             Stock::SHOW_HIDE_RULERS));
549     _act_grp->add(Gtk::ToggleAction::create("ShowHideScrollbars",
550                                             Stock::SHOW_HIDE_SCROLLBARS));
552     _act_grp->add(Gtk::ToggleAction::create("ShowHideStatusbar",
553                                             Stock::SHOW_HIDE_STATUSBAR));
555     _act_grp->add(Gtk::Action::create("ShowHideDialogs",
556                                       Stock::SHOW_HIDE_DIALOGS));
558     _act_grp->add(Gtk::Action::create("Grid",
559                                       Stock::GRID));
561     _act_grp->add(Gtk::Action::create("Guides",
562                                       Stock::GUIDES));
564     _act_grp->add(Gtk::Action::create("Fullscreen",
565                                       Stock::FULLSCREEN));
567     _act_grp->add(Gtk::Action::create("Messages",
568                                       Stock::MESSAGES),
569                   sigc::mem_fun(*this, &EditWidget::onDialogMessages));
571     _act_grp->add(Gtk::Action::create("Scripts",
572                                       Stock::SCRIPTS));
574     _act_grp->add(Gtk::Action::create("WindowPrev",
575                                       Stock::WINDOW_PREV));
577     _act_grp->add(Gtk::Action::create("WindowNext",
578                                       Stock::WINDOW_NEXT));
580     _act_grp->add(Gtk::Action::create("WindowDuplicate",
581                                       Stock::WINDOW_DUPLICATE));
583     // Layer menu
584     _act_grp->add(Gtk::Action::create("LayerNew",
585                                       Stock::LAYER_NEW));
587     _act_grp->add(Gtk::Action::create("LayerRename",
588                                       Stock::LAYER_RENAME));
590     _act_grp->add(Gtk::Action::create("LayerDuplicate",
591                                       Stock::LAYER_DUPLICATE));
593     _act_grp->add(Gtk::Action::create("LayerAnchor",
594                                       Stock::LAYER_ANCHOR));
596     _act_grp->add(Gtk::Action::create("LayerMergeDown",
597                                       Stock::LAYER_MERGE_DOWN));
599     _act_grp->add(Gtk::Action::create("LayerDelete",
600                                       Stock::LAYER_DELETE));
602     _act_grp->add(Gtk::Action::create("LayerSelectNext",
603                                       Stock::LAYER_SELECT_NEXT));
605     _act_grp->add(Gtk::Action::create("LayerSelectPrev",
606                                       Stock::LAYER_SELECT_PREV));
608     _act_grp->add(Gtk::Action::create("LayerSelectTop",
609                                       Stock::LAYER_SELECT_TOP));
611     _act_grp->add(Gtk::Action::create("LayerSelectBottom",
612                                       Stock::LAYER_SELECT_BOTTOM));
614     _act_grp->add(Gtk::Action::create("LayerRaise",
615                                       Stock::LAYER_RAISE));
617     _act_grp->add(Gtk::Action::create("LayerLower",
618                                       Stock::LAYER_LOWER));
620     _act_grp->add(Gtk::Action::create("LayerToTop",
621                                       Stock::LAYER_TO_TOP));
623     _act_grp->add(Gtk::Action::create("LayerToBottom",
624                                       Stock::LAYER_TO_BOTTOM));
626     // Object menu
627     _act_grp->add(Gtk::Action::create("FillAndStroke",
628                                       Stock::FILL_STROKE, Glib::ustring(),
629                                       _("PLACEHOLDER, do not translate")),
630                   sigc::mem_fun(*this, &EditWidget::onDialogFillAndStroke));
632     _act_grp->add(Gtk::Action::create("ObjectProperties",
633                                       Stock::OBJECT_PROPERTIES),
634                   sigc::mem_fun(*this, &EditWidget::onDialogObjectProperties));
636     _act_grp->add(Gtk::Action::create("Group",
637                                       Stock::GROUP, Glib::ustring(),
638                                       _("PLACEHOLDER, do not translate")));
640     _act_grp->add(Gtk::Action::create("Ungroup",
641                                       Stock::UNGROUP, Glib::ustring(),
642                                       _("PLACEHOLDER, do not translate")));
644     _act_grp->add(Gtk::Action::create("Raise",
645                                       Stock::RAISE, Glib::ustring(),
646                                       _("PLACEHOLDER, do not translate")));
648     _act_grp->add(Gtk::Action::create("Lower",
649                                       Stock::LOWER, Glib::ustring(),
650                                       _("PLACEHOLDER, do not translate")));
652     _act_grp->add(Gtk::Action::create("RaiseToTop",
653                                       Stock::RAISE_TO_TOP, Glib::ustring(),
654                                       _("PLACEHOLDER, do not translate")));
656     _act_grp->add(Gtk::Action::create("LowerToBottom",
657                                       Stock::LOWER_TO_BOTTOM, Glib::ustring(),
658                                       _("PLACEHOLDER, do not translate")));
660     _act_grp->add(Gtk::Action::create("MoveToNewLayer",
661                                       Stock::MOVE_TO_NEW_LAYER, Glib::ustring(),
662                                       _("PLACEHOLDER, do not translate")));
664     _act_grp->add(Gtk::Action::create("MoveToNextLayer",
665                                       Stock::MOVE_TO_NEXT_LAYER, Glib::ustring(),
666                                       _("PLACEHOLDER, do not translate")));
668     _act_grp->add(Gtk::Action::create("MoveToPrevLayer",
669                                       Stock::MOVE_TO_PREV_LAYER, Glib::ustring(),
670                                       _("PLACEHOLDER, do not translate")));
672     _act_grp->add(Gtk::Action::create("MoveToTopLayer",
673                                       Stock::MOVE_TO_TOP_LAYER, Glib::ustring(),
674                                       _("PLACEHOLDER, do not translate")));
676     _act_grp->add(Gtk::Action::create("MoveToBottomLayer",
677                                       Stock::MOVE_TO_BOTTOM_LAYER, Glib::ustring(),
678                                       _("PLACEHOLDER, do not translate")));
680     _act_grp->add(Gtk::Action::create("Rotate90CW",
681                                       Stock::ROTATE_90_CW, Glib::ustring(),
682                                       _("PLACEHOLDER, do not translate")));
684     _act_grp->add(Gtk::Action::create("Rotate90CCW",
685                                       Stock::ROTATE_90_CCW, Glib::ustring(),
686                                       _("PLACEHOLDER, do not translate")));
688     _act_grp->add(Gtk::Action::create("FlipHoriz",
689                                       Stock::FLIP_HORIZ, Glib::ustring(),
690                                       _("PLACEHOLDER, do not translate")));
692     _act_grp->add(Gtk::Action::create("FlipVert",
693                                       Stock::FLIP_VERT, Glib::ustring(),
694                                       _("PLACEHOLDER, do not translate")));
696     _act_grp->add(Gtk::Action::create("Transformation",
697                                       Stock::TRANSFORMATION, Glib::ustring(),
698                                       _("PLACEHOLDER, do not translate")),
699                   sigc::mem_fun(*this, &EditWidget::onDialogTransformation));
701     _act_grp->add(Gtk::Action::create("AlignAndDistribute",
702                                       Stock::ALIGN_DISTRIBUTE, Glib::ustring(),
703                                       _("PLACEHOLDER, do not translate")),
704                   sigc::mem_fun(*this, &EditWidget::onDialogAlignAndDistribute));
706     // Path menu
707     _act_grp->add(Gtk::Action::create("ObjectToPath",
708                                       Stock::OBJECT_TO_PATH, Glib::ustring(),
709                                       _("PLACEHOLDER, do not translate")));
711     _act_grp->add(Gtk::Action::create("StrokeToPath",
712                                       Stock::STROKE_TO_PATH, Glib::ustring(),
713                                       _("PLACEHOLDER, do not translate")));
715     _act_grp->add(Gtk::Action::create("Trace",
716                                       Stock::TRACE),
717                   sigc::mem_fun(*this, &EditWidget::onDialogTrace));
719     _act_grp->add(Gtk::Action::create("Union",
720                                       Stock::UNION));
722     _act_grp->add(Gtk::Action::create("Difference",
723                                       Stock::DIFFERENCE));
725     _act_grp->add(Gtk::Action::create("Intersection",
726                                       Stock::INTERSECTION));
728     _act_grp->add(Gtk::Action::create("Exclusion",
729                                       Stock::EXCLUSION));
731     _act_grp->add(Gtk::Action::create("Division",
732                                       Stock::DIVISION));
734     _act_grp->add(Gtk::Action::create("CutPath",
735                                       Stock::CUT_PATH));
737     _act_grp->add(Gtk::Action::create("Combine",
738                                       Stock::COMBINE));
740     _act_grp->add(Gtk::Action::create("BreakApart",
741                                       Stock::BREAK_APART));
743     _act_grp->add(Gtk::Action::create("Inset",
744                                       Stock::INSET));
746     _act_grp->add(Gtk::Action::create("Outset",
747                                       Stock::OUTSET));
749     _act_grp->add(Gtk::Action::create("OffsetDynamic",
750                                       Stock::OFFSET_DYNAMIC));
752     _act_grp->add(Gtk::Action::create("OffsetLinked",
753                                       Stock::OFFSET_LINKED));
755     _act_grp->add(Gtk::Action::create("Simplify",
756                                       Stock::SIMPLIFY));
758     _act_grp->add(Gtk::Action::create("Reverse",
759                                       Stock::REVERSE));
761     _act_grp->add(Gtk::Action::create("Cleanup",
762                                       Gtk::Stock::CLEAR,
763                                       _("PLACEHOLDER, do not translate")));
765     // Text menu
766     _act_grp->add(Gtk::Action::create("TextProperties",
767                                       Gtk::Stock::SELECT_FONT, Glib::ustring(),
768                                       _("PLACEHOLDER, do not translate")),
769                   sigc::mem_fun(*this, &EditWidget::onDialogTextProperties));
771     _act_grp->add(Gtk::Action::create("PutOnPath",
772                                       Stock::PUT_ON_PATH));
774     _act_grp->add(Gtk::Action::create("RemoveFromPath",
775                                       Stock::REMOVE_FROM_PATH));
777     _act_grp->add(Gtk::Action::create("RemoveManualKerns",
778                                       Stock::REMOVE_MANUAL_KERNS));
780         // Whiteboard menu
781 #ifdef WITH_INKBOARD
782 #endif
784     // About menu
785     _act_grp->add(Gtk::Action::create("KeysAndMouse",
786                                       Stock::KEYS_MOUSE));
788     _act_grp->add(Gtk::Action::create("Tutorials",
789                                       Stock::TUTORIALS));
791     _act_grp->add(Gtk::Action::create("About",
792                                       Stock::ABOUT),
793                   sigc::mem_fun(*this, &EditWidget::onDialogAbout));
796 void
797 EditWidget::initToolbarActions()
799     // Tools bar
800     Gtk::RadioAction::Group tools;
802     _act_grp->add(Gtk::RadioAction::create(tools, "ToolSelect",
803                                            Stock::TOOL_SELECT, Glib::ustring(),
804                                            _("PLACEHOLDER, do not translate")),
805                   sigc::mem_fun(*this, &EditWidget::onSelectTool));
807     _act_grp->add(Gtk::RadioAction::create(tools, "ToolNode",
808                                            Stock::TOOL_NODE, Glib::ustring(),
809                                            _("PLACEHOLDER, do not translate")),
810                   sigc::mem_fun(*this, &EditWidget::onNodeTool));
812     _act_grp->add(Gtk::RadioAction::create(tools, "ToolZoom",
813                                            Stock::TOOL_ZOOM, Glib::ustring(),
814                                            _("PLACEHOLDER, do not translate")));
816     _act_grp->add(Gtk::RadioAction::create(tools, "ToolRect",
817                                            Stock::TOOL_RECT, Glib::ustring(),
818                                            _("PLACEHOLDER, do not translate")));
820     _act_grp->add(Gtk::RadioAction::create(tools, "ToolArc",
821                                            Stock::TOOL_ARC, Glib::ustring(),
822                                            _("PLACEHOLDER, do not translate")));
824     _act_grp->add(Gtk::RadioAction::create(tools, "ToolStar",
825                                            Stock::TOOL_STAR, Glib::ustring(),
826                                            _("PLACEHOLDER, do not translate")));
828     _act_grp->add(Gtk::RadioAction::create(tools, "ToolSpiral",
829                                            Stock::TOOL_SPIRAL, Glib::ustring(),
830                                            _("PLACEHOLDER, do not translate")));
832     _act_grp->add(Gtk::RadioAction::create(tools, "ToolFreehand",
833                                            Stock::TOOL_FREEHAND, Glib::ustring(),
834                                            _("PLACEHOLDER, do not translate")));
836     _act_grp->add(Gtk::RadioAction::create(tools, "ToolPen",
837                                            Stock::TOOL_PEN, Glib::ustring(),
838                                            _("PLACEHOLDER, do not translate")));
840     _act_grp->add(Gtk::RadioAction::create(tools, "ToolDynaDraw",
841                                            Stock::TOOL_DYNADRAW, Glib::ustring(),
842                                            _("PLACEHOLDER, do not translate")));
844     _act_grp->add(Gtk::RadioAction::create(tools, "ToolText",
845                                            Stock::TOOL_TEXT, Glib::ustring(),
846                                            _("PLACEHOLDER, do not translate")));
848     _act_grp->add(Gtk::RadioAction::create(tools, "ToolDropper",
849                                            Stock::TOOL_DROPPER, Glib::ustring(),
850                                            _("PLACEHOLDER, do not translate")));
852     // Select Controls bar
853     _act_grp->add(Gtk::ToggleAction::create("TransformStroke",
854                                             Stock::TRANSFORM_STROKE, Glib::ustring(),
855                                             _("PLACEHOLDER, do not translate")));
857     _act_grp->add(Gtk::ToggleAction::create("TransformCorners",
858                                             Stock::TRANSFORM_CORNERS, Glib::ustring(),
859                                             _("PLACEHOLDER, do not translate")));
861     _act_grp->add(Gtk::ToggleAction::create("TransformGradient",
862                                             Stock::TRANSFORM_GRADIENT, Glib::ustring(),
863                                             _("PLACEHOLDER, do not translate")));
865     _act_grp->add(Gtk::ToggleAction::create("TransformPattern",
866                                             Stock::TRANSFORM_PATTERN, Glib::ustring(),
867                                             _("PLACEHOLDER, do not translate")));
869     // Node Controls bar
870     _act_grp->add(Gtk::Action::create("NodeInsert",
871                                       Gtk::Stock::ADD, Glib::ustring(),
872                                       _("PLACEHOLDER, do not translate")));
874     _act_grp->add(Gtk::Action::create("NodeDelete",
875                                       Gtk::Stock::REMOVE, Glib::ustring(),
876                                       _("PLACEHOLDER, do not translate")));
878     _act_grp->add(Gtk::Action::create("NodeJoin",
879                                       Stock::NODE_JOIN, Glib::ustring(),
880                                       _("PLACEHOLDER, do not translate")));
882     _act_grp->add(Gtk::Action::create("NodeJoinSegment",
883                                       Stock::NODE_JOIN_SEGMENT, Glib::ustring(),
884                                       _("PLACEHOLDER, do not translate")));
886     _act_grp->add(Gtk::Action::create("NodeDeleteSegment",
887                                       Stock::NODE_DELETE_SEGMENT, Glib::ustring(),
888                                       _("PLACEHOLDER, do not translate")));
890     _act_grp->add(Gtk::Action::create("NodeBreak",
891                                       Stock::NODE_BREAK, Glib::ustring(),
892                                       _("PLACEHOLDER, do not translate")));
894     _act_grp->add(Gtk::Action::create("NodeCorner",
895                                       Stock::NODE_CORNER, Glib::ustring(),
896                                       _("PLACEHOLDER, do not translate")));
898     _act_grp->add(Gtk::Action::create("NodeSmooth",
899                                       Stock::NODE_SMOOTH, Glib::ustring(),
900                                       _("PLACEHOLDER, do not translate")));
902     _act_grp->add(Gtk::Action::create("NodeSymmetric",
903                                       Stock::NODE_SYMMETRIC, Glib::ustring(),
904                                       _("PLACEHOLDER, do not translate")));
906     _act_grp->add(Gtk::Action::create("NodeLine",
907                                       Stock::NODE_LINE, Glib::ustring(),
908                                       _("PLACEHOLDER, do not translate")));
910     _act_grp->add(Gtk::Action::create("NodeCurve",
911                                       Stock::NODE_CURVE, Glib::ustring(),
912                                       _("PLACEHOLDER, do not translate")));
915 void
916 EditWidget::initAccelMap()
918     gchar *filename = g_build_filename(INKSCAPE_UIDIR, "keybindings.rc", NULL);
919     Gtk::AccelMap::load(filename);
920     g_free(filename);
922     // One problem is that the keys 1-6 are zoom accelerators which get
923     // caught as accelerator _before_ any Entry input handler receives them,
924     // for example the zoom status. At the moment, the best way seems to
925     // disable them as accelerators when the Entry gets focus, and enable
926     // them when focus goes elsewhere. The code for this belongs here,
927     // and not in zoom-status.cpp .
929     _zoom_status.signal_focus_in_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusIn));
930     _zoom_status.signal_focus_out_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusOut));
933 bool
934 EditWidget::onEntryFocusIn (GdkEventFocus* ev)
936     Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
937     Gtk::AccelMap::change_entry ("<Actions>//Zoom100", 0, m, false);
938     Gtk::AccelMap::change_entry ("<Actions>//Zoom50", 0, m, false);
939     Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", 0, m, false);
940     Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", 0, m, false);
941     Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", 0, m, false);
942     Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", 0, m, false);
943     return false;
946 bool
947 EditWidget::onEntryFocusOut (GdkEventFocus* ev)
949     Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
950     Gtk::AccelMap::change_entry ("<Actions>//Zoom100", '1', m, false);
951     Gtk::AccelMap::change_entry ("<Actions>//Zoom50", '2', m, false);
952     Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", '3', m, false);
953     Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", '4', m, false);
954     Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", '5', m, false);
955     Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", '6', m, false);
956     return false;
959 void
960 EditWidget::initMenuBar()
962     g_assert(_ui_mgr);
963     Gtk::MenuBar *menu = static_cast<Gtk::MenuBar*>(_ui_mgr->get_widget("/MenuBar"));
964     g_assert(menu != NULL);
965     _main_window_table.attach(*Gtk::manage(menu), 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
968 void
969 EditWidget::initCommandsBar()
971     g_assert(_ui_mgr);
972     Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/CommandsBar")),
973                                Gtk::TOOLBAR_ICONS);
974     g_assert(bar != NULL);
975     _toolbars_vbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
978 void
979 EditWidget::initToolControlsBar()
981     // TODO: Do UIManager controlled widgets need to be deleted?
982     _select_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/SelectControlsBar"));
983     _node_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/NodeControlsBar"));
985     _tool_ctrl = new Toolbox(_select_ctrl, Gtk::TOOLBAR_ICONS);
987     _toolbars_vbox.pack_start(*Gtk::manage(_tool_ctrl), Gtk::PACK_SHRINK);
990 void
991 EditWidget::initUriBar()
993     /// \todo  Create an Inkscape::UI::Widget::UriBar class (?)
995     _uri_ctrl = new Gtk::Toolbar();
997     _uri_label.set_label(_("PLACEHOLDER, DO NOT TRANSLATE"));
998     _uri_ctrl->add(_uri_label);
999     _uri_ctrl->add(_uri_entry);
1001     _uri_entry.signal_activate()
1002         .connect_notify(sigc::mem_fun(*this, &EditWidget::onUriChanged));
1004     _toolbars_vbox.pack_start(*Gtk::manage(_uri_ctrl), Gtk::PACK_SHRINK);
1007 void
1008 EditWidget::initToolsBar()
1010     Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/ToolsBar")),
1011                                Gtk::TOOLBAR_ICONS,
1012                                Gtk::ORIENTATION_VERTICAL);
1013     g_assert(bar != NULL);
1014     _sub_window_hbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
1017 void
1018 EditWidget::initTopRuler()
1020     _viewport_table.attach(_top_ruler,  1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1022     _tooltips.set_tip (_top_ruler, _top_ruler.get_tip());
1025 void
1026 EditWidget::initLeftRuler()
1028     _viewport_table.attach(_left_ruler, 0, 1, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1030     _tooltips.set_tip (_left_ruler, _left_ruler.get_tip());
1033 void
1034 EditWidget::initBottomScrollbar()
1036     _viewport_table.attach(_bottom_scrollbar, 1, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1037     _bottom_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1038     _bottom_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1041 void
1042 EditWidget::initRightScrollbar()
1044     _viewport_table.attach(_right_scrollbar, 2, 3, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1046     _right_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1047     _right_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1050 void
1051 EditWidget::initStickyZoom()
1053     _viewport_table.attach(_sticky_zoom, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
1055     _sticky_zoom.set_active (prefs_get_int_attribute ("options.stickyzoom", "value", 0) != 0);
1056     _tooltips.set_tip (_sticky_zoom, _("Zoom drawing if window size changes"));
1058     /// \todo icon not implemented
1061 void
1062 EditWidget::initStatusbar()
1064     _statusbar.pack_start (_selected_style_status, false, false, 1);
1065     _statusbar.pack_start (*new Gtk::VSeparator(), false, false, 0);
1067     _tooltips.set_tip (_zoom_status, _("Zoom"));
1069     _layer_selector.reference();
1070     _statusbar.pack_start (_layer_selector, false, false, 1);
1072     _coord_status.property_n_rows() = 2;
1073     _coord_status.property_n_columns() = 5;
1074     _coord_status.property_row_spacing() = 0;
1075     _coord_status.property_column_spacing() = 2;
1076     _coord_eventbox.add (_coord_status);
1077     _tooltips.set_tip (_coord_eventbox, _("Cursor coordinates"));
1078     _coord_status.attach (*new Gtk::VSeparator(), 0,1, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1079     _coord_status.attach (*new Gtk::Label("X:", 0.0, 0.5), 1,2, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1080     _coord_status.attach (*new Gtk::Label("Y:", 0.0, 0.5), 1,2, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1081     _coord_status_x.set_text ("0.0");
1082     _coord_status_x.set_alignment (0.0, 0.5);
1083     _coord_status_y.set_text ("0.0");
1084     _coord_status_y.set_alignment (0.0, 0.5);
1085     _coord_status.attach (_coord_status_x, 2,3, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1086     _coord_status.attach (_coord_status_y, 2,3, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1087     _coord_status.attach (*new Gtk::Label("Z:", 0.0, 0.5), 3,4, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1088     _coord_status.attach (_zoom_status, 4,5, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1089     sp_set_font_size_smaller (static_cast<GtkWidget*>((void*)_coord_status.gobj()));
1090     _statusbar.pack_end (_coord_eventbox, false, false, 1);
1092     _select_status.property_xalign() = 0.0;
1093     _select_status.property_yalign() = 0.5;
1094     _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."));
1095     // include this again with Gtk+-2.6
1096 #if GTK_VERSION_GE(2,6)
1097      gtk_label_set_ellipsize (GTK_LABEL(_select_status.gobj()), PANGO_ELLIPSIZE_END);
1098 #endif
1099     _select_status.set_size_request (1, -1);
1100     _statusbar.pack_start (_select_status, true, true, 0);
1102     _main_window_table.attach(_statusbar, 0, 1, 3, 4, Gtk::FILL, Gtk::SHRINK);
1105 //========================================
1106 //----------implements EditWidgetInterface
1108 void *
1109 EditWidget::getWindow()
1111     return this;
1114 void
1115 EditWidget::setTitle (gchar const* new_title)
1117     set_title (new_title);
1120 void
1121 EditWidget::layout()
1123    show_all_children();
1126 void
1127 EditWidget::present()
1129     this->Gtk::Window::present();
1132 void
1133 EditWidget::getGeometry (gint &x, gint &y, gint &w, gint &h)
1135     get_position (x, y);
1136     get_size (w, h);
1139 void
1140 EditWidget::setSize (gint w, gint h)
1142     resize (w, h);
1145 void
1146 EditWidget::setPosition (NR::Point p)
1148     move (int(p[NR::X]), int(p[NR::Y]));
1151 /// \param p is already gobj()!
1152 void
1153 EditWidget::setTransient (void* p, int i)
1155 #ifndef WIN32
1156     gtk_window_set_transient_for (static_cast<GtkWindow*>(p), this->gobj());
1157     if (i==2)
1158         this->Gtk::Window::present();
1159 #endif
1162 NR::Point
1163 EditWidget::getPointer()
1165     int x, y;
1166     get_pointer (x, y);
1167     return NR::Point (x, y);
1170 void
1171 EditWidget::setFullscreen()
1173     fullscreen();
1176 /**
1177  *  Shuts down the desktop object for the view being closed.  It checks
1178  *  to see if the document has been edited, and if so prompts the user
1179  *  to save, discard, or cancel.  Returns TRUE if the shutdown operation
1180  *  is cancelled or if the save is cancelled or fails, FALSE otherwise.
1181  */
1182 bool
1183 EditWidget::shutdown()
1185     g_assert (_desktop != NULL);
1186     if (Inkscape::NSApplication::Editor::isDuplicatedView (_desktop))
1187         return false;
1189     SPDocument *doc = _desktop->doc();
1190     if (sp_document_repr_root(doc)->attribute("sodipodi:modified") != NULL)
1191     {
1192         gchar *markup;
1193         /// \todo FIXME !!! obviously this will have problems if the document
1194         /// name contains markup characters
1195         markup = g_strdup_printf(
1196                 _("<span weight=\"bold\" size=\"larger\">Save changes to document \"%s\" before closing?</span>\n\n"
1197                   "If you close without saving, your changes will be discarded."),
1198                 SP_DOCUMENT_NAME(doc));
1200         Gtk::MessageDialog dlg (*this,
1201                        markup,
1202                        true,
1203                        Gtk::MESSAGE_WARNING,
1204                        Gtk::BUTTONS_NONE,
1205                        true);
1206         g_free(markup);
1207         Gtk::Button close_button (_("Close _without saving"), true);
1208         dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1209         close_button.show();
1210         dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1211         dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1212         dlg.set_default_response (Gtk::RESPONSE_YES);
1214         int response = dlg.run();
1215         switch (response)
1216         {
1217             case Gtk::RESPONSE_YES:
1218                 sp_document_ref(doc);
1219                 if (sp_file_save_document(doc)) {
1220                     sp_document_unref(doc);
1221                 } else { // save dialog cancelled or save failed
1222                     sp_document_unref(doc);
1223                     return TRUE;
1224                 }
1225                 break;
1226             case Gtk::RESPONSE_NO:
1227                 break;
1228             default: // cancel pressed, or dialog was closed
1229                 return TRUE;
1230                 break;
1231         }
1232     }
1234     /* Code to check data loss */
1235     bool allow_data_loss = FALSE;
1236     while (sp_document_repr_root(doc)->attribute("inkscape:dataloss") != NULL && allow_data_loss == FALSE)
1237     {
1238         gchar *markup;
1239         /// \todo FIXME !!! obviously this will have problems if the document
1240         /// name contains markup characters
1241         markup = g_strdup_printf(
1242                 _("<span weight=\"bold\" size=\"larger\">The file \"%s\" was saved with a format (%s) that may cause data loss!</span>\n\n"
1243                   "Do you want to save this file in another format?"),
1244                 SP_DOCUMENT_NAME(doc),
1245                 Inkscape::Extension::db.get(sp_document_repr_root(doc)->attribute("inkscape:output_extension"))->get_name());
1247         Gtk::MessageDialog dlg (*this,
1248                        markup,
1249                        true,
1250                        Gtk::MESSAGE_WARNING,
1251                        Gtk::BUTTONS_NONE,
1252                        true);
1253         g_free(markup);
1254         Gtk::Button close_button (_("Close _without saving"), true);
1255         dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1256         close_button.show();
1257         dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1258         dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1259         dlg.set_default_response (Gtk::RESPONSE_YES);
1261         int response = dlg.run();
1263         switch (response)
1264         {
1265             case Gtk::RESPONSE_YES:
1266                 sp_document_ref(doc);
1267                 if (sp_file_save_document(doc)) {
1268                     sp_document_unref(doc);
1269                 } else { // save dialog cancelled or save failed
1270                     sp_document_unref(doc);
1271                     return TRUE;
1272                 }
1273                 break;
1274             case Gtk::RESPONSE_NO:
1275                 allow_data_loss = TRUE;
1276                 break;
1277             default: // cancel pressed, or dialog was closed
1278                 return TRUE;
1279                 break;
1280         }
1281     }
1283     return false;
1287 void
1288 EditWidget::destroy()
1290     delete this;
1293 void
1294 EditWidget::requestCanvasUpdate()
1296     _svg_canvas.widget().queue_draw();
1299 void
1300 EditWidget::requestCanvasUpdateAndWait()
1302     requestCanvasUpdate();
1304     while (gtk_events_pending()) 
1305       gtk_main_iteration_do(FALSE);
1308 void
1309 EditWidget::enableInteraction()
1311   g_return_if_fail(_interaction_disabled_counter > 0);
1312   
1313   _interaction_disabled_counter--;
1314   
1315   if (_interaction_disabled_counter == 0) {
1316     this->set_sensitive(true);
1317   }
1320 void
1321 EditWidget::disableInteraction()
1323   if (_interaction_disabled_counter == 0) {
1324     this->set_sensitive(false);
1325   }
1326   
1327   _interaction_disabled_counter++;
1330 void
1331 EditWidget::activateDesktop()
1333     /// \todo active_desktop_indicator not implemented
1336 void
1337 EditWidget::deactivateDesktop()
1339     /// \todo active_desktop_indicator not implemented
1342 void
1343 EditWidget::viewSetPosition (NR::Point p)
1345     p -= _namedview->gridorigin;
1346     double lo, up, pos, max;
1347     _top_ruler.get_range (lo, up, pos, max);
1348     _top_ruler.set_range (lo, up, p[NR::X], max);
1349     _left_ruler.get_range (lo, up, pos, max);
1350     _left_ruler.set_range (lo, up, p[NR::Y], max);
1353 void
1354 EditWidget::updateRulers()
1356     NR::Point origin = _namedview->gridorigin;
1358     NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1359     double lo, up, pos, max;
1360     double const scale = _desktop->current_zoom();
1361     double s = viewbox.min()[NR::X] / scale - origin[NR::X];
1362     double e = viewbox.max()[NR::X] / scale - origin[NR::X];
1363     _top_ruler.get_range(lo, up, pos, max);
1364     _top_ruler.set_range(s, e, pos, e);
1365     s = viewbox.min()[NR::Y] / -scale - origin[NR::Y];
1366     e = viewbox.max()[NR::Y] / -scale - origin[NR::Y];
1367     _left_ruler.set_range(s, e, origin[NR::Y], e);
1368     /// \todo is that correct?
1371 void
1372 EditWidget::updateScrollbars (double scale)
1374     // do not call this function before canvas has its size allocated
1375     if (!is_realized() || _update_s_f) {
1376         return;
1377     }
1379     _update_s_f = true;
1381     /* The desktop region we always show unconditionally */
1382     SPDocument *doc = _desktop->doc();
1383     NR::Rect const r = sp_item_bbox_desktop(SP_ITEM(SP_DOCUMENT_ROOT(doc)));
1384     NR::Rect darea(NR::Point(MIN(r.min()[NR::X], -sp_document_width(doc)),
1385                              MIN(r.min()[NR::Y], -sp_document_height(doc))),
1386                    NR::Point(MAX(r.max()[NR::X], 2 * sp_document_width(doc)),
1387                              MAX(r.max()[NR::Y], 2 * sp_document_height(doc))));
1389     /* Canvas region we always show unconditionally */
1390     NR::Rect carea(NR::Point(darea.min()[NR::X] * scale - 64,
1391                              darea.max()[NR::Y] * -scale - 64),
1392                    NR::Point(darea.max()[NR::X] * scale + 64,
1393                              darea.min()[NR::Y] * -scale + 64));
1395     NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1397     /* Viewbox is always included into scrollable region */
1398     carea = NR::Rect::union_bounds(carea, viewbox);
1400     Gtk::Adjustment *adj = _bottom_scrollbar.get_adjustment();
1401     adj->set_value(viewbox.min()[NR::X]);
1402     adj->set_lower(carea.min()[NR::X]);
1403     adj->set_upper(carea.max()[NR::X]);
1404     adj->set_page_increment(viewbox.dimensions()[NR::X]);
1405     adj->set_step_increment(0.1 * (viewbox.dimensions()[NR::X]));
1406     adj->set_page_size(viewbox.dimensions()[NR::X]);
1408     adj = _right_scrollbar.get_adjustment();
1409     adj->set_value(viewbox.min()[NR::Y]);
1410     adj->set_lower(carea.min()[NR::Y]);
1411     adj->set_upper(carea.max()[NR::Y]);
1412     adj->set_page_increment(viewbox.dimensions()[NR::Y]);
1413     adj->set_step_increment(0.1 * viewbox.dimensions()[NR::Y]);
1414     adj->set_page_size(viewbox.dimensions()[NR::Y]);
1416     _update_s_f = false;
1419 void
1420 EditWidget::toggleRulers()
1422     if (_top_ruler.is_visible())
1423     {
1424         _top_ruler.hide_all();
1425         _left_ruler.hide_all();
1426         prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 0);
1427     } else {
1428         _top_ruler.show_all();
1429         _left_ruler.show_all();
1430         prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 1);
1431     }
1434 void
1435 EditWidget::toggleScrollbars()
1437     if (_bottom_scrollbar.is_visible())
1438     {
1439         _bottom_scrollbar.hide_all();
1440         _right_scrollbar.hide_all();
1441         prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 0);
1442     } else {
1443         _bottom_scrollbar.show_all();
1444         _right_scrollbar.show_all();
1445         prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 1);
1446     }
1449 void
1450 EditWidget::updateZoom()
1452     _zoom_status.update();
1455 void
1456 EditWidget::letZoomGrabFocus()
1458     _zoom_status.grab_focus();
1461 void
1462 EditWidget::setToolboxFocusTo (const gchar *)
1464     /// \todo not implemented
1467 void
1468 EditWidget::setToolboxAdjustmentValue (const gchar *, double)
1470     /// \todo not implemented
1473 bool
1474 EditWidget::isToolboxButtonActive (gchar const*)
1476     /// \todo not implemented
1477     return true;
1480 void
1481 EditWidget::setCoordinateStatus (NR::Point p)
1483     gchar *cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::X]);
1484     _coord_status_x.property_label() = cstr;
1485     g_free (cstr);
1486     cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::Y]);
1487     _coord_status_y.property_label() = cstr;
1488     g_free (cstr);
1491 void
1492 EditWidget::setMessage (Inkscape::MessageType type, gchar const* msg)
1494     _select_status.set_markup (msg? msg : "");
1497 bool
1498 EditWidget::warnDialog (gchar* msg)
1500     Gtk::MessageDialog dlg (*this,
1501                        msg,
1502                        true,
1503                        Gtk::MESSAGE_WARNING,
1504                        Gtk::BUTTONS_YES_NO,
1505                        true);
1506     int r = dlg.run();
1507     return r == Gtk::RESPONSE_YES;
1511 void EditWidget::_namedview_modified (SPObject *obj, guint flags) {
1512     SPNamedView *nv = static_cast<SPNamedView *>(obj);
1513     if (flags & SP_OBJECT_MODIFIED_FLAG) {
1514         this->_dt2r = 1.0 / nv->doc_units->unittobase;
1515         this->_top_ruler.update_metric();
1516         this->_left_ruler.update_metric();
1517         this->_tooltips.set_tip(this->_top_ruler, this->_top_ruler.get_tip());
1518         this->_tooltips.set_tip(this->_left_ruler, this->_left_ruler.get_tip());
1519         this->updateRulers();
1520     }
1523 void
1524 EditWidget::initEdit (SPDocument *doc)
1526     _desktop = new SPDesktop();
1527     _desktop->registerEditWidget (this);
1529     _namedview = sp_document_namedview (doc, 0);
1530     _svg_canvas.init (_desktop);
1531     _desktop->init (_namedview, _svg_canvas.spobj());
1532     sp_namedview_window_from_document (_desktop);
1533     sp_namedview_update_layers_from_document (_desktop);
1534     _dt2r = 1.0 / _namedview->doc_units->unittobase;
1536     /// \todo convert to sigc++ when SPObject hierarchy gets converted
1537     /* Listen on namedview modification */
1538     _namedview_modified_connection = _desktop->namedview->connectModified(sigc::mem_fun(*this, &EditWidget::_namedview_modified));
1539     _layer_selector.setDesktop (_desktop);
1540     _selected_style_status.setDesktop (_desktop);
1542     Inkscape::NSApplication::Editor::addDesktop (_desktop);
1544     _zoom_status.init (_desktop);
1545     _top_ruler.init (_desktop, _svg_canvas.widget());
1546     _left_ruler.init (_desktop, _svg_canvas.widget());
1547     updateRulers();
1550 void
1551 EditWidget::destroyEdit()
1553     if (_desktop) {
1554         _layer_selector.unreference();
1555         Inkscape::NSApplication::Editor::removeDesktop (_desktop); // clears selection too
1556         _namedview_modified_connection.disconnect();
1557         _desktop->destroy();
1558         Inkscape::GC::release (_desktop);
1559         _desktop = 0;
1560     }
1563 //----------end of EditWidgetInterface implementation
1565 //----------start of other callbacks
1567 bool
1568 EditWidget::on_key_press_event (GdkEventKey* event)
1570     // this is the original code from helper/window.cpp
1572     unsigned int shortcut;
1573     shortcut = get_group0_keyval (event) |
1574                    ( event->state & GDK_SHIFT_MASK ?
1575                      SP_SHORTCUT_SHIFT_MASK : 0 ) |
1576                    ( event->state & GDK_CONTROL_MASK ?
1577                      SP_SHORTCUT_CONTROL_MASK : 0 ) |
1578                    ( event->state & GDK_MOD1_MASK ?
1579                      SP_SHORTCUT_ALT_MASK : 0 );
1580     return sp_shortcut_invoke (shortcut,
1581                              Inkscape::NSApplication::Editor::getActiveDesktop());
1584 bool
1585 EditWidget::on_delete_event (GdkEventAny*)
1587     return shutdown();
1590 bool
1591 EditWidget::on_focus_in_event (GdkEventFocus*)
1593     Inkscape::NSApplication::Editor::activateDesktop (_desktop);
1594     _svg_canvas.widget().grab_focus();
1596     return false;
1599 void
1600 EditWidget::onWindowSizeAllocate (Gtk::Allocation &newall)
1602     if (!is_realized()) return;
1604     const Gtk::Allocation& all = get_allocation();
1605     if ((newall.get_x() == all.get_x()) &&
1606         (newall.get_y() == all.get_y()) &&
1607         (newall.get_width() == all.get_width()) &&
1608         (newall.get_height() == all.get_height())) {
1609         return;
1610     }
1612     NR::Rect const area = _desktop->get_display_area();
1613     double zoom = _desktop->current_zoom();
1615     if (_sticky_zoom.get_active()) {
1616         /* Calculate zoom per pixel */
1617         double const zpsp = zoom / hypot(area.dimensions()[NR::X], area.dimensions()[NR::Y]);
1618         /* Find new visible area */
1619         NR::Rect const newarea = _desktop->get_display_area();
1620         /* Calculate adjusted zoom */
1621         zoom = zpsp * hypot(newarea.dimensions()[NR::X], newarea.dimensions()[NR::Y]);
1622     }
1624     _desktop->zoom_absolute(area.midpoint()[NR::X], area.midpoint()[NR::Y], zoom);
1627 void
1628 EditWidget::onWindowRealize()
1630     NR::Rect d(NR::Point(0, 0),
1631                NR::Point(sp_document_width(_desktop->doc()), sp_document_height(_desktop->doc())));
1633     if (fabs(d.dimensions()[NR::X]) < 1.0 || fabs(d.dimensions()[NR::Y]) < 1.0) {
1634         return;
1635     }
1637     _desktop->set_display_area(d.min()[NR::X], d.min()[NR::Y], d.max()[NR::X], d.max()[NR::Y], 10);
1638     _namedview_modified(_desktop->namedview, SP_OBJECT_MODIFIED_FLAG);
1639     setTitle (SP_DOCUMENT_NAME(_desktop->doc()));
1642 void
1643 EditWidget::onAdjValueChanged()
1645     if (_update_a_f) return;
1646     _update_a_f = true;
1648     sp_canvas_scroll_to (_svg_canvas.spobj(),
1649                          _bottom_scrollbar.get_value(),
1650                          _right_scrollbar.get_value(),
1651                          false);
1652     updateRulers();
1654     _update_a_f = false;
1658 } // namespace View
1659 } // namespace UI
1660 } // namespace Inkscape
1662 /*
1663   Local Variables:
1664   mode:c++
1665   c-file-style:"stroustrup"
1666   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1667   indent-tabs-mode:nil
1668   fill-column:99
1669   End:
1670 */
1671 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :