Implement reactive-rendering for text_editor

This commit is contained in:
Héctor Ramón Jiménez 2024-11-04 23:21:06 +01:00
parent d5a886dbcb
commit 3482ffecdc
No known key found for this signature in database
GPG key ID: 4C07CEC81AFA161F

View file

@ -119,6 +119,7 @@ pub struct TextEditor<
&Highlighter::Highlight,
&Theme,
) -> highlighter::Format<Renderer::Font>,
last_status: Option<Status>,
}
impl<'a, Message, Theme, Renderer>
@ -146,6 +147,7 @@ where
highlighter_format: |_highlight, _theme| {
highlighter::Format::default()
},
last_status: None,
}
}
}
@ -269,6 +271,7 @@ where
on_edit: self.on_edit,
highlighter_settings: settings,
highlighter_format: to_format,
last_status: self.last_status,
}
}
@ -611,6 +614,10 @@ where
};
let state = tree.state.downcast_mut::<State<Highlighter>>();
let is_redraw = matches!(
event,
Event::Window(window::Event::RedrawRequested(_now)),
);
match event {
Event::Window(window::Event::Unfocused) => {
@ -647,16 +654,15 @@ where
_ => {}
}
let Some(update) = Update::from_event(
if let Some(update) = Update::from_event(
event,
state,
layout.bounds(),
self.padding,
cursor,
self.key_binding.as_deref(),
) else {
return;
};
) {
shell.capture_event();
match update {
Update::Click(click) => {
@ -707,7 +713,8 @@ where
clipboard: &mut dyn Clipboard,
shell: &mut Shell<'_, Message>,
) {
let mut publish = |action| shell.publish(on_edit(action));
let mut publish =
|action| shell.publish(on_edit(action));
match binding {
Binding::Unfocus => {
@ -736,9 +743,9 @@ where
if let Some(contents) =
clipboard.read(clipboard::Kind::Standard)
{
publish(Action::Edit(Edit::Paste(Arc::new(
contents,
))));
publish(Action::Edit(Edit::Paste(
Arc::new(contents),
)));
}
}
Binding::Move(motion) => {
@ -796,8 +803,31 @@ where
}
}
}
}
shell.capture_event();
let status = {
let is_disabled = self.on_edit.is_none();
let is_hovered = cursor.is_over(layout.bounds());
if is_disabled {
Status::Disabled
} else if state.focus.is_some() {
Status::Focused { is_hovered }
} else if is_hovered {
Status::Hovered
} else {
Status::Active
}
};
if is_redraw {
self.last_status = Some(status);
} else if self
.last_status
.is_some_and(|last_status| status != last_status)
{
shell.request_redraw();
}
}
fn draw(
@ -807,7 +837,7 @@ where
theme: &Theme,
_defaults: &renderer::Style,
layout: Layout<'_>,
cursor: mouse::Cursor,
_cursor: mouse::Cursor,
_viewport: &Rectangle,
) {
let bounds = layout.bounds();
@ -823,20 +853,8 @@ where
|highlight| (self.highlighter_format)(highlight, theme),
);
let is_disabled = self.on_edit.is_none();
let is_mouse_over = cursor.is_over(bounds);
let status = if is_disabled {
Status::Disabled
} else if state.focus.is_some() {
Status::Focused
} else if is_mouse_over {
Status::Hovered
} else {
Status::Active
};
let style = theme.style(&self.class, status);
let style = theme
.style(&self.class, self.last_status.unwrap_or(Status::Active));
renderer.fill_quad(
renderer::Quad {
@ -1035,7 +1053,7 @@ impl<Message> Binding<Message> {
status,
} = event;
if status != Status::Focused {
if !matches!(status, Status::Focused { .. }) {
return None;
}
@ -1175,7 +1193,9 @@ impl<Message> Update<Message> {
..
}) => {
let status = if state.focus.is_some() {
Status::Focused
Status::Focused {
is_hovered: cursor.is_over(bounds),
}
} else {
Status::Active
};
@ -1221,7 +1241,10 @@ pub enum Status {
/// The [`TextEditor`] is being hovered.
Hovered,
/// The [`TextEditor`] is focused.
Focused,
Focused {
/// Whether the [`TextEditor`] is hovered, while focused.
is_hovered: bool,
},
/// The [`TextEditor`] cannot be interacted with.
Disabled,
}
@ -1296,7 +1319,7 @@ pub fn default(theme: &Theme, status: Status) -> Style {
},
..active
},
Status::Focused => Style {
Status::Focused { .. } => Style {
border: Border {
color: palette.primary.strong.color,
..active.border