use ferroui_base::media::imaging::{BitmapEncoderOptions, PngBitmapEncoderOptions};
use ferroui_base::platform::SharedBitmapImpl;
use ferroui_controls::platform::{IPlatformIconLoader, IWindowIconImpl};
use std::cell::RefCell;
use std::fs::File;
use std::io;
use std::rc::Rc;
use std::sync::Arc;
#[derive(Default)]
pub struct PlatformIconLoader;
impl IPlatformIconLoader for PlatformIconLoader {
fn load_icon_from_file(&self, file_name: &str) -> io::Result<Rc<dyn IWindowIconImpl>> {
let mut file = File::open(file_name)?;
Ok(Rc::new(FakeIcon::new(&mut file)?))
}
fn load_icon_from_stream(&self, stream: &mut dyn io::Read) -> io::Result<Rc<dyn IWindowIconImpl>> {
Ok(Rc::new(FakeIcon::new(stream)?))
}
fn load_icon_from_bitmap(&self, bitmap: Arc<SharedBitmapImpl>) -> Rc<dyn IWindowIconImpl> {
let mut stream = Vec::new();
if bitmap.save(&mut stream, &BitmapEncoderOptions::Png(PngBitmapEncoderOptions::DEFAULT)).is_err() {
stream.clear();
}
Rc::new(FakeIcon { stream: RefCell::new(io::Cursor::new(Vec::new())) })
}
}
pub(crate) struct FakeIcon {
stream: RefCell<io::Cursor<Vec<u8>>>,
}
impl FakeIcon {
pub(crate) fn new(stream: &mut dyn io::Read) -> io::Result<Self> {
let mut bytes = Vec::new();
stream.read_to_end(&mut bytes)?;
let mut cursor = io::Cursor::new(bytes);
cursor.set_position(cursor.get_ref().len() as u64);
Ok(Self { stream: RefCell::new(cursor) })
}
}
impl IWindowIconImpl for FakeIcon {
fn save(&self, output_stream: &mut dyn io::Write) -> io::Result<()> {
io::copy(&mut *self.stream.borrow_mut(), output_stream).map(|_| ())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn an_icon_saves_what_is_left_of_its_stream_which_is_nothing() {
let icon = PlatformIconLoader.load_icon_from_stream(&mut io::Cursor::new(vec![1, 2, 3])).unwrap();
let mut output = Vec::new();
icon.save(&mut output).unwrap();
assert!(output.is_empty());
}
}