1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
use crate::{
    makepad_derive_widget::*,
    image_cache::*,
    makepad_draw::*,
    widget::*
};

live_design!{
    ImageBase = {{Image}} {}
}

#[derive(Live)]
pub struct Image {
    #[walk] walk: Walk,
    #[live] draw_bg: DrawQuad,
    #[live] min_width: i64,
    #[live] min_height: i64,
    #[live(1.0)] width_scale: f64,
    #[live] fit: ImageFit,
    #[live] source: LiveDependency,
    #[live] texture: Option<Texture>,
}

impl ImageCacheImpl for Image {
    fn get_texture(&self) -> &Option<Texture> {
        &self.texture
    }
    
    fn set_texture(&mut self, texture: Option<Texture>) {
        self.texture = texture;
    }
}

impl LiveHook for Image {
    fn before_live_design(cx: &mut Cx) {
        register_widget!(cx, Image)
    }
    
    fn after_apply(&mut self, cx: &mut Cx, _from: ApplyFrom, _index: usize, _nodes: &[LiveNode]) {
        self.lazy_create_image_cache(cx);
        let source = self.source.clone();
        if source.as_str().len()>0 {
            self.load_image_dep_by_path(cx, source.as_str())
        }
    }
}

impl Widget for Image {
    fn redraw(&mut self, cx: &mut Cx) {
        self.draw_bg.redraw(cx)
    }
    
    fn walk(&mut self, _cx:&mut Cx) -> Walk {
        self.walk
    }
    
    fn draw_walk_widget(&mut self, cx: &mut Cx2d, walk: Walk) -> WidgetDraw {
        self.draw_walk(cx, walk)
    }
}

impl Image {
    
    pub fn draw_walk(&mut self, cx: &mut Cx2d, mut walk: Walk) -> WidgetDraw {
        // alright we get a walk. depending on our aspect ratio
        // we change either nothing, or width or height
        let rect = cx.peek_walk_turtle(walk);
        let dpi = cx.current_dpi_factor();
        let (width, height) = if let Some(image_texture) = &self.texture {
            self.draw_bg.draw_vars.set_texture(0, image_texture);
            let desc = image_texture.get_desc(cx);
            let width = desc.width.unwrap_or(self.min_width as usize) as f64 / dpi;
            let height = desc.height.unwrap_or(self.min_height as usize) as f64 / dpi;
            (width*self.width_scale,height)
        }
        else {
            self.draw_bg.draw_vars.empty_texture(0);
            (self.min_width as f64 / dpi, self.min_height as f64 / dpi)
        };
        
        let aspect = width / height;
        match self.fit {
            ImageFit::Stretch => {},
            ImageFit::Horizontal => {
                walk.height = Size::Fixed(rect.size.x / aspect);
            },
            ImageFit::Vertical => {
                walk.width = Size::Fixed(rect.size.y * aspect);
            },
            ImageFit::Smallest => {
                let walk_height = rect.size.x / aspect;
                if walk_height > rect.size.y {
                    walk.width = Size::Fixed(rect.size.y * aspect);
                }
                else {
                    walk.height = Size::Fixed(walk_height);
                }
            }
            ImageFit::Biggest => {
                let walk_height = rect.size.x / aspect;
                if walk_height < rect.size.y {
                    walk.width = Size::Fixed(rect.size.y * aspect);
                }
                else {
                    walk.height = Size::Fixed(walk_height);
                }
            }
        }
        
        // lets start a turtle and center horizontally
        
        self.draw_bg.draw_walk(cx, walk);
        
        WidgetDraw::done()
    }
}

#[derive(Clone, Default, PartialEq, WidgetRef)]
pub struct ImageRef(WidgetRef);

impl ImageRef {
    pub fn load_image_dep_by_path(&self, cx: &mut Cx, image_path: &str) {
        if let Some(mut inner) = self.borrow_mut() {
            inner.load_image_dep_by_path(cx, image_path)
        }
    }
    
    pub fn load_jpg_from_data(&self, cx: &mut Cx, data: &[u8]) {
        if let Some(mut inner) = self.borrow_mut() {
            inner.load_jpg_from_data(cx, data)
        }
    }
    
    pub fn load_png_from_data(&self, cx: &mut Cx, data: &[u8]) {
        if let Some(mut inner) = self.borrow_mut() {
            inner.load_png_from_data(cx, data)
        }
    }
    
    pub fn set_texture(&self, texture: Option<Texture>) {
        if let Some(mut inner) = self.borrow_mut() {
            inner.texture = texture
        }
    }
}

#[derive(Clone, Default, WidgetSet)]
pub struct ImageSet(WidgetSet);

impl ImageSet {
}