macroquad/ui/widgets/
group.rs1use crate::{
2 math::{Rect, Vec2},
3 ui::{Drag, DragState, ElementState, Id, Layout, Ui},
4};
5
6#[derive(Debug, Clone)]
7pub struct Group {
8 id: Id,
9 position: Option<Vec2>,
10 layout: Layout,
11 size: Vec2,
12 draggable: bool,
13 highlight: bool,
14 hoverable: bool,
15}
16
17impl Group {
18 pub const fn new(id: Id, size: Vec2) -> Group {
19 Group {
20 id,
21 size,
22 position: None,
23 layout: Layout::Horizontal,
24 draggable: false,
25 highlight: false,
26 hoverable: false,
27 }
28 }
29
30 pub const fn position(self, position: Vec2) -> Group {
31 Group {
32 position: Some(position),
33 ..self
34 }
35 }
36
37 pub const fn layout(self, layout: Layout) -> Group {
38 Group { layout, ..self }
39 }
40
41 pub const fn draggable(self, draggable: bool) -> Group {
42 Group { draggable, ..self }
43 }
44
45 pub const fn hoverable(self, hoverable: bool) -> Group {
46 Group { hoverable, ..self }
47 }
48
49 pub const fn highlight(self, highlight: bool) -> Group {
50 Group { highlight, ..self }
51 }
52
53 pub fn ui<F: FnOnce(&mut Ui)>(self, ui: &mut Ui, f: F) -> Drag {
54 let token = self.begin(ui);
55 f(ui);
56 token.end(ui)
57 }
58
59 pub fn begin(self, ui: &mut Ui) -> GroupToken {
60 let mut drag = Drag::No;
61
62 let parent = ui.get_active_window_context();
63
64 let parent_rect = parent.window.content_rect();
65
66 parent.window.childs.push(self.id);
67
68 let pos = parent
69 .window
70 .cursor
71 .fit(self.size, self.position.map_or(self.layout, Layout::Free));
72 let rect = Rect::new(pos.x, pos.y, self.size.x, self.size.y);
73 let parent_id = Some(parent.window.id);
74
75 let mut context = ui.begin_window(self.id, parent_id, pos, self.size, false, true);
76
77 let hovered =
78 (self.hoverable || self.draggable) && rect.contains(context.input.mouse_position);
79
80 if self.draggable && context.dragging.is_none() && hovered && context.input.click_down {
81 *context.dragging = Some((self.id, DragState::Clicked(context.input.mouse_position)));
82 }
83
84 if let Some((id, DragState::Clicked(orig))) = context.dragging {
85 if *id == self.id
86 && context.input.is_mouse_down
87 && context.input.mouse_position.distance(*orig) > 5.
88 {
89 *context.dragging = Some((self.id, DragState::Dragging(*orig)));
90 }
91 if context.input.is_mouse_down == false {
92 *context.dragging = None;
93 }
94 }
95
96 if let Some((id, DragState::Dragging(_))) = context.dragging {
97 let id = *id;
98
99 if id == self.id {
100 drag = Drag::Dragging(
101 context.input.mouse_position,
102 *context.drag_hovered_previous_frame,
103 );
104
105 if context.input.is_mouse_down == false {
106 *context.dragging = None;
107 drag = Drag::Dropped(
108 context.input.mouse_position,
109 *context.drag_hovered_previous_frame,
110 );
111 }
112 }
113
114 if id != self.id && hovered {
115 *context.drag_hovered = Some(self.id);
116 }
117 }
118
119 context.window.painter.clip(parent_rect);
120
121 context.scroll_area();
122
123 let clip_rect = context.window.content_rect();
124 context.window.painter.clip(clip_rect);
125 context.window.painter.draw_rect(
126 rect,
127 context.style.group_style.color(ElementState {
128 focused: context.focused,
129 hovered,
130 clicked: false,
131 selected: self.highlight,
132 }),
133 None,
134 );
135
136 GroupToken {
137 draggable: self.draggable,
138 drag,
139 pos,
140 size: self.size,
141 }
142 }
143}
144
145#[must_use = "Must call `.end()` to finish Group"]
146pub struct GroupToken {
147 draggable: bool,
148 drag: Drag,
149 pos: Vec2,
150 size: Vec2,
151}
152
153impl GroupToken {
154 pub fn end(self, ui: &mut Ui) -> Drag {
155 let context = ui.get_active_window_context();
156
157 context.window.painter.clip(None);
158
159 if context.focused && self.draggable {
160 if
161 context.input.is_mouse_down
163 && Rect::new(self.pos.x, self.pos.y, self.size.x, self.size.y)
164 .contains(context.input.mouse_position)
165 {
166 }
171 }
172
173 ui.end_window();
174
175 self.drag
176 }
177}
178
179impl Ui {
180 pub fn group<F: FnOnce(&mut Ui)>(&mut self, id: Id, size: Vec2, f: F) -> Drag {
181 Group::new(id, size).ui(self, f)
182 }
183}