Design refresh of the gallery example (#1820)

* Visual refresh of the gallery example
* Add new Navigation
* Improve layout
* Fix layout behavior of material GroupBox
This commit is contained in:
Florian Blasius 2022-11-09 14:39:16 +01:00 committed by GitHub
parent 27347de92b
commit a3e1f9f246
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 454 additions and 179 deletions

View file

@ -1,171 +1,26 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
import { ScrollView, Button, CheckBox, SpinBox, Slider, GroupBox, LineEdit, StandardListView,
ComboBox, HorizontalBox, VerticalBox, GridBox, TabWidget, TextEdit, AboutSlint } from "std-widgets.slint";
import { CheckBox, StandardListView, StyleMetrics } from "std-widgets.slint";
import { AboutPage, ControlsPage, ListViewPage, TextEditPage } from "ui/pages/pages.slint";
import { GallerySettings } from "ui/gallery_settings.slint";
import { SideBar } from "ui/side_bar.slint";
App := Window {
preferred-width: 500px;
preferred-height: 600px;
title: "Slint Gallery";
preferred-width: 700px;
preferred-height: 500px;
title: "Slint Widgets Gallery";
icon: @image-url("../../logo/slint-logo-small-light-128x128.png");
VerticalBox {
HorizontalBox {
Text {
text: "Below are some of the standard widgets that application developers can easily re-use.";
wrap: word-wrap;
}
VerticalLayout {
alignment: start;
disable-toggle := CheckBox {
checked: false;
text: "Disable Widgets";
}
}
HorizontalLayout {
side-bar := SideBar {
title: "Slint Widgets Gallery";
model: ["Controls", "ListView", "TextEdit", "About"];
}
TabWidget {
Tab {
title: "Controls";
VerticalBox {
alignment: start;
HorizontalBox {
alignment: start;
GroupBox {
title: "Button";
enabled: !disable-toggle.checked;
Button {
text: "Regular Button";
enabled: !disable-toggle.checked;
}
}
GroupBox {
title: "Button with Icon";
enabled: !disable-toggle.checked;
Button {
text: "Regular Button";
icon: @image-url("thumbsup.png");
enabled: !disable-toggle.checked;
}
}
GroupBox {
title: "Button (checkable)";
enabled: !disable-toggle.checked;
Button {
checkable: true;
text: checked ? "ON" : "OFF";
enabled: !disable-toggle.checked;
}
}
}
HorizontalBox {
alignment: start;
GroupBox {
title: "SpinBox";
enabled: !disable-toggle.checked;
SpinBox {
value: 42;
enabled: !disable-toggle.checked;
}
}
GroupBox {
title: "ComboBox";
enabled: !disable-toggle.checked;
ComboBox {
model: ["Select Something", "From this", "Combobox"];
enabled: !disable-toggle.checked;
}
}
GroupBox {
title: "CheckBox";
enabled: !disable-toggle.checked;
checkbox := CheckBox {
text: checkbox.checked ? "(checked)" : "(unchecked)";
checked: true;
enabled: !disable-toggle.checked;
}
}
}
GroupBox {
title: "Slider";
enabled: !disable-toggle.checked;
Slider {
minimum: -100;
maximum: 100;
value: 42;
enabled: !disable-toggle.checked;
changed => {}
}
}
GroupBox {
title: "LineEdit";
enabled: !disable-toggle.checked;
LineEdit {
placeholder-text: "Enter some text";
enabled: !disable-toggle.checked;
}
}
}
}
Tab {
title: "List View";
GroupBox {
title: "StandardListView";
enabled: !disable-toggle.checked;
StandardListView {
model: [
{text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
{text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
{text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
{text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
{text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
{text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
{text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
];
}
}
}
Tab {
title: "TextEdit";
VerticalLayout {
GroupBox {
title: "Word-Wrap";
te1 := TextEdit {
text: "This is our TextEdit widget, which allows for editing text that spans over multiple paragraphs.\nFor example this line starts in a new paragraph.\n\nWhen the amount of lines - due to wrapping and number of paragraphs - exceeds the available vertical height, a vertical scrollbar is shown that allows scrolling.\nYou may want to enter a bit of text here then in order to make them visible.";
wrap: word-wrap;
enabled: !disable-toggle.checked;
}
}
GroupBox {
title: "No-Wrap";
TextEdit {
text <=> te1.text;
wrap: no-wrap;
enabled: !disable-toggle.checked;
}
}
}
}
Tab {
title: "About";
HorizontalBox {
alignment: center;
AboutSlint {
}
}
}
}
if(side-bar.current-item == 0) : ControlsPage {}
if(side-bar.current-item == 1) : ListViewPage {}
if(side-bar.current-item == 2) : TextEditPage {}
if(side-bar.current-item == 3) : AboutPage {}
}
}

View file

@ -0,0 +1,6 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
global GallerySettings := {
property<bool> widgets-disabled: false;
}

View file

@ -0,0 +1,14 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
import { AboutSlint } from "std-widgets.slint";
import { GallerySettings } from "../gallery_settings.slint";
import { Page } from "page.slint";
export AboutPage := Page {
title: "About";
description: "Are you curious now? Check out the docs and gettings start from the Github repository and the website https://slint-ui.com and try it yourself.";
AboutSlint {}
}

View file

@ -0,0 +1,147 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
import { Button, GroupBox, SpinBox, ComboBox, CheckBox, LineEdit, TabWidget, VerticalBox, HorizontalBox,
Slider, SpinBox } from "std-widgets.slint";
import { GallerySettings } from "../gallery_settings.slint";
import { Page } from "page.slint";
export ControlsPage := Page {
title: "Controls";
description: "This page gives an overview of the default widget set provided by Slint. The widgets are available in different styles native, fluent-(dark/light) and material-(dark/light). The widgets can be imported from \"std-widgets.slint\".";
GroupBox {
vertical-stretch: 0;
title: "Buttons";
HorizontalLayout {
spacing: 8px;
alignment: start;
Button {
text: "Regular Button";
enabled: !GallerySettings.widgets-disabled;
}
Button {
text: "Regular Button";
icon: @image-url("../../thumbsup.png");
enabled: !GallerySettings.widgets-disabled;
}
Button {
checkable: true;
text: checked ? "ON" : "OFF";
enabled: !GallerySettings.widgets-disabled;
}
}
}
GroupBox {
title: "CheckBox - SpinBox - ComboBox";
vertical-stretch: 0;
HorizontalBox {
checkbox := CheckBox {
text: checkbox.checked ? "(checked)" : "(unchecked)";
checked: true;
enabled: !GallerySettings.widgets-disabled;
}
SpinBox {
vertical-stretch: 0;
value: 42;
enabled: !GallerySettings.widgets-disabled;
}
ComboBox {
model: ["Select Something", "From this", "Combobox"];
enabled: !GallerySettings.widgets-disabled;
}
}
}
GroupBox {
title: "LineEdit";
vertical-stretch: 0;
LineEdit {
placeholder-text: "Enter some text";
enabled: !GallerySettings.widgets-disabled;
}
}
GroupBox {
title: "Slider";
vertical-stretch: 0;
Slider {
min-width: 160px;
minimum: -100;
maximum: 100;
value: 42;
enabled: !GallerySettings.widgets-disabled;
}
}
GroupBox {
title: "TabWidget";
TabWidget {
Tab {
title: "Tab 1";
VerticalBox {
alignment: start;
GroupBox {
title: "Content of tab 1";
VerticalBox {
alignment: start;
Button {
text: "Click me";
enabled: !GallerySettings.widgets-disabled;
}
}
}
}
}
Tab {
title: "Tab 2";
VerticalBox {
alignment: start;
GroupBox {
title: "Content of tab 2";
VerticalBox {
alignment: start;
CheckBox {
text: "Check me";
enabled: !GallerySettings.widgets-disabled;
}
}
}
}
}
Tab {
title: "Tab 3";
VerticalBox {
Text {
text: "Content of tab 3";
}
}
}
}
}
}

View file

@ -0,0 +1,48 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
import { HorizontalBox, VerticalBox, ListView, StandardListView, GroupBox } from "std-widgets.slint";
import { GallerySettings } from "../gallery_settings.slint";
import { Page } from "page.slint";
export ListViewPage := Page {
title: "ListView";
description: "ListViews can be used to display a list of elements. The StandardListBox is like the default ListView just with a default text based definition of the visual items. Both can be imported from \"std-widgets.slint\"";
HorizontalBox {
vertical-stretch: 1;
GroupBox {
title: "ListView";
ListView {
vertical-stretch: 0;
for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] : HorizontalBox {
Image {
width: 24px;
source: @image-url("../../thumbsup.png");
}
Text {
text: "Item " + i;
}
}
}
}
GroupBox {
title: "StandardListView";
vertical-stretch: 0;
StandardListView {
model: [
{text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
{text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
{text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
{text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
{text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
{text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
{text: "Lorem"}, {text: "ipsum"},{text: "dolor"},{text: "sit"},{text: "amet"},{text: "consetetur"},
];
}
}
}
}

View file

@ -0,0 +1,30 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
import { CheckBox, GridBox, ListView, ScrollView, VerticalBox } from "std-widgets.slint";
import { GallerySettings } from "../gallery_settings.slint";
export Page := VerticalBox {
property<string> title: "title";
property<string> description: "description";
HorizontalLayout {
height: 24px;
Text {
font-size: 20px;
text <=> root.title;
}
// Spacer
Rectangle {}
CheckBox {
horizontal-stretch: 0;
text: "Disable widgets";
checked <=> GallerySettings.widgets-disabled;
}
}
@children
}

View file

@ -0,0 +1,9 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
import { AboutPage } from "about_page.slint";
import { ControlsPage } from "controls_page.slint";
import { ListViewPage } from "list_view_page.slint";
import { TextEditPage } from "text_edit_page.slint";
export { AboutPage, ControlsPage, ListViewPage, TextEditPage }

View file

@ -0,0 +1,37 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
import { HorizontalBox, GroupBox, TextEdit } from "std-widgets.slint";
import { GallerySettings } from "../gallery_settings.slint";
import { Page } from "page.slint";
export TextEditPage := Page {
title: "TextEdit";
description: "Similar to LineEdit, but can be used to enter several lines of text. The widget can be imported from \"std-widgets.slint\".";
HorizontalBox {
GroupBox {
vertical-stretch: 0;
title: "Word-Wrap";
te1 := TextEdit {
min-width: 200px;
text: "This is our TextEdit widget, which allows for editing text that spans over multiple paragraphs.\nFor example this line starts in a new paragraph.\n\nWhen the amount of lines - due to wrapping and number of paragraphs - exceeds the available vertical height, a vertical scrollbar is shown that allows scrolling.\nYou may want to enter a bit of text here then in order to make them visible.";
wrap: word-wrap;
enabled: !GallerySettings.widgets-disabled;
}
}
GroupBox {
title: "No-Wrap";
vertical-stretch: 0;
te2 := TextEdit {
min-width: 200px;
text <=> te1.text;
wrap: no-wrap;
enabled: !GallerySettings.widgets-disabled;
}
}
}
}

View file

@ -0,0 +1,129 @@
// Copyright © SixtyFPS GmbH <info@slint-ui.com>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
import { StyleMetrics } from "std-widgets.slint";
SideBarItem := Rectangle {
callback clicked <=> touch.clicked;
property<string> text <=> label.text;
property<bool> selected;
property<bool> has-focus;
min-height: l.preferred-height;
state := Rectangle {
opacity: 0;
background: StyleMetrics.window-background;
animate opacity { duration: 150ms; }
}
l := HorizontalLayout {
y: (parent.height - height) / 2;
padding: StyleMetrics.layout-padding;
spacing: 0px;
label := Text {
color: StyleMetrics.default-text-color;
vertical-alignment: center;
}
}
touch := TouchArea {
width: 100%;
height: 100%;
}
states [
pressed when touch.pressed : {
state.opacity: 0.8;
}
hover when touch.has-hover : {
state.opacity: 0.6;
}
selected when root.selected : {
state.opacity: 1;
}
focused when root.has-focus : {
state.opacity: 0.8;
}
]
}
export SideBar := Rectangle {
property<[string]> model: [];
property<int> current-item: 0;
property<string> title <=> label.text;
property<int> current-focused: fs.has-focus ? fs.focused-tab : -1; // The currently focused tab
width: 180px;
forward-focus: fs;
accessible-role: tab;
accessible-delegate-focus: current-focused >= 0 ? current-focused : current-item;
Rectangle {
background: StyleMetrics.window-background.darker(0.2);
fs := FocusScope {
width: 0px; // Do not react on clicks
property<int> focused-tab: 0;
key-pressed(event) => {
if (event.text == "\n") {
current-item = current-focused;
return accept;
}
if (event.text == Keys.UpArrow) {
focused-tab = Math.max(focused-tab - 1, 0);
return accept;
}
if (event.text == Keys.DownArrow) {
focused-tab = Math.min(focused-tab + 1, model.length - 1);
return accept;
}
return reject;
}
key-released(event) => {
if (event.text == " ") {
current-item = current-focused;
return accept;
}
return reject;
}
}
}
VerticalLayout {
padding-top: StyleMetrics.layout-padding;
padding-bottom: StyleMetrics.layout-padding;
spacing: StyleMetrics.layout-spacing;
alignment: start;
label := Text {
font-size: 16px;
horizontal-alignment: center;
}
navigation := VerticalLayout {
alignment: start;
vertical-stretch: 0;
for item[index] in model : SideBarItem {
has-focus: index == root.current-focused;
text: item;
selected: index == current-item;
clicked => { current-item = index; }
}
}
VerticalLayout {
bottom := VerticalLayout {
padding-left: StyleMetrics.layout-padding;
padding-right: StyleMetrics.layout-padding;
@children
}
}
}
}

View file

@ -14,7 +14,7 @@ export global StyleMetrics := {
property<length> layout-padding: 8px;
property<length> text-cursor-width: 2px;
property<color> default-text-color: md.sys.color.primary;
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;

View file

@ -65,7 +65,7 @@ export CheckBox := Rectangle {
}
label := Text {
color: md.sys.color.primary;
color: md.sys.color.on-surface;
horizontal-alignment: left;
vertical-alignment: center;
vertical-stretch: 1;

View file

@ -8,20 +8,31 @@ export GroupBox := Rectangle {
property <string> title <=> label.text;
property<bool> enabled: true;
min-width: max(label-container.width + 16px, layout.min-width);
VerticalLayout {
padding-top: label-container.height + 16px;
padding-left: 16px;
padding-right: 16px;
padding-bottom: 16px;
Rectangle {
vertical-stretch: 1;
GridLayout {
@children
}
}
}
container := Rectangle {
border-radius: 4px;
border-width: 1px;
border-color: md.sys.color.outline;
y: layout.padding-top;
width: layout.width;
height: layout.height - layout.padding-top;
y: label-container.y + label-container.height / 2;
width: 100%;
height: parent.height - label-container.height / 2;
}
label-container := Rectangle {
x: 8px;
y: container.y;
width: label.width + 8px;
height: label.height + 8px;
background: md.sys.color.background;
@ -38,17 +49,6 @@ export GroupBox := Rectangle {
}
}
layout := HorizontalLayout {
padding-top: label-container.height / 2;
GridLayout {
padding-top: 16pt + label-container.height / 2;
padding-left: 16px;
padding-right: 16px;
padding-bottom: 16px;
@children
}
}
states [
disabled when !enabled : {
container.border-color: md.sys.color.on-surface;