native_windows_gui2/resources/
font_dialog.rs

1use super::FontInfo;
2use crate::NwgError;
3use crate::controls::ControlHandle;
4use std::cell::RefCell;
5use std::pin::Pin;
6use std::{mem, ptr};
7use winapi::shared::minwindef::DWORD;
8use winapi::um::commdlg::{CHOOSEFONTW, ChooseFontW};
9use winapi::um::wingdi::LOGFONTW;
10
11struct InnerFontDialog {
12    font: Pin<Box<LOGFONTW>>,
13    dialog: CHOOSEFONTW,
14}
15
16/// The Font dialog box lets the user choose attributes for a logical font, such as
17/// font family and associated font style, point size, effects (underline, strikeout),
18/// and a script (or character set).
19pub struct FontDialog {
20    data: RefCell<InnerFontDialog>,
21}
22
23impl FontDialog {
24    pub fn builder() -> FontDialogBuilder {
25        FontDialogBuilder {}
26    }
27
28    /// Execute the font dialog.
29    /// This function will return `true` if the user select a font or `false` if the dialog is cancelled
30    pub fn run<C: Into<ControlHandle>>(&self, owner: Option<C>) -> bool {
31        if owner.is_some() {
32            let ownder_handle = owner.unwrap().into();
33            self.data.borrow_mut().dialog.hwndOwner = ownder_handle
34                .hwnd()
35                .expect("Color dialog must be a window control");
36        }
37
38        unsafe {
39            let mut data = self.data.borrow_mut();
40            let data_ref = &mut data.dialog;
41            ChooseFontW(data_ref as *mut CHOOSEFONTW) > 0
42        }
43    }
44
45    /// Return a `FontInfo` structure that describe the font selected by the user.
46    pub fn font(&self) -> FontInfo {
47        let data: &InnerFontDialog = &self.data.borrow();
48        let font: &LOGFONTW = &data.font;
49
50        let end = font.lfFaceName.iter().position(|&c| c == 0).unwrap_or(0);
51        let name = String::from_utf16(&font.lfFaceName[0..end]).unwrap_or("ERROR".to_string());
52
53        FontInfo {
54            point_size: data.dialog.iPointSize as u32,
55            height: font.lfHeight as i32,
56            width: font.lfWidth as i32,
57            escapement: font.lfEscapement as i32,
58            orientation: font.lfOrientation as i32,
59            weight: font.lfWeight as i32,
60            italic: font.lfItalic == 1,
61            underline: font.lfUnderline == 1,
62            strike_out: font.lfStrikeOut == 1,
63            char_set: font.lfCharSet as u8,
64            out_precision: font.lfOutPrecision as u8,
65            clip_precision: font.lfClipPrecision as u8,
66            quality: font.lfQuality as u8,
67            pitch_and_family: font.lfPitchAndFamily as u8,
68            name,
69        }
70    }
71}
72
73/// The builder for a `FontDialog` object. Use `FontDialog::builder` to create one.
74pub struct FontDialogBuilder {}
75
76impl FontDialogBuilder {
77    pub fn build(self, _out: &mut FontDialog) -> Result<(), NwgError> {
78        Ok(())
79    }
80}
81
82impl Default for FontDialog {
83    fn default() -> FontDialog {
84        let dialog = CHOOSEFONTW {
85            lStructSize: mem::size_of::<CHOOSEFONTW>() as DWORD,
86            hwndOwner: ptr::null_mut(),
87            hDC: ptr::null_mut(),
88            lpLogFont: ptr::null_mut(),
89            iPointSize: 0,
90            Flags: 0,
91            rgbColors: 0,
92            lCustData: 0,
93            lpfnHook: None,
94            lpTemplateName: ptr::null(),
95            hInstance: ptr::null_mut(),
96            lpszStyle: ptr::null_mut(),
97            nFontType: 0,
98            ___MISSING_ALIGNMENT__: 0,
99            nSizeMin: 0,
100            nSizeMax: 0,
101        };
102
103        let font: LOGFONTW = unsafe { mem::zeroed() };
104
105        let mut inner = InnerFontDialog {
106            font: Box::pin(font),
107            dialog,
108        };
109
110        let mut font = inner.font.as_mut();
111        let cols_ref: &mut LOGFONTW = &mut font;
112        inner.dialog.lpLogFont = cols_ref as *mut LOGFONTW;
113
114        FontDialog {
115            data: RefCell::new(inner),
116        }
117    }
118}