feat: add examples

This commit is contained in:
drendog 2025-12-05 05:38:26 +01:00
parent b5ebb52d9c
commit 24ed27d5c3
Signed by: dwenya
GPG key ID: 8DD77074645332D0
16 changed files with 702 additions and 12 deletions

173
Cargo.lock generated
View file

@ -100,6 +100,56 @@ dependencies = [
"libc",
]
[[package]]
name = "anstream"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
dependencies = [
"anstyle",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstyle"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
[[package]]
name = "anstyle-parse"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
dependencies = [
"windows-sys 0.61.2",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys 0.61.2",
]
[[package]]
name = "arrayref"
version = "0.3.8"
@ -570,6 +620,12 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
[[package]]
name = "colorchoice"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
[[package]]
name = "combine"
version = "4.6.7"
@ -720,6 +776,15 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c297a1c74b71ae29df00c3e22dd9534821d60eb9af5a0192823fa2acea70c2a"
[[package]]
name = "declarative-config"
version = "0.1.0"
dependencies = [
"env_logger",
"layer-shika",
"log",
]
[[package]]
name = "derive_more"
version = "2.0.1"
@ -873,6 +938,29 @@ dependencies = [
"syn",
]
[[package]]
name = "env_filter"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2"
dependencies = [
"log",
"regex",
]
[[package]]
name = "env_logger"
version = "0.11.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f"
dependencies = [
"anstream",
"anstyle",
"env_filter",
"jiff",
"log",
]
[[package]]
name = "equivalent"
version = "1.0.1"
@ -1748,6 +1836,12 @@ dependencies = [
"windows-sys 0.48.0",
]
[[package]]
name = "is_terminal_polyfill"
version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
[[package]]
name = "itertools"
version = "0.13.0"
@ -1772,6 +1866,30 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "jiff"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35"
dependencies = [
"jiff-static",
"log",
"portable-atomic",
"portable-atomic-util",
"serde_core",
]
[[package]]
name = "jiff-static"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "jni"
version = "0.21.1"
@ -2121,6 +2239,15 @@ dependencies = [
"windows-sys 0.60.2",
]
[[package]]
name = "multi-surface"
version = "0.1.0"
dependencies = [
"env_logger",
"layer-shika",
"log",
]
[[package]]
name = "ndk"
version = "0.9.0"
@ -2604,6 +2731,12 @@ dependencies = [
"portable-atomic",
]
[[package]]
name = "once_cell_polyfill"
version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
[[package]]
name = "orbclient"
version = "0.3.47"
@ -2749,13 +2882,22 @@ dependencies = [
[[package]]
name = "portable-atomic"
version = "1.7.0"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265"
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
dependencies = [
"critical-section",
]
[[package]]
name = "portable-atomic-util"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
dependencies = [
"portable-atomic",
]
[[package]]
name = "prettyplease"
version = "0.2.20"
@ -2777,9 +2919,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.86"
version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
dependencies = [
"unicode-ident",
]
@ -2801,9 +2943,9 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.36"
version = "1.0.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
dependencies = [
"proc-macro2",
]
@ -3140,6 +3282,15 @@ version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "simple-bar"
version = "0.1.0"
dependencies = [
"env_logger",
"layer-shika",
"log",
]
[[package]]
name = "simplecss"
version = "0.2.1"
@ -3459,9 +3610,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.87"
version = "2.0.111"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
dependencies = [
"proc-macro2",
"quote",
@ -3845,6 +3996,12 @@ dependencies = [
"xmlwriter",
]
[[package]]
name = "utf8parse"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
version = "1.18.1"

View file

@ -18,7 +18,14 @@ layer-shika-composition.workspace = true
[workspace]
resolver = "2"
members = ["crates/domain", "crates/adapters", "crates/composition"]
members = [
"crates/domain",
"crates/adapters",
"crates/composition",
"examples/simple-bar",
"examples/multi-surface",
"examples/declarative-config",
]
[workspace.package]
version = "0.1.0"

View file

@ -19,7 +19,7 @@ Please note that this library is currently in early development and is not yet r
- Event handling system
- **UI Integration**: Slint integration layer with custom rendering backend
- **Documentation**: Work in progress
- **Examples**: Coming soon (examples directory prepared)
- **Examples**: Available - see [examples/](examples/) directory
**What's Working:**
@ -34,13 +34,28 @@ Please note that this library is currently in early development and is not yet r
- Not all features are fully implemented or tested
- API is still unstable and may change
- Examples and comprehensive documentation pending
- Comprehensive documentation pending
It's recommended to wait for a stable release before using this library in production projects. Development is trying to be as fast as a running skippy deer!
## Quick Start
Check out the [examples/](examples/) directory for comprehensive demonstrations.
Each example includes detailed documentation and can be run with:
```bash
cargo run -p simple-bar
cargo run -p multi-surface
cargo run -p declarative-config
...
...
```
See the [examples README](examples/README.md) for detailed usage instructions and patterns.
## Usage
Examples and usage instructions are coming soon. Hoping that they will not be too deer-ifying, like the current state of this library. If you want to use it now, use this repo as dependency instead of crates.io outdated versions.
If you want to use it now, use this repo as dependency instead of crates.io outdated versions.
## First Stable Release

78
examples/README.md Normal file
View file

@ -0,0 +1,78 @@
# layer-shika Examples
This directory contains comprehensive examples demonstrating the key features and use cases of layer-shika.
## Quick Start
Each example is a standalone crate that can be run from anywhere in the workspace:
```bash
# From workspace root
cargo run -p simple-bar
cargo run -p multi-surface
cargo run -p declarative-config
# Or with logging
RUST_LOG=info cargo run -p simple-bar
# Or from the example directory
cd examples/simple-bar
cargo run
```
## Building All Examples
From the workspace root:
```bash
cargo build --workspace
```
Or build a specific example:
```bash
cargo build -p simple-bar
cargo build -p multi-surface
cargo build -p declarative-config
```
## Example Progression
**Recommended learning path:**
1. **simple-bar** - Start here to understand the basics
2. **multi-surface** - Learn about multiple surfaces and callbacks
3. **declarative-config** - See the alternative configuration approach
## Common Patterns
### UI Files
Each example includes `.slint` files in its `ui/` directory. These demonstrate:
- Window components for surfaces
- Property bindings for dynamic updates
- Callback definitions for event handling
### Error Handling
All examples use layer-shika's `Result<()>` type for error handling with the `?` operator.
## Coming Soon
Additional examples demonstrating:
- Event loop integration (timers, channels, custom event sources)
- Multi-output support (multiple monitors) with different surfaces per output
- Advanced popup patterns
- Dynamic UI loading
## Contributing Examples
When adding new examples:
1. Create a new crate in `examples/<name>/`
2. Add to workspace members in root `Cargo.toml`
3. Include `Cargo.toml`, `src/main.rs`, `ui/*.slint`, and `README.md`
4. Follow the naming convention: kebab-case
5. Add entry to this README with clear description
6. Ensure code passes `cargo clippy --all-targets`

View file

@ -0,0 +1,14 @@
[package]
name = "declarative-config"
version.workspace = true
edition.workspace = true
license.workspace = true
publish = false
[lints]
workspace = true
[dependencies]
layer-shika = { path = "../.." }
env_logger = "0.11.7"
log.workspace = true

View file

@ -0,0 +1,27 @@
# Declarative Config Example
This example demonstrates the declarative configuration approach using `ShellConfig` instead of the fluent builder API.
## What it demonstrates
- Creating a shell from declarative configuration
- Using `ShellConfig` and `SurfaceComponentConfig`
- Specifying all surface properties explicitly via `SurfaceConfig`
- Separating configuration building from shell creation
- Loading UI from file path via `CompiledUiSource::file()`
## Running
```bash
cd examples/declarative-config
RUST_LOG=info cargo run
```
## When to use declarative config
- Loading configuration from external sources
- Programmatically generating configurations
- When you need full control over all configuration fields
- Building configuration tools or editors
For simple use cases, the fluent builder API is more ergonomic.

View file

@ -0,0 +1,54 @@
use std::path::PathBuf;
use layer_shika::prelude::*;
use layer_shika::slint_interpreter::Value;
fn main() -> Result<()> {
env_logger::builder()
.filter_level(log::LevelFilter::Info)
.init();
log::info!("Starting declarative-config example");
let config = build_config();
log::info!("Creating shell with {} surface(s)", config.surfaces.len());
let mut shell = Shell::from_config(config)?;
log::info!("Shell has surfaces: {:?}", shell.surface_names());
log::info!("Has StatusBar surface: {}", shell.has_surface("StatusBar"));
shell.on("StatusBar", "settings-clicked", |_control| {
log::info!("Settings button clicked");
Value::Void
})?;
log::info!("Registered callback for settings-clicked");
shell.run()?;
Ok(())
}
fn build_config() -> ShellConfig {
let ui_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("ui/bar.slint");
ShellConfig {
ui_source: CompiledUiSource::file(ui_path),
surfaces: vec![SurfaceComponentConfig::with_config(
"StatusBar",
SurfaceConfig {
dimensions: SurfaceDimension::new(0, 42),
anchor: AnchorEdges::top_bar(),
exclusive_zone: 42,
layer: Layer::Top,
margin: Margins::default(),
namespace: "declarative-config-example".to_string(),
scale_factor: ScaleFactor::default(),
keyboard_interactivity: KeyboardInteractivity::OnDemand,
output_policy: OutputPolicy::PrimaryOnly,
},
)],
}
}

View file

@ -0,0 +1,40 @@
import { Button } from "std-widgets.slint";
export component StatusBar inherits Window {
callback settings-clicked();
HorizontalLayout {
padding: 8px;
spacing: 16px;
Text {
text: "Declarative Config Example";
font-size: 14px;
vertical-alignment: center;
}
Rectangle {
horizontal-stretch: 1;
}
HorizontalLayout {
spacing: 12px;
Text {
text: "Layer: Top | Zone: 42px | Anchor: Top";
color: #88c0d0;
font-size: 12px;
vertical-alignment: center;
}
settings-btn := Button {
text: "⚙️";
min-width: 32px;
clicked => {
settings-clicked();
}
}
}
}
}

View file

@ -0,0 +1,14 @@
[package]
name = "multi-surface"
version.workspace = true
edition.workspace = true
license.workspace = true
publish = false
[lints]
workspace = true
[dependencies]
layer-shika = { path = "../.." }
env_logger = "0.11.7"
log.workspace = true

View file

@ -0,0 +1,53 @@
# Multi-Surface Example
This example demonstrates creating a shell with multiple independent surfaces - a top bar and a bottom dock.
## What it demonstrates
- Multiple surface creation in a single shell
- Chaining surface configurations with `.surface()`
- Different anchoring for each surface (top and bottom)
- Independent exclusive zones per surface
- Separate namespaces for each surface
- Registering callbacks on specific surfaces
- Listing all surfaces with `shell.surface_names()`
## Running
```bash
cd examples/multi-surface
RUST_LOG=info cargo run
```
## Key concepts
Each surface is configured independently via chained `.surface()` calls:
```rust
let mut shell = Shell::from_file("ui/shell.slint")
.surface("TopBar")
.height(42)
.anchor(AnchorEdges::top_bar())
.exclusive_zone(42)
.surface("Dock")
.height(64)
.anchor(AnchorEdges::bottom_bar())
.exclusive_zone(64)
.build()?;
```
Callbacks are registered per-surface:
```rust
shell.on("TopBar", "workspace_clicked", |control| {
// Handle TopBar events
Value::Void
})?;
shell.on("Dock", "app_clicked", |control| {
// Handle Dock events
Value::Void
})?;
```
Both surfaces run in the same event loop and share the same Slint compilation result.

View file

@ -0,0 +1,44 @@
use layer_shika::prelude::*;
use layer_shika::slint_interpreter::Value;
use std::path::PathBuf;
fn main() -> Result<()> {
env_logger::builder()
.filter_level(log::LevelFilter::Info)
.init();
log::info!("Starting multi-surface example");
let ui_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("ui/shell.slint");
let mut shell = Shell::from_file(ui_path)
.surface("TopBar")
.height(42)
.anchor(AnchorEdges::top_bar())
.exclusive_zone(42)
.namespace("multi-surface-top")
.surface("Dock")
.height(64)
.anchor(AnchorEdges::bottom_bar())
.exclusive_zone(64)
.namespace("multi-surface-dock")
.build()?;
shell.on("TopBar", "workspace_clicked", |_control| {
log::info!("Workspace button clicked in TopBar");
Value::Void
})?;
shell.on_with_args("Dock", "app_clicked", |args, _control| {
if let Some(Value::String(app_name)) = args.first() {
log::info!("App clicked in Dock: {}", app_name.as_str());
}
Value::Void
})?;
log::info!("Running shell with surfaces: {:?}", shell.surface_names());
shell.run()?;
Ok(())
}

View file

@ -0,0 +1,104 @@
import { HorizontalBox, Button } from "std-widgets.slint";
export component TopBar inherits Window {
callback workspace-clicked <=> workspace-btn.clicked;
HorizontalLayout {
padding: 8px;
spacing: 12px;
// Workspace switcher
HorizontalLayout {
alignment: start;
spacing: 8px;
workspace-btn := Button {
text: "Workspaces";
}
Text {
text: "1";
color: #88c0d0;
font-size: 14px;
vertical-alignment: center;
horizontal-alignment: center;
min-width: 24px;
}
Text {
text: "2";
color: #4c566a;
font-size: 14px;
vertical-alignment: center;
horizontal-alignment: center;
min-width: 24px;
}
}
Rectangle {
horizontal-stretch: 1;
}
// System info
HorizontalLayout {
alignment: end;
spacing: 12px;
Text {
text: "🕐 12:34";
color: #88c0d0;
font-size: 14px;
vertical-alignment: center;
}
}
}
}
export component Dock inherits Window {
callback app-clicked(string);
HorizontalBox {
padding: 12px;
spacing: 16px;
alignment: center;
// App icons
Button {
text: "🌐";
min-width: 48px;
min-height: 48px;
clicked => {
app-clicked("browser");
}
}
Button {
text: "📁";
min-width: 48px;
min-height: 48px;
clicked => {
app-clicked("files");
}
}
Button {
text: "💻";
min-width: 48px;
min-height: 48px;
clicked => {
app-clicked("terminal");
}
}
Button {
text: "🎵";
min-width: 48px;
min-height: 48px;
clicked => {
app-clicked("music");
}
}
}
}

View file

@ -0,0 +1,14 @@
[package]
name = "simple-bar"
version.workspace = true
edition.workspace = true
license.workspace = true
publish = false
[lints]
workspace = true
[dependencies]
layer-shika = { path = "../.." }
env_logger = "0.11.7"
log.workspace = true

View file

@ -0,0 +1,10 @@
# Simple Bar Example
This example demonstrates the most basic use case of layer-shika: creating a status bar using the fluent builder API.
## Running
```bash
cd examples/simple-bar
cargo run
```

View file

@ -0,0 +1,23 @@
use layer_shika::prelude::*;
use std::path::PathBuf;
fn main() -> Result<()> {
env_logger::builder()
.filter_level(log::LevelFilter::Info)
.init();
log::info!("Starting simple-bar example");
let ui_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("ui/bar.slint");
Shell::from_file(ui_path)
.surface("Bar")
.height(42)
.anchor(AnchorEdges::top_bar())
.exclusive_zone(42)
.namespace("simple-bar-example")
.build()?
.run()?;
Ok(())
}

View file

@ -0,0 +1,36 @@
import { VerticalBox, HorizontalBox } from "std-widgets.slint";
export component Bar inherits Window {
default-font-size: 16px;
HorizontalBox {
// Left section
Text {
text: "Simple Bar Example";
vertical-alignment: center;
}
// Center section (spacer)
Rectangle {
horizontal-stretch: 1;
}
// Right section
HorizontalLayout {
alignment: end;
spacing: 12px;
Text {
text: "🕐 12:34";
color: #88c0d0;
vertical-alignment: center;
}
Text {
text: "🔋 75%";
color: #a3be8c;
vertical-alignment: center;
}
}
}
}