slint/tools/lsp/ui/components/resizer.slint

242 lines
9.5 KiB
Text

// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
// cSpell: ignore resizer
global ResizeState {
out property <length> handle-size: 8px;
}
component ResizeHandle inherits Rectangle {
in property <bool> show-handle: true;
in property <color> my-color: Colors.black;
in property <MouseCursor> mouse-cursor;
out property <bool> resizing <=> ta.pressed;
callback resize(/* width */ length, /* height */ length, /* done? */ bool);
callback resize-done(/* width */ length, /* height */ length);
// Internal!
in-out property <length> new-width;
in-out property <length> new-height;
in-out property <length> new-x;
in-out property <length> new-y;
width: ResizeState.handle-size;
height: ResizeState.handle-size;
background: root.show-handle ? Colors.white : Colors.transparent;
border-color: root.show-handle ? root.my-color : Colors.transparent;
border-width: 1px;
ta := TouchArea {
private property <length> x-offset: self.mouse-x - self.pressed-x;
private property <length> y-offset: self.mouse-y - self.pressed-y;
mouse-cursor <=> root.mouse-cursor;
moved() => {
root.resize(x-offset, y-offset, false);
}
pointer-event(event) => {
if event.button == PointerEventButton.left && event.kind == PointerEventKind.up {
root.resize(x-offset, y-offset, true);
}
}
}
}
export component Resizer {
in property <length> x-position;
in property <length> y-position;
in property <bool> is-resizable: true;
in property <bool> is-moveable: false;
in property <color> color: Colors.black;
out property <bool> resizing: n.resizing || ne.resizing || e.resizing || se.resizing || s.resizing || sw.resizing || w.resizing || nw.resizing;
out property <bool> moving: resize-area.moving;
out property <length> handle-size: ResizeState.handle-size;
callback resize(/* x */ length, /* y */ length, /* width */ length, /* height */ length, /* done */ bool);
callback can-move-to(/* x */ length, /* y */ length, /* mouse_x */ length, /* mouse_y */ length) -> bool;
callback move-to(/* x */ length, /* y */ length, /* mouse_x */ length, /* mouse_y */ length);
callback double-clicked(/* x */ length, /* y */ length, /* modifiers */ KeyboardModifiers);
// Private!
in-out property <length> top: self.y-position;
in-out property <length> bottom: self.y-position + self.height;
in-out property <length> left: self.x-position;
in-out property <length> right: self.x-position + self.width;
resize-area := Rectangle {
in-out property <bool> moving: false;
width <=> root.width;
height <=> root.height;
@children
if root.is-moveable: TouchArea {
private property <length> x-offset: self.mouse-x - self.pressed-x;
private property <length> y-offset: self.mouse-y - self.pressed-y;
private property <KeyboardModifiers> modifiers;
private property <bool> has-moved;
private property <bool> can-move-to;
mouse-cursor: MouseCursor.move;
double-clicked() => {
root.double-clicked(self.mouse-x, self.mouse-y, self.modifiers);
}
moved() => {
self.can-move-to = root.can-move-to(root.x-position + x-offset, root.y-position + y-offset, root.x-position + self.mouse-x, root.y-position + self.mouse-y);
self.has-moved = true;
}
pointer-event(event) => {
resize-area.moving = self.pressed;
self.modifiers = event.modifiers;
if self.has-moved && event.button == PointerEventButton.left && event.kind == PointerEventKind.up {
root.move-to(root.x-position + x-offset, root.y-position + y-offset, root.x-position + self.mouse-x, root.y-position + self.mouse-y);
self.has-moved = false;
}
}
states [
dragging-no-drop when self.has-moved && !self.can-move-to: {
mouse-cursor: MouseCursor.no-drop;
}
dragging-can-drop when self.has-moved && self.can-move-to: {
mouse-cursor: MouseCursor.copy;
}
normal when !self.has-moved: {
mouse-cursor: MouseCursor.default;
}
]
}
}
Rectangle {
visible: is-resizable;
n := ResizeHandle {
show-handle: false;
resize(x-offset, y-offset, done) => {
self.new-width = root.width;
self.new-height = Math.max(0px, y-offset * -1.0 + root.height);
self.new-x = root.left;
self.new-y = root.bottom - self.new-height;
root.resize(self.new-x, self.new-y, self.new-width, self.new-height, done);
}
mouse-cursor: MouseCursor.n-resize;
x: (root.handle-size / 2.0);
y: -(root.handle-size / 2.0);
width: root.width - root.handle-size;
}
ne := ResizeHandle {
my-color: root.color;
resize(x-offset, y-offset, done) => {
self.new-width = Math.max(0px, x-offset + root.width);
self.new-height = Math.max(0px, y-offset * -1.0 + root.height);
self.new-x = root.left;
self.new-y = root.bottom - self.new-height;
root.resize(self.new-x, self.new-y, self.new-width, self.new-height, done);
}
mouse-cursor: MouseCursor.ne-resize;
x: root.width - (root.handle-size / 2.0);
y: -(root.handle-size / 2.0);
}
e := ResizeHandle {
show-handle: false;
resize(x-offset, y-offset, done) => {
self.new-width = Math.max(0px, x-offset + root.width);
self.new-height = root.height;
self.new-x = root.left;
self.new-y = root.top;
root.resize(self.new-x, self.new-y, self.new-width, self.new-height, done);
}
mouse-cursor: MouseCursor.e-resize;
x: root.width - (root.handle-size / 2.0);
y: root.handle-size / 2.0;
height: root.height - root.handle-size;
}
se := ResizeHandle {
my-color: root.color;
resize(x-offset, y-offset, done) => {
self.new-width = Math.max(0px, x-offset + root.width);
self.new-height = Math.max(0px, y-offset + root.height);
self.new-x = root.left;
self.new-y = root.top;
root.resize(self.new-x, self.new-y, self.new-width, self.new-height, done);
}
mouse-cursor: MouseCursor.se-resize;
x: root.width - (root.handle-size / 2.0);
y: root.height - (root.handle-size / 2.0);
}
s := ResizeHandle {
show-handle: false;
resize(x-offset, y-offset, done) => {
self.new-width = root.width;
self.new-height = Math.max(0px, y-offset + root.height);
self.new-x = root.left;
self.new-y = root.top;
root.resize(self.new-x, self.new-y, self.new-width, self.new-height, done);
}
mouse-cursor: MouseCursor.s-resize;
x: root.handle-size / 2.0;
y: root.height - (root.handle-size / 2.0);
width: root.width - root.handle-size;
}
sw := ResizeHandle {
my-color: root.color;
resize(x-offset, y-offset, done) => {
self.new-width = Math.max(0px, x-offset * -1.0 + root.width);
self.new-height = Math.max(0px, y-offset + root.height);
self.new-x = root.right - self.new-width;
self.new-y = root.top;
root.resize(self.new-x, self.new-y, self.new-width, self.new-height, done);
}
mouse-cursor: MouseCursor.sw-resize;
x: -(root.handle-size / 2.0);
y: root.height - (root.handle-size / 2.0);
}
w := ResizeHandle {
show-handle: false;
resize(x-offset, y-offset, done) => {
self.new-width = Math.max(0px, x-offset * -1.0 + root.width);
self.new-height = root.height;
self.new-x = root.right - self.new-width;
self.new-y = root.top;
root.resize(self.new-x, self.new-y, self.new-width, self.new-height, done);
}
mouse-cursor: MouseCursor.w-resize;
x: -(root.handle-size / 2.0);
y: (root.handle-size / 2.0);
height: root.height - root.handle-size;
}
nw := ResizeHandle {
my-color: root.color;
resize(x-offset, y-offset, done) => {
self.new-width = Math.max(0px, x-offset * -1.0 + root.width);
self.new-height = Math.max(0px, y-offset * -1.0 + root.height);
self.new-x = root.right - self.new-width;
self.new-y = root.bottom - self.new-height;
root.resize(self.new-x, self.new-y, self.new-width, self.new-height, done);
}
mouse-cursor: MouseCursor.nw-resize;
x: -(root.handle-size / 2.0);
y: -(root.handle-size / 2.0);
}
}
}