feather_ui/component/
image.rs1use crate::layout::{Layout, leaf};
5use crate::render::atlas::Size;
6use crate::{DAbsPoint, SourceID, UNSIZED_AXIS};
7use derive_where::derive_where;
8use std::rc::Rc;
9use std::sync::Arc;
10
11#[derive(feather_macro::StateMachineChild)]
12#[derive_where(Clone)]
13pub struct Image<T> {
14 pub id: Arc<SourceID>,
15 pub props: Rc<T>,
16 pub resource: Box<dyn crate::resource::Location>,
17 pub size: DAbsPoint,
18 pub dynamic: bool,
19}
20
21impl<T: leaf::Padded + 'static> Image<T> {
22 pub fn new(
23 id: Arc<SourceID>,
24 props: T,
25 resource: &dyn crate::resource::Location,
26 size: DAbsPoint,
27 dynamic: bool,
28 ) -> Self {
29 Self {
30 id,
31 props: props.into(),
32 resource: dyn_clone::clone_box(resource),
33 size,
34 dynamic,
35 }
36 }
37}
38
39fn zero_float(f: f32) -> i32 {
40 if f.is_finite() && f != UNSIZED_AXIS {
41 f.ceil() as i32
42 } else {
43 0
44 }
45}
46
47impl<T: leaf::Padded + 'static> super::Component for Image<T>
48where
49 for<'a> &'a T: Into<&'a (dyn leaf::Padded + 'static)>,
50{
51 type Props = T;
52
53 fn layout(
54 &self,
55 manager: &mut crate::StateManager,
56 driver: &crate::graphics::Driver,
57 window: &Arc<SourceID>,
58 ) -> Box<dyn Layout<T>> {
59 let dpi = manager
60 .get::<super::window::WindowStateMachine>(window)
61 .map(|x| x.state.dpi)
62 .unwrap_or(crate::BASE_DPI);
63
64 let size = self.size.resolve(dpi);
65
66 let uvsize = driver
69 .load_and_resize(
70 self.resource.as_ref(),
71 Size::new(zero_float(size.x), zero_float(size.y)),
72 dpi.width,
73 self.dynamic,
74 )
75 .unwrap();
76
77 Box::new(leaf::Sized::<T> {
78 props: self.props.clone(),
79 id: Arc::downgrade(&self.id),
80 size: uvsize.cast().cast_unit(),
81 renderable: Some(Rc::new(crate::render::image::Instance {
82 image: self.resource.clone(),
83 padding: self.props.padding().as_perimeter(dpi),
84 dpi: dpi.width,
85 resize: self.dynamic,
86 })),
87 })
88 }
89}