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 = WeakWidget; fn run(rsc: &mut Rsc, container: WeakWidget, id: Self::Input) { rsc.register_event(container, CursorSense::click_or_drag(), move |ctx, rsc| { let region = ctx.data.render.window_region(&id).unwrap(); let id_pos = region.top_left; let container_pos = ctx.data.render.window_region(&container).unwrap().top_left; // The pointer arrives from the platform in floats; everything // it is compared against is on the grid. let pos = (PxVec2::from_f32(ctx.data.pos) + container_pos - id_pos).to_f32(); let size = region.size().to_f32(); select( rsc, ctx.data.render, 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: WeakWidget, _: Self::Input) { rsc.register_event(id, CursorSense::click_or_drag(), move |ctx, rsc| { select( rsc, ctx.data.render, ctx.state, id, ctx.data.pos, ctx.data.size, ctx.data.sense.is_dragging(), ); }); } } fn select( rsc: &mut impl UiRsc, render: &UiRenderState, state: &mut impl HasDefaultUiState, id: WeakWidget, 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) = render.window_region(&id) { state.window.set_ime_allowed(true); state.window.set_ime_cursor_area( LogicalPosition::::from(region.top_left.to_f32().tuple()), LogicalSize::::from(region.size().to_f32().tuple()), ); } state.focus = Some(id); }