gpui-action
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseOverview
概述
Actions provide declarative keyboard-driven UI interactions in GPUI.
Key Concepts:
- Define actions with macro or
actions!#[derive(Action)] - Bind keys with
cx.bind_keys() - Handle with on elements
.on_action() - Context-aware via
key_context()
动作在GPUI中提供声明式的键盘驱动UI交互。
核心概念:
- 使用宏或
actions!定义动作#[derive(Action)] - 使用绑定按键
cx.bind_keys() - 在元素上通过处理动作
.on_action() - 通过实现上下文感知
key_context()
Quick Start
快速开始
Simple Actions
简单动作
rust
use gpui::actions;
actions!(editor, [MoveUp, MoveDown, Save, Quit]);
const CONTEXT: &str = "Editor";
pub fn init(cx: &mut App) {
cx.bind_keys([
KeyBinding::new("up", MoveUp, Some(CONTEXT)),
KeyBinding::new("down", MoveDown, Some(CONTEXT)),
KeyBinding::new("cmd-s", Save, Some(CONTEXT)),
KeyBinding::new("cmd-q", Quit, Some(CONTEXT)),
]);
}
impl Render for Editor {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.key_context(CONTEXT)
.on_action(cx.listener(Self::move_up))
.on_action(cx.listener(Self::move_down))
.on_action(cx.listener(Self::save))
}
}
impl Editor {
fn move_up(&mut self, _: &MoveUp, cx: &mut Context<Self>) {
// Handle move up
cx.notify();
}
fn move_down(&mut self, _: &MoveDown, cx: &mut Context<Self>) {
cx.notify();
}
fn save(&mut self, _: &Save, cx: &mut Context<Self>) {
// Save logic
cx.notify();
}
}rust
use gpui::actions;
actions!(editor, [MoveUp, MoveDown, Save, Quit]);
const CONTEXT: &str = "Editor";
pub fn init(cx: &mut App) {
cx.bind_keys([
KeyBinding::new("up", MoveUp, Some(CONTEXT)),
KeyBinding::new("down", MoveDown, Some(CONTEXT)),
KeyBinding::new("cmd-s", Save, Some(CONTEXT)),
KeyBinding::new("cmd-q", Quit, Some(CONTEXT)),
]);
}
impl Render for Editor {
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
div()
.key_context(CONTEXT)
.on_action(cx.listener(Self::move_up))
.on_action(cx.listener(Self::move_down))
.on_action(cx.listener(Self::save))
}
}
impl Editor {
fn move_up(&mut self, _: &MoveUp, cx: &mut Context<Self>) {
// 处理向上移动
cx.notify();
}
fn move_down(&mut self, _: &MoveDown, cx: &mut Context<Self>) {
cx.notify();
}
fn save(&mut self, _: &Save, cx: &mut Context<Self>) {
// 保存逻辑
cx.notify();
}
}Actions with Parameters
带参数的动作
rust
#[derive(Clone, PartialEq, Action, Deserialize)]
#[action(namespace = editor)]
pub struct InsertText {
pub text: String,
}
#[derive(Action, Clone, PartialEq, Eq, Deserialize)]
#[action(namespace = editor, no_json)]
pub struct Digit(pub u8);
cx.bind_keys([
KeyBinding::new("0", Digit(0), Some(CONTEXT)),
KeyBinding::new("1", Digit(1), Some(CONTEXT)),
// ...
]);
impl Editor {
fn on_digit(&mut self, action: &Digit, cx: &mut Context<Self>) {
self.insert_digit(action.0, cx);
}
}rust
#[derive(Clone, PartialEq, Action, Deserialize)]
#[action(namespace = editor)]
pub struct InsertText {
pub text: String,
}
#[derive(Action, Clone, PartialEq, Eq, Deserialize)]
#[action(namespace = editor, no_json)]
pub struct Digit(pub u8);
cx.bind_keys([
KeyBinding::new("0", Digit(0), Some(CONTEXT)),
KeyBinding::new("1", Digit(1), Some(CONTEXT)),
// ...
]);
impl Editor {
fn on_digit(&mut self, action: &Digit, cx: &mut Context<Self>) {
self.insert_digit(action.0, cx);
}
}Key Formats
按键格式
rust
// Modifiers
"cmd-s" // Command (macOS) / Ctrl (Windows/Linux)
"ctrl-c" // Control
"alt-f" // Alt
"shift-tab" // Shift
"cmd-ctrl-f" // Multiple modifiers
// Keys
"a-z", "0-9" // Letters and numbers
"f1-f12" // Function keys
"up", "down", "left", "right"
"enter", "escape", "space", "tab"
"backspace", "delete"
"-", "=", "[", "]", etc. // Special charactersrust
// 修饰键
"cmd-s" // Command(macOS)/ Ctrl(Windows/Linux)
"ctrl-c" // 控制键
"alt-f" // Alt键
"shift-tab" // Shift键
"cmd-ctrl-f" // 多个修饰键
// 普通键
"a-z", "0-9" // 字母和数字
"f1-f12" // 功能键
"up", "down", "left", "right"
"enter", "escape", "space", "tab"
"backspace", "delete"
"-", "=", "[", "]", etc. // 特殊字符Action Naming
动作命名
Prefer verb-noun pattern:
rust
actions!([
OpenFile, // ✅ Good
CloseWindow, // ✅ Good
ToggleSidebar, // ✅ Good
Save, // ✅ Good (common exception)
]);优先使用“动词-名词”模式:
rust
actions!([
OpenFile, // ✅ 推荐
CloseWindow, // ✅ 推荐
ToggleSidebar, // ✅ 推荐
Save, // ✅ 推荐(常见例外)
]);Context-Aware Bindings
上下文感知绑定
rust
const EDITOR_CONTEXT: &str = "Editor";
const MODAL_CONTEXT: &str = "Modal";
// Same key, different contexts
cx.bind_keys([
KeyBinding::new("escape", CloseModal, Some(MODAL_CONTEXT)),
KeyBinding::new("escape", ClearSelection, Some(EDITOR_CONTEXT)),
]);
// Set context on element
div()
.key_context(EDITOR_CONTEXT)
.child(editor_content)rust
const EDITOR_CONTEXT: &str = "Editor";
const MODAL_CONTEXT: &str = "Modal";
// 同一按键,不同上下文
cx.bind_keys([
KeyBinding::new("escape", CloseModal, Some(MODAL_CONTEXT)),
KeyBinding::new("escape", ClearSelection, Some(EDITOR_CONTEXT)),
]);
// 在元素上设置上下文
div()
.key_context(EDITOR_CONTEXT)
.child(editor_content)Best Practices
最佳实践
✅ Use Contexts
✅ 使用上下文
rust
// ✅ Good: Context-aware
div()
.key_context("MyComponent")
.on_action(cx.listener(Self::handle))rust
// ✅ 推荐:上下文感知
div()
.key_context("MyComponent")
.on_action(cx.listener(Self::handle))✅ Name Actions Clearly
✅ 清晰命名动作
rust
// ✅ Good: Clear intent
actions!([
SaveDocument,
CloseTab,
TogglePreview,
]);rust
// ✅ 推荐:意图明确
actions!([
SaveDocument,
CloseTab,
TogglePreview,
]);✅ Handle with Listeners
✅ 使用监听器处理动作
rust
// ✅ Good: Proper handler naming
impl MyComponent {
fn on_action_save(&mut self, _: &Save, cx: &mut Context<Self>) {
// Handle save
cx.notify();
}
}
div().on_action(cx.listener(Self::on_action_save))rust
// ✅ 推荐:合理命名处理函数
impl MyComponent {
fn on_action_save(&mut self, _: &Save, cx: &mut Context<Self>) {
// 处理保存逻辑
cx.notify();
}
}
div().on_action(cx.listener(Self::on_action_save))Reference Documentation
参考文档
- Complete Guide: See reference.md
- Action definition, keybinding, dispatch
- Focus-based routing, best practices
- Performance, accessibility
- 完整指南:查看reference.md
- 动作定义、按键绑定、分发
- 基于焦点的路由、最佳实践
- 性能、可访问性