dear_imgui_rs/widget/misc/
invisible_button.rs1use super::validation::assert_finite_vec2;
2use crate::Ui;
3use crate::sys;
4
5fn validate_invisible_button_flags(caller: &str, flags: ButtonFlags) {
6 let unsupported = flags.bits() & !ButtonFlags::all().bits();
7 assert!(
8 unsupported == 0,
9 "{caller} received unsupported ImGuiButtonFlags bits: 0x{unsupported:X}"
10 );
11}
12
13fn validate_invisible_button_options(caller: &str, options: InvisibleButtonOptions) {
14 validate_invisible_button_flags(caller, options.flags);
15 let unsupported_buttons =
16 options.mouse_buttons.bits() & !InvisibleButtonMouseButtons::all().bits();
17 assert!(
18 unsupported_buttons == 0,
19 "{caller} received unsupported ImGuiButtonFlags mouse-button bits: 0x{unsupported_buttons:X}"
20 );
21 assert!(
22 !options.mouse_buttons.is_empty(),
23 "{caller} requires at least one invisible-button mouse button"
24 );
25}
26
27fn validate_arrow_direction(caller: &str, dir: crate::Direction) {
28 assert!(
29 matches!(
30 dir,
31 crate::Direction::Left
32 | crate::Direction::Right
33 | crate::Direction::Up
34 | crate::Direction::Down
35 ),
36 "{caller} direction must be Left, Right, Up, or Down"
37 );
38}
39
40bitflags::bitflags! {
41 #[repr(transparent)]
46 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
47 pub struct ButtonFlags: i32 {
48 const NONE = 0;
50 const ALLOW_OVERLAP = sys::ImGuiButtonFlags_AllowOverlap as i32;
52 const ENABLE_NAV = sys::ImGuiButtonFlags_EnableNav as i32;
54 }
55}
56
57bitflags::bitflags! {
58 #[repr(transparent)]
60 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
61 pub struct InvisibleButtonMouseButtons: i32 {
62 const LEFT = sys::ImGuiButtonFlags_MouseButtonLeft as i32;
64 const RIGHT = sys::ImGuiButtonFlags_MouseButtonRight as i32;
66 const MIDDLE = sys::ImGuiButtonFlags_MouseButtonMiddle as i32;
68 }
69}
70
71impl Default for InvisibleButtonMouseButtons {
72 fn default() -> Self {
73 Self::LEFT
74 }
75}
76
77impl From<crate::MouseButton> for InvisibleButtonMouseButtons {
78 fn from(button: crate::MouseButton) -> Self {
79 match button {
80 crate::MouseButton::Left => Self::LEFT,
81 crate::MouseButton::Right => Self::RIGHT,
82 crate::MouseButton::Middle => Self::MIDDLE,
83 crate::MouseButton::Extra1 | crate::MouseButton::Extra2 => {
84 panic!("Dear ImGui invisible buttons only support left, right, and middle buttons")
85 }
86 }
87 }
88}
89
90#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
92pub struct InvisibleButtonOptions {
93 pub flags: ButtonFlags,
94 pub mouse_buttons: InvisibleButtonMouseButtons,
95}
96
97impl InvisibleButtonOptions {
98 pub const fn new() -> Self {
99 Self {
100 flags: ButtonFlags::NONE,
101 mouse_buttons: InvisibleButtonMouseButtons::LEFT,
102 }
103 }
104
105 pub fn flags(mut self, flags: ButtonFlags) -> Self {
106 self.flags = flags;
107 self
108 }
109
110 pub fn mouse_buttons(mut self, buttons: InvisibleButtonMouseButtons) -> Self {
111 self.mouse_buttons = buttons;
112 self
113 }
114
115 pub fn mouse_button(mut self, button: crate::MouseButton) -> Self {
116 self.mouse_buttons = button.into();
117 self
118 }
119
120 pub fn bits(self) -> i32 {
122 self.raw()
123 }
124
125 #[inline]
126 pub(crate) fn raw(self) -> i32 {
127 self.flags.bits() | self.mouse_buttons.bits()
128 }
129}
130
131impl Default for InvisibleButtonOptions {
132 fn default() -> Self {
133 Self::new()
134 }
135}
136
137impl From<ButtonFlags> for InvisibleButtonOptions {
138 fn from(flags: ButtonFlags) -> Self {
139 Self::new().flags(flags)
140 }
141}
142
143impl From<InvisibleButtonMouseButtons> for InvisibleButtonOptions {
144 fn from(buttons: InvisibleButtonMouseButtons) -> Self {
145 Self::new().mouse_buttons(buttons)
146 }
147}
148
149impl From<crate::MouseButton> for InvisibleButtonOptions {
150 fn from(button: crate::MouseButton) -> Self {
151 Self::new().mouse_button(button)
152 }
153}
154
155pub use crate::Direction as ArrowDirection;
157
158impl Ui {
159 #[doc(alias = "InvisibleButton")]
161 pub fn invisible_button(&self, str_id: impl AsRef<str>, size: impl Into<[f32; 2]>) -> bool {
162 self.invisible_button_flags(str_id, size, crate::widget::ButtonFlags::NONE)
163 }
164
165 #[doc(alias = "InvisibleButton")]
170 pub fn invisible_button_flags(
171 &self,
172 str_id: impl AsRef<str>,
173 size: impl Into<[f32; 2]>,
174 flags: crate::widget::ButtonFlags,
175 ) -> bool {
176 validate_invisible_button_flags("Ui::invisible_button_flags()", flags);
177 self.invisible_button_raw(str_id, size, flags.bits())
178 }
179
180 #[doc(alias = "InvisibleButton")]
182 pub fn invisible_button_options(
183 &self,
184 str_id: impl AsRef<str>,
185 size: impl Into<[f32; 2]>,
186 options: impl Into<crate::widget::InvisibleButtonOptions>,
187 ) -> bool {
188 let options = options.into();
189 validate_invisible_button_options("Ui::invisible_button_options()", options);
190 self.invisible_button_raw(str_id, size, options.raw())
191 }
192
193 fn invisible_button_raw(
194 &self,
195 str_id: impl AsRef<str>,
196 size: impl Into<[f32; 2]>,
197 flags: i32,
198 ) -> bool {
199 let id_ptr = self.scratch_txt(str_id);
200 let size = size.into();
201 assert_finite_vec2("Ui::invisible_button()", "size", size);
202 let size_vec: sys::ImVec2 = size.into();
203 unsafe { sys::igInvisibleButton(id_ptr, size_vec, flags) }
204 }
205
206 #[doc(alias = "ArrowButton")]
208 pub fn arrow_button(&self, str_id: impl AsRef<str>, dir: crate::Direction) -> bool {
209 validate_arrow_direction("Ui::arrow_button()", dir);
210 let id_ptr = self.scratch_txt(str_id);
211 unsafe { sys::igArrowButton(id_ptr, dir as i32) }
212 }
213}