//! 绘制宿主设置页面和主题选择区域。 //! 这里只投影当前设置和交互目标,平台原生窗口行为由对应系统适配层负责。 //! use super::*; /// 绘制强调色候选、自定义颜色编辑框及主题预览;实际应用和错误校验由输入动作处理。 pub(super) fn build(p: &mut Painter, state: &mut DeveloperToolsState, viewport: Rect) { let x = viewport.x; let w = viewport.width; p.label(x + 24.0, 62.0, "Appearance", TEXT, false); p.label( x + 24.0, 90.0, "Accent color · tabs, focus and execution separators", MUTED, false, ); // 色块动作携带调色板索引,绘制仅比较当前 accent 标记选中;实际修改由统一动作处理器执行。 for (i, color) in PALETTE.iter().enumerate() { let r = Rect::new(x + 24.0 + i as f32 * 44.0, 122.0, 32.0, 32.0); p.ui.swatch(r, Action::Theme(i), *color, *color == state.accent); } p.label( x + 24.0, 176.0, "Custom hex · Enter to apply (bright colors adjusted)", MUTED, false, ); // 自定义颜色框显示尚未应用的编辑文本;聚焦只改变外观和输入接收位置,不在这里解析 hex。 let custom = Rect::new(x + 24.0, 204.0, 200.0, 32.0); p.ui.text_field( custom, Action::Focus(Focus::Custom), state.focus == Some(Focus::Custom), ); p.label( custom.x + 10.0, custom.y + 6.0, &format!( "{}{}", state.custom, if state.focus == Some(Focus::Custom) { "│" } else { "" } ), TEXT, true, ); // 校验错误由输入处理路径写入,设置页只显示;错误不会在每次重绘时重复执行或清除。 if !state.input_error.is_empty() { p.label(x + 24.0, 245.0, &state.input_error, ERROR, false); } p.fill(Rect::new(x + 24.0, 285.0, w - 48.0, 1.0), BORDER); p.label(x + 24.0, 305.0, "Theme preview", TEXT, false); // 预览复用当前强调色和标准成功色,让用户看到主题如何影响执行分隔线;示例文字不送入 VM。 p.fill(Rect::new(x + 24.0, 340.0, w - 48.0, 2.0), state.accent); p.label(x + 32.0, 353.0, "› \"Hello\"", TEXT, true); p.label(x + 32.0, 380.0, "‹ \"Hello\"", OK, true); p.label( x + 24.0, 430.0, "Settings last for this window session. Source is not persisted.", MUTED, false, ); }