1use crate::{
2 Bounds, Element, InteractiveElement, InteractiveElementState, Interactivity, LayoutId, Pixels,
3 RenderOnce, SharedString, StyleRefinement, Styled, WindowContext,
4};
5use futures::FutureExt;
6use util::ResultExt;
7
8pub struct Img {
9 interactivity: Interactivity,
10 uri: Option<SharedString>,
11 grayscale: bool,
12}
13
14pub fn img() -> Img {
15 Img {
16 interactivity: Interactivity::default(),
17 uri: None,
18 grayscale: false,
19 }
20}
21
22impl Img {
23 pub fn uri(mut self, uri: impl Into<SharedString>) -> Self {
24 self.uri = Some(uri.into());
25 self
26 }
27
28 pub fn grayscale(mut self, grayscale: bool) -> Self {
29 self.grayscale = grayscale;
30 self
31 }
32}
33
34impl Element for Img {
35 type State = InteractiveElementState;
36
37 fn layout(
38 &mut self,
39 element_state: Option<Self::State>,
40 cx: &mut WindowContext,
41 ) -> (LayoutId, Self::State) {
42 self.interactivity.layout(element_state, cx, |style, cx| {
43 cx.request_layout(&style, None)
44 })
45 }
46
47 fn paint(
48 self,
49 bounds: Bounds<Pixels>,
50 element_state: &mut Self::State,
51 cx: &mut WindowContext,
52 ) {
53 self.interactivity.paint(
54 bounds,
55 bounds.size,
56 element_state,
57 cx,
58 |style, _scroll_offset, cx| {
59 let corner_radii = style.corner_radii;
60
61 if let Some(uri) = self.uri.clone() {
62 // eprintln!(">>> image_cache.get({uri}");
63 let image_future = cx.image_cache.get(uri.clone());
64 // eprintln!("<<< image_cache.get({uri}");
65 if let Some(data) = image_future
66 .clone()
67 .now_or_never()
68 .and_then(|result| result.ok())
69 {
70 let corner_radii = corner_radii.to_pixels(bounds.size, cx.rem_size());
71 cx.with_z_index(1, |cx| {
72 cx.paint_image(bounds, corner_radii, data, self.grayscale)
73 .log_err()
74 });
75 } else {
76 cx.spawn(|mut cx| async move {
77 if image_future.await.ok().is_some() {
78 cx.on_next_frame(|cx| cx.notify());
79 }
80 })
81 .detach()
82 }
83 }
84 },
85 )
86 }
87}
88
89impl RenderOnce for Img {
90 type Element = Self;
91
92 fn element_id(&self) -> Option<crate::ElementId> {
93 self.interactivity.element_id.clone()
94 }
95
96 fn render_once(self) -> Self::Element {
97 self
98 }
99}
100
101impl Styled for Img {
102 fn style(&mut self) -> &mut StyleRefinement {
103 &mut self.interactivity.base_style
104 }
105}
106
107impl InteractiveElement for Img {
108 fn interactivity(&mut self) -> &mut Interactivity {
109 &mut self.interactivity
110 }
111}