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 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 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}