example: Add input example. (#1380)

This commit is contained in:
Jason Lee 2025-10-15 13:40:36 +08:00 committed by GitHub
parent 4ccd7d99d0
commit 429a4b2858
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 107 additions and 38 deletions

9
Cargo.lock generated
View file

@ -3564,6 +3564,15 @@ dependencies = [
"generic-array",
]
[[package]]
name = "input"
version = "0.1.0"
dependencies = [
"anyhow",
"gpui",
"gpui-component",
]
[[package]]
name = "instant"
version = "0.1.13"

View file

@ -1,5 +1,5 @@
[workspace]
members = ["examples/hello_world", "examples/window_title", "crates/macros", "crates/story", "crates/ui", "examples/window_title", "examples/app_assets", "examples/app_assets"]
members = ["examples/hello_world", "examples/window_title", "crates/macros", "crates/story", "crates/ui", "examples/window_title", "examples/app_assets", "examples/app_assets", "examples/input"]
default-members = ["crates/story"]
resolver = "2"

View file

@ -1,12 +1,8 @@
use gpui::*;
use gpui_component::{
button::{Button, ButtonVariants},
Root, StyledExt,
};
use gpui_component::{button::*, *};
pub struct HelloWorld;
impl Render for HelloWorld {
pub struct Example;
impl Render for Example {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
div()
.v_flex()
@ -14,7 +10,6 @@ impl Render for HelloWorld {
.size_full()
.items_center()
.justify_center()
.text_center()
.child("Hello, World!")
.child(
Button::new("ok")
@ -29,38 +24,13 @@ fn main() {
let app = Application::new();
app.run(move |cx| {
// We must initialize gpui_component before using it.
// This must be called before using any GPUI Component features.
gpui_component::init(cx);
cx.activate(true);
let mut window_size = size(px(640.), px(480.));
if let Some(display) = cx.primary_display() {
let display_size = display.bounds().size;
window_size.width = window_size.width.min(display_size.width * 0.85);
window_size.height = window_size.height.min(display_size.height * 0.85);
}
let window_bounds = Bounds::centered(None, window_size, cx);
cx.spawn(async move |cx| {
let options = WindowOptions {
window_bounds: Some(WindowBounds::Windowed(window_bounds)),
titlebar: None,
window_min_size: Some(gpui::Size {
width: px(640.),
height: px(480.),
}),
kind: WindowKind::Normal,
#[cfg(target_os = "linux")]
window_background: gpui::WindowBackgroundAppearance::Transparent,
#[cfg(target_os = "linux")]
window_decorations: Some(gpui::WindowDecorations::Client),
..Default::default()
};
cx.open_window(options, |window, cx| {
let view = cx.new(|_| HelloWorld);
// The first level on the window must be Root.
cx.open_window(WindowOptions::default(), |window, cx| {
let view = cx.new(|_| Example);
// This first level on the window, should be a Root.
cx.new(|cx| Root::new(view.into(), window, cx))
})?;

12
examples/input/Cargo.toml Normal file
View file

@ -0,0 +1,12 @@
[package]
name = "input"
version = "0.1.0"
edition = "2024"
[dependencies]
anyhow.workspace = true
gpui.workspace = true
gpui-component = { workspace = true }
[lints]
workspace = true

View file

@ -0,0 +1,78 @@
use gpui::*;
use gpui_component::{
input::{InputEvent, InputState, TextInput},
*,
};
pub struct Example {
input_state: Entity<InputState>,
display_text: SharedString,
/// We need to keep the subscriptions alive with the Example entity.
///
/// So if the Example entity is dropped, the subscriptions are also dropped.
/// This is important to avoid memory leaks.
_subscriptions: Vec<Subscription>,
}
impl Example {
fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
let input_state = cx.new(|cx| InputState::new(window, cx).placeholder("Enter your name"));
let _subscriptions = vec![cx.subscribe_in(&input_state, window, {
let input_state = input_state.clone();
move |this, _, ev: &InputEvent, _window, cx| match ev {
InputEvent::Change => {
let value = input_state.read(cx).value();
this.display_text = format!("Hello, {}!", value).into();
cx.notify()
}
_ => {}
}
})];
Self {
input_state,
display_text: SharedString::default(),
_subscriptions,
}
}
}
impl Render for Example {
fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
v_flex()
.p_5()
.gap_2()
.size_full()
.items_center()
.justify_center()
.child(TextInput::new(&self.input_state))
.child(self.display_text.clone())
}
}
fn main() {
let app = Application::new();
app.run(move |cx| {
// This must be called before using any GPUI Component features.
gpui_component::init(cx);
let window_options = WindowOptions {
window_bounds: Some(WindowBounds::centered(size(px(800.), px(600.)), cx)),
..Default::default()
};
cx.spawn(async move |cx| {
cx.open_window(window_options, |window, cx| {
let view = cx.new(|cx| Example::new(window, cx));
// This first level on the window, should be a Root.
cx.new(|cx| Root::new(view.into(), window, cx))
})?;
Ok::<_, anyhow::Error>(())
})
.detach();
});
}