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;