gpui-element
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWhen to Use
使用场景
Use the low-level trait when:
Element- Need fine-grained control over layout calculation
- Building complex, performance-critical components
- Implementing custom layout algorithms (masonry, circular, etc.)
- High-level /
RenderAPIs are insufficientRenderOnce
Prefer / for: Simple components, standard layouts, declarative UI
RenderRenderOnce当以下情况时使用低级 trait:
Element- 需要对布局计算进行细粒度控制
- 构建复杂、性能关键的组件
- 实现自定义布局算法(瀑布流、环形布局等)
- 高级/
RenderAPI无法满足需求RenderOnce
优先使用/的场景: 简单组件、标准布局、声明式UI
RenderRenderOnceQuick Start
快速开始
The trait provides direct control over three rendering phases:
Elementrust
impl Element for MyElement {
type RequestLayoutState = MyLayoutState; // Data passed to later phases
type PrepaintState = MyPaintState; // Data for painting
fn id(&self) -> Option<ElementId> {
Some(self.id.clone())
}
fn source_location(&self) -> Option<&'static std::panic::Location<'static>> {
None
}
// Phase 1: Calculate sizes and positions
fn request_layout(&mut self, .., window: &mut Window, cx: &mut App)
-> (LayoutId, Self::RequestLayoutState)
{
let layout_id = window.request_layout(
Style { size: size(px(200.), px(100.)), ..default() },
vec![],
cx
);
(layout_id, MyLayoutState { /* ... */ })
}
// Phase 2: Create hitboxes, prepare for painting
fn prepaint(&mut self, .., bounds: Bounds<Pixels>, layout: &mut Self::RequestLayoutState,
window: &mut Window, cx: &mut App) -> Self::PrepaintState
{
let hitbox = window.insert_hitbox(bounds, HitboxBehavior::Normal);
MyPaintState { hitbox }
}
// Phase 3: Render and handle interactions
fn paint(&mut self, .., bounds: Bounds<Pixels>, layout: &mut Self::RequestLayoutState,
paint_state: &mut Self::PrepaintState, window: &mut Window, cx: &mut App)
{
window.paint_quad(paint_quad(bounds, Corners::all(px(4.)), cx.theme().background));
window.on_mouse_event({
let hitbox = paint_state.hitbox.clone();
move |event: &MouseDownEvent, phase, window, cx| {
if hitbox.is_hovered(window) && phase.bubble() {
// Handle interaction
cx.stop_propagation();
}
}
});
}
}
// Enable element to be used as child
impl IntoElement for MyElement {
type Element = Self;
fn into_element(self) -> Self::Element { self }
}Elementrust
impl Element for MyElement {
type RequestLayoutState = MyLayoutState; // Data passed to later phases
type PrepaintState = MyPaintState; // Data for painting
fn id(&self) -> Option<ElementId> {
Some(self.id.clone())
}
fn source_location(&self) -> Option<&'static std::panic::Location<'static>> {
None
}
// Phase 1: Calculate sizes and positions
fn request_layout(&mut self, .., window: &mut Window, cx: &mut App)
-> (LayoutId, Self::RequestLayoutState)
{
let layout_id = window.request_layout(
Style { size: size(px(200.), px(100.)), ..default() },
vec![],
cx
);
(layout_id, MyLayoutState { /* ... */ })
}
// Phase 2: Create hitboxes, prepare for painting
fn prepaint(&mut self, .., bounds: Bounds<Pixels>, layout: &mut Self::RequestLayoutState,
window: &mut Window, cx: &mut App) -> Self::PrepaintState
{
let hitbox = window.insert_hitbox(bounds, HitboxBehavior::Normal);
MyPaintState { hitbox }
}
// Phase 3: Render and handle interactions
fn paint(&mut self, .., bounds: Bounds<Pixels>, layout: &mut Self::RequestLayoutState,
paint_state: &mut Self::PrepaintState, window: &mut Window, cx: &mut App)
{
window.paint_quad(paint_quad(bounds, Corners::all(px(4.)), cx.theme().background));
window.on_mouse_event({
let hitbox = paint_state.hitbox.clone();
move |event: &MouseDownEvent, phase, window, cx| {
if hitbox.is_hovered(window) && phase.bubble() {
// Handle interaction
cx.stop_propagation();
}
}
});
}
}
// Enable element to be used as child
impl IntoElement for MyElement {
type Element = Self;
fn into_element(self) -> Self::Element { self }
}Core Concepts
核心概念
Three-Phase Rendering
三阶段渲染
- request_layout: Calculate sizes and positions, return layout ID and state
- prepaint: Create hitboxes, compute final bounds, prepare for painting
- paint: Render element, set up interactions (mouse events, cursor styles)
- request_layout:计算尺寸和位置,返回布局ID和状态
- prepaint:创建命中区域,计算最终边界,为绘制做准备
- paint:渲染元素,设置交互(鼠标事件、光标样式)
State Flow
状态流转
RequestLayoutState → PrepaintState → paintState flows in one direction through associated types, passed as mutable references between phases.
RequestLayoutState → PrepaintState → paint状态通过关联类型单向流转,在各阶段之间以可变引用的形式传递。
Key Operations
关键操作
- Layout: - Create layout node
window.request_layout(style, children, cx) - Hitboxes: - Create interaction area
window.insert_hitbox(bounds, behavior) - Painting: - Render visual content
window.paint_quad(...) - Events: - Handle user input
window.on_mouse_event(handler)
- 布局:- 创建布局节点
window.request_layout(style, children, cx) - 命中区域:- 创建交互区域
window.insert_hitbox(bounds, behavior) - 绘制:- 渲染视觉内容
window.paint_quad(...) - 事件:- 处理用户输入
window.on_mouse_event(handler)
Reference Documentation
参考文档
Complete API Documentation
完整API文档
- Element Trait API: See api-reference.md
- Associated types, methods, parameters, return values
- Hitbox system, event handling, cursor styles
- Element Trait API:参见api-reference.md
- 关联类型、方法、参数、返回值
- 命中区域系统、事件处理、光标样式
Implementation Guides
实现指南
-
Examples: See examples.md
- Simple text element with highlighting
- Interactive element with selection
- Complex element with child management
-
Best Practices: See best-practices.md
- State management, performance optimization
- Interaction handling, layout strategies
- Error handling, testing, common pitfalls
-
Common Patterns: See patterns.md
- Text rendering, container, interactive, composite, scrollable patterns
- Pattern selection guide
-
Advanced Patterns: See advanced-patterns.md
- Custom layout algorithms (masonry, circular)
- Element composition with traits
- Async updates, memoization, virtual lists
-
示例:参见examples.md
- 带高亮的简单文本元素
- 带选择功能的交互元素
- 带子元素管理的复杂元素
-
最佳实践:参见best-practices.md
- 状态管理、性能优化
- 交互处理、布局策略
- 错误处理、测试、常见陷阱
-
常见模式:参见patterns.md
- 文本渲染、容器、交互、复合、可滚动模式
- 模式选择指南
-
高级模式:参见advanced-patterns.md
- 自定义布局算法(瀑布流、环形布局)
- 基于trait的元素组合
- 异步更新、记忆化、虚拟列表