This repository has been archived by the owner on Jun 5, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 4a069d2
Showing
36 changed files
with
1,265 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
name: Rust | ||
|
||
on: | ||
push: | ||
branches: [ "main" ] | ||
pull_request: | ||
branches: [ "main" ] | ||
|
||
env: | ||
CARGO_TERM_COLOR: always | ||
|
||
jobs: | ||
build: | ||
|
||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Build | ||
run: cargo build --verbose | ||
- name: Run tests | ||
run: cargo test --verbose |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/target | ||
/Cargo.lock |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"rust-analyzer.linkedProjects": [ | ||
".\\Cargo.toml", | ||
".\\examples\\counter_floem\\Cargo.toml", | ||
".\\examples\\counter_uikit\\Cargo.toml", | ||
".\\examples\\showcase\\Cargo.toml" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"version": "2.0.0", | ||
"tasks": [ | ||
{ | ||
"type": "cargo", | ||
"command": "run", | ||
"problemMatcher": [ | ||
"$rustc" | ||
], | ||
"label": "rust: start showcase", | ||
"options": { | ||
"cwd": "examples/showcase" | ||
} | ||
} | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
[package] | ||
name = "floem-ui-kit" | ||
description = "Ready-to-use UI components for the Floem GUI library" | ||
license = "MIT" | ||
version = "0.1.0" | ||
edition = "2021" | ||
repository = "https://github.com/pieterdd/floem-ui-kit" | ||
include = ["/src", "/docs"] | ||
categories = ["gui"] | ||
keywords = ["gui", "ui", "graphics", "interface", "widgets"] | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
embed-doc-image = "0.1.4" | ||
floem = { git = "https://github.com/lapce/floem", rev = "e795021bfb28cd15a6d499349e547c435ceb8520" } | ||
im = "15.1.0" | ||
num = "0.4.1" | ||
strum = { version = "0.25.0", features = ["derive"] } | ||
|
||
[workspace] | ||
members = [ | ||
"examples/counter_floem", | ||
"examples/counter_uikit", | ||
"examples/showcase", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
MIT License | ||
|
||
Copyright (c) 2023 Floem UI Kit | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# Floem UI Kit | ||
|
||
[![Crates.io](https://img.shields.io/crates/v/floem-ui-kit.svg)](https://crates.io/crates/floem-ui-kit) | ||
[![docs.rs](https://img.shields.io/docsrs/floem-ui-kit/latest)](https://docs.rs/floem-ui-kit/latest/floem-ui-kit/theme/struct.Theme.html) | ||
|
||
Want a pretty Rust GUI with minimal time investment? Use a kit of premade UI components! Floem UI Kit provides polished widgets you can use in conjunction with the [Floem](https://github.com/lapce/floem) GUI library. | ||
|
||
- ✅ Supports all major desktop operating systems | ||
- ✅ All widgets implement hover, focus and disabled state | ||
- ✅ All widgets provide keyboard access | ||
- ✅ Supports multiple accent colors | ||
|
||
![Showcase](docs/img/showcase.png) | ||
|
||
⚠️ **Floem UI Kit, like Floem, is experimental software.** ⚠️ | ||
|
||
## Installation | ||
|
||
In addition to installing Floem UI Kit, you'll need to add Floem as a dependency: | ||
|
||
```toml | ||
floem = { git = "https://github.com/lapce/floem", rev = "e795021bfb28cd15a6d499349e547c435ceb8520" } | ||
``` | ||
|
||
## First time using Floem? | ||
|
||
Floem's documentation is available [here](http://lapce.dev/floem/floem/). You might notice that it incorporates familiar concepts from other UI frameworks, including: | ||
|
||
- Interface composition using nestable horizontal and vertical widget containers | ||
- A styling system that brings many CSS-like features to Rust, without the overhead of a browser runtime | ||
- Reactivity using signals, as seen in frameworks like [SolidJS](https://www.solidjs.com/) | ||
- Implementation of UIs using functions, similar to Jetpack Compose | ||
|
||
For a mimimal example involving a counter that can be incremented/decremented, have a look at [this file](examples/counter_floem/src/main.rs). It looks quite basic when rendered: | ||
|
||
![A counter in pure floem](docs/img/counter_floem.png) | ||
|
||
If you've familiarized yourself with the Floem's basics, keep reading to find out how to spice things up. | ||
|
||
## Getting started with Floem UI Kit | ||
|
||
The Floem UI Kit workflow involves: | ||
|
||
1. Creating an instance of [`floem_ui_kit::theme::Theme`](https://docs.rs/floem-ui-kit/latest/floem_ui_kit/theme/struct.Theme.html). `Theme::default()` creates an instance with default settings. | ||
2. Using the widget creation methods in `Theme` to build your UI. If Floem UI Kit doesn't have exactly what you want, you can mix and match with self-written UI components. You can keep using Floem's `v_stack` and `h_stack` methods to lay out your components. | ||
3. Wrapping your window contents in Floem UI Kit's padded container to ensure your widgets don't stick to the side of the window. | ||
4. Wrapping the padded container in Floem UI Kit's primary container to apply the theme's window background. | ||
|
||
[Over here](examples/counter_uikit/src/main.rs) you'll find the above example ported to Floem UI Kit. Here is a reference render: | ||
|
||
![A counter in Floem UI Kit](docs/img/counter_uikit.png) | ||
|
||
These components are still sticking to one another. You'll probably want to add a small gap between them. `v_stack` and `h_stack` can automatically add those gaps, provided that you request it: | ||
|
||
```rust | ||
v_stack(/* .. */) | ||
.style(|s| s.gap(0.0, 10.0)) | ||
``` | ||
|
||
The above will add no horizontal gap and a vertical 10-pixel gap. | ||
|
||
## Supported widgets | ||
|
||
For more information on how to use these, see the [code docs](https://docs.rs/floem-ui-kit/latest/floem_ui_kit/theme/struct.Theme.html#implementations). | ||
|
||
| **Widget** | **Preview** | | ||
| ---------------------------- | -------------------------------------------- | | ||
| Button _(multiple variants)_ | ![Button](docs/img/button.png) | | ||
| Checkbox | ![Checkbox](docs/img/checkbox.png) | | ||
| Integer input (spinbox) | ![Integer input](docs/img/integer_input.png) | | ||
| Label _(multiple variants)_ | ![Label](docs/img/label.png) | | ||
| Radio group | ![Radio group](docs/img/radio_group.png) | | ||
| Simple header | ![Simple header](docs/img/simple_header.png) | | ||
| Text input | ![Text input](docs/img/text_input.png) | | ||
|
||
For an example incorporating all available widgets, [see here](examples/showcase/src/main.rs). It's the source code for the screenshot at the top of the README. | ||
|
||
## Not quite what you're looking for? | ||
|
||
I'm not aware of any other floem UI component libraries right now. | ||
|
||
As far as Rust UI libraries go, [Iced](https://iced.rs/) is a well-known one. Device manufacturer System76 is using it to implement its own desktop environment. You might be able to build onto their work by checking out [libcosmic](https://github.com/pop-os/libcosmic). Be advised that its learning curve may be a bit steeper than Floem's, and that the library is primarily intended for use by applications that are native to the Cosmic desktop environment. | ||
|
||
If you're willing to consider Electron-like solutions that are not completely native and may have a larger resource footprint, I'd definitely check out [Tauri](https://tauri.app/). Since it's built on HTML/JS/CSS, you can use it with any web-based UI framework. |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[package] | ||
name = "counter-floem" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
floem = { git = "https://github.com/lapce/floem", rev = "e795021bfb28cd15a6d499349e547c435ceb8520" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
use floem::reactive::create_signal; | ||
use floem::view::View; | ||
use floem::views::{h_stack, label, text, v_stack, Decorators}; | ||
use floem::EventPropagation; | ||
|
||
/// Renders your UI, and updates it whenever a signal fires | ||
fn app_view() -> impl View { | ||
// Use counter.get() to access the counter value. | ||
// Change it with set_counter.update(..) or set_counter.set(). | ||
let (counter, set_counter) = create_signal(0); | ||
|
||
// v_stack = vertical group layout | ||
v_stack(( | ||
label(move || format!("Value: {}", counter.get())), | ||
// h_stack = horizontal group layout | ||
h_stack(( | ||
text("Increment").on_click(move |_| { | ||
set_counter.update(|value| *value += 1); | ||
EventPropagation::Stop | ||
}), | ||
text("Decrement").on_click(move |_| { | ||
set_counter.update(|value| *value -= 1); | ||
EventPropagation::Stop | ||
}), | ||
)), | ||
)) | ||
} | ||
|
||
fn main() { | ||
floem::launch(app_view); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
[package] | ||
name = "counter-uikit" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
floem-ui-kit = { path = "../.." } | ||
floem = { git = "https://github.com/lapce/floem", rev = "e795021bfb28cd15a6d499349e547c435ceb8520" } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
use floem::reactive::create_signal; | ||
use floem::view::View; | ||
use floem::views::{h_stack, v_stack, Decorators}; | ||
use floem::EventPropagation; | ||
use floem_ui_kit::button::ButtonVariant; | ||
use floem_ui_kit::label::LabelVariant; | ||
use floem_ui_kit::theme::Theme; | ||
|
||
fn app_view() -> impl View { | ||
let theme = Theme::default(); | ||
|
||
let (counter, set_counter) = create_signal(0); | ||
|
||
theme.primary_container( | ||
theme.padded_container(v_stack(( | ||
theme.label( | ||
move || format!("Value: {}", counter.get()), | ||
LabelVariant::Regular, | ||
), | ||
h_stack(( | ||
theme | ||
.button(|| "Increment", ButtonVariant::Emphasized) | ||
.on_click(move |_| { | ||
set_counter.update(|value| *value += 1); | ||
EventPropagation::Stop | ||
}), | ||
theme | ||
.button(|| "Decrement", ButtonVariant::Emphasized) | ||
.on_click(move |_| { | ||
set_counter.update(|value| *value -= 1); | ||
EventPropagation::Stop | ||
}), | ||
)), | ||
))), | ||
) | ||
} | ||
|
||
fn main() { | ||
floem::launch(app_view); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[package] | ||
name = "showcase" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
floem-ui-kit = { path = "../.." } | ||
floem = { git = "https://github.com/lapce/floem", rev = "e795021bfb28cd15a6d499349e547c435ceb8520" } | ||
strum = { version = "0.25.0", features = ["derive"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
#![windows_subsystem = "windows"] | ||
|
||
use floem::kurbo::Size; | ||
use floem::reactive::create_rw_signal; | ||
use floem::reactive::create_signal; | ||
use floem::style::AlignItems; | ||
use floem::view::View; | ||
use floem::views::h_stack; | ||
use floem::views::v_stack; | ||
use floem::views::Decorators; | ||
use floem::window::WindowConfig; | ||
use floem::EventPropagation; | ||
use floem_ui_kit::button::ButtonVariant; | ||
use floem_ui_kit::label::LabelVariant; | ||
use floem_ui_kit::radio::RadioGroupVariant; | ||
use floem_ui_kit::theme::Theme; | ||
|
||
fn app_view() -> impl View { | ||
let theme = Theme::default(); | ||
|
||
let (inputs_enabled, set_inputs_enabled) = create_signal(true); | ||
|
||
let (boolean_signal, set_boolean_signal) = create_signal(true); | ||
let rw_counter = create_rw_signal(0); | ||
let (counter, set_counter) = (rw_counter.read_only(), rw_counter.write_only()); | ||
let text_value = create_rw_signal(String::from("This is a text")); | ||
|
||
theme.primary_container( | ||
v_stack(( | ||
theme.simple_header("Header"), | ||
theme.padded_container( | ||
v_stack(( | ||
theme.labeled_checkbox(inputs_enabled, set_inputs_enabled, || { | ||
"Enable all inputs" | ||
}), | ||
h_stack(( | ||
v_stack(( | ||
theme.label(move || "Enable all inputs", LabelVariant::Dimmed), | ||
theme.label(move || "Counter", LabelVariant::Dimmed), | ||
theme.label(move || "Accent color", LabelVariant::Dimmed), | ||
theme.label(move || "Text input", LabelVariant::Dimmed), | ||
)) | ||
.style(|s| s.gap(0.0, 5.0)), | ||
v_stack(( | ||
theme.label( | ||
move || match inputs_enabled.get() { | ||
true => "Yes", | ||
false => "No", | ||
}, | ||
LabelVariant::Regular, | ||
), | ||
theme.label(move || counter.get(), LabelVariant::Regular), | ||
theme.label(move || theme.accent_color.get(), LabelVariant::Regular), | ||
theme.label(move || text_value.get(), LabelVariant::Regular), | ||
)) | ||
.style(|s| s.gap(0.0, 5.0)), | ||
)) | ||
.style(|s| s.gap(20.0, 0.0)), | ||
h_stack(( | ||
theme | ||
.button(|| "Increment", ButtonVariant::Emphasized) | ||
.on_click(move |_| { | ||
set_counter.update(|value| *value += 1); | ||
EventPropagation::Stop | ||
}) | ||
.disabled(move || !inputs_enabled.get()), | ||
theme | ||
.button(|| "Decrement", ButtonVariant::Regular) | ||
.on_click(move |_| { | ||
set_counter.update(|value| *value -= 1); | ||
EventPropagation::Stop | ||
}) | ||
.disabled(move || !inputs_enabled.get()), | ||
)) | ||
.style(|s| s.gap(10.0, 0.0)), | ||
theme | ||
.integer_input(rw_counter, 1, Some(-2), Some(9000)) | ||
.disabled(move || !inputs_enabled.get()), | ||
theme | ||
.labeled_checkbox(boolean_signal, set_boolean_signal, || { | ||
"Ordinary checkbox" | ||
}) | ||
.disabled(move || !inputs_enabled.get()), | ||
theme | ||
.radio_group( | ||
theme.accent_color.read_only(), | ||
theme.accent_color.write_only(), | ||
10.0, | ||
RadioGroupVariant::Horizontal, | ||
) | ||
.disabled(move || !inputs_enabled.get()), | ||
theme | ||
.text_input(text_value) | ||
.disabled(move || !inputs_enabled.get()), | ||
)) | ||
.style(|s| s.align_items(AlignItems::Start).gap(0.0, 20.0)), | ||
), | ||
)) | ||
.style(|s| s.width_full()), | ||
) | ||
} | ||
|
||
fn main() { | ||
let window_config = WindowConfig::default() | ||
.size(Size { | ||
width: 400.0, | ||
height: 550.0, | ||
}) | ||
.title("Floem UI Kit Showcase"); | ||
|
||
floem::Application::new() | ||
.window(move |_| app_view(), Some(window_config)) | ||
.run() | ||
} |
Oops, something went wrong.