diff --git a/crates/gpui_elements/src/editable_text.rs b/crates/gpui_elements/src/editable_text.rs index 91e68f372b..4664fa4f2f 100644 --- a/crates/gpui_elements/src/editable_text.rs +++ b/crates/gpui_elements/src/editable_text.rs @@ -1,4 +1,4 @@ -mod actions; +pub mod actions; mod input_element; mod input_state; pub mod notify; @@ -7,7 +7,6 @@ mod storage; mod text_area_element; mod text_area_state; -pub use actions::*; pub use input_element::*; pub use input_state::*; pub use shared_state::*; diff --git a/crates/gpui_elements/src/editable_text/actions.rs b/crates/gpui_elements/src/editable_text/actions.rs index 9b11909925..42f15753cb 100644 --- a/crates/gpui_elements/src/editable_text/actions.rs +++ b/crates/gpui_elements/src/editable_text/actions.rs @@ -1,4 +1,4 @@ -use gpui::{Action, App, AppContext, Context, InteractiveElement, Window}; +use gpui::{Action, AppContext, Context, InteractiveElement, Window}; /// The key context used for input element keybindings. pub const DEFAULT_INPUT_CONTEXT: &str = "Input"; @@ -234,7 +234,7 @@ pub trait EditableTextActionHandler<'app>: Sized { } } -pub trait EditableInputActionElement: super::StateBackedElement { +pub(super) trait EditableInputActionElement: super::StateBackedElement { fn register_action( &mut self, init_props: Self::InitProps, diff --git a/crates/gpui_elements/src/editable_text/input_element.rs b/crates/gpui_elements/src/editable_text/input_element.rs index b9ecb5a2ad..a8a55e37cd 100644 --- a/crates/gpui_elements/src/editable_text/input_element.rs +++ b/crates/gpui_elements/src/editable_text/input_element.rs @@ -1,18 +1,17 @@ -use std::{ops::Range, sync::Arc}; - use crate::editable_text::{ - EditableInputActionElement, EditableTextActionHandler, InitStorage, StateBackedElement, - TextInputLayoutData, TextInputState, TextLayoutWrapping, TextLineSegment, + InitStorage, StateBackedElement, TextInputState, TextInputStateBase, TextLayoutWrapping, + TextLineSegment, + actions::{DEFAULT_INPUT_CONTEXT, EditableInputActionElement}, }; use gpui::{ Along, App, Axis, Bounds, ContentMask, CursorStyle, DispatchPhase, Display, Element, ElementId, ElementInputHandler, Entity, FocusHandle, Focusable, Hitbox, HitboxBehavior, Hsla, InteractiveElement, Interactivity, IntoElement, MouseButton, MouseDownEvent, MouseMoveEvent, - MouseUpEvent, PaintQuad, Pixels, Point, ScrollWheelEvent, ShapedLine, SharedString, Style, - StyleRefinement, Styled, TextAlign, TextRun, TextStyle, Window, WrappedLine, fill, point, px, - size, + MouseUpEvent, PaintQuad, Pixels, Point, ScrollWheelEvent, SharedString, Style, StyleRefinement, + Styled, TextAlign, TextStyle, Window, WrappedLine, fill, point, px, size, }; use smallvec::SmallVec; +use std::{ops::Range, sync::Arc}; #[track_caller] pub fn input(id: impl Into) -> TextInputElement { @@ -22,7 +21,7 @@ pub fn input(id: impl Into) -> TextInputElement { interactivity: Interactivity::new(), init_storage: InitStorage::default(), }; - this = this.key_context(super::DEFAULT_INPUT_CONTEXT); + this = this.key_context(DEFAULT_INPUT_CONTEXT); this.register_actions(); this } @@ -174,25 +173,60 @@ impl Element for TextInputElement { window: &mut gpui::Window, cx: &mut gpui::App, ) -> Self::PrepaintState { + struct InteractivityPrepaint { + hitbox: Option, + scroll_offset: Point, + } + // TODO: how do we enable scrolling? overflow on interactivity? + let prepaint = self.interactivity.prepaint( + global_id, + inspector_id, + bounds, + bounds.size, + window, + cx, + |_style, scroll_offset, hitbox, window, _cx| { + let hitbox = + hitbox.or_else(|| Some(window.insert_hitbox(bounds, HitboxBehavior::Normal))); + InteractivityPrepaint { + hitbox, + scroll_offset, + } + }, + ); + let InteractivityPrepaint { + hitbox, + scroll_offset, + } = prepaint; + + let text_color = request_layout.text_style.color; + let placeholder_color = Hsla::black().opacity(0.5); // TODO: as an element param + let selection_color = Hsla::blue().opacity(0.5); // TODO: as an element param + let caret_color = Hsla::white(); // TODO: as an element param + // TODO: no wrapping in single-line let wrap_width = Some(bounds.size.width); - let wrapping = TextLayoutWrapping::new(request_layout.text_style.clone(), wrap_width); let showing_placeholder = request_layout.state.update(cx, |state, _cx| { - let text_value = state.storage().content_utf8(); - let is_empty = text_value.is_empty(); - let display_text = match is_empty { - false => text_value, - true => self - .placeholder - .as_ref() - .map(SharedString::as_str) - .unwrap_or_default(), - }; - - state.layout_data_mut().bounds = bounds; - state.apply_wrapping(wrapping, display_text, window); - is_empty + let show_placeholder = state.storage().content_utf8().is_empty(); + state.layout_data.bounds = bounds; + if state.layout_wrapping.integrate(wrapping) { + let (display_text, color) = match show_placeholder { + false => (state.storage().content_utf8(), text_color), + true => { + let value = self.placeholder.as_ref(); + let value = value.map(SharedString::as_str).unwrap_or_default(); + (value, placeholder_color) + } + }; + state.layout_data.lines = TextInputStateBase::build_wrapped_lines( + display_text, + &state.layout_wrapping, + window, + color, + ); + } + show_placeholder }); let input = request_layout.state.read(cx); @@ -204,28 +238,8 @@ impl Element for TextInputElement { // TODO: Cursor blinking let cursor_visible = true; // input.cursor_visible(); - let text_color = Hsla::white(); // TODO: as an element param - let placeholder_color = Hsla::black().opacity(0.5); // TODO: as an element param - let selection_color = Hsla::blue().opacity(0.5); // TODO: as an element param - let caret_color = Hsla::white(); // TODO: as an element param - let mut elements = SmallVec::new(); - // TODO: how do we enable scrolling? overflow on interactivity? - let (hitbox, scroll_offset) = self.interactivity.prepaint( - global_id, - inspector_id, - bounds, - bounds.size, - window, - cx, - |_style, scroll_offset, hitbox, window, _cx| { - let hitbox = - hitbox.or_else(|| Some(window.insert_hitbox(bounds, HitboxBehavior::Normal))); - (hitbox, scroll_offset) - }, - ); - let line_height = window.line_height(); let is_range_contained_by_range = |text_range: &Range, containing_range: &Range| { @@ -369,6 +383,7 @@ impl Element for TextInputElement { let ime_handler = ElementInputHandler::new(bounds, request_layout.state.clone()); window.handle_input(&prepaint.focus_handle, ime_handler, cx); + use super::actions::EditableTextActionHandler; let get_relative_position = { let bounds = bounds.clone(); move |position: Point| { diff --git a/crates/gpui_elements/src/editable_text/input_state.rs b/crates/gpui_elements/src/editable_text/input_state.rs index 790a2307a0..531e569324 100644 --- a/crates/gpui_elements/src/editable_text/input_state.rs +++ b/crates/gpui_elements/src/editable_text/input_state.rs @@ -1,7 +1,6 @@ use super::notify::TextHistoryPushed; use crate::editable_text::{ - EditableTextActionHandler, TextBoundary, TextInputStateBase, TextStateNotifier, - UnicodeTextStorage, notify::TextChanged, + TextBoundary, TextInputStateBase, TextStateNotifier, UnicodeTextStorage, notify::TextChanged, }; use gpui::{ Bounds, Context, EntityInputHandler, EventEmitter, NavigationDirection, Pixels, Point, @@ -142,55 +141,46 @@ impl EntityInputHandler for TextInputState { } } +use super::actions::*; impl<'app> EditableTextActionHandler<'app> for TextInputState { type Context = gpui::Context<'app, Self>; - fn escape(&mut self, _: &super::Escape, window: &mut Window, cx: &mut Self::Context) { + fn escape(&mut self, _: &Escape, window: &mut Window, cx: &mut Self::Context) { self.internal.set_selected_range(0..0); cx.notify(); window.blur(); } - fn insert_enter(&mut self, _: &super::Enter, _w: &mut Window, _cx: &mut Self::Context) {} + fn insert_enter(&mut self, _: &Enter, _w: &mut Window, _cx: &mut Self::Context) {} - fn insert_tab(&mut self, _: &super::Tab, window: &mut Window, cx: &mut Self::Context) { + fn insert_tab(&mut self, _: &Tab, window: &mut Window, cx: &mut Self::Context) { self.replace_text_in_range(None, "\t", window, cx); } - fn backspace(&mut self, _: &super::Backspace, _: &mut Window, cx: &mut Self::Context) { + fn backspace(&mut self, _: &Backspace, _: &mut Window, cx: &mut Self::Context) { self.internal .delete(NavigationDirection::Back, TextBoundary::Graphmeme, cx); } - fn delete(&mut self, _: &super::Delete, _w: &mut Window, cx: &mut Self::Context) { + fn delete(&mut self, _: &Delete, _w: &mut Window, cx: &mut Self::Context) { self.internal .delete(NavigationDirection::Forward, TextBoundary::Graphmeme, cx); } - fn delete_word_left( - &mut self, - _: &super::DeleteWordLeft, - _w: &mut Window, - cx: &mut Self::Context, - ) { + fn delete_word_left(&mut self, _: &DeleteWordLeft, _w: &mut Window, cx: &mut Self::Context) { self.internal .delete(NavigationDirection::Back, TextBoundary::Word, cx); } - fn delete_word_right( - &mut self, - _: &super::DeleteWordRight, - _w: &mut Window, - cx: &mut Self::Context, - ) { + fn delete_word_right(&mut self, _: &DeleteWordRight, _w: &mut Window, cx: &mut Self::Context) { self.internal .delete(NavigationDirection::Forward, TextBoundary::Word, cx); } fn delete_to_line_start( &mut self, - _: &super::DeleteToBeginningOfLine, + _: &DeleteToBeginningOfLine, _w: &mut Window, cx: &mut Self::Context, ) { @@ -200,7 +190,7 @@ impl<'app> EditableTextActionHandler<'app> for TextInputState { fn delete_to_line_end( &mut self, - _: &super::DeleteToEndOfLine, + _: &DeleteToEndOfLine, _w: &mut Window, cx: &mut Self::Context, ) { @@ -208,138 +198,123 @@ impl<'app> EditableTextActionHandler<'app> for TextInputState { .delete(NavigationDirection::Forward, TextBoundary::Line, cx); } - fn nav_left(&mut self, _: &super::Left, _w: &mut Window, cx: &mut Self::Context) { + fn nav_left(&mut self, _: &Left, _w: &mut Window, cx: &mut Self::Context) { self.internal .nav_linear(NavigationDirection::Back, TextBoundary::Graphmeme, cx); } - fn nav_right(&mut self, _: &super::Right, _w: &mut Window, cx: &mut Self::Context) { + fn nav_right(&mut self, _: &Right, _w: &mut Window, cx: &mut Self::Context) { self.internal .nav_linear(NavigationDirection::Forward, TextBoundary::Graphmeme, cx); } - fn nav_up(&mut self, _: &super::Up, _w: &mut Window, cx: &mut Self::Context) { + fn nav_up(&mut self, _: &Up, _w: &mut Window, cx: &mut Self::Context) { // semantically equivalent to line self.internal .nav_linear(NavigationDirection::Back, TextBoundary::Line, cx); } - fn nav_down(&mut self, _: &super::Down, _w: &mut Window, cx: &mut Self::Context) { + fn nav_down(&mut self, _: &Down, _w: &mut Window, cx: &mut Self::Context) { // semantically equivalent to line self.internal .nav_linear(NavigationDirection::Forward, TextBoundary::Line, cx); } - fn nav_line_start(&mut self, _: &super::Home, _w: &mut Window, cx: &mut Self::Context) { + fn nav_line_start(&mut self, _: &Home, _w: &mut Window, cx: &mut Self::Context) { // semantically equivalent to document self.internal .nav_linear(NavigationDirection::Back, TextBoundary::Line, cx); } - fn nav_line_end(&mut self, _: &super::End, _w: &mut Window, cx: &mut Self::Context) { + fn nav_line_end(&mut self, _: &End, _w: &mut Window, cx: &mut Self::Context) { // semantically equivalent to document self.internal .nav_linear(NavigationDirection::Forward, TextBoundary::Line, cx); } - fn nav_start(&mut self, _: &super::MoveToBeginning, _w: &mut Window, cx: &mut Self::Context) { + fn nav_start(&mut self, _: &MoveToBeginning, _w: &mut Window, cx: &mut Self::Context) { self.internal .nav_linear(NavigationDirection::Back, TextBoundary::Document, cx); } - fn nav_end(&mut self, _: &super::MoveToEnd, _w: &mut Window, cx: &mut Self::Context) { + fn nav_end(&mut self, _: &MoveToEnd, _w: &mut Window, cx: &mut Self::Context) { self.internal .nav_linear(NavigationDirection::Forward, TextBoundary::Document, cx); } - fn nav_left_word(&mut self, _: &super::WordLeft, _w: &mut Window, cx: &mut Self::Context) { + fn nav_left_word(&mut self, _: &WordLeft, _w: &mut Window, cx: &mut Self::Context) { self.internal .nav_linear(NavigationDirection::Back, TextBoundary::Word, cx); } - fn nav_right_word(&mut self, _: &super::WordRight, _w: &mut Window, cx: &mut Self::Context) { + fn nav_right_word(&mut self, _: &WordRight, _w: &mut Window, cx: &mut Self::Context) { self.internal .nav_linear(NavigationDirection::Forward, TextBoundary::Word, cx); } - fn select_all(&mut self, _: &super::SelectAll, _w: &mut Window, cx: &mut Self::Context) { + fn select_all(&mut self, _: &SelectAll, _w: &mut Window, cx: &mut Self::Context) { self.internal.select_all(cx); } - fn select_left(&mut self, _: &super::SelectLeft, _w: &mut Window, cx: &mut Self::Context) { + fn select_left(&mut self, _: &SelectLeft, _w: &mut Window, cx: &mut Self::Context) { self.internal .select_linear(NavigationDirection::Back, TextBoundary::Graphmeme, cx); } - fn select_right(&mut self, _: &super::SelectRight, _w: &mut Window, cx: &mut Self::Context) { + fn select_right(&mut self, _: &SelectRight, _w: &mut Window, cx: &mut Self::Context) { self.internal .select_linear(NavigationDirection::Forward, TextBoundary::Graphmeme, cx); } - fn select_up(&mut self, _: &super::SelectUp, _w: &mut Window, cx: &mut Self::Context) { + fn select_up(&mut self, _: &SelectUp, _w: &mut Window, cx: &mut Self::Context) { // semantically equivalent to select document self.internal .select_linear(NavigationDirection::Back, TextBoundary::Document, cx); } - fn select_down(&mut self, _: &super::SelectDown, _w: &mut Window, cx: &mut Self::Context) { + fn select_down(&mut self, _: &SelectDown, _w: &mut Window, cx: &mut Self::Context) { // semantically equivalent to select document self.internal .select_linear(NavigationDirection::Forward, TextBoundary::Document, cx); } - fn select_start( - &mut self, - _: &super::SelectToBeginning, - _w: &mut Window, - cx: &mut Self::Context, - ) { + fn select_start(&mut self, _: &SelectToBeginning, _w: &mut Window, cx: &mut Self::Context) { self.internal .select_linear(NavigationDirection::Back, TextBoundary::Document, cx); } - fn select_end(&mut self, _: &super::SelectToEnd, _w: &mut Window, cx: &mut Self::Context) { + fn select_end(&mut self, _: &SelectToEnd, _w: &mut Window, cx: &mut Self::Context) { self.internal .select_linear(NavigationDirection::Forward, TextBoundary::Document, cx); } - fn select_left_word( - &mut self, - _: &super::SelectWordLeft, - _w: &mut Window, - cx: &mut Self::Context, - ) { + fn select_left_word(&mut self, _: &SelectWordLeft, _w: &mut Window, cx: &mut Self::Context) { self.internal .select_linear(NavigationDirection::Back, TextBoundary::Word, cx); } - fn select_right_word( - &mut self, - _: &super::SelectWordRight, - _w: &mut Window, - cx: &mut Self::Context, - ) { + fn select_right_word(&mut self, _: &SelectWordRight, _w: &mut Window, cx: &mut Self::Context) { self.internal .select_linear(NavigationDirection::Forward, TextBoundary::Word, cx); } - fn cut(&mut self, _: &super::Cut, _w: &mut Window, cx: &mut Self::Context) { + fn cut(&mut self, _: &Cut, _w: &mut Window, cx: &mut Self::Context) { self.internal.cut(cx); } - fn copy(&mut self, _: &super::Copy, _w: &mut Window, cx: &mut Self::Context) { + fn copy(&mut self, _: &Copy, _w: &mut Window, cx: &mut Self::Context) { self.internal.copy(cx); } - fn paste(&mut self, _: &super::Paste, _w: &mut Window, cx: &mut Self::Context) { + fn paste(&mut self, _: &Paste, _w: &mut Window, cx: &mut Self::Context) { self.internal.paste(cx); } - fn undo(&mut self, _: &super::Undo, _w: &mut Window, _cx: &mut Self::Context) { + fn undo(&mut self, _: &Undo, _w: &mut Window, _cx: &mut Self::Context) { // TODO: STUB } - fn redo(&mut self, _: &super::Redo, _w: &mut Window, _cx: &mut Self::Context) { + fn redo(&mut self, _: &Redo, _w: &mut Window, _cx: &mut Self::Context) { // TODO: STUB } diff --git a/crates/gpui_elements/src/editable_text/shared_state.rs b/crates/gpui_elements/src/editable_text/shared_state.rs index 2cc19175c7..865b9b5eb1 100644 --- a/crates/gpui_elements/src/editable_text/shared_state.rs +++ b/crates/gpui_elements/src/editable_text/shared_state.rs @@ -54,8 +54,8 @@ pub struct TextInputStateBase { focus_handle: FocusHandle, - layout_wrapping: TextLayoutWrapping, - layout_data: TextInputLayoutData, + pub(super) layout_wrapping: TextLayoutWrapping, + pub(super) layout_data: TextInputLayoutData, } #[derive(Default)] @@ -72,6 +72,14 @@ impl TextLayoutWrapping { dirty: false, } } + + pub fn integrate(&mut self, other: Self) -> bool { + let dirty = self.dirty + || self.wrap_width != other.wrap_width + || self.text_style != other.text_style; + *self = other; + dirty + } } #[derive(Default)] @@ -155,38 +163,20 @@ impl TextInputStateBase { pub fn marked_range(&self) -> Option> { self.marked_range.clone() } - - pub(super) fn layout_data(&self) -> &TextInputLayoutData { - &self.layout_data - } - - pub(super) fn layout_data_mut(&mut self) -> &mut TextInputLayoutData { - &mut self.layout_data - } } impl TextInputStateBase { - pub fn apply_wrapping( - &mut self, - wrapping: TextLayoutWrapping, - display_text: &str, - window: &Window, - ) { - let dirty = self.layout_wrapping.dirty - || self.layout_wrapping.wrap_width != wrapping.wrap_width - || self.layout_wrapping.text_style != wrapping.text_style; - self.layout_wrapping = wrapping; - if dirty { - self.layout_data.lines = self.build_wrapped_lines(display_text, window); - } - } - pub fn line_segments(&self) -> &Vec { &self.layout_data.lines } - fn build_wrapped_lines(&self, content: &str, window: &Window) -> Vec { - let text_style = &self.layout_wrapping.text_style; + pub fn build_wrapped_lines( + content: &str, + wrapping: &TextLayoutWrapping, + window: &Window, + color: Hsla, + ) -> Vec { + let text_style = &wrapping.text_style; let font_size = text_style.font_size.to_pixels(window.rem_size()); let mut lines = Vec::new(); @@ -223,9 +213,7 @@ impl TextInputStateBase { let run = TextRun { len: line_slice.len(), font: text_style.font(), - // TODO: This is the actual text color that is stored in WrappedLine, - // needs to reflect the style color provided by paint - color: Hsla::default(), + color, background_color: None, underline: None, strikethrough: None, @@ -237,7 +225,7 @@ impl TextInputStateBase { SharedString::from(line_slice.to_string()), font_size, &[run], - self.layout_wrapping.wrap_width, + wrapping.wrap_width, None, ) .unwrap_or_default(); diff --git a/crates/gpui_elements/src/editable_text/text_area_element.rs b/crates/gpui_elements/src/editable_text/text_area_element.rs index 02662e0bd9..b2edd4c762 100644 --- a/crates/gpui_elements/src/editable_text/text_area_element.rs +++ b/crates/gpui_elements/src/editable_text/text_area_element.rs @@ -1,5 +1,5 @@ use crate::editable_text::{ - EditableInputActionElement, InitStorage, StateBackedElement, TextAreaState, + InitStorage, StateBackedElement, TextAreaState, actions::EditableInputActionElement, }; use gpui::{ App, Element, ElementId, Entity, Hitbox, InteractiveElement, Interactivity, IntoElement, @@ -13,7 +13,7 @@ pub fn text_area(id: impl Into) -> TextAreaElement { interactivity: Interactivity::new(), init_storage: InitStorage::default(), }; - this = this.key_context(super::DEFAULT_INPUT_CONTEXT); + this = this.key_context(super::actions::DEFAULT_INPUT_CONTEXT); this.register_actions(); this } diff --git a/crates/gpui_elements/src/editable_text/text_area_state.rs b/crates/gpui_elements/src/editable_text/text_area_state.rs index e3be1e0525..3661caa312 100644 --- a/crates/gpui_elements/src/editable_text/text_area_state.rs +++ b/crates/gpui_elements/src/editable_text/text_area_state.rs @@ -1,6 +1,5 @@ use crate::editable_text::{ - EditableTextActionHandler, TextBoundary, TextInputStateBase, TextStateNotifier, - UnicodeTextStorage, + TextBoundary, TextInputStateBase, TextStateNotifier, UnicodeTextStorage, notify::{TextChanged, TextHistoryPushed}, }; use gpui::{ @@ -142,57 +141,48 @@ impl EntityInputHandler for TextAreaState { } } +use super::actions::*; impl<'app> EditableTextActionHandler<'app> for TextAreaState { type Context = gpui::Context<'app, Self>; - fn escape(&mut self, _: &super::Escape, window: &mut Window, cx: &mut Self::Context) { + fn escape(&mut self, _: &Escape, window: &mut Window, cx: &mut Self::Context) { self.internal.set_selected_range(0..0); cx.notify(); window.blur(); } - fn insert_enter(&mut self, _: &super::Enter, window: &mut Window, cx: &mut Self::Context) { + fn insert_enter(&mut self, _: &Enter, window: &mut Window, cx: &mut Self::Context) { self.replace_text_in_range(None, "\n", window, cx); } - fn insert_tab(&mut self, _: &super::Tab, window: &mut Window, cx: &mut Self::Context) { + fn insert_tab(&mut self, _: &Tab, window: &mut Window, cx: &mut Self::Context) { self.replace_text_in_range(None, "\t", window, cx); } - fn backspace(&mut self, _: &super::Backspace, _w: &mut Window, cx: &mut Self::Context) { + fn backspace(&mut self, _: &Backspace, _w: &mut Window, cx: &mut Self::Context) { self.internal .delete(NavigationDirection::Back, TextBoundary::Graphmeme, cx); } - fn delete(&mut self, _: &super::Delete, _w: &mut Window, cx: &mut Self::Context) { + fn delete(&mut self, _: &Delete, _w: &mut Window, cx: &mut Self::Context) { self.internal .delete(NavigationDirection::Forward, TextBoundary::Graphmeme, cx); } - fn delete_word_left( - &mut self, - _: &super::DeleteWordLeft, - _w: &mut Window, - cx: &mut Self::Context, - ) { + fn delete_word_left(&mut self, _: &DeleteWordLeft, _w: &mut Window, cx: &mut Self::Context) { self.internal .delete(NavigationDirection::Back, TextBoundary::Word, cx); } - fn delete_word_right( - &mut self, - _: &super::DeleteWordRight, - _w: &mut Window, - cx: &mut Self::Context, - ) { + fn delete_word_right(&mut self, _: &DeleteWordRight, _w: &mut Window, cx: &mut Self::Context) { self.internal .delete(NavigationDirection::Forward, TextBoundary::Word, cx); } fn delete_to_line_start( &mut self, - _: &super::DeleteToBeginningOfLine, + _: &DeleteToBeginningOfLine, _w: &mut Window, cx: &mut Self::Context, ) { @@ -202,7 +192,7 @@ impl<'app> EditableTextActionHandler<'app> for TextAreaState { fn delete_to_line_end( &mut self, - _: &super::DeleteToEndOfLine, + _: &DeleteToEndOfLine, _w: &mut Window, cx: &mut Self::Context, ) { @@ -210,128 +200,113 @@ impl<'app> EditableTextActionHandler<'app> for TextAreaState { .delete(NavigationDirection::Forward, TextBoundary::Line, cx); } - fn nav_left(&mut self, _: &super::Left, _w: &mut Window, cx: &mut Self::Context) { + fn nav_left(&mut self, _: &Left, _w: &mut Window, cx: &mut Self::Context) { self.internal .nav_linear(NavigationDirection::Back, TextBoundary::Graphmeme, cx); } - fn nav_right(&mut self, _: &super::Right, _w: &mut Window, cx: &mut Self::Context) { + fn nav_right(&mut self, _: &Right, _w: &mut Window, cx: &mut Self::Context) { self.internal .nav_linear(NavigationDirection::Forward, TextBoundary::Graphmeme, cx); } - fn nav_up(&mut self, _: &super::Up, _w: &mut Window, cx: &mut Self::Context) { + fn nav_up(&mut self, _: &Up, _w: &mut Window, cx: &mut Self::Context) { // TODO: implement } - fn nav_down(&mut self, _: &super::Down, _w: &mut Window, cx: &mut Self::Context) { + fn nav_down(&mut self, _: &Down, _w: &mut Window, cx: &mut Self::Context) { // TODO: implement } - fn nav_line_start(&mut self, _: &super::Home, _w: &mut Window, cx: &mut Self::Context) { + fn nav_line_start(&mut self, _: &Home, _w: &mut Window, cx: &mut Self::Context) { self.internal .nav_linear(NavigationDirection::Back, TextBoundary::Line, cx); } - fn nav_line_end(&mut self, _: &super::End, _w: &mut Window, cx: &mut Self::Context) { + fn nav_line_end(&mut self, _: &End, _w: &mut Window, cx: &mut Self::Context) { self.internal .nav_linear(NavigationDirection::Forward, TextBoundary::Line, cx); } - fn nav_start(&mut self, _: &super::MoveToBeginning, _w: &mut Window, cx: &mut Self::Context) { + fn nav_start(&mut self, _: &MoveToBeginning, _w: &mut Window, cx: &mut Self::Context) { self.internal .nav_linear(NavigationDirection::Back, TextBoundary::Document, cx); } - fn nav_end(&mut self, _: &super::MoveToEnd, _w: &mut Window, cx: &mut Self::Context) { + fn nav_end(&mut self, _: &MoveToEnd, _w: &mut Window, cx: &mut Self::Context) { self.internal .nav_linear(NavigationDirection::Forward, TextBoundary::Document, cx); } - fn nav_left_word(&mut self, _: &super::WordLeft, _w: &mut Window, cx: &mut Self::Context) { + fn nav_left_word(&mut self, _: &WordLeft, _w: &mut Window, cx: &mut Self::Context) { self.internal .nav_linear(NavigationDirection::Back, TextBoundary::Word, cx); } - fn nav_right_word(&mut self, _: &super::WordRight, _w: &mut Window, cx: &mut Self::Context) { + fn nav_right_word(&mut self, _: &WordRight, _w: &mut Window, cx: &mut Self::Context) { self.internal .nav_linear(NavigationDirection::Forward, TextBoundary::Word, cx); } - fn select_all(&mut self, _: &super::SelectAll, _w: &mut Window, cx: &mut Self::Context) { + fn select_all(&mut self, _: &SelectAll, _w: &mut Window, cx: &mut Self::Context) { self.internal.select_all(cx); } - fn select_left(&mut self, _: &super::SelectLeft, _w: &mut Window, cx: &mut Self::Context) { + fn select_left(&mut self, _: &SelectLeft, _w: &mut Window, cx: &mut Self::Context) { self.internal .select_linear(NavigationDirection::Back, TextBoundary::Graphmeme, cx); } - fn select_right(&mut self, _: &super::SelectRight, _w: &mut Window, cx: &mut Self::Context) { + fn select_right(&mut self, _: &SelectRight, _w: &mut Window, cx: &mut Self::Context) { self.internal .select_linear(NavigationDirection::Forward, TextBoundary::Graphmeme, cx); } - fn select_up(&mut self, _: &super::SelectUp, _w: &mut Window, cx: &mut Self::Context) { + fn select_up(&mut self, _: &SelectUp, _w: &mut Window, cx: &mut Self::Context) { // TODO: implement } - fn select_down(&mut self, _: &super::SelectDown, _w: &mut Window, cx: &mut Self::Context) { + fn select_down(&mut self, _: &SelectDown, _w: &mut Window, cx: &mut Self::Context) { // TODO: implement } - fn select_start( - &mut self, - _: &super::SelectToBeginning, - _w: &mut Window, - cx: &mut Self::Context, - ) { + fn select_start(&mut self, _: &SelectToBeginning, _w: &mut Window, cx: &mut Self::Context) { self.internal .select_linear(NavigationDirection::Back, TextBoundary::Document, cx); } - fn select_end(&mut self, _: &super::SelectToEnd, _w: &mut Window, cx: &mut Self::Context) { + fn select_end(&mut self, _: &SelectToEnd, _w: &mut Window, cx: &mut Self::Context) { self.internal .select_linear(NavigationDirection::Forward, TextBoundary::Document, cx); } - fn select_left_word( - &mut self, - _: &super::SelectWordLeft, - _w: &mut Window, - cx: &mut Self::Context, - ) { + fn select_left_word(&mut self, _: &SelectWordLeft, _w: &mut Window, cx: &mut Self::Context) { self.internal .select_linear(NavigationDirection::Back, TextBoundary::Word, cx); } - fn select_right_word( - &mut self, - _: &super::SelectWordRight, - _w: &mut Window, - cx: &mut Self::Context, - ) { + fn select_right_word(&mut self, _: &SelectWordRight, _w: &mut Window, cx: &mut Self::Context) { self.internal .select_linear(NavigationDirection::Forward, TextBoundary::Word, cx); } - fn cut(&mut self, _: &super::Cut, _w: &mut Window, cx: &mut Self::Context) { + fn cut(&mut self, _: &Cut, _w: &mut Window, cx: &mut Self::Context) { self.internal.cut(cx); } - fn copy(&mut self, _: &super::Copy, _w: &mut Window, cx: &mut Self::Context) { + fn copy(&mut self, _: &Copy, _w: &mut Window, cx: &mut Self::Context) { self.internal.copy(cx); } - fn paste(&mut self, _: &super::Paste, _w: &mut Window, cx: &mut Self::Context) { + fn paste(&mut self, _: &Paste, _w: &mut Window, cx: &mut Self::Context) { self.internal.paste(cx); } - fn undo(&mut self, _: &super::Undo, _w: &mut Window, _cx: &mut Self::Context) { + fn undo(&mut self, _: &Undo, _w: &mut Window, _cx: &mut Self::Context) { // TODO: STUB } - fn redo(&mut self, _: &super::Redo, _w: &mut Window, _cx: &mut Self::Context) { + fn redo(&mut self, _: &Redo, _w: &mut Window, _cx: &mut Self::Context) { // TODO: STUB } diff --git a/crates/gpui_elements/src/input.rs b/crates/gpui_elements/src/input.rs index 1a2097e106..0b1575e708 100644 --- a/crates/gpui_elements/src/input.rs +++ b/crates/gpui_elements/src/input.rs @@ -1,4 +1,3 @@ -pub mod actions; mod colors; mod cursor; mod element; diff --git a/crates/gpui_elements/src/input/actions.rs b/crates/gpui_elements/src/input/actions.rs deleted file mode 100644 index c23acbe73b..0000000000 --- a/crates/gpui_elements/src/input/actions.rs +++ /dev/null @@ -1,157 +0,0 @@ -/// The key context used for input element keybindings. -pub const DEFAULT_INPUT_CONTEXT: &str = "Input"; - -gpui::actions!( - actions, - [ - /// Delete the character before the cursor. - Backspace, - /// Delete the character after the cursor. - Delete, - /// Blur focus from the input. - Escape, - /// Delete the word before the cursor. - DeleteWordLeft, - /// Delete the word after the cursor. - DeleteWordRight, - /// Delete from the cursor to the beginning of the line. - DeleteToBeginningOfLine, - /// Delete from the cursor to the end of the line. - DeleteToEndOfLine, - /// Insert a tab character at the cursor position. - Tab, - /// Move the cursor one character to the left. - Left, - /// Move the cursor one character to the right. - Right, - /// Move the cursor up one visual line. - Up, - /// Move the cursor down one visual line. - Down, - /// Extend selection one character to the left. - SelectLeft, - /// Extend selection one character to the right. - SelectRight, - /// Extend selection up one visual line. - SelectUp, - /// Extend selection down one visual line. - SelectDown, - /// Select all text content. - SelectAll, - /// Move cursor to the start of the current line. - Home, - /// Move cursor to the end of the current line. - End, - /// Extend selection to the beginning of the content. - SelectToBeginning, - /// Extend selection to the end of the content. - SelectToEnd, - /// Move cursor to the beginning of the content. - MoveToBeginning, - /// Move cursor to the end of the content. - MoveToEnd, - /// Paste from clipboard at the cursor position. - Paste, - /// Cut selected text to clipboard. - Cut, - /// Copy selected text to clipboard. - Copy, - /// Insert a newline at the cursor position. - Enter, - /// Move cursor one word to the left. - WordLeft, - /// Move cursor one word to the right. - WordRight, - /// Extend selection one word to the left. - SelectWordLeft, - /// Extend selection one word to the right. - SelectWordRight, - /// Undo the last edit. - Undo, - /// Redo the last undone edit. - Redo, - ] -); - -pub fn default_bindings() -> gpui::ActionBindingCollection { - let mut bindings = gpui::ActionBindingCollection::default(); - - #[cfg(target_os = "macos")] - { - bindings = bindings - .with::("backspace") - .with::("delete") - .with::("alt-backspace") - .with::("alt-delete") - .with::("cmd-backspace") - .with::("ctrl-k") - .with::("tab") - .with::("enter") - .with::("left") - .with::("right") - .with::("up") - .with::("down") - .with::("shift-left") - .with::("shift-right") - .with::("shift-up") - .with::("shift-down") - .with::("cmd-a") - // Mac keyboards don't have Home/End keys, so cmd-left/right are standard - .with::("cmd-left") - .with::("cmd-right") - .with::("cmd-up") - .with::("cmd-down") - .with::("cmd-shift-up") - .with::("cmd-shift-down") - .with::("alt-left") - .with::("alt-right") - .with::("alt-shift-left") - .with::("alt-shift-right") - .with::("cmd-c") - .with::("cmd-x") - .with::("cmd-v") - .with::("cmd-z") - .with::("cmd-shift-z") - .with::("escape"); - } - - #[cfg(not(target_os = "macos"))] - { - bindings = bindings - .with::("backspace") - .with::("delete") - .with::("ctrl-backspace") - .with::("ctrl-delete") - .with::("ctrl-shift-backspace") - .with::("ctrl-shift-delete") - .with::("tab") - .with::("enter") - .with::("left") - .with::("right") - .with::("up") - .with::("down") - .with::("shift-left") - .with::("shift-right") - .with::("shift-up") - .with::("shift-down") - .with::("ctrl-a") - .with::("home") - .with::("end") - .with::("ctrl-home") - .with::("ctrl-end") - .with::("ctrl-shift-home") - .with::("ctrl-shift-end") - .with::("ctrl-left") - .with::("ctrl-right") - .with::("ctrl-shift-left") - .with::("ctrl-shift-right") - .with::("ctrl-c") - .with::("ctrl-x") - .with::("ctrl-v") - .with::("ctrl-z") - .with::("ctrl-shift-z") - .with::("escape"); - } - - bindings -} diff --git a/crates/gpui_elements/src/input/element.rs b/crates/gpui_elements/src/input/element.rs index 5409136f9d..11adb146d7 100644 --- a/crates/gpui_elements/src/input/element.rs +++ b/crates/gpui_elements/src/input/element.rs @@ -31,7 +31,7 @@ impl Input { }; input.register_actions(); input - .key_context(super::actions::DEFAULT_INPUT_CONTEXT) + .key_context(crate::editable_text::actions::DEFAULT_INPUT_CONTEXT) .track_focus(&focus_handle) } @@ -122,7 +122,7 @@ impl Input { register_action(&mut self.interactivity, &self.input, InputState::redo); self.interactivity - .on_action::(|_action, window, _cx| { + .on_action::(|_action, window, _cx| { window.blur(); }); } diff --git a/crates/gpui_elements/src/input/state.rs b/crates/gpui_elements/src/input/state.rs index fa1ba51c34..1c4ebc7fba 100644 --- a/crates/gpui_elements/src/input/state.rs +++ b/crates/gpui_elements/src/input/state.rs @@ -1,4 +1,4 @@ -use super::actions::*; +use crate::editable_text::actions::*; use crate::input::{InputLayoutStyle, InputStorage}; use gpui::{ App, ClipboardItem, Context, EntityId, EntityInputHandler, EventEmitter, FocusHandle,