1use crate::ext::WidgetLayoutExt;
2use maycoon_core::app::info::AppInfo;
3use maycoon_core::app::update::Update;
4use maycoon_core::layout::{LayoutNode, LayoutStyle, StyleNode};
5use maycoon_core::state::{State, Val};
6use maycoon_core::vg::kurbo::{Affine, Vec2};
7use maycoon_core::vg::peniko::{Blob, ImageFormat};
8use maycoon_core::vg::{peniko, Scene};
9use maycoon_core::widget::Widget;
10use maycoon_theme::id::WidgetId;
11use maycoon_theme::theme::Theme;
12use nalgebra::Vector2;
13
14pub struct Image<S: State> {
21 image: Val<S, peniko::Image>,
22 style: Val<S, LayoutStyle>,
23}
24
25impl<S: State> Image<S> {
26 pub fn new(image: impl Into<Val<S, ImageData>>) -> Self {
28 Self {
29 image: image.into().map(|data| {
30 peniko::Image::new(
31 Blob::from(data.image),
32 data.format,
33 data.size.x,
34 data.size.y,
35 )
36 }),
37 style: LayoutStyle::default().into(),
38 }
39 }
40
41 pub fn with_image(mut self, image: impl Into<Val<S, ImageData>>) -> Self {
43 self.image = image.into().map(|data| {
44 peniko::Image::new(
45 Blob::from(data.image),
46 data.format,
47 data.size.x,
48 data.size.y,
49 )
50 });
51 self
52 }
53}
54
55impl<S: State> WidgetLayoutExt<S> for Image<S> {
56 fn set_layout_style(&mut self, layout_style: impl Into<Val<S, LayoutStyle>>) {
57 self.style = layout_style.into();
58 }
59}
60
61impl<S: State> Widget<S> for Image<S> {
62 fn render(
63 &mut self,
64 scene: &mut Scene,
65 _: &mut dyn Theme,
66 _: &AppInfo,
67 layout_node: &LayoutNode,
68 state: &S,
69 ) {
70 let image = self.image.get_ref(state);
71
72 scene.draw_image(
73 image,
74 Affine::translate(Vec2::new(
75 layout_node.layout.location.x as f64,
76 layout_node.layout.location.y as f64,
77 )),
78 );
79 }
80
81 fn layout_style(&mut self, state: &S) -> StyleNode {
82 StyleNode {
83 style: self.style.get_ref(state).clone(),
84 children: Vec::new(),
85 }
86 }
87
88 fn update(&mut self, _: &LayoutNode, _: &mut S, _: &AppInfo) -> Update {
89 self.image.invalidate();
90 self.style.invalidate();
91 Update::empty()
92 }
93
94 fn widget_id(&self) -> WidgetId {
95 WidgetId::new("maycoon-widgets", "Image")
96 }
97}
98
99#[derive(Clone, Debug, PartialEq, Eq)]
103pub struct ImageData {
104 image: Vec<u8>,
105 size: Vector2<u32>,
106 format: ImageFormat,
107}
108
109impl ImageData {
110 pub fn new(image: Vec<u8>, size: Vector2<u32>, format: ImageFormat) -> Self {
112 Self {
113 image,
114 size,
115 format,
116 }
117 }
118}