diff options
| author | MenTaLguY <mental@rydia.net> | 2006-01-16 02:36:01 +0000 |
|---|---|---|
| committer | mental <mental@users.sourceforge.net> | 2006-01-16 02:36:01 +0000 |
| commit | 179fa413b047bede6e32109e2ce82437c5fb8d34 (patch) | |
| tree | a5a6ac2c1708bd02288fbd8edb2ff500ff2e0916 /src/ui/view | |
| download | inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.tar.gz inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.zip | |
moving trunk for module inkscape
(bzr r1)
Diffstat (limited to 'src/ui/view')
| -rw-r--r-- | src/ui/view/.cvsignore | 3 | ||||
| -rw-r--r-- | src/ui/view/Makefile_insert | 27 | ||||
| -rw-r--r-- | src/ui/view/desktop-affine.cpp | 0 | ||||
| -rw-r--r-- | src/ui/view/desktop-affine.h | 0 | ||||
| -rw-r--r-- | src/ui/view/desktop-events.cpp | 0 | ||||
| -rw-r--r-- | src/ui/view/desktop-events.h | 0 | ||||
| -rw-r--r-- | src/ui/view/desktop-handles.cpp | 0 | ||||
| -rw-r--r-- | src/ui/view/desktop-handles.h | 0 | ||||
| -rw-r--r-- | src/ui/view/desktop-style.cpp | 0 | ||||
| -rw-r--r-- | src/ui/view/desktop-style.h | 0 | ||||
| -rw-r--r-- | src/ui/view/desktop.cpp | 0 | ||||
| -rw-r--r-- | src/ui/view/desktop.h | 0 | ||||
| -rw-r--r-- | src/ui/view/edit-widget-interface.h | 134 | ||||
| -rw-r--r-- | src/ui/view/edit-widget.cpp | 1701 | ||||
| -rw-r--r-- | src/ui/view/edit-widget.h | 211 | ||||
| -rw-r--r-- | src/ui/view/edit.cpp | 28 | ||||
| -rw-r--r-- | src/ui/view/edit.h | 27 | ||||
| -rw-r--r-- | src/ui/view/makefile.in | 17 | ||||
| -rw-r--r-- | src/ui/view/view-widget.cpp | 135 | ||||
| -rw-r--r-- | src/ui/view/view-widget.h | 97 | ||||
| -rw-r--r-- | src/ui/view/view.cpp | 163 | ||||
| -rw-r--r-- | src/ui/view/view.h | 148 |
22 files changed, 2691 insertions, 0 deletions
diff --git a/src/ui/view/.cvsignore b/src/ui/view/.cvsignore new file mode 100644 index 000000000..38efca7bc --- /dev/null +++ b/src/ui/view/.cvsignore @@ -0,0 +1,3 @@ +.deps +.dirstamp +makefile diff --git a/src/ui/view/Makefile_insert b/src/ui/view/Makefile_insert new file mode 100644 index 000000000..1b8c57630 --- /dev/null +++ b/src/ui/view/Makefile_insert @@ -0,0 +1,27 @@ +## Makefile.am fragment sourced by src/Makefile.am. + +ui/view/all: ui/view/libuiview.a + +ui/view/clean: + rm -f ui/view/libuiview.a $(ui_libuiview_a_OBJECTS) + +ui_view_libuiview_a_SOURCES = \ + ui/view/edit.h \ + ui/view/edit.cpp \ + ui/view/edit-widget.h \ + ui/view/edit-widget.cpp \ + ui/view/edit-widget-interface.h \ + ui/view/view.h \ + ui/view/view.cpp \ + ui/view/view-widget.cpp \ + ui/view/view-widget.h \ + ui/view/desktop.h \ + ui/view/desktop.cpp \ + ui/view/desktop-affine.h \ + ui/view/desktop-affine.cpp \ + ui/view/desktop-events.h \ + ui/view/desktop-events.cpp \ + ui/view/desktop-handles.h \ + ui/view/desktop-handles.cpp \ + ui/view/desktop-style.h \ + ui/view/desktop-style.cpp diff --git a/src/ui/view/desktop-affine.cpp b/src/ui/view/desktop-affine.cpp new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/ui/view/desktop-affine.cpp diff --git a/src/ui/view/desktop-affine.h b/src/ui/view/desktop-affine.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/ui/view/desktop-affine.h diff --git a/src/ui/view/desktop-events.cpp b/src/ui/view/desktop-events.cpp new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/ui/view/desktop-events.cpp diff --git a/src/ui/view/desktop-events.h b/src/ui/view/desktop-events.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/ui/view/desktop-events.h diff --git a/src/ui/view/desktop-handles.cpp b/src/ui/view/desktop-handles.cpp new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/ui/view/desktop-handles.cpp diff --git a/src/ui/view/desktop-handles.h b/src/ui/view/desktop-handles.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/ui/view/desktop-handles.h diff --git a/src/ui/view/desktop-style.cpp b/src/ui/view/desktop-style.cpp new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/ui/view/desktop-style.cpp diff --git a/src/ui/view/desktop-style.h b/src/ui/view/desktop-style.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/ui/view/desktop-style.h diff --git a/src/ui/view/desktop.cpp b/src/ui/view/desktop.cpp new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/ui/view/desktop.cpp diff --git a/src/ui/view/desktop.h b/src/ui/view/desktop.h new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/src/ui/view/desktop.h diff --git a/src/ui/view/edit-widget-interface.h b/src/ui/view/edit-widget-interface.h new file mode 100644 index 000000000..689eff4a7 --- /dev/null +++ b/src/ui/view/edit-widget-interface.h @@ -0,0 +1,134 @@ +/** + * \file + * + * Abstract base class for all EditWidget implementations. + * + * Authors: + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2005 Ralf Stephan + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_VIEW_EDIT_WIDGET_IFACE_H +#define INKSCAPE_UI_VIEW_EDIT_WIDGET_IFACE_H + +#include "gdk/gdktypes.h" +#include "libnr/nr-point.h" +#include "message.h" + +namespace Inkscape { +namespace UI { +namespace View { + +struct EditWidgetInterface +{ + EditWidgetInterface() {} + virtual ~EditWidgetInterface() {} + + /// Returns pointer to window UI object as void* + virtual void *getWindow() = 0; + + /// Set the widget's title + virtual void setTitle (gchar const*) = 0; + + /// Show all parts of widget the user wants to see. + virtual void layout() = 0; + + /// Present widget to user + virtual void present() = 0; + + /// Returns geometry of widget + virtual void getGeometry (gint &x, gint &y, gint &w, gint &h) = 0; + + /// Change the widget's size + virtual void setSize (gint w, gint h) = 0; + + /// Move widget to specified position + virtual void setPosition (NR::Point p) = 0; + + /// Transientize widget + virtual void setTransient (void*, int) = 0; + + /// Return mouse position in widget + virtual NR::Point getPointer() = 0; + + /// Make widget fill screen and show it if possible. + virtual void setFullscreen() = 0; + + /// Shuts down the desktop object for the view being closed. It checks + /// to see if the document has been edited, and if so prompts the user + /// to save, discard, or cancel. Returns TRUE if the shutdown operation + /// is cancelled or if the save is cancelled or fails, FALSE otherwise. + virtual bool shutdown() = 0; + + /// Destroy and delete widget. + virtual void destroy() = 0; + + + /// Queue a redraw request with the canvas + virtual void requestCanvasUpdate() = 0; + + /// Update the "active desktop" indicator + virtual void activateDesktop() = 0; + + /// Update the "inactive desktop" indicator + virtual void deactivateDesktop() = 0; + + /// Set rulers to position + virtual void viewSetPosition (NR::Point p) = 0; + + /// Update rulers from current values + virtual void updateRulers() = 0; + + /// Update scrollbars from current values + virtual void updateScrollbars (double scale) = 0; + + /// Toggle rulers on/off and set preference value accordingly + virtual void toggleRulers() = 0; + + /// Toggle scrollbars on/off and set preference value accordingly + virtual void toggleScrollbars() = 0; + + /// Temporarily block signals and update zoom display + virtual void updateZoom() = 0; + + /// The zoom display will get the keyboard focus. + virtual void letZoomGrabFocus() = 0; + + /// In auxiliary toolbox, set focus to widget having specific id + virtual void setToolboxFocusTo (const gchar *) = 0; + + /// In auxiliary toolbox, set value of adjustment with specific id + virtual void setToolboxAdjustmentValue (const gchar *, double) = 0; + + /// In auxiliary toolbox, return true if specific togglebutton is active + virtual bool isToolboxButtonActive (gchar const*) = 0; + + /// Set the coordinate display + virtual void setCoordinateStatus (NR::Point p) = 0; + + /// Message widget will get no content + virtual void setMessage (Inkscape::MessageType type, gchar const* msg) = 0; + + /// Open yes/no dialog with warning text and confirmation question. + virtual bool warnDialog (gchar*) = 0; +}; + +} // namespace View +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_VIEW_EDIT_WIDGET_IFACE_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/view/edit-widget.cpp b/src/ui/view/edit-widget.cpp new file mode 100644 index 000000000..5139f8ebf --- /dev/null +++ b/src/ui/view/edit-widget.cpp @@ -0,0 +1,1701 @@ +/** + * \brief This class implements the functionality of the window layout, menus, + * and signals. + * + * This is a reimplementation into C++/Gtkmm of Sodipodi's SPDesktopWidget class. + * Both SPDesktopWidget and EditWidget adhere to the EditWidgetInterface, so + * they both can serve as widget for the same SPDesktop/Edit class. + * + * Ideally, this class should only contain the handling of the Window (i.e., + * content construction and window signals) and implement its + * EditWidgetInterface. + * + * Authors: + * Ralf Stephan <ralf@ark.in-berlin.de> + * Bryce W. Harrington <bryce@bryceharrington.org> + * Derek P. Moore <derekm@hackunix.org> + * Lauris Kaplinski <lauris@kaplinski.com> + * Frank Felfe <innerspace@iname.com> + * + * Copyright (C) 1999-2005 Authors + * Copyright (C) 2000-2001 Ximian, Inc. + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gtk/gtkwindow.h> +#include <gtkmm/radioaction.h> +#include <gtkmm/menubar.h> +#include <gtkmm/messagedialog.h> +#include <gtkmm/stock.h> +#include <gtkmm/accelmap.h> +#include <gtkmm/separator.h> + +#include "macros.h" +#include "path-prefix.h" +#include "prefs-utils.h" +#include "file.h" +#include "application/editor.h" +#include "edit-widget.h" +#include "ui/stock.h" +#include "ui/stock-items.h" +#include "ui/icons.h" + +#include "display/sodipodi-ctrlrect.h" +#include "helper/units.h" +#include "shortcuts.h" +#include "widgets/spw-utilities.h" +#include "event-context.h" +#include "document.h" +#include "sp-namedview.h" +#include "sp-item.h" +#include "interface.h" +#include "extension/db.h" + +#ifdef WITH_INKBOARD +#include "ui/dialog/whiteboard-connect.h" +#include "ui/dialog/whiteboard-sharewithuser.h" +#include "ui/dialog/whiteboard-sharewithchat.h" +#endif + +using namespace Inkscape::UI; +using namespace Inkscape::UI::Widget; + +namespace Inkscape { +namespace UI { +namespace View { + +EditWidget::EditWidget (SPDocument *doc) + : _main_window_table(4), + _viewport_table(3,3), + _act_grp(Gtk::ActionGroup::create()), + _ui_mgr(Gtk::UIManager::create()), + _update_s_f(false), + _update_a_f(false) +{ + g_warning("Creating new EditWidget"); + + _desktop = 0; + Icons::init(); + Stock::init(); + initActions(); + initAccelMap(); + initUIManager(); + initLayout(); + initEdit (doc); + g_warning("Done creating new EditWidget"); +} + +EditWidget::~EditWidget() +{ + destroyEdit(); +} + +void +EditWidget::initActions() +{ + initMenuActions(); + initToolbarActions(); +} + +void +EditWidget::initUIManager() +{ + _ui_mgr->insert_action_group(_act_grp); + add_accel_group(_ui_mgr->get_accel_group()); + + gchar *filename_utf8 = g_build_filename(INKSCAPE_UIDIR, "menus-bars.xml", NULL); + if (_ui_mgr->add_ui_from_file(filename_utf8) == 0) { + g_warning("Error merging ui from file '%s'", filename_utf8); + // fixme-charset: What charset should we pass to g_warning? + } + g_free(filename_utf8); +} + +void +EditWidget::initLayout() +{ + set_title("New document 1 - Inkscape"); + set_resizable(); + set_default_size(640, 480); + + // top level window into which all other portions of the UI get inserted + add(_main_window_table); + // attach box for horizontal toolbars + _main_window_table.attach(_toolbars_vbox, 0, 1, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK); + // attach sub-window for viewport and vertical toolbars + _main_window_table.attach(_sub_window_hbox, 0, 1, 2, 3); + // viewport table with 3 rows by 3 columns + _sub_window_hbox.pack_end(_viewport_table); + + // Menus and Bars + initMenuBar(); + initCommandsBar(); + initToolControlsBar(); + initUriBar(); + initToolsBar(); + + // Canvas Viewport + initLeftRuler(); + initTopRuler(); + initStickyZoom(); + initBottomScrollbar(); + initRightScrollbar(); + _viewport_table.attach(_svg_canvas.widget(), 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND); + _svg_canvas.widget().show_all(); + + + // The statusbar comes last and appears at the bottom of _main_window_table + initStatusbar(); + + signal_size_allocate().connect (sigc::mem_fun (*this, &EditWidget::onWindowSizeAllocate), false); + signal_realize().connect (sigc::mem_fun (*this, &EditWidget::onWindowRealize)); + show_all_children(); +} + +void +EditWidget::onMenuItem() +{ + g_warning("onMenuItem called"); +} + +void +EditWidget::onActionFileNew() +{ +// g_warning("onActionFileNew called"); + sp_file_new_default(); +} + +void +EditWidget::onActionFileOpen() +{ +// g_warning("onActionFileOpen called"); + sp_file_open_dialog (NULL, NULL); +} + +void +EditWidget::onActionFileQuit() +{ + g_warning("onActionFileQuit"); + sp_ui_close_all(); +} + +void +EditWidget::onActionFilePrint() +{ + g_warning("onActionFilePrint"); +} + +void +EditWidget::onToolbarItem() +{ + g_warning("onToolbarItem called"); +} + +void +EditWidget::onSelectTool() +{ + _tool_ctrl->remove(); + _tool_ctrl->add(*_select_ctrl); +} + +void +EditWidget::onNodeTool() +{ + _tool_ctrl->remove(); + _tool_ctrl->add(*_node_ctrl); +} + +void +EditWidget::onDialogInkscapePreferences() +{ + _dlg_mgr.showDialog("InkscapePreferences"); +} + +void +EditWidget::onDialogAbout() +{ +} + +void +EditWidget::onDialogAlignAndDistribute() +{ + _dlg_mgr.showDialog("AlignAndDistribute"); +} + +void +EditWidget::onDialogDocumentProperties() +{ +// manage (Inkscape::UI::Dialog::DocumentPreferences::create()); + _dlg_mgr.showDialog("DocumentPreferences"); +} + +void +EditWidget::onDialogExport() +{ + _dlg_mgr.showDialog("Export"); +} + +void +EditWidget::onDialogExtensionEditor() +{ + _dlg_mgr.showDialog("ExtensionEditor"); +} + +void +EditWidget::onDialogFillAndStroke() +{ + _dlg_mgr.showDialog("FillAndStroke"); +} + +void +EditWidget::onDialogFind() +{ + _dlg_mgr.showDialog("Find"); +} + +void +EditWidget::onDialogLayerEditor() +{ + _dlg_mgr.showDialog("LayerEditor"); +} + +void +EditWidget::onDialogMessages() +{ + _dlg_mgr.showDialog("Messages"); +} + +void +EditWidget::onDialogObjectProperties() +{ + _dlg_mgr.showDialog("ObjectProperties"); +} + +void +EditWidget::onDialogTextProperties() +{ + _dlg_mgr.showDialog("TextProperties"); +} + +void +EditWidget::onDialogTrace() +{ +} + +void +EditWidget::onDialogTransformation() +{ + _dlg_mgr.showDialog("Transformation"); +} + +void +EditWidget::onDialogXmlEditor() +{ + _dlg_mgr.showDialog("XmlEditor"); +} + +#ifdef WITH_INKBOARD +void +EditWidget::onDialogWhiteboardConnect() +{ + Dialog::WhiteboardConnectDialogImpl* dlg = dynamic_cast< Dialog::WhiteboardConnectDialogImpl* >(_dlg_mgr.getDialog("WhiteboardConnect")); + dlg->setSessionManager(); + _dlg_mgr.showDialog("WhiteboardConnect"); +} + +void +EditWidget::onDialogWhiteboardShareWithUser() +{ + Dialog::WhiteboardShareWithUserDialogImpl* dlg = dynamic_cast< Dialog::WhiteboardShareWithUserDialogImpl* >(_dlg_mgr.getDialog("WhiteboardShareWithUser")); + dlg->setSessionManager(); + _dlg_mgr.showDialog("WhiteboardShareWithUser"); +} + +void +EditWidget::onDialogWhiteboardShareWithChat() +{ + Dialog::WhiteboardShareWithChatroomDialogImpl* dlg = dynamic_cast< Dialog::WhiteboardShareWithChatroomDialogImpl* >(_dlg_mgr.getDialog("WhiteboardShareWithChat")); + dlg->setSessionManager(); + _dlg_mgr.showDialog("WhiteboardShareWithChat"); +} + +void +EditWidget::onDialogOpenSessionFile() +{ + g_log(NULL, G_LOG_LEVEL_DEBUG, "not reimplemented yet"); +} + +void +EditWidget::onDumpXMLTracker() +{ + g_log(NULL, G_LOG_LEVEL_DEBUG, "not reimplemented yet"); +} + +#endif + +void +EditWidget::onUriChanged() +{ + g_message("onUriChanged called"); + +} + +// FIXME: strings are replaced by placeholders, NOT to be translated until the code is enabled +// See http://sourceforge.net/mailarchive/message.php?msg_id=11746016 for details + +void +EditWidget::initMenuActions() +{ +// _act_grp->add(Gtk::Action::create("MenuFile", _("PLACEHOLDER, do not translate"))); +// _act_grp->add(Gtk::Action::create("MenuEdit", _("PLACEHOLDER, do not translate"))); +// _act_grp->add(Gtk::Action::create("MenuView", _("PLACEHOLDER, do not translate"))); +// _act_grp->add(Gtk::Action::create("MenuLayer", _("PLACEHOLDER, do not translate"))); +// _act_grp->add(Gtk::Action::create("MenuObject", _("PLACEHOLDER, do not translate"))); +// _act_grp->add(Gtk::Action::create("MenuPath", _("PLACEHOLDER, do not translate"))); +// _act_grp->add(Gtk::Action::create("MenuText", _("PLACEHOLDER, do not translate"))); +#ifdef WITH_INKBOARD +// _act_grp->add(Gtk::Action::create("MenuWhiteboard", _("PLACEHOLDER, do not translate"))); +#endif +// _act_grp->add(Gtk::Action::create("MenuHelp", _("PLACEHOLDER, do not translate"))); +// temporarily replaced with non-gettext version to have a well-sized menu +// for testing: + + _act_grp->add(Gtk::Action::create("MenuFile", "File")); + _act_grp->add(Gtk::Action::create("MenuEdit", "Edit")); + _act_grp->add(Gtk::Action::create("MenuView", "View")); + _act_grp->add(Gtk::Action::create("MenuLayer", "Layer")); + _act_grp->add(Gtk::Action::create("MenuObject", "Object")); + _act_grp->add(Gtk::Action::create("MenuPath", "Path")); + _act_grp->add(Gtk::Action::create("MenuText", "Text")); +#ifdef WITH_INKBOARD + _act_grp->add(Gtk::Action::create("MenuWhiteboard", "Whiteboard")); +#endif + _act_grp->add(Gtk::Action::create("MenuHelp", "Help")); + + // File menu + _act_grp->add(Gtk::Action::create("New", + Gtk::Stock::NEW, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onActionFileNew)); + + _act_grp->add(Gtk::Action::create("Open", + Gtk::Stock::OPEN, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onActionFileOpen)); + + _act_grp->add(Gtk::Action::create("OpenRecent", + Stock::OPEN_RECENT)); + + _act_grp->add(Gtk::Action::create("Revert", + Gtk::Stock::REVERT_TO_SAVED, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onActionFileOpen)); + + _act_grp->add(Gtk::Action::create("Save", + Gtk::Stock::SAVE, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onActionFileOpen)); + + _act_grp->add(Gtk::Action::create("SaveAs", + Gtk::Stock::SAVE_AS, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onActionFileOpen)); + + _act_grp->add(Gtk::Action::create("Import", + Stock::IMPORT, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onActionFileOpen)); + + _act_grp->add(Gtk::Action::create("Export", + Stock::EXPORT, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onDialogExport)); + + _act_grp->add(Gtk::Action::create("Print", + Gtk::Stock::PRINT, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onActionFilePrint)); + + _act_grp->add(Gtk::Action::create("PrintPreview", + Gtk::Stock::PRINT_PREVIEW), + sigc::mem_fun(*this, &EditWidget::onActionFileOpen)); + + _act_grp->add(Gtk::Action::create("VacuumDefs", + Stock::VACUUM_DEFS), + sigc::mem_fun(*this, &EditWidget::onActionFileOpen)); + + _act_grp->add(Gtk::Action::create("DocumentProperties", + Gtk::Stock::PROPERTIES, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onDialogDocumentProperties)); + + _act_grp->add(Gtk::Action::create("InkscapePreferences", + Gtk::Stock::PREFERENCES, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onDialogInkscapePreferences)); + + _act_grp->add(Gtk::Action::create("Close", + Gtk::Stock::CLOSE), + sigc::mem_fun(*this, &EditWidget::onActionFileOpen)); + + _act_grp->add(Gtk::Action::create("Quit", + Gtk::Stock::QUIT), + sigc::mem_fun(*this, &EditWidget::onActionFileQuit)); + + // EditWidget menu + _act_grp->add(Gtk::Action::create("Undo", + Gtk::Stock::UNDO, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("Redo", + Gtk::Stock::REDO, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("Cut", + Gtk::Stock::CUT, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("Copy", + Gtk::Stock::COPY, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("Paste", + Gtk::Stock::PASTE, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("PasteInPlace", + Stock::PASTE_IN_PLACE)); + + _act_grp->add(Gtk::Action::create("PasteStyle", + Stock::PASTE_STYLE)); + + _act_grp->add(Gtk::Action::create("Find", + Gtk::Stock::FIND), + sigc::mem_fun(*this, &EditWidget::onDialogFind)); + + _act_grp->add(Gtk::Action::create("Duplicate", + Stock::DUPLICATE, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("Clone", + Stock::CLONE, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("CloneUnlink", + Stock::CLONE_UNLINK, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("CloneSelectOrig", + Stock::CLONE_SELECT_ORIG)); + + _act_grp->add(Gtk::Action::create("MakeBitmap", + Stock::MAKE_BITMAP)); + + _act_grp->add(Gtk::Action::create("Tile", + Stock::TILE)); + + _act_grp->add(Gtk::Action::create("Untile", + Stock::UNTILE)); + + _act_grp->add(Gtk::Action::create("Delete", + Gtk::Stock::DELETE)); + + _act_grp->add(Gtk::Action::create("SelectAll", + Stock::SELECT_ALL)); + + _act_grp->add(Gtk::Action::create("SelectAllInAllLayers", + Stock::SELECT_ALL_IN_ALL_LAYERS)); + + _act_grp->add(Gtk::Action::create("SelectInvert", + Stock::SELECT_INVERT)); + + _act_grp->add(Gtk::Action::create("SelectNone", + Stock::SELECT_NONE)); + + _act_grp->add(Gtk::Action::create("XmlEditor", + Stock::XML_EDITOR, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onDialogXmlEditor)); + + // View menu + _act_grp->add(Gtk::Action::create("Zoom", + Stock::ZOOM)); + + _act_grp->add(Gtk::Action::create("ZoomIn", + Stock::ZOOM_IN, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("ZoomOut", + Stock::ZOOM_OUT, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("Zoom100", + Stock::ZOOM_100, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("Zoom50", + Stock::ZOOM_50, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("Zoom200", + Stock::ZOOM_200, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("ZoomSelection", + Stock::ZOOM_SELECTION, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("ZoomDrawing", + Stock::ZOOM_DRAWING, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("ZoomPage", + Stock::ZOOM_PAGE, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("ZoomWidth", + Stock::ZOOM_WIDTH, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("ZoomPrev", + Stock::ZOOM_PREV, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("ZoomNext", + Stock::ZOOM_NEXT, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("ShowHide", + Stock::SHOW_HIDE)); + + _act_grp->add(Gtk::ToggleAction::create("ShowHideCommandsBar", + Stock::SHOW_HIDE_COMMANDS_BAR)); + + _act_grp->add(Gtk::ToggleAction::create("ShowHideToolControlsBar", + Stock::SHOW_HIDE_TOOL_CONTROLS_BAR)); + + _act_grp->add(Gtk::ToggleAction::create("ShowHideToolsBar", + Stock::SHOW_HIDE_TOOLS_BAR)); + + _act_grp->add(Gtk::ToggleAction::create("ShowHideRulers", + Stock::SHOW_HIDE_RULERS)); + + _act_grp->add(Gtk::ToggleAction::create("ShowHideScrollbars", + Stock::SHOW_HIDE_SCROLLBARS)); + + _act_grp->add(Gtk::ToggleAction::create("ShowHideStatusbar", + Stock::SHOW_HIDE_STATUSBAR)); + + _act_grp->add(Gtk::Action::create("ShowHideDialogs", + Stock::SHOW_HIDE_DIALOGS)); + + _act_grp->add(Gtk::Action::create("Grid", + Stock::GRID)); + + _act_grp->add(Gtk::Action::create("Guides", + Stock::GUIDES)); + + _act_grp->add(Gtk::Action::create("Fullscreen", + Stock::FULLSCREEN)); + + _act_grp->add(Gtk::Action::create("Messages", + Stock::MESSAGES), + sigc::mem_fun(*this, &EditWidget::onDialogMessages)); + + _act_grp->add(Gtk::Action::create("Scripts", + Stock::SCRIPTS)); + + _act_grp->add(Gtk::Action::create("WindowPrev", + Stock::WINDOW_PREV)); + + _act_grp->add(Gtk::Action::create("WindowNext", + Stock::WINDOW_NEXT)); + + _act_grp->add(Gtk::Action::create("WindowDuplicate", + Stock::WINDOW_DUPLICATE)); + + // Layer menu + _act_grp->add(Gtk::Action::create("LayerNew", + Stock::LAYER_NEW)); + + _act_grp->add(Gtk::Action::create("LayerRename", + Stock::LAYER_RENAME)); + + _act_grp->add(Gtk::Action::create("LayerDuplicate", + Stock::LAYER_DUPLICATE)); + + _act_grp->add(Gtk::Action::create("LayerAnchor", + Stock::LAYER_ANCHOR)); + + _act_grp->add(Gtk::Action::create("LayerMergeDown", + Stock::LAYER_MERGE_DOWN)); + + _act_grp->add(Gtk::Action::create("LayerDelete", + Stock::LAYER_DELETE)); + + _act_grp->add(Gtk::Action::create("LayerSelectNext", + Stock::LAYER_SELECT_NEXT)); + + _act_grp->add(Gtk::Action::create("LayerSelectPrev", + Stock::LAYER_SELECT_PREV)); + + _act_grp->add(Gtk::Action::create("LayerSelectTop", + Stock::LAYER_SELECT_TOP)); + + _act_grp->add(Gtk::Action::create("LayerSelectBottom", + Stock::LAYER_SELECT_BOTTOM)); + + _act_grp->add(Gtk::Action::create("LayerRaise", + Stock::LAYER_RAISE)); + + _act_grp->add(Gtk::Action::create("LayerLower", + Stock::LAYER_LOWER)); + + _act_grp->add(Gtk::Action::create("LayerToTop", + Stock::LAYER_TO_TOP)); + + _act_grp->add(Gtk::Action::create("LayerToBottom", + Stock::LAYER_TO_BOTTOM)); + + // Object menu + _act_grp->add(Gtk::Action::create("FillAndStroke", + Stock::FILL_STROKE, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onDialogFillAndStroke)); + + _act_grp->add(Gtk::Action::create("ObjectProperties", + Stock::OBJECT_PROPERTIES), + sigc::mem_fun(*this, &EditWidget::onDialogObjectProperties)); + + _act_grp->add(Gtk::Action::create("Group", + Stock::GROUP, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("Ungroup", + Stock::UNGROUP, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("Raise", + Stock::RAISE, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("Lower", + Stock::LOWER, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("RaiseToTop", + Stock::RAISE_TO_TOP, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("LowerToBottom", + Stock::LOWER_TO_BOTTOM, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("MoveToNewLayer", + Stock::MOVE_TO_NEW_LAYER, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("MoveToNextLayer", + Stock::MOVE_TO_NEXT_LAYER, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("MoveToPrevLayer", + Stock::MOVE_TO_PREV_LAYER, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("MoveToTopLayer", + Stock::MOVE_TO_TOP_LAYER, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("MoveToBottomLayer", + Stock::MOVE_TO_BOTTOM_LAYER, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("Rotate90CW", + Stock::ROTATE_90_CW, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("Rotate90CCW", + Stock::ROTATE_90_CCW, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("FlipHoriz", + Stock::FLIP_HORIZ, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("FlipVert", + Stock::FLIP_VERT, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("Transformation", + Stock::TRANSFORMATION, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onDialogTransformation)); + + _act_grp->add(Gtk::Action::create("AlignAndDistribute", + Stock::ALIGN_DISTRIBUTE, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onDialogAlignAndDistribute)); + + // Path menu + _act_grp->add(Gtk::Action::create("ObjectToPath", + Stock::OBJECT_TO_PATH, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("StrokeToPath", + Stock::STROKE_TO_PATH, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("Trace", + Stock::TRACE), + sigc::mem_fun(*this, &EditWidget::onDialogTrace)); + + _act_grp->add(Gtk::Action::create("Union", + Stock::UNION)); + + _act_grp->add(Gtk::Action::create("Difference", + Stock::DIFFERENCE)); + + _act_grp->add(Gtk::Action::create("Intersection", + Stock::INTERSECTION)); + + _act_grp->add(Gtk::Action::create("Exclusion", + Stock::EXCLUSION)); + + _act_grp->add(Gtk::Action::create("Division", + Stock::DIVISION)); + + _act_grp->add(Gtk::Action::create("CutPath", + Stock::CUT_PATH)); + + _act_grp->add(Gtk::Action::create("Combine", + Stock::COMBINE)); + + _act_grp->add(Gtk::Action::create("BreakApart", + Stock::BREAK_APART)); + + _act_grp->add(Gtk::Action::create("Inset", + Stock::INSET)); + + _act_grp->add(Gtk::Action::create("Outset", + Stock::OUTSET)); + + _act_grp->add(Gtk::Action::create("OffsetDynamic", + Stock::OFFSET_DYNAMIC)); + + _act_grp->add(Gtk::Action::create("OffsetLinked", + Stock::OFFSET_LINKED)); + + _act_grp->add(Gtk::Action::create("Simplify", + Stock::SIMPLIFY)); + + _act_grp->add(Gtk::Action::create("Reverse", + Stock::REVERSE)); + + _act_grp->add(Gtk::Action::create("Cleanup", + Gtk::Stock::CLEAR, + _("PLACEHOLDER, do not translate"))); + + // Text menu + _act_grp->add(Gtk::Action::create("TextProperties", + Gtk::Stock::SELECT_FONT, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onDialogTextProperties)); + + _act_grp->add(Gtk::Action::create("PutOnPath", + Stock::PUT_ON_PATH)); + + _act_grp->add(Gtk::Action::create("RemoveFromPath", + Stock::REMOVE_FROM_PATH)); + + _act_grp->add(Gtk::Action::create("RemoveManualKerns", + Stock::REMOVE_MANUAL_KERNS)); + + // Whiteboard menu +#ifdef WITH_INKBOARD + _act_grp->add(Gtk::Action::create("DialogWhiteboardConnect", + Gtk::Stock::CLEAR, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onDialogWhiteboardConnect)); + + _act_grp->add(Gtk::Action::create("DialogWhiteboardShareWithUser", + Gtk::Stock::CLEAR, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onDialogWhiteboardShareWithUser)); + + _act_grp->add(Gtk::Action::create("DialogWhiteboardShareWithChat", + Gtk::Stock::CLEAR, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onDialogWhiteboardShareWithChat)); + + _act_grp->add(Gtk::Action::create("WhiteboardOpenSessionFile", + Gtk::Stock::CLEAR, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onDialogOpenSessionFile)); + + _act_grp->add(Gtk::Action::create("WhiteboardDumpXMLTracker", + Gtk::Stock::CLEAR, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onDumpXMLTracker)); +#endif + + // About menu + _act_grp->add(Gtk::Action::create("KeysAndMouse", + Stock::KEYS_MOUSE)); + + _act_grp->add(Gtk::Action::create("Tutorials", + Stock::TUTORIALS)); + + _act_grp->add(Gtk::Action::create("About", + Stock::ABOUT), + sigc::mem_fun(*this, &EditWidget::onDialogAbout)); +} + +void +EditWidget::initToolbarActions() +{ + // Tools bar + Gtk::RadioAction::Group tools; + + _act_grp->add(Gtk::RadioAction::create(tools, "ToolSelect", + Stock::TOOL_SELECT, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onSelectTool)); + + _act_grp->add(Gtk::RadioAction::create(tools, "ToolNode", + Stock::TOOL_NODE, Glib::ustring(), + _("PLACEHOLDER, do not translate")), + sigc::mem_fun(*this, &EditWidget::onNodeTool)); + + _act_grp->add(Gtk::RadioAction::create(tools, "ToolZoom", + Stock::TOOL_ZOOM, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::RadioAction::create(tools, "ToolRect", + Stock::TOOL_RECT, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::RadioAction::create(tools, "ToolArc", + Stock::TOOL_ARC, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::RadioAction::create(tools, "ToolStar", + Stock::TOOL_STAR, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::RadioAction::create(tools, "ToolSpiral", + Stock::TOOL_SPIRAL, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::RadioAction::create(tools, "ToolFreehand", + Stock::TOOL_FREEHAND, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::RadioAction::create(tools, "ToolPen", + Stock::TOOL_PEN, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::RadioAction::create(tools, "ToolDynaDraw", + Stock::TOOL_DYNADRAW, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::RadioAction::create(tools, "ToolText", + Stock::TOOL_TEXT, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::RadioAction::create(tools, "ToolDropper", + Stock::TOOL_DROPPER, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + // Select Controls bar + _act_grp->add(Gtk::ToggleAction::create("TransformStroke", + Stock::TRANSFORM_STROKE, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::ToggleAction::create("TransformCorners", + Stock::TRANSFORM_CORNERS, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::ToggleAction::create("TransformGradient", + Stock::TRANSFORM_GRADIENT, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::ToggleAction::create("TransformPattern", + Stock::TRANSFORM_PATTERN, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + // Node Controls bar + _act_grp->add(Gtk::Action::create("NodeInsert", + Gtk::Stock::ADD, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("NodeDelete", + Gtk::Stock::REMOVE, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("NodeJoin", + Stock::NODE_JOIN, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("NodeJoinSegment", + Stock::NODE_JOIN_SEGMENT, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("NodeDeleteSegment", + Stock::NODE_DELETE_SEGMENT, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("NodeBreak", + Stock::NODE_BREAK, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("NodeCorner", + Stock::NODE_CORNER, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("NodeSmooth", + Stock::NODE_SMOOTH, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("NodeSymmetric", + Stock::NODE_SYMMETRIC, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("NodeLine", + Stock::NODE_LINE, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); + + _act_grp->add(Gtk::Action::create("NodeCurve", + Stock::NODE_CURVE, Glib::ustring(), + _("PLACEHOLDER, do not translate"))); +} + +void +EditWidget::initAccelMap() +{ + gchar *filename = g_build_filename(INKSCAPE_UIDIR, "keybindings.rc", NULL); + Gtk::AccelMap::load(filename); + g_free(filename); + + // One problem is that the keys 1-6 are zoom accelerators which get + // caught as accelerator _before_ any Entry input handler receives them, + // for example the zoom status. At the moment, the best way seems to + // disable them as accelerators when the Entry gets focus, and enable + // them when focus goes elsewhere. The code for this belongs here, + // and not in zoom-status.cpp . + + _zoom_status.signal_focus_in_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusIn)); + _zoom_status.signal_focus_out_event().connect (sigc::mem_fun (*this, &EditWidget::onEntryFocusOut)); +} + +bool +EditWidget::onEntryFocusIn (GdkEventFocus* ev) +{ + Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0); + Gtk::AccelMap::change_entry ("<Actions>//Zoom100", 0, m, false); + Gtk::AccelMap::change_entry ("<Actions>//Zoom50", 0, m, false); + Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", 0, m, false); + Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", 0, m, false); + Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", 0, m, false); + Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", 0, m, false); + return false; +} + +bool +EditWidget::onEntryFocusOut (GdkEventFocus* ev) +{ + Gdk::ModifierType m = static_cast<Gdk::ModifierType>(0); + Gtk::AccelMap::change_entry ("<Actions>//Zoom100", '1', m, false); + Gtk::AccelMap::change_entry ("<Actions>//Zoom50", '2', m, false); + Gtk::AccelMap::change_entry ("<Actions>//ZoomSelection", '3', m, false); + Gtk::AccelMap::change_entry ("<Actions>//ZoomDrawing", '4', m, false); + Gtk::AccelMap::change_entry ("<Actions>//ZoomPage", '5', m, false); + Gtk::AccelMap::change_entry ("<Actions>//ZoomWidth", '6', m, false); + return false; +} + +void +EditWidget::initMenuBar() +{ + g_assert(_ui_mgr); + Gtk::MenuBar *menu = static_cast<Gtk::MenuBar*>(_ui_mgr->get_widget("/MenuBar")); + g_assert(menu != NULL); + _main_window_table.attach(*Gtk::manage(menu), 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK); +} + +void +EditWidget::initCommandsBar() +{ + g_assert(_ui_mgr); + Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/CommandsBar")), + Gtk::TOOLBAR_ICONS); + g_assert(bar != NULL); + _toolbars_vbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK); +} + +void +EditWidget::initToolControlsBar() +{ + // TODO: Do UIManager controlled widgets need to be deleted? + _select_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/SelectControlsBar")); + _node_ctrl = static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/NodeControlsBar")); + + _tool_ctrl = new Toolbox(_select_ctrl, Gtk::TOOLBAR_ICONS); + + _toolbars_vbox.pack_start(*Gtk::manage(_tool_ctrl), Gtk::PACK_SHRINK); +} + +void +EditWidget::initUriBar() +{ + /// \todo Create an Inkscape::UI::Widget::UriBar class (?) + + _uri_ctrl = new Gtk::Toolbar(); + + _uri_label.set_label(_("PLACEHOLDER, DO NOT TRANSLATE")); + _uri_ctrl->add(_uri_label); + _uri_ctrl->add(_uri_entry); + + _uri_entry.signal_activate() + .connect_notify(sigc::mem_fun(*this, &EditWidget::onUriChanged)); + + _toolbars_vbox.pack_start(*Gtk::manage(_uri_ctrl), Gtk::PACK_SHRINK); +} + +void +EditWidget::initToolsBar() +{ + Toolbox *bar = new Toolbox(static_cast<Gtk::Toolbar*>(_ui_mgr->get_widget("/ToolsBar")), + Gtk::TOOLBAR_ICONS, + Gtk::ORIENTATION_VERTICAL); + g_assert(bar != NULL); + _sub_window_hbox.pack_start(*Gtk::manage(bar), Gtk::PACK_SHRINK); +} + +void +EditWidget::initTopRuler() +{ + _viewport_table.attach(_top_ruler, 1, 2, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK); + + _tooltips.set_tip (_top_ruler, _top_ruler.get_tip()); +} + +void +EditWidget::initLeftRuler() +{ + _viewport_table.attach(_left_ruler, 0, 1, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND); + + _tooltips.set_tip (_left_ruler, _left_ruler.get_tip()); +} + +void +EditWidget::initBottomScrollbar() +{ + _viewport_table.attach(_bottom_scrollbar, 1, 2, 2, 3, Gtk::FILL|Gtk::EXPAND, Gtk::SHRINK); + _bottom_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged)); + _bottom_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0); +} + +void +EditWidget::initRightScrollbar() +{ + _viewport_table.attach(_right_scrollbar, 2, 3, 1, 2, Gtk::SHRINK, Gtk::FILL|Gtk::EXPAND); + + _right_scrollbar.signal_value_changed().connect (sigc::mem_fun (*this, &EditWidget::onAdjValueChanged)); + _right_scrollbar.property_adjustment() = new Gtk::Adjustment (0.0, -4000.0, 4000.0, 10.0, 100.0, 4.0); +} + +void +EditWidget::initStickyZoom() +{ + _viewport_table.attach(_sticky_zoom, 2, 3, 0, 1, Gtk::SHRINK, Gtk::SHRINK); + + _sticky_zoom.set_active (prefs_get_int_attribute ("options.stickyzoom", "value", 0) != 0); + _tooltips.set_tip (_sticky_zoom, _("Zoom drawing if window size changes")); + + /// \todo icon not implemented +} + +void +EditWidget::initStatusbar() +{ + _statusbar.pack_start (_selected_style_status, false, false, 1); + _statusbar.pack_start (*new Gtk::VSeparator(), false, false, 0); + + _tooltips.set_tip (_zoom_status, _("Zoom")); + + _layer_selector.reference(); + _statusbar.pack_start (_layer_selector, false, false, 1); + + _coord_status.property_n_rows() = 2; + _coord_status.property_n_columns() = 5; + _coord_status.property_row_spacing() = 0; + _coord_status.property_column_spacing() = 2; + _coord_eventbox.add (_coord_status); + _tooltips.set_tip (_coord_eventbox, _("Cursor coordinates")); + _coord_status.attach (*new Gtk::VSeparator(), 0,1, 0,2, Gtk::FILL,Gtk::FILL, 0,0); + _coord_status.attach (*new Gtk::Label("X:", 0.0, 0.5), 1,2, 0,1, Gtk::FILL,Gtk::FILL, 0,0); + _coord_status.attach (*new Gtk::Label("Y:", 0.0, 0.5), 1,2, 1,2, Gtk::FILL,Gtk::FILL, 0,0); + _coord_status_x.set_text ("0.0"); + _coord_status_x.set_alignment (0.0, 0.5); + _coord_status_y.set_text ("0.0"); + _coord_status_y.set_alignment (0.0, 0.5); + _coord_status.attach (_coord_status_x, 2,3, 0,1, Gtk::FILL,Gtk::FILL, 0,0); + _coord_status.attach (_coord_status_y, 2,3, 1,2, Gtk::FILL,Gtk::FILL, 0,0); + _coord_status.attach (*new Gtk::Label("Z:", 0.0, 0.5), 3,4, 0,2, Gtk::FILL,Gtk::FILL, 0,0); + _coord_status.attach (_zoom_status, 4,5, 0,2, Gtk::FILL,Gtk::FILL, 0,0); + sp_set_font_size_smaller (static_cast<GtkWidget*>((void*)_coord_status.gobj())); + _statusbar.pack_end (_coord_eventbox, false, false, 1); + + _select_status.property_xalign() = 0.0; + _select_status.property_yalign() = 0.5; + _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.")); + // include this again with Gtk+-2.6 + //_select_status.property_ellipsize() = Pango::ELLIPSIZE_END; + _select_status.set_size_request (1, -1); + _statusbar.pack_start (_select_status, true, true, 0); + + _main_window_table.attach(_statusbar, 0, 1, 3, 4, Gtk::FILL, Gtk::SHRINK); +} + +//======================================== +//----------implements EditWidgetInterface + +void * +EditWidget::getWindow() +{ + return this; +} + +void +EditWidget::setTitle (gchar const* new_title) +{ + set_title (new_title); +} + +void +EditWidget::layout() +{ + show_all_children(); +} + +void +EditWidget::present() +{ + this->Gtk::Window::present(); +} + +void +EditWidget::getGeometry (gint &x, gint &y, gint &w, gint &h) +{ + get_position (x, y); + get_size (w, h); +} + +void +EditWidget::setSize (gint w, gint h) +{ + resize (w, h); +} + +void +EditWidget::setPosition (NR::Point p) +{ + move (int(p[NR::X]), int(p[NR::Y])); +} + +/// \param p is already gobj()! +void +EditWidget::setTransient (void* p, int i) +{ +#ifndef WIN32 + gtk_window_set_transient_for (static_cast<GtkWindow*>(p), this->gobj()); + if (i==2) + this->Gtk::Window::present(); +#endif +} + +NR::Point +EditWidget::getPointer() +{ + int x, y; + get_pointer (x, y); + return NR::Point (x, y); +} + +void +EditWidget::setFullscreen() +{ + fullscreen(); +} + +/** + * Shuts down the desktop object for the view being closed. It checks + * to see if the document has been edited, and if so prompts the user + * to save, discard, or cancel. Returns TRUE if the shutdown operation + * is cancelled or if the save is cancelled or fails, FALSE otherwise. + */ +bool +EditWidget::shutdown() +{ + g_assert (_desktop != NULL); + if (Inkscape::NSApplication::Editor::isDuplicatedView (_desktop)) + return false; + + SPDocument *doc = _desktop->doc(); + if (sp_document_repr_root(doc)->attribute("sodipodi:modified") != NULL) + { + gchar *markup; + /// \todo FIXME !!! obviously this will have problems if the document + /// name contains markup characters + markup = g_strdup_printf( + _("<span weight=\"bold\" size=\"larger\">Save changes to document \"%s\" before closing?</span>\n\n" + "If you close without saving, your changes will be discarded."), + SP_DOCUMENT_NAME(doc)); + + Gtk::MessageDialog dlg (*this, + markup, + true, + Gtk::MESSAGE_WARNING, + Gtk::BUTTONS_NONE, + true); + g_free(markup); + Gtk::Button close_button (_("Close _without saving"), true); + dlg.add_action_widget (close_button, Gtk::RESPONSE_NO); + close_button.show(); + dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); + dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES); + dlg.set_default_response (Gtk::RESPONSE_YES); + + int response = dlg.run(); + switch (response) + { + case Gtk::RESPONSE_YES: + sp_document_ref(doc); + if (sp_file_save_document(doc)) { + sp_document_unref(doc); + } else { // save dialog cancelled or save failed + sp_document_unref(doc); + return TRUE; + } + break; + case Gtk::RESPONSE_NO: + break; + default: // cancel pressed, or dialog was closed + return TRUE; + break; + } + } + + /* Code to check data loss */ + bool allow_data_loss = FALSE; + while (sp_document_repr_root(doc)->attribute("inkscape:dataloss") != NULL && allow_data_loss == FALSE) + { + gchar *markup; + /// \todo FIXME !!! obviously this will have problems if the document + /// name contains markup characters + markup = g_strdup_printf( + _("<span weight=\"bold\" size=\"larger\">The file \"%s\" was saved with a format (%s) that may cause data loss!</span>\n\n" + "Do you want to save this file in another format?"), + SP_DOCUMENT_NAME(doc), + Inkscape::Extension::db.get(sp_document_repr_root(doc)->attribute("inkscape:output_extension"))->get_name()); + + Gtk::MessageDialog dlg (*this, + markup, + true, + Gtk::MESSAGE_WARNING, + Gtk::BUTTONS_NONE, + true); + g_free(markup); + Gtk::Button close_button (_("Close _without saving"), true); + dlg.add_action_widget (close_button, Gtk::RESPONSE_NO); + close_button.show(); + dlg.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); + dlg.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_YES); + dlg.set_default_response (Gtk::RESPONSE_YES); + + int response = dlg.run(); + + switch (response) + { + case Gtk::RESPONSE_YES: + sp_document_ref(doc); + if (sp_file_save_document(doc)) { + sp_document_unref(doc); + } else { // save dialog cancelled or save failed + sp_document_unref(doc); + return TRUE; + } + break; + case Gtk::RESPONSE_NO: + allow_data_loss = TRUE; + break; + default: // cancel pressed, or dialog was closed + return TRUE; + break; + } + } + + return false; +} + + +void +EditWidget::destroy() +{ + delete this; +} + +void +EditWidget::requestCanvasUpdate() +{ + _svg_canvas.widget().queue_draw(); +} + +void +EditWidget::activateDesktop() +{ + /// \todo active_desktop_indicator not implemented +} + +void +EditWidget::deactivateDesktop() +{ + /// \todo active_desktop_indicator not implemented +} + +void +EditWidget::viewSetPosition (NR::Point p) +{ + p -= _namedview->gridorigin; + double lo, up, pos, max; + _top_ruler.get_range (lo, up, pos, max); + _top_ruler.set_range (lo, up, p[NR::X], max); + _left_ruler.get_range (lo, up, pos, max); + _left_ruler.set_range (lo, up, p[NR::Y], max); +} + +void +EditWidget::updateRulers() +{ + NR::Point origin = _namedview->gridorigin; + + NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox(); + double lo, up, pos, max; + double const scale = _desktop->current_zoom(); + double s = viewbox.min()[NR::X] / scale - origin[NR::X]; + double e = viewbox.max()[NR::X] / scale - origin[NR::X]; + _top_ruler.get_range(lo, up, pos, max); + _top_ruler.set_range(s, e, pos, e); + s = viewbox.min()[NR::Y] / -scale - origin[NR::Y]; + e = viewbox.max()[NR::Y] / -scale - origin[NR::Y]; + _left_ruler.set_range(s, e, origin[NR::Y], e); + /// \todo is that correct? +} + +void +EditWidget::updateScrollbars (double scale) +{ + // do not call this function before canvas has its size allocated + if (!is_realized() || _update_s_f) { + return; + } + + _update_s_f = true; + + /* The desktop region we always show unconditionally */ + SPDocument *doc = _desktop->doc(); + NR::Rect const r = sp_item_bbox_desktop(SP_ITEM(SP_DOCUMENT_ROOT(doc))); + NR::Rect darea(NR::Point(MIN(r.min()[NR::X], -sp_document_width(doc)), + MIN(r.min()[NR::Y], -sp_document_height(doc))), + NR::Point(MAX(r.max()[NR::X], 2 * sp_document_width(doc)), + MAX(r.max()[NR::Y], 2 * sp_document_height(doc)))); + + /* Canvas region we always show unconditionally */ + NR::Rect carea(NR::Point(darea.min()[NR::X] * scale - 64, + darea.max()[NR::Y] * -scale - 64), + NR::Point(darea.max()[NR::X] * scale + 64, + darea.min()[NR::Y] * -scale + 64)); + + NR::Rect const viewbox = _svg_canvas.spobj()->getViewbox(); + + /* Viewbox is always included into scrollable region */ + carea = NR::Rect::union_bounds(carea, viewbox); + + Gtk::Adjustment *adj = _bottom_scrollbar.get_adjustment(); + adj->set_value(viewbox.min()[NR::X]); + adj->set_lower(carea.min()[NR::X]); + adj->set_upper(carea.max()[NR::X]); + adj->set_page_increment(viewbox.dimensions()[NR::X]); + adj->set_step_increment(0.1 * (viewbox.dimensions()[NR::X])); + adj->set_page_size(viewbox.dimensions()[NR::X]); + + adj = _right_scrollbar.get_adjustment(); + adj->set_value(viewbox.min()[NR::Y]); + adj->set_lower(carea.min()[NR::Y]); + adj->set_upper(carea.max()[NR::Y]); + adj->set_page_increment(viewbox.dimensions()[NR::Y]); + adj->set_step_increment(0.1 * viewbox.dimensions()[NR::Y]); + adj->set_page_size(viewbox.dimensions()[NR::Y]); + + _update_s_f = false; +} + +void +EditWidget::toggleRulers() +{ + if (_top_ruler.is_visible()) + { + _top_ruler.hide_all(); + _left_ruler.hide_all(); + prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 0); + } else { + _top_ruler.show_all(); + _left_ruler.show_all(); + prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.rulers" : "window.rulers", "state", 1); + } +} + +void +EditWidget::toggleScrollbars() +{ + if (_bottom_scrollbar.is_visible()) + { + _bottom_scrollbar.hide_all(); + _right_scrollbar.hide_all(); + prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 0); + } else { + _bottom_scrollbar.show_all(); + _right_scrollbar.show_all(); + prefs_set_int_attribute (_desktop->is_fullscreen ? "fullscreen.scrollbars" : "window.scrollbars", "state", 1); + } +} + +void +EditWidget::updateZoom() +{ + _zoom_status.update(); +} + +void +EditWidget::letZoomGrabFocus() +{ + _zoom_status.grab_focus(); +} + +void +EditWidget::setToolboxFocusTo (const gchar *) +{ + /// \todo not implemented +} + +void +EditWidget::setToolboxAdjustmentValue (const gchar *, double) +{ + /// \todo not implemented +} + +bool +EditWidget::isToolboxButtonActive (gchar const*) +{ + /// \todo not implemented + return true; +} + +void +EditWidget::setCoordinateStatus (NR::Point p) +{ + gchar *cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::X]); + _coord_status_x.property_label() = cstr; + g_free (cstr); + cstr = g_strdup_printf ("%6.2f", _dt2r * p[NR::Y]); + _coord_status_y.property_label() = cstr; + g_free (cstr); +} + +void +EditWidget::setMessage (Inkscape::MessageType type, gchar const* msg) +{ + _select_status.set_markup (msg? msg : ""); +} + +bool +EditWidget::warnDialog (gchar* msg) +{ + Gtk::MessageDialog dlg (*this, + msg, + true, + Gtk::MESSAGE_WARNING, + Gtk::BUTTONS_YES_NO, + true); + int r = dlg.run(); + return r == Gtk::RESPONSE_YES; +} + + +void +EditWidget::initEdit (SPDocument *doc) +{ + _desktop = new SPDesktop(); + _desktop->registerEditWidget (this); + + _namedview = sp_document_namedview (doc, 0); + _svg_canvas.init (_desktop); + _desktop->init (_namedview, _svg_canvas.spobj()); + sp_namedview_window_from_document (_desktop); + _dt2r = 1.0 / _namedview->doc_units->unittobase; + + /// \todo convert to sigc++ when SPObject hierarchy gets converted + /* Listen on namedview modification */ + g_signal_connect (G_OBJECT (_desktop->namedview), "modified", G_CALLBACK (_namedview_modified), this); + _layer_selector.setDesktop (_desktop); + _selected_style_status.setDesktop (_desktop); + + Inkscape::NSApplication::Editor::addDesktop (_desktop); + + _zoom_status.init (_desktop); + _top_ruler.init (_desktop, _svg_canvas.widget()); + _left_ruler.init (_desktop, _svg_canvas.widget()); + updateRulers(); +} + +void +EditWidget::destroyEdit() +{ + if (_desktop) { + _layer_selector.unreference(); + Inkscape::NSApplication::Editor::removeDesktop (_desktop); // clears selection too + sp_signal_disconnect_by_data (G_OBJECT (_desktop->namedview), this); + _desktop->destroy(); + Inkscape::GC::release (_desktop); + _desktop = 0; + } +} + +//----------end of EditWidgetInterface implementation + +//----------start of other callbacks + +bool +EditWidget::on_key_press_event (GdkEventKey* event) +{ + // this is the original code from helper/window.cpp + + unsigned int shortcut; + shortcut = get_group0_keyval (event) | + ( event->state & GDK_SHIFT_MASK ? + SP_SHORTCUT_SHIFT_MASK : 0 ) | + ( event->state & GDK_CONTROL_MASK ? + SP_SHORTCUT_CONTROL_MASK : 0 ) | + ( event->state & GDK_MOD1_MASK ? + SP_SHORTCUT_ALT_MASK : 0 ); + return sp_shortcut_invoke (shortcut, + Inkscape::NSApplication::Editor::getActiveDesktop()); +} + +bool +EditWidget::on_delete_event (GdkEventAny*) +{ + return shutdown(); +} + +bool +EditWidget::on_focus_in_event (GdkEventFocus*) +{ + Inkscape::NSApplication::Editor::activateDesktop (_desktop); + _svg_canvas.widget().grab_focus(); + + return false; +} + +void +EditWidget::onWindowSizeAllocate (Gtk::Allocation &newall) +{ + if (!is_realized()) return; + + const Gtk::Allocation& all = get_allocation(); + if ((newall.get_x() == all.get_x()) && + (newall.get_y() == all.get_y()) && + (newall.get_width() == all.get_width()) && + (newall.get_height() == all.get_height())) { + return; + } + + NR::Rect const area = _desktop->get_display_area(); + double zoom = _desktop->current_zoom(); + + if (_sticky_zoom.get_active()) { + /* Calculate zoom per pixel */ + double const zpsp = zoom / hypot(area.dimensions()[NR::X], area.dimensions()[NR::Y]); + /* Find new visible area */ + NR::Rect const newarea = _desktop->get_display_area(); + /* Calculate adjusted zoom */ + zoom = zpsp * hypot(newarea.dimensions()[NR::X], newarea.dimensions()[NR::Y]); + } + + _desktop->zoom_absolute(area.midpoint()[NR::X], area.midpoint()[NR::Y], zoom); +} + +void +EditWidget::onWindowRealize() +{ + NR::Rect d(NR::Point(0, 0), + NR::Point(sp_document_width(_desktop->doc()), sp_document_height(_desktop->doc()))); + + if (fabs(d.dimensions()[NR::X]) < 1.0 || fabs(d.dimensions()[NR::Y]) < 1.0) { + return; + } + + _desktop->set_display_area(d.min()[NR::X], d.min()[NR::Y], d.max()[NR::X], d.max()[NR::Y], 10); + _namedview_modified(_desktop->namedview, SP_OBJECT_MODIFIED_FLAG, this); + setTitle (SP_DOCUMENT_NAME(_desktop->doc())); +} + +void +EditWidget::onAdjValueChanged() +{ + if (_update_a_f) return; + _update_a_f = true; + + sp_canvas_scroll_to (_svg_canvas.spobj(), + _bottom_scrollbar.get_value(), + _right_scrollbar.get_value(), + false); + updateRulers(); + + _update_a_f = false; +} + +/// \todo make this a member function when the signal is a sigc++ signal +void _namedview_modified (SPNamedView* nv, guint flags, EditWidget* ew) +{ + if (flags & SP_OBJECT_MODIFIED_FLAG) + { + ew->_dt2r = 1.0 / nv->doc_units->unittobase; + ew->_top_ruler.update_metric(); + ew->_left_ruler.update_metric(); + ew->_tooltips.set_tip (ew->_top_ruler, ew->_top_ruler.get_tip()); + ew->_tooltips.set_tip (ew->_left_ruler, ew->_left_ruler.get_tip()); + ew->updateRulers(); + } +} + +} // namespace View +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/view/edit-widget.h b/src/ui/view/edit-widget.h new file mode 100644 index 000000000..73e6f048e --- /dev/null +++ b/src/ui/view/edit-widget.h @@ -0,0 +1,211 @@ +/** + * \brief This class implements the functionality of the window layout, menus, + * and signals. + * + * Authors: + * Bryce W. Harrington <bryce@bryceharrington.org> + * Derek P. Moore <derekm@hackunix.org> + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2004 Bryce Harrington + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_VIEW_EDIT_WIDGET_H +#define INKSCAPE_UI_VIEW_EDIT_WIDGET_H + +#include <gtkmm/box.h> +#include <gtkmm/table.h> +#include <gtkmm/entry.h> +#include <gtkmm/scrollbar.h> +#include <gtkmm/actiongroup.h> +#include <gtkmm/uimanager.h> +#include <gtkmm/togglebutton.h> + +#include "ui/dialog/dialog-manager.h" +#include "ui/view/edit-widget-interface.h" +#include "ui/widget/selected-style.h" +#include "ui/widget/ruler.h" +#include "ui/widget/toolbox.h" +#include "ui/widget/svg-canvas.h" +#include "ui/widget/zoom-status.h" +#include "widgets/layer-selector.h" + +struct SPDesktop; +struct SPDocument; +struct SPNamedView; + +namespace Inkscape { +namespace UI { +namespace View { + +class EditWidget : public Gtk::Window, + public EditWidgetInterface { +public: + EditWidget (SPDocument*); + ~EditWidget(); + + // Initialization + void initActions(); + void initUIManager(); + void initLayout(); + void initEdit (SPDocument*); + void destroyEdit(); + + // Actions + void onActionFileNew(); + void onActionFileOpen(); + void onActionFilePrint(); + void onActionFileQuit(); + void onToolbarItem(); + void onSelectTool(); + void onNodeTool(); + + // Menus + void onMenuItem(); + + void onDialogAbout(); + void onDialogAlignAndDistribute(); + void onDialogInkscapePreferences(); + void onDialogDialog(); + void onDialogDocumentProperties(); + void onDialogExport(); + void onDialogExtensionEditor(); + void onDialogFillAndStroke(); + void onDialogFind(); + void onDialogLayerEditor(); + void onDialogMessages(); + void onDialogObjectProperties(); + void onDialogTextProperties(); + void onDialogTransform(); + void onDialogTransformation(); + void onDialogTrace(); + void onDialogXmlEditor(); + + // Whiteboard (Inkboard) +#ifdef WITH_INKBOARD + void onDialogWhiteboardConnect(); + void onDialogWhiteboardShareWithUser(); + void onDialogWhiteboardShareWithChat(); + void onDialogOpenSessionFile(); + void onDumpXMLTracker(); +#endif + + void onUriChanged(); + + // from EditWidgetInterface + virtual void *getWindow(); + virtual void setTitle (gchar const*); + virtual void layout(); + virtual void present(); + virtual void getGeometry (gint &x, gint &y, gint &w, gint &h); + virtual void setSize (gint w, gint h); + virtual void setPosition (NR::Point p); + virtual void setTransient (void*, int); + virtual NR::Point getPointer(); + virtual void setFullscreen(); + virtual bool shutdown(); + virtual void destroy(); + virtual void requestCanvasUpdate(); + virtual void activateDesktop(); + virtual void deactivateDesktop(); + virtual void viewSetPosition (NR::Point p); + virtual void updateRulers(); + virtual void updateScrollbars (double scale); + virtual void toggleRulers(); + virtual void toggleScrollbars(); + virtual void updateZoom(); + virtual void letZoomGrabFocus(); + virtual void setToolboxFocusTo (const gchar *); + virtual void setToolboxAdjustmentValue (const gchar *, double); + virtual bool isToolboxButtonActive (gchar const*); + virtual void setCoordinateStatus (NR::Point p); + virtual void setMessage (Inkscape::MessageType type, gchar const* msg); + virtual bool warnDialog (gchar*); + +protected: + friend void _namedview_modified (SPNamedView*, guint, EditWidget*); + + Gtk::Tooltips _tooltips; + + // Child widgets: + Gtk::Table _main_window_table; + Gtk::VBox _toolbars_vbox; + Gtk::HBox _sub_window_hbox; + Gtk::Table _viewport_table; + + UI::Widget::Toolbox *_tool_ctrl; + Gtk::Toolbar *_select_ctrl; + Gtk::Toolbar *_uri_ctrl; + Gtk::Label _uri_label; + Gtk::Entry _uri_entry; + Gtk::Toolbar *_node_ctrl; + + UI::Widget::HRuler _top_ruler; + UI::Widget::VRuler _left_ruler; + Gtk::HScrollbar _bottom_scrollbar; + Gtk::VScrollbar _right_scrollbar; + Gtk::ToggleButton _sticky_zoom; + UI::Widget::SVGCanvas _svg_canvas; + Gtk::HBox _statusbar; + UI::Widget::SelectedStyle _selected_style_status; + UI::Widget::ZoomStatus _zoom_status; + Inkscape::Widgets::LayerSelector _layer_selector; + Gtk::EventBox _coord_eventbox; + Gtk::Table _coord_status; + Gtk::Label _coord_status_x, _coord_status_y; + Gtk::Label _select_status; + + SPDesktop* _desktop; + SPNamedView* _namedview; + double _dt2r; + + Glib::RefPtr<Gtk::ActionGroup> _act_grp; + Glib::RefPtr<Gtk::UIManager> _ui_mgr; + UI::Dialog::DialogManager _dlg_mgr; + + void initMenuActions(); + void initToolbarActions(); + void initAccelMap(); + void initMenuBar(); + void initCommandsBar(); + void initToolControlsBar(); + void initUriBar(); + void initToolsBar(); + void initBottomScrollbar(); + void initRightScrollbar(); + void initLeftRuler(); + void initTopRuler(); + void initStickyZoom(); + void initStatusbar(); + + virtual bool on_key_press_event (GdkEventKey*); + virtual bool on_delete_event (GdkEventAny*); + virtual bool on_focus_in_event (GdkEventFocus*); + +private: + bool onEntryFocusIn (GdkEventFocus*); + bool onEntryFocusOut (GdkEventFocus*); + void onWindowSizeAllocate (Gtk::Allocation&); + void onWindowRealize(); + void onAdjValueChanged(); + + bool _update_s_f, _update_a_f; +}; +} // namespace View +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_VIEW_EDIT_WIDGET_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/view/edit.cpp b/src/ui/view/edit.cpp new file mode 100644 index 000000000..87bbc241c --- /dev/null +++ b/src/ui/view/edit.cpp @@ -0,0 +1,28 @@ +/** + * \brief Empty file left in repo for current desktop.cpp + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + + +namespace Inkscape { +namespace UI { +namespace View { + + +} // namespace View +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/view/edit.h b/src/ui/view/edit.h new file mode 100644 index 000000000..76c2b5942 --- /dev/null +++ b/src/ui/view/edit.h @@ -0,0 +1,27 @@ +/** + * \brief empty file left in repo for current desktop.h + */ + +#ifndef INKSCAPE_UI_VIEW_EDIT_H +#define INKSCAPE_UI_VIEW_EDIT_H + +namespace Inkscape { +namespace UI { +namespace View { + +} // namespace View +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_VIEW_EDIT_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/view/makefile.in b/src/ui/view/makefile.in new file mode 100644 index 000000000..00aaffe5a --- /dev/null +++ b/src/ui/view/makefile.in @@ -0,0 +1,17 @@ +# Convenience stub makefile to call the real Makefile. + +@SET_MAKE@ + +# Explicit so that it's the default rule. +all: + cd ../.. && $(MAKE) ui/view/all + +clean %.a %.o: + cd ../.. && $(MAKE) ui/view/$@ + +.PHONY: all clean + +OBJEXT = @OBJEXT@ + +.SUFFIXES: +.SUFFIXES: .a .$(OBJEXT) diff --git a/src/ui/view/view-widget.cpp b/src/ui/view/view-widget.cpp new file mode 100644 index 000000000..6e60a9dfe --- /dev/null +++ b/src/ui/view/view-widget.cpp @@ -0,0 +1,135 @@ +/** \file + * SPViewWidget implementation. + * + * Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2001-2002 Lauris Kaplinski + * Copyright (C) 2001 Ximian, Inc. + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "view.h" +#include "view-widget.h" + +//using namespace Inkscape::UI::View; + +/* SPViewWidget */ + +static void sp_view_widget_class_init(SPViewWidgetClass *vwc); +static void sp_view_widget_init(SPViewWidget *widget); +static void sp_view_widget_destroy(GtkObject *object); + +static GtkEventBoxClass *widget_parent_class; + +/** + * Registers the SPViewWidget class with Glib and returns its type number. + */ +GtkType sp_view_widget_get_type(void) +{ + static GtkType type = 0; + + if (!type) { + GtkTypeInfo info = { + "SPViewWidget", + sizeof(SPViewWidget), + sizeof(SPViewWidgetClass), + (GtkClassInitFunc) sp_view_widget_class_init, + (GtkObjectInitFunc) sp_view_widget_init, + NULL, NULL, NULL + }; + type = gtk_type_unique(GTK_TYPE_EVENT_BOX, &info); + } + + return type; +} + +/** + * Callback to initialize the SPViewWidget vtable. + */ +static void sp_view_widget_class_init(SPViewWidgetClass *vwc) +{ + GtkObjectClass *object_class = GTK_OBJECT_CLASS(vwc); + + widget_parent_class = (GtkEventBoxClass*) gtk_type_class(GTK_TYPE_EVENT_BOX); + + object_class->destroy = sp_view_widget_destroy; +} + +/** + * Callback to initialize the SPViewWidget. + */ +static void sp_view_widget_init(SPViewWidget *vw) +{ + vw->view = NULL; +} + +/** + * Callback to disconnect from view and destroy SPViewWidget. + * + * Apparently, this gets only called when a desktop is closed, but then twice! + */ +static void sp_view_widget_destroy(GtkObject *object) +{ + SPViewWidget *vw = SP_VIEW_WIDGET(object); + + if (vw->view) { + vw->view->close(); + Inkscape::GC::release(vw->view); + vw->view = NULL; + } + + if (((GtkObjectClass *) (widget_parent_class))->destroy) { + (* ((GtkObjectClass *) (widget_parent_class))->destroy)(object); + } +} + +/** + * Connects widget to view's 'resized' signal and calls virtual set_view() + * function. + */ +void sp_view_widget_set_view(SPViewWidget *vw, Inkscape::UI::View::View *view) +{ + g_return_if_fail(vw != NULL); + g_return_if_fail(SP_IS_VIEW_WIDGET(vw)); + g_return_if_fail(view != NULL); + + g_return_if_fail(vw->view == NULL); + + vw->view = view; + Inkscape::GC::anchor(view); + + if (((SPViewWidgetClass *) G_OBJECT_GET_CLASS(vw))->set_view) { + ((SPViewWidgetClass *) G_OBJECT_GET_CLASS(vw))->set_view(vw, view); + } +} + +/** + * Calls the virtual shutdown() function of the SPViewWidget. + */ +bool sp_view_widget_shutdown(SPViewWidget *vw) +{ + g_return_val_if_fail(vw != NULL, TRUE); + g_return_val_if_fail(SP_IS_VIEW_WIDGET(vw), TRUE); + + if (((SPViewWidgetClass *) G_OBJECT_GET_CLASS(vw))->shutdown) { + return ((SPViewWidgetClass *) G_OBJECT_GET_CLASS(vw))->shutdown(vw); + } + + return FALSE; +} + + + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/view/view-widget.h b/src/ui/view/view-widget.h new file mode 100644 index 000000000..9b5e9c4a8 --- /dev/null +++ b/src/ui/view/view-widget.h @@ -0,0 +1,97 @@ +#ifndef INKSCAPE_UI_VIEW_VIEWWIDGET_H +#define INKSCAPE_UI_VIEW_VIEWWIDGET_H + +/** \file + * A widget is the UI context for a document view. + * + * Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2001-2002 Lauris Kaplinski + * Copyright (C) 2001 Ximian, Inc. + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gtk/gtkeventbox.h> + +namespace Inkscape { + namespace UI { + namespace View { + class View; + }}} +class SPViewWidget; +class SPNamedView; + +#define SP_TYPE_VIEW_WIDGET (sp_view_widget_get_type ()) +#define SP_VIEW_WIDGET(obj) (GTK_CHECK_CAST ((obj), SP_TYPE_VIEW_WIDGET, SPViewWidget)) +#define SP_VIEW_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), SP_TYPE_VIEW_WIDGET, SPViewWidgetClass)) +#define SP_IS_VIEW_WIDGET(obj) (GTK_CHECK_TYPE ((obj), SP_TYPE_VIEW_WIDGET)) +#define SP_IS_VIEW_WIDGET_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), SP_TYPE_VIEW_WIDGET)) +#define SP_VIEW_WIDGET_VIEW(w) (SP_VIEW_WIDGET (w)->view) +#define SP_VIEW_WIDGET_DOCUMENT(w) (SP_VIEW_WIDGET (w)->view ? ((SPViewWidget *) (w))->view->doc : NULL) + +GType sp_view_widget_get_type (void); + +void sp_view_widget_set_view (SPViewWidget *vw, Inkscape::UI::View::View *view); + +/// Allows presenting 'save changes' dialog, FALSE - continue, TRUE - cancel +bool sp_view_widget_shutdown (SPViewWidget *vw); + +/// Create a new SPViewWidget (which happens to be a SPDesktopWidget). +SPViewWidget *sp_desktop_widget_new (SPNamedView *namedview); + +/** + * SPViewWidget is a GUI widget that contain a single View. It is also + * an abstract base class with little functionality of its own. + */ +class SPViewWidget { + public: + GtkEventBox eventbox; + + Inkscape::UI::View::View *view; + + // C++ Wrappers + GType getType() const { + return sp_view_widget_get_type(); + } + + void setView(Inkscape::UI::View::View *view) { + sp_view_widget_set_view(this, view); + } + + gboolean shutdown() { + return sp_view_widget_shutdown(this); + } + +// void resized (double x, double y) = 0; +}; + +/** + * The Glib-style vtable for the SPViewWidget class. + */ +class SPViewWidgetClass { + public: + GtkEventBoxClass parent_class; + + /* Virtual method to set/change/remove view */ + void (* set_view) (SPViewWidget *vw, Inkscape::UI::View::View *view); + /// Virtual method about view size change + void (* view_resized) (SPViewWidget *vw, Inkscape::UI::View::View *view, gdouble width, gdouble height); + + gboolean (* shutdown) (SPViewWidget *vw); +}; + +#endif + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/view/view.cpp b/src/ui/view/view.cpp new file mode 100644 index 000000000..0f7fd9195 --- /dev/null +++ b/src/ui/view/view.cpp @@ -0,0 +1,163 @@ +#define __SP_VIEW_C__ + +/** \file + * View implementation + * + * Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2001-2002 Lauris Kaplinski + * Copyright (C) 2001 Ximian, Inc. + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "libnr/nr-point.h" +#include "document.h" +#include "view.h" +#include "message-stack.h" +#include "message-context.h" +#include "verbs.h" + +namespace Inkscape { +namespace UI { +namespace View { + +static void +_onPositionSet (double x, double y, View* v) +{ + v->onPositionSet (x,y); +} + +static void +_onResized (double x, double y, View* v) +{ + v->onResized (x,y); +} + +static void +_onRedrawRequested (View* v) +{ + v->onRedrawRequested(); +} + +static void +_onStatusMessage (Inkscape::MessageType type, gchar const *message, View* v) +{ + v->onStatusMessage (type, message); +} + +static void +_onDocumentURISet (gchar const* uri, View* v) +{ + v->onDocumentURISet (uri); +} + +static void +_onDocumentResized (double x, double y, View* v) +{ + v->onDocumentResized (x,y); +} + +//-------------------------------------------------------------------- +View::View() +: _doc(0) +{ + _message_stack = GC::release(new Inkscape::MessageStack()); + _tips_message_context = new Inkscape::MessageContext(_message_stack); + + _position_set_connection = _position_set_signal.connect (sigc::bind (sigc::ptr_fun (&_onPositionSet), this)); + _resized_connection = _resized_signal.connect (sigc::bind (sigc::ptr_fun (&_onResized), this)); + _redraw_requested_connection = _redraw_requested_signal.connect (sigc::bind (sigc::ptr_fun (&_onRedrawRequested), this)); + + _message_changed_connection = _message_stack->connectChanged (sigc::bind (sigc::ptr_fun (&_onStatusMessage), this)); +} + +/** + * Deletes and nulls all View message stacks and disconnects it from signals. + */ +View::~View() +{ + _close(); +} + +void View::_close() { + _message_changed_connection.disconnect(); + + delete _tips_message_context; + _tips_message_context = 0; + + _message_stack = 0; + + if (_doc) { + _document_uri_set_connection.disconnect(); + _document_resized_connection.disconnect(); + _doc = 0; + } + + Inkscape::Verb::delete_all_view (this); +} + +void View::setPosition (double x, double y) +{ + _position_set_signal.emit (x,y); +} + +void View::setPosition(NR::Point const &p) +{ + setPosition (double(p[NR::X]), double(p[NR::Y])); +} + +void View::emitResized (double width, double height) +{ + _resized_signal.emit (width, height); +} + +void View::requestRedraw() +{ + _redraw_requested_signal.emit(); +} + +/** + * Disconnects the view from the document signals, connects the view + * to a new one, and emits the _document_set_signal on the view. + * + * This is code comon to all subclasses and called from their + * setDocument() methods after they are done. + * + * \param doc The new document to connect the view to. + */ +void View::setDocument(SPDocument *doc) { + g_return_if_fail(doc != NULL); + + if (_doc) { + _document_uri_set_connection.disconnect(); + _document_resized_connection.disconnect(); + sp_document_unref (_doc); + } + + _doc = sp_document_ref (doc); + _document_uri_set_connection = + _doc->connectURISet(sigc::bind(sigc::ptr_fun(&_onDocumentURISet), this)); + _document_resized_connection = + _doc->connectResized(sigc::bind(sigc::ptr_fun(&_onDocumentResized), this)); + _document_uri_set_signal.emit (SP_DOCUMENT_URI(_doc)); +} + +}}} + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/ui/view/view.h b/src/ui/view/view.h new file mode 100644 index 000000000..6f0a29543 --- /dev/null +++ b/src/ui/view/view.h @@ -0,0 +1,148 @@ +#ifndef INKSCAPE_UI_VIEW_VIEW_H +#define INKSCAPE_UI_VIEW_VIEW_H + +/** \file + * Abstract base class for all SVG document views + * + * Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * Ralf Stephan <ralf@ark.in-berlin.de> + * + * Copyright (C) 2001-2002 Lauris Kaplinski + * Copyright (C) 2001 Ximian, Inc. + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <gdk/gdktypes.h> +#include <sigc++/connection.h> +#include "message.h" +#include "gc-managed.h" +#include "gc-finalized.h" +#include "gc-anchored.h" + + +/** + * Iterates until true or returns false. + * When used as signal accumulator, stops emission if one slot returns true. + */ +struct StopOnTrue { + typedef bool result_type; + + template<typename T_iterator> + result_type operator()(T_iterator first, T_iterator last) const{ + for (; first != last; ++first) + if (*first) return true; + return false; + } +}; + +/** + * Iterates until nonzero or returns 0. + * When used as signal accumulator, stops emission if one slot returns nonzero. + */ +struct StopOnNonZero { + typedef int result_type; + + template<typename T_iterator> + result_type operator()(T_iterator first, T_iterator last) const{ + for (; first != last; ++first) + if (*first) return *first; + return 0; + } +}; + + +namespace NR { + class Point; +} +class SPDocument; + +namespace Inkscape { + class MessageContext; + class MessageStack; + namespace UI { + namespace View { + +/** + * View is an abstract base class of all UI document views. This + * includes both the editing window and the SVG preview, but does not + * include the non-UI RGBA buffer-based NRArena nor the XML editor or + * similar views. The View base class has very little functionality of + * its own. + */ +class View : public GC::Managed<>, + public GC::Finalized, + public GC::Anchored +{ +public: + + View(); + virtual ~View(); + + void close() { _close(); } + + /// Returns a pointer to the view's document. + SPDocument *doc() const + { return _doc; } + /// Returns a pointer to the view's message stack. + Inkscape::MessageStack *messageStack() const + { return _message_stack; } + /// Returns a pointer to the view's tipsMessageContext. + Inkscape::MessageContext *tipsMessageContext() const + { return _tips_message_context; } + + void setPosition(gdouble x, gdouble y); + void setPosition(NR::Point const &p); + void emitResized(gdouble width, gdouble height); + void requestRedraw(); + + // view subclasses must give implementations of these methods + + virtual bool shutdown() = 0; + virtual void mouseover() = 0; + virtual void mouseout() = 0; + + virtual void onPositionSet (double, double) = 0; + virtual void onResized (double, double) = 0; + virtual void onRedrawRequested() = 0; + virtual void onStatusMessage (Inkscape::MessageType type, gchar const *message) = 0; + virtual void onDocumentURISet (gchar const* uri) = 0; + virtual void onDocumentResized (double, double) = 0; + +protected: + SPDocument *_doc; + Inkscape::MessageStack *_message_stack; + Inkscape::MessageContext *_tips_message_context; + + virtual void _close(); + virtual void setDocument(SPDocument *doc); + + sigc::signal<void,double,double> _position_set_signal; + sigc::signal<void,double,double> _resized_signal; + sigc::signal<void,gchar const*> _document_uri_set_signal; + sigc::signal<void> _redraw_requested_signal; + +private: + sigc::connection _position_set_connection; + sigc::connection _resized_connection; + sigc::connection _redraw_requested_connection; + sigc::connection _message_changed_connection; // foreign + sigc::connection _document_uri_set_connection; // foreign + sigc::connection _document_resized_connection; // foreign +}; + +}}} + +#endif // INKSCAPE_UI_VIEW_VIEW_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : |
