makepad_widgets/
image.rs

1use crate::{
2    makepad_derive_widget::*,
3    image_cache::*,
4    makepad_draw::*,
5    widget::*
6};
7
8live_design!{
9    ImageBase = {{Image}} {}
10}
11
12#[derive(Live)]
13pub struct Image {
14    #[walk] walk: Walk,
15    #[live] draw_bg: DrawQuad,
16    #[live] min_width: i64,
17    #[live] min_height: i64,
18    #[live(1.0)] width_scale: f64,
19    #[live] fit: ImageFit,
20    #[live] source: LiveDependency,
21    #[live] texture: Option<Texture>,
22}
23
24impl ImageCacheImpl for Image {
25    fn get_texture(&self) -> &Option<Texture> {
26        &self.texture
27    }
28    
29    fn set_texture(&mut self, texture: Option<Texture>) {
30        self.texture = texture;
31    }
32}
33
34impl LiveHook for Image {
35    fn before_live_design(cx: &mut Cx) {
36        register_widget!(cx, Image)
37    }
38    
39    fn after_apply(&mut self, cx: &mut Cx, _from: ApplyFrom, _index: usize, _nodes: &[LiveNode]) {
40        self.lazy_create_image_cache(cx);
41        let source = self.source.clone();
42        if source.as_str().len()>0 {
43            self.load_image_dep_by_path(cx, source.as_str())
44        }
45    }
46}
47
48impl Widget for Image {
49    fn redraw(&mut self, cx: &mut Cx) {
50        self.draw_bg.redraw(cx)
51    }
52    
53    fn walk(&mut self, _cx:&mut Cx) -> Walk {
54        self.walk
55    }
56    
57    fn draw_walk_widget(&mut self, cx: &mut Cx2d, walk: Walk) -> WidgetDraw {
58        self.draw_walk(cx, walk)
59    }
60}
61
62impl Image {
63    
64    pub fn draw_walk(&mut self, cx: &mut Cx2d, mut walk: Walk) -> WidgetDraw {
65        // alright we get a walk. depending on our aspect ratio
66        // we change either nothing, or width or height
67        let rect = cx.peek_walk_turtle(walk);
68        let dpi = cx.current_dpi_factor();
69        let (width, height) = if let Some(image_texture) = &self.texture {
70            self.draw_bg.draw_vars.set_texture(0, image_texture);
71            let desc = image_texture.get_desc(cx);
72            let width = desc.width.unwrap_or(self.min_width as usize) as f64 / dpi;
73            let height = desc.height.unwrap_or(self.min_height as usize) as f64 / dpi;
74            (width*self.width_scale,height)
75        }
76        else {
77            self.draw_bg.draw_vars.empty_texture(0);
78            (self.min_width as f64 / dpi, self.min_height as f64 / dpi)
79        };
80        
81        let aspect = width / height;
82        match self.fit {
83            ImageFit::Stretch => {},
84            ImageFit::Horizontal => {
85                walk.height = Size::Fixed(rect.size.x / aspect);
86            },
87            ImageFit::Vertical => {
88                walk.width = Size::Fixed(rect.size.y * aspect);
89            },
90            ImageFit::Smallest => {
91                let walk_height = rect.size.x / aspect;
92                if walk_height > rect.size.y {
93                    walk.width = Size::Fixed(rect.size.y * aspect);
94                }
95                else {
96                    walk.height = Size::Fixed(walk_height);
97                }
98            }
99            ImageFit::Biggest => {
100                let walk_height = rect.size.x / aspect;
101                if walk_height < rect.size.y {
102                    walk.width = Size::Fixed(rect.size.y * aspect);
103                }
104                else {
105                    walk.height = Size::Fixed(walk_height);
106                }
107            }
108        }
109        
110        // lets start a turtle and center horizontally
111        
112        self.draw_bg.draw_walk(cx, walk);
113        
114        WidgetDraw::done()
115    }
116}
117
118#[derive(Clone, Default, PartialEq, WidgetRef)]
119pub struct ImageRef(WidgetRef);
120
121impl ImageRef {
122    pub fn load_image_dep_by_path(&self, cx: &mut Cx, image_path: &str) {
123        if let Some(mut inner) = self.borrow_mut() {
124            inner.load_image_dep_by_path(cx, image_path)
125        }
126    }
127    
128    pub fn load_jpg_from_data(&self, cx: &mut Cx, data: &[u8]) {
129        if let Some(mut inner) = self.borrow_mut() {
130            inner.load_jpg_from_data(cx, data)
131        }
132    }
133    
134    pub fn load_png_from_data(&self, cx: &mut Cx, data: &[u8]) {
135        if let Some(mut inner) = self.borrow_mut() {
136            inner.load_png_from_data(cx, data)
137        }
138    }
139    
140    pub fn set_texture(&self, texture: Option<Texture>) {
141        if let Some(mut inner) = self.borrow_mut() {
142            inner.texture = texture
143        }
144    }
145}
146
147#[derive(Clone, Default, WidgetSet)]
148pub struct ImageSet(WidgetSet);
149
150impl ImageSet {
151}