TEXT SELECTION

This commit is contained in:
2025-11-21 23:56:31 -05:00
parent 246caffb34
commit 1cec56e847
10 changed files with 332 additions and 69 deletions

View File

@@ -6,7 +6,12 @@ use iris::prelude::*;
use len_fns::*;
use render::Renderer;
use std::sync::Arc;
use winit::{event::WindowEvent, event_loop::ActiveEventLoop, window::Window};
use winit::{
dpi::{LogicalPosition, LogicalSize},
event::{Ime, WindowEvent},
event_loop::ActiveEventLoop,
window::Window,
};
mod app;
mod input;
@@ -18,11 +23,13 @@ fn main() {
pub struct Client {
renderer: Renderer,
window: Arc<Window>,
input: Input,
ui: Ui,
info: WidgetId<Text>,
focus: Option<WidgetId<TextEdit>>,
clipboard: Clipboard,
ime: usize,
}
#[derive(Eq, PartialEq, Hash, Clone)]
@@ -32,9 +39,37 @@ impl DefaultEvent for Submit {
type Data = ();
}
pub struct Selectable;
impl WidgetAttr<TextEdit> for Selectable {
type Input = ();
fn run(ui: &mut Ui, id: &WidgetId<TextEdit>, _: Self::Input) {
let id = id.clone();
ui.register_event(
&id.clone(),
CursorSense::click_or_drag(),
move |client: &mut Client, data| {
client
.ui
.text(&id)
.select(data.cursor, data.size, data.sense.is_dragging());
if let Some(region) = client.ui.window_region(&id) {
client.window.set_ime_allowed(true);
client.window.set_ime_cursor_area(
LogicalPosition::<f32>::from(region.top_left.tuple()),
LogicalSize::<f32>::from(region.size().tuple()),
);
}
client.focus = Some(id.clone());
},
);
}
}
impl Client {
pub fn new(window: Arc<Window>) -> Self {
let renderer = Renderer::new(window);
let renderer = Renderer::new(window.clone());
let mut ui = Ui::new();
let rrect = rect(Color::WHITE).radius(20);
@@ -127,10 +162,7 @@ impl Client {
.editable()
.text_align(Align::LEFT)
.size(30)
.id_on(CursorSense::click(), |id, client: &mut Client, ctx| {
client.ui.text(id).select(ctx.cursor, ctx.size);
client.focus = Some(id.clone());
})
.attr::<Selectable>(())
.id_on(Submit, move |id, client: &mut Client, _| {
let content = client.ui.text(id).take();
let text = text(content)
@@ -138,10 +170,7 @@ impl Client {
.size(30)
.text_align(Align::LEFT)
.wrap(true)
.id_on(CursorSense::click(), |id, client: &mut Client, ctx| {
client.ui.text(id).select(ctx.cursor, ctx.size);
client.focus = Some(id.clone());
});
.attr::<Selectable>(());
let msg_box = text
.background(rect(Color::WHITE.darker(0.5)))
.add(&mut client.ui);
@@ -213,11 +242,13 @@ impl Client {
Self {
renderer,
window,
input: Input::default(),
ui,
info,
focus: None,
clipboard: Clipboard::new().unwrap(),
ime: 0,
}
}
@@ -263,10 +294,31 @@ impl Client {
text.insert(&t);
}
}
TextInputResult::Copy(text) => {
if let Err(err) = self.clipboard.set_text(text) {
eprintln!("failed to copy text to clipboard: {err}")
}
}
TextInputResult::Unused | TextInputResult::Used => (),
}
}
}
WindowEvent::Ime(ime) => {
if let Some(sel) = &self.focus {
let mut text = self.ui.text(sel);
match ime {
Ime::Enabled | Ime::Disabled => (),
Ime::Preedit(content, _pos) => {
// TODO: highlight once that's real
text.replace(self.ime, &content);
self.ime = content.chars().count();
}
Ime::Commit(content) => {
text.insert(&content);
}
}
}
}
_ => (),
}
let new = format!(