native_windows_gui/controls/
button.rs1use winapi::um::winuser::{WS_DISABLED, BS_ICON, BS_BITMAP, BS_NOTIFY, WS_VISIBLE, WS_TABSTOP, WS_CHILD};
2use crate::win32::{
3 base_helper::check_hwnd,
4 window_helper as wh,
5 resources_helper as rh
6};
7use crate::{NwgError, Font, Bitmap, Icon};
8use super::{ControlBase, ControlHandle};
9
10const NOT_BOUND: &'static str = "Button is not yet bound to a winapi object";
11const BAD_HANDLE: &'static str = "INTERNAL ERROR: Button handle is not HWND!";
12
13
14bitflags! {
15 pub struct ButtonFlags: u32 {
27 const NONE = 0;
28 const VISIBLE = WS_VISIBLE;
29 const DISABLED = WS_DISABLED;
30 const ICON = BS_ICON;
31 const BITMAP = BS_BITMAP;
32 const NOTIFY = BS_NOTIFY;
33 const TAB_STOP = WS_TABSTOP;
34 }
35}
36
37#[derive(Default, Eq, PartialEq)]
77pub struct Button {
78 pub handle: ControlHandle
79}
80
81impl Button {
82
83 pub fn builder<'a>() -> ButtonBuilder<'a> {
84 ButtonBuilder {
85 text: "Button",
86 size: (100, 25),
87 position: (0, 0),
88 enabled: true,
89 flags: None,
90 ex_flags: 0,
91 font: None,
92 parent: None,
93 bitmap: None,
94 icon: None,
95 focus: false
96 }
97 }
98
99 pub fn click(&self) {
101 use winapi::um::winuser::BM_CLICK;
102 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
103 wh::send_message(handle, BM_CLICK, 0, 0);
104 }
105
106 pub fn set_bitmap<'a>(&self, image: Option<&'a Bitmap>) {
109 use winapi::um::winuser::{BM_SETIMAGE, IMAGE_BITMAP};
110 use winapi::shared::minwindef::{WPARAM, LPARAM};
111
112 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
113
114 let image_handle = image.map(|i| i.handle as LPARAM).unwrap_or(0);
115 wh::send_message(handle, BM_SETIMAGE, IMAGE_BITMAP as WPARAM, image_handle);
116 }
117
118 pub fn set_icon<'a>(&self, image: Option<&'a Icon>) {
121 use winapi::um::winuser::{BM_SETIMAGE, IMAGE_ICON};
122 use winapi::shared::minwindef::{WPARAM, LPARAM};
123
124 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
125
126 let image_handle = image.map(|i| i.handle as LPARAM).unwrap_or(0);
127 wh::send_message(handle, BM_SETIMAGE, IMAGE_ICON as WPARAM, image_handle);
128 }
129
130 pub fn image<'a>(&self, bitmap: &mut Option<Bitmap>, icon: &mut Option<Icon>) {
134 use winapi::um::winuser::{BM_GETIMAGE, IMAGE_BITMAP, IMAGE_ICON};
135 use winapi::shared::minwindef::WPARAM;
136 use winapi::shared::windef::HBITMAP;
137 use winapi::um::winnt::HANDLE;
138
139 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
140
141 let bitmap_handle = wh::send_message(handle, BM_GETIMAGE, IMAGE_BITMAP as WPARAM, 0);
142 let icon_handle = wh::send_message(handle, BM_GETIMAGE, IMAGE_ICON as WPARAM, 0);
143
144 *bitmap = None;
145 *icon = None;
146
147 if bitmap_handle != 0 && rh::is_bitmap(bitmap_handle as HBITMAP) {
148 *bitmap = Some(Bitmap { handle: bitmap_handle as HANDLE, owned: false });
149 } else if icon_handle != 0 {
150 *icon = Some(Icon { handle: icon_handle as HANDLE, owned: false });
151 }
152 }
153
154 pub fn font(&self) -> Option<Font> {
156 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
157
158 let font_handle = wh::get_window_font(handle);
159 if font_handle.is_null() {
160 None
161 } else {
162 Some(Font { handle: font_handle })
163 }
164 }
165
166 pub fn set_font(&self, font: Option<&Font>) {
168 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
169 unsafe { wh::set_window_font(handle, font.map(|f| f.handle), true); }
170 }
171
172 pub fn focus(&self) -> bool {
174 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
175 unsafe { wh::get_focus(handle) }
176 }
177
178 pub fn set_focus(&self) {
180 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
181 unsafe { wh::set_focus(handle); }
182 }
183
184 pub fn enabled(&self) -> bool {
186 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
187 unsafe { wh::get_window_enabled(handle) }
188 }
189
190 pub fn set_enabled(&self, v: bool) {
192 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
193 unsafe { wh::set_window_enabled(handle, v) }
194 }
195
196 pub fn visible(&self) -> bool {
199 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
200 unsafe { wh::get_window_visibility(handle) }
201 }
202
203 pub fn set_visible(&self, v: bool) {
205 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
206 unsafe { wh::set_window_visibility(handle, v) }
207 }
208
209 pub fn size(&self) -> (u32, u32) {
211 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
212 unsafe { wh::get_window_size(handle) }
213 }
214
215 pub fn set_size(&self, x: u32, y: u32) {
217 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
218 unsafe { wh::set_window_size(handle, x, y, false) }
219 }
220
221 pub fn position(&self) -> (i32, i32) {
223 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
224 unsafe { wh::get_window_position(handle) }
225 }
226
227 pub fn set_position(&self, x: i32, y: i32) {
229 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
230 unsafe { wh::set_window_position(handle, x, y) }
231 }
232
233 pub fn text(&self) -> String {
235 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
236 unsafe { wh::get_window_text(handle) }
237 }
238
239 pub fn set_text<'a>(&self, v: &'a str) {
241 let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
242 unsafe { wh::set_window_text(handle, v) }
243 }
244
245 pub fn class_name(&self) -> &'static str {
247 "BUTTON"
248 }
249
250 pub fn flags(&self) -> u32 {
252 WS_VISIBLE | WS_TABSTOP | BS_NOTIFY
253 }
254
255 pub fn forced_flags(&self) -> u32 {
257 WS_CHILD
258 }
259
260}
261
262impl Drop for Button {
263 fn drop(&mut self) {
264 self.handle.destroy();
265 }
266}
267
268pub struct ButtonBuilder<'a> {
269 text: &'a str,
270 size: (i32, i32),
271 position: (i32, i32),
272 enabled: bool,
273 flags: Option<ButtonFlags>,
274 ex_flags: u32,
275 font: Option<&'a Font>,
276 bitmap: Option<&'a Bitmap>,
277 icon: Option<&'a Icon>,
278 parent: Option<ControlHandle>,
279 focus: bool,
280}
281
282impl<'a> ButtonBuilder<'a> {
283
284 pub fn flags(mut self, flags: ButtonFlags) -> ButtonBuilder<'a> {
285 self.flags = Some(flags);
286 self
287 }
288
289 pub fn ex_flags(mut self, flags: u32) -> ButtonBuilder<'a> {
290 self.ex_flags = flags;
291 self
292 }
293
294 pub fn text(mut self, text: &'a str) -> ButtonBuilder<'a> {
295 self.text = text;
296 self
297 }
298
299 pub fn size(mut self, size: (i32, i32)) -> ButtonBuilder<'a> {
300 self.size = size;
301 self
302 }
303
304 pub fn position(mut self, pos: (i32, i32)) -> ButtonBuilder<'a> {
305 self.position = pos;
306 self
307 }
308
309 pub fn enabled(mut self, e: bool) -> ButtonBuilder<'a> {
310 self.enabled = e;
311 self
312 }
313
314 pub fn font(mut self, font: Option<&'a Font>) -> ButtonBuilder<'a> {
315 self.font = font;
316 self
317 }
318
319 pub fn bitmap(mut self, bit: Option<&'a Bitmap>) -> ButtonBuilder<'a> {
320 self.bitmap = bit;
321 self
322 }
323
324 pub fn icon(mut self, ico: Option<&'a Icon>) -> ButtonBuilder<'a> {
325 self.icon = ico;
326 self
327 }
328
329 pub fn focus(mut self, focus: bool) -> ButtonBuilder<'a> {
330 self.focus = focus;
331 self
332 }
333
334 pub fn parent<C: Into<ControlHandle>>(mut self, p: C) -> ButtonBuilder<'a> {
335 self.parent = Some(p.into());
336 self
337 }
338
339 pub fn build(self, out: &mut Button) -> Result<(), NwgError> {
340 let flags = self.flags.map(|f| f.bits()).unwrap_or(out.flags());
341
342 let parent = match self.parent {
343 Some(p) => Ok(p),
344 None => Err(NwgError::no_parent("Button"))
345 }?;
346
347 *out = Button::default();
349
350 out.handle = ControlBase::build_hwnd()
351 .class_name(out.class_name())
352 .forced_flags(out.forced_flags())
353 .flags(flags)
354 .ex_flags(self.ex_flags)
355 .size(self.size)
356 .position(self.position)
357 .text(self.text)
358 .parent(Some(parent))
359 .build()?;
360
361 if self.font.is_some() {
362 out.set_font(self.font);
363 } else {
364 out.set_font(Font::global_default().as_ref());
365 }
366
367 out.set_enabled(self.enabled);
368
369 if self.bitmap.is_some() {
370 out.set_bitmap(self.bitmap);
371 } else if self.icon.is_some() {
372 out.set_icon(self.icon);
373 }
374
375 if self.focus {
376 out.set_focus();
377 }
378
379 Ok(())
380 }
381
382}