zng_wgt_material_icons/
lib.rs

1#![doc(html_favicon_url = "https://zng-ui.github.io/res/zng-logo-icon.png")]
2#![doc(html_logo_url = "https://zng-ui.github.io/res/zng-logo.png")]
3//!
4//! Material icons for the [`Icon!`] widget.
5//!
6//! A map from name to icon codepoint is defined in a module for each font. The extension
7//! also registers [`ICONS`] handlers that provide the icons.
8//!
9//! The icons are from the [Material Design Icons] project.
10//!
11//! [`Icon!`]: struct@zng_wgt_text::icon::Icon
12//! [`ICONS`]: struct@zng_wgt::ICONS
13//! [Material Design Icons]: https://github.com/google/material-design-icons
14//!
15//! # Crate
16//!
17#![doc = include_str!(concat!("../", std::env!("CARGO_PKG_README")))]
18#![warn(unused_extern_crates)]
19#![warn(missing_docs)]
20
21zng_wgt::enable_widget_macros!();
22
23#[cfg(all(
24    feature = "embedded",
25    any(feature = "outlined", feature = "filled", feature = "rounded", feature = "sharp")
26))]
27zng_env::on_process_start!(|args| {
28    if args.yield_until_app() {
29        return;
30    }
31    zng_app::APP.on_init(zng_app::hn!(|_| {
32        use zng_wgt::{ICONS, IconRequestArgs, prelude::UiNode, wgt_fn};
33        use zng_wgt_text::icon::{GlyphIcon, Icon};
34
35        // register fonts
36
37        let sets = [
38            #[cfg(feature = "outlined")]
39            (outlined::FONT_NAME, outlined::FONT_BYTES),
40            #[cfg(feature = "filled")]
41            (filled::FONT_NAME, filled::FONT_BYTES),
42            #[cfg(feature = "rounded")]
43            (rounded::FONT_NAME, rounded::FONT_BYTES),
44            #[cfg(feature = "sharp")]
45            (sharp::FONT_NAME, sharp::FONT_BYTES),
46        ];
47
48        for (name, bytes) in sets {
49            let font = zng_ext_font::CustomFont::from_bytes(name, zng_ext_font::FontBytes::from_static(bytes), 0);
50            zng_ext_font::FONTS.register(font);
51        }
52
53        // register icons
54        ICONS.register(wgt_fn!(|args: IconRequestArgs| {
55            if let Some(strong_key) = args.name().strip_prefix("material/") {
56                #[expect(clippy::type_complexity)]
57                let sets: &[(&str, fn(&str) -> Option<GlyphIcon>)] = &[
58                    #[cfg(feature = "outlined")]
59                    ("outlined/", outlined::get),
60                    #[cfg(feature = "filled")]
61                    ("filled/", filled::get),
62                    #[cfg(feature = "rounded")]
63                    ("rounded/", rounded::get),
64                    #[cfg(feature = "sharp")]
65                    ("sharp/", sharp::get),
66                ];
67                for (name, get) in sets {
68                    if let Some(key) = strong_key.strip_prefix(name)
69                        && let Some(ico) = get(key)
70                    {
71                        return Icon!(ico);
72                    }
73                }
74            }
75
76            UiNode::nil()
77        }));
78
79        ICONS.register_fallback(wgt_fn!(|args: IconRequestArgs| {
80            let sets = [
81                #[cfg(feature = "outlined")]
82                outlined::get,
83                #[cfg(feature = "filled")]
84                filled::get,
85                #[cfg(feature = "rounded")]
86                rounded::get,
87                #[cfg(feature = "sharp")]
88                sharp::get,
89            ];
90            for get in sets {
91                if let Some(ico) = get(args.name()) {
92                    return Icon!(ico);
93                }
94            }
95            UiNode::nil()
96        }));
97    }));
98});
99
100#[cfg(any(feature = "outlined", feature = "filled", feature = "rounded", feature = "sharp"))]
101macro_rules! getters {
102    ($FONT_NAME:ident, $MAP:ident) => {
103        /// Gets the [`GlyphIcon`].
104        pub fn get(key: &str) -> Option<GlyphIcon> {
105            Some(GlyphIcon::new($FONT_NAME.clone(), *$MAP.get(key)?))
106        }
107
108        /// Require the [`GlyphIcon`], logs an error if not found.
109        ///
110        /// # Panics
111        ///
112        /// Panics if the `key` is not found.
113        ///
114        /// [`GlyphIcon`]: struct@zng_wgt_text::icon::GlyphIcon
115        pub fn req(key: &str) -> GlyphIcon {
116            match get(key) {
117                Some(g) => g,
118                None => {
119                    tracing::error!("icon {key:?} not found in `outlined`");
120                    GlyphIcon::new("", '\0')
121                }
122            }
123        }
124
125        /// All icons.
126        pub fn all() -> impl ExactSizeIterator<Item = (&'static str, GlyphIcon)> {
127            $MAP.entries()
128                .map(|(key, val)| (*key, GlyphIcon::new($FONT_NAME.clone(), *val)))
129        }
130    };
131}
132
133/// Outline icons.
134///  
135/// This is the "Material Icons Outlined" font.
136///
137/// # Icons
138///
139/// Use the [`ICONS`] service with key `"material/outlined/{name}"` or `"{name}"` to get an widget that renders the icon.
140///
141/// Use [`outlined::req`] to get a [`GlyphIcon`] directly for use in the [`Icon!`] widget.
142///
143/// [`Icon!`]: struct@zng_wgt_text::icon::Icon
144/// [`GlyphIcon`]: struct@zng_wgt_text::icon::GlyphIcon
145/// [`ICONS`]: struct@zng_wgt::ICONS
146///
147/// | Name | Icon |
148/// |------|------|
149#[doc = include_str!(concat!(env!("OUT_DIR"), "/generated.outlined.docs.txt"))]
150#[cfg(feature = "outlined")]
151pub mod outlined {
152    use zng_ext_font::FontName;
153    use zng_wgt_text::icon::GlyphIcon;
154
155    /// "Material Icons Outlined".
156    pub const FONT_NAME: FontName = FontName::from_static("Material Icons Outlined");
157
158    /// Embedded font bytes.
159    #[cfg(feature = "embedded")]
160    pub const FONT_BYTES: &[u8] = include_bytes!("../fonts/MaterialIconsOutlined-Regular.otf");
161
162    include!(concat!(env!("OUT_DIR"), "/generated.outlined.map.rs"));
163    getters!(FONT_NAME, MAP);
164}
165
166/// Filled icons.
167///
168/// This is the "Material Icons" font.
169///
170/// # Icons
171///
172/// Use the [`ICONS`] service with key `"material/filled/{name}"` or `"{name}"` to get an widget that renders the icon.
173///
174/// Use [`filled::req`] to get a [`GlyphIcon`] directly for use in the [`Icon!`] widget.
175///
176/// [`Icon!`]: struct@zng_wgt_text::icon::Icon
177/// [`GlyphIcon`]: struct@zng_wgt_text::icon::GlyphIcon
178/// [`ICONS`]: struct@zng_wgt::ICONS
179///
180/// | Name | Icon |
181/// |------|------|
182#[doc = include_str!(concat!(env!("OUT_DIR"), "/generated.filled.docs.txt"))]
183#[cfg(feature = "filled")]
184pub mod filled {
185    use zng_ext_font::FontName;
186    use zng_wgt_text::icon::GlyphIcon;
187
188    /// "Material Icons".
189    pub const FONT_NAME: FontName = FontName::from_static("Material Icons");
190
191    /// Embedded font bytes.
192    #[cfg(feature = "embedded")]
193    pub const FONT_BYTES: &[u8] = include_bytes!("../fonts/MaterialIcons-Regular.ttf");
194
195    include!(concat!(env!("OUT_DIR"), "/generated.filled.map.rs"));
196    getters!(FONT_NAME, MAP);
197}
198
199/// Rounded icons.
200///  
201/// This is the "Material Icons Rounded" font.
202///
203/// # Icons
204///
205/// Use the [`ICONS`] service with key `"material/rounded/{name}"` or `"{name}"` to get an widget that renders the icon.
206///
207/// Use [`rounded::req`] to get a [`GlyphIcon`] directly for use in the [`Icon!`] widget.
208///
209/// [`Icon!`]: struct@zng_wgt_text::icon::Icon
210/// [`GlyphIcon`]: struct@zng_wgt_text::icon::GlyphIcon
211/// [`ICONS`]: struct@zng_wgt::ICONS
212///
213/// | Name | Icon |
214/// |------|------|
215#[doc = include_str!(concat!(env!("OUT_DIR"), "/generated.rounded.docs.txt"))]
216#[cfg(feature = "rounded")]
217pub mod rounded {
218    use zng_ext_font::FontName;
219    use zng_wgt_text::icon::GlyphIcon;
220
221    /// "Material Icons Rounded".
222    pub const FONT_NAME: FontName = FontName::from_static("Material Icons Rounded");
223
224    /// Embedded font bytes.
225    #[cfg(feature = "embedded")]
226    pub const FONT_BYTES: &[u8] = include_bytes!("../fonts/MaterialIconsRound-Regular.otf");
227
228    include!(concat!(env!("OUT_DIR"), "/generated.rounded.map.rs"));
229    getters!(FONT_NAME, MAP);
230}
231
232/// Sharp icons.
233///  
234/// This is the "Material Icons Sharp" font.
235///
236/// # Icons
237///
238/// Use the [`ICONS`] service with key `"material/sharp/{name}"` or `"{name}"` to get an widget that renders the icon.
239///
240/// Use [`sharp::req`] to get a [`GlyphIcon`] directly for use in the [`Icon!`] widget.
241///
242/// [`Icon!`]: struct@zng_wgt_text::icon::Icon
243/// [`GlyphIcon`]: struct@zng_wgt_text::icon::GlyphIcon
244/// [`ICONS`]: struct@zng_wgt::ICONS
245///
246/// | Name | Icon |
247/// |------|------|
248#[doc = include_str!(concat!(env!("OUT_DIR"), "/generated.sharp.docs.txt"))]
249#[cfg(feature = "sharp")]
250pub mod sharp {
251    use zng_ext_font::FontName;
252    use zng_wgt_text::icon::GlyphIcon;
253
254    /// "Material Icons Sharp".
255    pub const FONT_NAME: FontName = FontName::from_static("Material Icons Sharp");
256
257    /// Embedded font bytes.
258    #[cfg(feature = "embedded")]
259    pub const FONT_BYTES: &[u8] = include_bytes!("../fonts/MaterialIconsSharp-Regular.otf");
260
261    include!(concat!(env!("OUT_DIR"), "/generated.sharp.map.rs"));
262    getters!(FONT_NAME, MAP);
263}