Skip to main content

native_windows_gui2/controls/
frame.rs

1use super::{ControlBase, ControlHandle};
2use crate::NwgError;
3use crate::win32::base_helper::check_hwnd;
4use crate::win32::window_helper as wh;
5use winapi::um::winuser::{
6    WS_BORDER, WS_CHILD, WS_CLIPCHILDREN, WS_DISABLED, WS_EX_CONTROLPARENT, WS_VISIBLE,
7};
8
9const NOT_BOUND: &'static str = "Frame is not yet bound to a winapi object";
10const BAD_HANDLE: &'static str = "INTERNAL ERROR: Frame handle is not HWND!";
11
12bitflags! {
13    /**
14        The frame flags
15
16        * NONE:     No flags. Equivalent to a invisible frame without borders.
17        * VISIBLE:  The frame is immediatly visible after creation
18        * DISABLED: The frame chidlren cannot be interacted with by the user.
19        * BORDER:   The frame has a thin black border
20    */
21    pub struct FrameFlags: u32 {
22        const NONE = 0;
23        const VISIBLE = WS_VISIBLE;
24        const DISABLED = WS_DISABLED;
25        const BORDER = WS_BORDER;
26    }
27}
28
29/**
30A frame is a rectangle containing children controls. Frame is implemented as a custom control.
31
32Requires the `frame` feature.
33
34**Builder parameters:**
35  * `parent`:   **Required.** The frame parent container.
36  * `size`:     The frame size.
37  * `position`: The frame position.
38  * `enabled`:  If the frame children can be used by the user.
39  * `flags`:    A combination of the FrameFlags values.
40  * `ex_flags`: A combination of win32 window extended flags. Unlike `flags`, ex_flags must be used straight from winapi
41
42**Control events:**
43  * `MousePress(_)`: Generic mouse press events on the button
44  * `OnMouseMove`: Generic mouse mouse event
45  * `OnMouseWheel`: Generic mouse wheel event
46*/
47#[derive(Default, PartialEq, Eq)]
48pub struct Frame {
49    pub handle: ControlHandle,
50}
51
52impl Frame {
53    pub fn builder() -> FrameBuilder {
54        FrameBuilder {
55            size: (100, 25),
56            position: (0, 0),
57            enabled: true,
58            flags: None,
59            ex_flags: 0,
60            parent: None,
61        }
62    }
63
64    /// Returns true if the control currently has the keyboard focus
65    pub fn focus(&self) -> bool {
66        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
67        wh::get_focus(handle)
68    }
69
70    /// Sets the keyboard focus on the button.
71    pub fn set_focus(&self) {
72        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
73
74        wh::set_focus(handle);
75    }
76
77    /// Returns true if the control user can interact with the control, return false otherwise
78    pub fn enabled(&self) -> bool {
79        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
80        wh::get_window_enabled(handle)
81    }
82
83    /// Enable or disable the control
84    pub fn set_enabled(&self, v: bool) {
85        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
86        wh::set_window_enabled(handle, v)
87    }
88
89    /// Returns true if the control is visible to the user. Will return true even if the
90    /// control is outside of the parent client view (ex: at the position (10000, 10000))
91    pub fn visible(&self) -> bool {
92        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
93        wh::get_window_visibility(handle)
94    }
95
96    /// Show or hide the control to the user
97    pub fn set_visible(&self, v: bool) {
98        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
99        wh::set_window_visibility(handle, v)
100    }
101
102    /// Returns the size of the button in the parent window
103    pub fn size(&self) -> (u32, u32) {
104        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
105        wh::get_window_size(handle)
106    }
107
108    /// Sets the size of the button in the parent window
109    pub fn set_size(&self, x: u32, y: u32) {
110        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
111        wh::set_window_size(handle, x, y, false)
112    }
113
114    /// Returns the position of the button in the parent window
115    pub fn position(&self) -> (i32, i32) {
116        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
117        wh::get_window_position(handle)
118    }
119
120    /// Sets the position of the button in the parent window
121    pub fn set_position(&self, x: i32, y: i32) {
122        let handle = check_hwnd(&self.handle, NOT_BOUND, BAD_HANDLE);
123        wh::set_window_position(handle, x, y)
124    }
125
126    /// Winapi class name used during control creation
127    pub fn class_name(&self) -> &'static str {
128        "NWG_FRAME"
129    }
130
131    /// Winapi base flags used during window creation
132    pub fn flags(&self) -> u32 {
133        WS_VISIBLE | WS_BORDER
134    }
135
136    /// Winapi flags required by the control
137    pub fn forced_flags(&self) -> u32 {
138        WS_CHILD | WS_CLIPCHILDREN
139    }
140}
141
142impl Drop for Frame {
143    fn drop(&mut self) {
144        self.handle.destroy();
145    }
146}
147pub struct FrameBuilder {
148    size: (i32, i32),
149    position: (i32, i32),
150    enabled: bool,
151    flags: Option<FrameFlags>,
152    ex_flags: u32,
153    parent: Option<ControlHandle>,
154}
155
156impl FrameBuilder {
157    pub fn flags(mut self, flags: FrameFlags) -> FrameBuilder {
158        self.flags = Some(flags);
159        self
160    }
161
162    pub fn ex_flags(mut self, flags: u32) -> FrameBuilder {
163        self.ex_flags = flags;
164        self
165    }
166
167    pub fn size(mut self, size: (i32, i32)) -> FrameBuilder {
168        self.size = size;
169        self
170    }
171
172    pub fn position(mut self, pos: (i32, i32)) -> FrameBuilder {
173        self.position = pos;
174        self
175    }
176
177    pub fn enabled(mut self, e: bool) -> FrameBuilder {
178        self.enabled = e;
179        self
180    }
181
182    pub fn parent<C: Into<ControlHandle>>(mut self, p: C) -> FrameBuilder {
183        self.parent = Some(p.into());
184        self
185    }
186
187    pub fn build(self, out: &mut Frame) -> Result<(), NwgError> {
188        let flags = self.flags.map(|f| f.bits()).unwrap_or(out.flags());
189
190        let parent = match self.parent {
191            Some(p) => Ok(p),
192            None => Err(NwgError::no_parent("Frame")),
193        }?;
194
195        *out = Default::default();
196
197        out.handle = ControlBase::build_hwnd()
198            .class_name(out.class_name())
199            .forced_flags(out.forced_flags())
200            .flags(flags)
201            .ex_flags(WS_EX_CONTROLPARENT | self.ex_flags)
202            .size(self.size)
203            .position(self.position)
204            .parent(Some(parent))
205            .build()?;
206
207        out.set_enabled(self.enabled);
208
209        Ok(())
210    }
211}