veloren_voxygen/ui/ice/renderer/widget/
container.rs

1use super::super::{super::Rotation, IcedRenderer, Primitive, style};
2use common::util::srgba_to_linear;
3use iced::{Element, Layout, Point, Rectangle, container};
4use style::container::Border;
5use vek::Rgba;
6
7// TODO: move to style
8const BORDER_SIZE: u16 = 8;
9
10impl container::Renderer for IcedRenderer {
11    type Style = style::container::Style;
12
13    fn draw<M>(
14        &mut self,
15        defaults: &Self::Defaults,
16        bounds: Rectangle,
17        cursor_position: Point,
18        viewport: &Rectangle,
19        style_sheet: &Self::Style,
20        content: &Element<'_, M, Self>,
21        content_layout: Layout<'_>,
22    ) -> Self::Output {
23        let (content, mouse_interaction) =
24            content.draw(self, defaults, content_layout, cursor_position, viewport);
25
26        let prim = match style_sheet {
27            Self::Style::Image(handle, color) => {
28                let background = Primitive::Image {
29                    handle: (*handle, Rotation::None),
30                    bounds,
31                    color: *color,
32                    source_rect: None,
33                };
34
35                Primitive::Group {
36                    primitives: vec![background, content],
37                }
38            },
39            Self::Style::Color(color, border) => {
40                let linear_color = srgba_to_linear(color.map(|e| e as f32 / 255.0));
41
42                let primitives = match border {
43                    Border::None => {
44                        let background = Primitive::Rectangle {
45                            bounds,
46                            linear_color,
47                        };
48
49                        vec![background, content]
50                    },
51                    Border::DoubleCornerless { inner, outer } => {
52                        let border_size = f32::from(BORDER_SIZE)
53                            .min(bounds.width / 4.0)
54                            .min(bounds.height / 4.0);
55
56                        let center = Primitive::Rectangle {
57                            bounds: Rectangle {
58                                x: bounds.x + border_size * 2.0,
59                                y: bounds.y + border_size * 2.0,
60                                width: bounds.width - border_size * 4.0,
61                                height: bounds.height - border_size * 4.0,
62                            },
63                            linear_color,
64                        };
65
66                        let linear_color = srgba_to_linear(outer.map(|e| e as f32 / 255.0));
67                        let top = Primitive::Rectangle {
68                            bounds: Rectangle {
69                                x: bounds.x + border_size,
70                                y: bounds.y,
71                                width: bounds.width - border_size * 2.0,
72                                height: border_size,
73                            },
74                            linear_color,
75                        };
76                        let bottom = Primitive::Rectangle {
77                            bounds: Rectangle {
78                                x: bounds.x + border_size,
79                                y: bounds.y + bounds.height - border_size,
80                                width: bounds.width - border_size * 2.0,
81                                height: border_size,
82                            },
83                            linear_color,
84                        };
85                        let left = Primitive::Rectangle {
86                            bounds: Rectangle {
87                                x: bounds.x,
88                                y: bounds.y + border_size,
89                                width: border_size,
90                                height: bounds.height - border_size * 2.0,
91                            },
92                            linear_color,
93                        };
94                        let right = Primitive::Rectangle {
95                            bounds: Rectangle {
96                                x: bounds.x + bounds.width - border_size,
97                                y: bounds.y + border_size,
98                                width: border_size,
99                                height: bounds.height - border_size * 2.0,
100                            },
101                            linear_color,
102                        };
103
104                        let linear_color = srgba_to_linear(inner.map(|e| e as f32 / 255.0));
105                        let top_inner = Primitive::Rectangle {
106                            bounds: Rectangle {
107                                x: bounds.x + border_size,
108                                y: bounds.y + border_size,
109                                width: bounds.width - border_size * 2.0,
110                                height: border_size,
111                            },
112                            linear_color,
113                        };
114                        let bottom_inner = Primitive::Rectangle {
115                            bounds: Rectangle {
116                                x: bounds.x + border_size,
117                                y: bounds.y + bounds.height - border_size * 2.0,
118                                width: bounds.width - border_size * 2.0,
119                                height: border_size,
120                            },
121                            linear_color,
122                        };
123                        let left_inner = Primitive::Rectangle {
124                            bounds: Rectangle {
125                                x: bounds.x + border_size,
126                                y: bounds.y + border_size * 2.0,
127                                width: border_size,
128                                height: bounds.height - border_size * 4.0,
129                            },
130                            linear_color,
131                        };
132                        let right_inner = Primitive::Rectangle {
133                            bounds: Rectangle {
134                                x: bounds.x + bounds.width - border_size * 2.0,
135                                y: bounds.y + border_size * 2.0,
136                                width: border_size,
137                                height: bounds.height - border_size * 4.0,
138                            },
139                            linear_color,
140                        };
141
142                        vec![
143                            center,
144                            top,
145                            bottom,
146                            left,
147                            right,
148                            top_inner,
149                            bottom_inner,
150                            left_inner,
151                            right_inner,
152                            content,
153                        ]
154                    },
155                    Border::Image { corner, edge } => {
156                        let border_size = f32::from(BORDER_SIZE)
157                            .min(bounds.width / 4.0)
158                            .min(bounds.height / 4.0);
159
160                        let center = Primitive::Rectangle {
161                            bounds: Rectangle {
162                                x: bounds.x + border_size,
163                                y: bounds.y + border_size,
164                                width: bounds.width - border_size * 2.0,
165                                height: bounds.height - border_size * 2.0,
166                            },
167                            linear_color,
168                        };
169
170                        let color = Rgba::white();
171
172                        let tl_corner = Primitive::Image {
173                            handle: (*corner, Rotation::None),
174                            bounds: Rectangle {
175                                x: bounds.x,
176                                y: bounds.y,
177                                width: border_size,
178                                height: border_size,
179                            },
180                            color,
181                            source_rect: None,
182                        };
183
184                        let tr_corner = Primitive::Image {
185                            handle: (*corner, Rotation::Cw90),
186                            bounds: Rectangle {
187                                x: bounds.x + bounds.width - border_size,
188                                y: bounds.y,
189                                width: border_size,
190                                height: border_size,
191                            },
192                            color,
193                            source_rect: None,
194                        };
195
196                        let bl_corner = Primitive::Image {
197                            handle: (*corner, Rotation::Cw270),
198                            bounds: Rectangle {
199                                x: bounds.x,
200                                y: bounds.y + bounds.height - border_size,
201                                width: border_size,
202                                height: border_size,
203                            },
204                            color,
205                            source_rect: None,
206                        };
207
208                        let br_corner = Primitive::Image {
209                            handle: (*corner, Rotation::Cw180),
210                            bounds: Rectangle {
211                                x: bounds.x + bounds.width - border_size,
212                                y: bounds.y + bounds.height - border_size,
213                                width: border_size,
214                                height: border_size,
215                            },
216                            color,
217                            source_rect: None,
218                        };
219
220                        let top_edge = Primitive::Image {
221                            handle: (*edge, Rotation::None),
222                            bounds: Rectangle {
223                                x: bounds.x + border_size,
224                                y: bounds.y,
225                                width: bounds.width - 2.0 * border_size,
226                                height: border_size,
227                            },
228                            color,
229                            source_rect: None,
230                        };
231
232                        let bottom_edge = Primitive::Image {
233                            handle: (*edge, Rotation::Cw180),
234                            bounds: Rectangle {
235                                x: bounds.x + border_size,
236                                y: bounds.y + bounds.height - border_size,
237                                width: bounds.width - 2.0 * border_size,
238                                height: border_size,
239                            },
240                            color,
241                            source_rect: None,
242                        };
243
244                        let left_edge = Primitive::Image {
245                            handle: (*edge, Rotation::Cw270),
246                            bounds: Rectangle {
247                                x: bounds.x,
248                                y: bounds.y + border_size,
249                                width: border_size,
250                                height: bounds.height - 2.0 * border_size,
251                            },
252                            color,
253                            source_rect: None,
254                        };
255
256                        let right_edge = Primitive::Image {
257                            handle: (*edge, Rotation::Cw90),
258                            bounds: Rectangle {
259                                x: bounds.x + bounds.width - border_size,
260                                y: bounds.y + border_size,
261                                width: border_size,
262                                height: bounds.height - 2.0 * border_size,
263                            },
264                            color,
265                            source_rect: None,
266                        };
267
268                        // Is this worth it as opposed to using a giant image? (Probably)
269                        vec![
270                            center,
271                            tl_corner,
272                            tr_corner,
273                            bl_corner,
274                            br_corner,
275                            top_edge,
276                            bottom_edge,
277                            left_edge,
278                            right_edge,
279                            content,
280                        ]
281                    },
282                };
283
284                Primitive::Group { primitives }
285            },
286            Self::Style::None => content,
287        };
288
289        (prim, mouse_interaction)
290    }
291}