warp-pipe/gui/SquareConnectionPainter.cpp

116 lines
3.3 KiB
C++

#include "SquareConnectionPainter.h"
#include <QtNodes/internal/ConnectionGraphicsObject.hpp>
#include <QtNodes/internal/ConnectionState.hpp>
#include <QtNodes/internal/Definitions.hpp>
#include <QtNodes/StyleCollection>
#include <QPainter>
#include <QPainterPath>
#include <QPainterPathStroker>
#include <algorithm>
#include <cmath>
QPainterPath SquareConnectionPainter::orthogonalPath(
QtNodes::ConnectionGraphicsObject const &cgo) const {
QPointF out = cgo.endPoint(QtNodes::PortType::Out);
QPointF in = cgo.endPoint(QtNodes::PortType::In);
constexpr double kRadius = 5.0;
constexpr double kSpacing = 8.0;
constexpr double kMinStub = 20.0;
auto cId = cgo.connectionId();
double spread = static_cast<double>(cId.outPortIndex) * kSpacing;
double dy = in.y() - out.y();
if (std::abs(dy) < 0.5 && in.x() > out.x()) {
QPainterPath path(out);
path.lineTo(in);
return path;
}
double midX = (out.x() + in.x()) / 2.0 + spread;
midX = std::max(midX, out.x() + kMinStub);
if (in.x() > out.x())
midX = std::min(midX, in.x() - kMinStub);
double r = std::min({kRadius, std::abs(dy) / 2.0,
std::abs(midX - out.x()),
std::abs(in.x() - midX)});
r = std::max(r, 0.0);
double sy = (dy > 0) ? 1.0 : -1.0;
double hDir = (in.x() >= midX) ? 1.0 : -1.0;
QPainterPath path(out);
if (r > 0.5) {
path.lineTo(midX - r, out.y());
path.quadTo(QPointF(midX, out.y()), QPointF(midX, out.y() + sy * r));
path.lineTo(midX, in.y() - sy * r);
path.quadTo(QPointF(midX, in.y()), QPointF(midX + hDir * r, in.y()));
} else {
path.lineTo(midX, out.y());
path.lineTo(midX, in.y());
}
path.lineTo(in);
return path;
}
void SquareConnectionPainter::paint(
QPainter *painter,
QtNodes::ConnectionGraphicsObject const &cgo) const {
auto const &style = QtNodes::StyleCollection::connectionStyle();
bool const hovered = cgo.connectionState().hovered();
bool const selected = cgo.isSelected();
bool const sketch = cgo.connectionState().requiresPort();
auto path = orthogonalPath(cgo);
if (hovered || selected) {
QPen pen;
pen.setWidth(static_cast<int>(2 * style.lineWidth()));
pen.setColor(selected ? style.selectedHaloColor() : style.hoveredColor());
painter->setPen(pen);
painter->setBrush(Qt::NoBrush);
painter->drawPath(path);
}
if (sketch) {
QPen pen;
pen.setWidth(static_cast<int>(style.constructionLineWidth()));
pen.setColor(style.constructionColor());
pen.setStyle(Qt::DashLine);
painter->setPen(pen);
painter->setBrush(Qt::NoBrush);
painter->drawPath(path);
} else {
QPen pen;
pen.setWidth(style.lineWidth());
pen.setColor(selected ? style.selectedColor() : style.normalColor());
painter->setPen(pen);
painter->setBrush(Qt::NoBrush);
painter->drawPath(path);
}
double const pointRadius = style.pointDiameter() / 2.0;
painter->setPen(style.constructionColor());
painter->setBrush(style.constructionColor());
painter->drawEllipse(cgo.out(), pointRadius, pointRadius);
painter->drawEllipse(cgo.in(), pointRadius, pointRadius);
}
QPainterPath SquareConnectionPainter::getPainterStroke(
QtNodes::ConnectionGraphicsObject const &cgo) const {
auto path = orthogonalPath(cgo);
QPainterPathStroker stroker;
stroker.setWidth(10.0);
return stroker.createStroke(path);
}