Warning, file /graphics/tikzkit/src/ui/view/Renderer.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* This file is part of the TikZKit project.
0002  *
0003  * Copyright (C) 2013 Dominik Haumann <dhaumann@kde.org>
0004  *
0005  * This library is free software; you can redistribute it and/or modify
0006  * it under the terms of the GNU Library General Public License as published
0007  * by the Free Software Foundation, either version 2 of the License, or
0008  * (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013  * GNU Library General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Library General Public License
0016  * along with this library; see the file COPYING.LIB.  If not, see
0017  * <http://www.gnu.org/licenses/>.
0018  */
0019 
0020 #include "Renderer.h"
0021 #include "Ruler.h"
0022 #include "TikzScene.h"
0023 #include "DocumentPrivate.h"
0024 #include "Grid.h"
0025 #include "ZoomController.h"
0026 
0027 #include <tikz/core/Document.h>
0028 
0029 #include <math.h>
0030 #include <QApplication>
0031 #include <QDebug>
0032 #include <QScrollBar>
0033 #include <QGridLayout>
0034 
0035 namespace tikz {
0036 namespace ui {
0037 
0038 static const int s_ruler_size = 16;
0039 
0040 Renderer::Renderer(DocumentPrivate * doc, QWidget * parent)
0041     : QGraphicsView(parent)
0042 {
0043     m_doc = doc;
0044 
0045     // add rulers
0046     setViewportMargins(s_ruler_size, s_ruler_size, 0, 0);
0047     QGridLayout* gridLayout = new QGridLayout();
0048     gridLayout->setSpacing(0);
0049     gridLayout->setContentsMargins(0, 0, 0, 0);
0050 
0051     m_grid = new Grid(this);
0052 
0053     m_hRuler = new tikz::ui::Ruler(Qt::Horizontal, this);
0054     m_vRuler = new tikz::ui::Ruler(Qt::Vertical, this);
0055 
0056     m_hRuler->setUnit(tikz::Unit::Centimeter);
0057     m_vRuler->setUnit(tikz::Unit::Centimeter);
0058 
0059     m_zoomController = new tikz::ui::ZoomController(this);
0060     connect(m_zoomController, &ZoomController::zoomChanged, this, &Renderer::setZoom);
0061 
0062     QWidget* top = new QWidget();
0063     top->setBackgroundRole(QPalette::Window);
0064     top->setFixedSize(s_ruler_size, s_ruler_size);
0065     gridLayout->addWidget(top, 0, 0);
0066     gridLayout->addWidget(m_hRuler, 0, 1);
0067     gridLayout->addWidget(m_vRuler, 1, 0);
0068     gridLayout->addWidget(viewport(), 1, 1);
0069 
0070     setLayout(gridLayout);
0071 
0072     // set graphics scene
0073     setScene(doc->scene());
0074 
0075     // scale to true display size
0076     const qreal s = tikz::Value(1, tikz::Unit::Inch).toPoint();
0077     scale(physicalDpiX() / s,
0078          -physicalDpiY() / s);
0079 
0080 //     setViewportUpdateMode(FullViewportUpdate);
0081 
0082     connect(doc, SIGNAL(preferredUnitChanged(tikz::Unit)), m_grid, SLOT(setUnit(tikz::Unit)));
0083     connect(doc, SIGNAL(preferredUnitChanged(tikz::Unit)), m_hRuler, SLOT(setUnit(tikz::Unit)));
0084     connect(doc, SIGNAL(preferredUnitChanged(tikz::Unit)), m_vRuler, SLOT(setUnit(tikz::Unit)));
0085     connect(doc, SIGNAL(preferredUnitChanged(tikz::Unit)), viewport(), SLOT(update()));
0086 
0087     m_grid->setUnit(doc->preferredUnit());
0088     m_hRuler->setUnit(doc->preferredUnit());
0089     m_vRuler->setUnit(doc->preferredUnit());
0090 }
0091 
0092 Renderer::~Renderer()
0093 {
0094 }
0095 
0096 DocumentPrivate * Renderer::document() const
0097 {
0098     return m_doc;
0099 }
0100 
0101 tikz::Value Renderer::snapValue(const tikz::Value & value) const
0102 {
0103     const bool snap = QApplication::keyboardModifiers() ^ Qt::ShiftModifier;
0104     if (snap) {
0105         return m_grid->snapValue(value);
0106     }
0107     return tikz::Value(static_cast<int>(value.value() * 100) / 100.0, value.unit());
0108 }
0109 
0110 tikz::Pos Renderer::snapPos(const tikz::Pos & pos) const
0111 {
0112     const bool snap = QApplication::keyboardModifiers() ^ Qt::ShiftModifier;
0113     if (snap) {
0114         m_grid->snapPos(pos);
0115     }
0116     return tikz::Pos(snapValue(pos.x()), snapValue(pos.y()));
0117 }
0118 
0119 qreal Renderer::snapAngle(qreal angle) const
0120 {
0121     const bool snap = QApplication::keyboardModifiers() ^ Qt::ShiftModifier;
0122     return snap ? (qRound(angle / 15) * 15) : angle;
0123 }
0124 
0125 tikz::ui::ZoomController * Renderer::zoomController() const
0126 {
0127     return m_zoomController;
0128 }
0129 
0130 void Renderer::setZoom(qreal zoomFactor)
0131 {
0132     // just in case, prevent division by 0
0133     if (zoomFactor == 0) {
0134         return;
0135     }
0136 
0137     constexpr qreal unit = tikz::Value(1, tikz::Unit::Inch).toPoint();
0138     const qreal s = unit / zoomFactor;
0139     QTransform m;
0140     m.scale(physicalDpiX() / s, -physicalDpiY() / s);
0141     setTransform(m);
0142 }
0143 
0144 void Renderer::mousePressEvent(QMouseEvent* event)
0145 {
0146     m_lastMousePos = event->pos();
0147 
0148     // start scrolling with middle mouse button
0149     if (event->button() == Qt::MiddleButton) {
0150         setCursor(Qt::SizeAllCursor);
0151         m_handTool = true;
0152         event->accept();
0153     } else {
0154         QGraphicsView::mousePressEvent(event);
0155     }
0156 }
0157 
0158 void Renderer::mouseMoveEvent(QMouseEvent* event)
0159 {
0160     // on middle mouse button down: move
0161     if (m_handTool) {
0162         const QPointF diff = event->pos() - m_lastMousePos;
0163         QScrollBar * h = horizontalScrollBar();
0164         QScrollBar * v = verticalScrollBar();
0165         h->setValue(h->value() - diff.x());
0166         v->setValue(v->value() - diff.y());
0167 
0168         event->accept();
0169     } else {
0170         QGraphicsView::mouseMoveEvent(event);
0171     }
0172 
0173     // update mouse indicator on rulers
0174     m_hRuler->setOrigin(m_hRuler->mapFromGlobal(viewport()->mapToGlobal(mapFromScene(QPointF(0, 0)))).x());
0175     m_vRuler->setOrigin(m_vRuler->mapFromGlobal(viewport()->mapToGlobal(mapFromScene(QPointF(0, 0)))).y());
0176 
0177     m_hRuler->setMousePos(event->globalPos());
0178     m_vRuler->setMousePos(event->globalPos());
0179 
0180     // track last mouse position
0181     m_lastMousePos = event->pos();
0182 
0183     const QPointF scenePos = mapToScene(event->pos());
0184     const tikz::Pos mousePos = tikz::Pos(scenePos).convertTo(m_grid->unit());
0185     Q_EMIT mousePositionChanged(snapPos(mousePos));
0186 }
0187 
0188 void Renderer::mouseReleaseEvent(QMouseEvent* event)
0189 {
0190     // end scrolling with middle mouse button
0191     if (event->button() == Qt::MiddleButton) {
0192         unsetCursor();
0193         m_handTool = false;
0194         event->accept();
0195     } else {
0196         QGraphicsView::mouseReleaseEvent(event);
0197     }
0198 }
0199 
0200 void Renderer::wheelEvent(QWheelEvent* event)
0201 {
0202     if (event->modifiers() & Qt::ControlModifier) {
0203         setTransformationAnchor(AnchorUnderMouse);
0204         m_zoomController->processWheelEvent(event->angleDelta().y());
0205     } else {
0206         QGraphicsView::wheelEvent(event);
0207     }
0208 }
0209 
0210 bool Renderer::viewportEvent(QEvent * event)
0211 {
0212     constexpr qreal s = 1.0_in .toPoint();
0213     const qreal xZoom = transform().m11() / physicalDpiX() * s;
0214     const qreal yZoom = qAbs(transform().m22()) / physicalDpiY() * s;
0215     Q_ASSERT(qFuzzyCompare(xZoom, yZoom));
0216 
0217     // update ruler (zoom, origin)
0218     m_hRuler->setOrigin(m_hRuler->mapFromGlobal(viewport()->mapToGlobal(mapFromScene(QPointF(0, 0)))).x());
0219     m_vRuler->setOrigin(m_vRuler->mapFromGlobal(viewport()->mapToGlobal(mapFromScene(QPointF(0, 0)))).y());
0220     m_hRuler->setZoom(xZoom);
0221     m_vRuler->setZoom(yZoom);
0222 
0223     // update grid (zoom)
0224     m_grid->setZoom(xZoom);
0225 
0226     return QGraphicsView::viewportEvent(event);
0227 }
0228 
0229 void Renderer::drawBackground(QPainter * painter, const QRectF & rect)
0230 {
0231     // draw default background (typically nothing)
0232     QGraphicsView::drawBackground(painter, rect);
0233 
0234     // draw raster on top
0235     m_grid->draw(painter, sceneRect().united(rect));
0236 }
0237 
0238 void Renderer::drawForeground(QPainter * painter, const QRectF & rect)
0239 {
0240     // draw default background (typically nothing)
0241     QGraphicsView::drawForeground(painter, rect);
0242 }
0243 
0244 }
0245 }
0246 
0247 // kate: indent-width 4; replace-tabs on;