native_windows_gui2/controls/
control_base.rs

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