1use super::constrain_size_preserving_aspect_ratio;
2use crate::{
3 geometry::{
4 rect::RectF,
5 vector::{vec2f, Vector2F},
6 },
7 json::{json, ToJson},
8 scene, Border, DebugContext, Element, Event, EventContext, ImageData, LayoutContext,
9 PaintContext, SizeConstraint,
10};
11use serde::Deserialize;
12use std::sync::Arc;
13
14pub struct Image {
15 data: Arc<ImageData>,
16 style: ImageStyle,
17}
18
19#[derive(Copy, Clone, Default, Deserialize)]
20pub struct ImageStyle {
21 #[serde(default)]
22 pub border: Border,
23 #[serde(default)]
24 pub corner_radius: f32,
25 #[serde(default)]
26 pub height: Option<f32>,
27 #[serde(default)]
28 pub width: Option<f32>,
29}
30
31impl Image {
32 pub fn new(data: Arc<ImageData>) -> Self {
33 Self {
34 data,
35 style: Default::default(),
36 }
37 }
38
39 pub fn with_style(mut self, style: ImageStyle) -> Self {
40 self.style = style;
41 self
42 }
43}
44
45impl Element for Image {
46 type LayoutState = ();
47 type PaintState = ();
48
49 fn layout(
50 &mut self,
51 constraint: SizeConstraint,
52 _: &mut LayoutContext,
53 ) -> (Vector2F, Self::LayoutState) {
54 let desired_size = vec2f(
55 self.style.width.unwrap_or(constraint.max.x()),
56 self.style.height.unwrap_or(constraint.max.y()),
57 );
58 let size = constrain_size_preserving_aspect_ratio(
59 constraint.constrain(desired_size),
60 self.data.size().to_f32(),
61 );
62 (size, ())
63 }
64
65 fn paint(
66 &mut self,
67 bounds: RectF,
68 _: RectF,
69 _: &mut Self::LayoutState,
70 cx: &mut PaintContext,
71 ) -> Self::PaintState {
72 cx.scene.push_image(scene::Image {
73 bounds,
74 border: self.style.border,
75 corner_radius: self.style.corner_radius,
76 data: self.data.clone(),
77 });
78 }
79
80 fn dispatch_event(
81 &mut self,
82 _: &Event,
83 _: RectF,
84 _: RectF,
85 _: &mut Self::LayoutState,
86 _: &mut Self::PaintState,
87 _: &mut EventContext,
88 ) -> bool {
89 false
90 }
91
92 fn debug(
93 &self,
94 bounds: RectF,
95 _: &Self::LayoutState,
96 _: &Self::PaintState,
97 _: &DebugContext,
98 ) -> serde_json::Value {
99 json!({
100 "type": "Image",
101 "bounds": bounds.to_json(),
102 })
103 }
104}