git.lucas.co / cce-ui
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 }