native_windows_gui/controls/
control_base.rs

1use winapi::shared::minwindef::DWORD;
2use winapi::shared::windef::{HWND};
3use super::ControlHandle;
4use crate::win32::window::{build_hwnd_control, build_timer, build_notice};
5use crate::{NwgError};
6
7#[cfg(feature = "menu")] use crate::win32::menu::build_hmenu_control;
8#[cfg(feature = "menu")] use winapi::shared::windef::{HMENU};
9
10const NOTICE: u32 = 1;
11const TRAY: u32 = 2;
12
13
14/**
15Control base is a low level interface to create base Windows handle (HWND, HMENU, TIMER, etc).
16This is used internally by every controls.
17
18
19```rust
20use native_windows_gui as nwg;
21
22fn basic_stuff(window: &nwg::Window) -> Result<(), nwg::NwgError> {
23    nwg::ControlBase::build_hwnd()
24        .class_name("BUTTON")
25        .forced_flags(0)
26        .flags(0)
27        .size((100, 100))
28        .position((100, 100))
29        .text("HELLO")
30        .parent(Some(window.handle))
31        .build()?;
32
33    #[cfg(feature = "menu")]
34    nwg::ControlBase::build_hmenu()
35        .text("Item")
36        .item(true)
37        .parent(window.handle)
38        .build()?;
39
40    Ok(())
41}
42```
43
44*/
45#[derive(Debug, Clone)]
46pub struct ControlBase;
47
48impl ControlBase {
49
50    pub fn build_hwnd() -> HwndBuilder {
51        HwndBuilder::default()
52    }
53
54    #[cfg(feature = "menu")]
55    pub fn build_hmenu() -> HmenuBuilder {
56        HmenuBuilder::default()
57    }
58
59    pub fn build_timer() -> TimerBuilder {
60        TimerBuilder::default()
61    }
62
63    pub fn build_notice() -> OtherBuilder {
64        OtherBuilder {
65            parent: None,
66            ty: NOTICE
67        }
68    }
69
70    pub fn build_tray_notification() -> OtherBuilder {
71        OtherBuilder {
72            parent: None,
73            ty: TRAY
74        }
75    }
76}
77
78
79/// Low level HWND builder. Instanced by `ControlBase::build_hwnd`.
80#[derive(Default)]
81pub struct HwndBuilder {
82    class_name: String,
83    text: Option<String>,
84    size: Option<(i32, i32)>,
85    pos: Option<(i32, i32)>,
86    forced_flags: DWORD,
87    flags: Option<DWORD>,
88    ex_flags: Option<DWORD>,
89    parent: Option<HWND>
90}
91
92impl HwndBuilder {
93
94    pub fn class_name<'a>(mut self, name: &'a str) -> HwndBuilder {
95        self.class_name = name.to_string();
96        self
97    }
98
99    pub fn text<'a>(mut self, text: &'a str) -> HwndBuilder {
100        self.text = Some(text.to_string());
101        self
102    }
103
104    pub fn size(mut self, size: (i32, i32)) -> HwndBuilder {
105        self.size = Some(size);
106        self
107    }
108
109    pub fn position(mut self, pos: (i32, i32)) -> HwndBuilder {
110        self.pos = Some(pos);
111        self
112    }
113
114    pub fn flags(mut self, flags: u32) -> HwndBuilder {
115        self.flags = Some(flags as DWORD);
116        self
117    }
118
119    pub fn ex_flags(mut self, flags: u32) -> HwndBuilder {
120        self.ex_flags = Some(flags as DWORD);
121        self
122    }
123
124    pub fn forced_flags(mut self, flags: u32) -> HwndBuilder {
125        self.forced_flags = flags as DWORD;
126        self
127    }
128
129    pub fn parent(mut self, parent: Option<ControlHandle>) -> HwndBuilder {
130        match parent {
131            Some(p) => { self.parent = p.hwnd(); }
132            None => { self.parent = None; }
133        }
134        self
135    }
136
137    pub fn build(self) -> Result<ControlHandle, NwgError> {
138        let handle = unsafe { build_hwnd_control(
139            &self.class_name,
140            self.text.as_ref().map(|v| v as &str),
141            self.size,
142            self.pos,
143            self.flags,
144            self.ex_flags,
145            self.forced_flags,
146            self.parent
147        )? };
148
149        Ok(handle)
150    }
151}
152
153
154/// Low level HMENU builder. Instanced by `ControlBase::build_hmenu`.
155#[derive(Default)]
156#[cfg(feature = "menu")]
157pub struct HmenuBuilder {
158    text: Option<String>,
159    item: bool,
160    separator: bool,
161    popup: bool,
162    parent_menu: Option<HMENU>,
163    parent_window: Option<HWND>,
164}
165
166#[cfg(feature = "menu")]
167impl HmenuBuilder {
168
169    /// Set the text of the Menu
170    pub fn text<'a>(mut self, text: &'a str) -> HmenuBuilder {
171        self.text = Some(text.to_string());
172        self
173    }
174
175    /// Set if the menu should be an item or a menu
176    pub fn item(mut self, i: bool) -> HmenuBuilder {
177        self.item = i;
178        self
179    }
180
181    /// Set if the menu item should be a separator
182    pub fn separator(mut self, i: bool) -> HmenuBuilder {
183        self.separator = i;
184        self
185    }
186
187    /// Set if the menu item should be a separator
188    pub fn popup(mut self, i: bool) -> HmenuBuilder {
189        self.popup = i;
190        self
191    }
192
193    /// Set the parent of the menu. Can be a window or another menu.
194    pub fn parent(mut self, parent: ControlHandle) -> HmenuBuilder {
195        match parent {
196            ControlHandle::Hwnd(hwnd) => { self.parent_window = Some(hwnd); }
197            ControlHandle::Menu(_parent, menu) => { self.parent_menu = Some(menu); }
198            ControlHandle::PopMenu(_hwnd, menu) => { self.parent_menu = Some(menu); },
199            _ => {}
200        }
201
202        self
203    }
204
205    pub fn build(self) -> Result<ControlHandle, NwgError> {
206        let handle = unsafe { build_hmenu_control(
207            self.text,
208            self.item,
209            self.separator,
210            self.popup,
211            self.parent_menu,
212            self.parent_window
213        )? };
214
215        Ok(handle)
216    }
217
218}
219
220
221/// Low level timer builder. Instanced by `ControlBase::build_timer`.
222#[derive(Default)]
223pub struct TimerBuilder {
224    parent: Option<HWND>,
225    interval: u32,
226    stopped: bool
227}
228
229impl TimerBuilder {
230
231    pub fn stopped(mut self, v: bool) -> TimerBuilder {
232        self.stopped = v;
233        self
234    }
235
236    pub fn interval(mut self, i: u32) -> TimerBuilder {
237        self.interval = i;
238        self
239    }
240
241    pub fn parent(mut self, parent: Option<ControlHandle>) -> TimerBuilder {
242        match parent {
243            Some(p) => { self.parent = p.hwnd(); }
244            None => panic!("Timer parent must be HWND")
245        }
246        self
247    }
248
249    pub fn build(self) -> Result<ControlHandle, NwgError> {
250        let handle = unsafe { build_timer(
251            self.parent.expect("Internal error. Timer without window parent"),
252            self.interval,
253            self.stopped
254        ) };
255        Ok(handle)
256    }
257
258}
259
260
261/// Low level builder for controls without specific winapi contructors. 
262/// Instanced by `ControlBase::build_notice` or `ControlBase::build_tray_notification`.
263#[derive(Default)]
264pub struct OtherBuilder {
265    parent: Option<HWND>,
266    ty: u32
267}
268
269impl OtherBuilder {
270
271    pub fn parent(mut self, parent: HWND) -> OtherBuilder {
272        self.parent = Some(parent);
273        self
274    }
275
276    pub fn build(self) -> Result<ControlHandle, NwgError> {
277        let handle = self.parent.expect("Internal error. Control without window parent");
278        let base = match self.ty {
279            NOTICE => build_notice(handle),
280            TRAY => ControlHandle::SystemTray(handle),
281            _ => unreachable!()
282        };
283
284        Ok(base)
285    }
286
287}