gpui-kit 基础多行文本域指南:深入 TextareaState 的固定行数、自动增长与内容编辑

gpui-kit 基础多行文本域指南:深入 TextareaState 的固定行数、自动增长与内容编辑 gpui-kit 基础多行文本域指南深入 TextareaState 的固定行数、自动增长与内容编辑【免费下载链接】gpui-kitRust GUI components for building fantastic cross-platform desktop application by using GPUI.项目地址: https://gitcode.com/GitHub_Trending/gp/gpui-kit导读Textarea是 gpui-kit 基础库gpui_kit::base中用于普通多行文本录入的无样式控件其职责被严格限定在文本输入本身行数、自动增长、自动换行、值更新、插入与替换、光标位置。本文基于 website/base/primitives/textarea.md 文档结合 crates/base/src/input 的源码实现完整讲解TextareaState的构建方式、两种布局模式固定行数 / 自动增长、程序化编辑 API、事件机制与呈现要点。读完本文你将能够直接在 GPUI 应用中以几行代码接入一个可定制的多行输入框并理解其底层引擎的边界与取舍。1. 定位普通多行文本而非代码编辑器在 gpui-kit 的输入体系中有三种状态共享同一个编辑引擎 InputBaseState它们只是模式标记mode marker不同pub type InputState InputBaseStateInputMode; // 单行文本 pub type TextareaState InputBaseStateTextareaMode; // 多行文本 pub type EditorState InputBaseStateEditorMode; // 代码编辑器这一设计在 crates/base/src/input/base/kind.rs 中有明确注释模式标记携带的类型信息决定了哪些方法存在。TextareaState拥有auto_grow、soft_wrap等多行专属方法却没有masked掩码、line_number行号等能力反过来InputState无法调用auto_grow——用错模式会在编译期报错而不是运行期断言。代码编辑器概念语言、诊断、折叠、LSP 等被有意隔离在 EditorState 上。Textarea的结构定义也印证了这一点crates/base/src/input/textarea/mod.rs 注释写道这是共享编辑引擎的多行形态代码编辑器设施不存在于该类型上。导入方式use gpui_kit::base::input::{InputEvent, Textarea, TextareaState};TextareaState是状态实体EntityTextareaStateTextarea是轻量的渲染包装#[derive(IntoElement)]持有状态的克隆并在render时直接返回该实体见 textarea/mod.rs。2. 固定行数Fixed rows当内容需要的行数超出设定值时Textarea内部会出现滚动。创建 5 行、带占位符与默认值的示例let notes cx.new(|cx| { TextareaState::new(window, cx) .rows(5) .placeholder(Notes) .default_value(First line\nSecond line) }); Textarea::new(notes)参数说明方法作用说明rows(usize)设定固定行数默认值为 2见 state.rs 注释多行模式下生效placeholder(...)占位文本接收impl IntoSharedStringstate.rsdefault_value(...)初始文本内部走set_value路径记录在撤销历史之外光标重置到0..0多行见 state.rs从源码看rows()实际写入的是运行时布局枚举 LayoutModePlainText { tab, rows }—— 固定行数形态AutoGrow { rows, min_rows, max_rows }—— 自动增长形态CodeEditor { ... }—— 代码编辑器形态Textarea不使用。在PlainText模式下rows()直接修改行数在AutoGrow模式下调用rows()则会同时把行数与 max_rows 设为该值state.rs因此固定行数与自动增长是互斥的两种布局策略。注意rows()方法目前标有#[doc(hidden)]其运行期语义默认值 2、AutoGrow 下的行为以 state.rs 源码为准。3. 自动增长Auto-grow消息输入框是最典型的自动增长场景内容少时保持紧凑内容多时随内容变高达到上限后内部滚动。let message cx.new(|cx| { TextareaState::new(window, cx) .auto_grow(2, 8) .placeholder(Write a message) }); Textarea::new(message)auto_grow(min_rows, max_rows)的语义高度在min_rows与max_rows之间随内容增长达到max_rows后内容开始滚动而非继续撑高控件增长以包裹后的视觉行数为准见 mode.rs 的update_auto_grow其调用display_map.wrap_row_count()计算换行后的行数。LayoutMode::AutoGrow在运行期对行数做了clamp(min_rows, max_rows)约束mode.rs并有对应的单元测试验证边界行为mode.rslet mut mode LayoutMode::auto_grow(2, 5); mode.set_rows(1); // 被钳制回 min_rows 2 mode.set_rows(10); // 被钳制到 max_rows 5如果你需要运行期切换增长策略可使用set_auto_grow(min_rows, max_rows)它会把max_rows钳制为不小于min_rowsstate.rs。4. 编辑值、光标与软换行程序化插入与读取notes.update(cx, |state, cx| { state.insert(Appended text, window, cx); }); let cursor notes.read(cx).cursor_position(cx); let value notes.read(cx).value();insert(text, window, cx)在当前光标处插入文本光标移动到插入内容末尾插入被记录为原子撤销操作EditIntent::Atomic并且会临时解除disabled/readonly限制保证程序化 API 始终可写state.rs。cursor_position()返回当前光标位置Position类型state.rs。value()返回当前完整文本SharedStringstate.rs。还有配套的replace(text, window, cx)替换选中区与replace_all(...)整体替换但保留撤销历史适合格式化场景state.rs。软换行与 Enter 行为// 关闭视觉换行soft wrap超长行水平滚动 state.soft_wrap(false); // 让 Enter 提交而不是插入换行ShiftEnter 仍然插入换行 state.submit_on_enter(true);soft_wrap(wrap: bool)与set_soft_wrap(...)默认开启视觉换行new_in_mode中soft_wrap: true见 state.rs。关闭时display_map以无换行宽度重新布局并把水平滚动归零state.rs。submit_on_enter(submit: bool)与set_submit_on_enter(...)默认false此时Enter 与 ShiftEnter 都插入换行设为true后 Enter 触发提交事件、ShiftEnter 插入换行state.rs。事件机制TextareaState与InputState发出相同的InputEvent变体state.rspub enum InputEvent { Change, // 内容变化 PressEnter { secondary: bool, shift: bool }, // 按 Entersecondary 表示辅助确认键 Focus, // 获得焦点 Blur, // 失去焦点 }其中Enter动作由共享键位表绑定enter、shift-enter、secondary-enter见 state.rsPressEnter事件携带修饰键信息供Enter 提交场景判断是否由 Shift 键触发换行。5. 呈现Presentation无样式由设计系统提供外观Textarea是无样式控件unstyled。它只负责文本编辑不绘制边框、背景、内边距与配色。你的设计系统需要负责提供控件外框frame与高度颜色与内边距供渲染使用的InputEditorStyle在每次渲染时由调色板解析重建保证主题切换后即时生效见 state.rs。仓库中的 showcase 示例演示了典型的包裹方式——用InputBase作为呈现层再在其中放入Textarea并自绘边框、焦点样式crates/base/examples/showcase/components/textarea.rsInputBase::new(example-textarea) .w_full() .h_16() .px_2() .py_2() .border_1() .border_color(example_rgb(0xd4d4d4)) .styles(|styles| { styles.focused(|style| style.border_color(example_rgb(0x171717))) }) .child(div().size_full().child(Textarea::new(self.textarea)))需要开箱即用的带样式多行输入框时请使用组件库中的gpui-componentTextarea见 website/component/textarea.md。6. 可运行示例仓库在gpui-base-examples中提供了 textarea 的可运行展示cargo run -p gpui-base-examples -- textarea该展示位于 crates/base/examples/showcase你可以对照运行效果阅读本节各 API 的行为。相关测试与更多输入体系文档可继续阅读编辑引擎与模式标记crates/base/src/input/base/kind.rs布局模式与自动增长钳制crates/base/src/input/base/mode.rs共享状态与全部构建器方法crates/base/src/input/base/state.rs单行输入对照website/base/primitives/input.md代码编辑器对照website/base/primitives/editor.md小结Textarea/TextareaState为 GPUI 应用提供了一个聚焦、可组合的多行文本录入基础件布局策略固定行数或自动增长由LayoutMode承载能力边界由TextareaMode类型标记在编译期锁死值操作插入、替换、读取、光标全部走共享编辑引擎并纳入撤销体系。掌握它之后你既能快速搭建备注、留言等基础表单也能在此基础上构建自己的样式与交互而无需触碰代码编辑器那套重型设施。【免费下载链接】gpui-kitRust GUI components for building fantastic cross-platform desktop application by using GPUI.项目地址: https://gitcode.com/GitHub_Trending/gp/gpui-kit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考