Files

181 lines
5.6 KiB
QML

// Somewhere to try a pointer change before deciding to keep it.
//
// Pointer speed, acceleration, scroll direction and scroll speed are all
// settings you cannot read: the number means nothing, and the only honest test
// is moving the pointer. Every one of them applies live, so this is simply a
// place to move it that is not somebody's document.
//
// Entirely local. Nothing here writes a preference or touches the compositor,
// and the scribble is not saved anywhere -- it exists for the length of a
// question ("is that too fast?") and is thrown away.
//
// The canvas repaints only when the pointer has actually moved across it,
// driven from the motion handler rather than a timer. A settings page that
// repainted continuously would be a persistent GPU load on a high-refresh
// display, in return for a picture that had not changed.
import QtQuick
import qs.config
Column {
id: root
width: parent ? parent.width : 620
spacing: 10
Rectangle {
id: pad
width: parent.width
height: 150
radius: Theme.cardRadius
color: Theme.alpha(Theme.bgDark, 0.55)
border.width: 1
border.color: Theme.alpha(Theme.fg, 0.08)
clip: true
// Segments drawn since the last paint. The canvas keeps what it has
// already been given, so each paint adds the new piece of the stroke
// instead of redrawing the whole scribble.
property var pending: []
property bool wiping: false
property bool drawn: false
Canvas {
id: scribble
anchors.fill: parent
renderStrategy: Canvas.Immediate
onPaint: {
const context = scribble.getContext("2d");
if (pad.wiping) {
context.reset();
pad.wiping = false;
pad.pending = [];
return;
}
context.strokeStyle = Theme.accent;
context.lineWidth = 2.4;
context.lineCap = "round";
context.lineJoin = "round";
context.beginPath();
for (const segment of pad.pending) {
context.moveTo(segment.fromX, segment.fromY);
context.lineTo(segment.toX, segment.toY);
}
context.stroke();
pad.pending = [];
}
}
Text {
anchors.centerIn: parent
visible: !pad.drawn
text: "Draw here to feel pointer speed"
color: Theme.fgMuted
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
}
MouseArea {
id: pointer
property real lastX: 0
property real lastY: 0
anchors.fill: parent
cursorShape: Qt.CrossCursor
// The page is a Flickable, which would otherwise take the drag off
// this and scroll instead of drawing.
preventStealing: true
onPressed: mouse => {
pointer.lastX = mouse.x;
pointer.lastY = mouse.y;
pad.drawn = true;
}
onPositionChanged: mouse => {
const segments = pad.pending;
segments.push({
fromX: pointer.lastX,
fromY: pointer.lastY,
toX: mouse.x,
toY: mouse.y
});
pad.pending = segments;
pointer.lastX = mouse.x;
pointer.lastY = mouse.y;
scribble.requestPaint();
}
}
SettingsButton {
anchors.right: parent.right
anchors.top: parent.top
anchors.margins: 8
visible: pad.drawn
text: "Clear"
onClicked: {
pad.wiping = true;
pad.drawn = false;
scribble.requestPaint();
}
}
}
Rectangle {
width: parent.width
height: 110
radius: Theme.cardRadius
color: Theme.alpha(Theme.bgDark, 0.55)
border.width: 1
border.color: Theme.alpha(Theme.fg, 0.08)
clip: true
Flickable {
id: strip
anchors.fill: parent
anchors.margins: 12
contentWidth: width
contentHeight: lines.implicitHeight
boundsBehavior: Flickable.StopAtBounds
Column {
id: lines
width: parent.width
spacing: 6
Repeater {
model: [
"Scroll here to feel scroll speed and direction.",
"Natural scrolling moves the content with your fingers.",
"The quick brown fox jumps over the lazy dog.",
"Line four.",
"Line five.",
"Line six.",
"Line seven — still scrolling.",
"Line eight.",
"Line nine.",
"Line ten, the bottom."
]
Text {
required property var modelData
width: lines.width
text: String(modelData)
color: Theme.fgDim
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
elide: Text.ElideRight
}
}
}
}
}
}