stub out <textarea> element
This commit is contained in:
@@ -1,11 +1,10 @@
|
||||
use crate::editable_text::{
|
||||
EditableInputActionElement, StateBackedElement, TextInputState, UnicodeTextStorage,
|
||||
EditableInputActionElement, InitStorage, StateBackedElement, TextInputState,
|
||||
};
|
||||
use gpui::{
|
||||
App, Element, ElementId, Entity, Hitbox, InteractiveElement, Interactivity, IntoElement,
|
||||
SharedString, StyleRefinement, Styled, TextStyle, Window,
|
||||
};
|
||||
use std::rc::Rc;
|
||||
|
||||
#[track_caller]
|
||||
pub fn input(id: impl Into<ElementId>) -> TextInputElement {
|
||||
@@ -47,17 +46,6 @@ impl IntoElement for TextInputElement {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub(super) struct InitStorage(Option<Rc<dyn Fn(&mut App) -> Box<dyn UnicodeTextStorage>>>);
|
||||
impl InitStorage {
|
||||
fn exec(&self, cx: &mut App) -> Box<dyn UnicodeTextStorage> {
|
||||
match &self.0 {
|
||||
None => Box::new(String::new()),
|
||||
Some(init) => (*init)(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EditableInputActionElement for TextInputElement {}
|
||||
impl super::StateBackedElement for TextInputElement {
|
||||
type State = TextInputState;
|
||||
@@ -80,20 +68,24 @@ impl super::StateBackedElement for TextInputElement {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct LayoutState {
|
||||
state: Entity<TextInputState>,
|
||||
text_style: TextStyle,
|
||||
}
|
||||
pub mod element {
|
||||
use super::*;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct PrepaintState {
|
||||
hitbox: Option<Hitbox>,
|
||||
#[doc(hidden)]
|
||||
pub struct LayoutState {
|
||||
pub state: Entity<TextInputState>,
|
||||
pub text_style: TextStyle,
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct PrepaintState {
|
||||
pub hitbox: Option<Hitbox>,
|
||||
}
|
||||
}
|
||||
|
||||
impl Element for TextInputElement {
|
||||
type RequestLayoutState = LayoutState;
|
||||
type PrepaintState = PrepaintState;
|
||||
type RequestLayoutState = element::LayoutState;
|
||||
type PrepaintState = element::PrepaintState;
|
||||
|
||||
fn id(&self) -> Option<ElementId> {
|
||||
self.interactivity.element_id.clone()
|
||||
@@ -130,7 +122,7 @@ impl Element for TextInputElement {
|
||||
},
|
||||
);
|
||||
|
||||
let layout_state = LayoutState {
|
||||
let layout_state = element::LayoutState {
|
||||
state,
|
||||
text_style: resolved_text_style.unwrap_or_else(|| window.text_style()),
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use gpui::NavigationDirection;
|
||||
use std::ops::Range;
|
||||
use gpui::{App, NavigationDirection};
|
||||
use std::{ops::Range, rc::Rc};
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
|
||||
pub enum TextBoundary {
|
||||
@@ -13,6 +13,17 @@ pub enum TextBoundary {
|
||||
Document,
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub(super) struct InitStorage(Option<Rc<dyn Fn(&mut App) -> Box<dyn UnicodeTextStorage>>>);
|
||||
impl InitStorage {
|
||||
pub fn exec(&self, cx: &mut App) -> Box<dyn UnicodeTextStorage> {
|
||||
match &self.0 {
|
||||
None => Box::new(String::new()),
|
||||
Some(init) => (*init)(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait UnicodeTextStorage {
|
||||
/// Returns a reference to the utf8 string.
|
||||
fn content_utf8(&self) -> &str;
|
||||
|
||||
@@ -1,3 +1,160 @@
|
||||
use gpui::ElementId;
|
||||
use crate::editable_text::{
|
||||
EditableInputActionElement, InitStorage, StateBackedElement, TextAreaState,
|
||||
};
|
||||
use gpui::{
|
||||
App, Element, ElementId, Entity, Hitbox, InteractiveElement, Interactivity, IntoElement,
|
||||
SharedString, StyleRefinement, Styled, TextStyle, Window,
|
||||
};
|
||||
|
||||
pub fn text_area(id: impl Into<ElementId>) {}
|
||||
pub fn text_area(id: impl Into<ElementId>) -> TextAreaElement {
|
||||
let mut this = TextAreaElement {
|
||||
id: id.into(),
|
||||
placeholder: None,
|
||||
interactivity: Interactivity::new(),
|
||||
init_storage: InitStorage::default(),
|
||||
};
|
||||
this = this.key_context(super::DEFAULT_INPUT_CONTEXT);
|
||||
this.register_actions();
|
||||
this
|
||||
}
|
||||
|
||||
// TODO: Disabled flag/state?
|
||||
pub struct TextAreaElement {
|
||||
id: ElementId,
|
||||
placeholder: Option<SharedString>,
|
||||
interactivity: Interactivity,
|
||||
init_storage: InitStorage,
|
||||
}
|
||||
|
||||
impl InteractiveElement for TextAreaElement {
|
||||
fn interactivity(&mut self) -> &mut Interactivity {
|
||||
&mut self.interactivity
|
||||
}
|
||||
}
|
||||
|
||||
impl Styled for TextAreaElement {
|
||||
fn style(&mut self) -> &mut StyleRefinement {
|
||||
&mut self.interactivity.base_style
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoElement for TextAreaElement {
|
||||
type Element = Self;
|
||||
fn into_element(self) -> Self::Element {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl EditableInputActionElement for TextAreaElement {}
|
||||
impl super::StateBackedElement for TextAreaElement {
|
||||
type State = TextAreaState;
|
||||
type InitProps = (ElementId, InitStorage);
|
||||
|
||||
fn init_props(&self) -> Self::InitProps {
|
||||
(self.id.clone(), self.init_storage.clone())
|
||||
}
|
||||
|
||||
fn get_or_init_state(
|
||||
init_props: &Self::InitProps,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) -> Entity<Self::State> {
|
||||
// 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.
|
||||
window.use_keyed_state(init_props.0.clone(), cx, |_window, cx| {
|
||||
TextAreaState::new(init_props.1.exec(cx), cx)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub mod element {
|
||||
use super::*;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct LayoutState {
|
||||
pub state: Entity<TextAreaState>,
|
||||
pub text_style: TextStyle,
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub struct PrepaintState {
|
||||
pub hitbox: Option<Hitbox>,
|
||||
}
|
||||
}
|
||||
|
||||
impl Element for TextAreaElement {
|
||||
type RequestLayoutState = element::LayoutState;
|
||||
type PrepaintState = element::PrepaintState;
|
||||
|
||||
fn id(&self) -> Option<ElementId> {
|
||||
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;
|
||||
|
||||
let state = self.get_state(window, 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 mut style = element_style.clone();
|
||||
if let gpui::Length::Auto = style.size.width {
|
||||
style.size.width = gpui::relative(1.).into();
|
||||
}
|
||||
if let gpui::Length::Auto = style.size.height {
|
||||
style.size.height = gpui::relative(1.).into();
|
||||
}
|
||||
window.request_layout(style, None, cx)
|
||||
})
|
||||
},
|
||||
);
|
||||
|
||||
let layout_state = element::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<gpui::Pixels>,
|
||||
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<gpui::Pixels>,
|
||||
request_layout: &mut Self::RequestLayoutState,
|
||||
prepaint: &mut Self::PrepaintState,
|
||||
window: &mut gpui::Window,
|
||||
cx: &mut gpui::App,
|
||||
) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::editable_text::{
|
||||
EditableTextActionHandler, TextBoundary, TextInputStateBase, TextStateNotifier,
|
||||
UnicodeTextStorage,
|
||||
notify::{TextChanged, TextHistoryPushed},
|
||||
};
|
||||
use gpui::{
|
||||
@@ -15,6 +16,13 @@ pub struct TextAreaState {
|
||||
impl EventEmitter<TextChanged> for TextAreaState {}
|
||||
impl EventEmitter<TextHistoryPushed> for TextAreaState {}
|
||||
|
||||
impl TextAreaState {
|
||||
pub fn new(storage: impl Into<Box<dyn UnicodeTextStorage>>, cx: &mut Context<Self>) -> Self {
|
||||
let internal = TextInputStateBase::new(storage, cx);
|
||||
Self { internal }
|
||||
}
|
||||
}
|
||||
|
||||
impl TextStateNotifier for Context<'_, TextAreaState> {
|
||||
fn notify_changed(&mut self) {
|
||||
self.notify();
|
||||
|
||||
Reference in New Issue
Block a user