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"
54 #include "display/sodipodi-ctrlrect.h"
55 #include "helper/units.h"
56 #include "shortcuts.h"
57 #include "widgets/spw-utilities.h"
58 #include "event-context.h"
59 #include "document.h"
60 #include "sp-namedview.h"
61 #include "sp-item.h"
62 #include "interface.h"
63 #include "extension/db.h"
65 #include "ui/dialog/dialog-manager.h"
67 using namespace Inkscape::UI;
68 using namespace Inkscape::UI::Widget;
70 namespace Inkscape {
71 namespace UI {
72 namespace View {
74 EditWidget::EditWidget (SPDocument *doc)
75 : _main_window_table(4),
76 _viewport_table(3,3),
77 _act_grp(Gtk::ActionGroup::create()),
78 _ui_mgr(Gtk::UIManager::create()),
79 _update_s_f(false),
80 _update_a_f(false),
81 _interaction_disabled_counter(0)
82 {
83 g_warning("Creating new EditWidget");
85 _desktop = 0;
86 initActions();
87 initAccelMap();
88 initUIManager();
89 initLayout();
90 initEdit (doc);
91 g_warning("Done creating new EditWidget");
92 }
94 EditWidget::~EditWidget()
95 {
96 destroyEdit();
97 }
99 void
100 EditWidget::initActions()
101 {
102 initMenuActions();
103 initToolbarActions();
104 }
106 void
107 EditWidget::initUIManager()
108 {
109 _ui_mgr->insert_action_group(_act_grp);
110 add_accel_group(_ui_mgr->get_accel_group());
112 gchar *filename_utf8 = g_build_filename(INKSCAPE_UIDIR, "menus-bars.xml", NULL);
113 if (_ui_mgr->add_ui_from_file(filename_utf8) == 0) {
114 g_warning("Error merging ui from file '%s'", filename_utf8);
115 // fixme-charset: What charset should we pass to g_warning?
116 }
117 g_free(filename_utf8);
118 }
120 void
121 EditWidget::initLayout()
122 {
123 set_title("New document 1 - Inkscape");
124 set_resizable();
125 set_default_size(640, 480);
127 // top level window into which all other portions of the UI get inserted
128 add(_main_window_table);
129 // attach box for horizontal toolbars
130 _main_window_table.attach(_toolbars_vbox, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
131 // attach sub-window for viewport and vertical toolbars
132 _main_window_table.attach(_sub_window_hbox, 0, 1, 2, 3);
133 // viewport table with 3 rows by 3 columns
134 _sub_window_hbox.pack_end(_viewport_table);
136 // Menus and Bars
137 initMenuBar();
138 initCommandsBar();
139 initToolControlsBar();
140 initUriBar();
141 initToolsBar();
143 // Canvas Viewport
144 initLeftRuler();
145 initTopRuler();
146 initStickyZoom();
147 initBottomScrollbar();
148 initRightScrollbar();
149 _viewport_table.attach(_svg_canvas.widget(), 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
150 _svg_canvas.widget().show_all();
152 // The statusbar comes last and appears at the bottom of _main_window_table
153 initStatusbar();
155 signal_size_allocate().connect (sigc::mem_fun (*this, &EditWidget::onWindowSizeAllocate), false);
156 signal_realize().connect (sigc::mem_fun (*this, &EditWidget::onWindowRealize));
157 show_all_children();
158 }
160 void
161 EditWidget::onMenuItem()
162 {
163 g_warning("onMenuItem called");
164 }
166 void
167 EditWidget::onActionFileNew()
168 {
169 // g_warning("onActionFileNew called");
170 sp_file_new_default();
171 }
173 void
174 EditWidget::onActionFileOpen()
175 {
176 // g_warning("onActionFileOpen called");
177 sp_file_open_dialog (*this, NULL, NULL);
178 }
180 void
181 EditWidget::onActionFileQuit()
182 {
183 g_warning("onActionFileQuit");
184 sp_ui_close_all();
185 }
187 void
188 EditWidget::onActionFilePrint()
189 {
190 g_warning("onActionFilePrint");
191 }
193 void
194 EditWidget::onToolbarItem()
195 {
196 g_warning("onToolbarItem called");
197 }
199 void
200 EditWidget::onSelectTool()
201 {
202 _tool_ctrl->remove();
203 _tool_ctrl->add(*_select_ctrl);
204 }
206 void
207 EditWidget::onNodeTool()
208 {
209 _tool_ctrl->remove();
210 _tool_ctrl->add(*_node_ctrl);
211 }
213 void
214 EditWidget::onDialogInkscapePreferences()
215 {
216 _dlg_mgr.showDialog("InkscapePreferences");
217 }
219 void
220 EditWidget::onDialogAbout()
221 {
222 }
224 void
225 EditWidget::onDialogAlignAndDistribute()
226 {
227 _dlg_mgr.showDialog("AlignAndDistribute");
228 }
230 void
231 EditWidget::onDialogDocumentProperties()
232 {
233 // manage (Inkscape::UI::Dialog::DocumentPreferences::create());
234 _dlg_mgr.showDialog("DocumentPreferences");
235 }
237 void
238 EditWidget::onDialogExport()
239 {
240 _dlg_mgr.showDialog("Export");
241 }
243 void
244 EditWidget::onDialogExtensionEditor()
245 {
246 _dlg_mgr.showDialog("ExtensionEditor");
247 }
249 void
250 EditWidget::onDialogFillAndStroke()
251 {
252 _dlg_mgr.showDialog("FillAndStroke");
253 }
255 void
256 EditWidget::onDialogFind()
257 {
258 _dlg_mgr.showDialog("Find");
259 }
261 void
262 EditWidget::onDialogLayerEditor()
263 {
264 _dlg_mgr.showDialog("LayerEditor");
265 }
267 void
268 EditWidget::onDialogMessages()
269 {
270 _dlg_mgr.showDialog("Messages");
271 }
273 void
274 EditWidget::onDialogObjectProperties()
275 {
276 _dlg_mgr.showDialog("ObjectProperties");
277 }
279 void
280 EditWidget::onDialogTextProperties()
281 {
282 _dlg_mgr.showDialog("TextProperties");
283 }
285 void
286 EditWidget::onDialogTrace()
287 {
288 }
290 void
291 EditWidget::onDialogTransformation()
292 {
293 _dlg_mgr.showDialog("Transformation");
294 }
296 void
297 EditWidget::onDialogXmlEditor()
298 {
299 _dlg_mgr.showDialog("XmlEditor");
300 }
302 void
303 EditWidget::onUriChanged()
304 {
305 g_message("onUriChanged called");
307 }
309 // FIXME: strings are replaced by placeholders, NOT to be translated until the code is enabled
310 // See http://sourceforge.net/mailarchive/message.php?msg_id=11746016 for details
312 void
313 EditWidget::initMenuActions()
314 {
315 // This has no chance of working right now.
316 // Has to be converted to Gtk::Action::create_with_icon_name.
318 _act_grp->add(Gtk::Action::create("MenuFile", "File"));
319 _act_grp->add(Gtk::Action::create("MenuEdit", "Edit"));
320 _act_grp->add(Gtk::Action::create("MenuView", "View"));
321 _act_grp->add(Gtk::Action::create("MenuLayer", "Layer"));
322 _act_grp->add(Gtk::Action::create("MenuObject", "Object"));
323 _act_grp->add(Gtk::Action::create("MenuPath", "Path"));
324 _act_grp->add(Gtk::Action::create("MenuText", "Text"));
325 _act_grp->add(Gtk::Action::create("MenuHelp", "Help"));
327 // File menu
328 _act_grp->add(Gtk::Action::create("New",
329 Gtk::Stock::NEW, Glib::ustring(),
330 _("PLACEHOLDER, do not translate")),
331 sigc::mem_fun(*this, &EditWidget::onActionFileNew));
333 _act_grp->add(Gtk::Action::create("Open",
334 Gtk::Stock::OPEN, Glib::ustring(),
335 _("PLACEHOLDER, do not translate")),
336 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
337 /*
338 _act_grp->add(Gtk::Action::create("OpenRecent",
339 Stock::OPEN_RECENT));*/
341 _act_grp->add(Gtk::Action::create("Revert",
342 Gtk::Stock::REVERT_TO_SAVED, Glib::ustring(),
343 _("PLACEHOLDER, do not translate")),
344 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
346 _act_grp->add(Gtk::Action::create("Save",
347 Gtk::Stock::SAVE, Glib::ustring(),
348 _("PLACEHOLDER, do not translate")),
349 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
351 _act_grp->add(Gtk::Action::create("SaveAs",
352 Gtk::Stock::SAVE_AS, Glib::ustring(),
353 _("PLACEHOLDER, do not translate")),
354 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
355 /*
356 _act_grp->add(Gtk::Action::create("Import",
357 Stock::IMPORT, Glib::ustring(),
358 _("PLACEHOLDER, do not translate")),
359 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
361 _act_grp->add(Gtk::Action::create("Export",
362 Stock::EXPORT, Glib::ustring(),
363 _("PLACEHOLDER, do not translate")),
364 sigc::mem_fun(*this, &EditWidget::onDialogExport));*/
366 _act_grp->add(Gtk::Action::create("Print",
367 Gtk::Stock::PRINT, Glib::ustring(),
368 _("PLACEHOLDER, do not translate")),
369 sigc::mem_fun(*this, &EditWidget::onActionFilePrint));
371 _act_grp->add(Gtk::Action::create("PrintPreview",
372 Gtk::Stock::PRINT_PREVIEW),
373 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
374 /*
375 _act_grp->add(Gtk::Action::create("VacuumDefs",
376 Stock::VACUUM_DEFS),
377 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));*/
379 _act_grp->add(Gtk::Action::create("DocumentProperties",
380 Gtk::Stock::PROPERTIES, Glib::ustring(),
381 _("PLACEHOLDER, do not translate")),
382 sigc::mem_fun(*this, &EditWidget::onDialogDocumentProperties));
384 _act_grp->add(Gtk::Action::create("InkscapePreferences",
385 Gtk::Stock::PREFERENCES, Glib::ustring(),
386 _("PLACEHOLDER, do not translate")),
387 sigc::mem_fun(*this, &EditWidget::onDialogInkscapePreferences));
389 _act_grp->add(Gtk::Action::create("Close",
390 Gtk::Stock::CLOSE),
391 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
393 _act_grp->add(Gtk::Action::create("Quit",
394 Gtk::Stock::QUIT),
395 sigc::mem_fun(*this, &EditWidget::onActionFileQuit));
397 // EditWidget menu
398 _act_grp->add(Gtk::Action::create("Undo",
399 Gtk::Stock::UNDO, Glib::ustring(),
400 _("PLACEHOLDER, do not translate")));
402 _act_grp->add(Gtk::Action::create("Redo",
403 Gtk::Stock::REDO, Glib::ustring(),
404 _("PLACEHOLDER, do not translate")));
405 /*
406 _act_grp->add(Gtk::Action::create("UndoHistory",
407 Stock::UNDO_HISTORY, Glib::ustring(),
408 _("PLACEHOLDER, do not translate")));*/
410 _act_grp->add(Gtk::Action::create("Cut",
411 Gtk::Stock::CUT, Glib::ustring(),
412 _("PLACEHOLDER, do not translate")));
414 _act_grp->add(Gtk::Action::create("Copy",
415 Gtk::Stock::COPY, Glib::ustring(),
416 _("PLACEHOLDER, do not translate")));
418 _act_grp->add(Gtk::Action::create("Paste",
419 Gtk::Stock::PASTE, Glib::ustring(),
420 _("PLACEHOLDER, do not translate")));
421 /*
422 _act_grp->add(Gtk::Action::create("PasteInPlace",
423 Stock::PASTE_IN_PLACE));
425 _act_grp->add(Gtk::Action::create("PasteStyle",
426 Stock::PASTE_STYLE));*/
428 _act_grp->add(Gtk::Action::create("Find",
429 Gtk::Stock::FIND),
430 sigc::mem_fun(*this, &EditWidget::onDialogFind));
431 /*
432 _act_grp->add(Gtk::Action::create("Duplicate",
433 Stock::DUPLICATE, Glib::ustring(),
434 _("PLACEHOLDER, do not translate")));
436 _act_grp->add(Gtk::Action::create("Clone",
437 Stock::CLONE, Glib::ustring(),
438 _("PLACEHOLDER, do not translate")));
440 _act_grp->add(Gtk::Action::create("CloneUnlink",
441 Stock::CLONE_UNLINK, Glib::ustring(),
442 _("PLACEHOLDER, do not translate")));
444 _act_grp->add(Gtk::Action::create("CloneSelectOrig",
445 Stock::CLONE_SELECT_ORIG));
447 _act_grp->add(Gtk::Action::create("MakeBitmap",
448 Stock::MAKE_BITMAP));
450 _act_grp->add(Gtk::Action::create("Tile",
451 Stock::TILE));
453 _act_grp->add(Gtk::Action::create("Untile",
454 Stock::UNTILE));
456 _act_grp->add(Gtk::Action::create("Delete",
457 Gtk::Stock::DELETE));
459 _act_grp->add(Gtk::Action::create("SelectAll",
460 Stock::SELECT_ALL));
462 _act_grp->add(Gtk::Action::create("SelectAllInAllLayers",
463 Stock::SELECT_ALL_IN_ALL_LAYERS));
465 _act_grp->add(Gtk::Action::create("SelectInvert",
466 Stock::SELECT_INVERT));
468 _act_grp->add(Gtk::Action::create("SelectNone",
469 Stock::SELECT_NONE));
471 _act_grp->add(Gtk::Action::create("XmlEditor",
472 Stock::XML_EDITOR, Glib::ustring(),
473 _("PLACEHOLDER, do not translate")),
474 sigc::mem_fun(*this, &EditWidget::onDialogXmlEditor));
476 // View menu
477 _act_grp->add(Gtk::Action::create("Zoom",
478 Stock::ZOOM));
480 _act_grp->add(Gtk::Action::create("ZoomIn",
481 Stock::ZOOM_IN, Glib::ustring(),
482 _("PLACEHOLDER, do not translate")));
484 _act_grp->add(Gtk::Action::create("ZoomOut",
485 Stock::ZOOM_OUT, Glib::ustring(),
486 _("PLACEHOLDER, do not translate")));
488 _act_grp->add(Gtk::Action::create("Zoom100",
489 Stock::ZOOM_100, Glib::ustring(),
490 _("PLACEHOLDER, do not translate")));
492 _act_grp->add(Gtk::Action::create("Zoom50",
493 Stock::ZOOM_50, Glib::ustring(),
494 _("PLACEHOLDER, do not translate")));
496 _act_grp->add(Gtk::Action::create("Zoom200",
497 Stock::ZOOM_200, Glib::ustring(),
498 _("PLACEHOLDER, do not translate")));
500 _act_grp->add(Gtk::Action::create("ZoomSelection",
501 Stock::ZOOM_SELECTION, Glib::ustring(),
502 _("PLACEHOLDER, do not translate")));
504 _act_grp->add(Gtk::Action::create("ZoomDrawing",
505 Stock::ZOOM_DRAWING, Glib::ustring(),
506 _("PLACEHOLDER, do not translate")));
508 _act_grp->add(Gtk::Action::create("ZoomPage",
509 Stock::ZOOM_PAGE, Glib::ustring(),
510 _("PLACEHOLDER, do not translate")));
512 _act_grp->add(Gtk::Action::create("ZoomWidth",
513 Stock::ZOOM_WIDTH, Glib::ustring(),
514 _("PLACEHOLDER, do not translate")));
516 _act_grp->add(Gtk::Action::create("ZoomPrev",
517 Stock::ZOOM_PREV, Glib::ustring(),
518 _("PLACEHOLDER, do not translate")));
520 _act_grp->add(Gtk::Action::create("ZoomNext",
521 Stock::ZOOM_NEXT, Glib::ustring(),
522 _("PLACEHOLDER, do not translate")));
524 _act_grp->add(Gtk::Action::create("ShowHide",
525 Stock::SHOW_HIDE));
527 _act_grp->add(Gtk::ToggleAction::create("ShowHideCommandsBar",
528 Stock::SHOW_HIDE_COMMANDS_BAR));
530 _act_grp->add(Gtk::ToggleAction::create("ShowHideToolControlsBar",
531 Stock::SHOW_HIDE_TOOL_CONTROLS_BAR));
533 _act_grp->add(Gtk::ToggleAction::create("ShowHideToolsBar",
534 Stock::SHOW_HIDE_TOOLS_BAR));
536 _act_grp->add(Gtk::ToggleAction::create("ShowHideRulers",
537 Stock::SHOW_HIDE_RULERS));
539 _act_grp->add(Gtk::ToggleAction::create("ShowHideScrollbars",
540 Stock::SHOW_HIDE_SCROLLBARS));
542 _act_grp->add(Gtk::ToggleAction::create("ShowHideStatusbar",
543 Stock::SHOW_HIDE_STATUSBAR));
545 _act_grp->add(Gtk::Action::create("ShowHideDialogs",
546 Stock::SHOW_HIDE_DIALOGS));
548 _act_grp->add(Gtk::Action::create("Grid",
549 Stock::GRID));
551 _act_grp->add(Gtk::Action::create("Guides",
552 Stock::GUIDES));
554 _act_grp->add(Gtk::Action::create("Fullscreen",
555 Stock::FULLSCREEN));
557 _act_grp->add(Gtk::Action::create("Messages",
558 Stock::MESSAGES),
559 sigc::mem_fun(*this, &EditWidget::onDialogMessages));
561 _act_grp->add(Gtk::Action::create("Scripts",
562 Stock::SCRIPTS));
564 _act_grp->add(Gtk::Action::create("WindowPrev",
565 Stock::WINDOW_PREV));
567 _act_grp->add(Gtk::Action::create("WindowNext",
568 Stock::WINDOW_NEXT));
570 _act_grp->add(Gtk::Action::create("WindowDuplicate",
571 Stock::WINDOW_DUPLICATE));
573 // Layer menu
574 _act_grp->add(Gtk::Action::create("LayerNew",
575 Stock::LAYER_NEW));
577 _act_grp->add(Gtk::Action::create("LayerRename",
578 Stock::LAYER_RENAME));
580 _act_grp->add(Gtk::Action::create("LayerDuplicate",
581 Stock::LAYER_DUPLICATE));
583 _act_grp->add(Gtk::Action::create("LayerAnchor",
584 Stock::LAYER_ANCHOR));
586 _act_grp->add(Gtk::Action::create("LayerMergeDown",
587 Stock::LAYER_MERGE_DOWN));
589 _act_grp->add(Gtk::Action::create("LayerDelete",
590 Stock::LAYER_DELETE));
592 _act_grp->add(Gtk::Action::create("LayerSelectNext",
593 Stock::LAYER_SELECT_NEXT));
595 _act_grp->add(Gtk::Action::create("LayerSelectPrev",
596 Stock::LAYER_SELECT_PREV));
598 _act_grp->add(Gtk::Action::create("LayerSelectTop",
599 Stock::LAYER_SELECT_TOP));
601 _act_grp->add(Gtk::Action::create("LayerSelectBottom",
602 Stock::LAYER_SELECT_BOTTOM));
604 _act_grp->add(Gtk::Action::create("LayerRaise",
605 Stock::LAYER_RAISE));
607 _act_grp->add(Gtk::Action::create("LayerLower",
608 Stock::LAYER_LOWER));
610 _act_grp->add(Gtk::Action::create("LayerToTop",
611 Stock::LAYER_TO_TOP));
613 _act_grp->add(Gtk::Action::create("LayerToBottom",
614 Stock::LAYER_TO_BOTTOM));
616 // Object menu
617 _act_grp->add(Gtk::Action::create("FillAndStroke",
618 Stock::FILL_STROKE, Glib::ustring(),
619 _("PLACEHOLDER, do not translate")),
620 sigc::mem_fun(*this, &EditWidget::onDialogFillAndStroke));
622 _act_grp->add(Gtk::Action::create("ObjectProperties",
623 Stock::OBJECT_PROPERTIES),
624 sigc::mem_fun(*this, &EditWidget::onDialogObjectProperties));
626 _act_grp->add(Gtk::Action::create("FilterEffects",
627 Stock::FILTER_EFFECTS));
629 _act_grp->add(Gtk::Action::create("Group",
630 Stock::GROUP, Glib::ustring(),
631 _("PLACEHOLDER, do not translate")));
633 _act_grp->add(Gtk::Action::create("Ungroup",
634 Stock::UNGROUP, Glib::ustring(),
635 _("PLACEHOLDER, do not translate")));
637 _act_grp->add(Gtk::Action::create("Raise",
638 Stock::RAISE, Glib::ustring(),
639 _("PLACEHOLDER, do not translate")));
641 _act_grp->add(Gtk::Action::create("Lower",
642 Stock::LOWER, Glib::ustring(),
643 _("PLACEHOLDER, do not translate")));
645 _act_grp->add(Gtk::Action::create("RaiseToTop",
646 Stock::RAISE_TO_TOP, Glib::ustring(),
647 _("PLACEHOLDER, do not translate")));
649 _act_grp->add(Gtk::Action::create("LowerToBottom",
650 Stock::LOWER_TO_BOTTOM, Glib::ustring(),
651 _("PLACEHOLDER, do not translate")));
653 _act_grp->add(Gtk::Action::create("MoveToNewLayer",
654 Stock::MOVE_TO_NEW_LAYER, Glib::ustring(),
655 _("PLACEHOLDER, do not translate")));
657 _act_grp->add(Gtk::Action::create("MoveToNextLayer",
658 Stock::MOVE_TO_NEXT_LAYER, Glib::ustring(),
659 _("PLACEHOLDER, do not translate")));
661 _act_grp->add(Gtk::Action::create("MoveToPrevLayer",
662 Stock::MOVE_TO_PREV_LAYER, Glib::ustring(),
663 _("PLACEHOLDER, do not translate")));
665 _act_grp->add(Gtk::Action::create("MoveToTopLayer",
666 Stock::MOVE_TO_TOP_LAYER, Glib::ustring(),
667 _("PLACEHOLDER, do not translate")));
669 _act_grp->add(Gtk::Action::create("MoveToBottomLayer",
670 Stock::MOVE_TO_BOTTOM_LAYER, Glib::ustring(),
671 _("PLACEHOLDER, do not translate")));
673 _act_grp->add(Gtk::Action::create("Rotate90CW",
674 Stock::ROTATE_90_CW, Glib::ustring(),
675 _("PLACEHOLDER, do not translate")));
677 _act_grp->add(Gtk::Action::create("Rotate90CCW",
678 Stock::ROTATE_90_CCW, Glib::ustring(),
679 _("PLACEHOLDER, do not translate")));
681 _act_grp->add(Gtk::Action::create("FlipHoriz",
682 Stock::FLIP_HORIZ, Glib::ustring(),
683 _("PLACEHOLDER, do not translate")));
685 _act_grp->add(Gtk::Action::create("FlipVert",
686 Stock::FLIP_VERT, Glib::ustring(),
687 _("PLACEHOLDER, do not translate")));
689 _act_grp->add(Gtk::Action::create("Transformation",
690 Stock::TRANSFORMATION, Glib::ustring(),
691 _("PLACEHOLDER, do not translate")),
692 sigc::mem_fun(*this, &EditWidget::onDialogTransformation));
694 _act_grp->add(Gtk::Action::create("AlignAndDistribute",
695 Stock::ALIGN_DISTRIBUTE, Glib::ustring(),
696 _("PLACEHOLDER, do not translate")),
697 sigc::mem_fun(*this, &EditWidget::onDialogAlignAndDistribute));
699 // Path menu
700 _act_grp->add(Gtk::Action::create("ObjectToPath",
701 Stock::OBJECT_TO_PATH, Glib::ustring(),
702 _("PLACEHOLDER, do not translate")));
704 _act_grp->add(Gtk::Action::create("StrokeToPath",
705 Stock::STROKE_TO_PATH, Glib::ustring(),
706 _("PLACEHOLDER, do not translate")));
708 _act_grp->add(Gtk::Action::create("Trace",
709 Stock::TRACE),
710 sigc::mem_fun(*this, &EditWidget::onDialogTrace));
712 _act_grp->add(Gtk::Action::create("Union",
713 Stock::UNION));
715 _act_grp->add(Gtk::Action::create("Difference",
716 Stock::DIFFERENCE));
718 _act_grp->add(Gtk::Action::create("Intersection",
719 Stock::INTERSECTION));
721 _act_grp->add(Gtk::Action::create("Exclusion",
722 Stock::EXCLUSION));
724 _act_grp->add(Gtk::Action::create("Division",
725 Stock::DIVISION));
727 _act_grp->add(Gtk::Action::create("CutPath",
728 Stock::CUT_PATH));
730 _act_grp->add(Gtk::Action::create("Combine",
731 Stock::COMBINE));
733 _act_grp->add(Gtk::Action::create("BreakApart",
734 Stock::BREAK_APART));
736 _act_grp->add(Gtk::Action::create("Inset",
737 Stock::INSET));
739 _act_grp->add(Gtk::Action::create("Outset",
740 Stock::OUTSET));
742 _act_grp->add(Gtk::Action::create("OffsetDynamic",
743 Stock::OFFSET_DYNAMIC));
745 _act_grp->add(Gtk::Action::create("OffsetLinked",
746 Stock::OFFSET_LINKED));
748 _act_grp->add(Gtk::Action::create("Simplify",
749 Stock::SIMPLIFY));
751 _act_grp->add(Gtk::Action::create("Reverse",
752 Stock::REVERSE));*/
754 _act_grp->add(Gtk::Action::create("Cleanup",
755 Gtk::Stock::CLEAR,
756 _("PLACEHOLDER, do not translate")));
758 // Text menu
759 _act_grp->add(Gtk::Action::create("TextProperties",
760 Gtk::Stock::SELECT_FONT, Glib::ustring(),
761 _("PLACEHOLDER, do not translate")),
762 sigc::mem_fun(*this, &EditWidget::onDialogTextProperties));
763 /*
764 _act_grp->add(Gtk::Action::create("PutOnPath",
765 Stock::PUT_ON_PATH));
767 _act_grp->add(Gtk::Action::create("RemoveFromPath",
768 Stock::REMOVE_FROM_PATH));
770 _act_grp->add(Gtk::Action::create("RemoveManualKerns",
771 Stock::REMOVE_MANUAL_KERNS));*/
773 // Whiteboard menu
774 #ifdef WITH_INKBOARD
775 #endif
777 // About menu
778 /*
779 _act_grp->add(Gtk::Action::create("KeysAndMouse",
780 Stock::KEYS_MOUSE));
782 _act_grp->add(Gtk::Action::create("Tutorials",
783 Stock::TUTORIALS));
785 _act_grp->add(Gtk::Action::create("About",
786 Stock::ABOUT),
787 sigc::mem_fun(*this, &EditWidget::onDialogAbout));*/
788 }
790 void
791 EditWidget::initToolbarActions()
792 {
793 // Tools bar
794 // This has zero chance to work, and has to be converted to create_with_icon_name
795 Gtk::RadioAction::Group tools;
796 /*
797 _act_grp->add(Gtk::RadioAction::create(tools, "ToolSelect",
798 Stock::TOOL_SELECT, Glib::ustring(),
799 _("PLACEHOLDER, do not translate")),
800 sigc::mem_fun(*this, &EditWidget::onSelectTool));
802 _act_grp->add(Gtk::RadioAction::create(tools, "ToolNode",
803 Stock::TOOL_NODE, Glib::ustring(),
804 _("PLACEHOLDER, do not translate")),
805 sigc::mem_fun(*this, &EditWidget::onNodeTool));
807 _act_grp->add(Gtk::RadioAction::create(tools, "ToolZoom",
808 Stock::TOOL_ZOOM, Glib::ustring(),
809 _("PLACEHOLDER, do not translate")));
811 _act_grp->add(Gtk::RadioAction::create(tools, "ToolRect",
812 Stock::TOOL_RECT, Glib::ustring(),
813 _("PLACEHOLDER, do not translate")));
815 _act_grp->add(Gtk::RadioAction::create(tools, "ToolArc",
816 Stock::TOOL_ARC, Glib::ustring(),
817 _("PLACEHOLDER, do not translate")));
819 _act_grp->add(Gtk::RadioAction::create(tools, "ToolStar",
820 Stock::TOOL_STAR, Glib::ustring(),
821 _("PLACEHOLDER, do not translate")));
823 _act_grp->add(Gtk::RadioAction::create(tools, "ToolSpiral",
824 Stock::TOOL_SPIRAL, Glib::ustring(),
825 _("PLACEHOLDER, do not translate")));
827 _act_grp->add(Gtk::RadioAction::create(tools, "ToolFreehand",
828 Stock::TOOL_FREEHAND, Glib::ustring(),
829 _("PLACEHOLDER, do not translate")));
831 _act_grp->add(Gtk::RadioAction::create(tools, "ToolPen",
832 Stock::TOOL_PEN, Glib::ustring(),
833 _("PLACEHOLDER, do not translate")));
835 _act_grp->add(Gtk::RadioAction::create(tools, "ToolDynaDraw",
836 Stock::TOOL_DYNADRAW, Glib::ustring(),
837 _("PLACEHOLDER, do not translate")));
839 _act_grp->add(Gtk::RadioAction::create(tools, "ToolText",
840 Stock::TOOL_TEXT, Glib::ustring(),
841 _("PLACEHOLDER, do not translate")));
843 _act_grp->add(Gtk::RadioAction::create(tools, "ToolDropper",
844 Stock::TOOL_DROPPER, Glib::ustring(),
845 _("PLACEHOLDER, do not translate")));
847 // Select Controls bar
848 _act_grp->add(Gtk::ToggleAction::create("TransformStroke",
849 Stock::TRANSFORM_STROKE, Glib::ustring(),
850 _("PLACEHOLDER, do not translate")));
852 _act_grp->add(Gtk::ToggleAction::create("TransformCorners",
853 Stock::TRANSFORM_CORNERS, Glib::ustring(),
854 _("PLACEHOLDER, do not translate")));
856 _act_grp->add(Gtk::ToggleAction::create("TransformGradient",
857 Stock::TRANSFORM_GRADIENT, Glib::ustring(),
858 _("PLACEHOLDER, do not translate")));
860 _act_grp->add(Gtk::ToggleAction::create("TransformPattern",
861 Stock::TRANSFORM_PATTERN, Glib::ustring(),
862 _("PLACEHOLDER, do not translate")));*/
864 // Node Controls bar
865 _act_grp->add(Gtk::Action::create("NodeInsert",
866 Gtk::Stock::ADD, Glib::ustring(),
867 _("PLACEHOLDER, do not translate")));
869 _act_grp->add(Gtk::Action::create("NodeDelete",
870 Gtk::Stock::REMOVE, Glib::ustring(),
871 _("PLACEHOLDER, do not translate")));
872 /*
873 _act_grp->add(Gtk::Action::create("NodeJoin",
874 Stock::NODE_JOIN, Glib::ustring(),
875 _("PLACEHOLDER, do not translate")));
877 _act_grp->add(Gtk::Action::create("NodeJoinSegment",
878 Stock::NODE_JOIN_SEGMENT, Glib::ustring(),
879 _("PLACEHOLDER, do not translate")));
881 _act_grp->add(Gtk::Action::create("NodeDeleteSegment",
882 Stock::NODE_DELETE_SEGMENT, Glib::ustring(),
883 _("PLACEHOLDER, do not translate")));
885 _act_grp->add(Gtk::Action::create("NodeBreak",
886 Stock::NODE_BREAK, Glib::ustring(),
887 _("PLACEHOLDER, do not translate")));
889 _act_grp->add(Gtk::Action::create("NodeCorner",
890 Stock::NODE_CORNER, Glib::ustring(),
891 _("PLACEHOLDER, do not translate")));
893 _act_grp->add(Gtk::Action::create("NodeSmooth",
894 Stock::NODE_SMOOTH, Glib::ustring(),
895 _("PLACEHOLDER, do not translate")));
897 _act_grp->add(Gtk::Action::create("NodeSymmetric",
898 Stock::NODE_SYMMETRIC, Glib::ustring(),
899 _("PLACEHOLDER, do not translate")));
901 _act_grp->add(Gtk::Action::create("NodeLine",
902 Stock::NODE_LINE, Glib::ustring(),
903 _("PLACEHOLDER, do not translate")));
905 _act_grp->add(Gtk::Action::create("NodeCurve",
906 Stock::NODE_CURVE, Glib::ustring(),
907 _("PLACEHOLDER, do not translate")));*/
908 }
910 void
911 EditWidget::initAccelMap()
912 {
913 gchar *filename = g_build_filename(INKSCAPE_UIDIR, "keybindings.rc", NULL);
914 Gtk::AccelMap::load(filename);
915 g_free(filename);
917 // One problem is that the keys 1-6 are zoom accelerators which get
918 // caught as accelerator _before_ any Entry input handler receives them,
919 // for example the zoom status. At the moment, the best way seems to
920 // disable them as accelerators when the Entry gets focus, and enable
921 // them when focus goes elsewhere. The code for this belongs here,
922 // and not in zoom-status.cpp .
924 _zoom_status.signal_focus_in_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusIn));
925 _zoom_status.signal_focus_out_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusOut));
926 }
928 bool
929 EditWidget::onEntryFocusIn (GdkEventFocus* /*ev*/)
930 {
931 Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
932 Gtk::AccelMap::change_entry ("<Actions>//Zoom100", 0, m, false);
933 Gtk::AccelMap::change_entry ("<Actions>//Zoom50", 0, m, false);
934 Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", 0, m, false);
935 Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", 0, m, false);
936 Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", 0, m, false);
937 Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", 0, m, false);
938 return false;
939 }
941 bool
942 EditWidget::onEntryFocusOut (GdkEventFocus* /*ev*/)
943 {
944 Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
945 Gtk::AccelMap::change_entry ("<Actions>//Zoom100", '1', m, false);
946 Gtk::AccelMap::change_entry ("<Actions>//Zoom50", '2', m, false);
947 Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", '3', m, false);
948 Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", '4', m, false);
949 Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", '5', m, false);
950 Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", '6', m, false);
951 return false;
952 }
954 void
955 EditWidget::initMenuBar()
956 {
957 g_assert(_ui_mgr);
958 Gtk::MenuBar *menu = static_cast<Gtk::MenuBar*>(_ui_mgr->get_widget("/MenuBar"));
959 g_assert(menu != NULL);
960 _main_window_table.attach(*Gtk::manage(menu), 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
961 }
963 void
964 EditWidget::initCommandsBar()
965 {
966 g_assert(_ui_mgr);
967 Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/CommandsBar")),
968 Gtk::TOOLBAR_ICONS);
969 g_assert(bar != NULL);
970 _toolbars_vbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
971 }
973 void
974 EditWidget::initToolControlsBar()
975 {
976 // TODO: Do UIManager controlled widgets need to be deleted?
977 _select_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/SelectControlsBar"));
978 _node_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/NodeControlsBar"));
980 _tool_ctrl = new Toolbox(_select_ctrl, Gtk::TOOLBAR_ICONS);
982 _toolbars_vbox.pack_start(*Gtk::manage(_tool_ctrl), Gtk::PACK_SHRINK);
983 }
985 void
986 EditWidget::initUriBar()
987 {
988 /// \todo Create an Inkscape::UI::Widget::UriBar class (?)
990 _uri_ctrl = new Gtk::Toolbar();
992 _uri_label.set_label(_("PLACEHOLDER, do not translate"));
993 _uri_ctrl->add(_uri_label);
994 _uri_ctrl->add(_uri_entry);
996 _uri_entry.signal_activate()
997 .connect_notify(sigc::mem_fun(*this, &EditWidget::onUriChanged));
999 _toolbars_vbox.pack_start(*Gtk::manage(_uri_ctrl), Gtk::PACK_SHRINK);
1000 }
1002 void
1003 EditWidget::initToolsBar()
1004 {
1005 Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/ToolsBar")),
1006 Gtk::TOOLBAR_ICONS,
1007 Gtk::ORIENTATION_VERTICAL);
1008 g_assert(bar != NULL);
1009 _sub_window_hbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
1010 }
1012 void
1013 EditWidget::initTopRuler()
1014 {
1015 _viewport_table.attach(_top_ruler, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1017 _tooltips.set_tip (_top_ruler, _top_ruler.get_tip());
1018 }
1020 void
1021 EditWidget::initLeftRuler()
1022 {
1023 _viewport_table.attach(_left_ruler, 0, 1, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1025 _tooltips.set_tip (_left_ruler, _left_ruler.get_tip());
1026 }
1028 void
1029 EditWidget::initBottomScrollbar()
1030 {
1031 _viewport_table.attach(_bottom_scrollbar, 1, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1032 _bottom_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1033 _bottom_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1034 }
1036 void
1037 EditWidget::initRightScrollbar()
1038 {
1039 _viewport_table.attach(_right_scrollbar, 2, 3, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1041 _right_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1042 _right_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1043 }
1045 void
1046 EditWidget::initStickyZoom()
1047 {
1048 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1049 _viewport_table.attach(_sticky_zoom, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
1050 _sticky_zoom.set_active (prefs->getBool("/options/stickyzoom/value"));
1051 _tooltips.set_tip (_sticky_zoom, _("Zoom drawing if window size changes"));
1053 /// \todo icon not implemented
1054 }
1056 void
1057 EditWidget::initStatusbar()
1058 {
1059 _statusbar.pack_start (_selected_style_status, false, false, 1);
1060 _statusbar.pack_start (*new Gtk::VSeparator(), false, false, 0);
1062 _tooltips.set_tip (_zoom_status, _("Zoom"));
1064 _layer_selector.reference();
1065 _statusbar.pack_start (_layer_selector, false, false, 1);
1067 _coord_status.property_n_rows() = 2;
1068 _coord_status.property_n_columns() = 5;
1069 _coord_status.property_row_spacing() = 0;
1070 _coord_status.property_column_spacing() = 2;
1071 _coord_eventbox.add (_coord_status);
1072 _tooltips.set_tip (_coord_eventbox, _("Cursor coordinates"));
1073 _coord_status.attach (*new Gtk::VSeparator(), 0,1, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1074 _coord_status.attach (*new Gtk::Label(_("X:"), 0.0, 0.5), 1,2, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1075 _coord_status.attach (*new Gtk::Label(_("Y:"), 0.0, 0.5), 1,2, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1076 _coord_status_x.set_text ("0.0");
1077 _coord_status_x.set_alignment (0.0, 0.5);
1078 _coord_status_y.set_text ("0.0");
1079 _coord_status_y.set_alignment (0.0, 0.5);
1080 _coord_status.attach (_coord_status_x, 2,3, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1081 _coord_status.attach (_coord_status_y, 2,3, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1082 _coord_status.attach (*new Gtk::Label(_("Z:"), 0.0, 0.5), 3,4, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1083 _coord_status.attach (_zoom_status, 4,5, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1084 sp_set_font_size_smaller (static_cast<GtkWidget*>((void*)_coord_status.gobj()));
1085 _statusbar.pack_end (_coord_eventbox, false, false, 1);
1087 _select_status.property_xalign() = 0.0;
1088 _select_status.property_yalign() = 0.5;
1089 _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."));
1090 // include this again with Gtk+-2.6
1091 #if GTK_VERSION_GE(2,6)
1092 gtk_label_set_ellipsize (GTK_LABEL(_select_status.gobj()), PANGO_ELLIPSIZE_END);
1093 #endif
1094 _select_status.set_size_request (1, -1);
1095 _statusbar.pack_start (_select_status, true, true, 0);
1097 _main_window_table.attach(_statusbar, 0, 1, 3, 4, Gtk::FILL, Gtk::SHRINK);
1098 }
1100 //========================================
1101 //----------implements EditWidgetInterface
1103 Gtk::Window *
1104 EditWidget::getWindow()
1105 {
1106 return this;
1107 }
1109 void
1110 EditWidget::setTitle (gchar const* new_title)
1111 {
1112 set_title (new_title);
1113 }
1115 void
1116 EditWidget::layout()
1117 {
1118 show_all_children();
1119 }
1121 void
1122 EditWidget::present()
1123 {
1124 this->Gtk::Window::present();
1125 }
1127 void
1128 EditWidget::getGeometry (gint &x, gint &y, gint &w, gint &h)
1129 {
1130 get_position (x, y);
1131 get_size (w, h);
1132 }
1134 void
1135 EditWidget::setSize (gint w, gint h)
1136 {
1137 resize (w, h);
1138 }
1140 void
1141 EditWidget::setPosition (Geom::Point p)
1142 {
1143 move (int(p[Geom::X]), int(p[Geom::Y]));
1144 }
1146 /// \param p is already gobj()!
1147 void
1148 EditWidget::setTransient (void* p, int i)
1149 {
1150 gtk_window_set_transient_for (static_cast<GtkWindow*>(p), this->gobj());
1151 if (i==2)
1152 this->Gtk::Window::present();
1153 }
1155 Geom::Point
1156 EditWidget::getPointer()
1157 {
1158 int x, y;
1159 get_pointer (x, y);
1160 return Geom::Point (x, y);
1161 }
1163 void
1164 EditWidget::setIconified()
1165 {
1166 iconify();
1167 }
1169 void
1170 EditWidget::setMaximized()
1171 {
1172 maximize();
1173 }
1175 void
1176 EditWidget::setFullscreen()
1177 {
1178 fullscreen();
1179 }
1181 /**
1182 * Shuts down the desktop object for the view being closed. It checks
1183 * to see if the document has been edited, and if so prompts the user
1184 * to save, discard, or cancel. Returns TRUE if the shutdown operation
1185 * is cancelled or if the save is cancelled or fails, FALSE otherwise.
1186 */
1187 bool
1188 EditWidget::shutdown()
1189 {
1190 g_assert (_desktop != NULL);
1191 if (Inkscape::NSApplication::Editor::isDuplicatedView (_desktop))
1192 return false;
1194 SPDocument *doc = _desktop->doc();
1195 if (doc->isModifiedSinceSave()) {
1196 gchar *markup;
1197 /// \todo FIXME !!! obviously this will have problems if the document
1198 /// name contains markup characters
1199 markup = g_strdup_printf(
1200 _("<span weight=\"bold\" size=\"larger\">Save changes to document \"%s\" before closing?</span>\n\n"
1201 "If you close without saving, your changes will be discarded."),
1202 SP_DOCUMENT_NAME(doc));
1204 Gtk::MessageDialog dlg (*this,
1205 markup,
1206 true,
1207 Gtk::MESSAGE_WARNING,
1208 Gtk::BUTTONS_NONE,
1209 true);
1210 g_free(markup);
1211 Gtk::Button close_button (_("Close _without saving"), true);
1212 dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1213 close_button.show();
1214 dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1215 dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1216 dlg.set_default_response (Gtk::RESPONSE_YES);
1218 int response = dlg.run();
1219 switch (response)
1220 {
1221 case Gtk::RESPONSE_YES:
1222 sp_document_ref(doc);
1223 sp_namedview_document_from_window(_desktop);
1224 if (sp_file_save_document(*this, doc)) {
1225 sp_document_unref(doc);
1226 } else { // save dialog cancelled or save failed
1227 sp_document_unref(doc);
1228 return TRUE;
1229 }
1230 break;
1231 case Gtk::RESPONSE_NO:
1232 break;
1233 default: // cancel pressed, or dialog was closed
1234 return TRUE;
1235 break;
1236 }
1237 }
1239 /* Code to check data loss */
1240 bool allow_data_loss = FALSE;
1241 while (sp_document_repr_root(doc)->attribute("inkscape:dataloss") != NULL && allow_data_loss == FALSE)
1242 {
1243 gchar *markup;
1244 /// \todo FIXME !!! obviously this will have problems if the document
1245 /// name contains markup characters
1246 markup = g_strdup_printf(
1247 _("<span weight=\"bold\" size=\"larger\">The file \"%s\" was saved with a format (%s) that may cause data loss!</span>\n\n"
1248 "Do you want to save this file as an Inkscape SVG?"),
1249 SP_DOCUMENT_NAME(doc),
1250 SP_MODULE_KEY_OUTPUT_SVG_INKSCAPE);
1252 Gtk::MessageDialog dlg (*this,
1253 markup,
1254 true,
1255 Gtk::MESSAGE_WARNING,
1256 Gtk::BUTTONS_NONE,
1257 true);
1258 g_free(markup);
1259 Gtk::Button close_button (_("Close _without saving"), true);
1260 dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1261 close_button.show();
1262 Gtk::Button save_button (_("_Save as SVG"), true);
1263 dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1264 dlg.add_action_widget (save_button, Gtk::RESPONSE_YES);
1265 save_button.show();
1266 dlg.set_default_response (Gtk::RESPONSE_YES);
1268 int response = dlg.run();
1270 switch (response)
1271 {
1272 case Gtk::RESPONSE_YES:
1273 sp_document_ref(doc);
1274 if (sp_file_save_document(*this, doc)) {
1275 sp_document_unref(doc);
1276 } else { // save dialog cancelled or save failed
1277 sp_document_unref(doc);
1278 return TRUE;
1279 }
1280 break;
1281 case Gtk::RESPONSE_NO:
1282 allow_data_loss = TRUE;
1283 break;
1284 default: // cancel pressed, or dialog was closed
1285 return TRUE;
1286 break;
1287 }
1288 }
1290 return false;
1291 }
1294 void
1295 EditWidget::destroy()
1296 {
1297 delete this;
1298 }
1300 void
1301 EditWidget::requestCanvasUpdate()
1302 {
1303 _svg_canvas.widget().queue_draw();
1304 }
1306 void
1307 EditWidget::requestCanvasUpdateAndWait()
1308 {
1309 requestCanvasUpdate();
1311 while (gtk_events_pending())
1312 gtk_main_iteration_do(FALSE);
1313 }
1315 void
1316 EditWidget::enableInteraction()
1317 {
1318 g_return_if_fail(_interaction_disabled_counter > 0);
1320 _interaction_disabled_counter--;
1322 if (_interaction_disabled_counter == 0) {
1323 this->set_sensitive(true);
1324 }
1325 }
1327 void
1328 EditWidget::disableInteraction()
1329 {
1330 if (_interaction_disabled_counter == 0) {
1331 this->set_sensitive(false);
1332 }
1334 _interaction_disabled_counter++;
1335 }
1337 void
1338 EditWidget::activateDesktop()
1339 {
1340 /// \todo active_desktop_indicator not implemented
1341 }
1343 void
1344 EditWidget::deactivateDesktop()
1345 {
1346 /// \todo active_desktop_indicator not implemented
1347 }
1349 void
1350 EditWidget::viewSetPosition (Geom::Point p)
1351 {
1352 // p -= _namedview->gridorigin;
1353 /// \todo Why was the origin corrected for the grid origin? (johan)
1355 double lo, up, pos, max;
1356 _top_ruler.get_range (lo, up, pos, max);
1357 _top_ruler.set_range (lo, up, p[Geom::X], max);
1358 _left_ruler.get_range (lo, up, pos, max);
1359 _left_ruler.set_range (lo, up, p[Geom::Y], max);
1360 }
1362 void
1363 EditWidget::updateRulers()
1364 {
1365 //Geom::Point gridorigin = _namedview->gridorigin;
1366 /// \todo Why was the origin corrected for the grid origin? (johan)
1368 Geom::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1369 double lo, up, pos, max;
1370 double const scale = _desktop->current_zoom();
1371 double s = viewbox.min()[Geom::X] / scale; //- gridorigin[Geom::X];
1372 double e = viewbox.max()[Geom::X] / scale; //- gridorigin[Geom::X];
1373 _top_ruler.get_range(lo, up, pos, max);
1374 _top_ruler.set_range(s, e, pos, e);
1375 s = viewbox.min()[Geom::Y] / -scale; //- gridorigin[Geom::Y];
1376 e = viewbox.max()[Geom::Y] / -scale; //- gridorigin[Geom::Y];
1377 _left_ruler.set_range(s, e, 0 /*gridorigin[Geom::Y]*/, e);
1378 /// \todo is that correct?
1379 }
1381 void
1382 EditWidget::updateScrollbars (double scale)
1383 {
1384 // do not call this function before canvas has its size allocated
1385 if (!is_realized() || _update_s_f) {
1386 return;
1387 }
1389 _update_s_f = true;
1391 /* The desktop region we always show unconditionally */
1392 SPDocument *doc = _desktop->doc();
1393 Geom::Rect darea ( Geom::Point(-sp_document_width(doc), -sp_document_height(doc)),
1394 Geom::Point(2 * sp_document_width(doc), 2 * sp_document_height(doc)) );
1395 SPObject* root = doc->root;
1396 SPItem* item = SP_ITEM(root);
1397 Geom::OptRect deskarea = Geom::unify(darea, sp_item_bbox_desktop(item));
1399 /* Canvas region we always show unconditionally */
1400 Geom::Rect carea( Geom::Point(deskarea->min()[Geom::X] * scale - 64, deskarea->max()[Geom::Y] * -scale - 64),
1401 Geom::Point(deskarea->max()[Geom::X] * scale + 64, deskarea->min()[Geom::Y] * -scale + 64) );
1403 Geom::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1405 /* Viewbox is always included into scrollable region */
1406 carea = Geom::unify(carea, viewbox);
1408 Gtk::Adjustment *adj = _bottom_scrollbar.get_adjustment();
1409 adj->set_value(viewbox.min()[Geom::X]);
1410 adj->set_lower(carea.min()[Geom::X]);
1411 adj->set_upper(carea.max()[Geom::X]);
1412 adj->set_page_increment(viewbox.dimensions()[Geom::X]);
1413 adj->set_step_increment(0.1 * (viewbox.dimensions()[Geom::X]));
1414 adj->set_page_size(viewbox.dimensions()[Geom::X]);
1416 adj = _right_scrollbar.get_adjustment();
1417 adj->set_value(viewbox.min()[Geom::Y]);
1418 adj->set_lower(carea.min()[Geom::Y]);
1419 adj->set_upper(carea.max()[Geom::Y]);
1420 adj->set_page_increment(viewbox.dimensions()[Geom::Y]);
1421 adj->set_step_increment(0.1 * viewbox.dimensions()[Geom::Y]);
1422 adj->set_page_size(viewbox.dimensions()[Geom::Y]);
1424 _update_s_f = false;
1425 }
1427 void
1428 EditWidget::toggleRulers()
1429 {
1430 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1431 if (_top_ruler.is_visible())
1432 {
1433 _top_ruler.hide_all();
1434 _left_ruler.hide_all();
1435 prefs->setBool(_desktop->is_fullscreen() ? "/fullscreen/rulers/state" : "/window/rulers/state", false);
1436 } else {
1437 _top_ruler.show_all();
1438 _left_ruler.show_all();
1439 prefs->setBool(_desktop->is_fullscreen() ? "/fullscreen/rulers/state" : "/window/rulers/state", true);
1440 }
1441 }
1443 void
1444 EditWidget::toggleScrollbars()
1445 {
1446 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
1447 if (_bottom_scrollbar.is_visible())
1448 {
1449 _bottom_scrollbar.hide_all();
1450 _right_scrollbar.hide_all();
1451 prefs->setBool(_desktop->is_fullscreen() ? "/fullscreen/scrollbars/state" : "/window/scrollbars/state", false);
1452 } else {
1453 _bottom_scrollbar.show_all();
1454 _right_scrollbar.show_all();
1455 prefs->setBool(_desktop->is_fullscreen() ? "/fullscreen/scrollbars/state" : "/window/scrollbars/state", true);
1456 }
1457 }
1459 void EditWidget::toggleColorProfAdjust()
1460 {
1461 // TODO implement
1462 }
1464 void
1465 EditWidget::updateZoom()
1466 {
1467 _zoom_status.update();
1468 }
1470 void
1471 EditWidget::letZoomGrabFocus()
1472 {
1473 _zoom_status.grab_focus();
1474 }
1476 void
1477 EditWidget::setToolboxFocusTo (const gchar *)
1478 {
1479 /// \todo not implemented
1480 }
1482 void
1483 EditWidget::setToolboxAdjustmentValue (const gchar *, double)
1484 {
1485 /// \todo not implemented
1486 }
1488 void
1489 EditWidget::setToolboxSelectOneValue (const gchar *, gint)
1490 {
1491 /// \todo not implemented
1492 }
1494 bool
1495 EditWidget::isToolboxButtonActive (gchar const*)
1496 {
1497 /// \todo not implemented
1498 return true;
1499 }
1501 void
1502 EditWidget::setCoordinateStatus (Geom::Point p)
1503 {
1504 gchar *cstr = g_strdup_printf ("%6.2f", _dt2r * p[Geom::X]);
1505 _coord_status_x.property_label() = cstr;
1506 g_free (cstr);
1507 cstr = g_strdup_printf ("%6.2f", _dt2r * p[Geom::Y]);
1508 _coord_status_y.property_label() = cstr;
1509 g_free (cstr);
1510 }
1512 void
1513 EditWidget::setMessage (Inkscape::MessageType /*type*/, gchar const* msg)
1514 {
1515 _select_status.set_markup (msg? msg : "");
1516 }
1518 bool
1519 EditWidget::warnDialog (gchar* msg)
1520 {
1521 Gtk::MessageDialog dlg (*this,
1522 msg,
1523 true,
1524 Gtk::MESSAGE_WARNING,
1525 Gtk::BUTTONS_YES_NO,
1526 true);
1527 int r = dlg.run();
1528 return r == Gtk::RESPONSE_YES;
1529 }
1532 Inkscape::UI::Widget::Dock*
1533 EditWidget::getDock ()
1534 {
1535 return &_dock;
1536 }
1538 void EditWidget::_namedview_modified (SPObject *obj, guint flags) {
1539 SPNamedView *nv = static_cast<SPNamedView *>(obj);
1540 if (flags & SP_OBJECT_MODIFIED_FLAG) {
1541 this->_dt2r = 1.0 / nv->doc_units->unittobase;
1542 this->_top_ruler.update_metric();
1543 this->_left_ruler.update_metric();
1544 this->_tooltips.set_tip(this->_top_ruler, this->_top_ruler.get_tip());
1545 this->_tooltips.set_tip(this->_left_ruler, this->_left_ruler.get_tip());
1546 this->updateRulers();
1547 }
1548 }
1550 void
1551 EditWidget::initEdit (SPDocument *doc)
1552 {
1553 _desktop = new SPDesktop();
1555 _namedview = sp_document_namedview (doc, 0);
1556 _svg_canvas.init (_desktop);
1557 _desktop->init (_namedview, _svg_canvas.spobj(), this);
1558 sp_namedview_window_from_document (_desktop);
1559 sp_namedview_update_layers_from_document (_desktop);
1560 _dt2r = 1.0 / _namedview->doc_units->unittobase;
1562 /// \todo convert to sigc++ when SPObject hierarchy gets converted
1563 /* Listen on namedview modification */
1564 _namedview_modified_connection = _desktop->namedview->connectModified(sigc::mem_fun(*this, &EditWidget::_namedview_modified));
1565 _layer_selector.setDesktop (_desktop);
1566 _selected_style_status.setDesktop (_desktop);
1568 Inkscape::NSApplication::Editor::addDesktop (_desktop);
1570 _zoom_status.init (_desktop);
1571 _top_ruler.init (_desktop, _svg_canvas.widget());
1572 _left_ruler.init (_desktop, _svg_canvas.widget());
1573 updateRulers();
1574 }
1576 void
1577 EditWidget::destroyEdit()
1578 {
1579 if (_desktop) {
1580 _layer_selector.unreference();
1581 Inkscape::NSApplication::Editor::removeDesktop (_desktop); // clears selection too
1582 _namedview_modified_connection.disconnect();
1583 _desktop->destroy();
1584 Inkscape::GC::release (_desktop);
1585 _desktop = 0;
1586 }
1587 }
1589 //----------end of EditWidgetInterface implementation
1591 //----------start of other callbacks
1593 bool
1594 EditWidget::on_key_press_event (GdkEventKey* event)
1595 {
1596 // this is the original code from helper/window.cpp
1598 unsigned int shortcut;
1599 shortcut = get_group0_keyval (event) |
1600 ( event->state & GDK_SHIFT_MASK ?
1601 SP_SHORTCUT_SHIFT_MASK : 0 ) |
1602 ( event->state & GDK_CONTROL_MASK ?
1603 SP_SHORTCUT_CONTROL_MASK : 0 ) |
1604 ( event->state & GDK_MOD1_MASK ?
1605 SP_SHORTCUT_ALT_MASK : 0 );
1606 return sp_shortcut_invoke (shortcut,
1607 Inkscape::NSApplication::Editor::getActiveDesktop());
1608 }
1610 bool
1611 EditWidget::on_delete_event (GdkEventAny*)
1612 {
1613 return shutdown();
1614 }
1616 bool
1617 EditWidget::on_focus_in_event (GdkEventFocus*)
1618 {
1619 Inkscape::NSApplication::Editor::activateDesktop (_desktop);
1620 _svg_canvas.widget().grab_focus();
1622 return false;
1623 }
1625 void
1626 EditWidget::onWindowSizeAllocate (Gtk::Allocation &newall)
1627 {
1628 if (!is_realized()) return;
1630 const Gtk::Allocation& all = get_allocation();
1631 if ((newall.get_x() == all.get_x()) &&
1632 (newall.get_y() == all.get_y()) &&
1633 (newall.get_width() == all.get_width()) &&
1634 (newall.get_height() == all.get_height())) {
1635 return;
1636 }
1638 Geom::Rect const area = _desktop->get_display_area();
1639 double zoom = _desktop->current_zoom();
1641 if (_sticky_zoom.get_active()) {
1642 /* Calculate zoom per pixel */
1643 double const zpsp = zoom / hypot(area.dimensions()[Geom::X], area.dimensions()[Geom::Y]);
1644 /* Find new visible area */
1645 Geom::Rect const newarea = _desktop->get_display_area();
1646 /* Calculate adjusted zoom */
1647 zoom = zpsp * hypot(newarea.dimensions()[Geom::X], newarea.dimensions()[Geom::Y]);
1648 }
1650 _desktop->zoom_absolute(area.midpoint()[Geom::X], area.midpoint()[Geom::Y], zoom);
1651 }
1653 void
1654 EditWidget::onWindowRealize()
1655 {
1657 if ( (sp_document_width(_desktop->doc()) < 1.0) || (sp_document_height(_desktop->doc()) < 1.0) ) {
1658 return;
1659 }
1661 Geom::Rect d( Geom::Point(0, 0),
1662 Geom::Point(sp_document_width(_desktop->doc()), sp_document_height(_desktop->doc())) );
1664 _desktop->set_display_area(d.min()[Geom::X], d.min()[Geom::Y], d.max()[Geom::X], d.max()[Geom::Y], 10);
1665 _namedview_modified(_desktop->namedview, SP_OBJECT_MODIFIED_FLAG);
1666 setTitle (SP_DOCUMENT_NAME(_desktop->doc()));
1667 }
1669 void
1670 EditWidget::onAdjValueChanged()
1671 {
1672 if (_update_a_f) return;
1673 _update_a_f = true;
1675 sp_canvas_scroll_to (_svg_canvas.spobj(),
1676 _bottom_scrollbar.get_value(),
1677 _right_scrollbar.get_value(),
1678 false);
1679 updateRulers();
1681 _update_a_f = false;
1682 }
1685 } // namespace View
1686 } // namespace UI
1687 } // namespace Inkscape
1689 /*
1690 Local Variables:
1691 mode:c++
1692 c-file-style:"stroustrup"
1693 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1694 indent-tabs-mode:nil
1695 fill-column:99
1696 End:
1697 */
1698 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :