veloren_voxygen/ui/ice/widget/
image.rs1use super::super::graphic;
2use iced::{Element, Hasher, Layout, Length, Point, Rectangle, Widget, layout};
3use std::hash::Hash;
4use vek::Rgba;
5
6pub type Handle = graphic::Id;
11
12pub struct Image {
13 handle: Handle,
14 width: Length,
15 height: Length,
16 fix_aspect_ratio: bool,
17 color: Rgba<u8>,
18}
19
20impl Image {
21 pub fn new(handle: Handle) -> Self {
22 let width = Length::Fill;
23 let height = Length::Fill;
24 Self {
25 handle,
26 width,
27 height,
28 fix_aspect_ratio: false,
29 color: Rgba::broadcast(255),
30 }
31 }
32
33 #[must_use]
34 pub fn width(mut self, width: Length) -> Self {
35 self.width = width;
36 self
37 }
38
39 #[must_use]
40 pub fn height(mut self, height: Length) -> Self {
41 self.height = height;
42 self
43 }
44
45 #[must_use]
46 pub fn fix_aspect_ratio(mut self) -> Self {
47 self.fix_aspect_ratio = true;
48 self
49 }
50
51 #[must_use]
52 pub fn color(mut self, color: Rgba<u8>) -> Self {
53 self.color = color;
54 self
55 }
56}
57
58impl<M, R> Widget<M, R> for Image
59where
60 R: Renderer,
61{
62 fn width(&self) -> Length { self.width }
63
64 fn height(&self) -> Length { self.height }
65
66 fn layout(&self, renderer: &R, limits: &layout::Limits) -> layout::Node {
67 let mut size = limits.width(self.width).height(self.height).max();
68
69 if self.fix_aspect_ratio {
70 let aspect_ratio = {
71 let (w, h) = renderer.dimensions(self.handle);
72 w as f32 / h as f32
73 };
74
75 let max_aspect_ratio = size.width / size.height;
76
77 if max_aspect_ratio > aspect_ratio {
78 size.width = size.height * aspect_ratio;
79 } else {
80 size.height = size.width / aspect_ratio;
81 }
82 }
83
84 layout::Node::new(size)
85 }
86
87 fn draw(
88 &self,
89 renderer: &mut R,
90 _defaults: &R::Defaults,
91 layout: Layout<'_>,
92 _cursor_position: Point,
93 _viewport: &Rectangle,
94 ) -> R::Output {
95 renderer.draw(self.handle, self.color, layout)
96 }
97
98 fn hash_layout(&self, state: &mut Hasher) {
99 struct Marker;
100 std::any::TypeId::of::<Marker>().hash(state);
101
102 self.width.hash(state);
103 self.height.hash(state);
104 self.fix_aspect_ratio.hash(state);
105 }
107}
108
109pub trait Renderer: iced::Renderer {
110 fn dimensions(&self, handle: Handle) -> (u32, u32);
111 fn draw(&mut self, handle: Handle, color: Rgba<u8>, layout: Layout<'_>) -> Self::Output;
112}
113
114impl<'a, M, R> From<Image> for Element<'a, M, R>
115where
116 R: Renderer,
117{
118 fn from(image: Image) -> Element<'a, M, R> { Element::new(image) }
119}
120
121impl<R> super::background_container::Background<R> for Image
122where
123 R: Renderer,
124{
125 fn width(&self) -> Length { self.width }
126
127 fn height(&self) -> Length { self.height }
128
129 fn aspect_ratio_fixed(&self) -> bool { self.fix_aspect_ratio }
130
131 fn pixel_dims(&self, renderer: &R) -> (u16, u16) {
132 let (w, h) = renderer.dimensions(self.handle);
133 (w as u16, h as u16)
134 }
135
136 fn draw(
137 &self,
138 renderer: &mut R,
139 _defaults: &R::Defaults,
140 layout: Layout<'_>,
141 _cursor_position: Point,
142 _viewport: &Rectangle,
143 ) -> R::Output {
144 renderer.draw(self.handle, self.color, layout)
145 }
146}