b86a5d3f9f79261b6ca8bd6284ecff58f4f56c8c
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 <gtkmm/radioaction.h>
33 #include <gtkmm/menubar.h>
34 #include <gtkmm/messagedialog.h>
35 #include <gtkmm/stock.h>
36 #include <gtkmm/accelmap.h>
37 #include <gtkmm/separator.h>
39 #include "macros.h"
40 #include "path-prefix.h"
41 #include "prefs-utils.h"
42 #include "file.h"
43 #include "application/editor.h"
44 #include "edit-widget.h"
45 #include "ui/stock.h"
46 #include "ui/stock-items.h"
47 #include "ui/icons.h"
49 #include "display/sodipodi-ctrlrect.h"
50 #include "helper/units.h"
51 #include "shortcuts.h"
52 #include "widgets/spw-utilities.h"
53 #include "event-context.h"
54 #include "document.h"
55 #include "sp-namedview.h"
56 #include "sp-item.h"
57 #include "interface.h"
58 #include "extension/db.h"
60 #ifdef WITH_INKBOARD
61 #include "ui/dialog/whiteboard-connect.h"
62 #include "ui/dialog/whiteboard-sharewithuser.h"
63 #include "ui/dialog/whiteboard-sharewithchat.h"
64 #endif
66 using namespace Inkscape::UI;
67 using namespace Inkscape::UI::Widget;
69 namespace Inkscape {
70 namespace UI {
71 namespace View {
73 EditWidget::EditWidget (SPDocument *doc)
74 : _main_window_table(4),
75 _viewport_table(3,3),
76 _act_grp(Gtk::ActionGroup::create()),
77 _ui_mgr(Gtk::UIManager::create()),
78 _update_s_f(false),
79 _update_a_f(false)
80 {
81 g_warning("Creating new EditWidget");
83 _desktop = 0;
84 Icons::init();
85 Stock::init();
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();
153 // The statusbar comes last and appears at the bottom of _main_window_table
154 initStatusbar();
156 signal_size_allocate().connect (sigc::mem_fun (*this, &EditWidget::onWindowSizeAllocate), false);
157 signal_realize().connect (sigc::mem_fun (*this, &EditWidget::onWindowRealize));
158 show_all_children();
159 }
161 void
162 EditWidget::onMenuItem()
163 {
164 g_warning("onMenuItem called");
165 }
167 void
168 EditWidget::onActionFileNew()
169 {
170 // g_warning("onActionFileNew called");
171 sp_file_new_default();
172 }
174 void
175 EditWidget::onActionFileOpen()
176 {
177 // g_warning("onActionFileOpen called");
178 sp_file_open_dialog (NULL, NULL);
179 }
181 void
182 EditWidget::onActionFileQuit()
183 {
184 g_warning("onActionFileQuit");
185 sp_ui_close_all();
186 }
188 void
189 EditWidget::onActionFilePrint()
190 {
191 g_warning("onActionFilePrint");
192 }
194 void
195 EditWidget::onToolbarItem()
196 {
197 g_warning("onToolbarItem called");
198 }
200 void
201 EditWidget::onSelectTool()
202 {
203 _tool_ctrl->remove();
204 _tool_ctrl->add(*_select_ctrl);
205 }
207 void
208 EditWidget::onNodeTool()
209 {
210 _tool_ctrl->remove();
211 _tool_ctrl->add(*_node_ctrl);
212 }
214 void
215 EditWidget::onDialogInkscapePreferences()
216 {
217 _dlg_mgr.showDialog("InkscapePreferences");
218 }
220 void
221 EditWidget::onDialogAbout()
222 {
223 }
225 void
226 EditWidget::onDialogAlignAndDistribute()
227 {
228 _dlg_mgr.showDialog("AlignAndDistribute");
229 }
231 void
232 EditWidget::onDialogDocumentProperties()
233 {
234 // manage (Inkscape::UI::Dialog::DocumentPreferences::create());
235 _dlg_mgr.showDialog("DocumentPreferences");
236 }
238 void
239 EditWidget::onDialogExport()
240 {
241 _dlg_mgr.showDialog("Export");
242 }
244 void
245 EditWidget::onDialogExtensionEditor()
246 {
247 _dlg_mgr.showDialog("ExtensionEditor");
248 }
250 void
251 EditWidget::onDialogFillAndStroke()
252 {
253 _dlg_mgr.showDialog("FillAndStroke");
254 }
256 void
257 EditWidget::onDialogFind()
258 {
259 _dlg_mgr.showDialog("Find");
260 }
262 void
263 EditWidget::onDialogLayerEditor()
264 {
265 _dlg_mgr.showDialog("LayerEditor");
266 }
268 void
269 EditWidget::onDialogMessages()
270 {
271 _dlg_mgr.showDialog("Messages");
272 }
274 void
275 EditWidget::onDialogObjectProperties()
276 {
277 _dlg_mgr.showDialog("ObjectProperties");
278 }
280 void
281 EditWidget::onDialogTextProperties()
282 {
283 _dlg_mgr.showDialog("TextProperties");
284 }
286 void
287 EditWidget::onDialogTrace()
288 {
289 }
291 void
292 EditWidget::onDialogTransformation()
293 {
294 _dlg_mgr.showDialog("Transformation");
295 }
297 void
298 EditWidget::onDialogXmlEditor()
299 {
300 _dlg_mgr.showDialog("XmlEditor");
301 }
303 #ifdef WITH_INKBOARD
304 void
305 EditWidget::onDialogWhiteboardConnect()
306 {
307 Dialog::WhiteboardConnectDialogImpl* dlg = dynamic_cast< Dialog::WhiteboardConnectDialogImpl* >(_dlg_mgr.getDialog("WhiteboardConnect"));
308 dlg->setSessionManager();
309 _dlg_mgr.showDialog("WhiteboardConnect");
310 }
312 void
313 EditWidget::onDialogWhiteboardShareWithUser()
314 {
315 Dialog::WhiteboardShareWithUserDialogImpl* dlg = dynamic_cast< Dialog::WhiteboardShareWithUserDialogImpl* >(_dlg_mgr.getDialog("WhiteboardShareWithUser"));
316 dlg->setSessionManager();
317 _dlg_mgr.showDialog("WhiteboardShareWithUser");
318 }
320 void
321 EditWidget::onDialogWhiteboardShareWithChat()
322 {
323 Dialog::WhiteboardShareWithChatroomDialogImpl* dlg = dynamic_cast< Dialog::WhiteboardShareWithChatroomDialogImpl* >(_dlg_mgr.getDialog("WhiteboardShareWithChat"));
324 dlg->setSessionManager();
325 _dlg_mgr.showDialog("WhiteboardShareWithChat");
326 }
328 void
329 EditWidget::onDialogOpenSessionFile()
330 {
331 g_log(NULL, G_LOG_LEVEL_DEBUG, "not reimplemented yet");
332 }
334 void
335 EditWidget::onDumpXMLTracker()
336 {
337 g_log(NULL, G_LOG_LEVEL_DEBUG, "not reimplemented yet");
338 }
340 #endif
342 void
343 EditWidget::onUriChanged()
344 {
345 g_message("onUriChanged called");
347 }
349 // FIXME: strings are replaced by placeholders, NOT to be translated until the code is enabled
350 // See http://sourceforge.net/mailarchive/message.php?msg_id=11746016 for details
352 void
353 EditWidget::initMenuActions()
354 {
355 // _act_grp->add(Gtk::Action::create("MenuFile", _("PLACEHOLDER, do not translate")));
356 // _act_grp->add(Gtk::Action::create("MenuEdit", _("PLACEHOLDER, do not translate")));
357 // _act_grp->add(Gtk::Action::create("MenuView", _("PLACEHOLDER, do not translate")));
358 // _act_grp->add(Gtk::Action::create("MenuLayer", _("PLACEHOLDER, do not translate")));
359 // _act_grp->add(Gtk::Action::create("MenuObject", _("PLACEHOLDER, do not translate")));
360 // _act_grp->add(Gtk::Action::create("MenuPath", _("PLACEHOLDER, do not translate")));
361 // _act_grp->add(Gtk::Action::create("MenuText", _("PLACEHOLDER, do not translate")));
362 #ifdef WITH_INKBOARD
363 // _act_grp->add(Gtk::Action::create("MenuWhiteboard", _("PLACEHOLDER, do not translate")));
364 #endif
365 // _act_grp->add(Gtk::Action::create("MenuHelp", _("PLACEHOLDER, do not translate")));
366 // temporarily replaced with non-gettext version to have a well-sized menu
367 // for testing:
369 _act_grp->add(Gtk::Action::create("MenuFile", "File"));
370 _act_grp->add(Gtk::Action::create("MenuEdit", "Edit"));
371 _act_grp->add(Gtk::Action::create("MenuView", "View"));
372 _act_grp->add(Gtk::Action::create("MenuLayer", "Layer"));
373 _act_grp->add(Gtk::Action::create("MenuObject", "Object"));
374 _act_grp->add(Gtk::Action::create("MenuPath", "Path"));
375 _act_grp->add(Gtk::Action::create("MenuText", "Text"));
376 #ifdef WITH_INKBOARD
377 _act_grp->add(Gtk::Action::create("MenuWhiteboard", "Whiteboard"));
378 #endif
379 _act_grp->add(Gtk::Action::create("MenuHelp", "Help"));
381 // File menu
382 _act_grp->add(Gtk::Action::create("New",
383 Gtk::Stock::NEW, Glib::ustring(),
384 _("PLACEHOLDER, do not translate")),
385 sigc::mem_fun(*this, &EditWidget::onActionFileNew));
387 _act_grp->add(Gtk::Action::create("Open",
388 Gtk::Stock::OPEN, Glib::ustring(),
389 _("PLACEHOLDER, do not translate")),
390 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
392 _act_grp->add(Gtk::Action::create("OpenRecent",
393 Stock::OPEN_RECENT));
395 _act_grp->add(Gtk::Action::create("Revert",
396 Gtk::Stock::REVERT_TO_SAVED, Glib::ustring(),
397 _("PLACEHOLDER, do not translate")),
398 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
400 _act_grp->add(Gtk::Action::create("Save",
401 Gtk::Stock::SAVE, Glib::ustring(),
402 _("PLACEHOLDER, do not translate")),
403 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
405 _act_grp->add(Gtk::Action::create("SaveAs",
406 Gtk::Stock::SAVE_AS, Glib::ustring(),
407 _("PLACEHOLDER, do not translate")),
408 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
410 _act_grp->add(Gtk::Action::create("Import",
411 Stock::IMPORT, Glib::ustring(),
412 _("PLACEHOLDER, do not translate")),
413 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
415 _act_grp->add(Gtk::Action::create("Export",
416 Stock::EXPORT, Glib::ustring(),
417 _("PLACEHOLDER, do not translate")),
418 sigc::mem_fun(*this, &EditWidget::onDialogExport));
420 _act_grp->add(Gtk::Action::create("Print",
421 Gtk::Stock::PRINT, Glib::ustring(),
422 _("PLACEHOLDER, do not translate")),
423 sigc::mem_fun(*this, &EditWidget::onActionFilePrint));
425 _act_grp->add(Gtk::Action::create("PrintPreview",
426 Gtk::Stock::PRINT_PREVIEW),
427 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
429 _act_grp->add(Gtk::Action::create("VacuumDefs",
430 Stock::VACUUM_DEFS),
431 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
433 _act_grp->add(Gtk::Action::create("DocumentProperties",
434 Gtk::Stock::PROPERTIES, Glib::ustring(),
435 _("PLACEHOLDER, do not translate")),
436 sigc::mem_fun(*this, &EditWidget::onDialogDocumentProperties));
438 _act_grp->add(Gtk::Action::create("InkscapePreferences",
439 Gtk::Stock::PREFERENCES, Glib::ustring(),
440 _("PLACEHOLDER, do not translate")),
441 sigc::mem_fun(*this, &EditWidget::onDialogInkscapePreferences));
443 _act_grp->add(Gtk::Action::create("Close",
444 Gtk::Stock::CLOSE),
445 sigc::mem_fun(*this, &EditWidget::onActionFileOpen));
447 _act_grp->add(Gtk::Action::create("Quit",
448 Gtk::Stock::QUIT),
449 sigc::mem_fun(*this, &EditWidget::onActionFileQuit));
451 // EditWidget menu
452 _act_grp->add(Gtk::Action::create("Undo",
453 Gtk::Stock::UNDO, Glib::ustring(),
454 _("PLACEHOLDER, do not translate")));
456 _act_grp->add(Gtk::Action::create("Redo",
457 Gtk::Stock::REDO, Glib::ustring(),
458 _("PLACEHOLDER, do not translate")));
460 _act_grp->add(Gtk::Action::create("Cut",
461 Gtk::Stock::CUT, Glib::ustring(),
462 _("PLACEHOLDER, do not translate")));
464 _act_grp->add(Gtk::Action::create("Copy",
465 Gtk::Stock::COPY, Glib::ustring(),
466 _("PLACEHOLDER, do not translate")));
468 _act_grp->add(Gtk::Action::create("Paste",
469 Gtk::Stock::PASTE, Glib::ustring(),
470 _("PLACEHOLDER, do not translate")));
472 _act_grp->add(Gtk::Action::create("PasteInPlace",
473 Stock::PASTE_IN_PLACE));
475 _act_grp->add(Gtk::Action::create("PasteStyle",
476 Stock::PASTE_STYLE));
478 _act_grp->add(Gtk::Action::create("Find",
479 Gtk::Stock::FIND),
480 sigc::mem_fun(*this, &EditWidget::onDialogFind));
482 _act_grp->add(Gtk::Action::create("Duplicate",
483 Stock::DUPLICATE, Glib::ustring(),
484 _("PLACEHOLDER, do not translate")));
486 _act_grp->add(Gtk::Action::create("Clone",
487 Stock::CLONE, Glib::ustring(),
488 _("PLACEHOLDER, do not translate")));
490 _act_grp->add(Gtk::Action::create("CloneUnlink",
491 Stock::CLONE_UNLINK, Glib::ustring(),
492 _("PLACEHOLDER, do not translate")));
494 _act_grp->add(Gtk::Action::create("CloneSelectOrig",
495 Stock::CLONE_SELECT_ORIG));
497 _act_grp->add(Gtk::Action::create("MakeBitmap",
498 Stock::MAKE_BITMAP));
500 _act_grp->add(Gtk::Action::create("Tile",
501 Stock::TILE));
503 _act_grp->add(Gtk::Action::create("Untile",
504 Stock::UNTILE));
506 _act_grp->add(Gtk::Action::create("Delete",
507 Gtk::Stock::DELETE));
509 _act_grp->add(Gtk::Action::create("SelectAll",
510 Stock::SELECT_ALL));
512 _act_grp->add(Gtk::Action::create("SelectAllInAllLayers",
513 Stock::SELECT_ALL_IN_ALL_LAYERS));
515 _act_grp->add(Gtk::Action::create("SelectInvert",
516 Stock::SELECT_INVERT));
518 _act_grp->add(Gtk::Action::create("SelectNone",
519 Stock::SELECT_NONE));
521 _act_grp->add(Gtk::Action::create("XmlEditor",
522 Stock::XML_EDITOR, Glib::ustring(),
523 _("PLACEHOLDER, do not translate")),
524 sigc::mem_fun(*this, &EditWidget::onDialogXmlEditor));
526 // View menu
527 _act_grp->add(Gtk::Action::create("Zoom",
528 Stock::ZOOM));
530 _act_grp->add(Gtk::Action::create("ZoomIn",
531 Stock::ZOOM_IN, Glib::ustring(),
532 _("PLACEHOLDER, do not translate")));
534 _act_grp->add(Gtk::Action::create("ZoomOut",
535 Stock::ZOOM_OUT, Glib::ustring(),
536 _("PLACEHOLDER, do not translate")));
538 _act_grp->add(Gtk::Action::create("Zoom100",
539 Stock::ZOOM_100, Glib::ustring(),
540 _("PLACEHOLDER, do not translate")));
542 _act_grp->add(Gtk::Action::create("Zoom50",
543 Stock::ZOOM_50, Glib::ustring(),
544 _("PLACEHOLDER, do not translate")));
546 _act_grp->add(Gtk::Action::create("Zoom200",
547 Stock::ZOOM_200, Glib::ustring(),
548 _("PLACEHOLDER, do not translate")));
550 _act_grp->add(Gtk::Action::create("ZoomSelection",
551 Stock::ZOOM_SELECTION, Glib::ustring(),
552 _("PLACEHOLDER, do not translate")));
554 _act_grp->add(Gtk::Action::create("ZoomDrawing",
555 Stock::ZOOM_DRAWING, Glib::ustring(),
556 _("PLACEHOLDER, do not translate")));
558 _act_grp->add(Gtk::Action::create("ZoomPage",
559 Stock::ZOOM_PAGE, Glib::ustring(),
560 _("PLACEHOLDER, do not translate")));
562 _act_grp->add(Gtk::Action::create("ZoomWidth",
563 Stock::ZOOM_WIDTH, Glib::ustring(),
564 _("PLACEHOLDER, do not translate")));
566 _act_grp->add(Gtk::Action::create("ZoomPrev",
567 Stock::ZOOM_PREV, Glib::ustring(),
568 _("PLACEHOLDER, do not translate")));
570 _act_grp->add(Gtk::Action::create("ZoomNext",
571 Stock::ZOOM_NEXT, Glib::ustring(),
572 _("PLACEHOLDER, do not translate")));
574 _act_grp->add(Gtk::Action::create("ShowHide",
575 Stock::SHOW_HIDE));
577 _act_grp->add(Gtk::ToggleAction::create("ShowHideCommandsBar",
578 Stock::SHOW_HIDE_COMMANDS_BAR));
580 _act_grp->add(Gtk::ToggleAction::create("ShowHideToolControlsBar",
581 Stock::SHOW_HIDE_TOOL_CONTROLS_BAR));
583 _act_grp->add(Gtk::ToggleAction::create("ShowHideToolsBar",
584 Stock::SHOW_HIDE_TOOLS_BAR));
586 _act_grp->add(Gtk::ToggleAction::create("ShowHideRulers",
587 Stock::SHOW_HIDE_RULERS));
589 _act_grp->add(Gtk::ToggleAction::create("ShowHideScrollbars",
590 Stock::SHOW_HIDE_SCROLLBARS));
592 _act_grp->add(Gtk::ToggleAction::create("ShowHideStatusbar",
593 Stock::SHOW_HIDE_STATUSBAR));
595 _act_grp->add(Gtk::Action::create("ShowHideDialogs",
596 Stock::SHOW_HIDE_DIALOGS));
598 _act_grp->add(Gtk::Action::create("Grid",
599 Stock::GRID));
601 _act_grp->add(Gtk::Action::create("Guides",
602 Stock::GUIDES));
604 _act_grp->add(Gtk::Action::create("Fullscreen",
605 Stock::FULLSCREEN));
607 _act_grp->add(Gtk::Action::create("Messages",
608 Stock::MESSAGES),
609 sigc::mem_fun(*this, &EditWidget::onDialogMessages));
611 _act_grp->add(Gtk::Action::create("Scripts",
612 Stock::SCRIPTS));
614 _act_grp->add(Gtk::Action::create("WindowPrev",
615 Stock::WINDOW_PREV));
617 _act_grp->add(Gtk::Action::create("WindowNext",
618 Stock::WINDOW_NEXT));
620 _act_grp->add(Gtk::Action::create("WindowDuplicate",
621 Stock::WINDOW_DUPLICATE));
623 // Layer menu
624 _act_grp->add(Gtk::Action::create("LayerNew",
625 Stock::LAYER_NEW));
627 _act_grp->add(Gtk::Action::create("LayerRename",
628 Stock::LAYER_RENAME));
630 _act_grp->add(Gtk::Action::create("LayerDuplicate",
631 Stock::LAYER_DUPLICATE));
633 _act_grp->add(Gtk::Action::create("LayerAnchor",
634 Stock::LAYER_ANCHOR));
636 _act_grp->add(Gtk::Action::create("LayerMergeDown",
637 Stock::LAYER_MERGE_DOWN));
639 _act_grp->add(Gtk::Action::create("LayerDelete",
640 Stock::LAYER_DELETE));
642 _act_grp->add(Gtk::Action::create("LayerSelectNext",
643 Stock::LAYER_SELECT_NEXT));
645 _act_grp->add(Gtk::Action::create("LayerSelectPrev",
646 Stock::LAYER_SELECT_PREV));
648 _act_grp->add(Gtk::Action::create("LayerSelectTop",
649 Stock::LAYER_SELECT_TOP));
651 _act_grp->add(Gtk::Action::create("LayerSelectBottom",
652 Stock::LAYER_SELECT_BOTTOM));
654 _act_grp->add(Gtk::Action::create("LayerRaise",
655 Stock::LAYER_RAISE));
657 _act_grp->add(Gtk::Action::create("LayerLower",
658 Stock::LAYER_LOWER));
660 _act_grp->add(Gtk::Action::create("LayerToTop",
661 Stock::LAYER_TO_TOP));
663 _act_grp->add(Gtk::Action::create("LayerToBottom",
664 Stock::LAYER_TO_BOTTOM));
666 // Object menu
667 _act_grp->add(Gtk::Action::create("FillAndStroke",
668 Stock::FILL_STROKE, Glib::ustring(),
669 _("PLACEHOLDER, do not translate")),
670 sigc::mem_fun(*this, &EditWidget::onDialogFillAndStroke));
672 _act_grp->add(Gtk::Action::create("ObjectProperties",
673 Stock::OBJECT_PROPERTIES),
674 sigc::mem_fun(*this, &EditWidget::onDialogObjectProperties));
676 _act_grp->add(Gtk::Action::create("Group",
677 Stock::GROUP, Glib::ustring(),
678 _("PLACEHOLDER, do not translate")));
680 _act_grp->add(Gtk::Action::create("Ungroup",
681 Stock::UNGROUP, Glib::ustring(),
682 _("PLACEHOLDER, do not translate")));
684 _act_grp->add(Gtk::Action::create("Raise",
685 Stock::RAISE, Glib::ustring(),
686 _("PLACEHOLDER, do not translate")));
688 _act_grp->add(Gtk::Action::create("Lower",
689 Stock::LOWER, Glib::ustring(),
690 _("PLACEHOLDER, do not translate")));
692 _act_grp->add(Gtk::Action::create("RaiseToTop",
693 Stock::RAISE_TO_TOP, Glib::ustring(),
694 _("PLACEHOLDER, do not translate")));
696 _act_grp->add(Gtk::Action::create("LowerToBottom",
697 Stock::LOWER_TO_BOTTOM, Glib::ustring(),
698 _("PLACEHOLDER, do not translate")));
700 _act_grp->add(Gtk::Action::create("MoveToNewLayer",
701 Stock::MOVE_TO_NEW_LAYER, Glib::ustring(),
702 _("PLACEHOLDER, do not translate")));
704 _act_grp->add(Gtk::Action::create("MoveToNextLayer",
705 Stock::MOVE_TO_NEXT_LAYER, Glib::ustring(),
706 _("PLACEHOLDER, do not translate")));
708 _act_grp->add(Gtk::Action::create("MoveToPrevLayer",
709 Stock::MOVE_TO_PREV_LAYER, Glib::ustring(),
710 _("PLACEHOLDER, do not translate")));
712 _act_grp->add(Gtk::Action::create("MoveToTopLayer",
713 Stock::MOVE_TO_TOP_LAYER, Glib::ustring(),
714 _("PLACEHOLDER, do not translate")));
716 _act_grp->add(Gtk::Action::create("MoveToBottomLayer",
717 Stock::MOVE_TO_BOTTOM_LAYER, Glib::ustring(),
718 _("PLACEHOLDER, do not translate")));
720 _act_grp->add(Gtk::Action::create("Rotate90CW",
721 Stock::ROTATE_90_CW, Glib::ustring(),
722 _("PLACEHOLDER, do not translate")));
724 _act_grp->add(Gtk::Action::create("Rotate90CCW",
725 Stock::ROTATE_90_CCW, Glib::ustring(),
726 _("PLACEHOLDER, do not translate")));
728 _act_grp->add(Gtk::Action::create("FlipHoriz",
729 Stock::FLIP_HORIZ, Glib::ustring(),
730 _("PLACEHOLDER, do not translate")));
732 _act_grp->add(Gtk::Action::create("FlipVert",
733 Stock::FLIP_VERT, Glib::ustring(),
734 _("PLACEHOLDER, do not translate")));
736 _act_grp->add(Gtk::Action::create("Transformation",
737 Stock::TRANSFORMATION, Glib::ustring(),
738 _("PLACEHOLDER, do not translate")),
739 sigc::mem_fun(*this, &EditWidget::onDialogTransformation));
741 _act_grp->add(Gtk::Action::create("AlignAndDistribute",
742 Stock::ALIGN_DISTRIBUTE, Glib::ustring(),
743 _("PLACEHOLDER, do not translate")),
744 sigc::mem_fun(*this, &EditWidget::onDialogAlignAndDistribute));
746 // Path menu
747 _act_grp->add(Gtk::Action::create("ObjectToPath",
748 Stock::OBJECT_TO_PATH, Glib::ustring(),
749 _("PLACEHOLDER, do not translate")));
751 _act_grp->add(Gtk::Action::create("StrokeToPath",
752 Stock::STROKE_TO_PATH, Glib::ustring(),
753 _("PLACEHOLDER, do not translate")));
755 _act_grp->add(Gtk::Action::create("Trace",
756 Stock::TRACE),
757 sigc::mem_fun(*this, &EditWidget::onDialogTrace));
759 _act_grp->add(Gtk::Action::create("Union",
760 Stock::UNION));
762 _act_grp->add(Gtk::Action::create("Difference",
763 Stock::DIFFERENCE));
765 _act_grp->add(Gtk::Action::create("Intersection",
766 Stock::INTERSECTION));
768 _act_grp->add(Gtk::Action::create("Exclusion",
769 Stock::EXCLUSION));
771 _act_grp->add(Gtk::Action::create("Division",
772 Stock::DIVISION));
774 _act_grp->add(Gtk::Action::create("CutPath",
775 Stock::CUT_PATH));
777 _act_grp->add(Gtk::Action::create("Combine",
778 Stock::COMBINE));
780 _act_grp->add(Gtk::Action::create("BreakApart",
781 Stock::BREAK_APART));
783 _act_grp->add(Gtk::Action::create("Inset",
784 Stock::INSET));
786 _act_grp->add(Gtk::Action::create("Outset",
787 Stock::OUTSET));
789 _act_grp->add(Gtk::Action::create("OffsetDynamic",
790 Stock::OFFSET_DYNAMIC));
792 _act_grp->add(Gtk::Action::create("OffsetLinked",
793 Stock::OFFSET_LINKED));
795 _act_grp->add(Gtk::Action::create("Simplify",
796 Stock::SIMPLIFY));
798 _act_grp->add(Gtk::Action::create("Reverse",
799 Stock::REVERSE));
801 _act_grp->add(Gtk::Action::create("Cleanup",
802 Gtk::Stock::CLEAR,
803 _("PLACEHOLDER, do not translate")));
805 // Text menu
806 _act_grp->add(Gtk::Action::create("TextProperties",
807 Gtk::Stock::SELECT_FONT, Glib::ustring(),
808 _("PLACEHOLDER, do not translate")),
809 sigc::mem_fun(*this, &EditWidget::onDialogTextProperties));
811 _act_grp->add(Gtk::Action::create("PutOnPath",
812 Stock::PUT_ON_PATH));
814 _act_grp->add(Gtk::Action::create("RemoveFromPath",
815 Stock::REMOVE_FROM_PATH));
817 _act_grp->add(Gtk::Action::create("RemoveManualKerns",
818 Stock::REMOVE_MANUAL_KERNS));
820 // Whiteboard menu
821 #ifdef WITH_INKBOARD
822 _act_grp->add(Gtk::Action::create("DialogWhiteboardConnect",
823 Gtk::Stock::CLEAR, Glib::ustring(),
824 _("PLACEHOLDER, do not translate")),
825 sigc::mem_fun(*this, &EditWidget::onDialogWhiteboardConnect));
827 _act_grp->add(Gtk::Action::create("DialogWhiteboardShareWithUser",
828 Gtk::Stock::CLEAR, Glib::ustring(),
829 _("PLACEHOLDER, do not translate")),
830 sigc::mem_fun(*this, &EditWidget::onDialogWhiteboardShareWithUser));
832 _act_grp->add(Gtk::Action::create("DialogWhiteboardShareWithChat",
833 Gtk::Stock::CLEAR, Glib::ustring(),
834 _("PLACEHOLDER, do not translate")),
835 sigc::mem_fun(*this, &EditWidget::onDialogWhiteboardShareWithChat));
837 _act_grp->add(Gtk::Action::create("WhiteboardOpenSessionFile",
838 Gtk::Stock::CLEAR, Glib::ustring(),
839 _("PLACEHOLDER, do not translate")),
840 sigc::mem_fun(*this, &EditWidget::onDialogOpenSessionFile));
842 _act_grp->add(Gtk::Action::create("WhiteboardDumpXMLTracker",
843 Gtk::Stock::CLEAR, Glib::ustring(),
844 _("PLACEHOLDER, do not translate")),
845 sigc::mem_fun(*this, &EditWidget::onDumpXMLTracker));
846 #endif
848 // About menu
849 _act_grp->add(Gtk::Action::create("KeysAndMouse",
850 Stock::KEYS_MOUSE));
852 _act_grp->add(Gtk::Action::create("Tutorials",
853 Stock::TUTORIALS));
855 _act_grp->add(Gtk::Action::create("About",
856 Stock::ABOUT),
857 sigc::mem_fun(*this, &EditWidget::onDialogAbout));
858 }
860 void
861 EditWidget::initToolbarActions()
862 {
863 // Tools bar
864 Gtk::RadioAction::Group tools;
866 _act_grp->add(Gtk::RadioAction::create(tools, "ToolSelect",
867 Stock::TOOL_SELECT, Glib::ustring(),
868 _("PLACEHOLDER, do not translate")),
869 sigc::mem_fun(*this, &EditWidget::onSelectTool));
871 _act_grp->add(Gtk::RadioAction::create(tools, "ToolNode",
872 Stock::TOOL_NODE, Glib::ustring(),
873 _("PLACEHOLDER, do not translate")),
874 sigc::mem_fun(*this, &EditWidget::onNodeTool));
876 _act_grp->add(Gtk::RadioAction::create(tools, "ToolZoom",
877 Stock::TOOL_ZOOM, Glib::ustring(),
878 _("PLACEHOLDER, do not translate")));
880 _act_grp->add(Gtk::RadioAction::create(tools, "ToolRect",
881 Stock::TOOL_RECT, Glib::ustring(),
882 _("PLACEHOLDER, do not translate")));
884 _act_grp->add(Gtk::RadioAction::create(tools, "ToolArc",
885 Stock::TOOL_ARC, Glib::ustring(),
886 _("PLACEHOLDER, do not translate")));
888 _act_grp->add(Gtk::RadioAction::create(tools, "ToolStar",
889 Stock::TOOL_STAR, Glib::ustring(),
890 _("PLACEHOLDER, do not translate")));
892 _act_grp->add(Gtk::RadioAction::create(tools, "ToolSpiral",
893 Stock::TOOL_SPIRAL, Glib::ustring(),
894 _("PLACEHOLDER, do not translate")));
896 _act_grp->add(Gtk::RadioAction::create(tools, "ToolFreehand",
897 Stock::TOOL_FREEHAND, Glib::ustring(),
898 _("PLACEHOLDER, do not translate")));
900 _act_grp->add(Gtk::RadioAction::create(tools, "ToolPen",
901 Stock::TOOL_PEN, Glib::ustring(),
902 _("PLACEHOLDER, do not translate")));
904 _act_grp->add(Gtk::RadioAction::create(tools, "ToolDynaDraw",
905 Stock::TOOL_DYNADRAW, Glib::ustring(),
906 _("PLACEHOLDER, do not translate")));
908 _act_grp->add(Gtk::RadioAction::create(tools, "ToolText",
909 Stock::TOOL_TEXT, Glib::ustring(),
910 _("PLACEHOLDER, do not translate")));
912 _act_grp->add(Gtk::RadioAction::create(tools, "ToolDropper",
913 Stock::TOOL_DROPPER, Glib::ustring(),
914 _("PLACEHOLDER, do not translate")));
916 // Select Controls bar
917 _act_grp->add(Gtk::ToggleAction::create("TransformStroke",
918 Stock::TRANSFORM_STROKE, Glib::ustring(),
919 _("PLACEHOLDER, do not translate")));
921 _act_grp->add(Gtk::ToggleAction::create("TransformCorners",
922 Stock::TRANSFORM_CORNERS, Glib::ustring(),
923 _("PLACEHOLDER, do not translate")));
925 _act_grp->add(Gtk::ToggleAction::create("TransformGradient",
926 Stock::TRANSFORM_GRADIENT, Glib::ustring(),
927 _("PLACEHOLDER, do not translate")));
929 _act_grp->add(Gtk::ToggleAction::create("TransformPattern",
930 Stock::TRANSFORM_PATTERN, Glib::ustring(),
931 _("PLACEHOLDER, do not translate")));
933 // Node Controls bar
934 _act_grp->add(Gtk::Action::create("NodeInsert",
935 Gtk::Stock::ADD, Glib::ustring(),
936 _("PLACEHOLDER, do not translate")));
938 _act_grp->add(Gtk::Action::create("NodeDelete",
939 Gtk::Stock::REMOVE, Glib::ustring(),
940 _("PLACEHOLDER, do not translate")));
942 _act_grp->add(Gtk::Action::create("NodeJoin",
943 Stock::NODE_JOIN, Glib::ustring(),
944 _("PLACEHOLDER, do not translate")));
946 _act_grp->add(Gtk::Action::create("NodeJoinSegment",
947 Stock::NODE_JOIN_SEGMENT, Glib::ustring(),
948 _("PLACEHOLDER, do not translate")));
950 _act_grp->add(Gtk::Action::create("NodeDeleteSegment",
951 Stock::NODE_DELETE_SEGMENT, Glib::ustring(),
952 _("PLACEHOLDER, do not translate")));
954 _act_grp->add(Gtk::Action::create("NodeBreak",
955 Stock::NODE_BREAK, Glib::ustring(),
956 _("PLACEHOLDER, do not translate")));
958 _act_grp->add(Gtk::Action::create("NodeCorner",
959 Stock::NODE_CORNER, Glib::ustring(),
960 _("PLACEHOLDER, do not translate")));
962 _act_grp->add(Gtk::Action::create("NodeSmooth",
963 Stock::NODE_SMOOTH, Glib::ustring(),
964 _("PLACEHOLDER, do not translate")));
966 _act_grp->add(Gtk::Action::create("NodeSymmetric",
967 Stock::NODE_SYMMETRIC, Glib::ustring(),
968 _("PLACEHOLDER, do not translate")));
970 _act_grp->add(Gtk::Action::create("NodeLine",
971 Stock::NODE_LINE, Glib::ustring(),
972 _("PLACEHOLDER, do not translate")));
974 _act_grp->add(Gtk::Action::create("NodeCurve",
975 Stock::NODE_CURVE, Glib::ustring(),
976 _("PLACEHOLDER, do not translate")));
977 }
979 void
980 EditWidget::initAccelMap()
981 {
982 gchar *filename = g_build_filename(INKSCAPE_UIDIR, "keybindings.rc", NULL);
983 Gtk::AccelMap::load(filename);
984 g_free(filename);
986 // One problem is that the keys 1-6 are zoom accelerators which get
987 // caught as accelerator _before_ any Entry input handler receives them,
988 // for example the zoom status. At the moment, the best way seems to
989 // disable them as accelerators when the Entry gets focus, and enable
990 // them when focus goes elsewhere. The code for this belongs here,
991 // and not in zoom-status.cpp .
993 _zoom_status.signal_focus_in_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusIn));
994 _zoom_status.signal_focus_out_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusOut));
995 }
997 bool
998 EditWidget::onEntryFocusIn (GdkEventFocus* ev)
999 {
1000 Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
1001 Gtk::AccelMap::change_entry ("<Actions>//Zoom100", 0, m, false);
1002 Gtk::AccelMap::change_entry ("<Actions>//Zoom50", 0, m, false);
1003 Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", 0, m, false);
1004 Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", 0, m, false);
1005 Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", 0, m, false);
1006 Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", 0, m, false);
1007 return false;
1008 }
1010 bool
1011 EditWidget::onEntryFocusOut (GdkEventFocus* ev)
1012 {
1013 Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0);
1014 Gtk::AccelMap::change_entry ("<Actions>//Zoom100", '1', m, false);
1015 Gtk::AccelMap::change_entry ("<Actions>//Zoom50", '2', m, false);
1016 Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", '3', m, false);
1017 Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", '4', m, false);
1018 Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", '5', m, false);
1019 Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", '6', m, false);
1020 return false;
1021 }
1023 void
1024 EditWidget::initMenuBar()
1025 {
1026 g_assert(_ui_mgr);
1027 Gtk::MenuBar *menu = static_cast<Gtk::MenuBar*>(_ui_mgr->get_widget("/MenuBar"));
1028 g_assert(menu != NULL);
1029 _main_window_table.attach(*Gtk::manage(menu), 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1030 }
1032 void
1033 EditWidget::initCommandsBar()
1034 {
1035 g_assert(_ui_mgr);
1036 Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/CommandsBar")),
1037 Gtk::TOOLBAR_ICONS);
1038 g_assert(bar != NULL);
1039 _toolbars_vbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
1040 }
1042 void
1043 EditWidget::initToolControlsBar()
1044 {
1045 // TODO: Do UIManager controlled widgets need to be deleted?
1046 _select_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/SelectControlsBar"));
1047 _node_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/NodeControlsBar"));
1049 _tool_ctrl = new Toolbox(_select_ctrl, Gtk::TOOLBAR_ICONS);
1051 _toolbars_vbox.pack_start(*Gtk::manage(_tool_ctrl), Gtk::PACK_SHRINK);
1052 }
1054 void
1055 EditWidget::initUriBar()
1056 {
1057 /// \todo Create an Inkscape::UI::Widget::UriBar class (?)
1059 _uri_ctrl = new Gtk::Toolbar();
1061 _uri_label.set_label(_("PLACEHOLDER, DO NOT TRANSLATE"));
1062 _uri_ctrl->add(_uri_label);
1063 _uri_ctrl->add(_uri_entry);
1065 _uri_entry.signal_activate()
1066 .connect_notify(sigc::mem_fun(*this, &EditWidget::onUriChanged));
1068 _toolbars_vbox.pack_start(*Gtk::manage(_uri_ctrl), Gtk::PACK_SHRINK);
1069 }
1071 void
1072 EditWidget::initToolsBar()
1073 {
1074 Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/ToolsBar")),
1075 Gtk::TOOLBAR_ICONS,
1076 Gtk::ORIENTATION_VERTICAL);
1077 g_assert(bar != NULL);
1078 _sub_window_hbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK);
1079 }
1081 void
1082 EditWidget::initTopRuler()
1083 {
1084 _viewport_table.attach(_top_ruler, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1086 _tooltips.set_tip (_top_ruler, _top_ruler.get_tip());
1087 }
1089 void
1090 EditWidget::initLeftRuler()
1091 {
1092 _viewport_table.attach(_left_ruler, 0, 1, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1094 _tooltips.set_tip (_left_ruler, _left_ruler.get_tip());
1095 }
1097 void
1098 EditWidget::initBottomScrollbar()
1099 {
1100 _viewport_table.attach(_bottom_scrollbar, 1, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK);
1101 _bottom_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1102 _bottom_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1103 }
1105 void
1106 EditWidget::initRightScrollbar()
1107 {
1108 _viewport_table.attach(_right_scrollbar, 2, 3, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND);
1110 _right_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged));
1111 _right_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0);
1112 }
1114 void
1115 EditWidget::initStickyZoom()
1116 {
1117 _viewport_table.attach(_sticky_zoom, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK);
1119 _sticky_zoom.set_active (prefs_get_int_attribute ("options.stickyzoom", "value", 0) != 0);
1120 _tooltips.set_tip (_sticky_zoom, _("Zoom drawing if window size changes"));
1122 /// \todo icon not implemented
1123 }
1125 void
1126 EditWidget::initStatusbar()
1127 {
1128 _statusbar.pack_start (_selected_style_status, false, false, 1);
1129 _statusbar.pack_start (*new Gtk::VSeparator(), false, false, 0);
1131 _tooltips.set_tip (_zoom_status, _("Zoom"));
1133 _layer_selector.reference();
1134 _statusbar.pack_start (_layer_selector, false, false, 1);
1136 _coord_status.property_n_rows() = 2;
1137 _coord_status.property_n_columns() = 5;
1138 _coord_status.property_row_spacing() = 0;
1139 _coord_status.property_column_spacing() = 2;
1140 _coord_eventbox.add (_coord_status);
1141 _tooltips.set_tip (_coord_eventbox, _("Cursor coordinates"));
1142 _coord_status.attach (*new Gtk::VSeparator(), 0,1, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1143 _coord_status.attach (*new Gtk::Label("X:", 0.0, 0.5), 1,2, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1144 _coord_status.attach (*new Gtk::Label("Y:", 0.0, 0.5), 1,2, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1145 _coord_status_x.set_text ("0.0");
1146 _coord_status_x.set_alignment (0.0, 0.5);
1147 _coord_status_y.set_text ("0.0");
1148 _coord_status_y.set_alignment (0.0, 0.5);
1149 _coord_status.attach (_coord_status_x, 2,3, 0,1, Gtk::FILL,Gtk::FILL, 0,0);
1150 _coord_status.attach (_coord_status_y, 2,3, 1,2, Gtk::FILL,Gtk::FILL, 0,0);
1151 _coord_status.attach (*new Gtk::Label("Z:", 0.0, 0.5), 3,4, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1152 _coord_status.attach (_zoom_status, 4,5, 0,2, Gtk::FILL,Gtk::FILL, 0,0);
1153 sp_set_font_size_smaller (static_cast<GtkWidget*>((void*)_coord_status.gobj()));
1154 _statusbar.pack_end (_coord_eventbox, false, false, 1);
1156 _select_status.property_xalign() = 0.0;
1157 _select_status.property_yalign() = 0.5;
1158 _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."));
1159 // include this again with Gtk+-2.6
1160 #if GTK_MAJOR_VERSION == 2 && GTK_MINOR_VERSION >= 6
1161 _select_status.property_ellipsize() = Pango::ELLIPSIZE_END;
1162 #endif
1163 _select_status.set_size_request (1, -1);
1164 _statusbar.pack_start (_select_status, true, true, 0);
1166 _main_window_table.attach(_statusbar, 0, 1, 3, 4, Gtk::FILL, Gtk::SHRINK);
1167 }
1169 //========================================
1170 //----------implements EditWidgetInterface
1172 void *
1173 EditWidget::getWindow()
1174 {
1175 return this;
1176 }
1178 void
1179 EditWidget::setTitle (gchar const* new_title)
1180 {
1181 set_title (new_title);
1182 }
1184 void
1185 EditWidget::layout()
1186 {
1187 show_all_children();
1188 }
1190 void
1191 EditWidget::present()
1192 {
1193 this->Gtk::Window::present();
1194 }
1196 void
1197 EditWidget::getGeometry (gint &x, gint &y, gint &w, gint &h)
1198 {
1199 get_position (x, y);
1200 get_size (w, h);
1201 }
1203 void
1204 EditWidget::setSize (gint w, gint h)
1205 {
1206 resize (w, h);
1207 }
1209 void
1210 EditWidget::setPosition (NR::Point p)
1211 {
1212 move (int(p[NR::X]), int(p[NR::Y]));
1213 }
1215 /// \param p is already gobj()!
1216 void
1217 EditWidget::setTransient (void* p, int i)
1218 {
1219 #ifndef WIN32
1220 gtk_window_set_transient_for (static_cast<GtkWindow*>(p), this->gobj());
1221 if (i==2)
1222 this->Gtk::Window::present();
1223 #endif
1224 }
1226 NR::Point
1227 EditWidget::getPointer()
1228 {
1229 int x, y;
1230 get_pointer (x, y);
1231 return NR::Point (x, y);
1232 }
1234 void
1235 EditWidget::setFullscreen()
1236 {
1237 fullscreen();
1238 }
1240 /**
1241 * Shuts down the desktop object for the view being closed. It checks
1242 * to see if the document has been edited, and if so prompts the user
1243 * to save, discard, or cancel. Returns TRUE if the shutdown operation
1244 * is cancelled or if the save is cancelled or fails, FALSE otherwise.
1245 */
1246 bool
1247 EditWidget::shutdown()
1248 {
1249 g_assert (_desktop != NULL);
1250 if (Inkscape::NSApplication::Editor::isDuplicatedView (_desktop))
1251 return false;
1253 SPDocument *doc = _desktop->doc();
1254 if (sp_document_repr_root(doc)->attribute("sodipodi:modified") != NULL)
1255 {
1256 gchar *markup;
1257 /// \todo FIXME !!! obviously this will have problems if the document
1258 /// name contains markup characters
1259 markup = g_strdup_printf(
1260 _("<span weight=\"bold\" size=\"larger\">Save changes to document \"%s\" before closing?</span>\n\n"
1261 "If you close without saving, your changes will be discarded."),
1262 SP_DOCUMENT_NAME(doc));
1264 Gtk::MessageDialog dlg (*this,
1265 markup,
1266 true,
1267 Gtk::MESSAGE_WARNING,
1268 Gtk::BUTTONS_NONE,
1269 true);
1270 g_free(markup);
1271 Gtk::Button close_button (_("Close _without saving"), true);
1272 dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1273 close_button.show();
1274 dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1275 dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1276 dlg.set_default_response (Gtk::RESPONSE_YES);
1278 int response = dlg.run();
1279 switch (response)
1280 {
1281 case Gtk::RESPONSE_YES:
1282 sp_document_ref(doc);
1283 if (sp_file_save_document(doc)) {
1284 sp_document_unref(doc);
1285 } else { // save dialog cancelled or save failed
1286 sp_document_unref(doc);
1287 return TRUE;
1288 }
1289 break;
1290 case Gtk::RESPONSE_NO:
1291 break;
1292 default: // cancel pressed, or dialog was closed
1293 return TRUE;
1294 break;
1295 }
1296 }
1298 /* Code to check data loss */
1299 bool allow_data_loss = FALSE;
1300 while (sp_document_repr_root(doc)->attribute("inkscape:dataloss") != NULL && allow_data_loss == FALSE)
1301 {
1302 gchar *markup;
1303 /// \todo FIXME !!! obviously this will have problems if the document
1304 /// name contains markup characters
1305 markup = g_strdup_printf(
1306 _("<span weight=\"bold\" size=\"larger\">The file \"%s\" was saved with a format (%s) that may cause data loss!</span>\n\n"
1307 "Do you want to save this file in another format?"),
1308 SP_DOCUMENT_NAME(doc),
1309 Inkscape::Extension::db.get(sp_document_repr_root(doc)->attribute("inkscape:output_extension"))->get_name());
1311 Gtk::MessageDialog dlg (*this,
1312 markup,
1313 true,
1314 Gtk::MESSAGE_WARNING,
1315 Gtk::BUTTONS_NONE,
1316 true);
1317 g_free(markup);
1318 Gtk::Button close_button (_("Close _without saving"), true);
1319 dlg.add_action_widget (close_button, Gtk::RESPONSE_NO);
1320 close_button.show();
1321 dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1322 dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES);
1323 dlg.set_default_response (Gtk::RESPONSE_YES);
1325 int response = dlg.run();
1327 switch (response)
1328 {
1329 case Gtk::RESPONSE_YES:
1330 sp_document_ref(doc);
1331 if (sp_file_save_document(doc)) {
1332 sp_document_unref(doc);
1333 } else { // save dialog cancelled or save failed
1334 sp_document_unref(doc);
1335 return TRUE;
1336 }
1337 break;
1338 case Gtk::RESPONSE_NO:
1339 allow_data_loss = TRUE;
1340 break;
1341 default: // cancel pressed, or dialog was closed
1342 return TRUE;
1343 break;
1344 }
1345 }
1347 return false;
1348 }
1351 void
1352 EditWidget::destroy()
1353 {
1354 delete this;
1355 }
1357 void
1358 EditWidget::requestCanvasUpdate()
1359 {
1360 _svg_canvas.widget().queue_draw();
1361 }
1363 void
1364 EditWidget::activateDesktop()
1365 {
1366 /// \todo active_desktop_indicator not implemented
1367 }
1369 void
1370 EditWidget::deactivateDesktop()
1371 {
1372 /// \todo active_desktop_indicator not implemented
1373 }
1375 void
1376 EditWidget::viewSetPosition (NR::Point p)
1377 {
1378 p -= _namedview->gridorigin;
1379 double lo, up, pos, max;
1380 _top_ruler.get_range (lo, up, pos, max);
1381 _top_ruler.set_range (lo, up, p[NR::X], max);
1382 _left_ruler.get_range (lo, up, pos, max);
1383 _left_ruler.set_range (lo, up, p[NR::Y], max);
1384 }
1386 void
1387 EditWidget::updateRulers()
1388 {
1389 NR::Point origin = _namedview->gridorigin;
1391 NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1392 double lo, up, pos, max;
1393 double const scale = _desktop->current_zoom();
1394 double s = viewbox.min()[NR::X] / scale - origin[NR::X];
1395 double e = viewbox.max()[NR::X] / scale - origin[NR::X];
1396 _top_ruler.get_range(lo, up, pos, max);
1397 _top_ruler.set_range(s, e, pos, e);
1398 s = viewbox.min()[NR::Y] / -scale - origin[NR::Y];
1399 e = viewbox.max()[NR::Y] / -scale - origin[NR::Y];
1400 _left_ruler.set_range(s, e, origin[NR::Y], e);
1401 /// \todo is that correct?
1402 }
1404 void
1405 EditWidget::updateScrollbars (double scale)
1406 {
1407 // do not call this function before canvas has its size allocated
1408 if (!is_realized() || _update_s_f) {
1409 return;
1410 }
1412 _update_s_f = true;
1414 /* The desktop region we always show unconditionally */
1415 SPDocument *doc = _desktop->doc();
1416 NR::Rect const r = sp_item_bbox_desktop(SP_ITEM(SP_DOCUMENT_ROOT(doc)));
1417 NR::Rect darea(NR::Point(MIN(r.min()[NR::X], -sp_document_width(doc)),
1418 MIN(r.min()[NR::Y], -sp_document_height(doc))),
1419 NR::Point(MAX(r.max()[NR::X], 2 * sp_document_width(doc)),
1420 MAX(r.max()[NR::Y], 2 * sp_document_height(doc))));
1422 /* Canvas region we always show unconditionally */
1423 NR::Rect carea(NR::Point(darea.min()[NR::X] * scale - 64,
1424 darea.max()[NR::Y] * -scale - 64),
1425 NR::Point(darea.max()[NR::X] * scale + 64,
1426 darea.min()[NR::Y] * -scale + 64));
1428 NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox();
1430 /* Viewbox is always included into scrollable region */
1431 carea = NR::Rect::union_bounds(carea, viewbox);
1433 Gtk::Adjustment *adj = _bottom_scrollbar.get_adjustment();
1434 adj->set_value(viewbox.min()[NR::X]);
1435 adj->set_lower(carea.min()[NR::X]);
1436 adj->set_upper(carea.max()[NR::X]);
1437 adj->set_page_increment(viewbox.dimensions()[NR::X]);
1438 adj->set_step_increment(0.1 * (viewbox.dimensions()[NR::X]));
1439 adj->set_page_size(viewbox.dimensions()[NR::X]);
1441 adj = _right_scrollbar.get_adjustment();
1442 adj->set_value(viewbox.min()[NR::Y]);
1443 adj->set_lower(carea.min()[NR::Y]);
1444 adj->set_upper(carea.max()[NR::Y]);
1445 adj->set_page_increment(viewbox.dimensions()[NR::Y]);
1446 adj->set_step_increment(0.1 * viewbox.dimensions()[NR::Y]);
1447 adj->set_page_size(viewbox.dimensions()[NR::Y]);
1449 _update_s_f = false;
1450 }
1452 void
1453 EditWidget::toggleRulers()
1454 {
1455 if (_top_ruler.is_visible())
1456 {
1457 _top_ruler.hide_all();
1458 _left_ruler.hide_all();
1459 prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 0);
1460 } else {
1461 _top_ruler.show_all();
1462 _left_ruler.show_all();
1463 prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 1);
1464 }
1465 }
1467 void
1468 EditWidget::toggleScrollbars()
1469 {
1470 if (_bottom_scrollbar.is_visible())
1471 {
1472 _bottom_scrollbar.hide_all();
1473 _right_scrollbar.hide_all();
1474 prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 0);
1475 } else {
1476 _bottom_scrollbar.show_all();
1477 _right_scrollbar.show_all();
1478 prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 1);
1479 }
1480 }
1482 void
1483 EditWidget::updateZoom()
1484 {
1485 _zoom_status.update();
1486 }
1488 void
1489 EditWidget::letZoomGrabFocus()
1490 {
1491 _zoom_status.grab_focus();
1492 }
1494 void
1495 EditWidget::setToolboxFocusTo (const gchar *)
1496 {
1497 /// \todo not implemented
1498 }
1500 void
1501 EditWidget::setToolboxAdjustmentValue (const gchar *, double)
1502 {
1503 /// \todo not implemented
1504 }
1506 bool
1507 EditWidget::isToolboxButtonActive (gchar const*)
1508 {
1509 /// \todo not implemented
1510 return true;
1511 }
1513 void
1514 EditWidget::setCoordinateStatus (NR::Point p)
1515 {
1516 gchar *cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::X]);
1517 _coord_status_x.property_label() = cstr;
1518 g_free (cstr);
1519 cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::Y]);
1520 _coord_status_y.property_label() = cstr;
1521 g_free (cstr);
1522 }
1524 void
1525 EditWidget::setMessage (Inkscape::MessageType type, gchar const* msg)
1526 {
1527 _select_status.set_markup (msg? msg : "");
1528 }
1530 bool
1531 EditWidget::warnDialog (gchar* msg)
1532 {
1533 Gtk::MessageDialog dlg (*this,
1534 msg,
1535 true,
1536 Gtk::MESSAGE_WARNING,
1537 Gtk::BUTTONS_YES_NO,
1538 true);
1539 int r = dlg.run();
1540 return r == Gtk::RESPONSE_YES;
1541 }
1544 void
1545 EditWidget::initEdit (SPDocument *doc)
1546 {
1547 _desktop = new SPDesktop();
1548 _desktop->registerEditWidget (this);
1550 _namedview = sp_document_namedview (doc, 0);
1551 _svg_canvas.init (_desktop);
1552 _desktop->init (_namedview, _svg_canvas.spobj());
1553 sp_namedview_window_from_document (_desktop);
1554 _dt2r = 1.0 / _namedview->doc_units->unittobase;
1556 /// \todo convert to sigc++ when SPObject hierarchy gets converted
1557 /* Listen on namedview modification */
1558 g_signal_connect (G_OBJECT (_desktop->namedview), "modified", G_CALLBACK (_namedview_modified), this);
1559 _layer_selector.setDesktop (_desktop);
1560 _selected_style_status.setDesktop (_desktop);
1562 Inkscape::NSApplication::Editor::addDesktop (_desktop);
1564 _zoom_status.init (_desktop);
1565 _top_ruler.init (_desktop, _svg_canvas.widget());
1566 _left_ruler.init (_desktop, _svg_canvas.widget());
1567 updateRulers();
1568 }
1570 void
1571 EditWidget::destroyEdit()
1572 {
1573 if (_desktop) {
1574 _layer_selector.unreference();
1575 Inkscape::NSApplication::Editor::removeDesktop (_desktop); // clears selection too
1576 sp_signal_disconnect_by_data (G_OBJECT (_desktop->namedview), this);
1577 _desktop->destroy();
1578 Inkscape::GC::release (_desktop);
1579 _desktop = 0;
1580 }
1581 }
1583 //----------end of EditWidgetInterface implementation
1585 //----------start of other callbacks
1587 bool
1588 EditWidget::on_key_press_event (GdkEventKey* event)
1589 {
1590 // this is the original code from helper/window.cpp
1592 unsigned int shortcut;
1593 shortcut = get_group0_keyval (event) |
1594 ( event->state & GDK_SHIFT_MASK ?
1595 SP_SHORTCUT_SHIFT_MASK : 0 ) |
1596 ( event->state & GDK_CONTROL_MASK ?
1597 SP_SHORTCUT_CONTROL_MASK : 0 ) |
1598 ( event->state & GDK_MOD1_MASK ?
1599 SP_SHORTCUT_ALT_MASK : 0 );
1600 return sp_shortcut_invoke (shortcut,
1601 Inkscape::NSApplication::Editor::getActiveDesktop());
1602 }
1604 bool
1605 EditWidget::on_delete_event (GdkEventAny*)
1606 {
1607 return shutdown();
1608 }
1610 bool
1611 EditWidget::on_focus_in_event (GdkEventFocus*)
1612 {
1613 Inkscape::NSApplication::Editor::activateDesktop (_desktop);
1614 _svg_canvas.widget().grab_focus();
1616 return false;
1617 }
1619 void
1620 EditWidget::onWindowSizeAllocate (Gtk::Allocation &newall)
1621 {
1622 if (!is_realized()) return;
1624 const Gtk::Allocation& all = get_allocation();
1625 if ((newall.get_x() == all.get_x()) &&
1626 (newall.get_y() == all.get_y()) &&
1627 (newall.get_width() == all.get_width()) &&
1628 (newall.get_height() == all.get_height())) {
1629 return;
1630 }
1632 NR::Rect const area = _desktop->get_display_area();
1633 double zoom = _desktop->current_zoom();
1635 if (_sticky_zoom.get_active()) {
1636 /* Calculate zoom per pixel */
1637 double const zpsp = zoom / hypot(area.dimensions()[NR::X], area.dimensions()[NR::Y]);
1638 /* Find new visible area */
1639 NR::Rect const newarea = _desktop->get_display_area();
1640 /* Calculate adjusted zoom */
1641 zoom = zpsp * hypot(newarea.dimensions()[NR::X], newarea.dimensions()[NR::Y]);
1642 }
1644 _desktop->zoom_absolute(area.midpoint()[NR::X], area.midpoint()[NR::Y], zoom);
1645 }
1647 void
1648 EditWidget::onWindowRealize()
1649 {
1650 NR::Rect d(NR::Point(0, 0),
1651 NR::Point(sp_document_width(_desktop->doc()), sp_document_height(_desktop->doc())));
1653 if (fabs(d.dimensions()[NR::X]) < 1.0 || fabs(d.dimensions()[NR::Y]) < 1.0) {
1654 return;
1655 }
1657 _desktop->set_display_area(d.min()[NR::X], d.min()[NR::Y], d.max()[NR::X], d.max()[NR::Y], 10);
1658 _namedview_modified(_desktop->namedview, SP_OBJECT_MODIFIED_FLAG, this);
1659 setTitle (SP_DOCUMENT_NAME(_desktop->doc()));
1660 }
1662 void
1663 EditWidget::onAdjValueChanged()
1664 {
1665 if (_update_a_f) return;
1666 _update_a_f = true;
1668 sp_canvas_scroll_to (_svg_canvas.spobj(),
1669 _bottom_scrollbar.get_value(),
1670 _right_scrollbar.get_value(),
1671 false);
1672 updateRulers();
1674 _update_a_f = false;
1675 }
1677 /// \todo make this a member function when the signal is a sigc++ signal
1678 void _namedview_modified (SPNamedView* nv, guint flags, EditWidget* ew)
1679 {
1680 if (flags & SP_OBJECT_MODIFIED_FLAG)
1681 {
1682 ew->_dt2r = 1.0 / nv->doc_units->unittobase;
1683 ew->_top_ruler.update_metric();
1684 ew->_left_ruler.update_metric();
1685 ew->_tooltips.set_tip (ew->_top_ruler, ew->_top_ruler.get_tip());
1686 ew->_tooltips.set_tip (ew->_left_ruler, ew->_left_ruler.get_tip());
1687 ew->updateRulers();
1688 }
1689 }
1691 } // namespace View
1692 } // namespace UI
1693 } // namespace Inkscape
1695 /*
1696 Local Variables:
1697 mode:c++
1698 c-file-style:"stroustrup"
1699 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1700 indent-tabs-mode:nil
1701 fill-column:99
1702 End:
1703 */
1704 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :