mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-19 14:57:22 +00:00
268 lines
10 KiB
Text
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);
|
|
}
|
|
}
|
|
}
|