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

1use super::super::{super::Rotation, IcedRenderer, Primitive, style};
2use common::util::srgba_to_linear;
3use core::ops::RangeInclusive;
4use iced::{Point, Rectangle, mouse, slider};
5use style::slider::{Bar, Cursor, Style};
6
7const CURSOR_DRAG_SHIFT: f32 = 0.7;
8
9impl slider::Renderer for IcedRenderer {
10    type Style = Style;
11
12    const DEFAULT_HEIGHT: u16 = 25;
13
14    fn draw(
15        &mut self,
16        bounds: Rectangle,
17        cursor_position: Point,
18        range: RangeInclusive<f32>,
19        value: f32,
20        is_dragging: bool,
21        style: &Self::Style,
22    ) -> Self::Output {
23        let bar_bounds = Rectangle {
24            height: style.bar_height as f32,
25            y: bounds.y + (bounds.height - style.bar_height as f32) / 2.0,
26            ..bounds
27        };
28        let bar = match style.bar {
29            Bar::Color(color) => Primitive::Rectangle {
30                bounds: bar_bounds,
31                linear_color: srgba_to_linear(color),
32            },
33            // Note: bar_pad adds to the size of the bar currently since the dragging logic wouldn't
34            // account for shrinking the area that the cursor is shown in
35            Bar::Image(handle, color, bar_pad) => Primitive::Image {
36                handle: (handle, Rotation::None),
37                bounds: Rectangle {
38                    x: bar_bounds.x - bar_pad as f32,
39                    width: bar_bounds.width + bar_pad as f32 * 2.0,
40                    ..bar_bounds
41                },
42                color,
43                source_rect: None,
44            },
45        };
46
47        let (cursor_width, cursor_height) = style.cursor_size;
48        let (cursor_width, cursor_height) = (f32::from(cursor_width), f32::from(cursor_height));
49        let (min, max) = range.into_inner();
50        let offset = bounds.width * (value - min) / (max - min);
51        let cursor_bounds = Rectangle {
52            x: bounds.x + offset - cursor_width / 2.0,
53            y: bounds.y
54                + if is_dragging { CURSOR_DRAG_SHIFT } else { 0.0 }
55                + (bounds.height - cursor_height) / 2.0,
56            width: cursor_width,
57            height: cursor_height,
58        };
59        let cursor = match style.cursor {
60            Cursor::Color(color) => Primitive::Rectangle {
61                bounds: cursor_bounds,
62                linear_color: srgba_to_linear(color),
63            },
64            Cursor::Image(handle, color) => Primitive::Image {
65                handle: (handle, Rotation::None),
66                bounds: cursor_bounds,
67                color,
68                source_rect: None,
69            },
70        };
71
72        let interaction = if is_dragging {
73            mouse::Interaction::Grabbing
74        } else if cursor_bounds.contains(cursor_position) {
75            mouse::Interaction::Grab
76        } else if bar_bounds.contains(cursor_position) {
77            mouse::Interaction::Pointer
78        } else {
79            mouse::Interaction::Idle
80        };
81
82        let primitives = if style.labels {
83            // TODO text label on left and right ends
84            vec![bar, cursor]
85        } else {
86            // TODO Cursor text label
87            vec![bar, cursor]
88        };
89        (Primitive::Group { primitives }, interaction)
90    }
91}