DiagramDesigner/source/connectionPainter.cpp

252 lines
6.8 KiB
C++

#include "connectionPainter.h"
#include <QtGui/QIcon>
#include "abstractGraphModel.h"
#include "connectionGraphicsObject.h"
#include "connectionState.h"
#include "global.h"
#include "nodeData.h"
#include "styleCollection.h"
static QPainterPath cubicPath(ConnectionGraphicsObject const &connection)
{
QPointF const &in = connection.endPoint(PortType::In);
QPointF const &out = connection.endPoint(PortType::Out);
auto const c1c2 = connection.pointsC1C2();
// cubic spline
QPainterPath cubic(out);
cubic.cubicTo(c1c2.first, c1c2.second, in);
return cubic;
}
QPainterPath ConnectionPainter::getPainterStroke(ConnectionGraphicsObject const &connection)
{
auto cubic = cubicPath(connection);
QPointF const &out = connection.endPoint(PortType::Out);
QPainterPath result(out);
unsigned segments = 20;
for (auto i = 0ul; i < segments; ++i) {
double ratio = double(i + 1) / segments;
result.lineTo(cubic.pointAtPercent(ratio));
}
QPainterPathStroker stroker;
stroker.setWidth(10.0);
return stroker.createStroke(result);
}
#ifdef NODE_DEBUG_DRAWING
static void debugDrawing(QPainter *painter, ConnectionGraphicsObject const &cgo)
{
Q_UNUSED(painter);
{
QPointF const &in = cgo.endPoint(PortType::In);
QPointF const &out = cgo.endPoint(PortType::Out);
auto const points = cgo.pointsC1C2();
painter->setPen(Qt::red);
painter->setBrush(Qt::red);
painter->drawLine(QLineF(out, points.first));
painter->drawLine(QLineF(points.first, points.second));
painter->drawLine(QLineF(points.second, in));
painter->drawEllipse(points.first, 3, 3);
painter->drawEllipse(points.second, 3, 3);
painter->setBrush(Qt::NoBrush);
painter->drawPath(cubicPath(cgo));
}
{
painter->setPen(Qt::yellow);
painter->drawRect(cgo.boundingRect());
}
}
#endif
static void drawSketchLine(QPainter *painter, ConnectionGraphicsObject const &cgo)
{
ConnectionState const &state = cgo.connectionState();
if (state.requiresPort()) {
auto const &connectionStyle = StyleCollection::connectionStyle();
QPen pen;
pen.setWidth(connectionStyle.constructionLineWidth());
pen.setColor(connectionStyle.constructionColor());
pen.setStyle(Qt::DashLine);
painter->setPen(pen);
painter->setBrush(Qt::NoBrush);
auto cubic = cubicPath(cgo);
// cubic spline
painter->drawPath(cubic);
}
}
static void drawHoveredOrSelected(QPainter *painter, ConnectionGraphicsObject const &cgo)
{
bool const hovered = cgo.connectionState().hovered();
bool const selected = cgo.isSelected();
// drawn as a fat background
if (hovered || selected) {
auto const &connectionStyle = StyleCollection::connectionStyle();
double const lineWidth = connectionStyle.lineWidth();
QPen pen;
pen.setWidth(2 * lineWidth);
pen.setColor(selected ? connectionStyle.selectedHaloColor()
: connectionStyle.hoveredColor());
painter->setPen(pen);
painter->setBrush(Qt::NoBrush);
// cubic spline
auto const cubic = cubicPath(cgo);
painter->drawPath(cubic);
}
}
static void drawNormalLine(QPainter *painter, ConnectionGraphicsObject const &cgo)
{
ConnectionState const &state = cgo.connectionState();
if (state.requiresPort())
return;
// colors
auto const &connectionStyle = StyleCollection::connectionStyle();
QColor normalColorOut = connectionStyle.normalColor();
QColor normalColorIn = connectionStyle.normalColor();
QColor selectedColor = connectionStyle.selectedColor();
bool useGradientColor = false;
AbstractGraphModel const &graphModel = cgo.graphModel();
if (connectionStyle.useDataDefinedColors()) {
auto const cId = cgo.connectionId();
auto dataTypeOut = graphModel
.portData(cId.outNodeId,
PortType::Out,
cId.outPortIndex,
PortRole::DataType)
.value<NodeDataType>();
auto dataTypeIn
= graphModel.portData(cId.inNodeId, PortType::In, cId.inPortIndex, PortRole::DataType)
.value<NodeDataType>();
useGradientColor = (dataTypeOut.id != dataTypeIn.id);
normalColorOut = connectionStyle.normalColor(dataTypeOut.id);
normalColorIn = connectionStyle.normalColor(dataTypeIn.id);
selectedColor = normalColorOut.darker(200);
}
// geometry
double const lineWidth = connectionStyle.lineWidth();
// draw normal line
QPen p;
p.setWidth(lineWidth);
bool const selected = cgo.isSelected();
auto cubic = cubicPath(cgo);
if (useGradientColor) {
painter->setBrush(Qt::NoBrush);
QColor cOut = normalColorOut;
if (selected)
cOut = cOut.darker(200);
p.setColor(cOut);
painter->setPen(p);
unsigned int const segments = 60;
for (unsigned int i = 0ul; i < segments; ++i) {
double ratioPrev = double(i) / segments;
double ratio = double(i + 1) / segments;
if (i == segments / 2) {
QColor cIn = normalColorIn;
if (selected)
cIn = cIn.darker(200);
p.setColor(cIn);
painter->setPen(p);
}
painter->drawLine(cubic.pointAtPercent(ratioPrev), cubic.pointAtPercent(ratio));
}
{
QIcon icon(":convert.png");
QPixmap pixmap = icon.pixmap(QSize(22, 22));
painter->drawPixmap(cubic.pointAtPercent(0.50)
- QPoint(pixmap.width() / 2, pixmap.height() / 2),
pixmap);
}
} else {
p.setColor(normalColorOut);
if (selected) {
p.setColor(selectedColor);
}
painter->setPen(p);
painter->setBrush(Qt::NoBrush);
painter->drawPath(cubic);
}
}
void ConnectionPainter::paint(QPainter *painter, ConnectionGraphicsObject const &cgo)
{
drawHoveredOrSelected(painter, cgo);
drawSketchLine(painter, cgo);
drawNormalLine(painter, cgo);
#ifdef NODE_DEBUG_DRAWING
debugDrawing(painter, cgo);
#endif
// draw end points
auto const &connectionStyle = StyleCollection::connectionStyle();
double const pointDiameter = connectionStyle.pointDiameter();
painter->setPen(connectionStyle.constructionColor());
painter->setBrush(connectionStyle.constructionColor());
double const pointRadius = pointDiameter / 2.0;
painter->drawEllipse(cgo.out(), pointRadius, pointRadius);
painter->drawEllipse(cgo.in(), pointRadius, pointRadius);
}