slint/tools/lsp/ui/components/resizer.slint
Olivier Goffart cf2caaf223 live-preview: Fix resizing of elements
Not sure why commit 004ade9d44 removed
that code
2025-09-16 13:08:50 +02:00

268 lines
10 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);
// 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;
in property <color> fill-color: Colors.white;
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;
out property <bool> has-hover <=> ta.has-hover;
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 clicked(x: length, y: length, modifiers: KeyboardModifiers);
callback double-clicked(x: length, y: length, modifiers: KeyboardModifiers);
callback pointer-event(x: length, y: length, event: PointerEvent);
callback scroll-event(event: PointerScrollEvent) -> EventResult;
// 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
ta := TouchArea {
enabled: root.is-moveable;
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: false;
private property <bool> process-moves: false;
private property <bool> can-move-to: false;
mouse-cursor: MouseCursor.move;
double-clicked() => {
root.double-clicked(self.mouse-x, self.mouse-y, self.modifiers);
}
clicked() => {
root.clicked(self.mouse-x, self.mouse-y, self.modifiers);
}
moved() => {
if self.process-moves {
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 event.button == PointerEventButton.left && event.kind == PointerEventKind.down {
self.process-moves = true;
} else 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;
self.process-moves = false;
} else {
root.pointer-event(self.mouse-x, self.mouse-y, event);
}
}
scroll-event(event) => {
return root.scroll-event(event);
}
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;
background: root.fill-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;
background: root.fill-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;
background: root.fill-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;
background: root.fill-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);
}
}
}