makepad_widgets/
multi_image.rs

1use crate::{
2    makepad_derive_widget::*,
3    image_cache::*,
4    makepad_draw::*,
5    widget::*
6};
7
8live_design!{
9    MultiImageBase = {{MultiImage}} {}
10}
11 
12#[derive(Live, Widget)]
13pub struct MultiImage {
14    #[walk] walk: Walk,
15    #[redraw] #[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] source1: LiveDependency,
21    #[live] source2: LiveDependency,
22    #[live] source3: LiveDependency,
23    #[live] source4: LiveDependency,
24    #[rust] textures: [Option<Texture>;4],
25}
26
27impl ImageCacheImpl for MultiImage {
28    fn get_texture(&self, id:usize) -> &Option<Texture> {
29        &self.textures[id]
30    }
31    
32    fn set_texture(&mut self, texture: Option<Texture>, id:usize) {
33        self.textures[id] = texture;
34    }
35}
36
37impl LiveHook for MultiImage{
38    fn after_apply(&mut self, cx: &mut Cx, _applyl: &mut Apply, _index: usize, _nodes: &[LiveNode]) {
39        self.lazy_create_image_cache(cx);
40        for (i,source) in [self.source1.clone(), self.source2.clone(), self.source2.clone(), self.source3.clone()].iter().enumerate(){
41            if source.as_str().len()>0 {
42                let _ = self.load_image_dep_by_path(cx, source.as_str(), i);
43            }
44        }
45    }
46}
47
48impl Widget for MultiImage {
49    fn draw_walk(&mut self, cx: &mut Cx2d, _scope: &mut Scope, walk: Walk) -> DrawStep {
50        self.draw_walk(cx, walk)
51    }
52}
53
54impl MultiImage {
55    /// Returns the original size of the image in pixels (not its displayed size).
56    ///
57    /// Returns `None` if the image has not been loaded into a texture yet.
58    pub fn size_in_pixels(&self, cx: &mut Cx) -> Option<(usize, usize)> {
59        self.textures[0].as_ref()
60            .and_then(|t| t.get_format(cx).vec_width_height())
61    }
62
63    pub fn draw_walk(&mut self, cx: &mut Cx2d, mut walk: Walk) -> DrawStep {
64        // alright we get a walk. depending on our aspect ratio
65        // we change either nothing, or width or height
66        let rect = cx.peek_walk_turtle(walk);
67        let dpi = cx.current_dpi_factor();
68        for i in 0..self.textures.len(){        
69            if let Some(image_texture) = &self.textures[i]{
70                self.draw_bg.draw_vars.set_texture(i, image_texture);
71            }
72        }
73        
74        let (width, height) = if let Some(image_texture) = &self.textures[0]{
75            let (width,height) = image_texture.get_format(cx).vec_width_height().unwrap_or((self.min_width as usize, self.min_height as usize));
76            (width as f64 * self.width_scale, height as f64)
77        }
78        else {
79            self.draw_bg.draw_vars.empty_texture(0);
80            (self.min_width as f64 / dpi, self.min_height as f64 / dpi)
81        };
82        
83        let aspect = width / height;
84        match self.fit {
85            ImageFit::Size => {
86                walk.width = Size::Fixed(width);
87                walk.height = Size::Fixed(height);
88            }
89            ImageFit::Stretch => {
90            }
91            ImageFit::Horizontal => {
92                walk.height = Size::Fixed(rect.size.x / aspect);
93            }
94            ImageFit::Vertical => {
95                walk.width = Size::Fixed(rect.size.y * aspect);
96            }
97            ImageFit::Smallest => {
98                let walk_height = rect.size.x / aspect;
99                if walk_height > rect.size.y {
100                    walk.width = Size::Fixed(rect.size.y * aspect);
101                }
102                else {
103                    walk.height = Size::Fixed(walk_height);
104                }
105            }
106            ImageFit::Biggest => {
107                let walk_height = rect.size.x / aspect;
108                if walk_height < rect.size.y {
109                    walk.width = Size::Fixed(rect.size.y * aspect);
110                }
111                else {
112                    walk.height = Size::Fixed(walk_height);
113                }
114            }
115        }
116        
117        self.draw_bg.draw_walk(cx, walk);
118        
119        DrawStep::done()
120    }
121}