native_windows_gui/controls/
frame.rs

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