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