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 "preferences.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()
100 {
101 destroyEdit();
102 }
104 void
105 EditWidget::initActions()
106 {
107 initMenuActions();
108 initToolbarActions();
109 }
111 void
112 EditWidget::initUIManager()
113 {
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);
123 }
125 void
126 EditWidget::initLayout()
127 {
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();
163 }
165 void
166 EditWidget::onMenuItem()
167 {
168 g_warning("onMenuItem called");
169 }
171 void
172 EditWidget::onActionFileNew()
173 {
174 // g_warning("onActionFileNew called");
175 sp_file_new_default();
176 }
178 void
179 EditWidget::onActionFileOpen()
180 {
181 // g_warning("onActionFileOpen called");
182 sp_file_open_dialog (*this, NULL, NULL);
183 }
185 void
186 EditWidget::onActionFileQuit()
187 {
188 g_warning("onActionFileQuit");
189 sp_ui_close_all();
190 }
192 void
193 EditWidget::onActionFilePrint()
194 {
195 g_warning("onActionFilePrint");
196 }
198 void
199 EditWidget::onToolbarItem()
200 {
201 g_warning("onToolbarItem called");
202 }
204 void
205 EditWidget::onSelectTool()
206 {
207 _tool_ctrl->remove();
208 _tool_ctrl->add(*_select_ctrl);
209 }
211 void
212 EditWidget::onNodeTool()
213 {
214 _tool_ctrl->remove();
215 _tool_ctrl->add(*_node_ctrl);
216 }
218 void
219 EditWidget::onDialogInkscapePreferences()
220 {
221 _dlg_mgr.showDialog("InkscapePreferences");
222 }
224 void
225 EditWidget::onDialogAbout()
226 {
227 }
229 void
230 EditWidget::onDialogAlignAndDistribute()
231 {
232 _dlg_mgr.showDialog("AlignAndDistribute");
233 }
235 void
236 EditWidget::onDialogDocumentProperties()
237 {
238 // manage (Inkscape::UI::Dialog::DocumentPreferences::create());
239 _dlg_mgr.showDialog("DocumentPreferences");
240 }
242 void
243 EditWidget::onDialogExport()
244 {
245 _dlg_mgr.showDialog("Export");
246 }
248 void
249 EditWidget::onDialogExtensionEditor()
250 {
251 _dlg_mgr.showDialog("ExtensionEditor");
252 }
254 void
255 EditWidget::onDialogFillAndStroke()
256 {
257 _dlg_mgr.showDialog("FillAndStroke");
258 }
260 void
261 EditWidget::onDialogFind()
262 {
263 _dlg_mgr.showDialog("Find");
264 }
266 void
267 EditWidget::onDialogLayerEditor()
268 {
269 _dlg_mgr.showDialog("LayerEditor");
270 }
272 void
273 EditWidget::onDialogMessages()
274 {
275 _dlg_mgr.showDialog("Messages");
276 }
278 void
279 EditWidget::onDialogObjectProperties()
280 {
281 _dlg_mgr.showDialog("ObjectProperties");
282 }
284 void
285 EditWidget::onDialogTextProperties()
286 {
287 _dlg_mgr.showDialog("TextProperties");
288 }
290 void
291 EditWidget::onDialogTrace()
292 {
293 }
295 void
296 EditWidget::onDialogTransformation()
297 {
298 _dlg_mgr.showDialog("Transformation");
299 }
301 void
302 EditWidget::onDialogXmlEditor()
303 {
304 _dlg_mgr.showDialog("XmlEditor");
305 }
307 void
308 EditWidget::onUriChanged()
309 {
310 g_message("onUriChanged called");
312 }
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()
319 {
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));
800 }
802 void
803 EditWidget::initToolbarActions()
804 {
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")));
919 }
921 void
922 EditWidget::initAccelMap()
923 {
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));
937 }
939 bool
940 EditWidget::onEntryFocusIn (GdkEventFocus* /*ev*/)
941 {
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;
950 }
952 bool
953 EditWidget::onEntryFocusOut (GdkEventFocus* /*ev*/)
954 {
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;
963 }
965 void
966 EditWidget::initMenuBar()
967 {
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);
972 }
974 void
975 EditWidget::initCommandsBar()
976 {
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);
982 }
984 void
985 EditWidget::initToolControlsBar()
986 {
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);
994 }
996 void
997 EditWidget::initUriBar()
998 {
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);
1011 }
1013 void
1014 EditWidget::initToolsBar()
1015 {
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);
1021 }
1023 void
1024 EditWidget::initTopRuler()
1025 {
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());
1029 }
1031 void
1032 EditWidget::initLeftRuler()
1033 {
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());
1037 }
1039 void
1040 EditWidget::initBottomScrollbar()
1041 {
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);
1045 }
1047 void
1048 EditWidget::initRightScrollbar()
1049 {
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);
1054 }
1056 void
1057 EditWidget::initStickyZoom()
1058 {
1059 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1060 _viewport_table.attach(_sticky_zoom, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
1061 _sticky_zoom.set_active (prefs->getBool("/options/stickyzoom/value"));
1062 _tooltips.set_tip (_sticky_zoom, _("Zoom drawing if window size changes"));
1064 /// \todo icon not implemented
1065 }
1067 void
1068 EditWidget::initStatusbar()
1069 {
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 drawing 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);
1109 }
1111 //========================================
1112 //----------implements EditWidgetInterface
1114 Gtk::Window *
1115 EditWidget::getWindow()
1116 {
1117 return this;
1118 }
1120 void
1121 EditWidget::setTitle (gchar const* new_title)
1122 {
1123 set_title (new_title);
1124 }
1126 void
1127 EditWidget::layout()
1128 {
1129 show_all_children();
1130 }
1132 void
1133 EditWidget::present()
1134 {
1135 this->Gtk::Window::present();
1136 }
1138 void
1139 EditWidget::getGeometry (gint &x, gint &y, gint &w, gint &h)
1140 {
1141 get_position (x, y);
1142 get_size (w, h);
1143 }
1145 void
1146 EditWidget::setSize (gint w, gint h)
1147 {
1148 resize (w, h);
1149 }
1151 void
1152 EditWidget::setPosition (Geom::Point p)
1153 {
1154 move (int(p[Geom::X]), int(p[Geom::Y]));
1155 }
1157 /// \param p is already gobj()!
1158 void
1159 EditWidget::setTransient (void* p, int i)
1160 {
1161 gtk_window_set_transient_for (static_cast<GtkWindow*>(p), this->gobj());
1162 if (i==2)
1163 this->Gtk::Window::present();
1164 }
1166 Geom::Point
1167 EditWidget::getPointer()
1168 {
1169 int x, y;
1170 get_pointer (x, y);
1171 return Geom::Point (x, y);
1172 }
1174 void
1175 EditWidget::setIconified()
1176 {
1177 iconify();
1178 }
1180 void
1181 EditWidget::setMaximized()
1182 {
1183 maximize();
1184 }
1186 void
1187 EditWidget::setFullscreen()
1188 {
1189 fullscreen();
1190 }
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()
1200 {
1201 g_assert (_desktop != NULL);
1202 if (Inkscape::NSApplication::Editor::isDuplicatedView (_desktop))
1203 return false;
1205 SPDocument *doc = _desktop->doc();
1206 if (doc->isModifiedSinceSave()) {
1207 gchar *markup;
1208 /// \todo FIXME !!! obviously this will have problems if the document
1209 /// name contains markup characters
1210 markup = g_strdup_printf(
1211 _("<span weight=\"bold\" size=\"larger\">Save changes to document \"%s\" before closing?</span>\n\n"
1212 "If you close without saving, your changes will be discarded."),
1213 SP_DOCUMENT_NAME(doc));
1215 Gtk::MessageDialog dlg (*this,
1216 markup,
1217 true,
1218 Gtk::MESSAGE_WARNING,
1219 Gtk::BUTTONS_NONE,
1220 true);
1221 g_free(markup);
1222 Gtk::Button close_button (_("Close _without saving"), true);
1223 dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1224 close_button.show();
1225 dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1226 dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1227 dlg.set_default_response (Gtk::RESPONSE_YES);
1229 int response = dlg.run();
1230 switch (response)
1231 {
1232 case Gtk::RESPONSE_YES:
1233 sp_document_ref(doc);
1234 if (sp_file_save_document(*this, doc)) {
1235 sp_document_unref(doc);
1236 } else { // save dialog cancelled or save failed
1237 sp_document_unref(doc);
1238 return TRUE;
1239 }
1240 break;
1241 case Gtk::RESPONSE_NO:
1242 break;
1243 default: // cancel pressed, or dialog was closed
1244 return TRUE;
1245 break;
1246 }
1247 }
1249 /* Code to check data loss */
1250 bool allow_data_loss = FALSE;
1251 while (sp_document_repr_root(doc)->attribute("inkscape:dataloss") != NULL && allow_data_loss == FALSE)
1252 {
1253 gchar *markup;
1254 /// \todo FIXME !!! obviously this will have problems if the document
1255 /// name contains markup characters
1256 markup = g_strdup_printf(
1257 _("<span weight=\"bold\" size=\"larger\">The file \"%s\" was saved with a format (%s) that may cause data loss!</span>\n\n"
1258 "Do you want to save this file as an Inkscape SVG?"),
1259 SP_DOCUMENT_NAME(doc),
1260 Inkscape::Extension::db.get(sp_document_repr_root(doc)->attribute("inkscape:output_extension"))->get_name());
1262 Gtk::MessageDialog dlg (*this,
1263 markup,
1264 true,
1265 Gtk::MESSAGE_WARNING,
1266 Gtk::BUTTONS_NONE,
1267 true);
1268 g_free(markup);
1269 Gtk::Button close_button (_("Close _without saving"), true);
1270 dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1271 close_button.show();
1272 Gtk::Button save_button (_("_Save as SVG"), true);
1273 dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1274 dlg.add_action_widget (save_button, Gtk::RESPONSE_YES);
1275 save_button.show();
1276 dlg.set_default_response (Gtk::RESPONSE_YES);
1278 int response = dlg.run();
1280 switch (response)
1281 {
1282 case Gtk::RESPONSE_YES:
1283 sp_document_ref(doc);
1284 if (sp_file_save_document(*this, doc)) {
1285 sp_document_unref(doc);
1286 } else { // save dialog cancelled or save failed
1287 sp_document_unref(doc);
1288 return TRUE;
1289 }
1290 break;
1291 case Gtk::RESPONSE_NO:
1292 allow_data_loss = TRUE;
1293 break;
1294 default: // cancel pressed, or dialog was closed
1295 return TRUE;
1296 break;
1297 }
1298 }
1300 return false;
1301 }
1304 void
1305 EditWidget::destroy()
1306 {
1307 delete this;
1308 }
1310 void
1311 EditWidget::requestCanvasUpdate()
1312 {
1313 _svg_canvas.widget().queue_draw();
1314 }
1316 void
1317 EditWidget::requestCanvasUpdateAndWait()
1318 {
1319 requestCanvasUpdate();
1321 while (gtk_events_pending())
1322 gtk_main_iteration_do(FALSE);
1323 }
1325 void
1326 EditWidget::enableInteraction()
1327 {
1328 g_return_if_fail(_interaction_disabled_counter > 0);
1330 _interaction_disabled_counter--;
1332 if (_interaction_disabled_counter == 0) {
1333 this->set_sensitive(true);
1334 }
1335 }
1337 void
1338 EditWidget::disableInteraction()
1339 {
1340 if (_interaction_disabled_counter == 0) {
1341 this->set_sensitive(false);
1342 }
1344 _interaction_disabled_counter++;
1345 }
1347 void
1348 EditWidget::activateDesktop()
1349 {
1350 /// \todo active_desktop_indicator not implemented
1351 }
1353 void
1354 EditWidget::deactivateDesktop()
1355 {
1356 /// \todo active_desktop_indicator not implemented
1357 }
1359 void
1360 EditWidget::viewSetPosition (Geom::Point p)
1361 {
1362 // p -= _namedview->gridorigin;
1363 /// \todo Why was the origin corrected for the grid origin? (johan)
1365 double lo, up, pos, max;
1366 _top_ruler.get_range (lo, up, pos, max);
1367 _top_ruler.set_range (lo, up, p[Geom::X], max);
1368 _left_ruler.get_range (lo, up, pos, max);
1369 _left_ruler.set_range (lo, up, p[Geom::Y], max);
1370 }
1372 void
1373 EditWidget::updateRulers()
1374 {
1375 //Geom::Point gridorigin = _namedview->gridorigin;
1376 /// \todo Why was the origin corrected for the grid origin? (johan)
1378 Geom::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1379 double lo, up, pos, max;
1380 double const scale = _desktop->current_zoom();
1381 double s = viewbox.min()[Geom::X] / scale; //- gridorigin[Geom::X];
1382 double e = viewbox.max()[Geom::X] / scale; //- gridorigin[Geom::X];
1383 _top_ruler.get_range(lo, up, pos, max);
1384 _top_ruler.set_range(s, e, pos, e);
1385 s = viewbox.min()[Geom::Y] / -scale; //- gridorigin[Geom::Y];
1386 e = viewbox.max()[Geom::Y] / -scale; //- gridorigin[Geom::Y];
1387 _left_ruler.set_range(s, e, 0 /*gridorigin[Geom::Y]*/, e);
1388 /// \todo is that correct?
1389 }
1391 void
1392 EditWidget::updateScrollbars (double scale)
1393 {
1394 // do not call this function before canvas has its size allocated
1395 if (!is_realized() || _update_s_f) {
1396 return;
1397 }
1399 _update_s_f = true;
1401 /* The desktop region we always show unconditionally */
1402 SPDocument *doc = _desktop->doc();
1403 Geom::Rect darea ( Geom::Point(-sp_document_width(doc), -sp_document_height(doc)),
1404 Geom::Point(2 * sp_document_width(doc), 2 * sp_document_height(doc)) );
1405 SPObject* root = doc->root;
1406 SPItem* item = SP_ITEM(root);
1407 Geom::OptRect deskarea = Geom::unify(darea, sp_item_bbox_desktop(item));
1409 /* Canvas region we always show unconditionally */
1410 Geom::Rect carea( Geom::Point(deskarea->min()[Geom::X] * scale - 64, deskarea->max()[Geom::Y] * -scale - 64),
1411 Geom::Point(deskarea->max()[Geom::X] * scale + 64, deskarea->min()[Geom::Y] * -scale + 64) );
1413 Geom::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1415 /* Viewbox is always included into scrollable region */
1416 carea = Geom::unify(carea, viewbox);
1418 Gtk::Adjustment *adj = _bottom_scrollbar.get_adjustment();
1419 adj->set_value(viewbox.min()[Geom::X]);
1420 adj->set_lower(carea.min()[Geom::X]);
1421 adj->set_upper(carea.max()[Geom::X]);
1422 adj->set_page_increment(viewbox.dimensions()[Geom::X]);
1423 adj->set_step_increment(0.1 * (viewbox.dimensions()[Geom::X]));
1424 adj->set_page_size(viewbox.dimensions()[Geom::X]);
1426 adj = _right_scrollbar.get_adjustment();
1427 adj->set_value(viewbox.min()[Geom::Y]);
1428 adj->set_lower(carea.min()[Geom::Y]);
1429 adj->set_upper(carea.max()[Geom::Y]);
1430 adj->set_page_increment(viewbox.dimensions()[Geom::Y]);
1431 adj->set_step_increment(0.1 * viewbox.dimensions()[Geom::Y]);
1432 adj->set_page_size(viewbox.dimensions()[Geom::Y]);
1434 _update_s_f = false;
1435 }
1437 void
1438 EditWidget::toggleRulers()
1439 {
1440 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1441 if (_top_ruler.is_visible())
1442 {
1443 _top_ruler.hide_all();
1444 _left_ruler.hide_all();
1445 prefs->setBool(_desktop->is_fullscreen() ? "/fullscreen/rulers/state" : "/window/rulers/state", false);
1446 } else {
1447 _top_ruler.show_all();
1448 _left_ruler.show_all();
1449 prefs->setBool(_desktop->is_fullscreen() ? "/fullscreen/rulers/state" : "/window/rulers/state", true);
1450 }
1451 }
1453 void
1454 EditWidget::toggleScrollbars()
1455 {
1456 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1457 if (_bottom_scrollbar.is_visible())
1458 {
1459 _bottom_scrollbar.hide_all();
1460 _right_scrollbar.hide_all();
1461 prefs->setBool(_desktop->is_fullscreen() ? "/fullscreen/scrollbars/state" : "/window/scrollbars/state", false);
1462 } else {
1463 _bottom_scrollbar.show_all();
1464 _right_scrollbar.show_all();
1465 prefs->setBool(_desktop->is_fullscreen() ? "/fullscreen/scrollbars/state" : "/window/scrollbars/state", true);
1466 }
1467 }
1469 void EditWidget::toggleColorProfAdjust()
1470 {
1471 // TODO implement
1472 }
1474 void
1475 EditWidget::updateZoom()
1476 {
1477 _zoom_status.update();
1478 }
1480 void
1481 EditWidget::letZoomGrabFocus()
1482 {
1483 _zoom_status.grab_focus();
1484 }
1486 void
1487 EditWidget::setToolboxFocusTo (const gchar *)
1488 {
1489 /// \todo not implemented
1490 }
1492 void
1493 EditWidget::setToolboxAdjustmentValue (const gchar *, double)
1494 {
1495 /// \todo not implemented
1496 }
1498 void
1499 EditWidget::setToolboxSelectOneValue (const gchar *, gint)
1500 {
1501 /// \todo not implemented
1502 }
1504 bool
1505 EditWidget::isToolboxButtonActive (gchar const*)
1506 {
1507 /// \todo not implemented
1508 return true;
1509 }
1511 void
1512 EditWidget::setCoordinateStatus (Geom::Point p)
1513 {
1514 gchar *cstr = g_strdup_printf ("%6.2f", _dt2r * p[Geom::X]);
1515 _coord_status_x.property_label() = cstr;
1516 g_free (cstr);
1517 cstr = g_strdup_printf ("%6.2f", _dt2r * p[Geom::Y]);
1518 _coord_status_y.property_label() = cstr;
1519 g_free (cstr);
1520 }
1522 void
1523 EditWidget::setMessage (Inkscape::MessageType /*type*/, gchar const* msg)
1524 {
1525 _select_status.set_markup (msg? msg : "");
1526 }
1528 bool
1529 EditWidget::warnDialog (gchar* msg)
1530 {
1531 Gtk::MessageDialog dlg (*this,
1532 msg,
1533 true,
1534 Gtk::MESSAGE_WARNING,
1535 Gtk::BUTTONS_YES_NO,
1536 true);
1537 int r = dlg.run();
1538 return r == Gtk::RESPONSE_YES;
1539 }
1542 Inkscape::UI::Widget::Dock*
1543 EditWidget::getDock ()
1544 {
1545 return &_dock;
1546 }
1548 void EditWidget::_namedview_modified (SPObject *obj, guint flags) {
1549 SPNamedView *nv = static_cast<SPNamedView *>(obj);
1550 if (flags & SP_OBJECT_MODIFIED_FLAG) {
1551 this->_dt2r = 1.0 / nv->doc_units->unittobase;
1552 this->_top_ruler.update_metric();
1553 this->_left_ruler.update_metric();
1554 this->_tooltips.set_tip(this->_top_ruler, this->_top_ruler.get_tip());
1555 this->_tooltips.set_tip(this->_left_ruler, this->_left_ruler.get_tip());
1556 this->updateRulers();
1557 }
1558 }
1560 void
1561 EditWidget::initEdit (SPDocument *doc)
1562 {
1563 _desktop = new SPDesktop();
1564 _desktop->registerEditWidget (this);
1566 _namedview = sp_document_namedview (doc, 0);
1567 _svg_canvas.init (_desktop);
1568 _desktop->init (_namedview, _svg_canvas.spobj());
1569 sp_namedview_window_from_document (_desktop);
1570 sp_namedview_update_layers_from_document (_desktop);
1571 _dt2r = 1.0 / _namedview->doc_units->unittobase;
1573 /// \todo convert to sigc++ when SPObject hierarchy gets converted
1574 /* Listen on namedview modification */
1575 _namedview_modified_connection = _desktop->namedview->connectModified(sigc::mem_fun(*this, &EditWidget::_namedview_modified));
1576 _layer_selector.setDesktop (_desktop);
1577 _selected_style_status.setDesktop (_desktop);
1579 Inkscape::NSApplication::Editor::addDesktop (_desktop);
1581 _zoom_status.init (_desktop);
1582 _top_ruler.init (_desktop, _svg_canvas.widget());
1583 _left_ruler.init (_desktop, _svg_canvas.widget());
1584 updateRulers();
1585 }
1587 void
1588 EditWidget::destroyEdit()
1589 {
1590 if (_desktop) {
1591 _layer_selector.unreference();
1592 Inkscape::NSApplication::Editor::removeDesktop (_desktop); // clears selection too
1593 _namedview_modified_connection.disconnect();
1594 _desktop->destroy();
1595 Inkscape::GC::release (_desktop);
1596 _desktop = 0;
1597 }
1598 }
1600 //----------end of EditWidgetInterface implementation
1602 //----------start of other callbacks
1604 bool
1605 EditWidget::on_key_press_event (GdkEventKey* event)
1606 {
1607 // this is the original code from helper/window.cpp
1609 unsigned int shortcut;
1610 shortcut = get_group0_keyval (event) |
1611 ( event->state & GDK_SHIFT_MASK ?
1612 SP_SHORTCUT_SHIFT_MASK : 0 ) |
1613 ( event->state & GDK_CONTROL_MASK ?
1614 SP_SHORTCUT_CONTROL_MASK : 0 ) |
1615 ( event->state & GDK_MOD1_MASK ?
1616 SP_SHORTCUT_ALT_MASK : 0 );
1617 return sp_shortcut_invoke (shortcut,
1618 Inkscape::NSApplication::Editor::getActiveDesktop());
1619 }
1621 bool
1622 EditWidget::on_delete_event (GdkEventAny*)
1623 {
1624 return shutdown();
1625 }
1627 bool
1628 EditWidget::on_focus_in_event (GdkEventFocus*)
1629 {
1630 Inkscape::NSApplication::Editor::activateDesktop (_desktop);
1631 _svg_canvas.widget().grab_focus();
1633 return false;
1634 }
1636 void
1637 EditWidget::onWindowSizeAllocate (Gtk::Allocation &newall)
1638 {
1639 if (!is_realized()) return;
1641 const Gtk::Allocation& all = get_allocation();
1642 if ((newall.get_x() == all.get_x()) &&
1643 (newall.get_y() == all.get_y()) &&
1644 (newall.get_width() == all.get_width()) &&
1645 (newall.get_height() == all.get_height())) {
1646 return;
1647 }
1649 Geom::Rect const area = _desktop->get_display_area();
1650 double zoom = _desktop->current_zoom();
1652 if (_sticky_zoom.get_active()) {
1653 /* Calculate zoom per pixel */
1654 double const zpsp = zoom / hypot(area.dimensions()[Geom::X], area.dimensions()[Geom::Y]);
1655 /* Find new visible area */
1656 Geom::Rect const newarea = _desktop->get_display_area();
1657 /* Calculate adjusted zoom */
1658 zoom = zpsp * hypot(newarea.dimensions()[Geom::X], newarea.dimensions()[Geom::Y]);
1659 }
1661 _desktop->zoom_absolute(area.midpoint()[Geom::X], area.midpoint()[Geom::Y], zoom);
1662 }
1664 void
1665 EditWidget::onWindowRealize()
1666 {
1667 NR::Rect d( Geom::Point(0, 0),
1668 Geom::Point(sp_document_width(_desktop->doc()), sp_document_height(_desktop->doc())) );
1670 if (d.isEmpty(1.0)) {
1671 return;
1672 }
1674 _desktop->set_display_area(d.min()[Geom::X], d.min()[Geom::Y], d.max()[Geom::X], d.max()[Geom::Y], 10);
1675 _namedview_modified(_desktop->namedview, SP_OBJECT_MODIFIED_FLAG);
1676 setTitle (SP_DOCUMENT_NAME(_desktop->doc()));
1677 }
1679 void
1680 EditWidget::onAdjValueChanged()
1681 {
1682 if (_update_a_f) return;
1683 _update_a_f = true;
1685 sp_canvas_scroll_to (_svg_canvas.spobj(),
1686 _bottom_scrollbar.get_value(),
1687 _right_scrollbar.get_value(),
1688 false);
1689 updateRulers();
1691 _update_a_f = false;
1692 }
1695 } // namespace View
1696 } // namespace UI
1697 } // namespace Inkscape
1699 /*
1700 Local Variables:
1701 mode:c++
1702 c-file-style:"stroustrup"
1703 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1704 indent-tabs-mode:nil
1705 fill-column:99
1706 End:
1707 */
1708 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :