Compare commits
1 Commits
90c579d734
...
2aa5719166
| Author | SHA1 | Date | |
|---|---|---|---|
| 2aa5719166 |
@@ -95,6 +95,7 @@ impl TextBuilderOutput for TextEditOutput {
|
||||
let mut text = TextEdit {
|
||||
view: TextView::new(buf, builder.attrs, builder.hint.get(ui)),
|
||||
selection: Default::default(),
|
||||
history: Default::default(),
|
||||
};
|
||||
let font_system = &mut ui.data.text.font_system;
|
||||
text.buf
|
||||
|
||||
@@ -11,6 +11,7 @@ use winit::{
|
||||
pub struct TextEdit {
|
||||
pub(super) view: TextView,
|
||||
pub(super) selection: TextSelection,
|
||||
pub(super) history: Vec<(String, TextSelection)>,
|
||||
}
|
||||
|
||||
impl TextEdit {
|
||||
@@ -180,6 +181,13 @@ impl<'a> TextEditCtx<'a> {
|
||||
text
|
||||
}
|
||||
|
||||
pub fn set(&mut self, text: &str) {
|
||||
self.text
|
||||
.buf
|
||||
.set_text(self.font_system, text, &Attrs::new(), SHAPING, None);
|
||||
self.text.selection.clear();
|
||||
}
|
||||
|
||||
pub fn motion(&mut self, motion: Motion) {
|
||||
if let TextSelection::Pos(cursor) = self.text.selection
|
||||
&& let Some(cursor) = self.buf_motion(cursor, motion)
|
||||
@@ -372,6 +380,24 @@ impl<'a> TextEditCtx<'a> {
|
||||
}
|
||||
|
||||
pub fn apply_event(&mut self, event: &KeyEvent, modifiers: &Modifiers) -> TextInputResult {
|
||||
let old = (self.text.content(), self.text.selection);
|
||||
let mut undo = false;
|
||||
let res = self.apply_event_inner(event, modifiers, &mut undo);
|
||||
if undo && let Some((old, selection)) = self.text.history.pop() {
|
||||
self.set(&old);
|
||||
self.text.selection = selection;
|
||||
} else if self.text.content() != old.0 {
|
||||
self.text.history.push(old);
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn apply_event_inner(
|
||||
&mut self,
|
||||
event: &KeyEvent,
|
||||
modifiers: &Modifiers,
|
||||
undo: &mut bool,
|
||||
) -> TextInputResult {
|
||||
match &event.logical_key {
|
||||
Key::Named(named) => match named {
|
||||
NamedKey::Backspace => self.backspace(modifiers.control),
|
||||
@@ -429,6 +455,9 @@ impl<'a> TextEditCtx<'a> {
|
||||
};
|
||||
}
|
||||
}
|
||||
"z" => {
|
||||
*undo = true;
|
||||
}
|
||||
_ => self.insert(text),
|
||||
}
|
||||
} else {
|
||||
@@ -463,7 +492,7 @@ pub enum TextInputResult {
|
||||
Paste,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
pub enum TextSelection {
|
||||
#[default]
|
||||
None,
|
||||
|
||||
@@ -9,7 +9,7 @@ use std::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
layout::{FnTag, Ui, Widget, WidgetLike, WidgetTag},
|
||||
layout::{Ui, WidgetLike},
|
||||
util::{Id, RefCounter},
|
||||
};
|
||||
|
||||
@@ -141,49 +141,6 @@ pub struct IdFnTag;
|
||||
pub trait WidgetIdFn<W>: FnOnce(&mut Ui) -> WidgetId<W> {}
|
||||
impl<W, F: FnOnce(&mut Ui) -> WidgetId<W>> WidgetIdFn<W> for F {}
|
||||
|
||||
/// TODO: does this ever make sense to use? it allows for invalid ids
|
||||
pub trait Idable<Tag> {
|
||||
type Widget: Widget;
|
||||
fn set(self, ui: &mut Ui, id: &WidgetId<Self::Widget>);
|
||||
fn id(self, id: &WidgetId<Self::Widget>) -> impl WidgetIdFn<Self::Widget>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let id = id.clone();
|
||||
move |ui| {
|
||||
self.set(ui, &id);
|
||||
id
|
||||
}
|
||||
}
|
||||
fn id_static(self, id: StaticWidgetId<Self::Widget>) -> impl WidgetIdFn<Self::Widget>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
move |ui| {
|
||||
let id = id.id(&ui.send);
|
||||
self.set(ui, &id);
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: Widget> Idable<WidgetTag> for W {
|
||||
type Widget = W;
|
||||
|
||||
fn set(self, ui: &mut Ui, id: &WidgetId<Self::Widget>) {
|
||||
ui.set(id, self);
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: FnOnce(&mut Ui) -> W, W: Widget> Idable<FnTag> for F {
|
||||
type Widget = W;
|
||||
|
||||
fn set(self, ui: &mut Ui, id: &WidgetId<Self::Widget>) {
|
||||
let w = self(ui);
|
||||
ui.set(id, w);
|
||||
}
|
||||
}
|
||||
|
||||
impl<W: 'static> WidgetLike<IdTag> for WidgetId<W> {
|
||||
type Widget = W;
|
||||
fn add(self, _: &mut Ui) -> WidgetId<W> {
|
||||
|
||||
@@ -52,15 +52,11 @@ impl Ui {
|
||||
}
|
||||
|
||||
pub fn push<W: Widget>(&mut self, w: W) -> WidgetId<W> {
|
||||
let id = self.id();
|
||||
let id = self.new_id();
|
||||
self.data.widgets.insert(id.id, w);
|
||||
id
|
||||
}
|
||||
|
||||
pub fn set<W: Widget>(&mut self, id: &WidgetId<W>, w: W) {
|
||||
self.data.widgets.insert(id.id, w);
|
||||
}
|
||||
|
||||
pub fn set_root<Tag>(&mut self, w: impl WidgetLike<Tag>) {
|
||||
self.root = Some(w.add(self).any());
|
||||
self.full_redraw = true;
|
||||
@@ -78,7 +74,7 @@ impl Ui {
|
||||
self.data.widgets.get_mut(id)
|
||||
}
|
||||
|
||||
pub fn id<W: Widget>(&mut self) -> WidgetId<W> {
|
||||
fn new_id<W: Widget>(&mut self) -> WidgetId<W> {
|
||||
WidgetId::new(
|
||||
self.data.widgets.reserve(),
|
||||
TypeId::of::<W>(),
|
||||
@@ -87,11 +83,6 @@ impl Ui {
|
||||
)
|
||||
}
|
||||
|
||||
pub fn id_static<W: Widget>(&mut self) -> StaticWidgetId<W> {
|
||||
let id = self.id();
|
||||
id.into_static()
|
||||
}
|
||||
|
||||
pub fn add_texture(&mut self, image: DynamicImage) -> TextureHandle {
|
||||
self.data.textures.add(image)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user