69 lines
2.0 KiB
Rust
69 lines
2.0 KiB
Rust
use crate::prelude::*;
|
|
use std::time::{Duration, Instant};
|
|
use winit::dpi::{LogicalPosition, LogicalSize};
|
|
|
|
pub struct Selector;
|
|
|
|
impl<Rsc: HasEvents, W: Widget + 'static> WidgetAttr<Rsc, W> for Selector
|
|
where
|
|
Rsc::State: HasDefaultUiState,
|
|
{
|
|
type Input = WidgetRef<TextEdit>;
|
|
|
|
fn run(rsc: &mut Rsc, container: WidgetRef<W>, 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<Rsc: HasEvents> WidgetAttr<Rsc, TextEdit> for Selectable
|
|
where
|
|
Rsc::State: HasDefaultUiState,
|
|
{
|
|
type Input = ();
|
|
|
|
fn run(rsc: &mut Rsc, id: WidgetRef<TextEdit>, _: 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<TextEdit>,
|
|
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::<f32>::from(region.top_left.tuple()),
|
|
LogicalSize::<f32>::from(region.size().tuple()),
|
|
);
|
|
}
|
|
state.focus = Some(id);
|
|
}
|