GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
src/widget/display/panel.rs (2.8K)
1 //! Narrow-trait movable panel (Phase 5i leaf sweep). Self-moving via
2 //! [`Input::drag_reposition`], with movement clamped to bounds pushed in through
3 //! [`Input::set_drag_bounds`] (or the inherent `set_bounds`).
4
5 use crate::colors;
6 use crate::scene::layout::Rect;
7 use crate::scene::paint::PaintCtx;
8 use crate::widget::{Adapted, WidgetHost, ElementState, Event, EventCtx, Input, Layout, MouseButton, Paint};
9
10 pub struct Panel {
11 dragging: bool,
12 drag_ox: f32,
13 drag_oy: f32,
14 bounds: Option<(f32, f32, f32, f32)>,
15 }
16
17 impl Panel {
18 pub fn new(x: f32, y: f32, w: f32, h: f32) -> Adapted<Panel> {
19 let mut p = Adapted::new(Panel { dragging: false, drag_ox: 0.0, drag_oy: 0.0, bounds: None });
20 WidgetHost::set_rect(&mut p, x, y, w, h);
21 p
22 }
23
24 pub fn set_bounds(&mut self, bx: f32, by: f32, bw: f32, bh: f32) {
25 self.bounds = Some((bx, by, bw, bh));
26 }
27 }
28
29 impl Layout for Panel {
30 fn inline_label(&self) -> bool {
31 true // legacy Panel never inflated for its label
32 }
33 }
34
35 impl Paint for Panel {
36 fn color(&self) -> [f32; 4] {
37 if self.dragging { colors::PANEL_DRAG } else { colors::PANEL_IDLE }
38 }
39
40 fn paint(&self, rect: Rect, ctx: &mut PaintCtx) {
41 ctx.quad(rect, self.color());
42 }
43 }
44
45 impl Input for Panel {
46 fn on_event(&mut self, event: &Event, ectx: &mut EventCtx) -> bool {
47 match event {
48 Event::MouseButton { button: MouseButton::Left, state: ElementState::Pressed, x, y, .. } => {
49 self.dragging = true;
50 self.drag_ox = x - ectx.rect.x;
51 self.drag_oy = y - ectx.rect.y;
52 true
53 }
54 Event::MouseButton { button: MouseButton::Left, state: ElementState::Released, .. } => {
55 std::mem::take(&mut self.dragging)
56 }
57 _ => false,
58 }
59 }
60
61 fn draggable(&self, _rect: Rect) -> bool {
62 true
63 }
64 fn is_dragging(&self) -> bool {
65 self.dragging
66 }
67 fn drag_begin(&mut self, px: f32, py: f32, rect: Rect) {
68 self.dragging = true;
69 self.drag_ox = px - rect.x;
70 self.drag_oy = py - rect.y;
71 }
72 fn drag_reposition(&mut self, px: f32, py: f32, rect: Rect) -> Option<(f32, f32)> {
73 let nx = px - self.drag_ox;
74 let ny = py - self.drag_oy;
75 let (nx, ny) = if let Some((bx, by, bw, bh)) = self.bounds {
76 (nx.clamp(bx, bx + bw - rect.width), ny.clamp(by, by + bh - rect.height))
77 } else {
78 (nx, ny)
79 };
80 if (nx - rect.x).abs() > 0.01 || (ny - rect.y).abs() > 0.01 {
81 Some((nx, ny))
82 } else {
83 None
84 }
85 }
86 fn drag_end(&mut self) {
87 self.dragging = false;
88 }
89 fn set_drag_bounds(&mut self, bx: f32, by: f32, bw: f32, bh: f32) {
90 self.bounds = Some((bx, by, bw, bh));
91 }
92 }