Decouple caching from Paragraph API
This commit is contained in:
parent
616689ca54
commit
ffb520fb37
7 changed files with 128 additions and 95 deletions
|
|
@ -79,7 +79,7 @@ impl text::Paragraph for () {
|
||||||
|
|
||||||
fn resize(&mut self, _new_bounds: Size) {}
|
fn resize(&mut self, _new_bounds: Size) {}
|
||||||
|
|
||||||
fn compare(&self, _text: Text<&str>) -> text::Difference {
|
fn compare(&self, _text: Text<()>) -> text::Difference {
|
||||||
text::Difference::None
|
text::Difference::None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
//! Draw and interact with text.
|
//! Draw and interact with text.
|
||||||
mod paragraph;
|
|
||||||
|
|
||||||
pub mod editor;
|
pub mod editor;
|
||||||
pub mod highlighter;
|
pub mod highlighter;
|
||||||
|
pub mod paragraph;
|
||||||
|
|
||||||
pub use editor::Editor;
|
pub use editor::Editor;
|
||||||
pub use highlighter::Highlighter;
|
pub use highlighter::Highlighter;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! Draw paragraphs.
|
||||||
use crate::alignment;
|
use crate::alignment;
|
||||||
use crate::text::{Difference, Hit, Text};
|
use crate::text::{Difference, Hit, Text};
|
||||||
use crate::{Point, Size};
|
use crate::{Point, Size};
|
||||||
|
|
@ -15,7 +16,7 @@ pub trait Paragraph: Sized + Default {
|
||||||
|
|
||||||
/// Compares the [`Paragraph`] with some desired [`Text`] and returns the
|
/// Compares the [`Paragraph`] with some desired [`Text`] and returns the
|
||||||
/// [`Difference`].
|
/// [`Difference`].
|
||||||
fn compare(&self, text: Text<&str, Self::Font>) -> Difference;
|
fn compare(&self, text: Text<(), Self::Font>) -> Difference;
|
||||||
|
|
||||||
/// Returns the horizontal alignment of the [`Paragraph`].
|
/// Returns the horizontal alignment of the [`Paragraph`].
|
||||||
fn horizontal_alignment(&self) -> alignment::Horizontal;
|
fn horizontal_alignment(&self) -> alignment::Horizontal;
|
||||||
|
|
@ -34,19 +35,6 @@ pub trait Paragraph: Sized + Default {
|
||||||
/// Returns the distance to the given grapheme index in the [`Paragraph`].
|
/// Returns the distance to the given grapheme index in the [`Paragraph`].
|
||||||
fn grapheme_position(&self, line: usize, index: usize) -> Option<Point>;
|
fn grapheme_position(&self, line: usize, index: usize) -> Option<Point>;
|
||||||
|
|
||||||
/// Updates the [`Paragraph`] to match the given [`Text`], if needed.
|
|
||||||
fn update(&mut self, text: Text<&str, Self::Font>) {
|
|
||||||
match self.compare(text) {
|
|
||||||
Difference::None => {}
|
|
||||||
Difference::Bounds => {
|
|
||||||
self.resize(text.bounds);
|
|
||||||
}
|
|
||||||
Difference::Shape => {
|
|
||||||
*self = Self::with_text(text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the minimum width that can fit the contents of the [`Paragraph`].
|
/// Returns the minimum width that can fit the contents of the [`Paragraph`].
|
||||||
fn min_width(&self) -> f32 {
|
fn min_width(&self) -> f32 {
|
||||||
self.min_bounds().width
|
self.min_bounds().width
|
||||||
|
|
@ -57,3 +45,77 @@ pub trait Paragraph: Sized + Default {
|
||||||
self.min_bounds().height
|
self.min_bounds().height
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A [`Paragraph`] of plain text.
|
||||||
|
#[derive(Debug, Clone, Default)]
|
||||||
|
pub struct Plain<P: Paragraph> {
|
||||||
|
raw: P,
|
||||||
|
content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<P: Paragraph> Plain<P> {
|
||||||
|
/// Creates a new [`Plain`] paragraph.
|
||||||
|
pub fn new(text: Text<&str, P::Font>) -> Self {
|
||||||
|
let content = text.content.to_owned();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
raw: P::with_text(text),
|
||||||
|
content,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the plain [`Paragraph`] to match the given [`Text`], if needed.
|
||||||
|
pub fn update(&mut self, text: Text<&str, P::Font>) {
|
||||||
|
if self.content != text.content {
|
||||||
|
text.content.clone_into(&mut self.content);
|
||||||
|
self.raw = P::with_text(text);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.raw.compare(Text {
|
||||||
|
content: (),
|
||||||
|
bounds: text.bounds,
|
||||||
|
size: text.size,
|
||||||
|
line_height: text.line_height,
|
||||||
|
font: text.font,
|
||||||
|
horizontal_alignment: text.horizontal_alignment,
|
||||||
|
vertical_alignment: text.vertical_alignment,
|
||||||
|
shaping: text.shaping,
|
||||||
|
}) {
|
||||||
|
Difference::None => {}
|
||||||
|
Difference::Bounds => {
|
||||||
|
self.raw.resize(text.bounds);
|
||||||
|
}
|
||||||
|
Difference::Shape => {
|
||||||
|
self.raw = P::with_text(text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the horizontal alignment of the [`Paragraph`].
|
||||||
|
pub fn horizontal_alignment(&self) -> alignment::Horizontal {
|
||||||
|
self.raw.horizontal_alignment()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the vertical alignment of the [`Paragraph`].
|
||||||
|
pub fn vertical_alignment(&self) -> alignment::Vertical {
|
||||||
|
self.raw.vertical_alignment()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the minimum boundaries that can fit the contents of the
|
||||||
|
/// [`Paragraph`].
|
||||||
|
pub fn min_bounds(&self) -> Size {
|
||||||
|
self.raw.min_bounds()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the minimum width that can fit the contents of the
|
||||||
|
/// [`Paragraph`].
|
||||||
|
pub fn min_width(&self) -> f32 {
|
||||||
|
self.raw.min_width()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the cached [`Paragraph`].
|
||||||
|
pub fn raw(&self) -> &P {
|
||||||
|
&self.raw
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,8 @@ use crate::alignment;
|
||||||
use crate::layout;
|
use crate::layout;
|
||||||
use crate::mouse;
|
use crate::mouse;
|
||||||
use crate::renderer;
|
use crate::renderer;
|
||||||
use crate::text::{self, Paragraph};
|
use crate::text;
|
||||||
|
use crate::text::paragraph::{self, Paragraph};
|
||||||
use crate::widget::tree::{self, Tree};
|
use crate::widget::tree::{self, Tree};
|
||||||
use crate::{
|
use crate::{
|
||||||
Color, Element, Layout, Length, Pixels, Point, Rectangle, Size, Theme,
|
Color, Element, Layout, Length, Pixels, Point, Rectangle, Size, Theme,
|
||||||
|
|
@ -155,7 +156,7 @@ where
|
||||||
|
|
||||||
/// The internal state of a [`Text`] widget.
|
/// The internal state of a [`Text`] widget.
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct State<P: Paragraph>(P);
|
pub struct State<P: Paragraph>(paragraph::Plain<P>);
|
||||||
|
|
||||||
impl<'a, Message, Theme, Renderer> Widget<Message, Theme, Renderer>
|
impl<'a, Message, Theme, Renderer> Widget<Message, Theme, Renderer>
|
||||||
for Text<'a, Theme, Renderer>
|
for Text<'a, Theme, Renderer>
|
||||||
|
|
@ -168,7 +169,9 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn state(&self) -> tree::State {
|
fn state(&self) -> tree::State {
|
||||||
tree::State::new(State(Renderer::Paragraph::default()))
|
tree::State::new(State::<Renderer::Paragraph>(
|
||||||
|
paragraph::Plain::default(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size(&self) -> Size<Length> {
|
fn size(&self) -> Size<Length> {
|
||||||
|
|
@ -294,7 +297,7 @@ pub fn draw<Renderer>(
|
||||||
};
|
};
|
||||||
|
|
||||||
renderer.fill_paragraph(
|
renderer.fill_paragraph(
|
||||||
paragraph,
|
paragraph.raw(),
|
||||||
Point::new(x, y),
|
Point::new(x, y),
|
||||||
appearance.color.unwrap_or(style.text_color),
|
appearance.color.unwrap_or(style.text_color),
|
||||||
*viewport,
|
*viewport,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
//! Draw paragraphs.
|
//! Draw paragraphs.
|
||||||
use crate::core;
|
use crate::core;
|
||||||
use crate::core::alignment;
|
use crate::core::alignment;
|
||||||
use crate::core::text::{Hit, LineHeight, Shaping, Text};
|
use crate::core::text::{Hit, Shaping, Text};
|
||||||
use crate::core::{Font, Pixels, Point, Size};
|
use crate::core::{Font, Point, Size};
|
||||||
use crate::text;
|
use crate::text;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
@ -10,11 +10,11 @@ use std::sync::{self, Arc};
|
||||||
|
|
||||||
/// A bunch of text.
|
/// A bunch of text.
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct Paragraph(Option<Arc<Internal>>);
|
pub struct Paragraph(Arc<Internal>);
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
struct Internal {
|
struct Internal {
|
||||||
buffer: cosmic_text::Buffer,
|
buffer: cosmic_text::Buffer,
|
||||||
content: String, // TODO: Reuse from `buffer` (?)
|
|
||||||
font: Font,
|
font: Font,
|
||||||
shaping: Shaping,
|
shaping: Shaping,
|
||||||
horizontal_alignment: alignment::Horizontal,
|
horizontal_alignment: alignment::Horizontal,
|
||||||
|
|
@ -52,9 +52,7 @@ impl Paragraph {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn internal(&self) -> &Arc<Internal> {
|
fn internal(&self) -> &Arc<Internal> {
|
||||||
self.0
|
&self.0
|
||||||
.as_ref()
|
|
||||||
.expect("paragraph should always be initialized")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,9 +88,8 @@ impl core::text::Paragraph for Paragraph {
|
||||||
|
|
||||||
let min_bounds = text::measure(&buffer);
|
let min_bounds = text::measure(&buffer);
|
||||||
|
|
||||||
Self(Some(Arc::new(Internal {
|
Self(Arc::new(Internal {
|
||||||
buffer,
|
buffer,
|
||||||
content: text.content.to_owned(),
|
|
||||||
font: text.font,
|
font: text.font,
|
||||||
horizontal_alignment: text.horizontal_alignment,
|
horizontal_alignment: text.horizontal_alignment,
|
||||||
vertical_alignment: text.vertical_alignment,
|
vertical_alignment: text.vertical_alignment,
|
||||||
|
|
@ -100,59 +97,31 @@ impl core::text::Paragraph for Paragraph {
|
||||||
bounds: text.bounds,
|
bounds: text.bounds,
|
||||||
min_bounds,
|
min_bounds,
|
||||||
version: font_system.version(),
|
version: font_system.version(),
|
||||||
})))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize(&mut self, new_bounds: Size) {
|
fn resize(&mut self, new_bounds: Size) {
|
||||||
let paragraph = self
|
let paragraph = Arc::make_mut(&mut self.0);
|
||||||
.0
|
|
||||||
.take()
|
|
||||||
.expect("paragraph should always be initialized");
|
|
||||||
|
|
||||||
match Arc::try_unwrap(paragraph) {
|
|
||||||
Ok(mut internal) => {
|
|
||||||
let mut font_system =
|
let mut font_system =
|
||||||
text::font_system().write().expect("Write font system");
|
text::font_system().write().expect("Write font system");
|
||||||
|
|
||||||
internal.buffer.set_size(
|
paragraph.buffer.set_size(
|
||||||
font_system.raw(),
|
font_system.raw(),
|
||||||
Some(new_bounds.width),
|
Some(new_bounds.width),
|
||||||
Some(new_bounds.height),
|
Some(new_bounds.height),
|
||||||
);
|
);
|
||||||
|
|
||||||
internal.bounds = new_bounds;
|
paragraph.bounds = new_bounds;
|
||||||
internal.min_bounds = text::measure(&internal.buffer);
|
paragraph.min_bounds = text::measure(¶graph.buffer);
|
||||||
|
|
||||||
self.0 = Some(Arc::new(internal));
|
|
||||||
}
|
|
||||||
Err(internal) => {
|
|
||||||
let metrics = internal.buffer.metrics();
|
|
||||||
|
|
||||||
// If there is a strong reference somewhere, we recompute the
|
|
||||||
// buffer from scratch
|
|
||||||
*self = Self::with_text(Text {
|
|
||||||
content: &internal.content,
|
|
||||||
bounds: internal.bounds,
|
|
||||||
size: Pixels(metrics.font_size),
|
|
||||||
line_height: LineHeight::Absolute(Pixels(
|
|
||||||
metrics.line_height,
|
|
||||||
)),
|
|
||||||
font: internal.font,
|
|
||||||
horizontal_alignment: internal.horizontal_alignment,
|
|
||||||
vertical_alignment: internal.vertical_alignment,
|
|
||||||
shaping: internal.shaping,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compare(&self, text: Text<&str>) -> core::text::Difference {
|
fn compare(&self, text: Text<()>) -> core::text::Difference {
|
||||||
let font_system = text::font_system().read().expect("Read font system");
|
let font_system = text::font_system().read().expect("Read font system");
|
||||||
let paragraph = self.internal();
|
let paragraph = self.internal();
|
||||||
let metrics = paragraph.buffer.metrics();
|
let metrics = paragraph.buffer.metrics();
|
||||||
|
|
||||||
if paragraph.version != font_system.version
|
if paragraph.version != font_system.version
|
||||||
|| paragraph.content != text.content
|
|
||||||
|| metrics.font_size != text.size.0
|
|| metrics.font_size != text.size.0
|
||||||
|| metrics.line_height != text.line_height.to_absolute(text.size).0
|
|| metrics.line_height != text.line_height.to_absolute(text.size).0
|
||||||
|| paragraph.font != text.font
|
|| paragraph.font != text.font
|
||||||
|
|
@ -231,7 +200,7 @@ impl core::text::Paragraph for Paragraph {
|
||||||
|
|
||||||
impl Default for Paragraph {
|
impl Default for Paragraph {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self(Some(Arc::new(Internal::default())))
|
Self(Arc::new(Internal::default()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -240,7 +209,6 @@ impl fmt::Debug for Paragraph {
|
||||||
let paragraph = self.internal();
|
let paragraph = self.internal();
|
||||||
|
|
||||||
f.debug_struct("Paragraph")
|
f.debug_struct("Paragraph")
|
||||||
.field("content", ¶graph.content)
|
|
||||||
.field("font", ¶graph.font)
|
.field("font", ¶graph.font)
|
||||||
.field("shaping", ¶graph.shaping)
|
.field("shaping", ¶graph.shaping)
|
||||||
.field("horizontal_alignment", ¶graph.horizontal_alignment)
|
.field("horizontal_alignment", ¶graph.horizontal_alignment)
|
||||||
|
|
@ -253,8 +221,7 @@ impl fmt::Debug for Paragraph {
|
||||||
|
|
||||||
impl PartialEq for Internal {
|
impl PartialEq for Internal {
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
self.content == other.content
|
self.font == other.font
|
||||||
&& self.font == other.font
|
|
||||||
&& self.shaping == other.shaping
|
&& self.shaping == other.shaping
|
||||||
&& self.horizontal_alignment == other.horizontal_alignment
|
&& self.horizontal_alignment == other.horizontal_alignment
|
||||||
&& self.vertical_alignment == other.vertical_alignment
|
&& self.vertical_alignment == other.vertical_alignment
|
||||||
|
|
@ -271,7 +238,6 @@ impl Default for Internal {
|
||||||
font_size: 1.0,
|
font_size: 1.0,
|
||||||
line_height: 1.0,
|
line_height: 1.0,
|
||||||
}),
|
}),
|
||||||
content: String::new(),
|
|
||||||
font: Font::default(),
|
font: Font::default(),
|
||||||
shaping: Shaping::default(),
|
shaping: Shaping::default(),
|
||||||
horizontal_alignment: alignment::Horizontal::Left,
|
horizontal_alignment: alignment::Horizontal::Left,
|
||||||
|
|
@ -298,7 +264,7 @@ pub struct Weak {
|
||||||
impl Weak {
|
impl Weak {
|
||||||
/// Tries to update the reference into a [`Paragraph`].
|
/// Tries to update the reference into a [`Paragraph`].
|
||||||
pub fn upgrade(&self) -> Option<Paragraph> {
|
pub fn upgrade(&self) -> Option<Paragraph> {
|
||||||
self.raw.upgrade().map(Some).map(Paragraph)
|
self.raw.upgrade().map(Paragraph)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ use crate::core::layout;
|
||||||
use crate::core::mouse;
|
use crate::core::mouse;
|
||||||
use crate::core::overlay;
|
use crate::core::overlay;
|
||||||
use crate::core::renderer;
|
use crate::core::renderer;
|
||||||
use crate::core::text::{self, Paragraph as _, Text};
|
use crate::core::text::paragraph;
|
||||||
|
use crate::core::text::{self, Text};
|
||||||
use crate::core::touch;
|
use crate::core::touch;
|
||||||
use crate::core::widget::tree::{self, Tree};
|
use crate::core::widget::tree::{self, Tree};
|
||||||
use crate::core::{
|
use crate::core::{
|
||||||
|
|
@ -622,8 +623,8 @@ struct State<P: text::Paragraph> {
|
||||||
keyboard_modifiers: keyboard::Modifiers,
|
keyboard_modifiers: keyboard::Modifiers,
|
||||||
is_open: bool,
|
is_open: bool,
|
||||||
hovered_option: Option<usize>,
|
hovered_option: Option<usize>,
|
||||||
options: Vec<P>,
|
options: Vec<paragraph::Plain<P>>,
|
||||||
placeholder: P,
|
placeholder: paragraph::Plain<P>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P: text::Paragraph> State<P> {
|
impl<P: text::Paragraph> State<P> {
|
||||||
|
|
@ -635,7 +636,7 @@ impl<P: text::Paragraph> State<P> {
|
||||||
is_open: bool::default(),
|
is_open: bool::default(),
|
||||||
hovered_option: Option::default(),
|
hovered_option: Option::default(),
|
||||||
options: Vec::new(),
|
options: Vec::new(),
|
||||||
placeholder: P::default(),
|
placeholder: paragraph::Plain::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,8 @@ use crate::core::keyboard::key;
|
||||||
use crate::core::layout;
|
use crate::core::layout;
|
||||||
use crate::core::mouse::{self, click};
|
use crate::core::mouse::{self, click};
|
||||||
use crate::core::renderer;
|
use crate::core::renderer;
|
||||||
use crate::core::text::{self, Paragraph as _, Text};
|
use crate::core::text::paragraph;
|
||||||
|
use crate::core::text::{self, Text};
|
||||||
use crate::core::time::{Duration, Instant};
|
use crate::core::time::{Duration, Instant};
|
||||||
use crate::core::touch;
|
use crate::core::touch;
|
||||||
use crate::core::widget;
|
use crate::core::widget;
|
||||||
|
|
@ -360,7 +361,7 @@ where
|
||||||
let icon_layout = children_layout.next().unwrap();
|
let icon_layout = children_layout.next().unwrap();
|
||||||
|
|
||||||
renderer.fill_paragraph(
|
renderer.fill_paragraph(
|
||||||
&state.icon,
|
state.icon.raw(),
|
||||||
icon_layout.bounds().center(),
|
icon_layout.bounds().center(),
|
||||||
style.icon,
|
style.icon,
|
||||||
*viewport,
|
*viewport,
|
||||||
|
|
@ -378,7 +379,7 @@ where
|
||||||
cursor::State::Index(position) => {
|
cursor::State::Index(position) => {
|
||||||
let (text_value_width, offset) =
|
let (text_value_width, offset) =
|
||||||
measure_cursor_and_scroll_offset(
|
measure_cursor_and_scroll_offset(
|
||||||
&state.value,
|
state.value.raw(),
|
||||||
text_bounds,
|
text_bounds,
|
||||||
position,
|
position,
|
||||||
);
|
);
|
||||||
|
|
@ -415,14 +416,14 @@ where
|
||||||
|
|
||||||
let (left_position, left_offset) =
|
let (left_position, left_offset) =
|
||||||
measure_cursor_and_scroll_offset(
|
measure_cursor_and_scroll_offset(
|
||||||
&state.value,
|
state.value.raw(),
|
||||||
text_bounds,
|
text_bounds,
|
||||||
left,
|
left,
|
||||||
);
|
);
|
||||||
|
|
||||||
let (right_position, right_offset) =
|
let (right_position, right_offset) =
|
||||||
measure_cursor_and_scroll_offset(
|
measure_cursor_and_scroll_offset(
|
||||||
&state.value,
|
state.value.raw(),
|
||||||
text_bounds,
|
text_bounds,
|
||||||
right,
|
right,
|
||||||
);
|
);
|
||||||
|
|
@ -469,9 +470,9 @@ where
|
||||||
|
|
||||||
renderer.fill_paragraph(
|
renderer.fill_paragraph(
|
||||||
if text.is_empty() {
|
if text.is_empty() {
|
||||||
&state.placeholder
|
state.placeholder.raw()
|
||||||
} else {
|
} else {
|
||||||
&state.value
|
state.value.raw()
|
||||||
},
|
},
|
||||||
Point::new(text_bounds.x, text_bounds.center_y())
|
Point::new(text_bounds.x, text_bounds.center_y())
|
||||||
- Vector::new(offset, 0.0),
|
- Vector::new(offset, 0.0),
|
||||||
|
|
@ -1178,9 +1179,9 @@ pub fn select_all<T>(id: Id) -> Task<T> {
|
||||||
/// The state of a [`TextInput`].
|
/// The state of a [`TextInput`].
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct State<P: text::Paragraph> {
|
pub struct State<P: text::Paragraph> {
|
||||||
value: P,
|
value: paragraph::Plain<P>,
|
||||||
placeholder: P,
|
placeholder: paragraph::Plain<P>,
|
||||||
icon: P,
|
icon: paragraph::Plain<P>,
|
||||||
is_focused: Option<Focus>,
|
is_focused: Option<Focus>,
|
||||||
is_dragging: bool,
|
is_dragging: bool,
|
||||||
is_pasting: Option<Value>,
|
is_pasting: Option<Value>,
|
||||||
|
|
@ -1212,9 +1213,9 @@ impl<P: text::Paragraph> State<P> {
|
||||||
/// Creates a new [`State`], representing a focused [`TextInput`].
|
/// Creates a new [`State`], representing a focused [`TextInput`].
|
||||||
pub fn focused() -> Self {
|
pub fn focused() -> Self {
|
||||||
Self {
|
Self {
|
||||||
value: P::default(),
|
value: paragraph::Plain::default(),
|
||||||
placeholder: P::default(),
|
placeholder: paragraph::Plain::default(),
|
||||||
icon: P::default(),
|
icon: paragraph::Plain::default(),
|
||||||
is_focused: None,
|
is_focused: None,
|
||||||
is_dragging: false,
|
is_dragging: false,
|
||||||
is_pasting: None,
|
is_pasting: None,
|
||||||
|
|
@ -1319,7 +1320,7 @@ fn offset<P: text::Paragraph>(
|
||||||
};
|
};
|
||||||
|
|
||||||
let (_, offset) = measure_cursor_and_scroll_offset(
|
let (_, offset) = measure_cursor_and_scroll_offset(
|
||||||
&state.value,
|
state.value.raw(),
|
||||||
text_bounds,
|
text_bounds,
|
||||||
focus_position,
|
focus_position,
|
||||||
);
|
);
|
||||||
|
|
@ -1357,6 +1358,7 @@ fn find_cursor_position<P: text::Paragraph>(
|
||||||
|
|
||||||
let char_offset = state
|
let char_offset = state
|
||||||
.value
|
.value
|
||||||
|
.raw()
|
||||||
.hit_test(Point::new(x + offset, text_bounds.height / 2.0))
|
.hit_test(Point::new(x + offset, text_bounds.height / 2.0))
|
||||||
.map(text::Hit::cursor)?;
|
.map(text::Hit::cursor)?;
|
||||||
|
|
||||||
|
|
@ -1386,7 +1388,7 @@ fn replace_paragraph<Renderer>(
|
||||||
let mut children_layout = layout.children();
|
let mut children_layout = layout.children();
|
||||||
let text_bounds = children_layout.next().unwrap().bounds();
|
let text_bounds = children_layout.next().unwrap().bounds();
|
||||||
|
|
||||||
state.value = Renderer::Paragraph::with_text(Text {
|
state.value = paragraph::Plain::new(Text {
|
||||||
font,
|
font,
|
||||||
line_height,
|
line_height,
|
||||||
content: &value.to_string(),
|
content: &value.to_string(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue