Run the syntax_updater on our widgets

This is commit is just the output of running the syntax updater on the
files in the internal/compiler/widgets directory.
No extra manual steps were done.

Note: In order to run the updater, I did a hack so that the updater wouldn't
choke on internal item used by the styles by commenting out the check in
ElementType::lookup_type_for_child_element
This commit is contained in:
Olivier Goffart 2023-01-10 18:01:56 +01:00 committed by Olivier Goffart
parent 8760262b60
commit 7947d44e59
27 changed files with 580 additions and 565 deletions

View file

@ -3,18 +3,18 @@
import { StyleMetrics, ScrollView } from "std-widgets-impl.slint";
export LineEditInner := Rectangle {
export component LineEditInner inherits Rectangle {
callback accepted(string);
callback edited(string);
property <string> placeholder-text;
property font-size <=> input.font-size;
property text <=> input.text;
property placeholder-color <=> placeholder.color;
property enabled <=> input.enabled;
property <bool> has-focus: input.has-focus;
property input-type <=> input.input-type;
property horizontal-alignment <=> input.horizontal-alignment;
property read-only <=> input.read-only;
in-out property <string> placeholder-text;
in-out property font-size <=> input.font-size;
in-out property text <=> input.text;
in-out property placeholder-color <=> placeholder.color;
in-out property enabled <=> input.enabled;
in-out property <bool> has-focus: input.has-focus;
in-out property input-type <=> input.input-type;
in-out property horizontal-alignment <=> input.horizontal-alignment;
in-out property read-only <=> input.read-only;
min-height: input.preferred-height;
min-width: max(50px, placeholder.min-width);
clip: true;
@ -26,15 +26,15 @@ export LineEditInner := Rectangle {
}
input := TextInput {
property <length> computed_x;
x: min(0px, max(parent.width - width, computed_x));
width: max(parent.width, preferred-width);
x: min(0px, max(parent.width - self.width, self.computed_x));
width: max(parent.width, self.preferred-width);
height: 100%;
color: enabled ? StyleMetrics.textedit-text-color : StyleMetrics.textedit-text-color-disabled;
color: self.enabled ? StyleMetrics.textedit-text-color : StyleMetrics.textedit-text-color-disabled;
cursor-position-changed(cpos) => {
if (cpos.x + computed_x < StyleMetrics.layout-padding) {
computed_x = - cpos.x + StyleMetrics.layout-padding;
} else if (cpos.x + computed_x > parent.width - StyleMetrics.layout-padding) {
computed_x = parent.width - cpos.x - StyleMetrics.layout-padding;
if (cpos.x + self.computed_x < StyleMetrics.layout-padding) {
self.computed_x = - cpos.x + StyleMetrics.layout-padding;
} else if (cpos.x + self.computed_x > parent.width - StyleMetrics.layout-padding) {
self.computed_x = parent.width - cpos.x - StyleMetrics.layout-padding;
}
}
accepted => { root.accepted(self.text); }
@ -44,7 +44,7 @@ export LineEditInner := Rectangle {
}
}
export TextEdit := ScrollView {
export component TextEdit inherits ScrollView {
in property <length> font-size <=> input.font-size;
in-out property <string> text <=> input.text;
has-focus: input.has-focus;
@ -58,36 +58,36 @@ export TextEdit := ScrollView {
horizontal-stretch: 1;
vertical-stretch: 1;
viewport-width: wrap == TextWrap.word-wrap ? root.visible-width : max(root.visible-width, input.preferred-width);
viewport-width: root.wrap == TextWrap.word-wrap ? root.visible-width : max(root.visible-width, input.preferred-width);
viewport-height: max(self.visible-height, input.preferred-height);
Rectangle {
background: enabled ? StyleMetrics.textedit-background : StyleMetrics.textedit-background-disabled;
background: root.enabled ? StyleMetrics.textedit-background : StyleMetrics.textedit-background-disabled;
}
input := TextInput {
enabled: true;
edited => { root.edited(self.text); }
color: enabled ? StyleMetrics.textedit-text-color : StyleMetrics.textedit-text-color-disabled;
color: self.enabled ? StyleMetrics.textedit-text-color : StyleMetrics.textedit-text-color-disabled;
single-line: false;
wrap: word-wrap;
cursor-position-changed(cpos) => {
if (cpos.x + viewport-x < StyleMetrics.layout-padding) {
viewport-x = min(0px, max(parent.visible-width - width, - cpos.x + StyleMetrics.layout-padding ));
} else if (cpos.x + viewport-x > parent.visible-width - StyleMetrics.layout-padding) {
viewport-x = min(0px, max(parent.visible-width - width, parent.visible-width - cpos.x - StyleMetrics.layout-padding ));
if (cpos.x + root.viewport-x < StyleMetrics.layout-padding) {
root.viewport-x = min(0px, max(parent.visible-width - self.width, - cpos.x + StyleMetrics.layout-padding ));
} else if (cpos.x + root.viewport-x > parent.visible-width - StyleMetrics.layout-padding) {
root.viewport-x = min(0px, max(parent.visible-width - self.width, parent.visible-width - cpos.x - StyleMetrics.layout-padding ));
}
if (cpos.y + viewport-y < StyleMetrics.layout-padding) {
viewport-y = min(0px, max(parent.visible-height - height, - cpos.y + StyleMetrics.layout-padding ));
} else if (cpos.y + viewport-y > parent.visible-height - StyleMetrics.layout-padding - 20px) {
if (cpos.y + root.viewport-y < StyleMetrics.layout-padding) {
root.viewport-y = min(0px, max(parent.visible-height - self.height, - cpos.y + StyleMetrics.layout-padding ));
} else if (cpos.y + root.viewport-y > parent.visible-height - StyleMetrics.layout-padding - 20px) {
// FIXME: font-height hardcoded to 20px
viewport-y = min(0px, max(parent.visible-height - height, parent.visible-height - cpos.y - StyleMetrics.layout-padding - 20px));
root.viewport-y = min(0px, max(parent.visible-height - self.height, parent.visible-height - cpos.y - StyleMetrics.layout-padding - 20px));
}
}
}
}
export AboutSlint := Rectangle {
export component AboutSlint inherits Rectangle {
VerticalLayout {
padding: 12px;
spacing: 8px;

View file

@ -3,18 +3,18 @@
import { StyleMetrics, Button } from "std-widgets-impl.slint";
export StandardButton := Button {
export component StandardButton inherits Button {
in property <StandardButtonKind> kind;
text:
kind == StandardButtonKind.ok ? "OK" :
kind == StandardButtonKind.cancel ? "Cancel" :
kind == StandardButtonKind.apply ? "Apply" :
kind == StandardButtonKind.close ? "Close" :
kind == StandardButtonKind.reset ? "Reset" :
kind == StandardButtonKind.help ? "Help" :
kind == StandardButtonKind.yes ? "Yes" :
kind == StandardButtonKind.no ? "No" :
kind == StandardButtonKind.abort ? "Abort" :
kind == StandardButtonKind.retry ? "Retry" :
kind == StandardButtonKind.ignore ? "Ignore" : "";
root.kind == StandardButtonKind.ok ? "OK" :
root.kind == StandardButtonKind.cancel ? "Cancel" :
root.kind == StandardButtonKind.apply ? "Apply" :
root.kind == StandardButtonKind.close ? "Close" :
root.kind == StandardButtonKind.reset ? "Reset" :
root.kind == StandardButtonKind.help ? "Help" :
root.kind == StandardButtonKind.yes ? "Yes" :
root.kind == StandardButtonKind.no ? "No" :
root.kind == StandardButtonKind.abort ? "Abort" :
root.kind == StandardButtonKind.retry ? "Retry" :
root.kind == StandardButtonKind.ignore ? "Ignore" : "";
}

View file

@ -3,8 +3,8 @@
import { ColorSchemeSelector } from "color-scheme.slint";
export global Palette := {
property<bool> dark-color-scheme: ColorSchemeSelector.dark-color-scheme;
export global Palette {
in-out property<bool> dark-color-scheme: ColorSchemeSelector.dark-color-scheme;
// The colors in light mode are default palette. In the
// Fluent UI Theme Designer they match the colors produced
@ -14,73 +14,73 @@ export global Palette := {
// and darkening the "white" and brightening the "neutralLight" variants for improved
// contrast (esp. on buttons).
property<color> themeDarker: #004578;
property<color> themeDark: #005a9e;
property<color> themeDarkAlt: #106ebe;
property<color> themePrimary: #0078d4;
property<color> themeSecondary: #2b88d8;
property<color> themeTertiary: #71afe5;
property<color> themeLight: #c7e0f4;
property<color> themeLighter: #deecf9;
property<color> themeLighterAlt: #eff6fc;
property<color> black: !dark-color-scheme ? #000000 : #f8f8f8;
property<color> blackTranslucent40: rgba(0,0,0,0.4);
property<color> neutralDark: !dark-color-scheme ? #201f1e : #f4f4f4;
property<color> neutralPrimary: !dark-color-scheme ? #323130 : #ffffff;
property<color> neutralPrimaryAlt: !dark-color-scheme ? #3b3a39 : #dadada;
property<color> neutralSecondary: !dark-color-scheme ? #605e5c : #d0d0d0;
property<color> neutralSecondaryAlt: #8a8886;
property<color> neutralTertiary: !dark-color-scheme ? #a19f9d : #c8c8c8;
property<color> neutralTertiaryAlt: !dark-color-scheme ? #c8c6c4 : #6d6d6d;
property<color> neutralQuaternary: #d2d0ce;
property<color> neutralQuaternaryAlt: !dark-color-scheme ? #e1dfdd : #484848;
property<color> neutralLight: !dark-color-scheme ? #edebe9 : #3f3f3f;
property<color> neutralLighter: !dark-color-scheme ? #f3f2f1 : #313131;
property<color> neutralLighterAlt: !dark-color-scheme ? #faf9f8 : #282828;
property<color> accent: #0078d4;
property<color> white: !dark-color-scheme ? #ffffff : #1f1f1f;
property<color> whiteTranslucent40: rgba(255,255,255,0.4);
property<color> yellowDark: #d29200;
property<color> yellow: #ffb900;
property<color> yellowLight: #fff100;
property<color> orange: #d83b01;
property<color> orangeLight: #ea4300;
property<color> orangeLighter: #ff8c00;
property<color> redDark: #a4262c;
property<color> red: #e81123;
property<color> magentaDark: #5c005c;
property<color> magenta: #b4009e;
property<color> magentaLight: #e3008c;
property<color> purpleDark: #32145a;
property<color> purple: #5c2d91;
property<color> purpleLight: #b4a0ff;
property<color> blueDark: #002050;
property<color> blueMid: #00188f;
property<color> blue: #0078d4;
property<color> blueLight: #00bcf2;
property<color> tealDark: #004b50;
property<color> teal: #008272;
property<color> tealLight: #00b294;
property<color> greenDark: #004b1c;
property<color> green: #107c10;
property<color> greenLight: #bad80a;
in-out property<color> themeDarker: #004578;
in-out property<color> themeDark: #005a9e;
in-out property<color> themeDarkAlt: #106ebe;
in-out property<color> themePrimary: #0078d4;
in-out property<color> themeSecondary: #2b88d8;
in-out property<color> themeTertiary: #71afe5;
in-out property<color> themeLight: #c7e0f4;
in-out property<color> themeLighter: #deecf9;
in-out property<color> themeLighterAlt: #eff6fc;
in-out property<color> black: !root.dark-color-scheme ? #000000 : #f8f8f8;
in-out property<color> blackTranslucent40: rgba(0,0,0,0.4);
in-out property<color> neutralDark: !root.dark-color-scheme ? #201f1e : #f4f4f4;
in-out property<color> neutralPrimary: !root.dark-color-scheme ? #323130 : #ffffff;
in-out property<color> neutralPrimaryAlt: !root.dark-color-scheme ? #3b3a39 : #dadada;
in-out property<color> neutralSecondary: !root.dark-color-scheme ? #605e5c : #d0d0d0;
in-out property<color> neutralSecondaryAlt: #8a8886;
in-out property<color> neutralTertiary: !root.dark-color-scheme ? #a19f9d : #c8c8c8;
in-out property<color> neutralTertiaryAlt: !root.dark-color-scheme ? #c8c6c4 : #6d6d6d;
in-out property<color> neutralQuaternary: #d2d0ce;
in-out property<color> neutralQuaternaryAlt: !root.dark-color-scheme ? #e1dfdd : #484848;
in-out property<color> neutralLight: !root.dark-color-scheme ? #edebe9 : #3f3f3f;
in-out property<color> neutralLighter: !root.dark-color-scheme ? #f3f2f1 : #313131;
in-out property<color> neutralLighterAlt: !root.dark-color-scheme ? #faf9f8 : #282828;
in-out property<color> accent: #0078d4;
in-out property<color> white: !root.dark-color-scheme ? #ffffff : #1f1f1f;
in-out property<color> whiteTranslucent40: rgba(255,255,255,0.4);
in-out property<color> yellowDark: #d29200;
in-out property<color> yellow: #ffb900;
in-out property<color> yellowLight: #fff100;
in-out property<color> orange: #d83b01;
in-out property<color> orangeLight: #ea4300;
in-out property<color> orangeLighter: #ff8c00;
in-out property<color> redDark: #a4262c;
in-out property<color> red: #e81123;
in-out property<color> magentaDark: #5c005c;
in-out property<color> magenta: #b4009e;
in-out property<color> magentaLight: #e3008c;
in-out property<color> purpleDark: #32145a;
in-out property<color> purple: #5c2d91;
in-out property<color> purpleLight: #b4a0ff;
in-out property<color> blueDark: #002050;
in-out property<color> blueMid: #00188f;
in-out property<color> blue: #0078d4;
in-out property<color> blueLight: #00bcf2;
in-out property<color> tealDark: #004b50;
in-out property<color> teal: #008272;
in-out property<color> tealLight: #00b294;
in-out property<color> greenDark: #004b1c;
in-out property<color> green: #107c10;
in-out property<color> greenLight: #bad80a;
}
export global StyleMetrics := {
property<length> layout-spacing: 8px;
property<length> layout-padding: 8px;
property<length> text-cursor-width: 2px;
property<brush> window-background: Palette.white;
property<color> default-text-color: Palette.neutralDark;
property<brush> textedit-background: Palette.white;
property<color> textedit-text-color: Palette.neutralPrimary;
property<brush> textedit-background-disabled: Palette.neutralLighter;
property<color> textedit-text-color-disabled: Palette.neutralTertiary;
property<bool> dark-color-scheme: Palette.dark-color-scheme;
export global StyleMetrics {
in-out property<length> layout-spacing: 8px;
in-out property<length> layout-padding: 8px;
in-out property<length> text-cursor-width: 2px;
in-out property<brush> window-background: Palette.white;
in-out property<color> default-text-color: Palette.neutralDark;
in-out property<brush> textedit-background: Palette.white;
in-out property<color> textedit-text-color: Palette.neutralPrimary;
in-out property<brush> textedit-background-disabled: Palette.neutralLighter;
in-out property<color> textedit-text-color-disabled: Palette.neutralTertiary;
in-out property<bool> dark-color-scheme: Palette.dark-color-scheme;
}
export Button := Rectangle {
export component Button inherits Rectangle {
callback clicked;
in property<string> text <=> text.text;
out property<bool> has-focus: fs.has-focus;
@ -97,9 +97,9 @@ export Button := Rectangle {
border-width: 1px;
border-radius: 2px;
border-color: !enabled ? Palette.neutralLighter : Palette.neutralSecondaryAlt;
background: !enabled ? Palette.neutralLighter
: (touch.pressed || checked) ? Palette.neutralLight
border-color: !root.enabled ? Palette.neutralLighter : Palette.neutralSecondaryAlt;
background: !root.enabled ? Palette.neutralLighter
: (touch.pressed || root.checked) ? Palette.neutralLight
: touch.has-hover ? Palette.neutralLighter
: Palette.white;
horizontal-stretch: 0;
@ -112,13 +112,13 @@ export Button := Rectangle {
padding-top: 3px;
padding-bottom: 3px;
if (icon.width > 0 && icon.height > 0): Image {
source <=> icon;
if (root.icon.width > 0 && root.icon.height > 0): Image {
source <=> root.icon;
width: 24px;
}
text := Text {
color: !enabled ? Palette.neutralTertiary : Palette.neutralDark;
color: !root.enabled ? Palette.neutralTertiary : Palette.neutralDark;
horizontal-alignment: center;
vertical-alignment: center;
font-weight: 600;
@ -135,6 +135,7 @@ export Button := Rectangle {
}
fs := FocusScope {
x:0;
width: 0px; // Do not react on clicks
enabled <=> root.enabled;
key-pressed(event) => {
@ -148,33 +149,33 @@ export Button := Rectangle {
Rectangle { // Focus rectangle
x: 3px;
y: x;
width: parent.width - 2*x;
height: parent.height - 2*y;
border-width: enabled && has-focus? 1px : 0px;
y: self.x;
width: parent.width - 2*self.x;
height: parent.height - 2*self.y;
border-width: root.enabled && root.has-focus? 1px : 0px;
border-color: Palette.black;
}
}
ScrollBar := Rectangle {
component ScrollBar inherits Rectangle {
background: Palette.white;
// border-color: Palette.button-background;
border-width: 1px;
property <bool> horizontal;
property<length> maximum;
property<length> page-size;
in-out property <bool> horizontal;
in-out property<length> maximum;
in-out property<length> page-size;
// this is always negative and bigger than -maximum
property<length> value;
in-out property<length> value;
handle := Rectangle {
width: !horizontal ? parent.width : maximum <= 0phx ? 0phx : parent.width * (page-size / (maximum + page-size));
height: horizontal ? parent.height : maximum <= 0phx ? 0phx : parent.height * (page-size / (maximum + page-size));
width: !root.horizontal ? parent.width : root.maximum <= 0phx ? 0phx : parent.width * (root.page-size / (root.maximum + root.page-size));
height: root.horizontal ? parent.height : root.maximum <= 0phx ? 0phx : parent.height * (root.page-size / (root.maximum + root.page-size));
border-radius: (horizontal ? self.height : self.width) / 2;
border-radius: (root.horizontal ? self.height : self.width) / 2;
background: touch-area.pressed ? Palette.themePrimary :
touch-area.has-hover ? Palette.themeSecondary : Palette.neutralTertiary;
x: !horizontal ? 0phx : (root.width - handle.width) * (-value / maximum);
y: horizontal ? 0phx : (root.height - handle.height) * (-value / maximum);
x: !root.horizontal ? 0phx : (root.width - handle.width) * (-root.value / root.maximum);
y: root.horizontal ? 0phx : (root.height - handle.height) * (-root.value / root.maximum);
}
touch-area := TouchArea {
width: parent.width;
@ -182,21 +183,21 @@ ScrollBar := Rectangle {
property <length> pressed-value;
pointer-event(event) => {
if (event.button == PointerEventButton.left && event.kind == PointerEventKind.down) {
pressed-value = -root.value;
self.pressed-value = -root.value;
}
}
moved => {
if (enabled && pressed) {
value = -max(0px, min(root.maximum, pressed-value + (
horizontal ? (touch-area.mouse-x - touch-area.pressed-x) * (maximum / (root.width - handle.width))
: (touch-area.mouse-y - touch-area.pressed-y) * (maximum / (root.height - handle.height))
if (self.enabled && self.pressed) {
root.value = -max(0px, min(root.maximum, self.pressed-value + (
root.horizontal ? (touch-area.mouse-x - touch-area.pressed-x) * (root.maximum / (root.width - handle.width))
: (touch-area.mouse-y - touch-area.pressed-y) * (root.maximum / (root.height - handle.height))
)));
}
}
}
}
export ScrollView := Rectangle {
export component ScrollView inherits Rectangle {
in-out property <length> viewport-width <=> fli.viewport-width;
in-out property <length> viewport-height <=> fli.viewport-height;
in-out property <length> viewport-x <=> fli.viewport-x;
@ -205,16 +206,16 @@ export ScrollView := Rectangle {
out property <length> visible-height <=> fli.height;
in property <bool> enabled: true;
// FIXME: remove. This property is currently set by the ListView and is used by the native style to draw the scrollbar differently when it has focus
property <bool> has-focus;
in-out property <bool> has-focus;
min-height: 50px;
min-width: 50px;
horizontal-stretch: 1;
vertical-stretch: 1;
border-radius: 2px;
border-width: !enabled ? 0px : has-focus ? 2px : 1px;
border-color: !enabled ? Palette.neutralLighter
: has-focus ? Palette.themeSecondary
border-width: !root.enabled ? 0px : root.has-focus ? 2px : 1px;
border-color: !root.enabled ? Palette.neutralLighter
: root.has-focus ? Palette.themeSecondary
: Palette.neutralPrimary;
fli := Flickable {

View file

@ -8,7 +8,7 @@ import { StandardButton } from "../common/standardbutton.slint";
import { StyleMetrics, ScrollView, Button, Palette } from "std-widgets-impl.slint";
export { StyleMetrics, ScrollView, Button, StandardButton, TextEdit, AboutSlint, AboutSlint as AboutSixtyFPS }
export CheckBox := Rectangle {
export component CheckBox inherits Rectangle {
callback toggled;
in property <string> text <=> text.text;
in-out property <bool> checked;
@ -20,7 +20,7 @@ export CheckBox := Rectangle {
accessible-label <=> text.text;
accessible-checkable: true;
accessible-checked <=> checked;
accessible-checked <=> root.checked;
accessible-role: checkbox;
HorizontalLayout {
@ -37,9 +37,9 @@ export CheckBox := Rectangle {
: touch.has-hover ? Palette.neutralLighter
: Palette.themePrimary;*/
border-color: checked ? background : !enabled ? Palette.neutralTertiaryAlt : Palette.neutralSecondaryAlt;
background: !checked ? Palette.white
: !enabled ? Palette.neutralTertiaryAlt
border-color: root.checked ? self.background : !root.enabled ? Palette.neutralTertiaryAlt : Palette.neutralSecondaryAlt;
background: !root.checked ? Palette.white
: !root.enabled ? Palette.neutralTertiaryAlt
: touch.has-hover || touch.pressed ? Palette.themeDark
: Palette.themePrimary;
animate background { duration: 250ms; easing: ease; }
@ -49,19 +49,19 @@ export CheckBox := Rectangle {
width: 20px;
height: 20px;
if (checked || touch.has-hover || touch.pressed) : Path {
if (root.checked || touch.has-hover || touch.pressed) : Path {
width: 66%;
height: 66%;
x: (parent.width - width) / 2;
y: (parent.height - height) / 2;
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
commands: "M.22.5.42.7.78.34.74.3.42.62.26.54z";
fill: checked ? Palette.white : Palette.neutralSecondaryAlt;
fill: root.checked ? Palette.white : Palette.neutralSecondaryAlt;
}
}
}
text := Text {
color: !enabled ? Palette.neutralTertiary : Palette.neutralDark;
color: !root.enabled ? Palette.neutralTertiary : Palette.neutralDark;
horizontal-alignment: left;
vertical-alignment: center;
vertical-stretch: 1;
@ -80,6 +80,7 @@ export CheckBox := Rectangle {
}
fs := FocusScope {
x:0;
width: 0px; // Do not react on clicks
enabled <=> root.enabled;
@ -94,33 +95,33 @@ export CheckBox := Rectangle {
Rectangle { // Focus rectangle
x: -3px;
y: x;
width: parent.width - 2*x;
height: parent.height - 2*y;
border-width: enabled && has-focus ? 1px : 0px;
y: self.x;
width: parent.width - 2*self.x;
height: parent.height - 2*self.y;
border-width: root.enabled && root.has-focus ? 1px : 0px;
border-color: Palette.black;
}
}
SpinBoxButton := Rectangle {
component SpinBoxButton inherits Rectangle {
callback clicked <=> touch.clicked;
property<string> text; // text and font-size are not used, but present in the other styles
property <length> font-size;
property<bool> enabled <=> touch.enabled;
background: !enabled ? transparent
in-out property<string> text; // text and font-size are not used, but present in the other styles
in-out property <length> font-size;
in-out property<bool> enabled <=> touch.enabled;
background: !root.enabled ? transparent
: touch.pressed ? Palette.neutralLight
: touch.has-hover ? Palette.neutralLighter
: Palette.white;
property <color> symbol-color: !enabled ? Palette.neutralTertiary
in-out property <color> symbol-color: !root.enabled ? Palette.neutralTertiary
: touch.pressed || touch.has-hover ? Palette.neutralPrimary
: Palette.neutralSecondary;
touch := TouchArea { }
}
export SpinBox := FocusScope {
export component SpinBox inherits FocusScope {
// FIXME: remove?
property <bool> checked;
in-out property <bool> checked;
in-out property <int> value;
in property <int> minimum;
in property <int> maximum: 100;
@ -133,13 +134,13 @@ export SpinBox := FocusScope {
vertical-stretch: 0;
accessible-role: spinbox;
accessible-value: value;
accessible-value-minimum: minimum;
accessible-value-maximum: maximum;
accessible-value-step: (maximum - minimum) / 100;
accessible-value: root.value;
accessible-value-minimum: root.minimum;
accessible-value-maximum: root.maximum;
accessible-value-step: (root.maximum - root.minimum) / 100;
Rectangle {
background: !enabled ? Palette.neutralLighter : Palette.white;
background: !root.enabled ? Palette.neutralLighter : Palette.white;
}
l := GridLayout {
@ -148,8 +149,8 @@ export SpinBox := FocusScope {
padding-bottom: 3px;
text := Text {
rowspan: 2;
text: value;
color: !enabled ? Palette.neutralTertiary : Palette.neutralDark;
text: root.value;
color: !root.enabled ? Palette.neutralTertiary : Palette.neutralDark;
horizontal-alignment: left;
vertical-alignment: center;
}
@ -161,8 +162,8 @@ export SpinBox := FocusScope {
commands: "M978.2,688.9l-84.2,82.1c-15.7,15.3-41.1,15.3-56.7,0l-341-304.2L162.6,764.5c-15.5,15.1-41,15.1-56.6,0l-84.3-82.1c-15.6-15.2-15.6-39.9,0-55.2l446.6-398.2c15.7-15.3,41-15.3,56.7,0l6.9,6.7l446.3,398.1C993.9,649,993.9,673.7,978.2,688.9z";
fill: parent.symbol-color;
height: 33%;
x: (parent.width - width) / 2;
y: (parent.height - height) / 2;
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
}
clicked => {
if (root.value < root.maximum) {
@ -178,8 +179,8 @@ export SpinBox := FocusScope {
commands: "M21.8,311.1l84.2-82.1c15.7-15.2,41-15.2,56.7,0l341.1,304.1l333.7-297.5c15.5-15.2,41-15.2,56.6,0l84.3,82.1c15.6,15.2,15.6,40,0,55.2L531.7,771c-15.7,15.3-41,15.3-56.7,0l-6.9-6.7L21.8,366.3C6.1,351,6.1,326.3,21.8,311.1z";
fill: parent.symbol-color;
height: 33%;
x: (parent.width - width) / 2;
y: (parent.height - height) / 2;
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
}
clicked => {
if (root.value > root.minimum) {
@ -192,23 +193,23 @@ export SpinBox := FocusScope {
}
Rectangle {
x: enabled && has-focus ? -2px : 0px;
y: x;
width: parent.width - 2*x;
height: parent.height - 2*y;
x: root.enabled && root.has-focus ? -2px : 0px;
y: self.x;
width: parent.width - 2*self.x;
height: parent.height - 2*self.y;
border-radius: 2px;
border-width: !enabled ? 0px : has-focus ? 3px : 1px;
border-color: !enabled ? Palette.neutralLighter
: has-focus ? Palette.themeSecondary
border-width: !root.enabled ? 0px : root.has-focus ? 3px : 1px;
border-color: !root.enabled ? Palette.neutralLighter
: root.has-focus ? Palette.themeSecondary
: Palette.neutralDark;
}
key-pressed(event) => {
if (enabled && event.text == Key.UpArrow && value < maximum) {
value += 1;
if (root.enabled && event.text == Key.UpArrow && root.value < root.maximum) {
root.value += 1;
accept
} else if (enabled && event.text == Key.DownArrow && value > minimum) {
value -= 1;
} else if (root.enabled && event.text == Key.DownArrow && root.value > root.minimum) {
root.value -= 1;
accept
} else {
reject
@ -216,7 +217,7 @@ export SpinBox := FocusScope {
}
}
export Slider := Rectangle {
export component Slider inherits Rectangle {
in property<float> maximum: 100;
in property<float> minimum: 0;
in-out property<float> value;
@ -230,29 +231,29 @@ export Slider := Rectangle {
vertical-stretch: 0;
accessible-role: slider;
accessible-value: value;
accessible-value-minimum: minimum;
accessible-value-maximum: maximum;
accessible-value-step: (maximum - minimum) / 100;
accessible-value: root.value;
accessible-value-minimum: root.minimum;
accessible-value-maximum: root.maximum;
accessible-value-step: (root.maximum - root.minimum) / 100;
Rectangle {
width: parent.width - parent.min-height;
x: parent.height / 2;
height: parent.min-height / 4;
y: (parent.height - height) / 2;
border-radius: height/2;
y: (parent.height - self.height) / 2;
border-radius: self.height/2;
background: !root.enabled ? Palette.neutralLighter
: touch.has-hover ? Palette.themeLight
: Palette.neutralTertiaryAlt;
}
Rectangle {
width: (parent.width - parent.min-height) * ((value - minimum) / (maximum - minimum));
width: (parent.width - parent.min-height) * ((root.value - root.minimum) / (root.maximum - root.minimum));
x: parent.height / 2;
height: parent.min-height / 4;
y: (parent.height - height) / 2;
border-radius: height/2;
y: (parent.height - self.height) / 2;
border-radius: self.height/2;
background: !root.enabled ? Palette.neutralTertiary
: touch.has-hover ? Palette.themeSecondary
: Palette.neutralSecondary;
@ -260,16 +261,16 @@ export Slider := Rectangle {
handle := Rectangle {
property<length> border: 3px;
width: height;
height: parent.height - 2 * border;
width: self.height;
height: parent.height - 2 * self.border;
border-width: 3px;
border-radius: height / 2;
border-radius: self.height / 2;
border-color: !root.enabled ? Palette.neutralTertiaryAlt
: touch.has-hover ? Palette.themePrimary
: Palette.neutralSecondary;
background: Palette.white;
x: (root.width - handle.width) * (value - minimum)/(maximum - minimum);
y: border;
x: (root.width - handle.width) * (root.value - root.minimum)/(root.maximum - root.minimum);
y: self.border;
}
touch := TouchArea {
width: parent.width;
@ -277,27 +278,28 @@ export Slider := Rectangle {
property <float> pressed-value;
pointer-event(event) => {
if (event.button == PointerEventButton.left && event.kind == PointerEventKind.down) {
pressed-value = root.value;
self.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);
if (self.enabled && self.pressed) {
root.value = max(root.minimum, min(root.maximum,
self.pressed-value + (touch.mouse-x - touch.pressed-x) * (root.maximum - root.minimum) / (root.width - handle.width)));
root.changed(root.value);
}
}
}
fs := FocusScope {
x:0;
width: 0px;
key-pressed(event) => {
if (enabled && event.text == Key.RightArrow) {
value = Math.min(value + 1, maximum);
if (self.enabled && event.text == Key.RightArrow) {
root.value = Math.min(root.value + 1, root.maximum);
accept
} else if (enabled && event.text == Key.LeftArrow) {
value = Math.max(value - 1, minimum);
} else if (self.enabled && event.text == Key.LeftArrow) {
root.value = Math.max(root.value - 1, root.minimum);
accept
} else {
reject
@ -306,14 +308,14 @@ export Slider := Rectangle {
}
Rectangle { // Focus rectangle
border-width: enabled && has-focus ? 1px : 0px;
border-width: root.enabled && root.has-focus ? 1px : 0px;
border-color: Palette.black;
}
}
export GroupBox := VerticalLayout {
export component GroupBox inherits VerticalLayout {
in property <string> title <=> label.text;
in property<bool> enabled: true;
spacing: 8px;
@ -321,7 +323,7 @@ export GroupBox := VerticalLayout {
padding-bottom: 8px;
label := Text {
vertical-stretch: 0;
color: !enabled ? Palette.neutralTertiary : Palette.neutralDark;
color: !root.enabled ? Palette.neutralTertiary : Palette.neutralDark;
font-weight: 600;
}
Rectangle {
@ -332,44 +334,44 @@ export GroupBox := VerticalLayout {
}
}
export TabWidgetImpl := Rectangle {
property <length> content-x: 0;
property <length> content-y: tabbar-preferred-height;
property <length> content-height: height - tabbar-preferred-height;
property <length> content-width: width;
property <length> tabbar-x: 0;
property <length> tabbar-y: 0;
property <length> tabbar-height: tabbar-preferred-height;
property <length> tabbar-width: width;
export component TabWidgetImpl inherits Rectangle {
in-out property <length> content-x: 0;
in-out property <length> content-y: root.tabbar-preferred-height;
in-out property <length> content-height: root.height - root.tabbar-preferred-height;
in-out property <length> content-width: root.width;
in-out property <length> tabbar-x: 0;
in-out property <length> tabbar-y: 0;
in-out property <length> tabbar-height: root.tabbar-preferred-height;
in-out property <length> tabbar-width: root.width;
property <length> tabbar-preferred-height;
property <length> tabbar-preferred-width;
property <length> content-min-height;
property <length> content-min-width;
property <int> current-index;
property <int> current-focused;
in-out property <length> tabbar-preferred-height;
in-out property <length> tabbar-preferred-width;
in-out property <length> content-min-height;
in-out property <length> content-min-width;
in-out property <int> current-index;
in-out property <int> current-focused;
preferred-width: content-min-width;
min-width: max(content-min-width, tabbar-preferred-width);
preferred-height: content-min-height + tabbar-preferred-height;
min-height: content-min-height + tabbar-preferred-height;
preferred-width: root.content-min-width;
min-width: max(root.content-min-width, root.tabbar-preferred-width);
preferred-height: root.content-min-height + root.tabbar-preferred-height;
min-height: root.content-min-height + root.tabbar-preferred-height;
}
export TabImpl := Rectangle {
property<string> title <=> t.text;
export component TabImpl inherits Rectangle {
in-out property<string> title <=> t.text;
//property<image> icon;
property<bool> enabled: true;
property<bool> has-focus: current-focused == tab-index;
property<bool> pressed;
property<int> current; // The currently selected tab
property<int> current-focused; // The currently focused tab
property<int> tab-index; // The index of this tab
property<int> num-tabs; // The total number of tabs
in-out property<bool> enabled: true;
in-out property<bool> has-focus: root.current-focused == root.tab-index;
in-out property<bool> pressed;
in-out property<int> current; // The currently selected tab
in-out property<int> current-focused; // The currently focused tab
in-out property<int> tab-index; // The index of this tab
in-out property<int> num-tabs; // The total number of tabs
min-height: t.preferred-height + 16px;
preferred-width: t.preferred-width + 16px;
background: !enabled ? Palette.neutralLighter
background: !root.enabled ? Palette.neutralLighter
: touch.pressed ? Palette.neutralLight
: touch.has-hover ? Palette.neutralLighter
: Palette.white;
@ -377,12 +379,12 @@ export TabImpl := Rectangle {
vertical-stretch: 0;
accessible-role: tab;
accessible-label <=> title;
accessible-label <=> root.title;
touch := TouchArea {
enabled <=> root.enabled;
clicked => {
current = tab-index;
root.current = root.tab-index;
}
}
t := Text {
@ -390,7 +392,7 @@ export TabImpl := Rectangle {
height: parent.height;
vertical-alignment: center;
horizontal-alignment: center;
color: !enabled ? Palette.neutralTertiary : Palette.neutralPrimary;
color: !root.enabled ? Palette.neutralTertiary : Palette.neutralPrimary;
font-weight: root.current == root.tab-index ? 600 : 500;
}
@ -399,21 +401,21 @@ export TabImpl := Rectangle {
width: touch.has-hover && root.current == root.tab-index ? parent.width : parent.width - 16px;
animate width { duration: 250ms; easing: ease-out; }
background: root.current == root.tab-index ? Palette.themeSecondary : transparent;
y: parent.height - height;
x: (parent.width - width) / 2;
y: parent.height - self.height;
x: (parent.width - self.width) / 2;
}
Rectangle { // Focus Rectangle
border-width: enabled && has-focus ? 1px : 0px;
border-width: root.enabled && root.has-focus ? 1px : 0px;
border-color: Palette.black;
}
}
export TabBarImpl := Rectangle {
export component TabBarImpl inherits Rectangle {
// injected properties:
property<int> current; // The currently selected tab
property<int> current-focused: fs.has-focus ? fs.focused-tab : -1; // The currently focused tab
property<int> num-tabs; // The total number of tabs
in-out property<int> current; // The currently selected tab
in-out property<int> current-focused: fs.has-focus ? fs.focused-tab : -1; // The currently focused tab
in-out property<int> num-tabs; // The total number of tabs
HorizontalLayout {
spacing: 8px;
@ -422,23 +424,24 @@ export TabBarImpl := Rectangle {
}
accessible-role: tab;
accessible-delegate-focus: current-focused >= 0 ? current-focused : current;
accessible-delegate-focus: root.current-focused >= 0 ? root.current-focused : root.current;
fs := FocusScope {
x:0;
width: 0px; // Do not react on clicks
property<int> focused-tab: 0;
key-pressed(event) => {
if (event.text == "\n") {
current = current-focused;
root.current = root.current-focused;
return accept;
}
if (event.text == Key.LeftArrow) {
focused-tab = Math.max(focused-tab - 1, 0);
self.focused-tab = Math.max(self.focused-tab - 1, 0);
return accept;
}
if (event.text == Key.RightArrow) {
focused-tab = Math.min(focused-tab + 1, num-tabs - 1);
self.focused-tab = Math.min(self.focused-tab + 1, root.num-tabs - 1);
return accept;
}
return reject;
@ -446,7 +449,7 @@ export TabBarImpl := Rectangle {
key-released(event) => {
if (event.text == " ") {
current = current-focused;
root.current = root.current-focused;
return accept;
}
return reject;
@ -454,9 +457,9 @@ export TabBarImpl := Rectangle {
}
}
export TabWidget := TabWidget {}
export component TabWidget inherits TabWidget {}
export LineEdit := Rectangle {
export component LineEdit inherits Rectangle {
in property <length> font-size <=> inner.font-size;
in-out property <string> text <=> inner.text;
in property <string> placeholder-text <=> inner.placeholder-text;
@ -474,11 +477,11 @@ export LineEdit := Rectangle {
vertical-stretch: 0;
min-height: max(32px, l.min-height);
background: !enabled ? Palette.neutralLighter : Palette.white;
background: !root.enabled ? Palette.neutralLighter : Palette.white;
border-radius: 2px;
border-width: !enabled ? 0px : has-focus ? 2px : 1px;
border-color: !enabled ? Palette.neutralLighter
: has-focus ? Palette.themeSecondary
border-width: !root.enabled ? 0px : root.has-focus ? 2px : 1px;
border-color: !root.enabled ? Palette.neutralLighter
: root.has-focus ? Palette.themeSecondary
: Palette.neutralPrimary;
l := HorizontalLayout {
@ -487,19 +490,19 @@ export LineEdit := Rectangle {
padding-top: 3px;
padding-bottom: 3px;
inner := LineEditInner {
placeholder-color: !enabled ? Palette.neutralTertiary : Palette.neutralSecondary;
placeholder-color: !self.enabled ? Palette.neutralTertiary : Palette.neutralSecondary;
}
}
}
export ListView := ScrollView {
export component ListView inherits ScrollView {
@children
}
StandardListViewBase := ListView {
property<[StandardListViewItem]> model;
property<int> current-item: -1;
for item[idx] in model : Rectangle {
component StandardListViewBase inherits ListView {
in-out property<[StandardListViewItem]> model;
in-out property<int> current-item: -1;
for item[idx] in root.model : Rectangle {
l := HorizontalLayout {
padding: 8px;
spacing: 0px;
@ -513,19 +516,19 @@ StandardListViewBase := ListView {
touch := TouchArea {
width: parent.width;
height: parent.height;
clicked => { current-item = idx; }
clicked => { root.current-item = idx; }
}
}
}
export StandardListView := StandardListViewBase {
export component StandardListView inherits StandardListViewBase {
FocusScope {
key-pressed(event) => {
if (event.text == Key.UpArrow && current-item > 0) {
current-item -= 1;
if (event.text == Key.UpArrow && root.current-item > 0) {
root.current-item -= 1;
return accept;
} else if (event.text == Key.DownArrow && current-item + 1 < model.length) {
current-item += 1;
} else if (event.text == Key.DownArrow && root.current-item + 1 < root.model.length) {
root.current-item += 1;
return accept;
}
reject
@ -533,24 +536,24 @@ export StandardListView := StandardListViewBase {
}
}
export ComboBox := FocusScope {
export component ComboBox inherits FocusScope {
in property <[string]> model;
in-out property <int> current-index : 0;
in-out property <string> current-value: model[current-index];
in-out property <string> current-value: root.model[root.current-index];
//property <bool> is-open: false;
callback selected(string);
accessible-role: combobox;
accessible-value <=> current-value;
accessible-value <=> root.current-value;
key-pressed(event) => {
if (event.text == Key.UpArrow) {
current-index = Math.max(current-index - 1, 0);
current-value = model[current-index];
root.current-index = Math.max(root.current-index - 1, 0);
root.current-value = root.model[root.current-index];
return accept;
} else if (event.text == Key.DownArrow) {
current-index = Math.min(current-index + 1, model.length - 1);
current-value = model[current-index];
root.current-index = Math.min(root.current-index + 1, root.model.length - 1);
root.current-value = root.model[root.current-index];
return accept;
// PopupWindow can not get hidden again at this time, so do not allow to pop that up.
// } else if (event.text == Key.Return) {
@ -561,11 +564,11 @@ export ComboBox := FocusScope {
}
Rectangle {
background: !enabled ? Palette.neutralLighter : Palette.white;
background: !root.enabled ? Palette.neutralLighter : Palette.white;
border-radius: 2px;
border-width: !enabled ? 0px : has-focus ? 3px : 1px;
border-color: !enabled ? Palette.neutralLighter
: has-focus ? Palette.themeSecondary
border-width: !root.enabled ? 0px : root.has-focus ? 3px : 1px;
border-color: !root.enabled ? Palette.neutralLighter
: root.has-focus ? Palette.themeSecondary
: Palette.neutralPrimary;
}
@ -586,7 +589,7 @@ export ComboBox := FocusScope {
horizontal-alignment: left;
vertical-alignment: center;
horizontal-stretch: 1;
color: !enabled ? Palette.neutralTertiary
color: !root.enabled ? Palette.neutralTertiary
: root.has-focus || touch.has-hover ? Palette.neutralPrimary
: Palette.neutralSecondary;
min-width: 0;
@ -594,8 +597,8 @@ export ComboBox := FocusScope {
Rectangle {
width: 25px;
Path {
x: (parent.width - width) / 2;
y: (parent.height - height) / 2;
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
height: 8px;
width: 25px;
commands: "M.22.4.5.64.78.4.74.36.5.6.26.36z";
@ -614,6 +617,7 @@ export ComboBox := FocusScope {
}
popup := PopupWindow {
x:0;
y: root.height;
width: root.width;
Rectangle {
@ -649,15 +653,15 @@ export ComboBox := FocusScope {
}
}
export VerticalBox := VerticalLayout {
export component VerticalBox inherits VerticalLayout {
spacing: StyleMetrics.layout-spacing;
padding: StyleMetrics.layout-padding;
}
export HorizontalBox := HorizontalLayout {
export component HorizontalBox inherits HorizontalLayout {
spacing: StyleMetrics.layout-spacing;
padding: StyleMetrics.layout-padding;
}
export GridBox := GridLayout {
export component GridBox inherits GridLayout {
spacing: StyleMetrics.layout-spacing;
padding: StyleMetrics.layout-padding;
}

View file

@ -1,6 +1,6 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
export global ColorSchemeSelector := {
property<bool> dark-color-scheme: true;
export global ColorSchemeSelector {
in-out property<bool> dark-color-scheme: true;
}

View file

@ -1,6 +1,6 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
export global ColorSchemeSelector := {
property<bool> dark-color-scheme: false;
export global ColorSchemeSelector {
in-out property<bool> dark-color-scheme: false;
}

View file

@ -1,6 +1,6 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
export global ColorSchemeSelector := {
property<bool> dark-color-scheme: SlintInternal.dark-color-scheme;
export global ColorSchemeSelector {
in-out property<bool> dark-color-scheme: SlintInternal.dark-color-scheme;
}

View file

@ -3,7 +3,7 @@
import { md } from "md.slint";
export Ripple := Rectangle {
export component Ripple inherits Rectangle {
in property<length> ripple-x;
in property<length> ripple-y;
in property<bool> active;
@ -11,27 +11,26 @@ export Ripple := Rectangle {
in property<brush> ripple-color <=> circle.background;
circle := Rectangle {
x: root.ripple-x - width / 2;
y: root.ripple-y - width / 2;
height: width;
border-radius: width / 2;
x: root.ripple-x - self.width / 2;
y: root.ripple-y - self.width / 2;
height: self.width;
border-radius: self.width / 2;
}
states [
active when root.active && root.has-effect: {
circle.width: root.width * 2 * 1.4142;
in {
animate circle.width { duration: 2s; easing: ease-out; }
}
}
]
transitions [
in active : {
animate circle.width { duration: 2s; easing: ease-out; }
}
]
}
// A touch area that also represents a visual state.
export StateLayer := TouchArea {
export component StateLayer inherits TouchArea {
in property<bool> focusable;
in property<brush> selection-background;
in property<brush> ripple-color;
@ -63,6 +62,7 @@ export StateLayer := TouchArea {
}
fs := FocusScope {
x:0;
width: 0px; // Do not react on clicks
enabled: root.enabled && root.focusable;
@ -81,7 +81,7 @@ export StateLayer := TouchArea {
}
checked when root.checked: {
ripple.opacity: 1.0;
ripple.background: selection-background;
ripple.background: root.selection-background;
}
hover when root.has-hover: {
ripple.opacity: 0.08;

View file

@ -4,15 +4,15 @@
import { StyleMetrics } from "std-widgets-impl.slint";
export VerticalBox := VerticalLayout {
export component VerticalBox inherits VerticalLayout {
spacing: StyleMetrics.layout-spacing;
padding: StyleMetrics.layout-padding;
}
export HorizontalBox := HorizontalLayout {
export component HorizontalBox inherits HorizontalLayout {
spacing: StyleMetrics.layout-spacing;
padding: StyleMetrics.layout-padding;
}
export GridBox := GridLayout {
export component GridBox inherits GridLayout {
spacing: StyleMetrics.layout-spacing;
padding: StyleMetrics.layout-padding;
}

View file

@ -5,7 +5,7 @@
import { ColorSchemeSelector } from "color-scheme.slint";
// helper to create material design token like path md.sys.colors.
struct Color := {
struct Color {
background: color,
surface: color,
surface-variant: color,
@ -23,20 +23,20 @@ struct Color := {
}
// typo settings
struct Label := {
struct Label {
size: relative-font-size,
weight: int
}
// helper to create material design token like path md.sys.elevation.
struct Elevation := {
struct Elevation {
level0: length,
level1: length,
level2: length
}
// helper to create material design token like path md.sys.typescale.
struct Typescale := {
struct Typescale {
label-large: Label,
label-medium: Label,
body-large: Label,
@ -45,33 +45,33 @@ struct Typescale := {
}
// helper to create material design token like path md.sys.
struct Sys := {
struct Sys {
color: Color,
elevation: Elevation,
typescale: Typescale
}
// Material Desigin v3 style defintions.
export global md := {
property<bool> dark-color-scheme: ColorSchemeSelector.dark-color-scheme;
export global md {
in-out property<bool> dark-color-scheme: ColorSchemeSelector.dark-color-scheme;
property<Sys> sys: {
in-out property<Sys> sys: {
color: {
background: !dark-color-scheme ? #FFFBFE : #1C1B1F,
surface: !dark-color-scheme ? #FFFBFE : #1C1B1F,
surface-variant: !dark-color-scheme ? #E7E0EC.darker(0.2) : #49454F,
on-surface: !dark-color-scheme ? #1C1B1F : #E6E1E5,
on-surface-variant: !dark-color-scheme ? #49454E : #CAC4D0,
surface-tint: !dark-color-scheme ? #6750A4 : #D0BCFF,
primary: !dark-color-scheme ? #6750A4 : #D0BCFF,
primary-ripple: !dark-color-scheme ? #D0BCFF : #6750A4,
on-primary: !dark-color-scheme ? #FFFFFF : #371E73,
background: !root.dark-color-scheme ? #FFFBFE : #1C1B1F,
surface: !root.dark-color-scheme ? #FFFBFE : #1C1B1F,
surface-variant: !root.dark-color-scheme ? #E7E0EC.darker(0.2) : #49454F,
on-surface: !root.dark-color-scheme ? #1C1B1F : #E6E1E5,
on-surface-variant: !root.dark-color-scheme ? #49454E : #CAC4D0,
surface-tint: !root.dark-color-scheme ? #6750A4 : #D0BCFF,
primary: !root.dark-color-scheme ? #6750A4 : #D0BCFF,
primary-ripple: !root.dark-color-scheme ? #D0BCFF : #6750A4,
on-primary: !root.dark-color-scheme ? #FFFFFF : #371E73,
shadow: #000000,
outline: !dark-color-scheme ? #79747E : #938F99,
outline-variant: !dark-color-scheme ? #C4C7C5 : #444746,
secondary-container: !dark-color-scheme ? #E8DEF8 : #4A4458,
on-secondary-container: !dark-color-scheme ? #1E192B : #E8DEF8,
secondary-ripple: !dark-color-scheme ? #fffc : #000000,
outline: !root.dark-color-scheme ? #79747E : #938F99,
outline-variant: !root.dark-color-scheme ? #C4C7C5 : #444746,
secondary-container: !root.dark-color-scheme ? #E8DEF8 : #4A4458,
on-secondary-container: !root.dark-color-scheme ? #1E192B : #E8DEF8,
secondary-ripple: !root.dark-color-scheme ? #fffc : #000000,
},
elevation: {

View file

@ -9,19 +9,19 @@ import { md } from "md.slint";
export { Button, CheckBox, ScrollView }
export global StyleMetrics := {
property<length> layout-spacing: 8px;
property<length> layout-padding: 8px;
property<length> text-cursor-width: 2px;
export global StyleMetrics {
in-out property<length> layout-spacing: 8px;
in-out property<length> layout-padding: 8px;
in-out property<length> text-cursor-width: 2px;
property<color> default-text-color: md.sys.color.on-surface;
property<brush> textedit-background: transparent;
property<color> textedit-text-color: md.sys.color.on-surface;
property<brush> textedit-background-disabled: transparent;
property<color> textedit-text-color-disabled: md.sys.color.on-surface;
property<bool> dark-color-scheme: md.dark-color-scheme;
in-out property<color> default-text-color: md.sys.color.on-surface;
in-out property<brush> textedit-background: transparent;
in-out property<color> textedit-text-color: md.sys.color.on-surface;
in-out property<brush> textedit-background-disabled: transparent;
in-out property<color> textedit-text-color-disabled: md.sys.color.on-surface;
in-out property<bool> dark-color-scheme: md.dark-color-scheme;
property <string> default-font-family: "Roboto";
in-out property <string> default-font-family: "Roboto";
property<brush> window-background: md.sys.color.background;
in-out property<brush> window-background: md.sys.color.background;
}

View file

@ -5,7 +5,7 @@ import { StateLayer } from "comp-state-layer.slint";
import { md } from "md.slint";
// Default button widget with Material Design Filled Button look and feel.
export Button := Rectangle {
export component Button inherits Rectangle {
callback clicked;
in-out property<string> text <=> label.text;
@ -54,8 +54,8 @@ export Button := Rectangle {
padding-right: 24px;
spacing: 8px;
if (icon.width > 0 && icon.height > 0): Image {
source <=> icon;
if (root.icon.width > 0 && root.icon.height > 0): Image {
source <=> root.icon;
width: 24px;
opacity: label.opacity;
}

View file

@ -5,7 +5,7 @@
import { md } from "md.slint";
// Selection control that can be toggled between checked und unchecked by click.
export CheckBox := Rectangle {
export component CheckBox inherits Rectangle {
callback toggled;
in property <string> text <=> label.text;
@ -16,7 +16,7 @@ export CheckBox := Rectangle {
accessible-label <=> label.text;
accessible-checkable: true;
accessible-checked <=> checked;
accessible-checked <=> root.checked;
accessible-role: checkbox;
layout := HorizontalLayout {
@ -37,19 +37,19 @@ export CheckBox := Rectangle {
state-layer := Rectangle {
width: 40px;
height: 40px;
x: (parent.width - width) / 2;
y: (parent.height - height) / 2;
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
opacity: 0;
background: md.sys.color.primary;
border-radius: 20px;
animate opacity { duration: 300ms; easing: ease; }
}
if (checked) : Path {
if (root.checked) : Path {
width: 66%;
height: 66%;
x: (parent.width - width) / 2;
y: (parent.height - height) / 2;
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
commands: "M18.9 35.7 7.7 24.5l2.15-2.15 9.05 9.05 19.2-19.2 2.15 2.15Z";
fill: md.sys.color.on-primary;
@ -88,6 +88,7 @@ export CheckBox := Rectangle {
}
fs := FocusScope {
x:0;
width: 0px; // Do not react on clicks
enabled <=> root.enabled;
@ -101,7 +102,7 @@ export CheckBox := Rectangle {
}
states [
disabled-selected when !enabled && checked : {
disabled-selected when !root.enabled && root.checked : {
container.border-width: 0px;
container.border-color: transparent;
container.background: md.sys.color.primary;
@ -109,7 +110,7 @@ export CheckBox := Rectangle {
label.opacity: 0.38;
label.color: md.sys.color.primary;
}
disabled when !enabled : {
disabled when !root.enabled : {
container.opacity: 0.38;
label.opacity: 0.38;
label.color: md.sys.color.primary;
@ -117,32 +118,32 @@ export CheckBox := Rectangle {
pressed when touch.pressed && !root.checked : {
state-layer.opacity: 0.12;
}
pressed-selected when touch.pressed && checked : {
pressed-selected when touch.pressed && root.checked : {
state-layer.opacity: 0.12;
state-layer.background: md.sys.color.on-surface;
container.border-width: 0px;
container.border-color: transparent;
container.background: md.sys.color.primary;
}
hover-selected when touch.has-hover && checked : {
hover-selected when touch.has-hover && root.checked : {
state-layer.opacity: 0.08;
container.border-width: 0px;
container.border-color: transparent;
container.background: md.sys.color.primary;
}
hover when touch.has-hover && !checked : {
hover when touch.has-hover && !root.checked : {
state-layer.background: md.sys.color.on-surface;
state-layer.opacity: 0.08;
}
selected when !touch.has-hover && checked : {
selected when !touch.has-hover && root.checked : {
container.border-width: 0px;
container.border-color: transparent;
container.background: md.sys.color.primary;
}
focused-selected when fs.has-focus && checked : {
focused-selected when fs.has-focus && root.checked : {
state-layer.opacity: 0.12;
}
focused when fs.has-focus && !checked : {
focused when fs.has-focus && !root.checked : {
state-layer.background: md.sys.color.on-surface;
state-layer.opacity: 0.12;
}

View file

@ -5,14 +5,14 @@
import { md } from "md.slint";
import { Item } from "widget-item.slint";
export ComboBox := FocusScope {
export component ComboBox inherits FocusScope {
in property <[string]> model;
in-out property <int> current-index : 0;
in-out property <string> current-value: model[current-index];
in-out property <string> current-value: root.model[root.current-index];
callback selected(string);
accessible-role: combobox;
accessible-value <=> current-value;
accessible-value <=> root.current-value;
horizontal-stretch: 1;
vertical-stretch: 0;
@ -46,7 +46,7 @@ export ComboBox := FocusScope {
icon := Path {
width: 16px;
height: 16px;
y: (parent.height - height) / 2;
y: (parent.height - self.height) / 2;
commands: "m24 30.75-12-12 2.15-2.15L24 26.5l9.85-9.85L36 18.8Z";
fill: md.sys.color.on-surface;
}
@ -61,6 +61,7 @@ export ComboBox := FocusScope {
}
popup := PopupWindow {
x:0;
y: root.height;
width: root.width;
@ -89,25 +90,25 @@ export ComboBox := FocusScope {
key-pressed(event) => {
if (event.text == Key.UpArrow) {
current-index = Math.max(current-index - 1, 0);
current-value = model[current-index];
root.current-index = Math.max(root.current-index - 1, 0);
root.current-value = root.model[root.current-index];
return accept;
} else if (event.text == Key.DownArrow) {
current-index = Math.min(current-index + 1, model.length - 1);
current-value = model[current-index];
root.current-index = Math.min(root.current-index + 1, root.model.length - 1);
root.current-value = root.model[root.current-index];
return accept;
}
return reject;
}
states [
disabled when !enabled : {
disabled when !root.enabled : {
container.border-color: md.sys.color.on-surface;
container.opacity: 0.38;
label.opacity: 0.38;
icon.opacity: 0.38;
}
focused when has-focus : {
focused when root.has-focus : {
container.border-width: 2px;
container.border-color: md.sys.color.primary;
label.color: md.sys.color.primary;

View file

@ -4,7 +4,7 @@
import { md } from "md.slint";
// A container widget with a title.
export GroupBox := Rectangle {
export component GroupBox inherits Rectangle {
in property <string> title <=> label.text;
in property<bool> enabled: true;
@ -32,6 +32,7 @@ export GroupBox := Rectangle {
}
label-container := Rectangle {
y:0;
x: 8px;
width: label.width + 8px;
height: label.height + 8px;
@ -50,7 +51,7 @@ export GroupBox := Rectangle {
}
states [
disabled when !enabled : {
disabled when !root.enabled : {
container.border-color: md.sys.color.on-surface;
container.opacity: 0.38;
label.opacity: 0.38;

View file

@ -5,7 +5,7 @@ import { StateLayer } from "comp-state-layer.slint";
import { md } from "md.slint";
// A selectable item that is used by `StandardListView` and `ComboBox`.
export Item := Rectangle {
export component Item inherits Rectangle {
callback clicked <=> state-layer.clicked;
in property<bool> selected;
@ -38,7 +38,7 @@ export Item := Rectangle {
}
states [
selected when selected : {
selected when root.selected : {
state-layer.background: md.sys.color.secondary-container;
}
]

View file

@ -5,7 +5,7 @@
import { md } from "md.slint";
// Single line text input field with Material Design Outline TextField look and feel.
export LineEdit := Rectangle {
export component LineEdit inherits Rectangle {
in property <length> font-size <=> input.font-size;
in-out property <string> text <=> input.text;
in property <string> placeholder-text <=> placeholder.text;
@ -56,8 +56,8 @@ export LineEdit := Rectangle {
property <length> computed_x;
property <length> padding-outer: layout.padding-left + layout.padding-right;
x: min(0px, max(parent.width - width, computed_x));
width: max(parent.width, preferred-width);
x: min(0px, max(parent.width - self.width, self.computed_x));
width: max(parent.width, self.preferred-width);
height: 100%;
color: md.sys.color.on-surface;
vertical-alignment: center;
@ -67,10 +67,10 @@ export LineEdit := Rectangle {
accepted => { root.accepted(self.text); }
edited => { root.edited(self.text); }
cursor-position-changed(cpos) => {
if (cpos.x + computed_x < padding-outer) {
computed_x = - cpos.x + padding-outer;
} else if (cpos.x + computed_x > parent.width - padding-outer) {
computed_x = parent.width - cpos.x - padding-outer;
if (cpos.x + self.computed_x < self.padding-outer) {
self.computed_x = - cpos.x + self.padding-outer;
} else if (cpos.x + self.computed_x > parent.width - self.padding-outer) {
self.computed_x = parent.width - cpos.x - self.padding-outer;
}
}
}
@ -78,13 +78,13 @@ export LineEdit := Rectangle {
}
states [
disabled when !enabled : {
disabled when !root.enabled : {
container.border-color: md.sys.color.on-surface;
container.opacity: 0.38;
input.opacity: 0.38;
placeholder.opacity: 0.38;
}
focused when has-focus : {
focused when root.has-focus : {
container.border-width: 2px;
container.border-color: md.sys.color.primary;
input.color: md.sys.color.primary;

View file

@ -6,30 +6,30 @@ import { ScrollView } from "widget-scrollview.slint";
import { Item } from "widget-item.slint";
// `ListView` is like a `Scrollview` but it should have a for element, and the content are automatically layed out in a list.
export ListView := ScrollView {
export component ListView inherits ScrollView {
@children
}
StandardListViewBase := ListView {
component StandardListViewBase inherits ListView {
in property<[StandardListViewItem]> model;
in-out property<int> current-item: -1;
for item[idx] in model : Item {
for item[idx] in root.model : Item {
selected: idx == root.current-item;
text: item.text;
clicked => { current-item = idx; }
clicked => { root.current-item = idx; }
}
}
// Like `ListView`, but with a default delegate, and a `model` property which is a model of type `StandardListViewItem`.
export StandardListView := StandardListViewBase {
export component StandardListView inherits StandardListViewBase {
FocusScope {
key-pressed(event) => {
if (event.text == Key.UpArrow && current-item > 0) {
current-item -= 1;
if (event.text == Key.UpArrow && root.current-item > 0) {
root.current-item -= 1;
return accept;
} else if (event.text == Key.DownArrow && current-item + 1 < model.length) {
current-item += 1;
} else if (event.text == Key.DownArrow && root.current-item + 1 < root.model.length) {
root.current-item += 1;
return accept;
}
reject

View file

@ -4,13 +4,13 @@
import { md } from "md.slint";
ScrollBar := Rectangle {
property <bool> horizontal;
property<length> maximum;
property<length> page-size;
component ScrollBar inherits Rectangle {
in-out property <bool> horizontal;
in-out property<length> maximum;
in-out property<length> page-size;
// this is always negative and bigger than -maximum
property<length> value;
property<bool> enabled <=> touch.enabled;
in-out property<length> value;
in-out property<bool> enabled <=> touch.enabled;
state_layer := Rectangle {
width: 100%;
@ -23,10 +23,10 @@ ScrollBar := Rectangle {
}
handle := Rectangle {
x: !horizontal ? 0phx : (root.width - handle.width) * (-value / maximum);
y: horizontal ? 0phx : (root.height - handle.height) * (-value / maximum);
width: !horizontal ? parent.width : maximum <= 0phx ? 0phx : parent.width * (page-size / (maximum + page-size));
height: horizontal ? parent.height : maximum <= 0phx ? 0phx : parent.height * (page-size / (maximum + page-size));
x: !root.horizontal ? 0phx : (root.width - handle.width) * (-root.value / root.maximum);
y: root.horizontal ? 0phx : (root.height - handle.height) * (-root.value / root.maximum);
width: !root.horizontal ? parent.width : root.maximum <= 0phx ? 0phx : parent.width * (root.page-size / (root.maximum + root.page-size));
height: root.horizontal ? parent.height : root.maximum <= 0phx ? 0phx : parent.height * (root.page-size / (root.maximum + root.page-size));
container := Rectangle {
width: 100%;
@ -45,14 +45,14 @@ ScrollBar := Rectangle {
pointer-event(event) => {
if (event.button == PointerEventButton.left && event.kind == PointerEventKind.down) {
pressed-value = -root.value;
self.pressed-value = -root.value;
}
}
moved => {
if (enabled && pressed) {
value = -max(0px, min(root.maximum, pressed-value + (
horizontal ? (touch.mouse-x - touch.pressed-x) * (maximum / (root.width - handle.width))
: (touch.mouse-y - touch.pressed-y) * (maximum / (root.height - handle.height))
if (self.enabled && self.pressed) {
root.value = -max(0px, min(root.maximum, self.pressed-value + (
root.horizontal ? (touch.mouse-x - touch.pressed-x) * (root.maximum / (root.width - handle.width))
: (touch.mouse-y - touch.pressed-y) * (root.maximum / (root.height - handle.height))
)));
}
}
@ -73,7 +73,7 @@ ScrollBar := Rectangle {
}
// Scrollview contains a viewport that is bigger than the view and can be scrolled.
export ScrollView := Rectangle {
export component ScrollView inherits Rectangle {
in-out property <length> viewport-width <=> fli.viewport-width;
in-out property <length> viewport-height <=> fli.viewport-height;
in-out property <length> viewport-x <=> fli.viewport-x;
@ -81,7 +81,7 @@ export ScrollView := Rectangle {
out property <length> visible-width <=> fli.width;
out property <length> visible-height <=> fli.height;
in property <bool> enabled: true;
property <bool> has-focus;
in-out property <bool> has-focus;
background: md.sys.color.surface;
min-height: 50px;
@ -90,6 +90,7 @@ export ScrollView := Rectangle {
vertical-stretch: 1;
fli := Flickable {
x:0;y:0;
interactive: false;
viewport-y <=> vbar.value;
viewport-x <=> hbar.value;

View file

@ -5,7 +5,7 @@
import { md } from "md.slint";
// Allows to select a value from a range of values.
export Slider := Rectangle {
export component Slider inherits Rectangle {
in property<float> maximum: 100;
in property<float> minimum: 0;
in-out property<float> value;
@ -16,15 +16,15 @@ export Slider := Rectangle {
height: 20px;
accessible-role: slider;
accessible-value: value;
accessible-value-minimum: minimum;
accessible-value-maximum: maximum;
accessible-value-step: (maximum - minimum) / 100;
accessible-value: root.value;
accessible-value-minimum: root.minimum;
accessible-value-maximum: root.maximum;
accessible-value-step: (root.maximum - root.minimum) / 100;
container := Rectangle {
background: md.sys.color.surface-variant;
opacity: 0.38;
y: (parent.height - height) / 2;
y: (parent.height - self.height) / 2;
width: 100%;
height: 4px;
border-radius: 2px;
@ -33,7 +33,7 @@ export Slider := Rectangle {
track := Rectangle {
background: md.sys.color.primary;
x: container.x;
y: (parent.height - height) / 2;
y: (parent.height - self.height) / 2;
width: handle.x + (handle.width / 2);
height: container.height;
border-radius: container.border-radius;
@ -42,21 +42,21 @@ export Slider := Rectangle {
state-layer := Rectangle {
opacity: 0;
background: md.sys.color.primary;
x: handle.x - (width - handle.width) / 2;
y: (parent.height - height) / 2;
x: handle.x - (self.width - handle.width) / 2;
y: (parent.height - self.height) / 2;
width: 40px;
height: 40px;
border-radius: max(width, height) / 2;
border-radius: max(self.width, self.height) / 2;
animate opacity { duration: 250ms; easing: ease; }
}
handle := Rectangle {
background: md.sys.color.primary;
x: (parent.width - handle.width) * (value - minimum) / (maximum - minimum);
y: (parent.height - height) / 2;
x: (parent.width - handle.width) * (root.value - root.minimum) / (root.maximum - root.minimum);
y: (parent.height - self.height) / 2;
width: root.height;
height: root.height;
border-radius: max(width, height) / 2;
border-radius: max(self.width, self.height) / 2;
drop-shadow-color: md.sys.color.shadow;
drop-shadow-blur: md.sys.elevation.level1;
drop-shadow-offset-y: 1px;
@ -66,31 +66,32 @@ export Slider := Rectangle {
touch := TouchArea {
property <float> pressed-value;
property <bool> handle-hover: has-hover && mouse-x >= handle.x && mouse-x <= handle.x + handle.width
&& mouse-y >= handle.y && mouse-y <= handle.y + handle.height;
property <bool> handle-hover: self.has-hover && self.mouse-x >= handle.x && self.mouse-x <= handle.x + handle.width
&& self.mouse-y >= handle.y && self.mouse-y <= handle.y + handle.height;
pointer-event(event) => {
if (event.button == PointerEventButton.left && event.kind == PointerEventKind.down) {
pressed-value = root.value;
self.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);
if (self.enabled && self.pressed) {
root.value = max(root.minimum, min(root.maximum,
self.pressed-value + (touch.mouse-x - touch.pressed-x) * (root.maximum - root.minimum) / (root.width - handle.width)));
root.changed(root.value);
}
}
}
fs := FocusScope {
x:0;
width: 0px;
key-pressed(event) => {
if (enabled && event.text == Key.RightArrow) {
value = Math.min(value + 1, maximum);
if (self.enabled && event.text == Key.RightArrow) {
root.value = Math.min(root.value + 1, root.maximum);
accept
} else if (enabled && event.text == Key.LeftArrow) {
value = Math.max(value - 1, minimum);
} else if (self.enabled && event.text == Key.LeftArrow) {
root.value = Math.max(root.value - 1, root.minimum);
accept
} else {
reject
@ -99,7 +100,7 @@ export Slider := Rectangle {
}
states [
disabled when !enabled : {
disabled when !root.enabled : {
handle.background: md.sys.color.on-surface;
handle.drop-shadow-blur: md.sys.elevation.level0;
track.background: md.sys.color.on-surface;

View file

@ -3,24 +3,25 @@
import { md } from "md.slint";
SpinBoxButton := Rectangle {
component SpinBoxButton inherits Rectangle {
callback clicked <=> touch.clicked;
property<bool> pressed: self.enabled && touch.pressed;
property<bool> enabled <=> touch.enabled;
property<float> icon-opacity: 1;
property<brush> icon-fill: md.sys.color.on-primary;
in-out property<bool> pressed: self.enabled && touch.pressed;
in-out property<bool> enabled <=> touch.enabled;
in-out property<float> icon-opacity: 1;
in-out property<brush> icon-fill: md.sys.color.on-primary;
width: height;
width: root.height;
container := Rectangle {
width: 100%;
height: 100%;
border-radius: max(width, height) / 2;
border-radius: max(self.width, self.height) / 2;
background: md.sys.color.primary;
}
state-layer := Rectangle {
x:0;y:0;
opacity: 0;
width: container.width;
height: container.height;
@ -54,8 +55,8 @@ SpinBoxButton := Rectangle {
}
// Increment and decrement a value in the given range.
export SpinBox := FocusScope {
property <bool> checked;
export component SpinBox inherits FocusScope {
in-out property <bool> checked;
in-out property <int> value;
in property <int> minimum;
in property <int> maximum: 100;
@ -68,10 +69,10 @@ export SpinBox := FocusScope {
height: 56px;
accessible-role: spinbox;
accessible-value: value;
accessible-value-minimum: minimum;
accessible-value-maximum: maximum;
accessible-value-step: (maximum - minimum) / 100;
accessible-value: root.value;
accessible-value-minimum: root.minimum;
accessible-value-maximum: root.maximum;
accessible-value-step: (root.maximum - root.minimum) / 100;
container := Rectangle {
width: 100%;
@ -89,7 +90,7 @@ export SpinBox := FocusScope {
spacing: 16px;
label := Text {
text: value;
text: root.value;
height: 100%;
color: md.sys.color.on-surface;
vertical-alignment: center;
@ -105,8 +106,8 @@ export SpinBox := FocusScope {
enabled: root.enabled;
Path {
x: (parent.width - width) / 2;
y: (parent.height - height) / 2;
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
width: 44%;
height: 44%;
commands: "M14.15 30.75 12 28.6l12-12 12 11.95-2.15 2.15L24 20.85Z";
@ -127,8 +128,8 @@ export SpinBox := FocusScope {
enabled: root.enabled;
Path {
x: (parent.width - width) / 2;
y: (parent.height - height) / 2;
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
width: 44%;
height: 44%;
commands: "m24 30.75-12-12 2.15-2.15L24 26.5l9.85-9.85L36 18.8Z";
@ -149,11 +150,11 @@ export SpinBox := FocusScope {
}
key-pressed(event) => {
if (enabled && event.text == Key.UpArrow && value < maximum) {
value += 1;
if (root.enabled && event.text == Key.UpArrow && root.value < root.maximum) {
root.value += 1;
accept
} else if (enabled && event.text == Key.DownArrow && value > minimum) {
value -= 1;
} else if (root.enabled && event.text == Key.DownArrow && root.value > root.minimum) {
root.value -= 1;
accept
} else {
reject
@ -161,12 +162,12 @@ export SpinBox := FocusScope {
}
states [
disabled when !enabled : {
disabled when !root.enabled : {
container.border-color: md.sys.color.on-surface;
container.opacity: 0.38;
label.opacity: 0.38;
}
focused when has-focus : {
focused when root.has-focus : {
container.border-width: 2px;
container.border-color: md.sys.color.primary;
label.color: md.sys.color.primary;

View file

@ -4,43 +4,43 @@
import { md } from "md.slint";
export TabWidgetImpl := Rectangle {
property <length> content-x: 0;
property <length> content-y: tabbar-preferred-height;
property <length> content-height: height - tabbar-preferred-height;
property <length> content-width: width;
property <length> tabbar-x: 0;
property <length> tabbar-y: 0;
property <length> tabbar-height: tabbar-preferred-height;
property <length> tabbar-width: width;
export component TabWidgetImpl inherits Rectangle {
in-out property <length> content-x: 0;
in-out property <length> content-y: root.tabbar-preferred-height;
in-out property <length> content-height: root.height - root.tabbar-preferred-height;
in-out property <length> content-width: root.width;
in-out property <length> tabbar-x: 0;
in-out property <length> tabbar-y: 0;
in-out property <length> tabbar-height: root.tabbar-preferred-height;
in-out property <length> tabbar-width: root.width;
property <length> tabbar-preferred-height;
property <length> tabbar-preferred-width;
property <length> content-min-height;
property <length> content-min-width;
property <int> current-index;
property <int> current-focused;
in-out property <length> tabbar-preferred-height;
in-out property <length> tabbar-preferred-width;
in-out property <length> content-min-height;
in-out property <length> content-min-width;
in-out property <int> current-index;
in-out property <int> current-focused;
preferred-width: content-min-width;
min-width: max(content-min-width, tabbar-preferred-width);
preferred-height: content-min-height + tabbar-preferred-height;
min-height: content-min-height + tabbar-preferred-height;
preferred-width: root.content-min-width;
min-width: max(root.content-min-width, root.tabbar-preferred-width);
preferred-height: root.content-min-height + root.tabbar-preferred-height;
min-height: root.content-min-height + root.tabbar-preferred-height;
}
export TabImpl := Rectangle {
property<string> title <=> label.text;
property<bool> enabled: true;
property<bool> has-focus: current-focused == tab-index;
property<bool> active: tab-index == current;
property<bool> pressed;
property<int> current; // The currently selected tab
property<int> current-focused; // The currently focused tab
property<int> tab-index; // The index of this tab
property<int> num-tabs; // The total number of tabs
export component TabImpl inherits Rectangle {
in-out property<string> title <=> label.text;
in-out property<bool> enabled: true;
in-out property<bool> has-focus: root.current-focused == root.tab-index;
in-out property<bool> active: root.tab-index == root.current;
in-out property<bool> pressed;
in-out property<int> current; // The currently selected tab
in-out property<int> current-focused; // The currently focused tab
in-out property<int> tab-index; // The index of this tab
in-out property<int> num-tabs; // The total number of tabs
height: 48px;
accessible-role: tab;
accessible-label <=> title;
accessible-label <=> root.title;
container := Rectangle {
background: md.sys.color.surface;
@ -61,7 +61,7 @@ export TabImpl := Rectangle {
label := Text {
vertical-alignment: center;
color: !active ? md.sys.color.on-surface : md.sys.color.primary;
color: !root.active ? md.sys.color.on-surface : md.sys.color.primary;
// FIXME after Roboto font can be loaded
//font-family: md.sys.typescale.title-small.font;
font-size: md.sys.typescale.title-small.size;
@ -72,10 +72,10 @@ export TabImpl := Rectangle {
}
indicator := Rectangle {
opacity: !active ? 0 : 1;
opacity: !root.active ? 0 : 1;
width: 100%;
height: 3px;
y: parent.height - height;
y: parent.height - self.height;
background: md.sys.color.primary;
animate opacity { duration: 250ms; easing: ease; }
@ -84,16 +84,16 @@ export TabImpl := Rectangle {
touch := TouchArea {
enabled <=> root.enabled;
clicked => {
current = tab-index;
root.current = root.tab-index;
}
}
}
export TabBarImpl := Rectangle {
export component TabBarImpl inherits Rectangle {
// injected properties:
property<int> current; // The currently selected tab
property<int> current-focused: fs.has-focus ? fs.focused-tab : -1; // The currently focused tab
property<int> num-tabs; // The total number of tabs
in-out property<int> current; // The currently selected tab
in-out property<int> current-focused: fs.has-focus ? fs.focused-tab : -1; // The currently focused tab
in-out property<int> num-tabs; // The total number of tabs
HorizontalLayout {
alignment: start;
@ -101,23 +101,24 @@ export TabBarImpl := Rectangle {
}
accessible-role: tab;
accessible-delegate-focus: current-focused >= 0 ? current-focused : current;
accessible-delegate-focus: root.current-focused >= 0 ? root.current-focused : root.current;
fs := FocusScope {
x:0;
width: 0px; // Do not react on clicks
property<int> focused-tab: 0;
key-pressed(event) => {
if (event.text == "\n") {
current = current-focused;
root.current = root.current-focused;
return accept;
}
if (event.text == Key.LeftArrow) {
focused-tab = Math.max(focused-tab - 1, 0);
self.focused-tab = Math.max(self.focused-tab - 1, 0);
return accept;
}
if (event.text == Key.RightArrow) {
focused-tab = Math.min(focused-tab + 1, num-tabs - 1);
self.focused-tab = Math.min(self.focused-tab + 1, root.num-tabs - 1);
return accept;
}
return reject;
@ -125,7 +126,7 @@ export TabBarImpl := Rectangle {
key-released(event) => {
if (event.text == " ") {
current = current-focused;
root.current = root.current-focused;
return accept;
}
return reject;
@ -134,4 +135,4 @@ export TabBarImpl := Rectangle {
}
export TabWidget := TabWidget {}
export component TabWidget inherits TabWidget {}

View file

@ -1,6 +1,6 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
export global ColorSchemeSelector := {
property<bool> dark-color-scheme: true;
export global ColorSchemeSelector {
in-out property<bool> dark-color-scheme: true;
}

View file

@ -1,6 +1,6 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
export global ColorSchemeSelector := {
property<bool> dark-color-scheme: false;
export global ColorSchemeSelector {
in-out property<bool> dark-color-scheme: false;
}

View file

@ -1,6 +1,6 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
export global ColorSchemeSelector := {
property<bool> dark-color-scheme: SlintInternal.dark-color-scheme;
export global ColorSchemeSelector {
in-out property<bool> dark-color-scheme: SlintInternal.dark-color-scheme;
}

View file

@ -3,7 +3,7 @@
export { NativeStyleMetrics as StyleMetrics }
export ScrollView := NativeScrollView {
export component ScrollView inherits NativeScrollView {
in-out property <length> viewport-width <=> fli.viewport-width;
in-out property <length> viewport-height <=> fli.viewport-height;
in-out property <length> viewport-x <=> fli.viewport-x;

View file

@ -8,55 +8,56 @@ import { StyleMetrics, ScrollView } from "std-widgets-impl.slint";
export { StyleMetrics, ScrollView, TextEdit, AboutSlint, AboutSlint as AboutSixtyFPS }
// FIXME: the font-size should be removed but is required right now to compile the printer-demo
export Button := NativeButton {
export component Button inherits NativeButton {
// FIXME: remove
property<length> font-size;
accessible-checkable <=> checkable;
accessible-checked <=> checked;
accessible-label <=> text;
in-out property<length> font-size;
accessible-checkable <=> root.checkable;
accessible-checked <=> root.checked;
accessible-label <=> root.text;
accessible-role: button;
checkable: false;
enabled: true;
}
export StandardButton := NativeButton {
export component StandardButton inherits NativeButton {
in property<StandardButtonKind> kind <=> self.standard-button-kind;
accessible-checkable <=> checkable;
accessible-checked <=> checked;
accessible-label <=> text;
accessible-checkable <=> root.checkable;
accessible-checked <=> root.checked;
accessible-label <=> root.text;
accessible-role: button;
is-standard-button: true;
checkable: false;
}
export CheckBox := NativeCheckBox {
export component CheckBox inherits NativeCheckBox {
accessible-checkable: true;
accessible-checked <=> checked;
accessible-label <=> text;
accessible-checked <=> root.checked;
accessible-label <=> root.text;
accessible-role: checkbox;
}
export SpinBox := NativeSpinBox {
export component SpinBox inherits NativeSpinBox {
// FIXME: remove
property<length> font-size;
in-out property<length> font-size;
accessible-role: spinbox;
accessible-value: value;
accessible-value-minimum: minimum;
accessible-value-maximum: maximum;
accessible-value-step: (maximum - minimum) / 100;
accessible-value: root.value;
accessible-value-minimum: root.minimum;
accessible-value-maximum: root.maximum;
accessible-value-step: (root.maximum - root.minimum) / 100;
}
export Slider := NativeSlider {
export component Slider inherits NativeSlider {
accessible-role: slider;
accessible-value: value;
accessible-value-minimum: minimum;
accessible-value-maximum: maximum;
accessible-value-step: (maximum - minimum) / 100;
accessible-value: root.value;
accessible-value-minimum: root.minimum;
accessible-value-maximum: root.maximum;
accessible-value-step: (root.maximum - root.minimum) / 100;
out property <bool> has-focus: fs.has-focus;
fs := FocusScope {
x:0;
width: 0px;
key-pressed(event) => {
@ -74,7 +75,7 @@ export Slider := NativeSlider {
}
export GroupBox := NativeGroupBox {
export component GroupBox inherits NativeGroupBox {
GridLayout {
padding-left: root.native-padding-left;
padding-right: root.native-padding-right;
@ -84,7 +85,7 @@ export GroupBox := NativeGroupBox {
}
}
export LineEdit := NativeLineEdit {
export component LineEdit inherits NativeLineEdit {
in property <length> font-size <=> inner.font-size;
in-out property <string> text <=> inner.text;
in property <string> placeholder-text <=> inner.placeholder-text;
@ -105,38 +106,38 @@ export LineEdit := NativeLineEdit {
padding-top: root.native-padding-top;
padding-bottom: root.native-padding-bottom;
inner := LineEditInner {
placeholder-color: enabled ? StyleMetrics.placeholder-color : StyleMetrics.placeholder-color-disabled;
placeholder-color: self.enabled ? StyleMetrics.placeholder-color : StyleMetrics.placeholder-color-disabled;
enabled <=> root.enabled;
}
}
}
export ListView := ScrollView {
export component ListView inherits ScrollView {
@children
}
StandardListViewBase := ListView {
component StandardListViewBase inherits ListView {
in property<[StandardListViewItem]> model;
in-out property<int> current-item: -1;
for item[i] in model : NativeStandardListViewItem {
for item[i] in root.model : NativeStandardListViewItem {
item: item;
index: i;
is-selected: current-item == i;
is-selected: root.current-item == i;
has-hover: ta.has-hover;
ta := TouchArea {
clicked => { current-item = i; }
clicked => { root.current-item = i; }
}
}
}
export StandardListView := StandardListViewBase {
export component StandardListView inherits StandardListViewBase {
FocusScope {
key-pressed(event) => {
if (event.text == Key.UpArrow && current-item > 0) {
current-item -= 1;
if (event.text == Key.UpArrow && root.current-item > 0) {
root.current-item -= 1;
accept
} else if (event.text == Key.DownArrow && current-item + 1 < model.length) {
current-item += 1;
} else if (event.text == Key.DownArrow && root.current-item + 1 < root.model.length) {
root.current-item += 1;
accept
} else {
reject
@ -145,7 +146,7 @@ export StandardListView := StandardListViewBase {
}
}
export ComboBox := NativeComboBox {
export component ComboBox inherits NativeComboBox {
in property <[string]> model;
in-out property <int> current-index : -1;
enabled: true;
@ -153,9 +154,10 @@ export ComboBox := NativeComboBox {
callback selected(string);
accessible-role: combobox;
accessible-value <=> current-value;
accessible-value <=> root.current-value;
popup := PopupWindow {
x:0;
Rectangle { background: NativeStyleMetrics.window-background; }
NativeComboBoxPopup {
width: 100%;
@ -167,14 +169,14 @@ export ComboBox := NativeComboBox {
spacing: 0px;
for value[i] in root.model: NativeStandardListViewItem {
item: { text: value };
is-selected: current-index == i;
is-selected: root.current-index == i;
has-hover: ta.has-hover;
ta := TouchArea {
clicked => {
if (root.enabled) {
current-index = i;
current-value = value;
selected(current-value);
root.current-index = i;
root.current-value = value;
root.selected(root.current-value);
}
//is-open = false;
}
@ -187,11 +189,11 @@ export ComboBox := NativeComboBox {
key-pressed(event) => {
if (event.text == Key.UpArrow) {
root.current-index = Math.max(root.current-index - 1, 0);
root.current-value = model[root.current-index];
root.current-value = root.model[root.current-index];
return accept;
} else if (event.text == Key.DownArrow) {
root.current-index = Math.min(root.current-index + 1, root.model.length - 1);
root.current-value = model[root.current-index];
root.current-value = root.model[root.current-index];
return accept;
// PopupWindow can not get hidden again at this time, so do not allow to pop that up.
// } else if (event.text == Key.Return) {
@ -203,21 +205,21 @@ export ComboBox := NativeComboBox {
}
}
export TabWidgetImpl := NativeTabWidget { }
export component TabWidgetImpl inherits NativeTabWidget { }
export TabImpl := NativeTab {
export component TabImpl inherits NativeTab {
accessible-role: tab;
accessible-label <=> title;
accessible-label <=> root.title;
}
export TabBarImpl := Rectangle {
export component TabBarImpl inherits Rectangle {
// injected properties:
property<int> current; // The currently selected tab
property<int> current-focused: fs.has-focus ? current : -1; // The currently focused tab
property<int> num-tabs; // The total number of tabs
in-out property<int> current; // The currently selected tab
in-out property<int> current-focused: fs.has-focus ? root.current : -1; // The currently focused tab
in-out property<int> num-tabs; // The total number of tabs
accessible-role: tab;
accessible-delegate-focus: current;
accessible-delegate-focus: root.current;
HorizontalLayout {
spacing: 0px; // Qt renders Tabs next to each other and renders "spacing" as part of the tab itself
@ -226,6 +228,7 @@ export TabBarImpl := Rectangle {
}
fs := FocusScope {
x:0;
width: 0px; // Do not react on clicks
key-pressed(event) => {
if (event.text == Key.LeftArrow) {
@ -233,7 +236,7 @@ export TabBarImpl := Rectangle {
return accept;
}
if (event.text == Key.RightArrow) {
root.current = Math.min(root.current + 1, num-tabs - 1);
root.current = Math.min(root.current + 1, root.num-tabs - 1);
return accept;
}
return reject;
@ -241,19 +244,19 @@ export TabBarImpl := Rectangle {
}
}
export TabWidget := TabWidget {}
export component TabWidget inherits TabWidget {}
export VerticalBox := VerticalLayout {
export component VerticalBox inherits VerticalLayout {
spacing: NativeStyleMetrics.layout-spacing;
padding: NativeStyleMetrics.layout-spacing;
}
export HorizontalBox := HorizontalLayout {
export component HorizontalBox inherits HorizontalLayout {
spacing: NativeStyleMetrics.layout-spacing;
padding: NativeStyleMetrics.layout-spacing;
}
export GridBox := GridLayout {
export component GridBox inherits GridLayout {
spacing: NativeStyleMetrics.layout-spacing;
padding: NativeStyleMetrics.layout-spacing;
}