slint/examples/fancy_demo/main.slint
Tobias Hunger 4230ac2572
Update copyright information to reflect name change
Also run resue over the codebase and fix complaints from that tool.
2022-02-09 10:27:47 +01:00

502 lines
16 KiB
Text

// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
global Palette := {
property <color> window-background: #eee;
property <color> widget-background: #ddd;
property <color> widget-stroke: #888;
property <color> window-border: #ccc;
property <color> text-color: #666;
property <color> hyper-blue: #90d1ff;
}
//------ MdiWindow ----
MdiWindow := Rectangle {
property <string> title;
property <length> window-x <=> window.x;
property <length> window-y <=> window.y;
property <bool> is-open: true;
width: 100%;
height: 100%;
window := Rectangle {
background: Palette.window-background;
border-width: 2px;
border-color: Palette.window-border;
border-radius: 6px;
drop-shadow-blur: 25px;
drop-shadow-color: Palette.window-border;
property <length> open-width: l.preferred-width;
property <length> open-height: l.preferred-height;
width: l.preferred-width;
height: l.preferred-height;
states [
open when is-open : {
width: open-width;
height: open-height;
expand.angle: 0deg;
}
]
transitions [
in open : { animate width, height, expand.angle { duration: 150ms; easing: ease; } }
out open : { animate width, height, expand.angle { duration: 150ms; easing: ease; } }
]
clip: true;
TouchArea {}
l := VerticalLayout {
padding: window.border-width;
alignment: is-open ? stretch : start;
title_bar := TouchArea {
moved => {
if (pressed) {
window-x += mouse-x - pressed-x;
window-y += mouse-y - pressed-y;
}
}
HorizontalLayout {
padding: window.border-width;
spacing: window.border-width * 2;
expand := TouchArea {
width: 30px;
property <angle> angle: -90deg;
clicked => { is-open = !is-open; }
Path {
MoveTo { x: cos(expand.angle) * -1 - sin(expand.angle) * -1; y: sin(expand.angle) * -1 + cos(expand.angle) * -1; }
LineTo { x: cos(expand.angle) * 1 - sin(expand.angle) * -1; y: sin(expand.angle) * 1 + cos(expand.angle) * -1; }
LineTo { x: cos(expand.angle) * 0 - sin(expand.angle) * 1; y: sin(expand.angle) * 0 + cos(expand.angle) * 1; }
LineTo { x: cos(expand.angle) * -1 - sin(expand.angle) * -1; y: sin(expand.angle) * -1 + cos(expand.angle) * -1; }
stroke-width: window.border-width * (expand.has-hover ? 1.5 : 1);
stroke: parent.has-hover ? Palette.widget-stroke.darker(100%) : Palette.widget-stroke;
viewbox-x: -1.5;
viewbox-y: -1.5;
viewbox-height: 3;
viewbox-width: 3;
}
}
Text {
text: title;
horizontal-alignment: center;
color: Palette.text-color;
}
close_button := TouchArea {
width: 30px;
clicked => { root.visible = false; }
Path {
MoveTo { x: -1; y: -1; }
LineTo { x: 1; y: 1; }
MoveTo { x: -1; y: 1; }
LineTo { x: 1; y: -1; }
stroke-width: window.border-width * (close-button.has-hover ? 1.5 : 1);
stroke: parent.has-hover ? Palette.widget-stroke.darker(100%) : Palette.widget-stroke;
viewbox-x: -1.5;
viewbox-y: -1.5;
viewbox-height: 3;
viewbox-width: 3;
}
}
}
}
if is-open : VerticalLayout {
Rectangle {
height: window.border-width;
background: window.border-color;
}
@children
}
}
if is-open : resize-handle := TouchArea {
width: 20px;
height: width;
x: parent.width - width;
y: parent.height - height;
mouse-cursor: MouseCursor.nwse-resize;
Path {
MoveTo { x: 0; y: 1; }
LineTo { x: 1; y: 0; }
MoveTo { x: 0.4; y: 1; }
LineTo { x: 1; y: 0.4; }
MoveTo { x: 0.8; y: 1; }
LineTo { x: 1; y: 0.8; }
stroke-width: window.border-width;
stroke: Palette.window-border;
viewbox-height: 1.2; viewbox-width: 1.2;
}
moved => {
if (pressed) {
window.open-width = max(l.min-width, min(l.max-width, window.open-width + mouse-x - pressed-x));
window.open-height = max(l.min-height, min(l.max-height, window.open-height + mouse-y - pressed-y));
}
}
}
}
}
//------ Widgets ------
import {LineEdit, TextEdit, ComboBox, GridBox, VerticalBox, HorizontalBox, StyleMetrics} from "std-widgets.slint";
Label := Text {
color: Palette.text-color;
}
Button := TouchArea {
min-height: t.min-height;
min-width: t.min-width + 10px;
property text <=> t.text;
Rectangle {
border-width: 1.5px;
border-color: root.has-hover ? Palette.widget-stroke : transparent;
border-radius: 3px;
background: root.pressed ? Palette.widget-background.darker(30%) : Palette.widget-background;
t := Label {
width: 100%;
horizontal-alignment: center;
}
}
}
CheckBox := TouchArea {
property <bool> checked;
property text <=> t.text;
clicked => { checked = !checked; }
HorizontalLayout {
spacing: 5px;
VerticalLayout {
alignment: center;
Rectangle {
width: 20px;
height: 20px;
border-width: 1.5px;
border-color: root.has-hover ? Palette.widget-stroke : transparent;
border-radius: 3px;
background: root.pressed ? Palette.widget-background.darker(30%) : Palette.widget-background;
if checked : Path {
stroke: root.has-hover ? Palette.widget-stroke.darker(100%) : Palette.widget-stroke;
stroke-width: root.pressed ? 2.5px : 2px;
viewbox-height: 1; viewbox-width: 1;
MoveTo { x: 0.2; y: 0.5; }
LineTo { x: 0.5; y: 0.8; }
LineTo { x: 0.8; y: 0.2; }
}
}
}
t := Label {
}
}
}
RadioButton := TouchArea {
property <bool> checked;
property text <=> t.text;
HorizontalLayout {
spacing: 5px;
VerticalLayout {
alignment: center;
Rectangle {
width: 20px;
height: 20px;
border-width: 1.5px;
border-color: root.has-hover ? Palette.widget-stroke : transparent;
border-radius: width / 2;
background: root.pressed ? Palette.widget-background.darker(30%) : Palette.widget-background;
if checked : Rectangle {
background: root.has-hover ? Palette.widget-stroke.darker(100%) : Palette.widget-stroke;
border-radius: width / 2;
width: parent.width / 2;
height: parent.width / 2;
x: parent.width / 4;
y: parent.width / 4;
}
}
}
t := Label {
}
}
}
SelectableLabel := TouchArea {
min-height: t.min-height;
min-width: t.min-width + 10px;
property <bool> checked;
property text <=> t.text;
Rectangle {
border-width: 1.5px;
border-color: root.has-hover ? Palette.widget-stroke : transparent;
border-radius: 3px;
background:
root.checked ? Palette.hyper-blue :
root.pressed ? Palette.widget-background.darker(30%) :
root.has-hover ? Palette.widget-background : transparent;
t := Label {
width: 100%;
horizontal-alignment: center;
}
}
}
Slider := Rectangle {
property<float> maximum: 100;
property<float> minimum: 0;
property<float> value;
property<bool> enabled <=> touch.enabled;
callback changed(float);
min-height: 24px;
min-width: 100px;
horizontal-stretch: 1;
vertical-stretch: 0;
Rectangle {
width: parent.width;
height: parent.height / 2;
y: (parent.height - height) / 2;
border-radius: 2px;
background: Palette.widget-background;
}
handle := Rectangle {
width: height;
height: parent.height;
border-radius: height / 2;
border-color: touch.has-hover ? Palette.widget-stroke.darker(100%) : Palette.widget-stroke;
border-width: touch.pressed ? 4px : touch.has-hover ? 3px : 2px;
background: touch.pressed ? Palette.widget-background.darker(30%) : Palette.widget-background;
x: (root.width - handle.width) * max(0, min(1, (value - minimum)/(maximum - minimum)));
}
touch := TouchArea {
width: parent.width;
height: parent.height;
property <float> pressed-value;
pointer-event(event) => {
if (event.button == PointerEventButton.left && event.kind == PointerEventKind.down) {
pressed-value = root.value;
}
}
moved => {
if (enabled && pressed) {
value = max(root.minimum, min(root.maximum,
pressed-value + (touch.mouse-x - touch.pressed-x) * (maximum - minimum) / (root.width - handle.width)));
root.changed(value);
}
}
}
}
Hyperlink := Text {
color: Palette.hyper-blue;
TouchArea { mouse-cursor: pointer; }
property<string> link;
}
DragValue := TouchArea {
property <float> value;
min-height: t.min-height;
min-width: Math.max(t.min-width + 10px, 50px);
Rectangle {
border-width: 1.5px;
border-color: root.has-hover ? Palette.widget-stroke : transparent;
border-radius: 3px;
background: root.pressed ? Palette.widget-background.darker(30%) : Palette.widget-background;
t := Label {
width: 100%;
horizontal-alignment: center;
text: round(value);
}
}
moved => {
if (pressed) {
value = _pressed-value +(mouse-x - pressed-x) / 2px;
}
}
pointer-event(e) => {
if (e.kind == PointerEventKind.down) {
_pressed-value = value;
}
}
property <float> _pressed-value;
mouse-cursor: MouseCursor.ew-resize;
}
ProgressBar := Rectangle {
property <float> value;
min-height: 24px;
min-width: 100px;
background: StyleMetrics.textedit-background;
border-radius: height / 2;
Rectangle {
height: 100%;
width: height + (parent.width - height) * max(0, min(1, value / 100));
border-radius: height / 2;
background: Palette.hyper-blue;
}
Label {
height: 100%;
vertical-alignment: center;
x: height/2;
text: round(value) + "%";
}
}
//------ Demo apps -------
Gallery := GridBox {
callback unsel();
unsel => { r1.checked = false; r2.checked = false; r3.checked = false; }
Row {
Text { text: "Label:"; }
Label { text: "Welcome to the widget gallery!"; }
}
Row {
Text { text: "Hyperlink:"; }
Hyperlink { text: "Slint homepage"; link: "https://slint-ui.com"; }
}
Row {
Text { text: "TextEdit:"; }
LineEdit { placeholder-text: "WriteSomething here";}
}
Row {
Text { text: "Button:"; }
HorizontalLayout {
alignment: start;
Button { text: "Click me!"; clicked => { cb.checked = !cb.checked; } }
}
}
Row {
Text { text: "Checkbox:"; }
cb := CheckBox { text: "Checkbox"; }
}
Row {
Text { text: "RadioButton:"; }
HorizontalBox {
alignment: start;
r1 := RadioButton { text: "First"; clicked => { unsel(); r1.checked = true; } }
r2 := RadioButton { text: "Second"; clicked => { unsel(); r2.checked = true; } }
r3 := RadioButton { text: "Third"; clicked => { unsel(); r3.checked = true; } }
}
}
Row {
Text { text: "SelectableLabel:"; }
HorizontalBox {
alignment: start;
SelectableLabel { text: "First"; checked <=> r1.checked; clicked => { unsel(); r1.checked = true; } }
SelectableLabel { text: "Second"; checked <=> r2.checked; clicked => { unsel(); r2.checked = true; } }
SelectableLabel { text: "Third"; checked <=> r3.checked; clicked => { unsel(); r3.checked = true; } }
}
}
Row {
Text { text: "ComboBox:"; }
HorizontalBox {
alignment: start;
ComboBox {
model: ["First", "Second", "Third"];
selected => {
r1.checked = current-index == 0;
r2.checked = current-index == 1;
r3.checked = current-index == 2;
}
}
Label { text: "Take your pick"; }
}
}
Row {
Text { text: "Slider:"; }
sl := Slider { }
}
Row {
Text { text: "DragValue:"; }
HorizontalLayout {
alignment: start;
DragValue { value <=> sl.value; }
}
}
Row {
Text { text: "ProgressBar:"; }
ProgressBar { value <=> sl.value; }
}
Rectangle {}
}
TextEditDemo := VerticalLayout {
preferred-height: 150px;
preferred-width: 300px;
TextEdit {
text: "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum";
}
}
Demo := Window {
preferred-width: 1024px;
preferred-height: 800px;
background: white;
w1 := MdiWindow {
title: "🗄 Widget Gallery";
window-x: 30px;
window-y: 20px;
Gallery { }
}
w2 := MdiWindow {
visible: false;
title: "🗉 TextEdit";
window-x: 230px;
window-y: 520px;
TextEditDemo { }
}
side-panel := Rectangle {
border-color: resize-side-panel.has-hover ? Palette.window-border.darker(100%) : Palette.window-border;
border-width: 2px;
background: Palette.window-background;
x: parent.width - width;
width: side-panel-l.preferred-width;
height: 100%;
side-panel-l := VerticalBox {
alignment: start;
Label {
font-weight: 500;
text: "Slint Demos";
horizontal-alignment: center;
}
Rectangle { height: 2px; background: Palette.window-border; }
Label {
preferred-width: 0px;
text: "This is a demo which is based on the demo from the egui framework";
wrap: word-wrap;
horizontal-alignment: center;
}
Rectangle { height: 2px; background: Palette.window-border; }
CheckBox { text: w1.title; checked <=> w1.visible; }
CheckBox { text: w2.title; checked <=> w2.visible; }
}
resize-side-panel := TouchArea {
height: 100%;
width: 4px;
mouse-cursor: ew-resize;
moved => {
if (pressed) {
side-panel.width = max(side-panel-l.min-width, min(root.width, side-panel.width - (mouse-x - pressed-x)));
}
}
}
}
}