From 7c1658a24a14ff981740fd28b71b8f4bdb504ebe Mon Sep 17 00:00:00 2001 From: temportalflux Date: Sat, 20 Jun 2026 14:39:04 -0400 Subject: [PATCH] add empty render for element --- .../src/editable_text/input_element.rs | 137 +++++++++++++++++- .../src/editable_text/input_state.rs | 9 +- .../src/editable_text/shared_state.rs | 6 +- 3 files changed, 145 insertions(+), 7 deletions(-) diff --git a/crates/gpui_elements/src/editable_text/input_element.rs b/crates/gpui_elements/src/editable_text/input_element.rs index 4800e2c35b..483ee4b871 100644 --- a/crates/gpui_elements/src/editable_text/input_element.rs +++ b/crates/gpui_elements/src/editable_text/input_element.rs @@ -1,3 +1,136 @@ -use gpui::ElementId; +use gpui::{ + App, Element, ElementId, Entity, Hitbox, InteractiveElement, Interactivity, IntoElement, + Length, SharedString, StyleRefinement, Styled, TextStyle, +}; -pub fn input(id: impl Into) {} +use crate::editable_text::{TextInputState, UnicodeTextStorage}; + +#[track_caller] +pub fn input(id: impl Into) -> TextInputElement { + let mut this = TextInputElement { + id: id.into(), + placeholder: None, + interactivity: Interactivity::new(), + init_storage: None, + }; + this = this.key_context(super::DEFAULT_INPUT_CONTEXT); + this +} + +// TODO: Disabled flag/state? +pub struct TextInputElement { + id: ElementId, + placeholder: Option, + interactivity: Interactivity, + init_storage: Option Box>>, +} + +impl InteractiveElement for TextInputElement { + fn interactivity(&mut self) -> &mut Interactivity { + &mut self.interactivity + } +} + +impl Styled for TextInputElement { + fn style(&mut self) -> &mut StyleRefinement { + &mut self.interactivity.base_style + } +} + +impl IntoElement for TextInputElement { + type Element = Self; + fn into_element(self) -> Self::Element { + self + } +} + +#[doc(hidden)] +pub struct LayoutState { + state: Entity, + text_style: TextStyle, +} + +#[doc(hidden)] +pub struct PrepaintState { + hitbox: Option, +} + +impl Element for TextInputElement { + type RequestLayoutState = LayoutState; + type PrepaintState = PrepaintState; + + fn id(&self) -> Option { + self.interactivity.element_id.clone() + } + + fn source_location(&self) -> Option<&'static std::panic::Location<'static>> { + self.interactivity.source_location() + } + + fn request_layout( + &mut self, + global_id: Option<&gpui::GlobalElementId>, + inspector_id: Option<&gpui::InspectorElementId>, + window: &mut gpui::Window, + cx: &mut gpui::App, + ) -> (gpui::LayoutId, Self::RequestLayoutState) { + let mut resolved_text_style = None; + + // Get the state from the app using the element's id as the key. + // If it doesnt exist, initialize a new state with the user's desired storage medium. + let state = window.use_keyed_state(self.id.clone(), cx, |_window, cx| { + let storage = match &self.init_storage { + None => Box::new(String::new()), + Some(init_storage) => (*init_storage)(cx), + }; + TextInputState::new(storage, cx) + }); + + let layout_id = self.interactivity.request_layout( + global_id, + inspector_id, + window, + cx, + |element_style, window, cx| { + window.with_text_style(element_style.text_style().cloned(), |window| { + resolved_text_style = Some(window.text_style()); + + let style = element_style.clone(); + // TODO: Does this need to propagate the line_height as the element's height? + window.request_layout(style, None, cx) + }) + }, + ); + + let layout_state = LayoutState { + state, + text_style: resolved_text_style.unwrap_or_else(|| window.text_style()), + }; + (layout_id, layout_state) + } + + fn prepaint( + &mut self, + id: Option<&gpui::GlobalElementId>, + inspector_id: Option<&gpui::InspectorElementId>, + bounds: gpui::Bounds, + request_layout: &mut Self::RequestLayoutState, + window: &mut gpui::Window, + cx: &mut gpui::App, + ) -> Self::PrepaintState { + todo!() + } + + fn paint( + &mut self, + id: Option<&gpui::GlobalElementId>, + inspector_id: Option<&gpui::InspectorElementId>, + bounds: gpui::Bounds, + request_layout: &mut Self::RequestLayoutState, + prepaint: &mut Self::PrepaintState, + window: &mut gpui::Window, + cx: &mut gpui::App, + ) { + todo!() + } +} diff --git a/crates/gpui_elements/src/editable_text/input_state.rs b/crates/gpui_elements/src/editable_text/input_state.rs index 2baceab4a0..d5c784172e 100644 --- a/crates/gpui_elements/src/editable_text/input_state.rs +++ b/crates/gpui_elements/src/editable_text/input_state.rs @@ -1,7 +1,7 @@ use super::notify::TextHistoryPushed; use crate::editable_text::{ EditableTextActionHandler, TextBoundary, TextInputStateBase, TextStateNotifier, - notify::TextChanged, + UnicodeTextStorage, notify::TextChanged, }; use gpui::{ Bounds, Context, EntityInputHandler, EventEmitter, NavigationDirection, Pixels, Point, @@ -16,6 +16,13 @@ pub struct TextInputState { impl EventEmitter for TextInputState {} impl EventEmitter for TextInputState {} +impl TextInputState { + pub fn new(storage: impl Into>, cx: &mut Context) -> Self { + let internal = TextInputStateBase::new(storage, cx); + Self { internal } + } +} + impl TextStateNotifier for Context<'_, TextInputState> { fn notify_changed(&mut self) { self.notify(); diff --git a/crates/gpui_elements/src/editable_text/shared_state.rs b/crates/gpui_elements/src/editable_text/shared_state.rs index b40428d140..bc1c87b549 100644 --- a/crates/gpui_elements/src/editable_text/shared_state.rs +++ b/crates/gpui_elements/src/editable_text/shared_state.rs @@ -3,8 +3,8 @@ use crate::editable_text::{ notify::{TextChanged, TextHistoryPushed}, }; use gpui::{ - App, AppContext, ClipboardItem, FocusHandle, Focusable, NavigationDirection, Pixels, Point, - UTF16Selection, Window, + App, ClipboardItem, FocusHandle, Focusable, NavigationDirection, Pixels, Point, UTF16Selection, + Window, }; use std::ops::Range; @@ -45,8 +45,6 @@ impl Focusable for TextInputStateBase { } impl TextInputStateBase { - /// Creates a new `Input` with the specified multiline setting. - /// Cursor blinking is enabled by default. pub fn new(storage: impl Into>, cx: &mut App) -> Self { Self { storage: storage.into(),