use crate::prelude::*; use std::time::{Duration, Instant}; use winit::dpi::{LogicalPosition, LogicalSize}; pub struct Selector; impl WidgetAttr for Selector where Rsc::State: HasDefaultUiState, { type Input = WidgetRef; fn run(rsc: &mut Rsc, container: WidgetRef, id: Self::Input) { rsc.register_event(container, CursorSense::click_or_drag(), move |ctx, rsc| { let region = rsc.ui().window_region(&id).unwrap(); let id_pos = region.top_left; let container_pos = rsc.ui().window_region(&container).unwrap().top_left; let pos = ctx.data.pos + container_pos - id_pos; let size = region.size(); select(rsc, ctx.state, id, pos, size, ctx.data.sense.is_dragging()); }); } } pub struct Selectable; impl WidgetAttr for Selectable where Rsc::State: HasDefaultUiState, { type Input = (); fn run(rsc: &mut Rsc, id: WidgetRef, _: Self::Input) { rsc.register_event(id, CursorSense::click_or_drag(), move |ctx, rsc| { select( rsc, ctx.state, id, ctx.data.pos, ctx.data.size, ctx.data.sense.is_dragging(), ); }); } } fn select( rsc: &mut impl HasUi, state: &mut impl HasDefaultUiState, id: WidgetRef, pos: Vec2, size: Vec2, dragging: bool, ) { let state = state.default_state_mut(); let now = Instant::now(); let recent = (now - state.last_click) < Duration::from_millis(300); state.last_click = now; id.edit(rsc).select(pos, size, dragging, recent); if let Some(region) = rsc.ui().window_region(&id) { state.window.set_ime_allowed(true); state.window.set_ime_cursor_area( LogicalPosition::::from(region.top_left.tuple()), LogicalSize::::from(region.size().tuple()), ); } state.focus = Some(id); }