added usecases demo (#7603)
* [autofix.ci] apply automated fixes * Update demos/usecases/esp-idf/README.md Co-authored-by: Olivier Goffart <olivier.goffart@slint.dev> * Update demos/usecases/esp-idf/rust-toolchain.toml Co-authored-by: Olivier Goffart <olivier.goffart@slint.dev> --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Olivier Goffart <olivier.goffart@slint.dev>
3
.github/workflows/wasm_demos.yaml
vendored
|
@ -46,7 +46,7 @@ jobs:
|
|||
- name: Remaining wasm demos
|
||||
if: ${{ inputs.build_artifacts }}
|
||||
run: |
|
||||
for demo in demos/printerdemo/rust examples/todo/rust examples/todo-mvc/rust examples/carousel/rust examples/slide_puzzle examples/memory examples/imagefilter/rust examples/plotter examples/opengl_underlay demos/home-automation/rust; do
|
||||
for demo in demos/printerdemo/rust demos/usecases/rust examples/todo/rust examples/todo-mvc/rust examples/carousel/rust examples/slide_puzzle examples/memory examples/imagefilter/rust examples/plotter examples/opengl_underlay demos/home-automation/rust; do
|
||||
pushd $demo
|
||||
sed -i "s/#wasm# //" Cargo.toml
|
||||
wasm-pack build --release --target web
|
||||
|
@ -82,6 +82,7 @@ jobs:
|
|||
demos/energy-monitor/
|
||||
demos/home-automation/rust
|
||||
demos/weather-demo/
|
||||
demos/usecases/rust
|
||||
!/**/.gitignore
|
||||
- name: Clean cache # Otherwise the cache is much too big
|
||||
run: |
|
||||
|
|
|
@ -32,6 +32,7 @@ members = [
|
|||
'examples/mcu-board-support',
|
||||
'examples/uefi-demo',
|
||||
'demos/weather-demo',
|
||||
'demos/usecases/rust',
|
||||
'helper_crates/const-field-offset',
|
||||
'helper_crates/vtable',
|
||||
'helper_crates/vtable/macro',
|
||||
|
|
|
@ -190,6 +190,7 @@ path = [
|
|||
"internal/compiler/widgets/cupertino/_**.svg",
|
||||
"internal/compiler/widgets/qt/_**.svg",
|
||||
"examples/todo-mvc/assets/**.svg",
|
||||
"demos/usecases/ui/assets/**.svg"
|
||||
]
|
||||
precedence = "aggregate"
|
||||
SPDX-FileCopyrightText = "Material Icons <https://github.com/material-icons/material-icons/blob/master/LICENSE>"
|
||||
|
|
|
@ -11,6 +11,7 @@ These demos showcase different complex use-cases for building UIs with Slint.
|
|||
| [Printer UI ](./printerdemo) | A fictional user interface for the touch screen of a printer. <br/> [Project...](./printerdemo) | [Wasm Demo](https://slint.dev/snapshots/master/demos/printerdemo/) |
|
||||
| [Energy Meter](./energy-monitor/) | A fictional user interface of a device that monitors energy consumption in a building. <br/> [Project...](./energy-monitor) | [Wasm Demo](https://slint.dev/snapshots/master/demos/energy-monitor/) |
|
||||
| [Weather](./weather-demo/) | A simple, cross-platform (Desktop, Android, Wasm) weather application using real weather data from the [OpenWeather](https://openweathermap.org/) API. <br/> [Project...](./weather-demo/) | [Wasm Demo](https://slint.dev/snapshots/master/demos/weather-demo/) |
|
||||
| [Usecases ](./usecases) | Different example use cases in one app. <br/> [Project...](./usecases) | [Wasm Demo](https://slint.dev/snapshots/master/demos/usecases/) |
|
||||
|
||||
---
|
||||
### Running the Rust Demos
|
||||
|
|
1
demos/usecases/cpp/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
build
|
15
demos/usecases/cpp/CMakeLists.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required(VERSION 3.21)
|
||||
project(slint_cpp_usecases LANGUAGES CXX)
|
||||
|
||||
if (NOT TARGET Slint::Slint)
|
||||
find_package(Slint REQUIRED)
|
||||
endif()
|
||||
|
||||
set(SLINT_STYLE "cosmic-light" CACHE STRING "Style for demo" FORCE)
|
||||
|
||||
add_executable(usecases main.cpp)
|
||||
target_link_libraries(usecases PRIVATE Slint::Slint)
|
||||
slint_target_sources(usecases ../ui/app.slint)
|
85
demos/usecases/cpp/main.cpp
Normal file
|
@ -0,0 +1,85 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "app.h"
|
||||
|
||||
void init_virtual_keyboard(slint::ComponentHandle<App> app)
|
||||
{
|
||||
app->global<VirtualKeyboardHandler>().on_key_pressed([=](auto key) {
|
||||
app->window().dispatch_key_press_event(key);
|
||||
app->window().dispatch_key_release_event(key);
|
||||
});
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
auto app = App::create();
|
||||
|
||||
init_virtual_keyboard(app);
|
||||
|
||||
auto mails = std::make_shared<slint::VectorModel<CardListViewItem>>(std::vector {
|
||||
CardListViewItem { "Simon Hausmann", "1 hour ago", "Meeting tomorrow",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
|
||||
"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
|
||||
"enim ad minim veniam, quis nostrud exercitation ullamco laboris "
|
||||
"nisi ut aliquip ex ea commodo consequat." },
|
||||
CardListViewItem { "Tobias Hunger", "1 day ago", "Meeting tomorrow",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
|
||||
"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
|
||||
"enim ad minim veniam, quis nostrud exercitation ullamco laboris "
|
||||
"nisi ut aliquip ex ea commodo consequat." },
|
||||
CardListViewItem { "Olivier Goffart", "2 hour ago", "Meeting tomorrow",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
|
||||
"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
|
||||
"enim ad minim veniam, quis nostrud exercitation ullamco laboris "
|
||||
"nisi ut aliquip ex ea commodo consequat." },
|
||||
CardListViewItem { "Aurindam Jana", "5 hour ago", "Meeting tomorrow",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
|
||||
"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
|
||||
"enim ad minim veniam, quis nostrud exercitation ullamco laboris "
|
||||
"nisi ut aliquip ex ea commodo consequat." },
|
||||
CardListViewItem { "Simon Hausmann", "7 hour ago", "Meeting tomorrow",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
|
||||
"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
|
||||
"enim ad minim veniam, quis nostrud exercitation ullamco laboris "
|
||||
"nisi ut aliquip ex ea commodo consequat." },
|
||||
CardListViewItem { "Tobias Hunger", "1 day ago", "Meeting tomorrow",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
|
||||
"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
|
||||
"enim ad minim veniam, quis nostrud exercitation ullamco laboris "
|
||||
"nisi ut aliquip ex ea commodo consequat." },
|
||||
CardListViewItem { "Olivier Goffart", "8 hour ago", "Meeting tomorrow",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
|
||||
"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
|
||||
"enim ad minim veniam, quis nostrud exercitation ullamco laboris "
|
||||
"nisi ut aliquip ex ea commodo consequat." },
|
||||
CardListViewItem { "Aurindam Jana", "9 hour ago", "Meeting tomorrow",
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
|
||||
"eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut "
|
||||
"enim ad minim veniam, quis nostrud exercitation ullamco laboris "
|
||||
"nisi ut aliquip ex ea commodo consequat." },
|
||||
});
|
||||
|
||||
app->global<MailBoxViewAdapter>().set_mails(mails);
|
||||
|
||||
app->global<MailBoxViewAdapter>().on_search_text_changed(
|
||||
[mails, app = slint::ComponentWeakHandle(app)](const slint::SharedString &text) {
|
||||
auto app_lock = app.lock();
|
||||
|
||||
std::string text_str(text.data());
|
||||
|
||||
(*app_lock)->global<MailBoxViewAdapter>().set_mails(
|
||||
std::make_shared<slint::FilterModel<CardListViewItem>>(
|
||||
mails, [text_str](auto e) {
|
||||
std::string title_str(e.title.data());
|
||||
return title_str.find(text_str) != std::string::npos;
|
||||
}));
|
||||
});
|
||||
|
||||
app->run();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
run();
|
||||
}
|
6
demos/usecases/esp-idf/.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
build
|
||||
managed_components
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
dependencies.lock
|
||||
.cache
|
15
demos/usecases/esp-idf/CMakeLists.txt
Normal file
|
@ -0,0 +1,15 @@
|
|||
# Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
set(SLINT_ESP_LOCAL_EXAMPLE ON)
|
||||
set(SLINT_FEATURE_EXPERIMENTAL ON)
|
||||
set(EXTRA_COMPONENT_DIRS ../../../api/cpp/esp-idf/)
|
||||
set(SLINT_STYLE "cosmic-light" CACHE STRING "Style for demo" FORCE)
|
||||
|
||||
add_compile_options(-fdiagnostics-color=always)
|
||||
|
||||
project(slint_esp_usecases_mcu LANGUAGES CXX)
|
8
demos/usecases/esp-idf/README.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
<!-- Copyright © SixtyFPS GmbH <info@slint.dev> ; SPDX-License-Identifier: MIT -->
|
||||
|
||||
# Building
|
||||
|
||||
```
|
||||
cd demos/usecases/esp-idf
|
||||
SLINT_SCALE_FACTOR=2 idf.py flash monitor
|
||||
```
|
12
demos/usecases/esp-idf/main/CMakeLists.txt
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
|
||||
idf_component_register(
|
||||
SRCS "main.cpp"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES esp32_p4_function_ev_board_noglib slint
|
||||
)
|
||||
|
||||
slint_target_sources(${COMPONENT_LIB} ../../ui/app.slint)
|
||||
target_link_options(${COMPONENT_LIB} PUBLIC -Wl,--allow-multiple-definition)
|
7
demos/usecases/esp-idf/main/idf_component.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
# Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
idf: ">=5.1"
|
||||
espressif/esp32_p4_function_ev_board_noglib: "^1.0.0"
|
48
demos/usecases/esp-idf/main/main.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include "../../cpp/main.cpp"
|
||||
|
||||
#include "slint-esp.h"
|
||||
#include <ctime>
|
||||
#include <memory>
|
||||
#include "esp_log.h"
|
||||
|
||||
#include <slint-platform.h>
|
||||
|
||||
#include <bsp/display.h>
|
||||
#include <bsp/esp-bsp.h>
|
||||
#include <bsp/touch.h>
|
||||
#include <vector>
|
||||
|
||||
#undef BSP_LCD_H_RES
|
||||
#define BSP_LCD_H_RES 800
|
||||
#undef BSP_LCD_V_RES
|
||||
#define BSP_LCD_V_RES 1280
|
||||
|
||||
extern "C" void app_main(void)
|
||||
{
|
||||
|
||||
/* Initialize I2C (for touch and audio) */
|
||||
bsp_i2c_init();
|
||||
|
||||
/* Initialize display */
|
||||
esp_lcd_panel_handle_t panel_handle = NULL;
|
||||
bsp_lcd_handles_t handles {};
|
||||
|
||||
bsp_display_new_with_handles(nullptr, &handles);
|
||||
|
||||
esp_lcd_touch_handle_t touch_handle = NULL;
|
||||
const bsp_touch_config_t bsp_touch_cfg = {};
|
||||
bsp_touch_new(&bsp_touch_cfg, &touch_handle);
|
||||
|
||||
panel_handle = handles.panel;
|
||||
|
||||
/* Set display brightness to 100% */
|
||||
bsp_display_backlight_on();
|
||||
|
||||
slint_esp_init(slint::PhysicalSize({ BSP_LCD_H_RES, BSP_LCD_V_RES }), panel_handle,
|
||||
touch_handle);
|
||||
|
||||
run();
|
||||
}
|
5
demos/usecases/esp-idf/rust-toolchain.toml
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
[toolchain]
|
||||
channel = "esp"
|
80
demos/usecases/esp-idf/sdkconfig.defaults
Normal file
|
@ -0,0 +1,80 @@
|
|||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
||||
#
|
||||
CONFIG_IDF_TARGET="esp32p4"
|
||||
|
||||
# CONFIG_SPIRAM=y
|
||||
# CONFIG_SPIRAM_MODE_HEX=y
|
||||
# CONFIG_SPIRAM_SPEED_200M=y
|
||||
# CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
||||
#
|
||||
# CONFIG_LV_CONF_SKIP=y
|
||||
#
|
||||
# #CLIB default
|
||||
# CONFIG_LV_USE_CLIB_MALLOC=y
|
||||
# CONFIG_LV_USE_CLIB_SPRINTF=y
|
||||
# CONFIG_LV_USE_CLIB_STRING=y
|
||||
#
|
||||
# # Performance monitor
|
||||
# CONFIG_LV_USE_OBSERVER=y
|
||||
# CONFIG_LV_USE_SYSMON=y
|
||||
# CONFIG_LV_USE_PERF_MONITOR=y
|
||||
#
|
||||
#
|
||||
# # CONFIG_LV_BUILD_EXAMPLES is not set
|
||||
#
|
||||
CONFIG_MAIN_TASK_STACK_SIZE=20584
|
||||
# #CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
|
||||
CONFIG_ESPTOOLPY_FLASHSIZE="4MB"
|
||||
CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE=y
|
||||
#
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
|
||||
|
||||
|
||||
CONFIG_IDF_TARGET="esp32p4"
|
||||
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
|
||||
#CONFIG_COMPILER_OPTIMIZATION_PERF=y
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_MODE_OCT=y
|
||||
CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
|
||||
CONFIG_SPIRAM_RODATA=y
|
||||
CONFIG_SPIRAM_SPEED_80M=y
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_BSP_LCD_RGB_BUFFER_NUMS=2
|
||||
CONFIG_BSP_LCD_RGB_BOUNCE_BUFFER_MODE=y
|
||||
CONFIG_BSP_DISPLAY_LVGL_AVOID_TEAR=y
|
||||
CONFIG_BSP_DISPLAY_LVGL_DIRECT_MODE=y
|
||||
CONFIG_LV_FONT_MONTSERRAT_12=y
|
||||
CONFIG_LV_FONT_MONTSERRAT_16=y
|
||||
CONFIG_LV_FONT_MONTSERRAT_24=y
|
||||
CONFIG_LV_USE_DEMO_WIDGETS=y
|
||||
CONFIG_LV_USE_DEMO_BENCHMARK=y
|
||||
CONFIG_LV_USE_DEMO_STRESS=y
|
||||
CONFIG_LV_USE_DEMO_MUSIC=y
|
||||
CONFIG_LV_DEMO_MUSIC_AUTO_PLAY=y
|
||||
CONFIG_LV_ATTRIBUTE_FAST_MEM_USE_IRAM=y
|
||||
CONFIG_LV_DISP_DEF_REFR_PERIOD=10
|
||||
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_MODE_HEX=y
|
||||
CONFIG_SPIRAM_SPEED_200M=y
|
||||
CONFIG_IDF_EXPERIMENTAL_FEATURES=y
|
||||
|
||||
## LVGL8 ##
|
||||
CONFIG_LV_MEM_SIZE_KILOBYTES=48
|
||||
CONFIG_LV_USE_PERF_MONITOR=y
|
||||
|
||||
## LVGL9 ##
|
||||
CONFIG_LV_CONF_SKIP=y
|
||||
|
||||
#CLIB default
|
||||
CONFIG_LV_USE_CLIB_MALLOC=y
|
||||
CONFIG_LV_USE_CLIB_SPRINTF=y
|
||||
CONFIG_LV_USE_CLIB_STRING=y
|
||||
|
||||
# Performance monitor
|
||||
#CONFIG_LV_USE_OBSERVER=y
|
||||
#CONFIG_LV_USE_SYSMON=y
|
||||
#CONFIG_LV_USE_PERF_MONITOR=y
|
34
demos/usecases/rust/Cargo.toml
Normal file
|
@ -0,0 +1,34 @@
|
|||
# Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
[package]
|
||||
name = "usecases"
|
||||
version = "1.10.0"
|
||||
authors = ["Slint Developers <info@slint.dev>"]
|
||||
edition = "2021"
|
||||
build = "build.rs"
|
||||
publish = false
|
||||
license = "MIT"
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "cdylib"]
|
||||
path = "src/lib.rs"
|
||||
name = "usecases_lib"
|
||||
|
||||
[[bin]]
|
||||
path = "src/main.rs"
|
||||
name = "usecases"
|
||||
|
||||
[dependencies]
|
||||
slint = { path = "../../../api/rs/slint", features = ["serde"] }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
wasm-bindgen = { version = "0.2" }
|
||||
console_error_panic_hook = "0.1.5"
|
||||
|
||||
[build-dependencies]
|
||||
slint-build = { path = "../../../api/rs/build" }
|
||||
|
||||
|
12
demos/usecases/rust/build.rs
Normal file
|
@ -0,0 +1,12 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use slint_build::CompilerConfiguration;
|
||||
|
||||
fn main() {
|
||||
slint_build::compile_with_config(
|
||||
"../ui/app.slint",
|
||||
CompilerConfiguration::new().with_style("cosmic".into()),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
40
demos/usecases/rust/index.html
Normal file
|
@ -0,0 +1,40 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<!-- Copyright © SixtyFPS GmbH <info@slint.dev> -->
|
||||
<!-- SPDX-License-Identifier: MIT -->
|
||||
|
||||
<html>
|
||||
<!--
|
||||
This is a static html file used to display the wasm build.
|
||||
In order to generate the build
|
||||
- Run `wasm-pack build --release --target web` in this directory.
|
||||
-->
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Slint use cases Demo (Web Assembly version)</title>
|
||||
<link rel="stylesheet" href="https://slint.dev/css/demos-v1.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p>This is the <a href="https://slint.dev">Slint</a> Use cases Demo compiled to WebAssembly.</p>
|
||||
<div id="spinner" style="position: relative;">
|
||||
<div class="spinner">Loading...</div>
|
||||
</div>
|
||||
<canvas id="canvas" unselectable="on" data-slint-auto-resize-to-preferred="true"></canvas>
|
||||
<p class="links">
|
||||
<a href="https://github.com/slint-ui/slint/blob/master/demos/usecases/">
|
||||
View Source Code on GitHub</a> -
|
||||
<a href="https://slint.dev/editor?load_demo=demos/usecases/ui/app.slint">
|
||||
Open in SlintPad
|
||||
</a>
|
||||
</p>
|
||||
<script type="module">
|
||||
import init from './pkg/usecases_lib.js';
|
||||
init().finally(() => {
|
||||
document.getElementById("spinner").remove();
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
119
demos/usecases/rust/src/lib.rs
Normal file
|
@ -0,0 +1,119 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use wasm_bindgen::prelude::*;
|
||||
|
||||
slint::include_modules!();
|
||||
|
||||
#[cfg_attr(target_arch = "wasm32", wasm_bindgen(start))]
|
||||
pub fn main() {
|
||||
// This provides better error messages in debug mode.
|
||||
// It's disabled in release mode so it doesn't bloat up the file size.
|
||||
#[cfg(all(debug_assertions, target_arch = "wasm32"))]
|
||||
console_error_panic_hook::set_once();
|
||||
|
||||
let app = App::new().unwrap();
|
||||
|
||||
virtual_keyboard::init(&app);
|
||||
data::init(&app);
|
||||
|
||||
app.run().unwrap();
|
||||
}
|
||||
|
||||
mod virtual_keyboard {
|
||||
use super::*;
|
||||
use slint::*;
|
||||
|
||||
pub fn init(app: &App) {
|
||||
let weak = app.as_weak();
|
||||
app.global::<VirtualKeyboardHandler>().on_key_pressed({
|
||||
move |key| {
|
||||
weak.unwrap()
|
||||
.window()
|
||||
.dispatch_event(slint::platform::WindowEvent::KeyPressed { text: key.clone() });
|
||||
weak.unwrap()
|
||||
.window()
|
||||
.dispatch_event(slint::platform::WindowEvent::KeyReleased { text: key });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
mod data {
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::*;
|
||||
use slint::*;
|
||||
|
||||
pub fn init(app: &App) {
|
||||
let mail_box_adapter = MailBoxViewAdapter::get(app);
|
||||
|
||||
let message = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.".to_string();
|
||||
|
||||
let mails = VecModel::from_slice(&[
|
||||
CardListViewItem {
|
||||
title: "Simon Hausmann".into(),
|
||||
note: "1 hour ago".into(),
|
||||
sub_title: "Meeting tomorrow".into(),
|
||||
caption: message.clone().into(),
|
||||
},
|
||||
CardListViewItem {
|
||||
title: "Tobias Hunger".into(),
|
||||
note: "1 day ago".into(),
|
||||
sub_title: "Meeting tomorrow".into(),
|
||||
caption: message.clone().into(),
|
||||
},
|
||||
CardListViewItem {
|
||||
title: "Olivier Goffart".into(),
|
||||
note: "1 day".into(),
|
||||
sub_title: "Meeting tomorrow".into(),
|
||||
caption: message.clone().into(),
|
||||
},
|
||||
CardListViewItem {
|
||||
title: "Aurindam Jana".into(),
|
||||
note: "2 hour ago".into(),
|
||||
sub_title: "Meeting tomorrow".into(),
|
||||
caption: message.clone().into(),
|
||||
},
|
||||
CardListViewItem {
|
||||
title: "Simon Hausmann".into(),
|
||||
note: "5 hour ago".into(),
|
||||
sub_title: "Meeting tomorrow".into(),
|
||||
caption: message.clone().into(),
|
||||
},
|
||||
CardListViewItem {
|
||||
title: "Tobias Hunger".into(),
|
||||
note: "7 hours ago".into(),
|
||||
sub_title: "Meeting tomorrow".into(),
|
||||
caption: message.clone().into(),
|
||||
},
|
||||
CardListViewItem {
|
||||
title: "Olivier Goffart".into(),
|
||||
note: "8 hour ago".into(),
|
||||
sub_title: "Meeting tomorrow".into(),
|
||||
caption: message.clone().into(),
|
||||
},
|
||||
CardListViewItem {
|
||||
title: "Aurindam Jana".into(),
|
||||
note: "9 hour ago".into(),
|
||||
sub_title: "Meeting tomorrow".into(),
|
||||
caption: message.into(),
|
||||
},
|
||||
]);
|
||||
|
||||
mail_box_adapter.on_search_text_changed({
|
||||
let app_weak = app.as_weak();
|
||||
let mails = mails.clone();
|
||||
|
||||
move |text| {
|
||||
let mails = mails
|
||||
.clone()
|
||||
.filter(move |e| e.title.to_lowercase().contains(text.to_lowercase().as_str()));
|
||||
MailBoxViewAdapter::get(&app_weak.unwrap()).set_mails(Rc::new(mails).into());
|
||||
}
|
||||
});
|
||||
|
||||
mail_box_adapter.set_mails(mails.into());
|
||||
}
|
||||
}
|
9
demos/usecases/rust/src/main.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// In order to be compatible with both desktop, wasm, and android, the example is both a binary and a library.
|
||||
// Just forward to the library in main
|
||||
|
||||
fn main() {
|
||||
usecases_lib::main();
|
||||
}
|
31
demos/usecases/ui/app.slint
Normal file
|
@ -0,0 +1,31 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { MainView, MainViewAdapter, MailViewAdapter, MailBoxViewAdapter, DashboardViewAdapter } from "views.slint";
|
||||
export { MainViewAdapter, MailViewAdapter, MailBoxViewAdapter, DashboardViewAdapter }
|
||||
|
||||
import { CardListViewItem } from "widgets.slint";
|
||||
export { CardListViewItem }
|
||||
|
||||
import { VirtualKeyboardHandler, VirtualKeyboard } from "virtual_keyboard.slint";
|
||||
|
||||
export { VirtualKeyboardHandler }
|
||||
|
||||
export component App inherits Window {
|
||||
preferred-width: 800px;
|
||||
preferred-height: 1280px;
|
||||
title: "Slint usecases";
|
||||
|
||||
main-view := MainView {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
VirtualKeyboard {
|
||||
y: TextInputInterface.text-input-focused ? parent.height - self.height : parent.height;
|
||||
|
||||
close => {
|
||||
main-view.focus();
|
||||
}
|
||||
}
|
||||
}
|
21
demos/usecases/ui/assets.slint
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { Palette } from "std-widgets.slint";
|
||||
|
||||
export global Icons {
|
||||
out property <image> archive: @image-url("assets/archive.svg");
|
||||
out property <image> inbox: @image-url("assets/inbox.svg");
|
||||
out property <image> cloud: @image-url("assets/cloud.svg");
|
||||
out property <image> document: @image-url("assets/document.svg");
|
||||
out property <image> forward: @image-url("assets/forward.svg");
|
||||
out property <image> junk: @image-url("assets/junk.svg");
|
||||
out property <image> message: @image-url("assets/message.svg");
|
||||
out property <image> reply: @image-url("assets/reply.svg");
|
||||
out property <image> search: @image-url("assets/search.svg");
|
||||
out property <image> send: @image-url("assets/send.svg");
|
||||
out property <image> trash: @image-url("assets/trash.svg");
|
||||
out property <image> updates: @image-url("assets/updates.svg");
|
||||
out property <image> useres: @image-url("assets/users.svg");
|
||||
out property <image> slint-logo: Palette.color-scheme == ColorScheme.dark ? @image-url("../../../logo/slint-logo-simple-dark.png") : @image-url("../../../logo/slint-logo-simple-light.png");
|
||||
}
|
12
demos/usecases/ui/assets/archive.svg
Normal file
|
@ -0,0 +1,12 @@
|
|||
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_1527_4634)">
|
||||
<path d="M4 4.02002V9.02002H12V4.02002H4ZM5 5.02002L8 6.52002L10.998 5.02002V6.02002L8 7.52002L5 6.02002V5.02002Z" fill="#232323"/>
|
||||
<path d="M0 0.0200195H16V16.02H0V0.0200195Z" fill="#808080" fill-opacity="0.01"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.99998 1.02002C0.968978 1.08302 0.999978 2.02002 0.999978 2.02002V14.02C0.999978 14.02 0.968978 14.958 1.99998 15.02H14C15 15.02 15 14.02 15 14.02V2.02002C15 2.02002 15 1.02002 14 1.02002H7.99998H1.99998ZM2.99998 3.02002H13V10.02H9.99998C9.99998 11.128 9.10798 12.02 7.99998 12.02C6.89198 12.02 5.99998 11.128 5.99998 10.02H2.99998V3.02002Z" fill="#232323"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_1527_4634">
|
||||
<rect width="16" height="16" fill="white" transform="translate(0 0.0200195)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 907 B |
4
demos/usecases/ui/assets/arrow-circle-o-left.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<svg width="16" height="24" viewBox="0 0 1536 1792" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1152 800v192c0 17-15 32-32 32H768v192c0 18-14 32-32 32-9 0-17-4-24-10L393 919c-6-6-9-15-9-23s3-17 9-23l320-320c6-6 15-9 23-9 17 0 32 15 32 32v192h352c17 0 32 15 32 32zm160 96c0-300-244-544-544-544S224 596 224 896s244 544 544 544 544-244 544-544zm224 0c0 424-344 768-768 768S0 1320 0 896s344-768 768-768 768 344 768 768z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 433 B |
3
demos/usecases/ui/assets/arrow-left.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="24" viewBox="0 0 1536 1792" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1536 896v128c0 68-45 128-117 128H715l293 294c24 23 38 56 38 90s-14 67-38 90l-75 76c-23 23-56 37-90 37s-67-14-91-37l-651-652c-23-23-37-56-37-90s14-67 37-91l651-650c24-24 57-38 91-38s66 14 90 38l75 74c24 24 38 57 38 91s-14 67-38 91L715 768h704c72 0 117 60 117 128z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 375 B |
3
demos/usecases/ui/assets/arrow-right.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="24" viewBox="0 0 1536 1792" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1472 960c0 34-13 67-37 91l-651 651c-24 23-57 37-91 37s-66-14-90-37l-75-75c-24-24-38-57-38-91s14-67 38-91l293-293H117c-72 0-117-60-117-128V896c0-68 45-128 117-128h704L528 474c-24-23-38-56-38-90s14-67 38-90l75-75c24-24 56-38 90-38s67 14 91 38l651 651c24 23 37 56 37 90z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 380 B |
3
demos/usecases/ui/assets/arrow-up.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="24" viewBox="0 0 1536 1792" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1611 971c0 34-14 66-37 90l-75 75c-24 24-57 38-91 38s-67-14-90-38l-294-293v704c0 72-60 117-128 117H768c-68 0-128-45-128-117V843l-294 293c-23 24-56 38-90 38s-67-14-90-38l-75-75c-24-24-38-56-38-90s14-67 38-91l651-651c23-24 56-37 90-37s67 13 91 37l651 651c23 24 37 57 37 91z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 383 B |
3
demos/usecases/ui/assets/chevron-left.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="16" height="24" viewBox="0 0 1536 1792" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1171 301L640 832l531 531c25 25 25 65 0 90l-166 166c-25 25-65 25-90 0L173 877c-25-25-25-65 0-90L915 45c25-25 65-25 90 0l166 166c25 25 25 65 0 90z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 257 B |
12
demos/usecases/ui/assets/cloud.svg
Normal file
|
@ -0,0 +1,12 @@
|
|||
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_412_3753)">
|
||||
<path d="M11.0008 9.00299C9.68877 9.00299 8.59577 9.86099 8.18777 11.034C7.5573 11.1122 6.98046 11.4282 6.57499 11.9172C6.16951 12.4063 5.96597 13.0317 6.00591 13.6658C6.04585 14.2998 6.32626 14.8947 6.7899 15.3291C7.25354 15.7634 7.86546 16.0045 8.50077 16.003H13.5008C14.1361 16.0045 14.748 15.7634 15.2116 15.3291C15.6753 14.8947 15.9557 14.2998 15.9956 13.6658C16.0356 13.0317 15.832 12.4063 15.4266 11.9172C15.0211 11.4282 14.4442 11.1122 13.8138 11.034C13.4058 9.86099 12.3128 9.00299 11.0008 9.00299Z" fill="#232323"/>
|
||||
<path d="M0.000732422 0.00299072H16.0007V16.003H0.000732422V0.00299072Z" fill="#808080" fill-opacity="0.01"/>
|
||||
<path d="M7.00078 0.00299072L6.50078 1.03399C6.66278 1.02099 6.83578 1.00299 7.00078 1.00299H7.50078L7.00078 0.00299072ZM7.00078 2.00299C5.6747 2.00299 4.40293 2.52977 3.46525 3.46746C2.52756 4.40514 2.00078 5.67691 2.00078 7.00299C2.00078 9.25499 3.51078 11.125 5.55778 11.751C5.77778 11.431 6.05278 11.151 6.37178 10.917C6.40478 10.892 6.43578 10.867 6.46978 10.843C6.54378 10.793 6.61978 10.748 6.69778 10.703C6.95647 10.5387 7.23549 10.409 7.52778 10.317C7.59778 10.175 7.67778 10.037 7.76078 9.90299C8.22778 9.15499 8.90678 8.55799 9.72978 8.24499C9.72978 8.24432 9.72978 8.24366 9.72978 8.24299C9.73278 8.24299 9.73578 8.23999 9.73978 8.23899C9.90478 8.17699 10.0758 8.12599 10.2528 8.08899C10.2958 8.07899 10.3368 8.06699 10.3798 8.05899C10.5798 8.02499 10.7868 8.00299 11.0008 8.00299C11.1492 8.00189 11.2974 8.01361 11.4438 8.03799C11.5938 8.05599 11.7358 8.08599 11.8778 8.12199C11.9616 7.75461 12.0029 7.37881 12.0008 7.00199C12.0008 6.34538 11.8715 5.6952 11.6202 5.08857C11.3689 4.48195 11.0006 3.93075 10.5363 3.46646C10.072 3.00216 9.52082 2.63387 8.9142 2.38259C8.30757 2.13132 7.65739 2.00199 7.00078 2.00199V2.00299ZM2.06278 2.06499L2.40678 3.12799C2.62678 2.86799 2.86678 2.62799 3.12578 2.40899L2.06278 2.06499ZM11.9388 2.06499L10.8448 2.43999H10.7818C10.9218 2.55099 11.0568 2.66599 11.1878 2.78399C11.3188 2.90199 11.4458 3.02599 11.5628 3.15899L11.9388 2.06499ZM0.998779 6.50299L-0.0012207 7.00299L1.03078 7.50299C1.01578 7.33299 0.998779 7.17699 0.998779 7.00299C0.998779 6.97499 0.996779 6.91899 0.998779 6.84699C1.00478 6.73099 1.02178 6.61499 1.03078 6.50299H0.998779ZM12.9688 6.50299C12.9828 6.67299 12.9988 6.82899 12.9988 7.00299C12.9988 7.02999 13.0018 7.08699 12.9988 7.15899C12.9938 7.27499 12.9768 7.39099 12.9688 7.50299H12.9988L13.9988 7.00299L12.9688 6.50299ZM2.43678 10.847L2.06178 11.941L3.15578 11.566H3.21878C3.07878 11.455 2.94378 11.34 2.81278 11.222C2.68178 11.104 2.55478 10.98 2.43778 10.847H2.43678Z" fill="#232323"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_412_3753">
|
||||
<rect width="16" height="16.003" fill="white" transform="translate(0.000732422)"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 2.8 KiB |
11
demos/usecases/ui/assets/document.svg
Normal file
|
@ -0,0 +1,11 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_758_3659)">
|
||||
<path d="M0 0H16V16H0V0Z" fill="#808080" fill-opacity="0.01"/>
|
||||
<path d="M4 0.0100098C3.46957 0.0100098 2.96086 0.220723 2.58579 0.595796C2.21071 0.970869 2 1.47958 2 2.01001V13.01C2 13.5404 2.21071 14.0492 2.58579 14.4242C2.96086 14.7993 3.46957 15.01 4 15.01H12C13.09 15.01 13.974 14.136 13.996 13.051C14.006 11.957 14.001 7.62801 13.996 4.92101C13.9868 4.42272 13.7917 3.94586 13.449 3.58401L10.48 0.61501C10.2937 0.423568 10.0708 0.271401 9.82473 0.16749C9.5786 0.0635796 9.31416 0.0100324 9.047 0.0100098H4Z" fill="#232323"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_758_3659">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 776 B |
3
demos/usecases/ui/assets/expand-more.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24">
|
||||
<path d="M480-345 240-585l56-56 184 184 184-184 56 56-240 240Z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 162 B |
10
demos/usecases/ui/assets/forward.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_409_3651)">
|
||||
<path d="M9 1.5V4H6.5C3.5 4 1.5 6.127 1.5 9.25C1.5 12.5 5.5 14 5.5 14C5.5 14 3.625 11.348 4.062 10C4.428 8.873 5.635 8 7 8H9V10.5L15.469 6L9 1.5Z" fill="#232323"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_409_3651">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 410 B |
4
demos/usecases/ui/assets/globe.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<svg width="16" height="24" viewBox="0 0 1536 1792" xmlns="http://www.w3.org/2000/svg">
|
||||
<path style="isolation:auto;mix-blend-mode:normal" d="M768 132A768 768 0 0 0 0 900a768 768 0 0 0 768 768 768 768 0 0 0 768-768 768 768 0 0 0-768-768zm-30.951 218.365c9.385-.112 17.497 1.602 22.98 7.086 15.953 15.953 0 36.096 0 54.145 0 18.043 11.934 31.834 0 54.138-11.933 22.305-54.145 36.109-81.218 54.162-27.073 18.054-55.739 60.932-81.22 54.168-25.48-6.763-18.058-36.102-27.087-54.156-9.03-18.054-27.088-33.974-27.088-54.156 0-20.182 18.057-36.097 27.086-54.15 9.029-18.049 6.986-41.729 27.086-54.15 20.1-12.418 54.148 0 81.22 0 17.768 0 40.324-6.872 58.24-7.087zm-246.522 7.248c2.12-.025 4.402.367 6.153 1.836 4.001 3.358-7.403 15.827-7.403 24.692 0 8.859 4.175 16.505 0 26.588-4.175 10.088-18.323 18.346-27.484 27.525-9.161 9.173-149.752 112.129-85.02 112.129 64.734 0 93.621-48.513 111.664-30.46 18.043 18.05 54.132 15.958 54.13 54.145 0 38.187-91.657 100.044-127.614 136-8.99 8.995 8.52 99.463-5.63 99.463-14.234 0-46.426-53.233-56.837-43.99-19.962 14.474-12.25 6.042-25.662 24.291-13.205 31.884-23.332 47.702-23.332 65.87 0 18.167-4.412 49.432 1.793 57.495 6.21 8.063 4.603 1.247 6.346 1.68 1.744.541 101.388 5.68 129.27 12.644 27.88 6.964 75.031 10.414 101.384 25.327 26.353 14.913 36.39 36.377 54.586 54.566 18.195 18.19 50.943 32.198 54.586 54.563 3.645 22.369-17.489 35.068-26.234 52.607-8.746 17.534-16.694 39.307-26.237 52.601-9.542 13.289-18.517 18.624-27.777 27.938-9.26 9.308-13.872 1.84-27.777 27.936-13.906 26.068-19.612 98.011-27.051 135.19-5.74 28.689-7.021 93.82-16.553 122.079a640 640 0 0 1-101.818-58.666c-20.7-32.649-34.79-70.782-44.115-117.447-7.447-37.218-10.23-103.808-27.08-135.34-16.851-31.532-36.012-36.108-54.016-54.156-18.005-18.054-50.39-31.63-54.016-54.157-3.628-22.526 18.06-35.998 27.088-54.003 9.03-18 37.742-50.82 33.07-79.725-4.673-28.906-60.32-28.62-87.488-55.793-13.543-13.545-37.34-24.66-60.04-36.35A640 640 0 0 1 408.91 370.967c31.885-5.307 75.117-12.496 75.713-12.602.719 0 3.178-.72 5.904-.752zm721.407 82.36a640 640 0 0 1 193.172 404.123c-24.094-.828-50.922 37.807-76.243 54.693-26.99 18-52.17 56.852-80.972 53.998-28.804-2.87-35.98-35.994-53.971-53.988-17.99-18-33.87-45.68-53.97-53.992-20.101-8.307-44.911-6.64-54.16 0-9.25 6.736-4.425 9.054-4.474 13.78-.046 4.712-3.916 3.845 4.034 13.3 7.945 9.433 34.026 9.567 53.718 26.982 19.693 17.415 36.106 54.141 54.159 81.211 18.053 27.07 46.828 57.004 54.16 81.209 7.332 24.21 0 36.108 0 54.162 0 18.054 8.992 16.07 0 54.16-8.992 38.095-58.58 117.167-80.8 161.613-10.766 21.536-21.836 60.135-34.474 94.217a640 640 0 0 1-106.531 59.574c-103.19-32.356-61.234-157.588-75.14-230.7-7.205-36.06-26.53-132.523-27.116-134.96-.585-2.436-52.516-38.236-81.994-57.892-29.477-19.657-71.164-25.176-81.074-54.07-9.91-28.895 18.097-54.28 27.146-81.42 9.05-27.14-17.079-51.976 27.149-81.428 44.227-29.447 198.263 69.816 232.334 17.258 34.07-52.564-69.304-85.953-67.82-125.727 1.483-39.768 45.957-61.136 51.714-80.814 5.757-19.679 18.326-17.268 0-27.074-18.325-9.807-54.149 36.112-81.224 54.166-27.076 18.059-54.944 68.236-81.227 54.167-26.284-14.062 0-54.15 0-81.226 0-27.075-14.05-54.964 0-81.227 14.05-26.257 54.058-36.047 81.086-54.068 27.029-18.027 36.015-36.86 81.084-54.074 43.045-16.446 119.453-17.976 181.434-25.953z" color="#000" overflow="visible"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
12
demos/usecases/ui/assets/inbox.svg
Normal file
|
@ -0,0 +1,12 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_758_3671)">
|
||||
<path d="M0 0H16V16H0V0Z" fill="#808080" fill-opacity="0.01"/>
|
||||
<path d="M6 1V5H4L8 10L12 5H10V1H6Z" fill="#232323"/>
|
||||
<path d="M1.97996 5.98597C1.71508 5.99018 1.46272 6.09932 1.27824 6.28943C1.09375 6.47954 0.992207 6.73509 0.995949 6.99997V14C0.995949 14.2652 1.10132 14.5195 1.28886 14.7071C1.47639 14.8946 1.73073 15 1.99595 15H13.9959C14.2612 15 14.5156 14.8946 14.7031 14.7071C14.8906 14.5195 14.9959 14.2652 14.9959 14V6.99997C14.9959 5.67297 12.9959 5.67497 12.9959 6.99997V11H2.99595V6.99997C2.99784 6.86612 2.97288 6.73325 2.92246 6.60924C2.87205 6.48523 2.79724 6.3726 2.70249 6.27804C2.60774 6.18347 2.49494 6.10889 2.37083 6.05872C2.24672 6.00855 2.11381 5.98381 1.97996 5.98597ZM2.99595 12H12.9959V13H2.99595V12Z" fill="#232323"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_758_3671">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 990 B |
10
demos/usecases/ui/assets/junk.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_409_3649)">
|
||||
<path d="M5.219 1L4.906 1.28101L1.282 4.90601L1 5.21899V10.78L1.282 11.093L4.907 14.718L5.219 14.999H10.782L11.094 14.718L14.719 11.093L15 10.78V5.21997L14.719 4.90698L11.094 1.28198L10.781 1.00098H5.625L5.219 1ZM7 4H9V7L8.75 9H7.281L7.001 7L7 4ZM8 9.75C8.33152 9.75 8.64946 9.88167 8.88388 10.1161C9.11831 10.3505 9.25 10.6685 9.25 11C9.25 11.3315 9.11831 11.6495 8.88388 11.8839C8.64946 12.1183 8.33152 12.25 8 12.25C7.66848 12.25 7.35054 12.1183 7.11612 11.8839C6.8817 11.6495 6.75 11.3315 6.75 11C6.75 10.6685 6.8817 10.3505 7.11612 10.1161C7.35054 9.88167 7.66848 9.75 8 9.75Z" fill="#232323"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_409_3649">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 846 B |
10
demos/usecases/ui/assets/message.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_409_3645)">
|
||||
<path d="M2 2C0.892 2 0 2.892 0 4V12C0 13.108 0.892 14 2 14H14C15.108 14 16 13.108 16 12V4C16 2.892 15.108 2 14 2H2ZM2 4L8 7L14 4V6L8 9L2 6V4ZM4 7.996L5.25 8.635L2 11.996V9.996L4 7.996ZM12 7.996L14 9.996V11.996L10.75 8.635L12 7.996Z" fill="#232323"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_409_3645">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 497 B |
11
demos/usecases/ui/assets/reply.svg
Normal file
|
@ -0,0 +1,11 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_409_3644)">
|
||||
<path d="M7.00024 1.5L0.53125 6L7.00024 10.5V8H9.00024C9.19024 8 9.37625 8.01999 9.55925 8.05299C9.91925 7.64599 10.4232 7.353 10.9822 7.217L11.1122 6.785C11.2313 6.39332 11.4442 6.03663 11.7325 5.74594C12.0207 5.45525 12.3756 5.23935 12.7662 5.117C11.9212 4.404 10.8062 4 9.50024 4H7.00024V1.5ZM11.5002 9C11.4485 9.00139 11.3973 9.01048 11.3482 9.02699C11.5722 9.26999 11.7482 9.543 11.8692 9.84C11.9545 9.74739 12.0013 9.62585 12.0002 9.5C12.0002 9.212 11.7882 9 11.5002 9Z" fill="#232323"/>
|
||||
<path d="M13.5 6.00003C12.821 6.00003 12.255 6.45403 12.07 7.07203C12.985 7.29103 13.71 8.01703 13.928 8.93203C14.2744 8.83089 14.5725 8.60798 14.7675 8.30438C14.9624 8.00078 15.0411 7.63695 14.989 7.27992C14.9369 6.92289 14.7574 6.59672 14.4838 6.36152C14.2102 6.12632 13.8608 5.99794 13.5 6.00003ZM11.5 8.00003C11.1022 8.00003 10.7207 8.15807 10.4393 8.43937C10.158 8.72068 10 9.1022 10 9.50003C10 9.89785 10.158 10.2794 10.4393 10.5607C10.7207 10.842 11.1022 11 11.5 11C11.8978 11 12.2794 10.842 12.5607 10.5607C12.842 10.2794 13 9.89785 13 9.50003C13 9.1022 12.842 8.72068 12.5607 8.43937C12.2794 8.15807 11.8978 8.00003 11.5 8.00003ZM13.936 10.033C13.8164 10.5182 13.5562 10.9572 13.188 11.295C13.674 11.473 14.066 11.713 14.346 12H16V11.5C16 11.5 15.972 10.206 13.936 10.033ZM11.5 12C9 12 9 13.5 9 13.5V14H14V13.5C14 13.5 14 12 11.5 12Z" fill="#232323"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_409_3644">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
12
demos/usecases/ui/assets/search.svg
Normal file
|
@ -0,0 +1,12 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_758_3666)">
|
||||
<path d="M16 0H0V16H16V0Z" fill="#808080" fill-opacity="0.01"/>
|
||||
<path d="M11.7101 10.285L10.2881 11.707L13.298 14.717C14.257 15.654 15.663 14.217 14.704 13.279L11.7101 10.285Z" fill="#232323"/>
|
||||
<path d="M6.5 1C5.04131 1 3.64236 1.57946 2.61091 2.61091C1.57946 3.64236 1 5.04131 1 6.5C1 7.95869 1.57946 9.35764 2.61091 10.3891C3.64236 11.4205 5.04131 12 6.5 12C7.95869 12 9.35764 11.4205 10.3891 10.3891C11.4205 9.35764 12 7.95869 12 6.5C12 5.04131 11.4205 3.64236 10.3891 2.61091C9.35764 1.57946 7.95869 1 6.5 1ZM6.5 3C7.42826 3 8.3185 3.36875 8.97487 4.02513C9.63125 4.6815 10 5.57174 10 6.5C10 7.42826 9.63125 8.3185 8.97487 8.97487C8.3185 9.63125 7.42826 10 6.5 10C5.57174 10 4.6815 9.63125 4.02513 8.97487C3.36875 8.3185 3 7.42826 3 6.5C3 5.57174 3.36875 4.6815 4.02513 4.02513C4.6815 3.36875 5.57174 3 6.5 3Z" fill="#232323"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_758_3666">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
10
demos/usecases/ui/assets/send.svg
Normal file
|
@ -0,0 +1,10 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_409_3640)">
|
||||
<path d="M1 1V7L10 8L1 9V15L15 8L1 1Z" fill="#232323"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_409_3640">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 302 B |
11
demos/usecases/ui/assets/trash.svg
Normal file
|
@ -0,0 +1,11 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_758_3679)">
|
||||
<path d="M0 0H16V16H0V0Z" fill="#808080" fill-opacity="0.01"/>
|
||||
<path d="M1.82002 2.01C1.55923 2.05745 1.32796 2.20651 1.17701 2.4244C1.02607 2.64229 0.967803 2.91119 1.01502 3.17202L3.16502 14.994H12.834L14.984 3.17202C15.0074 3.04273 15.005 2.91008 14.9771 2.7817C14.9492 2.65331 14.8962 2.5317 14.8213 2.42379C14.7464 2.31587 14.6509 2.22379 14.5403 2.15279C14.4298 2.08179 14.3063 2.03326 14.177 2.01C13.9162 1.96278 13.6473 2.02104 13.4294 2.17199C13.2115 2.32293 13.0625 2.55424 13.015 2.81502L11.165 12.995H4.83403L2.98402 2.81502C2.96054 2.68569 2.91178 2.56224 2.84056 2.45177C2.76933 2.3413 2.677 2.24596 2.56889 2.17119C2.46078 2.09643 2.33899 2.0437 2.21049 2.01604C2.08199 1.98838 1.94931 1.98633 1.82002 2.01Z" fill="#232323"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_758_3679">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 987 B |
12
demos/usecases/ui/assets/updates.svg
Normal file
|
@ -0,0 +1,12 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_412_3773)">
|
||||
<path d="M0 0.00299072H16V16.003H0V0.00299072Z" fill="#808080" fill-opacity="0.01"/>
|
||||
<path d="M7.99999 0.723022C7.26199 1.45102 6.55499 2.28002 5.80899 3.00402H2.99999V5.81302C2.27499 6.55902 1.44699 7.26602 0.718994 8.00402C1.44699 8.74202 2.27499 9.47802 2.99999 10.227V13.004H5.80699C6.55399 13.729 7.26099 14.557 7.99999 15.285C8.73899 14.556 9.47499 13.729 10.225 13.005H13V10.227C13.725 9.47702 14.553 8.74302 15.281 8.00402C14.553 7.26602 13.725 6.56002 13 5.81302V3.00402H10.223C9.47299 2.28002 8.73799 1.45202 7.99999 0.723022ZM6.99999 4.00402H8.99999V9.00402H6.99999V7.00002V4.00402ZM6.99999 10H8.99999V12H6.99999V10Z" fill="#FF9800"/>
|
||||
<path d="M0 0.00299072H16V16.003H0V0.00299072Z" fill="#808080" fill-opacity="0.01"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_412_3773">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 977 B |
4
demos/usecases/ui/assets/users.svg
Normal file
|
@ -0,0 +1,4 @@
|
|||
<svg width="16" height="13" viewBox="0 0 16 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11 1.9502C10.6117 1.9502 10.2467 2.03949 9.91602 2.18847C9.97062 2.45052 10.0001 2.72155 10.0001 2.99901C10.0001 4.10112 9.54584 5.1032 8.81647 5.82909C9.27677 6.53278 10.0795 7.00292 11 7.00292C12.4327 7.00292 13.5938 5.87267 13.5938 4.47754C13.5938 3.08241 12.4327 1.9502 11 1.9502ZM11 8.00292C10.8039 8.00292 10.6283 8.01552 10.4473 8.02442C11.1448 8.42408 11.6764 8.90154 12.0508 9.40138C12.993 10.6587 13 12.0029 13 12.0029H16V11.0029C16 11.0029 16 8.00292 11 8.00292ZM7.09766 9.0537C6.00862 9.91889 6 11.0029 6 11.0029V12.0029H11C11 12.0029 11.007 11.3457 10.4492 10.6006C9.97211 9.96363 9.07898 9.2484 7.09766 9.0537Z" fill="#D4D4D4"/>
|
||||
<path d="M6.00024 0C7.6571 0 9.00024 1.3432 9.00024 3C9.00024 4.6568 7.6571 6 6.00024 6C4.34338 6 3.00024 4.6568 3.00024 3C3.00024 1.3432 4.34338 0 6.00024 0ZM6.00024 8C12 7.997 12 12.0034 12 12.0034V13.0034H0V12.0034C0 12.0034 1.43051e-05 8.00336 6.00024 8Z" fill="#D4D4D4"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1 KiB |
12
demos/usecases/ui/icons.slint
Normal file
|
@ -0,0 +1,12 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
export global Icons {
|
||||
out property <image> arrow-up: @image-url("assets/arrow-up.svg");
|
||||
out property <image> arrow-left: @image-url("assets/arrow-left.svg");
|
||||
out property <image> arrow-right: @image-url("assets/arrow-right.svg");
|
||||
out property <image> chevron-left: @image-url("assets/chevron-left.svg");
|
||||
out property <image> arrow-circle-o-left: @image-url("assets/arrow-circle-o-left.svg");
|
||||
out property <image> globe: @image-url("assets/globe.svg");
|
||||
out property <image> expand-more: @image-url("assets/expand-more.svg");
|
||||
}
|
11
demos/usecases/ui/views.slint
Normal file
|
@ -0,0 +1,11 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { DashboardView, DashboardViewAdapter } from "views/dashboard_view.slint";
|
||||
export { DashboardView, DashboardViewAdapter }
|
||||
|
||||
import { MailView, MailViewAdapter, MailBoxViewAdapter } from "views/mail_view.slint";
|
||||
export { MailView, MailViewAdapter, MailBoxViewAdapter }
|
||||
|
||||
import { MainView, MainViewAdapter } from "views/main_view.slint";
|
||||
export { MainView, MainViewAdapter }
|
146
demos/usecases/ui/views/dashboard_view.slint
Normal file
|
@ -0,0 +1,146 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { ScrollView, GroupBox, Palette, VerticalBox } from "std-widgets.slint";
|
||||
import { TitleText, Tile, BarTileModel, BarTiles, BarChart, Value, ValueDisplay } from "../widgets.slint";
|
||||
import { Icons } from "../assets.slint";
|
||||
|
||||
export global WeatherViewAdapter {
|
||||
in property <image> current-temperature-icon: Icons.cloud;
|
||||
in property <string> current-temperature: "22°";
|
||||
in property <string> current-day: "May 6th 2023";
|
||||
in property <string> current-weather-description: "Very cloudy";
|
||||
in property <[BarTileModel]> week-model: [
|
||||
{
|
||||
title: "Thu",
|
||||
icon: Icons.cloud,
|
||||
max: 21,
|
||||
min: 18,
|
||||
absolute-max: 21,
|
||||
absolute-min: 15,
|
||||
unit: "°"
|
||||
},
|
||||
{
|
||||
title: "Fri",
|
||||
icon: Icons.cloud,
|
||||
max: 20,
|
||||
min: 17,
|
||||
absolute-max: 21,
|
||||
absolute-min: 15,
|
||||
unit: "°"
|
||||
},
|
||||
{
|
||||
title: "Sat",
|
||||
icon: Icons.cloud,
|
||||
max: 18,
|
||||
min: 15,
|
||||
absolute-max: 21,
|
||||
absolute-min: 15,
|
||||
unit: "°"
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
export global UsageViewAdapter {
|
||||
in property <string> title: "Usage";
|
||||
in property <[Value]> overview-model: [
|
||||
{
|
||||
value: 16.41,
|
||||
title: "Daily",
|
||||
unit: "kWh",
|
||||
},
|
||||
{
|
||||
value: 15.23,
|
||||
title: "Weekly",
|
||||
unit: "kWh",
|
||||
}
|
||||
];
|
||||
in property <[float]> model: [
|
||||
10.0,
|
||||
9.0,
|
||||
11.0,
|
||||
12.0,
|
||||
8.0,
|
||||
14.0,
|
||||
9.0,
|
||||
16.0,
|
||||
18.0,
|
||||
12.0,
|
||||
11.0,
|
||||
14.0,
|
||||
12.0,
|
||||
16.0
|
||||
];
|
||||
in property <float> min: 0.0;
|
||||
in property <float> max: 24.0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
export global DashboardViewAdapter {
|
||||
|
||||
}
|
||||
|
||||
export component DashboardView {
|
||||
ScrollView {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
VerticalLayout {
|
||||
padding: 4px;
|
||||
spacing: 4px;
|
||||
|
||||
TitleText {
|
||||
horizontal-alignment: left;
|
||||
text: "Dashboard";
|
||||
}
|
||||
|
||||
GroupBox {
|
||||
title: "Weather";
|
||||
|
||||
HorizontalLayout {
|
||||
Tile {
|
||||
value: WeatherViewAdapter.current-temperature;
|
||||
text: WeatherViewAdapter.current-day;
|
||||
sub-text: WeatherViewAdapter.current-weather-description;
|
||||
icon: WeatherViewAdapter.current-temperature-icon;
|
||||
}
|
||||
|
||||
BarTiles {
|
||||
model: WeatherViewAdapter.week-model;
|
||||
active: true;
|
||||
}
|
||||
|
||||
// stretches the empty element
|
||||
if WeatherViewAdapter.week-model.length == 0 : Rectangle {}
|
||||
}
|
||||
}
|
||||
|
||||
GroupBox {
|
||||
title: "Usage";
|
||||
|
||||
Rectangle {
|
||||
BarChart {
|
||||
preferred-width: 100%;
|
||||
preferred-height: 100%;
|
||||
model: UsageViewAdapter.model;
|
||||
min: UsageViewAdapter.min;
|
||||
max: UsageViewAdapter.max;
|
||||
active: true;
|
||||
}
|
||||
|
||||
VerticalLayout {
|
||||
alignment: start;
|
||||
|
||||
ValueDisplay {
|
||||
model: UsageViewAdapter.overview-model;
|
||||
transparent-background: true;
|
||||
alternative-colors: true;
|
||||
active: true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
29
demos/usecases/ui/views/header_view.slint
Normal file
|
@ -0,0 +1,29 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { Palette, HorizontalBox, Switch } from "std-widgets.slint";
|
||||
import { Icons } from "../assets.slint";
|
||||
|
||||
export component HeaderView {
|
||||
min-height: 48px;
|
||||
|
||||
HorizontalBox {
|
||||
Image {
|
||||
max-height: 32px;
|
||||
source: Icons.slint-logo;
|
||||
horizontal-alignment: left;
|
||||
}
|
||||
|
||||
// spaceer
|
||||
Rectangle {}
|
||||
|
||||
Switch {
|
||||
text: "Dark Mode";
|
||||
checked: Palette.color-scheme == ColorScheme.dark;
|
||||
|
||||
toggled => {
|
||||
Palette.color-scheme = self.checked ? ColorScheme.dark : ColorScheme.light;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
286
demos/usecases/ui/views/mail_view.slint
Normal file
|
@ -0,0 +1,286 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { GroupBox, ComboBox, VerticalBox, GroupBox, GridBox, Palette, TextEdit, Button, Switch, ScrollView } from "std-widgets.slint";
|
||||
import { NavigationListView, NavigationListViewItem, Container, ExtendedLineEdit, Icon, CardListView, CardListViewItem, IconButton, TitleText } from "../widgets.slint";
|
||||
import { Icons } from "../assets.slint";
|
||||
|
||||
export global MailViewAdapter { }
|
||||
|
||||
export global MailSideBarViewAdapter {
|
||||
out property <[string]> accounts: ["jon.doe@slint.dev", "jon.doe@my-mail.com", "jon.doe@gmail.com"];
|
||||
|
||||
out property <[NavigationListViewItem]> boxes: [
|
||||
{ text: "Inbox", message: "128", icon: Icons.inbox },
|
||||
{ text: "Drafts", message: "9", icon: Icons.document },
|
||||
{ text: "Sent", icon: Icons.send },
|
||||
{
|
||||
text: "Junk",
|
||||
icon: Icons.junk,
|
||||
message: "23",
|
||||
},
|
||||
{ text: "Trash", icon: Icons.trash },
|
||||
{ text: "Archive", icon: Icons.archive }
|
||||
];
|
||||
|
||||
out property <[NavigationListViewItem]> custom-boxes: [
|
||||
{ text: "Social", message: "3972", icon: Icons.useres },
|
||||
{ text: "Updates", message: "342", icon: Icons.updates },
|
||||
{ text: "Forums", message: "128", icon: Icons.message }
|
||||
];
|
||||
in-out property <int> current-box;
|
||||
in-out property <int> current-custom-box: -1;
|
||||
|
||||
public pure function current-title() -> string {
|
||||
if current-box > -1 && current-box < boxes.length {
|
||||
return boxes[current-box].text;
|
||||
}
|
||||
if current-custom-box > -1 && current-custom-box < custom-boxes.length {
|
||||
return custom-boxes[current-custom-box].text;
|
||||
}
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
export component MailSideBarView {
|
||||
horizontal-stretch: 0;
|
||||
min-width: 264px / 2;
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 4px;
|
||||
|
||||
ComboBox {
|
||||
model: MailSideBarViewAdapter.accounts;
|
||||
}
|
||||
|
||||
Container {
|
||||
NavigationListView {
|
||||
model: MailSideBarViewAdapter.boxes;
|
||||
current-item <=> MailSideBarViewAdapter.current-box;
|
||||
min-height: 248px;
|
||||
vertical-stretch: 0;
|
||||
|
||||
selected(index) => {
|
||||
MailSideBarViewAdapter.current-custom-box = -1;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
background: Palette.border;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
NavigationListView {
|
||||
model: MailSideBarViewAdapter.custom-boxes;
|
||||
current-item <=> MailSideBarViewAdapter.current-custom-box;
|
||||
|
||||
selected(index) => {
|
||||
MailSideBarViewAdapter.current-box = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export global MailBoxViewAdapter {
|
||||
callback search-text-changed(/* search-text */ string);
|
||||
|
||||
in property <string> title: MailSideBarViewAdapter.current-title();
|
||||
in property <[CardListViewItem]> mails: [
|
||||
{
|
||||
title: "Simon Hausmann",
|
||||
note: "1 hour ago",
|
||||
sub-title: "Meeting tomorrow",
|
||||
caption: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||
},
|
||||
{ title: "Tobias Hunger", note: "1 day ago", sub-title: "Meeting tomorrow", caption: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." },
|
||||
{
|
||||
title: "Olivier Goffart",
|
||||
note: "2 hour ago",
|
||||
sub-title: "Meeting tomorrow",
|
||||
caption: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||
},
|
||||
{
|
||||
title: "Aurindam Jana",
|
||||
note: "5 hour ago",
|
||||
sub-title: "Meeting tomorrow",
|
||||
caption: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||
},
|
||||
{
|
||||
title: "Simon Hausmann",
|
||||
note: "7 hour ago",
|
||||
sub-title: "Meeting tomorrow",
|
||||
caption: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||
},
|
||||
{ title: "Tobias Hunger", note: "1 day ago", sub-title: "Meeting tomorrow", caption: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat." },
|
||||
{
|
||||
title: "Olivier Goffart",
|
||||
note: "8 hour ago",
|
||||
sub-title: "Meeting tomorrow",
|
||||
caption: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||
},
|
||||
{
|
||||
title: "Aurindam Jana",
|
||||
note: "9 hour ago",
|
||||
sub-title: "Meeting tomorrow",
|
||||
caption: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
export component MailBoxView {
|
||||
horizontal-stretch: 1;
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 4px;
|
||||
|
||||
TitleText {
|
||||
text: MailBoxViewAdapter.title;
|
||||
min-height: 32px;
|
||||
|
||||
}
|
||||
|
||||
Container {
|
||||
background: Palette.control-background;
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 8px;
|
||||
|
||||
ExtendedLineEdit {
|
||||
vertical-stretch: 0;
|
||||
placeholder-text: "Search by Sender";
|
||||
|
||||
Icon {
|
||||
source: Icons.search;
|
||||
}
|
||||
|
||||
edited => {
|
||||
MailBoxViewAdapter.search-text-changed(self.text);
|
||||
}
|
||||
}
|
||||
|
||||
CardListView {
|
||||
model: MailBoxViewAdapter.mails;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export global MailMessageViewAdapter {
|
||||
callback move-to-archive();
|
||||
callback move-to-junk();
|
||||
callback move-to-trash();
|
||||
callback reply();
|
||||
callback forward();
|
||||
callback send();
|
||||
|
||||
in property <string> message: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.";
|
||||
in-out property <bool> mute-this-thread: false;
|
||||
}
|
||||
|
||||
export component MailMessageView {
|
||||
horizontal-stretch: 1;
|
||||
|
||||
Container {
|
||||
background: Palette.control-background;
|
||||
|
||||
HorizontalLayout {
|
||||
spacing: 8px;
|
||||
|
||||
IconButton {
|
||||
icon: Icons.archive;
|
||||
|
||||
clicked => {
|
||||
MailMessageViewAdapter.move-to-archive();
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
icon: Icons.junk;
|
||||
|
||||
clicked => {
|
||||
MailMessageViewAdapter.move-to-junk();
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
icon: Icons.trash;
|
||||
|
||||
clicked => {
|
||||
MailMessageViewAdapter.move-to-trash();
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {}
|
||||
|
||||
IconButton {
|
||||
icon: Icons.reply;
|
||||
|
||||
clicked => {
|
||||
MailMessageViewAdapter.reply();
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
icon: Icons.forward;
|
||||
|
||||
clicked => {
|
||||
MailMessageViewAdapter.forward();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VerticalBox {
|
||||
text-edit := TextEdit {
|
||||
max-height: 94px;
|
||||
wrap: word-wrap;
|
||||
}
|
||||
|
||||
ScrollView {
|
||||
Text {
|
||||
y: 0;
|
||||
vertical-alignment: top;
|
||||
width: parent.width;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: Palette.foreground;
|
||||
text: MailMessageViewAdapter.message;
|
||||
wrap: word-wrap;
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalLayout {
|
||||
Switch {
|
||||
text: "Mute this thread";
|
||||
checked <=> MailMessageViewAdapter.mute-this-thread;
|
||||
}
|
||||
|
||||
Button {
|
||||
text: "Send";
|
||||
primary: true;
|
||||
enabled: text-edit.text != "";
|
||||
|
||||
clicked => {
|
||||
MailMessageViewAdapter.send();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export component MailView {
|
||||
HorizontalLayout {
|
||||
spacing: 16px;
|
||||
|
||||
MailSideBarView { }
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 16px;
|
||||
|
||||
MailBoxView { }
|
||||
MailMessageView {}
|
||||
}
|
||||
}
|
||||
}
|
40
demos/usecases/ui/views/main_view.slint
Normal file
|
@ -0,0 +1,40 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { TabWidget, HorizontalBox } from "std-widgets.slint";
|
||||
import { MailView } from "mail_view.slint";
|
||||
import { HeaderView } from "header_view.slint";
|
||||
import { DashboardView } from "dashboard_view.slint";
|
||||
|
||||
export global MainViewAdapter { }
|
||||
|
||||
export component MainView {
|
||||
forward-focus: focus-scope;
|
||||
focus-scope := FocusScope {}
|
||||
|
||||
VerticalLayout {
|
||||
HeaderView {}
|
||||
|
||||
HorizontalBox {
|
||||
TabWidget {
|
||||
Tab {
|
||||
title: "Mail";
|
||||
|
||||
HorizontalBox {
|
||||
MailView { }
|
||||
}
|
||||
}
|
||||
|
||||
Tab {
|
||||
title: "Dashboard";
|
||||
|
||||
HorizontalLayout {
|
||||
padding: 4px;
|
||||
|
||||
DashboardView { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
289
demos/usecases/ui/virtual_keyboard.slint
Normal file
|
@ -0,0 +1,289 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { Button, Palette } from "std-widgets.slint";
|
||||
|
||||
import { Icons } from "icons.slint";
|
||||
|
||||
component VirtualKeyboardButton {
|
||||
in property <string> key;
|
||||
in property <image> icon;
|
||||
|
||||
callback key-pressed(/* key */ string);
|
||||
|
||||
min-width: 32px;
|
||||
min-height: 32px;
|
||||
horizontal-stretch: 0;
|
||||
|
||||
states [
|
||||
pressed when i-touch-area.pressed : {
|
||||
i-state-area.opacity: 0.5;
|
||||
}
|
||||
]
|
||||
|
||||
i-container := Rectangle {
|
||||
border-radius: 4px;
|
||||
background: Palette.color-scheme == ColorScheme.dark ? #373737 : #ffffff;
|
||||
|
||||
HorizontalLayout {
|
||||
padding: 8px;
|
||||
|
||||
if (root.key != "") : Text {
|
||||
text: root.key;
|
||||
color: Palette.color-scheme == ColorScheme.dark ? #ffffff : #000000;
|
||||
font-size: 12px;
|
||||
vertical-alignment: center;
|
||||
horizontal-alignment: center;
|
||||
}
|
||||
|
||||
if (root.key == "") : Image {
|
||||
y: (parent.height - self.height) / 2;
|
||||
source: root.icon;
|
||||
height: 18px;
|
||||
colorize: Palette.color-scheme == ColorScheme.dark ? #ffffff : #000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i-state-area := Rectangle {
|
||||
border-radius: i-container.border-radius;
|
||||
opacity: 0;
|
||||
background: #000000;
|
||||
|
||||
animate opacity { duration: 150ms; }
|
||||
}
|
||||
|
||||
i-touch-area := TouchArea {
|
||||
pointer-event(event) => {
|
||||
if(event.kind == PointerEventKind.down) {
|
||||
root.key-pressed(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export struct KeyModel {
|
||||
key: string,
|
||||
shift-key: string,
|
||||
}
|
||||
|
||||
export global VirtualKeyboardHandler {
|
||||
in property <[[[KeyModel]]]> default-key-sets: [
|
||||
[
|
||||
[
|
||||
{ key: "q", shift-key: "Q" },
|
||||
{ key: "w", shift-key: "W" },
|
||||
{ key: "e", shift-key: "E" },
|
||||
{ key: "r", shift-key: "R" },
|
||||
{ key: "t", shift-key: "T" },
|
||||
{ key: "y", shift-key: "Y" },
|
||||
{ key: "u", shift-key: "U" },
|
||||
{ key: "i", shift-key: "I" },
|
||||
{ key: "o", shift-key: "O" },
|
||||
{ key: "p", shift-key: "P" }
|
||||
],
|
||||
[
|
||||
{ key: "a", shift-key: "A" },
|
||||
{ key: "s", shift-key: "S" },
|
||||
{ key: "d", shift-key: "D" },
|
||||
{ key: "f", shift-key: "F" },
|
||||
{ key: "g", shift-key: "G" },
|
||||
{ key: "h", shift-key: "H" },
|
||||
{ key: "j", shift-key: "J" },
|
||||
{ key: "k", shift-key: "K" },
|
||||
{ key: "l", shift-key: "L" }
|
||||
],
|
||||
[
|
||||
{ key: "z", shift-key: "Z" },
|
||||
{ key: "x", shift-key: "X" },
|
||||
{ key: "c", shift-key: "C" },
|
||||
{ key: "v", shift-key: "V" },
|
||||
{ key: "b", shift-key: "B" },
|
||||
{ key: "n", shift-key: "N" },
|
||||
{ key: "m", shift-key: "M" },
|
||||
{ key: ",", shift-key: ";" },
|
||||
{ key: ".", shift-key: ":" },
|
||||
{ key: "?", shift-key: "?" }
|
||||
],
|
||||
],
|
||||
[
|
||||
[
|
||||
{ key: "1", shift-key: "[" },
|
||||
{ key: "2", shift-key: "]" },
|
||||
{ key: "3", shift-key: "{" },
|
||||
{ key: "4", shift-key: "}" },
|
||||
{ key: "5", shift-key: "#" },
|
||||
{ key: "6", shift-key: "%" },
|
||||
{ key: "7", shift-key: "^" },
|
||||
{ key: "8", shift-key: "*" },
|
||||
{ key: "9", shift-key: "+" },
|
||||
{ key: "0", shift-key: "=" }
|
||||
],
|
||||
[
|
||||
{ key: "-", shift-key: "_" },
|
||||
{ key: "/", shift-key: "\\" },
|
||||
{ key: ":", shift-key: "|" },
|
||||
{ key: ";", shift-key: "~" },
|
||||
{ key: "(", shift-key: "<" },
|
||||
{ key: ")", shift-key: ">" },
|
||||
{ key: "€", shift-key: "$" },
|
||||
{ key: "&", shift-key: "€" },
|
||||
{ key: "@", shift-key: "°" },
|
||||
{ key: "'", shift-key: "#" },
|
||||
],
|
||||
[
|
||||
{ key: ".", shift-key: "." },
|
||||
{ key: ",", shift-key: "," },
|
||||
{ key: "?", shift-key: "?" },
|
||||
{ key: "!", shift-key: "!" },
|
||||
{ key: "'", shift-key: "'" },
|
||||
],
|
||||
]
|
||||
];
|
||||
|
||||
out property <int> current-key-set;
|
||||
out property <[[KeyModel]]> keys: default-key-sets[self.current-key-set];
|
||||
in-out property <bool> open;
|
||||
|
||||
callback key_pressed(/* key */ string);
|
||||
|
||||
public function switch-keyboard() {
|
||||
if (self.current-key-set < self.default-key-sets.length - 1) {
|
||||
self.current-key-set += 1;
|
||||
} else {
|
||||
self.current-key-set -= 1;
|
||||
}
|
||||
|
||||
self.current-key-set = min(self.default-key-sets.length - 1, max(0, self.current-key-set))
|
||||
}
|
||||
}
|
||||
|
||||
export component VirtualKeyboard {
|
||||
private property <bool> shift;
|
||||
|
||||
callback close();
|
||||
|
||||
preferred-width: 100%;
|
||||
|
||||
TouchArea {}
|
||||
|
||||
Rectangle {
|
||||
background: Palette.color-scheme == ColorScheme.dark ? #1c1c1c : #d4d4d4;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
i-layout := VerticalLayout {
|
||||
padding: 8px;
|
||||
spacing: 4px;
|
||||
|
||||
for row[index] in VirtualKeyboardHandler.keys : HorizontalLayout {
|
||||
spacing: 4px;
|
||||
|
||||
if (index == 0) : VirtualKeyboardButton {
|
||||
key: "ESC";
|
||||
|
||||
key-pressed => {
|
||||
VirtualKeyboardHandler.key-pressed(Key.Escape);
|
||||
}
|
||||
}
|
||||
|
||||
if (index == 1) : VirtualKeyboardButton {
|
||||
key: "Tab";
|
||||
|
||||
key-pressed => {
|
||||
VirtualKeyboardHandler.key-pressed(Key.Tab);
|
||||
}
|
||||
}
|
||||
|
||||
// shift
|
||||
if (index == 2) : VirtualKeyboardButton {
|
||||
icon: Icons.arrow-up;
|
||||
|
||||
key-pressed => {
|
||||
root.shift = !root.shift;
|
||||
}
|
||||
}
|
||||
|
||||
for km in row : VirtualKeyboardButton {
|
||||
key: root.shift ? km.shift-key : km.key;
|
||||
|
||||
key-pressed(key) => {
|
||||
VirtualKeyboardHandler.key-pressed(key);
|
||||
root.shift = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == 0) : VirtualKeyboardButton {
|
||||
icon: Icons.chevron-left;
|
||||
|
||||
key-pressed => {
|
||||
VirtualKeyboardHandler.key-pressed(Key.Backspace);
|
||||
}
|
||||
}
|
||||
|
||||
if (index == 1) : VirtualKeyboardButton {
|
||||
icon: Icons.arrow-circle-o-left;
|
||||
|
||||
key-pressed => {
|
||||
VirtualKeyboardHandler.key-pressed(Key.Return);
|
||||
}
|
||||
}
|
||||
|
||||
// shift
|
||||
if (index == 2) : VirtualKeyboardButton {
|
||||
icon: Icons.arrow-up;
|
||||
|
||||
key-pressed => {
|
||||
root.shift = !root.shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HorizontalLayout {
|
||||
spacing: 4px;
|
||||
|
||||
VirtualKeyboardButton {
|
||||
icon: Icons.expand-more;
|
||||
|
||||
key-pressed(key) => {
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
VirtualKeyboardButton {
|
||||
icon: Icons.globe;
|
||||
|
||||
key-pressed(key) => {
|
||||
VirtualKeyboardHandler.switch-keyboard();
|
||||
}
|
||||
}
|
||||
VirtualKeyboardButton {
|
||||
horizontal-stretch: 1;
|
||||
key: " ";
|
||||
|
||||
key-pressed(key) => {
|
||||
root.shift = false;
|
||||
VirtualKeyboardHandler.key-pressed(key);
|
||||
}
|
||||
}
|
||||
VirtualKeyboardButton {
|
||||
icon: Icons.arrow-left;
|
||||
|
||||
key-pressed(key) => {
|
||||
VirtualKeyboardHandler.key-pressed(Key.LeftArrow);
|
||||
}
|
||||
}
|
||||
VirtualKeyboardButton {
|
||||
icon: Icons.arrow-right;
|
||||
|
||||
key-pressed(key) => {
|
||||
VirtualKeyboardHandler.key-pressed(Key.RightArrow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
animate y { duration: 500ms; easing: cubic-bezier(0.05, 0.7, 0.1, 1.0); }
|
||||
}
|
35
demos/usecases/ui/widgets.slint
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { CardListView, CardListViewItem } from "widgets/card_list_view.slint";
|
||||
export { CardListView, CardListViewItem }
|
||||
|
||||
import { Container, StateContainer } from "widgets/container.slint";
|
||||
export { Container, StateContainer }
|
||||
|
||||
import { ExtendedLineEdit } from "widgets/extended_line_edit.slint";
|
||||
export { ExtendedLineEdit }
|
||||
|
||||
import { IconButton } from "widgets/icon_button.slint";
|
||||
export { IconButton }
|
||||
|
||||
import { Icon } from "widgets/icon.slint";
|
||||
export { Icon }
|
||||
|
||||
import { Segmented } from "widgets/segmented.slint";
|
||||
export { Segmented }
|
||||
|
||||
import { NavigationListView, NavigationListViewItem } from "widgets/navigation_list_view.slint";
|
||||
export { NavigationListView, NavigationListViewItem }
|
||||
|
||||
import { Tile, BarTileModel, BarTiles } from "widgets/tile.slint";
|
||||
export { Tile, BarTileModel, BarTiles }
|
||||
|
||||
import { TitleText } from "widgets/title_text.slint";
|
||||
export { TitleText }
|
||||
|
||||
import { BarChart } from "widgets/bar_chart.slint";
|
||||
export { BarChart }
|
||||
|
||||
import { Value, ValueDisplay } from "widgets/value_display.slint";
|
||||
export { Value, ValueDisplay }
|
73
demos/usecases/ui/widgets/bar_chart.slint
Normal file
|
@ -0,0 +1,73 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { CosmicPalette } from "styling.slint";
|
||||
|
||||
component Bar {
|
||||
in property <length> bar-height;
|
||||
|
||||
horizontal-stretch: 1;
|
||||
|
||||
Rectangle {
|
||||
border-radius: 2px;
|
||||
y: parent.height - self.height;
|
||||
height: bar-height;
|
||||
clip: true;
|
||||
|
||||
Rectangle {
|
||||
height: root.height;
|
||||
y: parent.height - self.height;
|
||||
background: CosmicPalette.bar-gradient;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export component BarBackground inherits Rectangle {
|
||||
border-radius: 2px;
|
||||
// background: Theme.palette.bar-background-gradient;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
export component ChartPattern {
|
||||
in property <int> count;
|
||||
|
||||
HorizontalLayout {
|
||||
spacing: 1px;
|
||||
for _ in count : BarBackground {}
|
||||
}
|
||||
}
|
||||
|
||||
export component BarChart {
|
||||
in property <[float]> model;
|
||||
in property <float> min;
|
||||
in property <float> max;
|
||||
in property <bool> active;
|
||||
|
||||
cache-rendering-hint: true;
|
||||
|
||||
ChartPattern {
|
||||
count: model.length / 2;
|
||||
}
|
||||
|
||||
layout := HorizontalLayout {
|
||||
spacing: 1px;
|
||||
|
||||
for value in model : Bar {
|
||||
private property <float> display-value;
|
||||
|
||||
min-height: 120px;
|
||||
preferred-height: 100%;
|
||||
bar-height: parent.height * (display-value - root.min) / (root.max - root.min);
|
||||
|
||||
states [
|
||||
active when active : {
|
||||
display-value: value;
|
||||
|
||||
in {
|
||||
animate display-value { duration: 500ms; easing: ease-in-out; }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
91
demos/usecases/ui/widgets/card_list_view.slint
Normal file
|
@ -0,0 +1,91 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { ListView, Palette, VerticalBox } from "std-widgets.slint";
|
||||
import { StateContainer } from "container.slint";
|
||||
|
||||
export component CardListItem {
|
||||
callback clicked <=> state-container.clicked;
|
||||
|
||||
in property <string> title <=> title.text;
|
||||
in property <string> sub-title <=> sub-title.text;
|
||||
in property <string> note <=> note.text;
|
||||
in property <string> caption <=> caption.text;
|
||||
in property <bool> selected <=> state-container.checked;
|
||||
|
||||
min-height: max(41px, layout.min-height);
|
||||
|
||||
layout := HorizontalLayout {
|
||||
padding-bottom: 8px;
|
||||
|
||||
state-container := StateContainer {
|
||||
VerticalBox {
|
||||
padding: 16px;
|
||||
|
||||
HorizontalLayout {
|
||||
spacing: 4px;
|
||||
|
||||
title := Text {
|
||||
horizontal-stretch: 1;
|
||||
color: Palette.foreground;
|
||||
font-size: 10px;
|
||||
font-weight: 400;
|
||||
overflow: elide;
|
||||
}
|
||||
|
||||
note := Text {
|
||||
horizontal-stretch: 0;
|
||||
color: Palette.foreground;
|
||||
font-size: 10px;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
sub-title := Text {
|
||||
horizontal-stretch: 1;
|
||||
color: Palette.foreground;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
overflow: elide;
|
||||
}
|
||||
|
||||
caption := Text {
|
||||
height: 40px;
|
||||
wrap: word-wrap;
|
||||
overflow: elide;
|
||||
color: Palette.foreground;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export struct CardListViewItem {
|
||||
title: string,
|
||||
sub-title: string,
|
||||
note: string,
|
||||
caption: string
|
||||
}
|
||||
|
||||
export component CardListView inherits ListView {
|
||||
callback current-item-changed(/* current-item */ int);
|
||||
|
||||
in property <[CardListViewItem]> model;
|
||||
in-out property <int> current-item;
|
||||
|
||||
for item[index] in root.model : CardListItem {
|
||||
height: self.min-height;
|
||||
title: item.title;
|
||||
sub-title: item.sub-title;
|
||||
note: item.note;
|
||||
caption: item.caption;
|
||||
selected: index == root.current-item;
|
||||
|
||||
clicked => {
|
||||
root.current-item = index;
|
||||
root.current-item-changed(index);
|
||||
}
|
||||
}
|
||||
}
|
43
demos/usecases/ui/widgets/container.slint
Normal file
|
@ -0,0 +1,43 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { Palette, VerticalBox } from "std-widgets.slint";
|
||||
import { CosmicPalette } from "styling.slint";
|
||||
|
||||
export component StateContainer inherits Rectangle {
|
||||
callback clicked <=> touch-area.clicked;
|
||||
|
||||
in property <bool> checked;
|
||||
|
||||
background: Palette.alternate-background;
|
||||
border-radius: 8px;
|
||||
|
||||
touch-area := TouchArea {}
|
||||
|
||||
state-layer := Rectangle {
|
||||
border-radius: root.border-radius;
|
||||
|
||||
states [
|
||||
pressed when touch-area.pressed : {
|
||||
state-layer.background: CosmicPalette.state-pressed;
|
||||
}
|
||||
hover when touch-area.has-hover : {
|
||||
state-layer.background: CosmicPalette.state-hover;
|
||||
}
|
||||
checked when root.checked : {
|
||||
state-layer.background: CosmicPalette.state-selected;
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@children
|
||||
}
|
||||
|
||||
export component Container inherits Rectangle {
|
||||
background: Palette.alternate-background;
|
||||
border-radius: 8px;
|
||||
|
||||
VerticalBox {
|
||||
@children
|
||||
}
|
||||
}
|
178
demos/usecases/ui/widgets/extended_line_edit.slint
Normal file
|
@ -0,0 +1,178 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { Palette } from "std-widgets.slint";
|
||||
import { CosmicPalette } from "styling.slint";
|
||||
|
||||
// copied from common that is not public now
|
||||
component LineEditBase inherits Rectangle {
|
||||
in property <string> placeholder-text;
|
||||
in property <length> font-size <=> text-input.font-size;
|
||||
in_out property <string> text <=> text-input.text;
|
||||
in property <brush> placeholder-color;
|
||||
in property <bool> enabled <=> text-input.enabled;
|
||||
in property <bool> has-focus: text-input.has-focus;
|
||||
in property <InputType> input-type <=> text-input.input-type;
|
||||
in property <TextHorizontalAlignment> horizontal-alignment <=> text-input.horizontal-alignment;
|
||||
in property <bool> read-only <=> text-input.read-only;
|
||||
in property <int> font-weight <=> text-input.font-weight;
|
||||
in property <brush> text-color;
|
||||
in property <color> selection-background-color <=> text-input.selection-background-color;
|
||||
in property <color> selection-foreground-color <=> text-input.selection-foreground-color;
|
||||
in property <length> margin;
|
||||
|
||||
callback accepted( /* text */ string);
|
||||
callback edited(/* text */ string);
|
||||
|
||||
public function set-selection-offsets(start: int, end: int) {
|
||||
text-input.set-selection-offsets(start, end);
|
||||
}
|
||||
|
||||
public function select-all() {
|
||||
text-input.select-all();
|
||||
}
|
||||
|
||||
public function clear-selection() {
|
||||
text-input.clear-selection();
|
||||
}
|
||||
|
||||
public function cut() {
|
||||
text-input.cut();
|
||||
}
|
||||
|
||||
public function copy() {
|
||||
text-input.copy();
|
||||
}
|
||||
|
||||
public function paste() {
|
||||
text-input.paste();
|
||||
}
|
||||
|
||||
min-height: text-input.preferred-height;
|
||||
min-width: max(50px, placeholder.min-width);
|
||||
clip: true;
|
||||
forward-focus: text-input;
|
||||
|
||||
placeholder := Text {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
vertical-alignment: center;
|
||||
text: (root.text == "" && text-input.preedit-text == "") ? root.placeholder-text : "";
|
||||
font-size: text-input.font-size;
|
||||
font-italic: text-input.font-italic;
|
||||
font-weight: text-input.font-weight;
|
||||
font-family: text-input.font-family;
|
||||
color: root.placeholder-color;
|
||||
horizontal-alignment: root.horizontal-alignment;
|
||||
}
|
||||
|
||||
text-input := TextInput {
|
||||
property <length> computed-x;
|
||||
|
||||
x: min(0px, max(parent.width - self.width - self.text-cursor-width, self.computed-x));
|
||||
width: max(parent.width - self.text-cursor-width, self.preferred-width);
|
||||
height: 100%;
|
||||
vertical-alignment: center;
|
||||
single-line: true;
|
||||
color: root.text-color;
|
||||
|
||||
cursor-position-changed(cpos) => {
|
||||
if (cpos.x + self.computed_x < root.margin) {
|
||||
self.computed_x = - cpos.x + root.margin;
|
||||
} else if (cpos.x + self.computed_x > parent.width - root.margin - self.text-cursor-width) {
|
||||
self.computed_x = parent.width - cpos.x - root.margin - self.text-cursor-width;
|
||||
}
|
||||
}
|
||||
|
||||
accepted => { root.accepted(self.text); }
|
||||
|
||||
edited => { root.edited(self.text); }
|
||||
}
|
||||
}
|
||||
|
||||
export component ExtendedLineEdit {
|
||||
in property <bool> enabled <=> base.enabled;
|
||||
in property <InputType> input-type <=> base.input-type;
|
||||
in property <TextHorizontalAlignment> horizontal-alignment <=> base.horizontal-alignment;
|
||||
in property <bool> read-only <=> base.read-only;
|
||||
in property <length> font-size <=> base.font-size;
|
||||
in property <string> placeholder-text <=> base.placeholder-text;
|
||||
out property <bool> has-focus <=> base.has-focus;
|
||||
in-out property <string> text <=> base.text;
|
||||
|
||||
callback accepted <=> base.accepted;
|
||||
callback edited <=> base.edited;
|
||||
accessible-role: text-input;
|
||||
accessible-value <=> text;
|
||||
|
||||
public function set-selection-offsets(start: int, end: int) {
|
||||
base.set-selection-offsets(start, end);
|
||||
}
|
||||
|
||||
public function select-all() {
|
||||
base.select-all();
|
||||
}
|
||||
|
||||
public function clear-selection() {
|
||||
base.clear-selection();
|
||||
}
|
||||
|
||||
public function cut() {
|
||||
base.cut();
|
||||
}
|
||||
|
||||
public function copy() {
|
||||
base.copy();
|
||||
}
|
||||
|
||||
public function paste() {
|
||||
base.paste();
|
||||
}
|
||||
|
||||
vertical-stretch: 0;
|
||||
horizontal-stretch: 1;
|
||||
min-width: max(160px, layout.min-width);
|
||||
min-height: max(32px, layout.min-height);
|
||||
forward-focus: base;
|
||||
|
||||
states [
|
||||
disabled when !root.enabled : {
|
||||
root.opacity: 0.5;
|
||||
}
|
||||
]
|
||||
|
||||
background := Rectangle {
|
||||
border-radius: 8px;
|
||||
background: Palette.control-background;
|
||||
border-width: 1px;
|
||||
border-color: CosmicPalette.control-divider;
|
||||
|
||||
layout := HorizontalLayout {
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
spacing: 8px;
|
||||
|
||||
HorizontalLayout {
|
||||
@children
|
||||
}
|
||||
|
||||
base := LineEditBase {
|
||||
font-size: 15 * 0.0769rem;
|
||||
font-weight: 400;
|
||||
selection-background-color: Palette.selection-background;
|
||||
selection-foreground-color: Palette.accent-foreground;
|
||||
text-color: Palette.foreground;
|
||||
placeholder-color: CosmicPalette.placeholder-foreground;
|
||||
margin: layout.padding-left + layout.padding-right;
|
||||
}
|
||||
}
|
||||
|
||||
if root.has-focus && root.enabled : Rectangle {
|
||||
width: parent.width + 2px;
|
||||
height: parent.height + 2px;
|
||||
border-radius: parent.border-radius + 2px;
|
||||
border-color: CosmicPalette.state-focus;
|
||||
border-width: 1px;
|
||||
}
|
||||
}
|
||||
}
|
9
demos/usecases/ui/widgets/icon.slint
Normal file
|
@ -0,0 +1,9 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { Palette } from "std-widgets.slint";
|
||||
|
||||
export component Icon inherits Image {
|
||||
width: 16px;
|
||||
colorize: Palette.foreground;
|
||||
}
|
26
demos/usecases/ui/widgets/icon_button.slint
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { Palette } from "std-widgets.slint";
|
||||
import { StateContainer } from "container.slint";
|
||||
|
||||
export component IconButton {
|
||||
callback clicked <=> state-container.clicked;
|
||||
|
||||
in property <image> icon <=> icon.source;
|
||||
|
||||
width: self.height;
|
||||
min-height: 32px;
|
||||
|
||||
vertical-stretch: 0;
|
||||
horizontal-stretch: 0;
|
||||
|
||||
state-container := StateContainer {
|
||||
background: transparent;
|
||||
border-radius: max(self.width, self.height) / 2;
|
||||
icon := Image {
|
||||
height: 16px;
|
||||
colorize: Palette.foreground;
|
||||
}
|
||||
}
|
||||
}
|
90
demos/usecases/ui/widgets/navigation_list_view.slint
Normal file
|
@ -0,0 +1,90 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { Palette, ListView, HorizontalBox } from "std-widgets.slint";
|
||||
import { CosmicPalette } from "styling.slint";
|
||||
import { Icon } from "icon.slint";
|
||||
|
||||
export component NavigationListItem {
|
||||
private property <brush> foreground: Palette.foreground;
|
||||
|
||||
callback select <=> touch-area.clicked;
|
||||
|
||||
in property <bool> selected;
|
||||
in property <string> title <=> text.text;
|
||||
in property <string> message <=> message.text;
|
||||
in property <image> icon <=> icon.source;
|
||||
|
||||
min-height: max(41px, layout.min-height);
|
||||
|
||||
layout := HorizontalLayout {
|
||||
padding-bottom: 8px;
|
||||
|
||||
background := Rectangle {
|
||||
border-radius: 16px;
|
||||
|
||||
HorizontalLayout {
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
|
||||
spacing: 8px;
|
||||
|
||||
icon := Icon {
|
||||
y: (parent.height - self.height) / 2;
|
||||
colorize: root.foreground;
|
||||
}
|
||||
|
||||
text := Text {
|
||||
color: root.foreground;
|
||||
horizontal-stretch: 1;
|
||||
vertical-alignment: center;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
message := Text {
|
||||
color: root.foreground;
|
||||
horizontal-stretch: 0;
|
||||
vertical-alignment: center;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
touch-area := TouchArea {}
|
||||
}
|
||||
}
|
||||
|
||||
states [
|
||||
selected when root.selected : {
|
||||
background.background: CosmicPalette.state-selected;
|
||||
foreground: CosmicPalette.accent-text;
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export struct NavigationListViewItem {
|
||||
icon: image,
|
||||
text: string,
|
||||
message: string,
|
||||
}
|
||||
|
||||
export component NavigationListView inherits ListView {
|
||||
in property <[NavigationListViewItem]> model;
|
||||
in-out property <int> current-item: -1;
|
||||
|
||||
callback selected(/* current-item */ int);
|
||||
|
||||
for item[index] in root.model : NavigationListItem {
|
||||
height: self.min-height;
|
||||
title: item.text;
|
||||
icon: item.icon;
|
||||
message: item.message;
|
||||
selected: index == root.current-item;
|
||||
|
||||
select => {
|
||||
root.current-item = index;
|
||||
selected(root.current-item);
|
||||
}
|
||||
}
|
||||
}
|
4
demos/usecases/ui/widgets/segmented.slint
Normal file
|
@ -0,0 +1,4 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
export component Segmented {}
|
39
demos/usecases/ui/widgets/styling.slint
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { Palette } from "std-widgets.slint";
|
||||
|
||||
export global CosmicPalette {
|
||||
out property <brush> state-selected: Palette.color-scheme == ColorScheme.dark ? #4D4D4D4D : #98989833;
|
||||
out property <brush> accent-text: Palette.color-scheme == ColorScheme.dark ? #63D0DF : #00525A;
|
||||
out property <brush> control-divider: Palette.color-scheme == ColorScheme.dark ? #DEDEDE33 : #3D3D3D33;
|
||||
out property <brush> state-focus: Palette.color-scheme == ColorScheme.dark ? #63D0DF : #00525A;
|
||||
out property <brush> placeholder-foreground: Palette.color-scheme == ColorScheme.dark ? #959595 : #585858;
|
||||
out property <brush> state-hover: #63636333;
|
||||
out property <brush> state-pressed: Palette.color-scheme == ColorScheme.dark ? #16161680 : #BEBEBE80;
|
||||
out property <brush> bar-gradient: Palette.color-scheme == ColorScheme.dark ? @linear-gradient(180deg, #63D0DF 0%, #00525A 100%) : @linear-gradient(180deg, #00525A 0%, #63D0DF 100%);
|
||||
}
|
||||
|
||||
export struct TextStyle {
|
||||
font-size: relative-font-size,
|
||||
font-weight: int,
|
||||
}
|
||||
|
||||
export global CosmicFontSettings {
|
||||
out property <int> light-font-weight: 300;
|
||||
out property <int> regular-font-weight: 400;
|
||||
out property <int> semibold-font-weight: 600;
|
||||
out property <TextStyle> body: {
|
||||
font-size: 14 * 0.0769rem,
|
||||
font-weight: regular-font-weight
|
||||
};
|
||||
out property <TextStyle> body-strong: {
|
||||
font-size: 14 * 0.0769rem,
|
||||
font-weight: semibold-font-weight
|
||||
};
|
||||
|
||||
out property <TextStyle> title-2: {
|
||||
font-size: 28 * 0.0769rem,
|
||||
font-weight: regular-font-weight
|
||||
};
|
||||
}
|
191
demos/usecases/ui/widgets/tile.slint
Normal file
|
@ -0,0 +1,191 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { Palette } from "std-widgets.slint";
|
||||
import { CosmicFontSettings } from "styling.slint";
|
||||
|
||||
export struct BarTileModel {
|
||||
title: string,
|
||||
icon: image,
|
||||
max: int,
|
||||
min: int,
|
||||
absolute-min: int,
|
||||
absolute-max: int,
|
||||
unit: string,
|
||||
}
|
||||
|
||||
component ValueLabel {
|
||||
in property <string> text;
|
||||
in property <string> unit;
|
||||
|
||||
HorizontalLayout {
|
||||
Text {
|
||||
color: Palette.foreground;
|
||||
vertical-stretch: 0;
|
||||
horizontal-alignment: right;
|
||||
text: root.text;
|
||||
font-size: CosmicFontSettings.body-strong.font-size;
|
||||
font-weight: CosmicFontSettings.body-strong.font-weight;
|
||||
}
|
||||
|
||||
Text {
|
||||
color: Palette.foreground;
|
||||
vertical-stretch: 0;
|
||||
horizontal-alignment: left;
|
||||
text: "°";
|
||||
font-size: CosmicFontSettings.body-strong.font-size;
|
||||
font-weight: CosmicFontSettings.body-strong.font-weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
component BarTile {
|
||||
in property <string> title <=> i-title.text;
|
||||
in property <image> icon <=> i-icon.source;
|
||||
in property <float> max;
|
||||
in property <float> min;
|
||||
in property <string> unit;
|
||||
in property <float> absolute-min;
|
||||
in property <float> absolute-max;
|
||||
|
||||
HorizontalLayout {
|
||||
alignment: center;
|
||||
|
||||
VerticalLayout {
|
||||
spacing: 7px;
|
||||
|
||||
i-title := Text {
|
||||
color: Palette.foreground;
|
||||
vertical-stretch: 0;
|
||||
horizontal-alignment: center;
|
||||
font-size: CosmicFontSettings.body-strong.font-size;
|
||||
font-weight: CosmicFontSettings.body-strong.font-weight;
|
||||
}
|
||||
|
||||
i-icon := Image {
|
||||
height: 20px;
|
||||
vertical-stretch: 0;
|
||||
colorize: Palette.accent-background;
|
||||
}
|
||||
|
||||
ValueLabel {
|
||||
text: floor(max);
|
||||
unit: unit;
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
private property <int> range: root.absolute-max - root.absolute-min;
|
||||
private property <length> max-y: self.height * (root.max - root.absolute-min) / range;
|
||||
private property <length> min-y: self.height * (root.min - root.absolute-min) / range;
|
||||
|
||||
vertical-stretch: 1;
|
||||
|
||||
HorizontalLayout {
|
||||
alignment: center;
|
||||
y: parent.height - max-y;
|
||||
height: max-y - min-y;
|
||||
|
||||
Rectangle {
|
||||
min_width: 12px;
|
||||
border-radius: 6px;
|
||||
|
||||
background: Palette.accent-background;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ValueLabel {
|
||||
text: floor(min);
|
||||
unit: unit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export component BarTiles {
|
||||
in property <[BarTileModel]> model;
|
||||
in property <bool> active;
|
||||
|
||||
horizontal-stretch: 1;
|
||||
vertical-stretch: 1;
|
||||
|
||||
HorizontalLayout {
|
||||
padding-right: 16px;
|
||||
padding-left: 16px;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
|
||||
for tile in model : BarTile {
|
||||
private property <float> display-max: tile.max;
|
||||
|
||||
horizontal-stretch: 1;
|
||||
title: tile.title;
|
||||
icon: tile.icon;
|
||||
min: tile.min;
|
||||
absolute-min: tile.absolute-min;
|
||||
absolute-max: tile.absolute-max;
|
||||
unit: tile.unit;
|
||||
|
||||
states [
|
||||
active when active : {
|
||||
max: display-max;
|
||||
|
||||
in {
|
||||
animate max { duration: 240ms; easing: cubic-bezier(0, 0, 0, 1); }
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export component Tile {
|
||||
in property <image> icon <=> i-icon.source;
|
||||
in property <string> value <=> i-value.text;
|
||||
in property <string> text <=> i-text.text;
|
||||
in property <string> sub-text <=> i-sub-text.text;
|
||||
|
||||
horizontal-stretch: 0;
|
||||
vertical-stretch: 1;
|
||||
|
||||
VerticalLayout {
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
spacing: 8px;
|
||||
alignment: center;
|
||||
|
||||
i-icon := Image {
|
||||
height: 34px;
|
||||
horizontal-alignment: center;
|
||||
colorize: Palette.foreground;
|
||||
image-fit: contain;
|
||||
}
|
||||
|
||||
i-value := Text {
|
||||
horizontal-alignment: center;
|
||||
color: Palette.foreground;
|
||||
font-size: CosmicFontSettings.title-2.font-size;
|
||||
font-weight: CosmicFontSettings.title-2.font-weight;
|
||||
}
|
||||
|
||||
VerticalLayout {
|
||||
i-text := Text {
|
||||
horizontal-alignment: center;
|
||||
color: Palette.foreground;
|
||||
font-size: CosmicFontSettings.body-strong.font-size;
|
||||
font-weight: CosmicFontSettings.body-strong.font-weight;
|
||||
}
|
||||
|
||||
i-sub-text := Text {
|
||||
horizontal-alignment: center;
|
||||
color: Palette.accent-background;
|
||||
font-size: CosmicFontSettings.body-strong.font-size;
|
||||
font-weight: CosmicFontSettings.body-strong.font-weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
11
demos/usecases/ui/widgets/title_text.slint
Normal file
|
@ -0,0 +1,11 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { Palette } from "std-widgets.slint";
|
||||
import { CosmicFontSettings } from "styling.slint";
|
||||
|
||||
export component TitleText inherits Text {
|
||||
color: Palette.foreground;
|
||||
font-size: CosmicFontSettings.title-2.font-size;
|
||||
font-weight: CosmicFontSettings.title-2.font-weight;
|
||||
}
|
113
demos/usecases/ui/widgets/value_display.slint
Normal file
|
@ -0,0 +1,113 @@
|
|||
// Copyright © SixtyFPS GmbH <info@slint.dev>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
import { CosmicPalette, CosmicFontSettings } from "styling.slint";
|
||||
import { Palette } from "std-widgets.slint";
|
||||
|
||||
component ValueDelegate {
|
||||
in property <bool> active;
|
||||
in property <string> title <=> title.text;
|
||||
in property <string> unit <=> unit.text;
|
||||
in property <float> value;
|
||||
in property <bool> alternative-colors;
|
||||
|
||||
private property <float> display-value;
|
||||
|
||||
states [
|
||||
active when active : {
|
||||
display-value: value;
|
||||
|
||||
in {
|
||||
animate display-value { duration: 500ms; }
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
HorizontalLayout {
|
||||
spacing: 15px;
|
||||
|
||||
Rectangle {
|
||||
min_width: 1px;
|
||||
background: Palette.accent-background;
|
||||
horizontal-stretch: 0;
|
||||
}
|
||||
|
||||
VerticalLayout {
|
||||
alignment: center;
|
||||
horizontal-stretch: 1;
|
||||
|
||||
title := Text {
|
||||
color: Palette.accent-background;
|
||||
font-size: CosmicFontSettings.body-strong.font-size;
|
||||
font-weight: CosmicFontSettings.body-strong.font-weight;
|
||||
}
|
||||
|
||||
HorizontalLayout {
|
||||
alignment: start;
|
||||
spacing: 5px;
|
||||
|
||||
Text {
|
||||
color: Palette.foreground;
|
||||
text: round(display-value * 100) / 100;
|
||||
font-size: CosmicFontSettings.body-strong.font-size;
|
||||
font-weight: CosmicFontSettings.body-strong.font-weight;
|
||||
vertical-alignment: center;
|
||||
}
|
||||
|
||||
unit := Text {
|
||||
y: 4px;
|
||||
vertical-alignment: center;
|
||||
color: Palette.accent-background;
|
||||
font-size: CosmicFontSettings.body.font-size;
|
||||
font-weight: CosmicFontSettings.body.font-weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export struct Value {
|
||||
title: string,
|
||||
value: float,
|
||||
unit: string,
|
||||
}
|
||||
|
||||
export component ValueDisplay {
|
||||
in property <bool> alternative-colors;
|
||||
in property <[Value]> model;
|
||||
in property <bool> active;
|
||||
in property <bool> transparent-background;
|
||||
in property <bool> vertical;
|
||||
|
||||
min-height: 70px;
|
||||
|
||||
|
||||
if(model.length > 0 && !vertical) : HorizontalLayout {
|
||||
x: 15px;
|
||||
width: parent.width - 30px;
|
||||
height: 100%;
|
||||
padding-top: 12px;
|
||||
padding-bottom: 12px;
|
||||
|
||||
for value in root.model : ValueDelegate {
|
||||
width: parent.width / model.length;
|
||||
horizontal-stretch: 1;
|
||||
alternative-colors: root.alternative-colors;
|
||||
title: value.title;
|
||||
value: value.value;
|
||||
unit: value.unit;
|
||||
active: root.active;
|
||||
}
|
||||
}
|
||||
|
||||
if(model.length > 0 && vertical) : VerticalLayout {
|
||||
for value in root.model : ValueDelegate {
|
||||
vertical-stretch: 1;
|
||||
alternative-colors: root.alternative-colors;
|
||||
title: value.title;
|
||||
value: value.value;
|
||||
unit: value.unit;
|
||||
active: root.active;
|
||||
}
|
||||
}
|
||||
}
|
3
examples/virtual_keyboard/ui/assets/expand-more.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24">
|
||||
<path d="M480-345 240-585l56-56 184 184 184-184 56 56-240 240Z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 162 B |
|
@ -8,4 +8,5 @@ export global Icons {
|
|||
out property <image> chevron-left: @image-url("assets/chevron-left.svg");
|
||||
out property <image> arrow-circle-o-left: @image-url("assets/arrow-circle-o-left.svg");
|
||||
out property <image> globe: @image-url("assets/globe.svg");
|
||||
}
|
||||
out property <image> expand-more: @image-url("assets/expand-more.svg");
|
||||
}
|
||||
|
|
|
@ -161,6 +161,8 @@ export global VirtualKeyboardHandler {
|
|||
export component VirtualKeyboard {
|
||||
private property <bool> shift;
|
||||
|
||||
callback close();
|
||||
|
||||
preferred-width: 100%;
|
||||
|
||||
TouchArea {}
|
||||
|
@ -240,6 +242,14 @@ export component VirtualKeyboard {
|
|||
HorizontalLayout {
|
||||
spacing: 4px;
|
||||
|
||||
VirtualKeyboardButton {
|
||||
icon: Icons.expand-more;
|
||||
|
||||
key-pressed(key) => {
|
||||
root.close();
|
||||
}
|
||||
}
|
||||
|
||||
VirtualKeyboardButton {
|
||||
icon: Icons.globe;
|
||||
|
||||
|
@ -276,4 +286,4 @@ export component VirtualKeyboard {
|
|||
}
|
||||
|
||||
animate y { duration: 500ms; easing: cubic-bezier(0.05, 0.7, 0.1, 1.0); }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ macro_rules! test_example {
|
|||
}
|
||||
|
||||
test_example!(example_printerdemo, "demos/printerdemo/ui/printerdemo.slint");
|
||||
test_example!(example_usecases, "demos/usecases/ui/app.slint");
|
||||
test_example!(example_memory, "examples/memory/memory.slint");
|
||||
test_example!(example_slide_puzzle, "examples/slide_puzzle/slide_puzzle.slint");
|
||||
test_example!(example_todo, "examples/todo/ui/todo.slint");
|
||||
|
|