diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2018-12-03 14:12:58 +0000 |
|---|---|---|
| committer | Tavmjong Bah <tavmjong@free.fr> | 2018-12-03 14:12:58 +0000 |
| commit | d0a70cf731c5d3e2698f62876a4acade0361bb8e (patch) | |
| tree | ff8e35ffe8c44db6b28b8c29c108513307f057c7 /src/ui/view/svg-view-widget.cpp | |
| parent | Use std::unique_ptr for all MessageContext (diff) | |
| download | inkscape-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.cpp | 206 |
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 |
