GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
src/widget/display/splitter.rs (2.7K)
1 //! Narrow-trait pane splitter (Phase 5i leaf sweep). A self-moving widget: dragging repositions
2 //! the splitter itself via [`Input::drag_reposition`] (the adapter applies the new origin to the
3 //! base rect). Hover/drag drive the color, tracked from the forwarded events.
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 Splitter {
11 hovered: bool,
12 dragging: bool,
13 drag_ox: f32,
14 }
15
16 impl Splitter {
17 pub fn new(w: f32) -> Adapted<Splitter> {
18 let mut s = Adapted::new(Splitter { hovered: false, dragging: false, drag_ox: 0.0 });
19 WidgetHost::set_rect(&mut s, 0.0, 0.0, w, 0.0);
20 s
21 }
22 }
23
24 impl Layout for Splitter {}
25
26 impl Paint for Splitter {
27 fn color(&self) -> [f32; 4] {
28 if self.dragging {
29 colors::SPLITTER_DRAG
30 } else if self.hovered {
31 colors::SPLITTER_HOVER
32 } else {
33 colors::SPLITTER_IDLE
34 }
35 }
36
37 /// The bar as a capsule: fully rounded ends on its short side.
38 fn paint(&self, rect: Rect, ctx: &mut PaintCtx) {
39 let color = self.color();
40 if color[3].abs() > 0.001 {
41 let r = rect.width.min(rect.height) * 0.5;
42 ctx.rounded_rect(rect, r, (true, true, true, true), color);
43 }
44 }
45 }
46
47 impl Input for Splitter {
48 fn on_event(&mut self, event: &Event, ectx: &mut EventCtx) -> bool {
49 match event {
50 Event::MouseButton { button: MouseButton::Left, state: ElementState::Pressed, x, .. } => {
51 self.dragging = true;
52 self.drag_ox = x - ectx.rect.x;
53 true
54 }
55 Event::MouseButton { button: MouseButton::Left, state: ElementState::Released, .. } => {
56 std::mem::take(&mut self.dragging)
57 }
58 Event::MouseEnter => {
59 self.hovered = true;
60 false
61 }
62 Event::MouseLeave => {
63 self.hovered = false;
64 false
65 }
66 _ => false,
67 }
68 }
69
70 fn draggable(&self, _rect: Rect) -> bool {
71 true
72 }
73 fn is_dragging(&self) -> bool {
74 self.dragging
75 }
76 fn drag_begin(&mut self, px: f32, _py: f32, rect: Rect) {
77 self.dragging = true;
78 self.drag_ox = px - rect.x;
79 }
80 fn drag_reposition(&mut self, px: f32, _py: f32, rect: Rect) -> Option<(f32, f32)> {
81 let new_x = px - self.drag_ox;
82 if (new_x - rect.x).abs() > 0.5 {
83 Some((new_x, rect.y))
84 } else {
85 None
86 }
87 }
88 fn drag_end(&mut self) {
89 self.dragging = false;
90 }
91 }