summaryrefslogtreecommitdiffstats
path: root/src/ui/view
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/ui/view/README51
-rw-r--r--src/ui/view/edit-widget-interface.h178
-rw-r--r--src/ui/view/svg-view-widget.cpp266
-rw-r--r--src/ui/view/svg-view-widget.h89
-rw-r--r--src/ui/view/view-widget.cpp102
-rw-r--r--src/ui/view/view-widget.h107
-rw-r--r--src/ui/view/view.cpp138
-rw-r--r--src/ui/view/view.h148
8 files changed, 1079 insertions, 0 deletions
diff --git a/src/ui/view/README b/src/ui/view/README
new file mode 100644
index 0000000..9316f8b
--- /dev/null
+++ b/src/ui/view/README
@@ -0,0 +1,51 @@
+
+This directory contains the class Inkscape::UI::View::View and related items.
+
+View is an abstract base class for all UI document views. Documents
+can be displayed by more than one window, each having its own view
+(e.g. zoom level, selection, etc.).
+
+View is the base class for:
+
+* SPDesktop
+* SVGView REMOVED
+
+SPViewWidget is the base for:
+
+* SPDocumentWidget
+* SPSVGViewWidget REMOVED
+
+SPSVGViewWidget has been replaced by SVGViewWidget, see below.
+
+
+SPViewWidget:
+ Contains a GtkEventBox and holds a View.
+
+SPDesktopWidget:
+ Contains:
+ VBox
+ HBox
+ GtkGrid
+ GtkPaned
+ GtkGrid
+ SPCanvas
+ Plus lots of other junk.
+
+
+SVGViewWidget:
+ Used many places as a convenient way to show an SVG (file dialog, Inkview).
+ Derived, rather uselessly, from Gtk::Scrollbar.
+ It no longer is dependent on View (and really doesn't belong here anymore).
+
+ It contains: SPCanvas
+
+To do:
+
+
+* Convert everything to C++.
+* Evaluate moving SPDesktopWidget down the widget stack.
+ It doesn't use the EventBox of SPViewWidget!
+
+A DesktopViewWidget should contain:
+ DesktopView (aka SPDesktop)
+ SPCanvas
diff --git a/src/ui/view/edit-widget-interface.h b/src/ui/view/edit-widget-interface.h
new file mode 100644
index 0000000..eb3e33b
--- /dev/null
+++ b/src/ui/view/edit-widget-interface.h
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Authors:
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ * John Bintz <jcoswell@coswellproductions.org>
+ *
+ * Copyright (C) 2006 John Bintz
+ * Copyright (C) 2005 Ralf Stephan
+ *
+ * Released under GNU GPL v2+, read the file 'COPYING' for more information.
+ */
+
+#ifndef INKSCAPE_UI_VIEW_EDIT_WIDGET_IFACE_H
+#define INKSCAPE_UI_VIEW_EDIT_WIDGET_IFACE_H
+
+#include "message.h"
+#include <2geom/point.h>
+
+namespace Gtk {
+ class Toolbar;
+ class Window;
+}
+
+namespace Glib {
+class ustring;
+}
+
+namespace Inkscape { namespace UI { namespace Widget { class Dock; } } }
+
+namespace Inkscape {
+namespace UI {
+namespace View {
+
+/**
+ * Abstract base class for all EditWidget implementations.
+ */
+struct EditWidgetInterface
+{
+ EditWidgetInterface() = default;
+ virtual ~EditWidgetInterface() = default;
+
+ /// Returns pointer to window UI object as void*
+ virtual Gtk::Window *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 (Geom::Point p) = 0;
+
+ /// Transientize widget
+ virtual void setTransient (void*, int) = 0;
+
+ /// Return mouse position in widget
+ virtual Geom::Point getPointer() = 0;
+
+ /// Make widget iconified
+ virtual void setIconified() = 0;
+
+ /// Make widget maximized on screen
+ virtual void setMaximized() = 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;
+
+
+ /// Store window position to prefs
+ virtual void storeDesktopPosition() = 0;
+
+ /// Queue a redraw request with the canvas
+ virtual void requestCanvasUpdate() = 0;
+
+ /// Force a redraw of the canvas
+ virtual void requestCanvasUpdateAndWait() = 0;
+
+ /// Enable interaction on this desktop
+ virtual void enableInteraction() = 0;
+
+ /// Disable interaction on this desktop
+ virtual void disableInteraction() = 0;
+
+ /// Update the "active desktop" indicator
+ virtual void activateDesktop() = 0;
+
+ /// Update the "inactive desktop" indicator
+ virtual void deactivateDesktop() = 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;
+
+ /// Toggle CMS on/off and set preference value accordingly
+ virtual void toggleColorProfAdjust() = 0;
+
+ /// Is CMS on/off
+ virtual bool colorProfAdjustEnabled() = 0;
+
+ /// Temporarily block signals and update zoom display
+ virtual void updateZoom() = 0;
+
+ /// The zoom display will get the keyboard focus.
+ virtual void letZoomGrabFocus() = 0;
+
+ /// Temporarily block signals and update rotation display
+ virtual void updateRotation() = 0;
+
+ virtual Gtk::Toolbar* get_toolbar_by_name(const Glib::ustring&) = 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 (Geom::Point p) = 0;
+
+ /// Message widget will get no content
+ virtual void setMessage (Inkscape::MessageType type, gchar const* msg) = 0;
+
+
+ /** Show an info dialog with the given message */
+ virtual bool showInfoDialog( Glib::ustring const &message ) = 0;
+
+ /// Open yes/no dialog with warning text and confirmation question.
+ virtual bool warnDialog (Glib::ustring const &) = 0;
+
+ virtual Inkscape::UI::Widget::Dock* getDock () = 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:fileencoding=utf-8:textwidth=99 :
diff --git a/src/ui/view/svg-view-widget.cpp b/src/ui/view/svg-view-widget.cpp
new file mode 100644
index 0000000..c349b5a
--- /dev/null
+++ b/src/ui/view/svg-view-widget.cpp
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/**
+ * @file
+ * A light-weight widget containing an SPCanvas for rendering an SVG.
+ */
+/*
+ * Authors:
+ * Tavmjong Bah <tavmjong@free.fr>
+ *
+ * Includes code moved from svg-view.cpp authored by:
+ * MenTaLGuy
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ * Jon A. Cruz <jon@joncruz.org>
+ *
+ * Copyright (C) 2018 Authors
+ *
+ * The contents of this file may be used under the GNU General Public License Version 2 or later.
+ * Read the file 'COPYING' for more information.
+ *
+ */
+
+#include <iostream>
+
+#include "svg-view-widget.h"
+
+#include "document.h"
+
+#include "2geom/transforms.h"
+
+#include "display/sp-canvas.h"
+#include "display/sp-canvas-group.h"
+#include "display/sp-canvas-item.h"
+#include "display/canvas-arena.h"
+
+#include "object/sp-item.h"
+#include "object/sp-root.h"
+
+#include "util/units.h"
+
+namespace Inkscape {
+namespace UI {
+namespace View {
+
+/**
+ * Callback connected with arena_event.
+ */
+// This hasn't worked since at least 0.48. It should result in a cursor change over <a></a> links.
+// There should be a better way of doing this. See note in canvas-arena.cpp.
+static gint arena_handler(SPCanvasArena */*arena*/, Inkscape::DrawingItem *ai,
+ GdkEvent *event, SVGViewWidget *svgview)
+{
+ static gdouble x, y;
+ static gboolean active = FALSE;
+ SPEvent spev;
+
+ SPItem *spitem = (ai) ? ai->getItem() : nullptr;
+
+ switch (event->type) {
+ case GDK_BUTTON_PRESS:
+ if (event->button.button == 1) {
+ active = TRUE;
+ x = event->button.x;
+ y = event->button.y;
+ }
+ break;
+ case GDK_BUTTON_RELEASE:
+ if (event->button.button == 1) {
+ if (active && (event->button.x == x) &&
+ (event->button.y == y)) {
+ spev.type = SPEvent::ACTIVATE;
+ if ( spitem != nullptr )
+ {
+ spitem->emitEvent (spev);
+ }
+ }
+ }
+ active = FALSE;
+ break;
+ case GDK_MOTION_NOTIFY:
+ active = FALSE;
+ break;
+ case GDK_ENTER_NOTIFY:
+ spev.type = SPEvent::MOUSEOVER;
+ spev.view = svgview;
+ if ( spitem != nullptr )
+ {
+ spitem->emitEvent (spev);
+ }
+ break;
+ case GDK_LEAVE_NOTIFY:
+ spev.type = SPEvent::MOUSEOUT;
+ spev.view = svgview;
+ if ( spitem != nullptr )
+ {
+ spitem->emitEvent (spev);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * A light-weight widget containing an SPCanvas for rendering an SVG.
+ * It's derived from a Gtk::ScrolledWindow like the previous C version, but that doesn't seem to be
+ * too useful.
+ */
+SVGViewWidget::SVGViewWidget(SPDocument* document)
+ : _document(nullptr)
+ , _dkey(0)
+ , _parent(nullptr)
+ , _drawing(nullptr)
+ , _hscale(1.0)
+ , _vscale(1.0)
+ , _rescale(false)
+ , _keepaspect(false)
+ , _width(0.0)
+ , _height(0.0)
+{
+ _canvas = SPCanvas::createAA();
+ add(*Glib::wrap(_canvas));
+
+ SPCanvasItem* item =
+ sp_canvas_item_new(SP_CANVAS(_canvas)->getRoot(), SP_TYPE_CANVAS_GROUP, nullptr);
+ _parent = SP_CANVAS_GROUP(item);
+
+ _drawing = sp_canvas_item_new (_parent, SP_TYPE_CANVAS_ARENA, nullptr);
+ g_signal_connect (G_OBJECT (_drawing), "arena_event", G_CALLBACK (arena_handler), this);
+
+ setDocument(document);
+
+ signal_size_allocate().connect(sigc::mem_fun(*this, &SVGViewWidget::size_allocate));
+}
+
+SVGViewWidget::~SVGViewWidget()
+{
+ if (_document) {
+ _document = nullptr;
+ }
+}
+
+void
+SVGViewWidget::setDocument(SPDocument* document)
+{
+ // Clear old document
+ if (_document) {
+ _document->getRoot()->invoke_hide(_dkey); // Removed from display tree
+ }
+
+ // Add new document
+ if (document) {
+ _document = document;
+
+ Inkscape::DrawingItem *ai = document->getRoot()->invoke_show(
+ SP_CANVAS_ARENA (_drawing)->drawing,
+ _dkey,
+ SP_ITEM_SHOW_DISPLAY);
+
+ if (ai) {
+ SP_CANVAS_ARENA (_drawing)->drawing.root()->prependChild(ai);
+ }
+
+ doRescale ();
+ }
+}
+
+void
+SVGViewWidget::setResize(int width, int height)
+{
+ // Triggers size_allocation which calls SVGViewWidget::size_allocate.
+ set_size_request(width, height);
+ queue_resize();
+}
+
+void
+SVGViewWidget::size_allocate(Gtk::Allocation& allocation)
+{
+ double width = allocation.get_width();
+ double height = allocation.get_height();
+
+ if (width < 0.0 || height < 0.0) {
+ std::cerr << "SVGViewWidget::size_allocate: negative dimensions!" << std::endl;
+ return;
+ }
+
+ _rescale = true;
+ _keepaspect = true;
+ _width = width;
+ _height = height;
+
+ doRescale ();
+}
+
+void
+SVGViewWidget::doRescale()
+{
+ if (!_document) {
+ std::cerr << "SVGViewWidget::doRescale: No document!" << std::endl;
+ return;
+ }
+
+ if (_document->getWidth().value("px") < 1e-9) {
+ std::cerr << "SVGViewWidget::doRescale: Width too small!" << std::endl;
+ return;
+ }
+
+ if (_document->getHeight().value("px") < 1e-9) {
+ std::cerr << "SVGViewWidget::doRescale: Height too small!" << std::endl;
+ return;
+ }
+
+ double x_offset = 0.0;
+ double y_offset = 0.0;
+ if (_rescale) {
+ _hscale = _width / _document->getWidth().value("px");
+ _vscale = _height / _document->getHeight().value("px");
+ if (_keepaspect) {
+ if (_hscale > _vscale) {
+ _hscale = _vscale;
+ x_offset = (_width - _document->getWidth().value("px") * _vscale)/2.0;
+ } else {
+ _vscale = _hscale;
+ y_offset = (_height - _document->getHeight().value("px") * _hscale)/2.0;
+ }
+ }
+ }
+
+ if (_drawing) {
+ sp_canvas_item_affine_absolute (_drawing, Geom::Scale(_hscale, _vscale) * Geom::Translate(x_offset, y_offset));
+ }
+}
+
+void
+SVGViewWidget::mouseover()
+{
+ GdkDisplay *display = gdk_display_get_default();
+ GdkCursor *cursor = gdk_cursor_new_for_display(display, GDK_HAND2);
+ GdkWindow *window = gtk_widget_get_window (GTK_WIDGET(SP_CANVAS_ITEM(_drawing)->canvas));
+ gdk_window_set_cursor(window, cursor);
+ g_object_unref(cursor);
+}
+
+void
+SVGViewWidget::mouseout()
+{
+ GdkWindow *window = gtk_widget_get_window (GTK_WIDGET(SP_CANVAS_ITEM(_drawing)->canvas));
+ gdk_window_set_cursor(window, nullptr);
+}
+
+} // 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:fileencoding=utf-8 :
diff --git a/src/ui/view/svg-view-widget.h b/src/ui/view/svg-view-widget.h
new file mode 100644
index 0000000..644c879
--- /dev/null
+++ b/src/ui/view/svg-view-widget.h
@@ -0,0 +1,89 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/**
+ * @file
+ * A light-weight widget containing an SPCanvas with for rendering an SVG.
+ */
+/*
+ * Authors:
+ * Tavmjong Bah <tavmjong@free.fr>
+ *
+ * Copyright (C) 2018 Authors
+ *
+ * The contents of this file may be used under the GNU General Public License Version 2 or later.
+ * Read the file 'COPYING' for more information.
+ *
+ */
+
+#ifndef INKSCAPE_UI_SVG_VIEW_WIDGET_VARIATIONS_H
+#define INKSCAPE_UI_SVG_VIEW_WIDGET_VARIATIONS_H
+
+
+#include <gtkmm.h>
+
+class SPDocument;
+class SPCanvasGroup;
+class SPCanvasItem;
+
+namespace Inkscape {
+namespace UI {
+namespace View {
+
+/**
+ * A light-weight widget containing an SPCanvas for rendering an SVG.
+ */
+class SVGViewWidget : public Gtk::ScrolledWindow {
+
+public:
+ SVGViewWidget(SPDocument* document);
+ ~SVGViewWidget() override;
+ void setDocument( SPDocument* document);
+ void setResize( int width, int height);
+
+private:
+ void size_allocate(Gtk::Allocation& allocation);
+
+ GtkWidget* _canvas;
+
+// From SVGView ---------------------------------
+
+public:
+ SPDocument* _document;
+ unsigned int _dkey;
+ SPCanvasGroup *_parent;
+ SPCanvasItem *_drawing;
+ double _hscale; ///< horizontal scale
+ double _vscale; ///< vertical scale
+ bool _rescale; ///< whether to rescale automatically
+ bool _keepaspect;
+ double _width;
+ double _height;
+
+ /**
+ * Helper function that sets rescale ratio.
+ */
+ void doRescale();
+
+ /**
+ * Change cursor (used for links).
+ */
+ void mouseover();
+ void mouseout();
+
+};
+
+} // Namespace View
+} // Namespace UI
+} // Namespace Inkscape
+
+#endif // INKSCAPE_UI_SVG_VIEW_WIDGET
+
+/*
+ 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:fileencoding=utf-8 :
diff --git a/src/ui/view/view-widget.cpp b/src/ui/view/view-widget.cpp
new file mode 100644
index 0000000..ce9745d
--- /dev/null
+++ b/src/ui/view/view-widget.cpp
@@ -0,0 +1,102 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * 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 v2+, 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_dispose(GObject *object);
+
+G_DEFINE_TYPE(SPViewWidget, sp_view_widget, GTK_TYPE_EVENT_BOX);
+
+/**
+ * Callback to initialize the SPViewWidget vtable.
+ */
+static void sp_view_widget_class_init(SPViewWidgetClass *vwc)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS(vwc);
+
+ object_class->dispose = sp_view_widget_dispose;
+}
+
+/**
+ * Callback to initialize the SPViewWidget.
+ */
+static void sp_view_widget_init(SPViewWidget *vw)
+{
+ vw->view = nullptr;
+}
+
+/**
+ * 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_dispose(GObject *object)
+{
+ SPViewWidget *vw = SP_VIEW_WIDGET(object);
+
+ if (vw->view) {
+ vw->view->close();
+ Inkscape::GC::release(vw->view);
+ vw->view = nullptr;
+ }
+
+ if (G_OBJECT_CLASS(sp_view_widget_parent_class)->dispose) {
+ G_OBJECT_CLASS(sp_view_widget_parent_class)->dispose(object);
+ }
+
+ Inkscape::GC::request_early_collection();
+}
+
+void sp_view_widget_set_view(SPViewWidget *vw, Inkscape::UI::View::View *view)
+{
+ g_return_if_fail(vw != nullptr);
+ g_return_if_fail(SP_IS_VIEW_WIDGET(vw));
+ g_return_if_fail(view != nullptr);
+
+ g_return_if_fail(vw->view == nullptr);
+
+ 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);
+ }
+}
+
+bool sp_view_widget_shutdown(SPViewWidget *vw)
+{
+ g_return_val_if_fail(vw != nullptr, 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 0000000..0296ac6
--- /dev/null
+++ b/src/ui/view/view-widget.h
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#ifndef INKSCAPE_UI_VIEW_VIEWWIDGET_H
+#define INKSCAPE_UI_VIEW_VIEWWIDGET_H
+
+/*
+ * 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 v2+, read the file 'COPYING' for more information.
+ */
+
+#include <gtk/gtk.h>
+
+
+namespace Inkscape {
+namespace UI {
+namespace View {
+class View;
+} // namespace View
+} // namespace UI
+} // namespace Inkscape
+
+class SPViewWidget;
+class SPNamedView;
+
+#define SP_TYPE_VIEW_WIDGET (sp_view_widget_get_type ())
+#define SP_VIEW_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_VIEW_WIDGET, SPViewWidget))
+#define SP_VIEW_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SP_TYPE_VIEW_WIDGET, SPViewWidgetClass))
+#define SP_IS_VIEW_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SP_TYPE_VIEW_WIDGET))
+#define SP_IS_VIEW_WIDGET_CLASS(klass) (G_TYPE_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)
+
+/**
+ * Registers the SPViewWidget class with Glib and returns its type number.
+ */
+GType sp_view_widget_get_type();
+
+/**
+ * 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);
+
+/**
+ * Allows presenting 'save changes' dialog, FALSE - continue, TRUE - cancel.
+ * Calls the virtual shutdown() function of the SPViewWidget.
+ */
+bool sp_view_widget_shutdown(SPViewWidget *vw);
+
+/**
+ * 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; // NOT USED!
+
+ 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 0000000..3b2b7f2
--- /dev/null
+++ b/src/ui/view/view.cpp
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Authors:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Ralf Stephan <ralf@ark.in-berlin.de>
+ * Jon A. Cruz <jon@joncruz.org>
+ *
+ * Copyright (C) 2001-2002 Lauris Kaplinski
+ * Copyright (C) 2001 Ximian, Inc.
+ *
+ * Released under GNU GPL v2+, read the file 'COPYING' for more information.
+ */
+
+#include <2geom/point.h>
+#include <memory>
+#include "document.h"
+#include "view.h"
+#include "message-stack.h"
+#include "message-context.h"
+#include "verbs.h"
+#include "inkscape.h"
+
+namespace Inkscape {
+namespace UI {
+namespace View {
+
+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(nullptr)
+{
+ _message_stack = std::make_shared<Inkscape::MessageStack>();
+ _tips_message_context = std::unique_ptr<Inkscape::MessageContext>(new Inkscape::MessageContext(_message_stack));
+
+ _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));
+}
+
+View::~View()
+{
+ _close();
+}
+
+void View::_close() {
+ _message_changed_connection.disconnect();
+
+ _tips_message_context = nullptr;
+
+ _message_stack = nullptr;
+
+ if (_doc) {
+ _document_uri_set_connection.disconnect();
+ _document_resized_connection.disconnect();
+ if (INKSCAPE.remove_document(_doc)) {
+ // this was the last view of this document, so delete it
+ // delete _doc; Delete now handled in Inkscape::Application
+ }
+ _doc = nullptr;
+ }
+
+ Inkscape::Verb::delete_all_view (this);
+}
+
+void View::emitResized (double width, double height)
+{
+ _resized_signal.emit (width, height);
+}
+
+void View::requestRedraw()
+{
+ _redraw_requested_signal.emit();
+}
+
+void View::setDocument(SPDocument *doc) {
+ g_return_if_fail(doc != nullptr);
+
+ if (_doc) {
+ _document_uri_set_connection.disconnect();
+ _document_resized_connection.disconnect();
+ if (INKSCAPE.remove_document(_doc)) {
+ // this was the last view of this document, so delete it
+ // delete _doc; Delete now handled in Inkscape::Application
+ }
+ }
+
+ INKSCAPE.add_document(doc);
+
+ _doc = 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( _doc->getDocumentURI() );
+}
+
+}}}
+
+/*
+ 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 0000000..3acfd2c
--- /dev/null
+++ b/src/ui/view/view.h
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+#ifndef INKSCAPE_UI_VIEW_VIEW_H
+#define INKSCAPE_UI_VIEW_VIEW_H
+/*
+ * 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 v2+, read the file 'COPYING' for more information.
+ */
+
+#include <gdk/gdk.h>
+#include <cstddef>
+#include <memory>
+#include <sigc++/connection.h>
+#include "message.h"
+#include "inkgc/gc-managed.h"
+#include "gc-finalized.h"
+#include "gc-anchored.h"
+#include <2geom/forward.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;
+ }
+};
+
+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 Inkscape::Drawing 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();
+
+ /**
+ * Deletes and nulls all View message stacks and disconnects it from signals.
+ */
+ ~View() override;
+
+ 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.
+ std::shared_ptr<Inkscape::MessageStack> messageStack() const
+ { return _message_stack; }
+ /// Returns a pointer to the view's tipsMessageContext.
+ Inkscape::MessageContext *tipsMessageContext() const
+ { return _tips_message_context.get(); }
+
+ void emitResized(gdouble width, gdouble height);
+ void requestRedraw();
+
+ virtual void onResized (double, double) {};
+ virtual void onRedrawRequested() {};
+ virtual void onStatusMessage (Inkscape::MessageType type, gchar const *message) {};
+ virtual void onDocumentURISet (gchar const* uri) {};
+ virtual void onDocumentResized (double, double) {};
+ virtual bool shutdown() { return false; };
+
+protected:
+ SPDocument *_doc;
+ std::shared_ptr<Inkscape::MessageStack> _message_stack;
+ std::unique_ptr<Inkscape::MessageContext> _tips_message_context;
+
+ virtual void _close();
+
+ /**
+ * 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 common to all subclasses and called from their
+ * setDocument() methods after they are done.
+ *
+ * @param doc The new document to connect the view to.
+ */
+ virtual void setDocument(SPDocument *doc);
+
+ 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 _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 :