cursor crosshair + outline of pen width
Lint & Format (JS/TS) / lint-format (pull_request) Successful in 10s
Python / lint-format (pull_request) Successful in 14s
Python / test (pull_request) Successful in 32s
Lint & Format (Rust) / lint-format (pull_request) Successful in 1m7s

This commit is contained in:
2026-06-22 11:52:11 +02:00
parent 2f3f41cedd
commit 80d5f13663
6 changed files with 95 additions and 23 deletions
+1 -2
View File
@@ -123,7 +123,6 @@ Item {
property bool setInitialPoint: false
acceptedButtons: Qt.LeftButton | Qt.RightButton
cursorShape: Qt.BlankCursor
enabled: root.visibilities.isDrawing && (!root.inLeftPanel(root.panels.drawing, hoverHandler.point.position.x, hoverHandler.point.position.y) || !root.panels.drawing.expanded)
onActiveChanged: {
@@ -162,7 +161,7 @@ Item {
HoverHandler {
id: hoverHandler
cursorShape: root.visibilities.isDrawing && !root.inLeftPanel(root.panels.drawing, point.position.x, point.position.y) ? Qt.CrossCursor : undefined
cursorShape: root.visibilities.isDrawing && !root.inLeftPanel(root.panels.drawing, point.position.x, point.position.y) ? Qt.BlankCursor : undefined
onHoveredChanged: {
if (!hovered) {
+1
View File
@@ -13,6 +13,7 @@ struct Stroke {
QColor color;
float width;
int groupId = -1;
bool isSinglePoint = false;
};
};
+18 -10
View File
@@ -2,6 +2,7 @@
#include "strokecanvasrenderer.hpp"
#include <qcanvaspainter.h>
#include <qnamespace.h>
#include <qpoint.h>
namespace ZShell::internal {
@@ -28,12 +29,11 @@ static bool shouldAddPoint(
>= minDistance * minDistance;
}
static QCanvasPath buildStrokePath(const QVector<QPointF> &points) {
static QCanvasPath buildStrokePath(const QVector<QPointF> &points, float width) {
QCanvasPath path;
if (points.size() == 1) {
// Single point — store as a tiny circle so the group can still be cached
path.circle(points[0], 0); // radius 0; actual width applied at draw time
path.circle(points[0], width * 0.5f);
return path;
}
@@ -95,12 +95,18 @@ void StrokeCanvasItem::setHoverPoint(const QPointF &point) {
}
void StrokeCanvasItem::showHover(qreal x, qreal y) {
m_hoverPoint = {x, y};
m_hoverVisible = true;
update();
const QPointF newPoint{x, y};
const bool pointChanged = (m_hoverPoint != newPoint);
const bool visibleChanged = !m_hoverVisible;
emit hoverPointChanged();
emit hoverVisibleChanged();
if (pointChanged || visibleChanged) {
m_hoverVisible = true;
m_hoverPoint = newPoint;
if (pointChanged) emit hoverPointChanged();
if (visibleChanged) emit hoverVisibleChanged();
update();
}
}
void StrokeCanvasItem::hideHover() {
@@ -124,6 +130,7 @@ void StrokeCanvasItem::setPenWidth(float width) {
}
void StrokeCanvasItem::beginStroke(qreal x, qreal y) {
m_isDrawing = true;
m_currentStroke.points.clear();
m_currentStroke.points.append({x, y});
@@ -163,13 +170,14 @@ void StrokeCanvasItem::appendPoint(qreal x, qreal y) {
}
void StrokeCanvasItem::endStroke() {
m_isDrawing = false;
if (m_currentStroke.points.isEmpty())
return;
m_currentStroke.path = buildStrokePath(m_currentStroke.points);
m_currentStroke.isSinglePoint = (m_currentStroke.points.size() == 1);
m_currentStroke.path = buildStrokePath(m_currentStroke.points, m_currentStroke.width);
m_currentStroke.groupId = m_nextGroupId++;
m_currentStroke.points.clear();
m_strokes.append(m_currentStroke);
m_currentStroke = {};
@@ -70,6 +70,7 @@ bool m_hoverVisible = false;
QPointF m_hoverPoint;
QColor m_penColor = Qt::white;
float m_penWidth = 4.f;
bool m_isDrawing = false;
int m_nextGroupId = 0;
QVector<Stroke> m_strokes;
@@ -1,5 +1,6 @@
#include "strokecanvasrenderer.hpp"
#include "strokecanvasitem.hpp"
#include <qcolor.h>
namespace ZShell::internal {
@@ -54,17 +55,79 @@ static void drawStroke(
painter->stroke();
}
static void drawDot(
static void drawHoverCursor(
QCanvasPainter *painter,
const QPointF &point,
const QColor &color,
float width)
float penWidth,
QColor penColor,
bool isDrawing)
{
painter->setFillStyle(color);
const float radius = penWidth * 0.5f;
painter->beginPath();
painter->circle(point, width * 0.5f);
painter->fill();
if (isDrawing) {
painter->setFillStyle(penColor);
painter->beginPath();
painter->circle(point, radius);
painter->fill();
}
const float lineWidth = 1.5f;
const float crosshairSize = 6.0f;
const bool useDashes = penWidth > 10.0f;
auto drawOutline = [&](const QColor &color, float width) {
painter->setStrokeStyle(color);
painter->setLineWidth(width);
painter->setLineCap(QCanvasPainter::LineCap::Round);
if (useDashes) {
const int dashCount = 12;
const float fullAngle = 2.0f * M_PI;
const float dashAngle = fullAngle / dashCount * 0.5f;
const float gapAngle = fullAngle / dashCount * 0.5f;
float angle = 0.0f;
for (int i = 0; i < dashCount; ++i) {
painter->beginPath();
painter->arc(point, radius, angle, angle + dashAngle,
QCanvasPainter::PathWinding::ClockWise,
QCanvasPainter::PathConnection::NotConnected);
painter->stroke();
angle += dashAngle + gapAngle;
}
} else {
painter->beginPath();
painter->circle(point, radius);
painter->stroke();
}
};
auto drawCrosshair = [&](const QColor &color, float width) {
painter->setStrokeStyle(color);
painter->setLineWidth(width);
painter->setLineCap(QCanvasPainter::LineCap::Round);
const float inner = radius + 3.0f;
const float outer = radius + 3.0f + crosshairSize;
painter->beginPath();
painter->moveTo(point + QPointF(0, -outer));
painter->lineTo(point + QPointF(0, -inner));
painter->moveTo(point + QPointF(0, outer));
painter->lineTo(point + QPointF(0, inner));
painter->moveTo(point + QPointF(-outer, 0));
painter->lineTo(point + QPointF(-inner, 0));
painter->moveTo(point + QPointF( outer, 0));
painter->lineTo(point + QPointF( inner, 0));
painter->stroke();
};
drawOutline(QColor(0, 0, 0, 160), lineWidth + 1.0f);
drawCrosshair(QColor(0, 0, 0, 160), lineWidth + 1.0f);
drawOutline(QColor(255, 255, 255, 220), lineWidth);
drawCrosshair(QColor(255, 255, 255, 220), lineWidth);
}
void StrokeCanvasRenderer::synchronizeData(QCanvasPainterItem *item) {
@@ -73,11 +136,9 @@ void StrokeCanvasRenderer::synchronizeData(QCanvasPainterItem *item) {
m_penColor = canvas->m_penColor;
m_penWidth = canvas->m_penWidth;
// Only copy strokes the renderer hasn't seen yet
while (m_strokes.size() < canvas->m_strokes.size())
m_strokes.append(canvas->m_strokes[m_strokes.size()]);
// Handle clear()
if (canvas->m_strokes.isEmpty() && !m_strokes.isEmpty()) {
for (const auto &stroke : m_strokes)
if (stroke.groupId >= 0)
@@ -89,6 +150,7 @@ void StrokeCanvasRenderer::synchronizeData(QCanvasPainterItem *item) {
m_hoverVisible = canvas->m_hoverVisible;
m_hoverPoint = canvas->m_hoverPoint;
m_isDrawing = canvas->m_isDrawing;
}
void StrokeCanvasRenderer::paint(QCanvasPainter *painter) {
@@ -105,7 +167,7 @@ void StrokeCanvasRenderer::paint(QCanvasPainter *painter) {
painter->setLineCap(QCanvasPainter::LineCap::Round);
painter->setLineJoin(QCanvasPainter::LineJoin::Round);
if (stroke.path.commandsSize() == 1) {
if (stroke.isSinglePoint) {
painter->fill(stroke.path, stroke.groupId);
} else {
painter->stroke(stroke.path, stroke.groupId);
@@ -115,7 +177,7 @@ void StrokeCanvasRenderer::paint(QCanvasPainter *painter) {
drawStroke(painter, m_currentStroke.points, m_currentStroke.color, m_currentStroke.width);
if (m_hoverVisible)
drawDot(painter, m_hoverPoint, m_penColor, m_penWidth);
drawHoverCursor(painter, m_hoverPoint, m_penWidth, m_penColor, m_isDrawing);
}
};
@@ -17,6 +17,7 @@ QColor m_penColor;
float m_penWidth = 4.f;
bool m_hoverVisible = false;
QPointF m_hoverPoint;
bool m_isDrawing = false;
QVector<Stroke> m_strokes;
Stroke m_currentStroke;