Files
z-bar-qt/Helpers/Picker/AnnotationCanvas.qml
T

137 lines
3.0 KiB
QML
Executable File

pragma ComponentBehavior: Bound
import QtQuick
import ZShell.Internal
Item {
id: root
property color inkColor: "#ff3b30"
property real inkWidth: 4
required property Rectangle selection
property string tool: "none"
signal changed
function clearAll() {
canvas.clear();
changed();
}
function sampleShape(tool, x1, y1, x2, y2) {
const pts = [];
switch (tool) {
case "line":
pts.push([x1, y1], [x2, y2]);
break;
case "arrow":
{
const angle = Math.atan2(y2 - y1, x2 - x1);
const headLen = 14 + root.inkWidth * 2;
pts.push([x1, y1], [x2, y2]);
pts.push([x2 - headLen * Math.cos(angle - Math.PI / 6), y2 - headLen * Math.sin(angle - Math.PI / 6)]);
pts.push([x2, y2]);
pts.push([x2 - headLen * Math.cos(angle + Math.PI / 6), y2 - headLen * Math.sin(angle + Math.PI / 6)]);
break;
}
case "rect":
pts.push([x1, y1], [x2, y1], [x2, y2], [x1, y2], [x1, y1]);
break;
case "ellipse":
{
const cx = (x1 + x2) / 2, cy = (y1 + y2) / 2;
const rx = Math.abs(x2 - x1) / 2, ry = Math.abs(y2 - y1) / 2;
const perimeter = Math.PI * (3 * (rx + ry) - Math.sqrt((3 * rx + ry) * (rx + 3 * ry)));
const steps = Math.max(48, Math.min(256, Math.ceil(perimeter / 4)));
for (let i = 0; i <= steps; i++) {
const a = (i / steps) * Math.PI * 2;
pts.push([cx + rx * Math.cos(a), cy + ry * Math.sin(a)]);
}
break;
}
}
return pts;
}
function undo() {
canvas.undoLastGroup();
changed();
}
anchors.fill: parent
StrokeCanvas {
id: canvas
anchors.fill: parent
penColor: root.inkColor
penWidth: root.inkWidth
}
MouseArea {
id: drawHandler
property real startX
property real startY
acceptedButtons: Qt.LeftButton | Qt.RightButton
anchors.fill: parent
cursorShape: undefined
enabled: root.tool !== "none"
hoverEnabled: true
onPositionChanged: e => {
const x = e.x;
const y = e.y;
canvas.hoverPoint = Qt.point(x, y);
if (!pressed)
return;
if (root.tool === "pen") {
canvas.appendPoint(x, y);
return;
}
const pts = root.sampleShape(root.tool, startX, startY, x, y);
if (pts.length > 0) {
canvas.beginStroke(pts[0][0], pts[0][1], true);
for (let i = 1; i < pts.length; i++)
canvas.appendPoint(pts[i][0], pts[i][1]);
}
}
onPressed: e => {
if (e.button & Qt.LeftButton) {
startX = e.x;
startY = e.y;
canvas.beginStroke(e.x, e.y);
} else if (e.button & Qt.RightButton) {
root.clearAll();
}
}
onPressedChanged: if (!pressed)
canvas.endStroke()
}
HoverHandler {
cursorShape: {
if (root.tool === "none")
return undefined;
const x = point.position.x;
const y = point.position.y;
const withinXWidth = x > root.selection.x && x < root.selection.x + root.selection.implicitWidth;
const withinYHeight = y > root.selection.y && y < root.selection.y + root.selection.implicitHeight;
if (withinXWidth && withinYHeight) {
canvas.showHover(x, y);
return Qt.BlankCursor;
} else {
canvas.hideHover();
return undefined;
}
}
}
}