summaryrefslogtreecommitdiffstats
path: root/src/ui/view/svg-view-widget.cpp
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2018-12-03 14:12:58 +0000
committerTavmjong Bah <tavmjong@free.fr>2018-12-03 14:12:58 +0000
commitd0a70cf731c5d3e2698f62876a4acade0361bb8e (patch)
treeff8e35ffe8c44db6b28b8c29c108513307f057c7 /src/ui/view/svg-view-widget.cpp
parentUse std::unique_ptr for all MessageContext (diff)
downloadinkscape-d0a70cf731c5d3e2698f62876a4acade0361bb8e.tar.gz
inkscape-d0a70cf731c5d3e2698f62876a4acade0361bb8e.zip
Remove dependance of SVGViewWidget on SVGView and View. Remove SVGView.
Another step in making View not dependent on GUI.
Diffstat (limited to 'src/ui/view/svg-view-widget.cpp')
-rw-r--r--src/ui/view/svg-view-widget.cpp206
1 files changed, 193 insertions, 13 deletions
diff --git a/src/ui/view/svg-view-widget.cpp b/src/ui/view/svg-view-widget.cpp
index c696a3ad2..c349b5aca 100644
--- a/src/ui/view/svg-view-widget.cpp
+++ b/src/ui/view/svg-view-widget.cpp
@@ -1,12 +1,17 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/**
* @file
- * A light-weight widget containing an SPCanvas with a View for rendering an SVG.
+ * 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.
@@ -14,52 +19,158 @@
*
*/
+#include <iostream>
+
#include "svg-view-widget.h"
-#include "svg-view.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 {
/**
- * A light-weight widget containing an SPCanvas with a View for rendering an SVG.
+ * 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));
+ _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);
- SPCanvasItem* parent =
- sp_canvas_item_new(SP_CANVAS(_canvas)->getRoot(), SP_TYPE_CANVAS_GROUP, nullptr);
- _view = new SVGView(SP_CANVAS_GROUP(parent));
- _view->setDocument(document);
+ setDocument(document);
- signal_size_allocate().connect(sigc::mem_fun(*this, &SVGViewWidget::size_allocate));
+ signal_size_allocate().connect(sigc::mem_fun(*this, &SVGViewWidget::size_allocate));
}
SVGViewWidget::~SVGViewWidget()
{
- delete _view;
+ if (_document) {
+ _document = nullptr;
+ }
}
void
SVGViewWidget::setDocument(SPDocument* document)
{
- _view->setDocument(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();
}
@@ -67,7 +178,76 @@ SVGViewWidget::setResize(int width, int height)
void
SVGViewWidget::size_allocate(Gtk::Allocation& allocation)
{
- _view->setRescale(true, true, allocation.get_width(), allocation.get_height());
+ 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