Added Spinner widget (#3871)

This commit is contained in:
Florian Blasius 2023-11-07 15:04:24 +01:00 committed by GitHub
parent 3c9dca6daf
commit 110689bad1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 217 additions and 5 deletions

View file

@ -27,6 +27,7 @@ All notable changes to this project are documented in this file.
- `SpinBox` value can now be incremented and decremented by scroll event - `SpinBox` value can now be incremented and decremented by scroll event
- Added `focus-changed-event` callback to `FocusScope` - Added `focus-changed-event` callback to `FocusScope`
- Added many new easing curves. - Added many new easing curves.
- Added `Spinner`
### Rust ### Rust

View file

@ -24,6 +24,7 @@ Widgets
scrollview.md scrollview.md
slider.md slider.md
spinbox.md spinbox.md
spinner.md
standardbutton.md standardbutton.md
standardlistview.md standardlistview.md
standardtableview.md standardtableview.md

View file

@ -0,0 +1,24 @@
<!-- Copyright © SixtyFPS GmbH <info@slint.dev> ; SPDX-License-Identifier: MIT -->
## `Spinner`
The `Spinner` informs the user about the status of an on-going operation, such as loading data from the network. It provides the same properties as
[`ProgressIndicator`](./progressindicator.md) but differs in shape.
### Properties
- **`indeterminate`**: (_in_ _bool_): Set to true if the progress of the operation cannot be determined by value (default value: `false`).
- **`progress`** (_in_ _float_): Percentage of completion, as value between 0 and 1. Values less than 0 or greater than 1 are capped.
### Example
```slint
import { Spinner } from "std-widgets.slint";
export component Example inherits Window {
width: 200px;
height: 25px;
Spinner {
progress: 50%;
}
}
```

View file

@ -2,7 +2,7 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
import { Button, GroupBox, SpinBox, ComboBox, CheckBox, LineEdit, TabWidget, VerticalBox, HorizontalBox, import { Button, GroupBox, SpinBox, ComboBox, CheckBox, LineEdit, TabWidget, VerticalBox, HorizontalBox,
Slider, ProgressIndicator, SpinBox, Switch } from "std-widgets.slint"; Slider, ProgressIndicator, SpinBox, Switch, Spinner, GridBox } from "std-widgets.slint";
import { GallerySettings } from "../gallery_settings.slint"; import { GallerySettings } from "../gallery_settings.slint";
import { Page } from "page.slint"; import { Page } from "page.slint";
@ -106,19 +106,33 @@ export component ControlsPage inherits Page {
} }
GroupBox { GroupBox {
title: @tr("ProgressIndicator"); title: @tr("ProgressIndicator | Spinner");
vertical-stretch: 0; vertical-stretch: 0;
VerticalLayout { GridBox {
spacing: 16px; spacing: 16px;
i-progress-indicator := ProgressIndicator { i-progress-indicator := ProgressIndicator {
row: 0;
col: 0;
min-width: 160px; min-width: 160px;
progress: (i-slider.value - i-slider.minimum) / (i-slider.maximum - i-slider.minimum); progress: (i-slider.value - i-slider.minimum) / (i-slider.maximum - i-slider.minimum);
indeterminate: true; indeterminate: true;
} }
Rectangle {
row: 0;
col: 1;
rowspan: 2;
Spinner {
progress: i-progress-indicator.progress;
indeterminate: i-progress-indicator.indeterminate;
}
}
CheckBox { CheckBox {
row: 1;
col: 0;
text: @tr("indeterminate"); text: @tr("indeterminate");
checked <=> i-progress-indicator.indeterminate; checked <=> i-progress-indicator.indeterminate;
} }

View file

@ -0,0 +1,65 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial
export component SpinnerBase {
in property <float> progress;
in property <bool> indeterminate;
in property <length> stroke-width <=> path.stroke-width;
in property <brush> stroke <=> path.stroke;
path := Path {
private property <float> radius: min(self.viewbox-width, self.viewbox-height) / 2;
private property <float> start-x: self.viewbox-width / 2;
private property <float> start-y: self.viewbox-height / 2;
private property <float> thickness: 2;
private property <float> inner-radius: self.radius - self.thickness;
private property <float> start : !indeterminate ? 0 :
1 * mod(animation-tick(), 3s) / 3s;
// min is a workaground to get filled circle by 1.0
private property <float> progress: !root.indeterminate ? min(0.999, root.progress) :
min(0.99, max(0.25, 1 * abs(sin(360deg * animation-tick() / 1.5s))));
viewbox-width: 100;
viewbox-height: 100;
width: 100%;
height: 100%;
MoveTo {
x: start-x - radius * sin(-path.start * 360deg);
y: start-y - radius * cos(-path.start * 360deg);
}
LineTo {
x: start-x - path.inner-radius * sin(-path.start * 360deg);
y: start-y - path.inner-radius * cos(-path.start * 360deg);
}
ArcTo {
radius-x: path.inner-radius;
radius-y: path.inner-radius;
x: start-x - path.inner-radius * sin(-(path.start + path.progress) * 360deg);
y: start-y - path.inner-radius * cos(-(path.start + path.progress) * 360deg);
sweep: path.progress > 0;
large-arc: path.progress > 0.5;
}
LineTo {
x: start-x - radius * sin(-(path.start + path.progress) * 360deg);
y: start-y - radius * cos(-(path.start + path.progress) * 360deg);
}
ArcTo {
radius-x: radius;
radius-y: radius;
x: start-x - radius * sin(-path.start * 360deg);
y: start-y - radius * cos(-path.start * 360deg);
sweep: path.progress < 0;
large-arc: path.progress > 0.5;
}
LineTo {
x: start-x - radius * sin(-path.start * 360deg);
y: start-y - radius * cos(-path.start * 360deg);
}
}
}

View file

@ -0,0 +1,24 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial
import { Palette } from "styling.slint";
import { SpinnerBase } from "../common/spinner-base.slint";
export component Spinner {
in property <float> progress <=> base.progress;
in property <bool> indeterminate <=> base.indeterminate;
min-width: 30px;
min-height: 30px;
horizontal-stretch: 0;
vertical-stretch: 0;
accessible-role: progress-indicator;
accessible-value: root.progress;
base := SpinnerBase {
width: 100%;
height: 100%;
stroke-width: 2px;
stroke: Palette.accent;
}
}

View file

@ -31,6 +31,9 @@ export { Slider }
import { SpinBox } from "spinbox.slint"; import { SpinBox } from "spinbox.slint";
export { SpinBox } export { SpinBox }
import { Spinner } from "spinner.slint";
export { Spinner }
import { TabWidgetImpl, TabImpl, TabBarImpl, TabWidget } from "tabwidget.slint"; import { TabWidgetImpl, TabImpl, TabBarImpl, TabWidget } from "tabwidget.slint";
export { TabWidgetImpl, TabImpl, TabBarImpl, TabWidget } export { TabWidgetImpl, TabImpl, TabBarImpl, TabWidget }

View file

@ -0,0 +1,24 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial
import { Palette } from "styling.slint";
import { SpinnerBase } from "../common/spinner-base.slint";
export component Spinner {
in property <float> progress <=> base.progress;
in property <bool> indeterminate <=> base.indeterminate;
min-width: 30px;
min-height: 30px;
horizontal-stretch: 0;
vertical-stretch: 0;
accessible-role: progress-indicator;
accessible-value: root.progress;
base := SpinnerBase {
width: 100%;
height: 100%;
stroke-width: 2px;
stroke: Palette.accent-default;
}
}

View file

@ -31,6 +31,9 @@ export { Slider }
import { SpinBox } from "spinbox.slint"; import { SpinBox } from "spinbox.slint";
export { SpinBox } export { SpinBox }
import { Spinner } from "spinner.slint";
export { Spinner }
import { TabWidgetImpl, TabImpl, TabBarImpl, TabWidget } from "tabwidget.slint"; import { TabWidgetImpl, TabImpl, TabBarImpl, TabWidget } from "tabwidget.slint";
export { TabWidgetImpl, TabImpl, TabBarImpl, TabWidget } export { TabWidgetImpl, TabImpl, TabBarImpl, TabWidget }

View file

@ -10,7 +10,7 @@ export component ProgressIndicator {
min-height: 4px; min-height: 4px;
horizontal-stretch: 1; horizontal-stretch: 1;
vertical-stretch: 0; vertical-stretch: 0;
accessible-role: none; accessible-role: progress-indicator;
accessible-value: root.progress; accessible-value: root.progress;
i-background := Rectangle { i-background := Rectangle {

View file

@ -0,0 +1,24 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial
import { Palette } from "styling.slint";
import { SpinnerBase } from "../common/spinner-base.slint";
export component Spinner {
in property <float> progress <=> base.progress;
in property <bool> indeterminate <=> base.indeterminate;
min-width: 30px;
min-height: 30px;
horizontal-stretch: 0;
vertical-stretch: 0;
accessible-role: progress-indicator;
accessible-value: root.progress;
base := SpinnerBase {
width: 100%;
height: 100%;
stroke-width: 2px;
stroke: Palette.primary;
}
}

View file

@ -21,3 +21,6 @@ import { Switch } from "switch.slint";
export { StyleMetrics, ScrollView, Button, ComboBox, CheckBox, GroupBox, StandardButton, TextEdit, TabWidgetImpl, export { StyleMetrics, ScrollView, Button, ComboBox, CheckBox, GroupBox, StandardButton, TextEdit, TabWidgetImpl,
TabImpl, TabBarImpl, TabWidget, LineEdit, AboutSlint, VerticalBox, HorizontalBox, TabImpl, TabBarImpl, TabWidget, LineEdit, AboutSlint, VerticalBox, HorizontalBox,
GridBox, Slider, ListView, StandardListView, StandardTableView, SpinBox, ProgressIndicator, Switch } GridBox, Slider, ListView, StandardListView, StandardTableView, SpinBox, ProgressIndicator, Switch }
import { Spinner } from "spinner.slint";
export { Spinner }

View file

@ -0,0 +1,23 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial
import { SpinnerBase } from "../common/spinner-base.slint";
export component Spinner {
in property <float> progress <=> base.progress;
in property <bool> indeterminate <=> base.indeterminate;
min-width: 30px;
min-height: 30px;
horizontal-stretch: 0;
vertical-stretch: 0;
accessible-role: progress-indicator;
accessible-value: root.progress;
base := SpinnerBase {
width: 100%;
height: 100%;
stroke-width: 2px;
stroke: NativeStyleMetrics.dark-color-scheme ? #60CDFF : #005FB8;
}
}

View file

@ -40,4 +40,7 @@ import { HorizontalBox, VerticalBox, GridBox } from "layouts.slint";
export { HorizontalBox, VerticalBox, GridBox } export { HorizontalBox, VerticalBox, GridBox }
import { ProgressIndicator } from "progressindicator.slint"; import { ProgressIndicator } from "progressindicator.slint";
export { ProgressIndicator } export { ProgressIndicator }
import { Spinner } from "spinner.slint";
export { Spinner }