Skip to main content

ferroui_native/
icon_loader.rs

1use ferroui_base::media::imaging::{BitmapEncoderOptions, PngBitmapEncoderOptions};
2use ferroui_base::platform::{IBitmapImpl, IPlatformRenderInterface};
3use ferroui_base::{FerroLocator, LocatorExtensions};
4use ferroui_controls::platform::{IPlatformIconLoader, IWindowIconImpl};
5use std::io;
6use std::rc::Rc;
7
8// OSX doesn't have a concept of *window* icon.
9// Icons in the title bar are only shown if there is
10// an opened file (on disk) associated with the current window
11// see https://stackoverflow.com/a/7038671/2231814
12#[derive(Default)]
13pub struct IconLoader;
14
15struct IconStub {
16    bitmap: std::sync::Arc<ferroui_base::platform::SharedBitmapImpl>,
17}
18
19impl IWindowIconImpl for IconStub {
20    fn save(&self, output_stream: &mut dyn io::Write) -> io::Result<()> {
21        self.bitmap.save(output_stream, &BitmapEncoderOptions::Png(PngBitmapEncoderOptions::DEFAULT))
22    }
23}
24
25fn render_interface() -> Rc<dyn IPlatformRenderInterface> {
26    FerroLocator::current().get_required_service::<dyn IPlatformRenderInterface>()
27}
28
29impl IPlatformIconLoader for IconLoader {
30    fn load_icon_from_file(&self, file_name: &str) -> io::Result<Rc<dyn IWindowIconImpl>> {
31        Ok(Rc::new(IconStub { bitmap: render_interface().load_bitmap_from_file(file_name)? }))
32    }
33
34    fn load_icon_from_stream(&self, stream: &mut dyn io::Read) -> io::Result<Rc<dyn IWindowIconImpl>> {
35        Ok(Rc::new(IconStub { bitmap: render_interface().load_bitmap(stream)? }))
36    }
37
38    /// # Panics
39    /// Panics when the bitmap cannot be encoded or decoded again, where the
40    /// reference implementation throws.
41    fn load_icon_from_bitmap(&self, bitmap: std::sync::Arc<ferroui_base::platform::SharedBitmapImpl>) -> Rc<dyn IWindowIconImpl> {
42        let mut ms = Vec::new();
43        if let Err(error) = bitmap.save(&mut ms, &BitmapEncoderOptions::Png(PngBitmapEncoderOptions::DEFAULT)) {
44            panic!("Unable to save the icon bitmap: {error}");
45        }
46        match self.load_icon_from_stream(&mut io::Cursor::new(ms)) {
47            Ok(icon) => icon,
48            Err(error) => panic!("Unable to load the icon bitmap: {error}"),
49        }
50    }
51}