veloren_voxygen/ui/widgets/
toggle_button.rs

1use conrod_core::{
2    Color, Positionable, Rect, Sizeable, Widget, WidgetCommon, image,
3    widget::{self, button},
4    widget_ids,
5};
6
7#[derive(Clone, WidgetCommon)]
8pub struct ToggleButton {
9    #[conrod(common_builder)]
10    common: widget::CommonBuilder,
11    value: bool,
12    f_image: button::Image,
13    t_image: button::Image,
14}
15
16widget_ids! {
17    struct Ids {
18        button,
19    }
20}
21
22pub struct State {
23    ids: Ids,
24}
25
26impl ToggleButton {
27    pub fn new(value: bool, f_image_id: image::Id, t_image_id: image::Id) -> Self {
28        ToggleButton {
29            common: widget::CommonBuilder::default(),
30            value,
31            f_image: button::Image {
32                image_id: f_image_id,
33                hover_image_id: None,
34                press_image_id: None,
35                src_rect: None,
36                color: button::ImageColor::None,
37            },
38            t_image: button::Image {
39                image_id: t_image_id,
40                hover_image_id: None,
41                press_image_id: None,
42                src_rect: None,
43                color: button::ImageColor::None,
44            },
45        }
46    }
47
48    #[must_use]
49    pub fn source_rectangle(mut self, rect: Rect) -> Self {
50        self.f_image.src_rect = Some(rect);
51        self.t_image.src_rect = Some(rect);
52        self
53    }
54
55    #[must_use]
56    pub fn image_colors(mut self, f_color: Color, t_color: Color) -> Self {
57        self.f_image.color = button::ImageColor::Normal(f_color);
58        self.t_image.color = button::ImageColor::Normal(t_color);
59        self
60    }
61
62    #[must_use]
63    pub fn image_color_with_feedback(mut self, f_color: Color, t_color: Color) -> Self {
64        self.f_image.color = button::ImageColor::WithFeedback(f_color);
65        self.t_image.color = button::ImageColor::WithFeedback(t_color);
66        self
67    }
68
69    #[must_use]
70    pub fn hover_images(mut self, f_id: image::Id, t_id: image::Id) -> Self {
71        self.f_image.hover_image_id = Some(f_id);
72        self.t_image.hover_image_id = Some(t_id);
73        self
74    }
75
76    #[must_use]
77    pub fn press_images(mut self, f_id: image::Id, t_id: image::Id) -> Self {
78        self.f_image.press_image_id = Some(f_id);
79        self.t_image.press_image_id = Some(t_id);
80        self
81    }
82}
83
84impl Widget for ToggleButton {
85    type Event = bool;
86    type State = State;
87    type Style = ();
88
89    fn init_state(&self, id_gen: widget::id::Generator) -> Self::State {
90        State {
91            ids: Ids::new(id_gen),
92        }
93    }
94
95    fn style(&self) -> Self::Style {}
96
97    fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
98        let widget::UpdateArgs {
99            id,
100            state,
101            ui,
102            rect,
103            ..
104        } = args;
105        let ToggleButton {
106            mut value,
107            f_image,
108            t_image,
109            ..
110        } = self;
111        // Check if the button was clicked.
112        // (Can't use `.set().was_clicked()` because we are changing the image after
113        // setting the widget, which causes flickering since it takes a frame to
114        // change after the mouse button is lifted).
115        if ui.widget_input(state.ids.button).clicks().left().count() % 2 == 1 {
116            value = !value;
117        }
118        let image = if value { t_image } else { f_image };
119        let (x, y, w, h) = rect.x_y_w_h();
120        // Button
121        let mut button = button::Button::image(image.image_id)
122            .x_y(x, y)
123            .w_h(w, h)
124            .parent(id);
125        button.show = image;
126        button.set(state.ids.button, ui);
127
128        value
129    }
130}