From ddef8360cbaebe06065c63a5a1893173f0a5f35e Mon Sep 17 00:00:00 2001 From: Kayshen-X Date: Sat, 20 Jun 2026 21:57:02 +0800 Subject: [PATCH] refactor(variables): render search box via unified TextInputView MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a general paint_text_input_view helper (placeholder + focused params; paint_text_input_view_value now delegates to it) and route the variables search/filter box through it instead of a hand-rolled draw_text + manual fill_rect caret. The search_input TextInputState was already rebuilt each frame, so this is render-only — the caret now uses the family-aware measure (no drift) and shares one implementation. --- .../src/widgets/property_panel_text_input.rs | 38 +++++++++++++- .../src/widgets/variables_panel/paint.rs | 52 ++++++------------- 2 files changed, 53 insertions(+), 37 deletions(-) diff --git a/crates/op-editor-ui/src/widgets/property_panel_text_input.rs b/crates/op-editor-ui/src/widgets/property_panel_text_input.rs index a7d85ad9c..d7572c015 100644 --- a/crates/op-editor-ui/src/widgets/property_panel_text_input.rs +++ b/crates/op-editor-ui/src/widgets/property_panel_text_input.rs @@ -16,12 +16,46 @@ pub(crate) fn paint_text_input_view_value( pad_x: f32, text_baseline_y: f32, now_ms: u64, +) { + // The "_value" variant always reads as focused with no placeholder — it + // backs property-panel fields that only render while focused. + paint_text_input_view( + cx, + theme, + input, + rect, + font_size, + pad_x, + text_baseline_y, + now_ms, + "", + true, + ); +} + +/// Render a `TextInputView` for `input` inside `rect`, baselining the run at +/// `text_baseline_y`. Unlike `_value`, this exposes `placeholder` (drawn muted +/// when the buffer is empty) and `focused` (caret blinks only when true) — so +/// it serves search / filter boxes that must look right whether or not they +/// hold focus, on one unified caret implementation. +#[allow(clippy::too_many_arguments)] +pub(crate) fn paint_text_input_view( + cx: &mut PaintCx<'_>, + theme: &Theme, + input: &TextInputState, + rect: Rect, + font_size: f32, + pad_x: f32, + text_baseline_y: f32, + now_ms: u64, + placeholder: &str, + focused: bool, ) { let resolved_pad_x = if pad_x <= 0.0 { f32::EPSILON } else { pad_x }; let view = TextInputView { state: input, - placeholder: "", - focused: true, + placeholder, + focused, font_size, now_ms, pad_x: resolved_pad_x, diff --git a/crates/op-editor-ui/src/widgets/variables_panel/paint.rs b/crates/op-editor-ui/src/widgets/variables_panel/paint.rs index c7614f9a6..ef167d8d8 100644 --- a/crates/op-editor-ui/src/widgets/variables_panel/paint.rs +++ b/crates/op-editor-ui/src/widgets/variables_panel/paint.rs @@ -1,6 +1,6 @@ use super::*; use crate::widgets::button::paint_button_feedback_wash; -use crate::widgets::property_panel_text_input::paint_text_input_view_value; +use crate::widgets::property_panel_text_input::{paint_text_input_view, paint_text_input_view_value}; use crate::widgets::{draw_icon, Icon, PaintCx}; use crate::{Color, Point2D, Rect}; @@ -83,40 +83,22 @@ fn paint_search_row( ); let text_x = input.origin.x + 8.0 + icon_size + 7.0; let baseline_y = input.origin.y + input.size.y / 2.0 + 4.0; - if panel.search.is_empty() { - paint_text( - cx, - labels.search_placeholder, - 12.0, - theme.muted_foreground, - text_x, - baseline_y, - ); - } else { - paint_text( - cx, - &panel.search, - 12.0, - theme.foreground, - text_x, - baseline_y, - ); - } - if panel.search_focus && panel.search_input.caret_visible(panel.now_ms) { - let caret_x = text_x - + if panel.search.is_empty() { - 0.0 - } else { - cx.backend.measure_text(&panel.search, 12.0) - }; - cx.backend.fill_rect( - Rect { - origin: Point2D::new(caret_x + 1.0, input.origin.y + 5.0), - size: Point2D::new(1.5, 18.0), - }, - theme.foreground, - ); - } + // Value + placeholder + caret render through the unified jian TextInputView + // (family-aware caret, no hand-rolled drift). `search_input` is rebuilt from + // `panel.search` each frame (variables_panel::for_editor_at), so the caret + // sits at end-of-text and blinks off the keystroke timestamp. + paint_text_input_view( + cx, + &theme, + &panel.search_input, + input, + 12.0, + text_x - input.origin.x, + baseline_y, + panel.now_ms, + labels.search_placeholder, + panel.search_focus, + ); paint_hairline( cx, rect.origin.x,