1use crate::{
2 Element, Layout, LayoutId, Result, SharedString, Style, StyleHelpers, Styled, ViewContext,
3};
4use futures::FutureExt;
5use refineable::RefinementCascade;
6use std::marker::PhantomData;
7use util::ResultExt;
8
9pub struct Img<S> {
10 style: RefinementCascade<Style>,
11 uri: Option<SharedString>,
12 grayscale: bool,
13 state_type: PhantomData<S>,
14}
15
16pub fn img<S>() -> Img<S> {
17 Img {
18 style: RefinementCascade::default(),
19 uri: None,
20 grayscale: false,
21 state_type: PhantomData,
22 }
23}
24
25impl<S> Img<S> {
26 pub fn uri(mut self, uri: impl Into<SharedString>) -> Self {
27 self.uri = Some(uri.into());
28 self
29 }
30
31 pub fn grayscale(mut self, grayscale: bool) -> Self {
32 self.grayscale = grayscale;
33 self
34 }
35}
36
37impl<S: 'static> Element for Img<S> {
38 type State = S;
39 type FrameState = ();
40
41 fn layout(
42 &mut self,
43 _: &mut Self::State,
44 cx: &mut ViewContext<Self::State>,
45 ) -> anyhow::Result<(LayoutId, Self::FrameState)>
46 where
47 Self: Sized,
48 {
49 let style = self.computed_style();
50 let layout_id = cx.request_layout(style, [])?;
51 Ok((layout_id, ()))
52 }
53
54 fn paint(
55 &mut self,
56 layout: Layout,
57 _: &mut Self::State,
58 _: &mut Self::FrameState,
59 cx: &mut ViewContext<Self::State>,
60 ) -> Result<()> {
61 let style = self.computed_style();
62 let order = layout.order;
63 let bounds = layout.bounds;
64
65 style.paint(order, bounds, cx);
66
67 if let Some(uri) = &self.uri {
68 let image_future = cx.image_cache.get(uri.clone());
69 if let Some(data) = image_future
70 .clone()
71 .now_or_never()
72 .and_then(ResultExt::log_err)
73 {
74 cx.paint_image(bounds, order, data, self.grayscale)?;
75 } else {
76 log::warn!("image not loaded yet");
77 // cx.spawn(|this, mut cx| async move {
78 // if image_future.await.log_err().is_some() {
79 // this.update(&mut cx, |_, cx| cx.notify()).ok();
80 // }
81 // })
82 // .detach();
83 }
84 }
85 Ok(())
86 }
87}
88
89impl<S> Styled for Img<S> {
90 type Style = Style;
91
92 fn style_cascade(&mut self) -> &mut RefinementCascade<Self::Style> {
93 &mut self.style
94 }
95
96 fn declared_style(&mut self) -> &mut <Self::Style as refineable::Refineable>::Refinement {
97 self.style.base()
98 }
99}
100
101impl<S> StyleHelpers for Img<S> {}