examples: Add examples folder. (#1378)
This commit is contained in:
parent
6998708b81
commit
4ccd7d99d0
12 changed files with 287 additions and 14 deletions
19
Cargo.lock
generated
19
Cargo.lock
generated
|
|
@ -92,6 +92,16 @@ version = "1.0.99"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
|
||||
|
||||
[[package]]
|
||||
name = "app_assets"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"gpui",
|
||||
"gpui-component",
|
||||
"rust-embed",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
version = "1.4.1"
|
||||
|
|
@ -8760,6 +8770,15 @@ version = "0.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "window_title"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"gpui",
|
||||
"gpui-component",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.57.0"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
[workspace]
|
||||
members = ["crates/hello_world", "crates/macros", "crates/story", "crates/ui"]
|
||||
members = ["examples/hello_world", "examples/window_title", "crates/macros", "crates/story", "crates/ui", "examples/window_title", "examples/app_assets", "examples/app_assets"]
|
||||
|
||||
default-members = ["crates/story"]
|
||||
resolver = "2"
|
||||
|
|
|
|||
18
examples/README.md
Normal file
18
examples/README.md
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# GPUI Component basic examples
|
||||
|
||||
This folder contains basic examples of how to use the GPUI Component library. Each example demonstrates a specific feature or functionality of the library.
|
||||
|
||||
Unlike the examples in the `story` folder, these examples focus on 1 example for 1 feature, making it easier to understand and implement specific functionalities in your own projects.
|
||||
|
||||
## Contributing
|
||||
|
||||
Feel free to contribute more examples to this folder!
|
||||
|
||||
If you have a specific use case or feature you'd like to demonstrate, please create a new example file and submit a pull request. We will happy to merge it into the repository.
|
||||
|
||||
When creating a new example, please follow these guidelines:
|
||||
|
||||
1. Keep 1 example just doing 1 thing for more clarity.
|
||||
2. Testing the example to ensure it works as expected.
|
||||
3. Write some comment at some key parts of the code to explain what it does.
|
||||
4. Following the code style and name style used in the existing examples or in entire of GPUI Component.
|
||||
15
examples/app_assets/Cargo.toml
Normal file
15
examples/app_assets/Cargo.toml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
[package]
|
||||
edition = "2021"
|
||||
name = "app_assets"
|
||||
description = "Example to load icons or images from assets folder."
|
||||
publish = false
|
||||
version = "0.2.0"
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
gpui.workspace = true
|
||||
gpui-component = { workspace = true }
|
||||
rust-embed = { version = "8", features = ["interpolate-folder-path"] }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
62
examples/app_assets/README.md
Normal file
62
examples/app_assets/README.md
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
## Icon assets in GPUI Component
|
||||
|
||||
The [IconName](https://github.com/longbridge/gpui-component/blob/6998708b817024c2ac0f1ea164d74ddfc024e124/crates/ui/src/icon.rs#L9) is a enum that defined a bunch of icon names, because some internal components in GPUI Component will use them.
|
||||
|
||||
You can see, we have a lot of svg icon files in the `assets/icons` folder, but we are not embed all of the icon files in the library by default. This for keep the library size small.
|
||||
|
||||
So you must have your own icon files to use the `Icon` component in GPUI Component.
|
||||
|
||||
You can download the icon files from [here](https://lucide.dev/) or use your own icon files as you wish, just use the same filename as the icon name (match with the `IconName` defined) you want to use.
|
||||
|
||||
For example your assets folder:
|
||||
|
||||
```
|
||||
app_root
|
||||
assets
|
||||
icons
|
||||
close.svg
|
||||
menu.svg
|
||||
...
|
||||
src
|
||||
main.rs
|
||||
Cargo.toml
|
||||
```
|
||||
|
||||
You also can just copy the svg files you want from the `assets/icons` folder in GPUI Component repo to your own assets folder.
|
||||
|
||||
## How to use
|
||||
|
||||
You need define a `Assets` struct with rust-embed to register assets to GPUI application.
|
||||
|
||||
```rs
|
||||
use anyhow::anyhow;
|
||||
use gpui::*;
|
||||
use rust_embed::RustEmbed;
|
||||
use std::borrow::Cow;
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "./assets"]
|
||||
#[include = "icons/**/*.svg"]
|
||||
pub struct Assets;
|
||||
|
||||
impl AssetSource for Assets {
|
||||
fn load(&self, path: &str) -> Result<Option<Cow<'static, [u8]>>> {
|
||||
Self::get(path)
|
||||
.map(|f| Some(f.data))
|
||||
.ok_or_else(|| anyhow!("could not find asset at path \"{path}\""))
|
||||
}
|
||||
|
||||
fn list(&self, path: &str) -> Result<Vec<SharedString>> {
|
||||
Ok(Self::iter()
|
||||
.filter_map(|p| p.starts_with(path).then(|| p.into()))
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Call with_assets to register assets
|
||||
let app = Application::new().with_assets(Assets);
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
14
examples/app_assets/assets/icons/bot.svg
Normal file
14
examples/app_assets/assets/icons/bot.svg
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-bot"
|
||||
><path d="M12 8V4H8" /><rect width="16" height="12" x="4" y="8" rx="2" /><path
|
||||
d="M2 14h2"
|
||||
/><path d="M20 14h2" /><path d="M15 13v2" /><path d="M9 13v2" /></svg>
|
||||
|
After Width: | Height: | Size: 421 B |
14
examples/app_assets/assets/icons/inbox.svg
Normal file
14
examples/app_assets/assets/icons/inbox.svg
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="lucide lucide-inbox"
|
||||
><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" /><path
|
||||
d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z"
|
||||
/></svg>
|
||||
|
After Width: | Height: | Size: 443 B |
64
examples/app_assets/src/main.rs
Normal file
64
examples/app_assets/src/main.rs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
use anyhow::anyhow;
|
||||
use gpui::*;
|
||||
use gpui_component::{v_flex, IconName, Root};
|
||||
use rust_embed::RustEmbed;
|
||||
use std::borrow::Cow;
|
||||
|
||||
/// An asset source that loads assets from the `./assets` folder.
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "./assets"]
|
||||
#[include = "icons/**/*.svg"]
|
||||
pub struct Assets;
|
||||
|
||||
impl AssetSource for Assets {
|
||||
fn load(&self, path: &str) -> Result<Option<Cow<'static, [u8]>>> {
|
||||
if path.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
Self::get(path)
|
||||
.map(|f| Some(f.data))
|
||||
.ok_or_else(|| anyhow!("could not find asset at path \"{path}\""))
|
||||
}
|
||||
|
||||
fn list(&self, path: &str) -> Result<Vec<SharedString>> {
|
||||
Ok(Self::iter()
|
||||
.filter_map(|p| p.starts_with(path).then(|| p.into()))
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Example;
|
||||
impl Render for Example {
|
||||
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.gap_2()
|
||||
.size_full()
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.text_center()
|
||||
.child(IconName::Inbox)
|
||||
.child(IconName::Bot)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// Register Assets to GPUI application.
|
||||
let app = Application::new().with_assets(Assets);
|
||||
|
||||
app.run(move |cx| {
|
||||
// We must initialize gpui_component before using it.
|
||||
gpui_component::init(cx);
|
||||
|
||||
cx.spawn(async move |cx| {
|
||||
cx.open_window(WindowOptions::default(), |window, cx| {
|
||||
let view = cx.new(|_| Example);
|
||||
// The first level on the window must be Root.
|
||||
cx.new(|cx| Root::new(view.into(), window, cx))
|
||||
})?;
|
||||
|
||||
Ok::<_, anyhow::Error>(())
|
||||
})
|
||||
.detach();
|
||||
});
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ fn main() {
|
|||
let app = Application::new();
|
||||
|
||||
app.run(move |cx| {
|
||||
// We must initialize gpui_component before using it.
|
||||
gpui_component::init(cx);
|
||||
|
||||
cx.activate(true);
|
||||
|
|
@ -57,19 +58,11 @@ fn main() {
|
|||
..Default::default()
|
||||
};
|
||||
|
||||
let window = cx
|
||||
.open_window(options, |window, cx| {
|
||||
let view = cx.new(|_| HelloWorld);
|
||||
cx.new(|cx| Root::new(view.into(), window, cx))
|
||||
})
|
||||
.expect("failed to open window");
|
||||
|
||||
window
|
||||
.update(cx, |_, window, _| {
|
||||
window.activate_window();
|
||||
window.set_window_title("Example");
|
||||
})
|
||||
.expect("failed to update window");
|
||||
cx.open_window(options, |window, cx| {
|
||||
let view = cx.new(|_| HelloWorld);
|
||||
// The first level on the window must be Root.
|
||||
cx.new(|cx| Root::new(view.into(), window, cx))
|
||||
})?;
|
||||
|
||||
Ok::<_, anyhow::Error>(())
|
||||
})
|
||||
14
examples/window_title/Cargo.toml
Normal file
14
examples/window_title/Cargo.toml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
edition = "2021"
|
||||
name = "window_title"
|
||||
description = "An example of using gpui-component to create a window with a custom title bar."
|
||||
publish = false
|
||||
version = "0.2.0"
|
||||
|
||||
[dependencies]
|
||||
anyhow.workspace = true
|
||||
gpui.workspace = true
|
||||
gpui-component = { workspace = true }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
60
examples/window_title/src/main.rs
Normal file
60
examples/window_title/src/main.rs
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
use gpui::*;
|
||||
use gpui_component::{
|
||||
button::{Button, ButtonVariants},
|
||||
v_flex, Root, TitleBar,
|
||||
};
|
||||
|
||||
pub struct Example;
|
||||
impl Render for Example {
|
||||
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.size_full()
|
||||
.child(
|
||||
// Render custom title bar on top of Root view.
|
||||
TitleBar::new()
|
||||
.justify_between()
|
||||
.pr_2()
|
||||
.child("App with Custom title bar")
|
||||
.child("Right Item"),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.id("window-body")
|
||||
.p_5()
|
||||
.size_full()
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.child("Hello, World!")
|
||||
.child(
|
||||
Button::new("ok")
|
||||
.primary()
|
||||
.label("Let's Go!")
|
||||
.on_click(|_, _, _| println!("Clicked!")),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let app = Application::new();
|
||||
|
||||
app.run(move |cx| {
|
||||
gpui_component::init(cx);
|
||||
|
||||
cx.spawn(async move |cx| {
|
||||
let window_options = WindowOptions {
|
||||
// Setup GPUI to use custom title bar
|
||||
titlebar: Some(TitleBar::title_bar_options()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
cx.open_window(window_options, |window, cx| {
|
||||
let view = cx.new(|_| Example);
|
||||
cx.new(|cx| Root::new(view.into(), window, cx))
|
||||
})?;
|
||||
|
||||
Ok::<_, anyhow::Error>(())
|
||||
})
|
||||
.detach();
|
||||
});
|
||||
}
|
||||
Loading…
Reference in a new issue