142 lines
4.3 KiB
C++
142 lines
4.3 KiB
C++
#pragma once
|
|
|
|
#include <QtNodes/GraphicsView>
|
|
#include <QtNodes/StyleCollection>
|
|
|
|
#include <QGraphicsProxyWidget>
|
|
#include <QMouseEvent>
|
|
#include <QPainter>
|
|
#include <QScrollBar>
|
|
#include <QWheelEvent>
|
|
|
|
#include <QtNodes/internal/ConnectionGraphicsObject.hpp>
|
|
|
|
#include <cmath>
|
|
|
|
class ZoomGraphicsView : public QtNodes::GraphicsView {
|
|
public:
|
|
explicit ZoomGraphicsView(QtNodes::BasicGraphicsScene *scene,
|
|
QWidget *parent = nullptr)
|
|
: QtNodes::GraphicsView(scene, parent) {
|
|
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
|
|
setCacheMode(QGraphicsView::CacheNone);
|
|
}
|
|
|
|
void setZoomSensitivity(double sensitivity) {
|
|
m_sensitivity = sensitivity;
|
|
}
|
|
double zoomSensitivity() const { return m_sensitivity; }
|
|
|
|
void updateProxyCacheMode() {
|
|
if (!scene())
|
|
return;
|
|
|
|
const double zoom = transform().m11();
|
|
const bool highZoom = zoom > 1.4;
|
|
|
|
if (highZoom == m_proxiesCached)
|
|
return;
|
|
m_proxiesCached = highZoom;
|
|
|
|
auto cacheMode = highZoom ? QGraphicsItem::DeviceCoordinateCache
|
|
: QGraphicsItem::NoCache;
|
|
for (QGraphicsItem *item : scene()->items()) {
|
|
if (item->type() == QGraphicsProxyWidget::Type ||
|
|
item->type() == QtNodes::ConnectionGraphicsObject::Type)
|
|
item->setCacheMode(cacheMode);
|
|
}
|
|
}
|
|
|
|
protected:
|
|
void wheelEvent(QWheelEvent *event) override {
|
|
const double dy = event->angleDelta().y();
|
|
if (dy == 0.0) {
|
|
event->ignore();
|
|
return;
|
|
}
|
|
|
|
static constexpr double kTickUnits = 120.0;
|
|
const double exponent = dy / kTickUnits;
|
|
const double factor = std::pow(m_sensitivity, exponent);
|
|
const double proposed = transform().m11() * factor;
|
|
setupScale(proposed);
|
|
}
|
|
|
|
void mousePressEvent(QMouseEvent *event) override {
|
|
if (event->button() == Qt::LeftButton) {
|
|
m_panActive = true;
|
|
m_panStart = event->pos();
|
|
}
|
|
QGraphicsView::mousePressEvent(event);
|
|
}
|
|
|
|
void mouseMoveEvent(QMouseEvent *event) override {
|
|
if (m_panActive && (event->buttons() & Qt::LeftButton) &&
|
|
!(event->modifiers() & Qt::ShiftModifier) &&
|
|
!scene()->mouseGrabberItem()) {
|
|
QPoint delta = event->pos() - m_panStart;
|
|
m_panStart = event->pos();
|
|
horizontalScrollBar()->setValue(horizontalScrollBar()->value() - delta.x());
|
|
verticalScrollBar()->setValue(verticalScrollBar()->value() - delta.y());
|
|
return;
|
|
}
|
|
QGraphicsView::mouseMoveEvent(event);
|
|
}
|
|
|
|
void mouseReleaseEvent(QMouseEvent *event) override {
|
|
if (event->button() == Qt::LeftButton)
|
|
m_panActive = false;
|
|
QGraphicsView::mouseReleaseEvent(event);
|
|
}
|
|
|
|
void drawBackground(QPainter *painter, const QRectF &r) override {
|
|
QGraphicsView::drawBackground(painter, r);
|
|
|
|
const double zoom = transform().m11();
|
|
auto const &style =
|
|
QtNodes::StyleCollection::flowViewStyle();
|
|
|
|
static constexpr double kBaseFine = 15.0;
|
|
static constexpr double kBaseCoarse = 150.0;
|
|
static constexpr double kMinPixelSpacing = 10.0;
|
|
|
|
double fineStep = kBaseFine;
|
|
while (fineStep * zoom < kMinPixelSpacing)
|
|
fineStep *= 2.0;
|
|
|
|
double coarseStep = kBaseCoarse;
|
|
while (coarseStep * zoom < kMinPixelSpacing * 5.0)
|
|
coarseStep *= 2.0;
|
|
|
|
auto drawGrid = [&](double gridStep) {
|
|
QRect windowRect = rect();
|
|
QPointF tl = mapToScene(windowRect.topLeft());
|
|
QPointF br = mapToScene(windowRect.bottomRight());
|
|
|
|
double left = std::floor(tl.x() / gridStep - 0.5);
|
|
double right = std::floor(br.x() / gridStep + 1.0);
|
|
double bottom = std::floor(tl.y() / gridStep - 0.5);
|
|
double top = std::floor(br.y() / gridStep + 1.0);
|
|
|
|
for (int xi = int(left); xi <= int(right); ++xi)
|
|
painter->drawLine(QLineF(xi * gridStep, bottom * gridStep,
|
|
xi * gridStep, top * gridStep));
|
|
|
|
for (int yi = int(bottom); yi <= int(top); ++yi)
|
|
painter->drawLine(QLineF(left * gridStep, yi * gridStep,
|
|
right * gridStep, yi * gridStep));
|
|
};
|
|
|
|
painter->setPen(QPen(style.FineGridColor, 1.0));
|
|
drawGrid(fineStep);
|
|
|
|
painter->setPen(QPen(style.CoarseGridColor, 1.0));
|
|
drawGrid(coarseStep);
|
|
}
|
|
|
|
private:
|
|
double m_sensitivity = 1.2;
|
|
bool m_proxiesCached = false;
|
|
bool m_panActive = false;
|
|
QPoint m_panStart;
|
|
};
|