C++ / fmt (pull_request) Successful in 7s
JS/TS / lint (pull_request) Successful in 21s
JS/TS / fmt (pull_request) Successful in 20s
Python / lint (pull_request) Successful in 31s
Python / fmt (pull_request) Successful in 33s
Python / typecheck (pull_request) Failing after 1m4s
Python / test (pull_request) Successful in 1m7s
C++ / build (pull_request) Successful in 1m48s
Rust / fmt (pull_request) Successful in 37s
Rust / build (pull_request) Successful in 1m42s
Python / buildcheck (pull_request) Successful in 2m33s
Rust / clippy (pull_request) Successful in 1m32s
C++ / clang-tidy (pull_request) Successful in 3m35s
144 lines
3.2 KiB
QML
Executable File
144 lines
3.2 KiB
QML
Executable File
pragma ComponentBehavior: Bound
|
|
|
|
import QtQuick
|
|
import ZShell.Internal
|
|
|
|
Item {
|
|
id: root
|
|
|
|
property color inkColor: "#ff3b30"
|
|
property real inkWidth: 4
|
|
property string tool: "none"
|
|
|
|
signal changed
|
|
|
|
function clearAll() {
|
|
committedCanvas.clear();
|
|
previewCanvas.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() {
|
|
committedCanvas.undoLastGroup();
|
|
changed();
|
|
}
|
|
|
|
anchors.fill: parent
|
|
|
|
StrokeCanvas {
|
|
id: committedCanvas
|
|
|
|
anchors.fill: parent
|
|
penColor: root.inkColor
|
|
penWidth: root.inkWidth
|
|
}
|
|
|
|
StrokeCanvas {
|
|
id: previewCanvas
|
|
|
|
anchors.fill: parent
|
|
penColor: root.inkColor
|
|
penWidth: root.inkWidth
|
|
}
|
|
|
|
PointHandler {
|
|
id: drawHandler
|
|
|
|
property real startX
|
|
property real startY
|
|
property bool started: false
|
|
|
|
acceptedButtons: Qt.LeftButton | Qt.RightButton
|
|
enabled: root.tool !== "none"
|
|
|
|
onActiveChanged: {
|
|
if (active)
|
|
return;
|
|
|
|
if (root.tool === "pen") {
|
|
committedCanvas.endStroke();
|
|
} else if (started) {
|
|
const pts = root.sampleShape(root.tool, startX, startY, point.position.x, point.position.y);
|
|
if (pts.length > 0) {
|
|
committedCanvas.beginStroke(pts[0][0], pts[0][1], true);
|
|
for (let i = 1; i < pts.length; i++)
|
|
committedCanvas.appendPoint(pts[i][0], pts[i][1]);
|
|
committedCanvas.endStroke();
|
|
}
|
|
previewCanvas.clear();
|
|
}
|
|
started = false;
|
|
root.changed();
|
|
}
|
|
onPointChanged: {
|
|
if (!active)
|
|
return;
|
|
|
|
if (point.pressedButtons & Qt.RightButton) {
|
|
root.clearAll();
|
|
return;
|
|
}
|
|
|
|
const x = point.position.x;
|
|
const y = point.position.y;
|
|
|
|
if (root.tool === "pen") {
|
|
if (!started) {
|
|
started = true;
|
|
committedCanvas.beginStroke(x, y);
|
|
return;
|
|
}
|
|
committedCanvas.appendPoint(x, y);
|
|
return;
|
|
}
|
|
|
|
if (!started) {
|
|
started = true;
|
|
startX = point.pressPosition.x;
|
|
startY = point.pressPosition.y;
|
|
}
|
|
const pts = root.sampleShape(root.tool, startX, startY, x, y);
|
|
if (pts.length > 0) {
|
|
previewCanvas.beginStroke(pts[0][0], pts[0][1], true);
|
|
for (let i = 1; i < pts.length; i++)
|
|
previewCanvas.appendPoint(pts[i][0], pts[i][1]);
|
|
}
|
|
}
|
|
}
|
|
}
|