Files
ruin/aspirational_examples/02_widget_refs_and_commands.rs

117 lines
3.5 KiB
Rust

//! Aspirational RUIN app API for imperative widget refs, typed shortcuts, and overlay layers.
//!
//! Intentionally non-compiling; this is a design sketch.
use ruin::prelude::*;
#[ruin_runtime::async_main]
async fn main() -> ruin::Result<()> {
App::new()
.window(Window::new().title("RUIN Search").size(1100.0, 760.0))
.mount::<CommandSearchApp>()
.run()
.await
}
#[component]
fn CommandSearchApp() -> impl View {
let query = use_signal(String::new);
let selected_index = use_signal(|| 0usize);
let search_input = use_widget_ref::<TextInput>();
let results_list = use_widget_ref::<ScrollArea>();
let toast_region = use_widget_ref::<ToastRegion>();
let results = use_memo(move || fuzzy::search(COMMANDS, &query.get()));
use_mount({
let search_input = search_input.clone();
move || search_input.focus()
});
use_shortcut(
Shortcut::new(Key::Character('K')).with_ctrl(),
ShortcutScope::Application,
{
let search_input = search_input.clone();
move || search_input.focus()
},
);
use_shortcut(
Shortcut::new(Key::ArrowDown),
ShortcutScope::FocusedWithin(results_list.focus_scope()),
move || {
selected_index.update(|index| {
*index = (*index + 1).min(results.with(|items| items.len().saturating_sub(1)));
});
results_list.scroll_selected_into_view();
},
);
use_shortcut(
Shortcut::new(Key::Enter),
ShortcutScope::FocusedItem(results_list.focus_scope()),
{
let toast_region = toast_region.clone();
move || {
if let Some(command) = results.with(|items| items.get(selected_index.get()).cloned()) {
toast_region.show(command.title.to_string());
command.run();
}
}
},
);
view! {
layers(fill = true) {
layer(kind = LayerKind::Content) {
column(fill = true, gap = 16, padding = 20) {
text(role = TextRole::Heading(1), size = 28, weight = FontWeight::Semibold) {
"Command search"
}
text_input(
ref = search_input,
value = query,
placeholder = "Search commands...",
) {}
scroll_area(ref = results_list, fill = true) {
list(gap = 8) {
for (row_index, command) in results.iter().enumerate() keyed by command.id {
CommandRow(
selected = row_index == selected_index.get(),
title = command.title,
subtitle = command.subtitle,
on_press = move |_| command.run(),
) {}
}
}
}
}
}
layer(
kind = LayerKind::Overlay,
anchor = Anchor::bottom_right(20.0, 20.0),
pointer_events = PointerEvents::PassThrough,
) {
ToastRegion(ref = toast_region) {}
}
}
}
}
static COMMANDS: &[Command] = &[];
struct Command {
id: &'static str,
title: &'static str,
subtitle: &'static str,
}
impl Command {
fn run(&self) {}
}