dbac65938e639cba3d584a8a3c0d3c2f332959b9
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 *
20 * Copyright (C) 1999-2005 Authors
21 * Copyright (C) 2000-2001 Ximian, Inc.
22 *
23 * Released under GNU GPL. Read the file 'COPYING' for more information.
24 */
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
30 #include <gtk/gtkwindow.h>
31 #include <gtk/gtkversion.h>
32 #include <gtk/gtklabel.h>
33 #include <gtkmm/radioaction.h>
34 #include <gtkmm/menubar.h>
35 #include <gtkmm/messagedialog.h>
36 #include <gtkmm/stock.h>
37 #include <gtkmm/accelmap.h>
38 #include <gtkmm/separator.h>
39 #include <gtkmm/base.h>
41 #include "macros.h"
42 #include "path-prefix.h"
43 #include "prefs-utils.h"
44 #include "file.h"
45 #include "application/editor.h"
46 #include "edit-widget.h"
47 #include "ui/stock.h"
48 #include "ui/stock-items.h"
49 #include "ui/icons.h"
51 #include "display/sodipodi-ctrlrect.h"
52 #include "helper/units.h"
53 #include "shortcuts.h"
54 #include "widgets/spw-utilities.h"
55 #include "event-context.h"
56 #include "document.h"
57 #include "sp-namedview.h"
58 #include "sp-item.h"
59 #include "interface.h"
60 #include "extension/db.h"
62 #ifdef WITH_INKBOARD
63 #include "ui/dialog/whiteboard-connect.h"
64 #include "ui/dialog/whiteboard-sharewithuser.h"
65 #include "ui/dialog/whiteboard-sharewithchat.h"
66 #endif
68 using namespace Inkscape::UI;
69 using namespace Inkscape::UI::Widget;
71 namespace Inkscape {
72 namespace UI {
73 namespace View {
75 EditWidget::EditWidget (SPDocument *doc)
76 : _main_window_table(4),
77 _viewport_table(3,3),
78 _act_grp(Gtk::ActionGroup::create()),
79 _ui_mgr(Gtk::UIManager::create()),
80 _update_s_f(false),
81 _update_a_f(false)
82 {
83 g_warning("Creating new EditWidget");
85 _desktop = 0;
86 Icons::init();
87 Stock::init();
88 initActions();
89 initAccelMap();
90 initUIManager();
91 initLayout();
92 initEdit (doc);
93 g_warning("Done creating new EditWidget");
94 }
96 EditWidget::~EditWidget()
97 {
98 destroyEdit();
99 }
101 void
102 EditWidget::initActions()
103 {
104 initMenuActions();
105 initToolbarActions();
106 }
108 void
109 EditWidget::initUIManager()
110 {
111 _ui_mgr->insert_action_group(_act_grp);
112 add_accel_group(_ui_mgr->get_accel_group());
114 gchar *filename_utf8 = g_build_filename(INKSCAPE_UIDIR, "menus-bars.xml", NULL);
115 if (_ui_mgr->add_ui_from_file(filename_utf8) == 0) {
116 g_warning("Error merging ui from file '%s'", filename_utf8);
117 // fixme-charset: What charset should we pass to g_warning?
118 }
119 g_free(filename_utf8);
120 }
122 void
123 EditWidget::initLayout()
124 {
125 set_title("New document 1 - Inkscape");
126 set_resizable();
127 set_default_size(640, 480);
129 // top level window into which all other portions of the UI get inserted
130 add(_main_window_table);
131 // attach box for horizontal toolbars
132 _main_window_table.attach(_toolbars_vbox, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
133 // attach sub-window for viewport and vertical toolbars
134 _main_window_table.attach(_sub_window_hbox, 0, 1, 2, 3);
135 // viewport table with 3 rows by 3 columns
136 _sub_window_hbox.pack_end(_viewport_table);
138 // Menus and Bars
139 initMenuBar();
140 initCommandsBar();
141 initToolControlsBar();
142 initUriBar();
143 initToolsBar();
145 // Canvas Viewport
146 initLeftRuler();
147 initTopRuler();
148 initStickyZoom();
149 initBottomScrollbar();
150 initRightScrollbar();
151 _viewport_table.attach(_svg_canvas.widget(), 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND);
152 _svg_canvas.widget().show_all();
155 // The statusbar comes last and appears at the bottom of _main_window_table
156 initStatusbar();
158 signal_size_allocate().connect (sigc::mem_fun (*this, &EditWidget::onWindowSizeAllocate), false);
159 signal_realize().connect (sigc::mem_fun (*this, &EditWidget::onWindowRealize));
160 show_all_children();
161 }
163 void
164 EditWidget::onMenuItem()
165 {
166 g_warning("onMenuItem called");
167 }
169 void
170 EditWidget::onActionFileNew()
171 {
172 // g_warning("onActionFileNew called");
173 sp_file_new_default();
174 }
176 void
177 EditWidget::onActionFileOpen()
178 {
179 // g_warning("onActionFileOpen called");
180 sp_file_open_dialog (NULL, NULL);
181 }
183 void
184 EditWidget::onActionFileQuit()
185 {
186 g_warning("onActionFileQuit");
187 sp_ui_close_all();
188 }
190 void
191 EditWidget::onActionFilePrint()
192 {
193 g_warning("onActionFilePrint");
194 }
196 void
197 EditWidget::onToolbarItem()
198 {
199 g_warning("onToolbarItem called");
200 }
202 void
203 EditWidget::onSelectTool()
204 {
205 _tool_ctrl->remove();
206 _tool_ctrl->add(*_select_ctrl);
207 }
209 void
210 EditWidget::onNodeTool()
211 {
212 _tool_ctrl->remove();
213 _tool_ctrl->add(*_node_ctrl);
214 }
216 void
217 EditWidget::onDialogInkscapePreferences()
218 {
219 _dlg_mgr.showDialog("InkscapePreferences");
220 }
222 void
223 EditWidget::onDialogAbout()
224 {
225 }
227 void
228 EditWidget::onDialogAlignAndDistribute()
229 {
230 _dlg_mgr.showDialog("AlignAndDistribute");
231 }
233 void
234 EditWidget::onDialogDocumentProperties()
235 {
236 // manage (Inkscape::UI::Dialog::DocumentPreferences::create());
237 _dlg_mgr.showDialog("DocumentPreferences");
238 }
240 void
241 EditWidget::onDialogExport()
242 {
243 _dlg_mgr.showDialog("Export");
244 }
246 void
247 EditWidget::onDialogExtensionEditor()
248 {
249 _dlg_mgr.showDialog("ExtensionEditor");
250 }
252 void
253 EditWidget::onDialogFillAndStroke()
254 {
255 _dlg_mgr.showDialog("FillAndStroke");
256 }
258 void
259 EditWidget::onDialogFind()
260 {
261 _dlg_mgr.showDialog("Find");
262 }
264 void
265 EditWidget::onDialogLayerEditor()
266 {
267 _dlg_mgr.showDialog("LayerEditor");
268 }
270 void
271 EditWidget::onDialogMessages()
272 {
273 _dlg_mgr.showDialog("Messages");
274 }
276 void
277 EditWidget::onDialogObjectProperties()
278 {
279 _dlg_mgr.showDialog("ObjectProperties");
280 }
282 void
283 EditWidget::onDialogTextProperties()
284 {
285 _dlg_mgr.showDialog("TextProperties");
286 }
288 void
289 EditWidget::onDialogTrace()
290 {
291 }
293 void
294 EditWidget::onDialogTransformation()
295 {
296 _dlg_mgr.showDialog("Transformation");
297 }
299 void
300 EditWidget::onDialogXmlEditor()
301 {
302 _dlg_mgr.showDialog("XmlEditor");
303 }
305 #ifdef WITH_INKBOARD
306 void
307 EditWidget::onDialogWhiteboardConnect()
308 {
309 Dialog::WhiteboardConnectDialogImpl* dlg = dynamic_cast< Dialog::WhiteboardConnectDialogImpl* >(_dlg_mgr.getDialog("WhiteboardConnect"));
310 dlg->setSessionManager();
311 _dlg_mgr.showDialog("WhiteboardConnect");
312 }
314 void
315 EditWidget::onDialogWhiteboardShareWithUser()
316 {
317 Dialog::WhiteboardShareWithUserDialogImpl* dlg = dynamic_cast< Dialog::WhiteboardShareWithUserDialogImpl* >(_dlg_mgr.getDialog("WhiteboardShareWithUser"));
318 dlg->setSessionManager();
319 _dlg_mgr.showDialog("WhiteboardShareWithUser");
320 }
322 void
323 EditWidget::onDialogWhiteboardShareWithChat()
324 {
325 Dialog::WhiteboardShareWithChatroomDialogImpl* dlg = dynamic_cast< Dialog::WhiteboardShareWithChatroomDialogImpl* >(_dlg_mgr.getDialog("WhiteboardShareWithChat"));
326 dlg->setSessionManager();
327 _dlg_mgr.showDialog("WhiteboardShareWithChat");
328 }
330 void
331 EditWidget::onDialogOpenSessionFile()
332 {
333 g_log(NULL, G_LOG_LEVEL_DEBUG, "not reimplemented yet");
334 }
336 void
337 EditWidget::onDumpXMLTracker()
338 {
339 g_log(NULL, G_LOG_LEVEL_DEBUG, "not reimplemented yet");
340 }
342 #endif
344 void
345 EditWidget::onUriChanged()
346 {
347 g_message("onUriChanged called");
349 }
351 // FIXME: strings are replaced by placeholders, NOT to be translated until the code is enabled
352 // See http://sourceforge.net/mailarchive/message.php?msg_id=11746016 for details
354 void
355 EditWidget::initMenuActions()
356 {
357 // _act_grp->add(Gtk::Action::create("MenuFile", _("PLACEHOLDER, do not translate")));
358 // _act_grp->add(Gtk::Action::create("MenuEdit", _("PLACEHOLDER, do not translate")));
359 // _act_grp->add(Gtk::Action::create("MenuView", _("PLACEHOLDER, do not translate")));
360 // _act_grp->add(Gtk::Action::create("MenuLayer", _("PLACEHOLDER, do not translate")));
361 // _act_grp->add(Gtk::Action::create("MenuObject", _("PLACEHOLDER, do not translate")));
362 // _act_grp->add(Gtk::Action::create("MenuPath", _("PLACEHOLDER, do not translate")));
363 // _act_grp->add(Gtk::Action::create("MenuText", _("PLACEHOLDER, do not translate")));
364 #ifdef WITH_INKBOARD
365 // _act_grp->add(Gtk::Action::create("MenuWhiteboard", _("PLACEHOLDER, do not translate")));
366 #endif
367 // _act_grp->add(Gtk::Action::create("MenuHelp", _("PLACEHOLDER, do not translate")));
368 // temporarily replaced with non-gettext version to have a well-sized menu
369 // for testing:
371 _act_grp->add(Gtk::Action::create("MenuFile", "File"));
372 _act_grp->add(Gtk::Action::create("MenuEdit", "Edit"));
373 _act_grp->add(Gtk::Action::create("MenuView", "View"));
374 _act_grp->add(Gtk::Action::create("MenuLayer", "Layer"));
375 _act_grp->add(Gtk::Action::create("MenuObject", "Object"));
376 _act_grp->add(Gtk::Action::create("MenuPath", "Path"));
377 _act_grp->add(Gtk::Action::create("MenuText", "Text"));
378 #ifdef WITH_INKBOARD
379 _act_grp->add(Gtk::Action::create("MenuWhiteboard", "Whiteboard"));
380 #endif
381 _act_grp->add(Gtk::Action::create("MenuHelp", "Help"));
383 // File menu
384 _act_grp->add(Gtk::Action::create("New",
385 Gtk::Stock::NEW, Glib::ustring(),
386 _("PLACEHOLDER, do not translate")),
387 sigc::mem_fun(*this, &EditWidget::onActionFileNew));
389 _act_grp->add(Gtk::Action::create("Open",
390 Gtk::Stock::OPEN, Glib::ustring(),
391 _("PLACEHOLDER, do not translate")),
392 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
394 _act_grp->add(Gtk::Action::create("OpenRecent",
395 Stock::OPEN_RECENT));
397 _act_grp->add(Gtk::Action::create("Revert",
398 Gtk::Stock::REVERT_TO_SAVED, Glib::ustring(),
399 _("PLACEHOLDER, do not translate")),
400 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
402 _act_grp->add(Gtk::Action::create("Save",
403 Gtk::Stock::SAVE, Glib::ustring(),
404 _("PLACEHOLDER, do not translate")),
405 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
407 _act_grp->add(Gtk::Action::create("SaveAs",
408 Gtk::Stock::SAVE_AS, Glib::ustring(),
409 _("PLACEHOLDER, do not translate")),
410 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
412 _act_grp->add(Gtk::Action::create("Import",
413 Stock::IMPORT, Glib::ustring(),
414 _("PLACEHOLDER, do not translate")),
415 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
417 _act_grp->add(Gtk::Action::create("Export",
418 Stock::EXPORT, Glib::ustring(),
419 _("PLACEHOLDER, do not translate")),
420 sigc::mem_fun(*this, &EditWidget::onDialogExport));
422 _act_grp->add(Gtk::Action::create("Print",
423 Gtk::Stock::PRINT, Glib::ustring(),
424 _("PLACEHOLDER, do not translate")),
425 sigc::mem_fun(*this, &EditWidget::onActionFilePrint));
427 _act_grp->add(Gtk::Action::create("PrintPreview",
428 Gtk::Stock::PRINT_PREVIEW),
429 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
431 _act_grp->add(Gtk::Action::create("VacuumDefs",
432 Stock::VACUUM_DEFS),
433 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
435 _act_grp->add(Gtk::Action::create("DocumentProperties",
436 Gtk::Stock::PROPERTIES, Glib::ustring(),
437 _("PLACEHOLDER, do not translate")),
438 sigc::mem_fun(*this, &EditWidget::onDialogDocumentProperties));
440 _act_grp->add(Gtk::Action::create("InkscapePreferences",
441 Gtk::Stock::PREFERENCES, Glib::ustring(),
442 _("PLACEHOLDER, do not translate")),
443 sigc::mem_fun(*this, &EditWidget::onDialogInkscapePreferences));
445 _act_grp->add(Gtk::Action::create("Close",
446 Gtk::Stock::CLOSE),
447 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
449 _act_grp->add(Gtk::Action::create("Quit",
450 Gtk::Stock::QUIT),
451 sigc::mem_fun(*this, &EditWidget::onActionFileQuit));
453 // EditWidget menu
454 _act_grp->add(Gtk::Action::create("Undo",
455 Gtk::Stock::UNDO, Glib::ustring(),
456 _("PLACEHOLDER, do not translate")));
458 _act_grp->add(Gtk::Action::create("Redo",
459 Gtk::Stock::REDO, Glib::ustring(),
460 _("PLACEHOLDER, do not translate")));
462 _act_grp->add(Gtk::Action::create("Cut",
463 Gtk::Stock::CUT, Glib::ustring(),
464 _("PLACEHOLDER, do not translate")));
466 _act_grp->add(Gtk::Action::create("Copy",
467 Gtk::Stock::COPY, Glib::ustring(),
468 _("PLACEHOLDER, do not translate")));
470 _act_grp->add(Gtk::Action::create("Paste",
471 Gtk::Stock::PASTE, Glib::ustring(),
472 _("PLACEHOLDER, do not translate")));
474 _act_grp->add(Gtk::Action::create("PasteInPlace",
475 Stock::PASTE_IN_PLACE));
477 _act_grp->add(Gtk::Action::create("PasteStyle",
478 Stock::PASTE_STYLE));
480 _act_grp->add(Gtk::Action::create("Find",
481 Gtk::Stock::FIND),
482 sigc::mem_fun(*this, &EditWidget::onDialogFind));
484 _act_grp->add(Gtk::Action::create("Duplicate",
485 Stock::DUPLICATE, Glib::ustring(),
486 _("PLACEHOLDER, do not translate")));
488 _act_grp->add(Gtk::Action::create("Clone",
489 Stock::CLONE, Glib::ustring(),
490 _("PLACEHOLDER, do not translate")));
492 _act_grp->add(Gtk::Action::create("CloneUnlink",
493 Stock::CLONE_UNLINK, Glib::ustring(),
494 _("PLACEHOLDER, do not translate")));
496 _act_grp->add(Gtk::Action::create("CloneSelectOrig",
497 Stock::CLONE_SELECT_ORIG));
499 _act_grp->add(Gtk::Action::create("MakeBitmap",
500 Stock::MAKE_BITMAP));
502 _act_grp->add(Gtk::Action::create("Tile",
503 Stock::TILE));
505 _act_grp->add(Gtk::Action::create("Untile",
506 Stock::UNTILE));
508 _act_grp->add(Gtk::Action::create("Delete",
509 Gtk::Stock::DELETE));
511 _act_grp->add(Gtk::Action::create("SelectAll",
512 Stock::SELECT_ALL));
514 _act_grp->add(Gtk::Action::create("SelectAllInAllLayers",
515 Stock::SELECT_ALL_IN_ALL_LAYERS));
517 _act_grp->add(Gtk::Action::create("SelectInvert",
518 Stock::SELECT_INVERT));
520 _act_grp->add(Gtk::Action::create("SelectNone",
521 Stock::SELECT_NONE));
523 _act_grp->add(Gtk::Action::create("XmlEditor",
524 Stock::XML_EDITOR, Glib::ustring(),
525 _("PLACEHOLDER, do not translate")),
526 sigc::mem_fun(*this, &EditWidget::onDialogXmlEditor));
528 // View menu
529 _act_grp->add(Gtk::Action::create("Zoom",
530 Stock::ZOOM));
532 _act_grp->add(Gtk::Action::create("ZoomIn",
533 Stock::ZOOM_IN, Glib::ustring(),
534 _("PLACEHOLDER, do not translate")));
536 _act_grp->add(Gtk::Action::create("ZoomOut",
537 Stock::ZOOM_OUT, Glib::ustring(),
538 _("PLACEHOLDER, do not translate")));
540 _act_grp->add(Gtk::Action::create("Zoom100",
541 Stock::ZOOM_100, Glib::ustring(),
542 _("PLACEHOLDER, do not translate")));
544 _act_grp->add(Gtk::Action::create("Zoom50",
545 Stock::ZOOM_50, Glib::ustring(),
546 _("PLACEHOLDER, do not translate")));
548 _act_grp->add(Gtk::Action::create("Zoom200",
549 Stock::ZOOM_200, Glib::ustring(),
550 _("PLACEHOLDER, do not translate")));
552 _act_grp->add(Gtk::Action::create("ZoomSelection",
553 Stock::ZOOM_SELECTION, Glib::ustring(),
554 _("PLACEHOLDER, do not translate")));
556 _act_grp->add(Gtk::Action::create("ZoomDrawing",
557 Stock::ZOOM_DRAWING, Glib::ustring(),
558 _("PLACEHOLDER, do not translate")));
560 _act_grp->add(Gtk::Action::create("ZoomPage",
561 Stock::ZOOM_PAGE, Glib::ustring(),
562 _("PLACEHOLDER, do not translate")));
564 _act_grp->add(Gtk::Action::create("ZoomWidth",
565 Stock::ZOOM_WIDTH, Glib::ustring(),
566 _("PLACEHOLDER, do not translate")));
568 _act_grp->add(Gtk::Action::create("ZoomPrev",
569 Stock::ZOOM_PREV, Glib::ustring(),
570 _("PLACEHOLDER, do not translate")));
572 _act_grp->add(Gtk::Action::create("ZoomNext",
573 Stock::ZOOM_NEXT, Glib::ustring(),
574 _("PLACEHOLDER, do not translate")));
576 _act_grp->add(Gtk::Action::create("ShowHide",
577 Stock::SHOW_HIDE));
579 _act_grp->add(Gtk::ToggleAction::create("ShowHideCommandsBar",
580 Stock::SHOW_HIDE_COMMANDS_BAR));
582 _act_grp->add(Gtk::ToggleAction::create("ShowHideToolControlsBar",
583 Stock::SHOW_HIDE_TOOL_CONTROLS_BAR));
585 _act_grp->add(Gtk::ToggleAction::create("ShowHideToolsBar",
586 Stock::SHOW_HIDE_TOOLS_BAR));
588 _act_grp->add(Gtk::ToggleAction::create("ShowHideRulers",
589 Stock::SHOW_HIDE_RULERS));
591 _act_grp->add(Gtk::ToggleAction::create("ShowHideScrollbars",
592 Stock::SHOW_HIDE_SCROLLBARS));
594 _act_grp->add(Gtk::ToggleAction::create("ShowHideStatusbar",
595 Stock::SHOW_HIDE_STATUSBAR));
597 _act_grp->add(Gtk::Action::create("ShowHideDialogs",
598 Stock::SHOW_HIDE_DIALOGS));
600 _act_grp->add(Gtk::Action::create("Grid",
601 Stock::GRID));
603 _act_grp->add(Gtk::Action::create("Guides",
604 Stock::GUIDES));
606 _act_grp->add(Gtk::Action::create("Fullscreen",
607 Stock::FULLSCREEN));
609 _act_grp->add(Gtk::Action::create("Messages",
610 Stock::MESSAGES),
611 sigc::mem_fun(*this, &EditWidget::onDialogMessages));
613 _act_grp->add(Gtk::Action::create("Scripts",
614 Stock::SCRIPTS));
616 _act_grp->add(Gtk::Action::create("WindowPrev",
617 Stock::WINDOW_PREV));
619 _act_grp->add(Gtk::Action::create("WindowNext",
620 Stock::WINDOW_NEXT));
622 _act_grp->add(Gtk::Action::create("WindowDuplicate",
623 Stock::WINDOW_DUPLICATE));
625 // Layer menu
626 _act_grp->add(Gtk::Action::create("LayerNew",
627 Stock::LAYER_NEW));
629 _act_grp->add(Gtk::Action::create("LayerRename",
630 Stock::LAYER_RENAME));
632 _act_grp->add(Gtk::Action::create("LayerDuplicate",
633 Stock::LAYER_DUPLICATE));
635 _act_grp->add(Gtk::Action::create("LayerAnchor",
636 Stock::LAYER_ANCHOR));
638 _act_grp->add(Gtk::Action::create("LayerMergeDown",
639 Stock::LAYER_MERGE_DOWN));
641 _act_grp->add(Gtk::Action::create("LayerDelete",
642 Stock::LAYER_DELETE));
644 _act_grp->add(Gtk::Action::create("LayerSelectNext",
645 Stock::LAYER_SELECT_NEXT));
647 _act_grp->add(Gtk::Action::create("LayerSelectPrev",
648 Stock::LAYER_SELECT_PREV));
650 _act_grp->add(Gtk::Action::create("LayerSelectTop",
651 Stock::LAYER_SELECT_TOP));
653 _act_grp->add(Gtk::Action::create("LayerSelectBottom",
654 Stock::LAYER_SELECT_BOTTOM));
656 _act_grp->add(Gtk::Action::create("LayerRaise",
657 Stock::LAYER_RAISE));
659 _act_grp->add(Gtk::Action::create("LayerLower",
660 Stock::LAYER_LOWER));
662 _act_grp->add(Gtk::Action::create("LayerToTop",
663 Stock::LAYER_TO_TOP));
665 _act_grp->add(Gtk::Action::create("LayerToBottom",
666 Stock::LAYER_TO_BOTTOM));
668 // Object menu
669 _act_grp->add(Gtk::Action::create("FillAndStroke",
670 Stock::FILL_STROKE, Glib::ustring(),
671 _("PLACEHOLDER, do not translate")),
672 sigc::mem_fun(*this, &EditWidget::onDialogFillAndStroke));
674 _act_grp->add(Gtk::Action::create("ObjectProperties",
675 Stock::OBJECT_PROPERTIES),
676 sigc::mem_fun(*this, &EditWidget::onDialogObjectProperties));
678 _act_grp->add(Gtk::Action::create("Group",
679 Stock::GROUP, Glib::ustring(),
680 _("PLACEHOLDER, do not translate")));
682 _act_grp->add(Gtk::Action::create("Ungroup",
683 Stock::UNGROUP, Glib::ustring(),
684 _("PLACEHOLDER, do not translate")));
686 _act_grp->add(Gtk::Action::create("Raise",
687 Stock::RAISE, Glib::ustring(),
688 _("PLACEHOLDER, do not translate")));
690 _act_grp->add(Gtk::Action::create("Lower",
691 Stock::LOWER, Glib::ustring(),
692 _("PLACEHOLDER, do not translate")));
694 _act_grp->add(Gtk::Action::create("RaiseToTop",
695 Stock::RAISE_TO_TOP, Glib::ustring(),
696 _("PLACEHOLDER, do not translate")));
698 _act_grp->add(Gtk::Action::create("LowerToBottom",
699 Stock::LOWER_TO_BOTTOM, Glib::ustring(),
700 _("PLACEHOLDER, do not translate")));
702 _act_grp->add(Gtk::Action::create("MoveToNewLayer",
703 Stock::MOVE_TO_NEW_LAYER, Glib::ustring(),
704 _("PLACEHOLDER, do not translate")));
706 _act_grp->add(Gtk::Action::create("MoveToNextLayer",
707 Stock::MOVE_TO_NEXT_LAYER, Glib::ustring(),
708 _("PLACEHOLDER, do not translate")));
710 _act_grp->add(Gtk::Action::create("MoveToPrevLayer",
711 Stock::MOVE_TO_PREV_LAYER, Glib::ustring(),
712 _("PLACEHOLDER, do not translate")));
714 _act_grp->add(Gtk::Action::create("MoveToTopLayer",
715 Stock::MOVE_TO_TOP_LAYER, Glib::ustring(),
716 _("PLACEHOLDER, do not translate")));
718 _act_grp->add(Gtk::Action::create("MoveToBottomLayer",
719 Stock::MOVE_TO_BOTTOM_LAYER, Glib::ustring(),
720 _("PLACEHOLDER, do not translate")));
722 _act_grp->add(Gtk::Action::create("Rotate90CW",
723 Stock::ROTATE_90_CW, Glib::ustring(),
724 _("PLACEHOLDER, do not translate")));
726 _act_grp->add(Gtk::Action::create("Rotate90CCW",
727 Stock::ROTATE_90_CCW, Glib::ustring(),
728 _("PLACEHOLDER, do not translate")));
730 _act_grp->add(Gtk::Action::create("FlipHoriz",
731 Stock::FLIP_HORIZ, Glib::ustring(),
732 _("PLACEHOLDER, do not translate")));
734 _act_grp->add(Gtk::Action::create("FlipVert",
735 Stock::FLIP_VERT, Glib::ustring(),
736 _("PLACEHOLDER, do not translate")));
738 _act_grp->add(Gtk::Action::create("Transformation",
739 Stock::TRANSFORMATION, Glib::ustring(),
740 _("PLACEHOLDER, do not translate")),
741 sigc::mem_fun(*this, &EditWidget::onDialogTransformation));
743 _act_grp->add(Gtk::Action::create("AlignAndDistribute",
744 Stock::ALIGN_DISTRIBUTE, Glib::ustring(),
745 _("PLACEHOLDER, do not translate")),
746 sigc::mem_fun(*this, &EditWidget::onDialogAlignAndDistribute));
748 // Path menu
749 _act_grp->add(Gtk::Action::create("ObjectToPath",
750 Stock::OBJECT_TO_PATH, Glib::ustring(),
751 _("PLACEHOLDER, do not translate")));
753 _act_grp->add(Gtk::Action::create("StrokeToPath",
754 Stock::STROKE_TO_PATH, Glib::ustring(),
755 _("PLACEHOLDER, do not translate")));
757 _act_grp->add(Gtk::Action::create("Trace",
758 Stock::TRACE),
759 sigc::mem_fun(*this, &EditWidget::onDialogTrace));
761 _act_grp->add(Gtk::Action::create("Union",
762 Stock::UNION));
764 _act_grp->add(Gtk::Action::create("Difference",
765 Stock::DIFFERENCE));
767 _act_grp->add(Gtk::Action::create("Intersection",
768 Stock::INTERSECTION));
770 _act_grp->add(Gtk::Action::create("Exclusion",
771 Stock::EXCLUSION));
773 _act_grp->add(Gtk::Action::create("Division",
774 Stock::DIVISION));
776 _act_grp->add(Gtk::Action::create("CutPath",
777 Stock::CUT_PATH));
779 _act_grp->add(Gtk::Action::create("Combine",
780 Stock::COMBINE));
782 _act_grp->add(Gtk::Action::create("BreakApart",
783 Stock::BREAK_APART));
785 _act_grp->add(Gtk::Action::create("Inset",
786 Stock::INSET));
788 _act_grp->add(Gtk::Action::create("Outset",
789 Stock::OUTSET));
791 _act_grp->add(Gtk::Action::create("OffsetDynamic",
792 Stock::OFFSET_DYNAMIC));
794 _act_grp->add(Gtk::Action::create("OffsetLinked",
795 Stock::OFFSET_LINKED));
797 _act_grp->add(Gtk::Action::create("Simplify",
798 Stock::SIMPLIFY));
800 _act_grp->add(Gtk::Action::create("Reverse",
801 Stock::REVERSE));
803 _act_grp->add(Gtk::Action::create("Cleanup",
804 Gtk::Stock::CLEAR,
805 _("PLACEHOLDER, do not translate")));
807 // Text menu
808 _act_grp->add(Gtk::Action::create("TextProperties",
809 Gtk::Stock::SELECT_FONT, Glib::ustring(),
810 _("PLACEHOLDER, do not translate")),
811 sigc::mem_fun(*this, &EditWidget::onDialogTextProperties));
813 _act_grp->add(Gtk::Action::create("PutOnPath",
814 Stock::PUT_ON_PATH));
816 _act_grp->add(Gtk::Action::create("RemoveFromPath",
817 Stock::REMOVE_FROM_PATH));
819 _act_grp->add(Gtk::Action::create("RemoveManualKerns",
820 Stock::REMOVE_MANUAL_KERNS));
822 // Whiteboard menu
823 #ifdef WITH_INKBOARD
824 _act_grp->add(Gtk::Action::create("DialogWhiteboardConnect",
825 Gtk::Stock::CLEAR, Glib::ustring(),
826 _("PLACEHOLDER, do not translate")),
827 sigc::mem_fun(*this, &EditWidget::onDialogWhiteboardConnect));
829 _act_grp->add(Gtk::Action::create("DialogWhiteboardShareWithUser",
830 Gtk::Stock::CLEAR, Glib::ustring(),
831 _("PLACEHOLDER, do not translate")),
832 sigc::mem_fun(*this, &EditWidget::onDialogWhiteboardShareWithUser));
834 _act_grp->add(Gtk::Action::create("DialogWhiteboardShareWithChat",
835 Gtk::Stock::CLEAR, Glib::ustring(),
836 _("PLACEHOLDER, do not translate")),
837 sigc::mem_fun(*this, &EditWidget::onDialogWhiteboardShareWithChat));
839 _act_grp->add(Gtk::Action::create("WhiteboardOpenSessionFile",
840 Gtk::Stock::CLEAR, Glib::ustring(),
841 _("PLACEHOLDER, do not translate")),
842 sigc::mem_fun(*this, &EditWidget::onDialogOpenSessionFile));
844 _act_grp->add(Gtk::Action::create("WhiteboardDumpXMLTracker",
845 Gtk::Stock::CLEAR, Glib::ustring(),
846 _("PLACEHOLDER, do not translate")),
847 sigc::mem_fun(*this, &EditWidget::onDumpXMLTracker));
848 #endif
850 // About menu
851 _act_grp->add(Gtk::Action::create("KeysAndMouse",
852 Stock::KEYS_MOUSE));
854 _act_grp->add(Gtk::Action::create("Tutorials",
855 Stock::TUTORIALS));
857 _act_grp->add(Gtk::Action::create("About",
858 Stock::ABOUT),
859 sigc::mem_fun(*this, &EditWidget::onDialogAbout));
860 }
862 void
863 EditWidget::initToolbarActions()
864 {
865 // Tools bar
866 Gtk::RadioAction::Group tools;
868 _act_grp->add(Gtk::RadioAction::create(tools, "ToolSelect",
869 Stock::TOOL_SELECT, Glib::ustring(),
870 _("PLACEHOLDER, do not translate")),
871 sigc::mem_fun(*this, &EditWidget::onSelectTool));
873 _act_grp->add(Gtk::RadioAction::create(tools, "ToolNode",
874 Stock::TOOL_NODE, Glib::ustring(),
875 _("PLACEHOLDER, do not translate")),
876 sigc::mem_fun(*this, &EditWidget::onNodeTool));
878 _act_grp->add(Gtk::RadioAction::create(tools, "ToolZoom",
879 Stock::TOOL_ZOOM, Glib::ustring(),
880 _("PLACEHOLDER, do not translate")));
882 _act_grp->add(Gtk::RadioAction::create(tools, "ToolRect",
883 Stock::TOOL_RECT, Glib::ustring(),
884 _("PLACEHOLDER, do not translate")));
886 _act_grp->add(Gtk::RadioAction::create(tools, "ToolArc",
887 Stock::TOOL_ARC, Glib::ustring(),
888 _("PLACEHOLDER, do not translate")));
890 _act_grp->add(Gtk::RadioAction::create(tools, "ToolStar",
891 Stock::TOOL_STAR, Glib::ustring(),
892 _("PLACEHOLDER, do not translate")));
894 _act_grp->add(Gtk::RadioAction::create(tools, "ToolSpiral",
895 Stock::TOOL_SPIRAL, Glib::ustring(),
896 _("PLACEHOLDER, do not translate")));
898 _act_grp->add(Gtk::RadioAction::create(tools, "ToolFreehand",
899 Stock::TOOL_FREEHAND, Glib::ustring(),
900 _("PLACEHOLDER, do not translate")));
902 _act_grp->add(Gtk::RadioAction::create(tools, "ToolPen",
903 Stock::TOOL_PEN, Glib::ustring(),
904 _("PLACEHOLDER, do not translate")));
906 _act_grp->add(Gtk::RadioAction::create(tools, "ToolDynaDraw",
907 Stock::TOOL_DYNADRAW, Glib::ustring(),
908 _("PLACEHOLDER, do not translate")));
910 _act_grp->add(Gtk::RadioAction::create(tools, "ToolText",
911 Stock::TOOL_TEXT, Glib::ustring(),
912 _("PLACEHOLDER, do not translate")));
914 _act_grp->add(Gtk::RadioAction::create(tools, "ToolDropper",
915 Stock::TOOL_DROPPER, Glib::ustring(),
916 _("PLACEHOLDER, do not translate")));
918 // Select Controls bar
919 _act_grp->add(Gtk::ToggleAction::create("TransformStroke",
920 Stock::TRANSFORM_STROKE, Glib::ustring(),
921 _("PLACEHOLDER, do not translate")));
923 _act_grp->add(Gtk::ToggleAction::create("TransformCorners",
924 Stock::TRANSFORM_CORNERS, Glib::ustring(),
925 _("PLACEHOLDER, do not translate")));
927 _act_grp->add(Gtk::ToggleAction::create("TransformGradient",
928 Stock::TRANSFORM_GRADIENT, Glib::ustring(),
929 _("PLACEHOLDER, do not translate")));
931 _act_grp->add(Gtk::ToggleAction::create("TransformPattern",
932 Stock::TRANSFORM_PATTERN, Glib::ustring(),
933 _("PLACEHOLDER, do not translate")));
935 // Node Controls bar
936 _act_grp->add(Gtk::Action::create("NodeInsert",
937 Gtk::Stock::ADD, Glib::ustring(),
938 _("PLACEHOLDER, do not translate")));
940 _act_grp->add(Gtk::Action::create("NodeDelete",
941 Gtk::Stock::REMOVE, Glib::ustring(),
942 _("PLACEHOLDER, do not translate")));
944 _act_grp->add(Gtk::Action::create("NodeJoin",
945 Stock::NODE_JOIN, Glib::ustring(),
946 _("PLACEHOLDER, do not translate")));
948 _act_grp->add(Gtk::Action::create("NodeJoinSegment",
949 Stock::NODE_JOIN_SEGMENT, Glib::ustring(),
950 _("PLACEHOLDER, do not translate")));
952 _act_grp->add(Gtk::Action::create("NodeDeleteSegment",
953 Stock::NODE_DELETE_SEGMENT, Glib::ustring(),
954 _("PLACEHOLDER, do not translate")));
956 _act_grp->add(Gtk::Action::create("NodeBreak",
957 Stock::NODE_BREAK, Glib::ustring(),
958 _("PLACEHOLDER, do not translate")));
960 _act_grp->add(Gtk::Action::create("NodeCorner",
961 Stock::NODE_CORNER, Glib::ustring(),
962 _("PLACEHOLDER, do not translate")));
964 _act_grp->add(Gtk::Action::create("NodeSmooth",
965 Stock::NODE_SMOOTH, Glib::ustring(),
966 _("PLACEHOLDER, do not translate")));
968 _act_grp->add(Gtk::Action::create("NodeSymmetric",
969 Stock::NODE_SYMMETRIC, Glib::ustring(),
970 _("PLACEHOLDER, do not translate")));
972 _act_grp->add(Gtk::Action::create("NodeLine",
973 Stock::NODE_LINE, Glib::ustring(),
974 _("PLACEHOLDER, do not translate")));
976 _act_grp->add(Gtk::Action::create("NodeCurve",
977 Stock::NODE_CURVE, Glib::ustring(),
978 _("PLACEHOLDER, do not translate")));
979 }
981 void
982 EditWidget::initAccelMap()
983 {
984 gchar *filename = g_build_filename(INKSCAPE_UIDIR, "keybindings.rc", NULL);
985 Gtk::AccelMap::load(filename);
986 g_free(filename);
988 // One problem is that the keys 1-6 are zoom accelerators which get
989 // caught as accelerator _before_ any Entry input handler receives them,
990 // for example the zoom status. At the moment, the best way seems to
991 // disable them as accelerators when the Entry gets focus, and enable
992 // them when focus goes elsewhere. The code for this belongs here,
993 // and not in zoom-status.cpp .
995 _zoom_status.signal_focus_in_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusIn));
996 _zoom_status.signal_focus_out_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusOut));
997 }
999 bool
1000 EditWidget::onEntryFocusIn (GdkEventFocus* ev)
1001 {
1002 Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
1003 Gtk::AccelMap::change_entry ("<Actions>//Zoom100", 0, m, false);
1004 Gtk::AccelMap::change_entry ("<Actions>//Zoom50", 0, m, false);
1005 Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", 0, m, false);
1006 Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", 0, m, false);
1007 Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", 0, m, false);
1008 Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", 0, m, false);
1009 return false;
1010 }
1012 bool
1013 EditWidget::onEntryFocusOut (GdkEventFocus* ev)
1014 {
1015 Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
1016 Gtk::AccelMap::change_entry ("<Actions>//Zoom100", '1', m, false);
1017 Gtk::AccelMap::change_entry ("<Actions>//Zoom50", '2', m, false);
1018 Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", '3', m, false);
1019 Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", '4', m, false);
1020 Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", '5', m, false);
1021 Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", '6', m, false);
1022 return false;
1023 }
1025 void
1026 EditWidget::initMenuBar()
1027 {
1028 g_assert(_ui_mgr);
1029 Gtk::MenuBar *menu = static_cast<Gtk::MenuBar*>(_ui_mgr->get_widget("/MenuBar"));
1030 g_assert(menu != NULL);
1031 _main_window_table.attach(*Gtk::manage(menu), 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1032 }
1034 void
1035 EditWidget::initCommandsBar()
1036 {
1037 g_assert(_ui_mgr);
1038 Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/CommandsBar")),
1039 Gtk::TOOLBAR_ICONS);
1040 g_assert(bar != NULL);
1041 _toolbars_vbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
1042 }
1044 void
1045 EditWidget::initToolControlsBar()
1046 {
1047 // TODO: Do UIManager controlled widgets need to be deleted?
1048 _select_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/SelectControlsBar"));
1049 _node_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/NodeControlsBar"));
1051 _tool_ctrl = new Toolbox(_select_ctrl, Gtk::TOOLBAR_ICONS);
1053 _toolbars_vbox.pack_start(*Gtk::manage(_tool_ctrl), Gtk::PACK_SHRINK);
1054 }
1056 void
1057 EditWidget::initUriBar()
1058 {
1059 /// \todo Create an Inkscape::UI::Widget::UriBar class (?)
1061 _uri_ctrl = new Gtk::Toolbar();
1063 _uri_label.set_label(_("PLACEHOLDER, DO NOT TRANSLATE"));
1064 _uri_ctrl->add(_uri_label);
1065 _uri_ctrl->add(_uri_entry);
1067 _uri_entry.signal_activate()
1068 .connect_notify(sigc::mem_fun(*this, &EditWidget::onUriChanged));
1070 _toolbars_vbox.pack_start(*Gtk::manage(_uri_ctrl), Gtk::PACK_SHRINK);
1071 }
1073 void
1074 EditWidget::initToolsBar()
1075 {
1076 Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/ToolsBar")),
1077 Gtk::TOOLBAR_ICONS,
1078 Gtk::ORIENTATION_VERTICAL);
1079 g_assert(bar != NULL);
1080 _sub_window_hbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
1081 }
1083 void
1084 EditWidget::initTopRuler()
1085 {
1086 _viewport_table.attach(_top_ruler, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1088 _tooltips.set_tip (_top_ruler, _top_ruler.get_tip());
1089 }
1091 void
1092 EditWidget::initLeftRuler()
1093 {
1094 _viewport_table.attach(_left_ruler, 0, 1, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1096 _tooltips.set_tip (_left_ruler, _left_ruler.get_tip());
1097 }
1099 void
1100 EditWidget::initBottomScrollbar()
1101 {
1102 _viewport_table.attach(_bottom_scrollbar, 1, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1103 _bottom_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1104 _bottom_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1105 }
1107 void
1108 EditWidget::initRightScrollbar()
1109 {
1110 _viewport_table.attach(_right_scrollbar, 2, 3, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1112 _right_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1113 _right_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1114 }
1116 void
1117 EditWidget::initStickyZoom()
1118 {
1119 _viewport_table.attach(_sticky_zoom, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
1121 _sticky_zoom.set_active (prefs_get_int_attribute ("options.stickyzoom", "value", 0) != 0);
1122 _tooltips.set_tip (_sticky_zoom, _("Zoom drawing if window size changes"));
1124 /// \todo icon not implemented
1125 }
1127 void
1128 EditWidget::initStatusbar()
1129 {
1130 _statusbar.pack_start (_selected_style_status, false, false, 1);
1131 _statusbar.pack_start (*new Gtk::VSeparator(), false, false, 0);
1133 _tooltips.set_tip (_zoom_status, _("Zoom"));
1135 _layer_selector.reference();
1136 _statusbar.pack_start (_layer_selector, false, false, 1);
1138 _coord_status.property_n_rows() = 2;
1139 _coord_status.property_n_columns() = 5;
1140 _coord_status.property_row_spacing() = 0;
1141 _coord_status.property_column_spacing() = 2;
1142 _coord_eventbox.add (_coord_status);
1143 _tooltips.set_tip (_coord_eventbox, _("Cursor coordinates"));
1144 _coord_status.attach (*new Gtk::VSeparator(), 0,1, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1145 _coord_status.attach (*new Gtk::Label("X:", 0.0, 0.5), 1,2, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1146 _coord_status.attach (*new Gtk::Label("Y:", 0.0, 0.5), 1,2, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1147 _coord_status_x.set_text ("0.0");
1148 _coord_status_x.set_alignment (0.0, 0.5);
1149 _coord_status_y.set_text ("0.0");
1150 _coord_status_y.set_alignment (0.0, 0.5);
1151 _coord_status.attach (_coord_status_x, 2,3, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1152 _coord_status.attach (_coord_status_y, 2,3, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1153 _coord_status.attach (*new Gtk::Label("Z:", 0.0, 0.5), 3,4, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1154 _coord_status.attach (_zoom_status, 4,5, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1155 sp_set_font_size_smaller (static_cast<GtkWidget*>((void*)_coord_status.gobj()));
1156 _statusbar.pack_end (_coord_eventbox, false, false, 1);
1158 _select_status.property_xalign() = 0.0;
1159 _select_status.property_yalign() = 0.5;
1160 _select_status.set_markup (_("<b>Welcome to Inkscape!</b> Use shape or freehand tools to create objects; use selector (arrow) to move or transform them."));
1161 // include this again with Gtk+-2.6
1162 #if GTK_VERSION_GE(2,6)
1163 gtk_label_set_ellipsize (GTK_LABEL(_select_status.gobj()), PANGO_ELLIPSIZE_END);
1164 #endif
1165 _select_status.set_size_request (1, -1);
1166 _statusbar.pack_start (_select_status, true, true, 0);
1168 _main_window_table.attach(_statusbar, 0, 1, 3, 4, Gtk::FILL, Gtk::SHRINK);
1169 }
1171 //========================================
1172 //----------implements EditWidgetInterface
1174 void *
1175 EditWidget::getWindow()
1176 {
1177 return this;
1178 }
1180 void
1181 EditWidget::setTitle (gchar const* new_title)
1182 {
1183 set_title (new_title);
1184 }
1186 void
1187 EditWidget::layout()
1188 {
1189 show_all_children();
1190 }
1192 void
1193 EditWidget::present()
1194 {
1195 this->Gtk::Window::present();
1196 }
1198 void
1199 EditWidget::getGeometry (gint &x, gint &y, gint &w, gint &h)
1200 {
1201 get_position (x, y);
1202 get_size (w, h);
1203 }
1205 void
1206 EditWidget::setSize (gint w, gint h)
1207 {
1208 resize (w, h);
1209 }
1211 void
1212 EditWidget::setPosition (NR::Point p)
1213 {
1214 move (int(p[NR::X]), int(p[NR::Y]));
1215 }
1217 /// \param p is already gobj()!
1218 void
1219 EditWidget::setTransient (void* p, int i)
1220 {
1221 #ifndef WIN32
1222 gtk_window_set_transient_for (static_cast<GtkWindow*>(p), this->gobj());
1223 if (i==2)
1224 this->Gtk::Window::present();
1225 #endif
1226 }
1228 NR::Point
1229 EditWidget::getPointer()
1230 {
1231 int x, y;
1232 get_pointer (x, y);
1233 return NR::Point (x, y);
1234 }
1236 void
1237 EditWidget::setFullscreen()
1238 {
1239 fullscreen();
1240 }
1242 /**
1243 * Shuts down the desktop object for the view being closed. It checks
1244 * to see if the document has been edited, and if so prompts the user
1245 * to save, discard, or cancel. Returns TRUE if the shutdown operation
1246 * is cancelled or if the save is cancelled or fails, FALSE otherwise.
1247 */
1248 bool
1249 EditWidget::shutdown()
1250 {
1251 g_assert (_desktop != NULL);
1252 if (Inkscape::NSApplication::Editor::isDuplicatedView (_desktop))
1253 return false;
1255 SPDocument *doc = _desktop->doc();
1256 if (sp_document_repr_root(doc)->attribute("sodipodi:modified") != NULL)
1257 {
1258 gchar *markup;
1259 /// \todo FIXME !!! obviously this will have problems if the document
1260 /// name contains markup characters
1261 markup = g_strdup_printf(
1262 _("<span weight=\"bold\" size=\"larger\">Save changes to document \"%s\" before closing?</span>\n\n"
1263 "If you close without saving, your changes will be discarded."),
1264 SP_DOCUMENT_NAME(doc));
1266 Gtk::MessageDialog dlg (*this,
1267 markup,
1268 true,
1269 Gtk::MESSAGE_WARNING,
1270 Gtk::BUTTONS_NONE,
1271 true);
1272 g_free(markup);
1273 Gtk::Button close_button (_("Close _without saving"), true);
1274 dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1275 close_button.show();
1276 dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1277 dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1278 dlg.set_default_response (Gtk::RESPONSE_YES);
1280 int response = dlg.run();
1281 switch (response)
1282 {
1283 case Gtk::RESPONSE_YES:
1284 sp_document_ref(doc);
1285 if (sp_file_save_document(doc)) {
1286 sp_document_unref(doc);
1287 } else { // save dialog cancelled or save failed
1288 sp_document_unref(doc);
1289 return TRUE;
1290 }
1291 break;
1292 case Gtk::RESPONSE_NO:
1293 break;
1294 default: // cancel pressed, or dialog was closed
1295 return TRUE;
1296 break;
1297 }
1298 }
1300 /* Code to check data loss */
1301 bool allow_data_loss = FALSE;
1302 while (sp_document_repr_root(doc)->attribute("inkscape:dataloss") != NULL && allow_data_loss == FALSE)
1303 {
1304 gchar *markup;
1305 /// \todo FIXME !!! obviously this will have problems if the document
1306 /// name contains markup characters
1307 markup = g_strdup_printf(
1308 _("<span weight=\"bold\" size=\"larger\">The file \"%s\" was saved with a format (%s) that may cause data loss!</span>\n\n"
1309 "Do you want to save this file in another format?"),
1310 SP_DOCUMENT_NAME(doc),
1311 Inkscape::Extension::db.get(sp_document_repr_root(doc)->attribute("inkscape:output_extension"))->get_name());
1313 Gtk::MessageDialog dlg (*this,
1314 markup,
1315 true,
1316 Gtk::MESSAGE_WARNING,
1317 Gtk::BUTTONS_NONE,
1318 true);
1319 g_free(markup);
1320 Gtk::Button close_button (_("Close _without saving"), true);
1321 dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1322 close_button.show();
1323 dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1324 dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1325 dlg.set_default_response (Gtk::RESPONSE_YES);
1327 int response = dlg.run();
1329 switch (response)
1330 {
1331 case Gtk::RESPONSE_YES:
1332 sp_document_ref(doc);
1333 if (sp_file_save_document(doc)) {
1334 sp_document_unref(doc);
1335 } else { // save dialog cancelled or save failed
1336 sp_document_unref(doc);
1337 return TRUE;
1338 }
1339 break;
1340 case Gtk::RESPONSE_NO:
1341 allow_data_loss = TRUE;
1342 break;
1343 default: // cancel pressed, or dialog was closed
1344 return TRUE;
1345 break;
1346 }
1347 }
1349 return false;
1350 }
1353 void
1354 EditWidget::destroy()
1355 {
1356 delete this;
1357 }
1359 void
1360 EditWidget::requestCanvasUpdate()
1361 {
1362 _svg_canvas.widget().queue_draw();
1363 }
1365 void
1366 EditWidget::activateDesktop()
1367 {
1368 /// \todo active_desktop_indicator not implemented
1369 }
1371 void
1372 EditWidget::deactivateDesktop()
1373 {
1374 /// \todo active_desktop_indicator not implemented
1375 }
1377 void
1378 EditWidget::viewSetPosition (NR::Point p)
1379 {
1380 p -= _namedview->gridorigin;
1381 double lo, up, pos, max;
1382 _top_ruler.get_range (lo, up, pos, max);
1383 _top_ruler.set_range (lo, up, p[NR::X], max);
1384 _left_ruler.get_range (lo, up, pos, max);
1385 _left_ruler.set_range (lo, up, p[NR::Y], max);
1386 }
1388 void
1389 EditWidget::updateRulers()
1390 {
1391 NR::Point origin = _namedview->gridorigin;
1393 NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1394 double lo, up, pos, max;
1395 double const scale = _desktop->current_zoom();
1396 double s = viewbox.min()[NR::X] / scale - origin[NR::X];
1397 double e = viewbox.max()[NR::X] / scale - origin[NR::X];
1398 _top_ruler.get_range(lo, up, pos, max);
1399 _top_ruler.set_range(s, e, pos, e);
1400 s = viewbox.min()[NR::Y] / -scale - origin[NR::Y];
1401 e = viewbox.max()[NR::Y] / -scale - origin[NR::Y];
1402 _left_ruler.set_range(s, e, origin[NR::Y], e);
1403 /// \todo is that correct?
1404 }
1406 void
1407 EditWidget::updateScrollbars (double scale)
1408 {
1409 // do not call this function before canvas has its size allocated
1410 if (!is_realized() || _update_s_f) {
1411 return;
1412 }
1414 _update_s_f = true;
1416 /* The desktop region we always show unconditionally */
1417 SPDocument *doc = _desktop->doc();
1418 NR::Rect const r = sp_item_bbox_desktop(SP_ITEM(SP_DOCUMENT_ROOT(doc)));
1419 NR::Rect darea(NR::Point(MIN(r.min()[NR::X], -sp_document_width(doc)),
1420 MIN(r.min()[NR::Y], -sp_document_height(doc))),
1421 NR::Point(MAX(r.max()[NR::X], 2 * sp_document_width(doc)),
1422 MAX(r.max()[NR::Y], 2 * sp_document_height(doc))));
1424 /* Canvas region we always show unconditionally */
1425 NR::Rect carea(NR::Point(darea.min()[NR::X] * scale - 64,
1426 darea.max()[NR::Y] * -scale - 64),
1427 NR::Point(darea.max()[NR::X] * scale + 64,
1428 darea.min()[NR::Y] * -scale + 64));
1430 NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1432 /* Viewbox is always included into scrollable region */
1433 carea = NR::Rect::union_bounds(carea, viewbox);
1435 Gtk::Adjustment *adj = _bottom_scrollbar.get_adjustment();
1436 adj->set_value(viewbox.min()[NR::X]);
1437 adj->set_lower(carea.min()[NR::X]);
1438 adj->set_upper(carea.max()[NR::X]);
1439 adj->set_page_increment(viewbox.dimensions()[NR::X]);
1440 adj->set_step_increment(0.1 * (viewbox.dimensions()[NR::X]));
1441 adj->set_page_size(viewbox.dimensions()[NR::X]);
1443 adj = _right_scrollbar.get_adjustment();
1444 adj->set_value(viewbox.min()[NR::Y]);
1445 adj->set_lower(carea.min()[NR::Y]);
1446 adj->set_upper(carea.max()[NR::Y]);
1447 adj->set_page_increment(viewbox.dimensions()[NR::Y]);
1448 adj->set_step_increment(0.1 * viewbox.dimensions()[NR::Y]);
1449 adj->set_page_size(viewbox.dimensions()[NR::Y]);
1451 _update_s_f = false;
1452 }
1454 void
1455 EditWidget::toggleRulers()
1456 {
1457 if (_top_ruler.is_visible())
1458 {
1459 _top_ruler.hide_all();
1460 _left_ruler.hide_all();
1461 prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 0);
1462 } else {
1463 _top_ruler.show_all();
1464 _left_ruler.show_all();
1465 prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 1);
1466 }
1467 }
1469 void
1470 EditWidget::toggleScrollbars()
1471 {
1472 if (_bottom_scrollbar.is_visible())
1473 {
1474 _bottom_scrollbar.hide_all();
1475 _right_scrollbar.hide_all();
1476 prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 0);
1477 } else {
1478 _bottom_scrollbar.show_all();
1479 _right_scrollbar.show_all();
1480 prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 1);
1481 }
1482 }
1484 void
1485 EditWidget::updateZoom()
1486 {
1487 _zoom_status.update();
1488 }
1490 void
1491 EditWidget::letZoomGrabFocus()
1492 {
1493 _zoom_status.grab_focus();
1494 }
1496 void
1497 EditWidget::setToolboxFocusTo (const gchar *)
1498 {
1499 /// \todo not implemented
1500 }
1502 void
1503 EditWidget::setToolboxAdjustmentValue (const gchar *, double)
1504 {
1505 /// \todo not implemented
1506 }
1508 bool
1509 EditWidget::isToolboxButtonActive (gchar const*)
1510 {
1511 /// \todo not implemented
1512 return true;
1513 }
1515 void
1516 EditWidget::setCoordinateStatus (NR::Point p)
1517 {
1518 gchar *cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::X]);
1519 _coord_status_x.property_label() = cstr;
1520 g_free (cstr);
1521 cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::Y]);
1522 _coord_status_y.property_label() = cstr;
1523 g_free (cstr);
1524 }
1526 void
1527 EditWidget::setMessage (Inkscape::MessageType type, gchar const* msg)
1528 {
1529 _select_status.set_markup (msg? msg : "");
1530 }
1532 bool
1533 EditWidget::warnDialog (gchar* msg)
1534 {
1535 Gtk::MessageDialog dlg (*this,
1536 msg,
1537 true,
1538 Gtk::MESSAGE_WARNING,
1539 Gtk::BUTTONS_YES_NO,
1540 true);
1541 int r = dlg.run();
1542 return r == Gtk::RESPONSE_YES;
1543 }
1546 void
1547 EditWidget::initEdit (SPDocument *doc)
1548 {
1549 _desktop = new SPDesktop();
1550 _desktop->registerEditWidget (this);
1552 _namedview = sp_document_namedview (doc, 0);
1553 _svg_canvas.init (_desktop);
1554 _desktop->init (_namedview, _svg_canvas.spobj());
1555 sp_namedview_window_from_document (_desktop);
1556 _dt2r = 1.0 / _namedview->doc_units->unittobase;
1558 /// \todo convert to sigc++ when SPObject hierarchy gets converted
1559 /* Listen on namedview modification */
1560 g_signal_connect (G_OBJECT (_desktop->namedview), "modified", G_CALLBACK (Inkscape::UI::View::_namedview_modified), this);
1561 _layer_selector.setDesktop (_desktop);
1562 _selected_style_status.setDesktop (_desktop);
1564 Inkscape::NSApplication::Editor::addDesktop (_desktop);
1566 _zoom_status.init (_desktop);
1567 _top_ruler.init (_desktop, _svg_canvas.widget());
1568 _left_ruler.init (_desktop, _svg_canvas.widget());
1569 updateRulers();
1570 }
1572 void
1573 EditWidget::destroyEdit()
1574 {
1575 if (_desktop) {
1576 _layer_selector.unreference();
1577 Inkscape::NSApplication::Editor::removeDesktop (_desktop); // clears selection too
1578 sp_signal_disconnect_by_data (G_OBJECT (_desktop->namedview), this);
1579 _desktop->destroy();
1580 Inkscape::GC::release (_desktop);
1581 _desktop = 0;
1582 }
1583 }
1585 //----------end of EditWidgetInterface implementation
1587 //----------start of other callbacks
1589 bool
1590 EditWidget::on_key_press_event (GdkEventKey* event)
1591 {
1592 // this is the original code from helper/window.cpp
1594 unsigned int shortcut;
1595 shortcut = get_group0_keyval (event) |
1596 ( event->state & GDK_SHIFT_MASK ?
1597 SP_SHORTCUT_SHIFT_MASK : 0 ) |
1598 ( event->state & GDK_CONTROL_MASK ?
1599 SP_SHORTCUT_CONTROL_MASK : 0 ) |
1600 ( event->state & GDK_MOD1_MASK ?
1601 SP_SHORTCUT_ALT_MASK : 0 );
1602 return sp_shortcut_invoke (shortcut,
1603 Inkscape::NSApplication::Editor::getActiveDesktop());
1604 }
1606 bool
1607 EditWidget::on_delete_event (GdkEventAny*)
1608 {
1609 return shutdown();
1610 }
1612 bool
1613 EditWidget::on_focus_in_event (GdkEventFocus*)
1614 {
1615 Inkscape::NSApplication::Editor::activateDesktop (_desktop);
1616 _svg_canvas.widget().grab_focus();
1618 return false;
1619 }
1621 void
1622 EditWidget::onWindowSizeAllocate (Gtk::Allocation &newall)
1623 {
1624 if (!is_realized()) return;
1626 const Gtk::Allocation& all = get_allocation();
1627 if ((newall.get_x() == all.get_x()) &&
1628 (newall.get_y() == all.get_y()) &&
1629 (newall.get_width() == all.get_width()) &&
1630 (newall.get_height() == all.get_height())) {
1631 return;
1632 }
1634 NR::Rect const area = _desktop->get_display_area();
1635 double zoom = _desktop->current_zoom();
1637 if (_sticky_zoom.get_active()) {
1638 /* Calculate zoom per pixel */
1639 double const zpsp = zoom / hypot(area.dimensions()[NR::X], area.dimensions()[NR::Y]);
1640 /* Find new visible area */
1641 NR::Rect const newarea = _desktop->get_display_area();
1642 /* Calculate adjusted zoom */
1643 zoom = zpsp * hypot(newarea.dimensions()[NR::X], newarea.dimensions()[NR::Y]);
1644 }
1646 _desktop->zoom_absolute(area.midpoint()[NR::X], area.midpoint()[NR::Y], zoom);
1647 }
1649 void
1650 EditWidget::onWindowRealize()
1651 {
1652 NR::Rect d(NR::Point(0, 0),
1653 NR::Point(sp_document_width(_desktop->doc()), sp_document_height(_desktop->doc())));
1655 if (fabs(d.dimensions()[NR::X]) < 1.0 || fabs(d.dimensions()[NR::Y]) < 1.0) {
1656 return;
1657 }
1659 _desktop->set_display_area(d.min()[NR::X], d.min()[NR::Y], d.max()[NR::X], d.max()[NR::Y], 10);
1660 _namedview_modified(_desktop->namedview, SP_OBJECT_MODIFIED_FLAG, this);
1661 setTitle (SP_DOCUMENT_NAME(_desktop->doc()));
1662 }
1664 void
1665 EditWidget::onAdjValueChanged()
1666 {
1667 if (_update_a_f) return;
1668 _update_a_f = true;
1670 sp_canvas_scroll_to (_svg_canvas.spobj(),
1671 _bottom_scrollbar.get_value(),
1672 _right_scrollbar.get_value(),
1673 false);
1674 updateRulers();
1676 _update_a_f = false;
1677 }
1679 /// \todo make this a member function when the signal is a sigc++ signal
1680 void _namedview_modified (SPNamedView* nv, guint flags, EditWidget* ew)
1681 {
1682 if (flags & SP_OBJECT_MODIFIED_FLAG)
1683 {
1684 ew->_dt2r = 1.0 / nv->doc_units->unittobase;
1685 ew->_top_ruler.update_metric();
1686 ew->_left_ruler.update_metric();
1687 ew->_tooltips.set_tip (ew->_top_ruler, ew->_top_ruler.get_tip());
1688 ew->_tooltips.set_tip (ew->_left_ruler, ew->_left_ruler.get_tip());
1689 ew->updateRulers();
1690 }
1691 }
1693 } // namespace View
1694 } // namespace UI
1695 } // namespace Inkscape
1697 /*
1698 Local Variables:
1699 mode:c++
1700 c-file-style:"stroustrup"
1701 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1702 indent-tabs-mode:nil
1703 fill-column:99
1704 End:
1705 */
1706 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :