add versioning to storage so that the ui can re-render on storage change
This commit is contained in:
@@ -206,8 +206,12 @@ impl Element for TextInputElement {
|
||||
|
||||
// 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 wrapping = TextLayoutWrapping::new(
|
||||
request_layout.text_style.clone(),
|
||||
wrap_width,
|
||||
state.storage().version(),
|
||||
);
|
||||
let show_placeholder = state.storage().content_utf8().is_empty();
|
||||
state.layout_data.bounds = bounds;
|
||||
if state.layout_wrapping.integrate(wrapping) {
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::editable_text::{
|
||||
};
|
||||
use gpui::{
|
||||
App, Bounds, ClipboardItem, Entity, FocusHandle, Focusable, Hsla, NavigationDirection, Pixels,
|
||||
Point, ShapedLine, SharedString, TextRun, TextStyle, UTF16Selection, Window, WrappedLine,
|
||||
Point, SharedString, TextRun, TextStyle, UTF16Selection, Window, WrappedLine,
|
||||
};
|
||||
use std::{ops::Range, sync::Arc};
|
||||
|
||||
@@ -58,25 +58,32 @@ pub struct TextInputStateBase {
|
||||
pub(super) layout_data: TextInputLayoutData,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(PartialEq)]
|
||||
pub(super) struct TextLayoutWrapping {
|
||||
text_style: TextStyle,
|
||||
wrap_width: Option<Pixels>,
|
||||
dirty: bool,
|
||||
last_seen_storage_version: u16,
|
||||
}
|
||||
impl Default for TextLayoutWrapping {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
text_style: Default::default(),
|
||||
wrap_width: Default::default(),
|
||||
last_seen_storage_version: u16::MAX,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl TextLayoutWrapping {
|
||||
pub fn new(text_style: TextStyle, wrap_width: Option<Pixels>) -> Self {
|
||||
pub fn new(text_style: TextStyle, wrap_width: Option<Pixels>, storage_version: u16) -> Self {
|
||||
Self {
|
||||
text_style,
|
||||
wrap_width,
|
||||
dirty: false,
|
||||
last_seen_storage_version: storage_version,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn integrate(&mut self, other: Self) -> bool {
|
||||
let dirty = self.dirty
|
||||
|| self.wrap_width != other.wrap_width
|
||||
|| self.text_style != other.text_style;
|
||||
let dirty = *self != other;
|
||||
*self = other;
|
||||
dirty
|
||||
}
|
||||
@@ -125,10 +132,7 @@ impl TextInputStateBase {
|
||||
|
||||
focus_handle: cx.focus_handle(),
|
||||
|
||||
layout_wrapping: TextLayoutWrapping {
|
||||
dirty: true,
|
||||
..TextLayoutWrapping::default()
|
||||
},
|
||||
layout_wrapping: TextLayoutWrapping::default(),
|
||||
layout_data: TextInputLayoutData::default(),
|
||||
}
|
||||
}
|
||||
@@ -166,11 +170,11 @@ impl TextInputStateBase {
|
||||
}
|
||||
|
||||
impl TextInputStateBase {
|
||||
pub fn line_segments(&self) -> &Vec<TextLineSegment> {
|
||||
pub(super) fn line_segments(&self) -> &Vec<TextLineSegment> {
|
||||
&self.layout_data.lines
|
||||
}
|
||||
|
||||
pub fn build_wrapped_lines(
|
||||
pub(super) fn build_wrapped_lines(
|
||||
content: &str,
|
||||
wrapping: &TextLayoutWrapping,
|
||||
window: &Window,
|
||||
|
||||
@@ -18,13 +18,15 @@ pub(super) struct InitStorage(Option<Rc<dyn Fn(&mut App) -> Box<dyn UnicodeTextS
|
||||
impl InitStorage {
|
||||
pub fn exec(&self, cx: &mut App) -> Box<dyn UnicodeTextStorage> {
|
||||
match &self.0 {
|
||||
None => Box::new(String::new()),
|
||||
None => Box::new(StringStorage::default()),
|
||||
Some(init) => (*init)(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait UnicodeTextStorage {
|
||||
fn version(&self) -> u16;
|
||||
|
||||
/// Returns a reference to the utf8 string.
|
||||
fn content_utf8(&self) -> &str;
|
||||
|
||||
@@ -215,16 +217,34 @@ pub trait UnicodeTextStorage {
|
||||
}
|
||||
}
|
||||
|
||||
impl UnicodeTextStorage for String {
|
||||
#[derive(Default)]
|
||||
pub struct StringStorage {
|
||||
value: String,
|
||||
version: u16,
|
||||
}
|
||||
impl From<String> for StringStorage {
|
||||
fn from(value: String) -> Self {
|
||||
Self {
|
||||
value,
|
||||
version: u16::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl UnicodeTextStorage for StringStorage {
|
||||
fn version(&self) -> u16 {
|
||||
self.version
|
||||
}
|
||||
|
||||
fn content_utf8(&self) -> &str {
|
||||
self.as_str()
|
||||
self.value.as_str()
|
||||
}
|
||||
|
||||
fn len_utf16(&self) -> usize {
|
||||
self.len()
|
||||
self.value.chars().map(|c| c.len_utf16()).sum()
|
||||
}
|
||||
|
||||
fn replace_range(&mut self, range: Range<usize>, text: &str) {
|
||||
self.replace_range(range, &text);
|
||||
self.value.replace_range(range, &text);
|
||||
self.version = self.version.wrapping_add(1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user