use conrod_core::{ image, widget::{self, button}, widget_ids, Color, Positionable, Rect, Sizeable, Widget, WidgetCommon, }; #[derive(Clone, WidgetCommon)] pub struct ToggleButton { #[conrod(common_builder)] common: widget::CommonBuilder, value: bool, f_image: button::Image, t_image: button::Image, } widget_ids! { struct Ids { button, } } pub struct State { ids: Ids, } impl ToggleButton { pub fn new(value: bool, f_image_id: image::Id, t_image_id: image::Id) -> Self { ToggleButton { common: widget::CommonBuilder::default(), value, f_image: button::Image { image_id: f_image_id, hover_image_id: None, press_image_id: None, src_rect: None, color: button::ImageColor::None, }, t_image: button::Image { image_id: t_image_id, hover_image_id: None, press_image_id: None, src_rect: None, color: button::ImageColor::None, }, } } pub fn source_rectangle(mut self, rect: Rect) -> Self { self.f_image.src_rect = Some(rect); self.t_image.src_rect = Some(rect); self } pub fn image_colors(mut self, f_color: Color, t_color: Color) -> Self { self.f_image.color = button::ImageColor::Normal(f_color); self.t_image.color = button::ImageColor::Normal(t_color); self } pub fn image_color_with_feedback(mut self, f_color: Color, t_color: Color) -> Self { self.f_image.color = button::ImageColor::WithFeedback(f_color); self.t_image.color = button::ImageColor::WithFeedback(t_color); self } pub fn hover_images(mut self, f_id: image::Id, t_id: image::Id) -> Self { self.f_image.hover_image_id = Some(f_id); self.t_image.hover_image_id = Some(t_id); self } pub fn press_images(mut self, f_id: image::Id, t_id: image::Id) -> Self { self.f_image.press_image_id = Some(f_id); self.t_image.press_image_id = Some(t_id); self } } impl Widget for ToggleButton { type Event = bool; type State = State; type Style = (); fn init_state(&self, id_gen: widget::id::Generator) -> Self::State { State { ids: Ids::new(id_gen), } } #[allow(clippy::unused_unit)] // TODO: Pending review in #587 fn style(&self) -> Self::Style { () } fn update(self, args: widget::UpdateArgs) -> Self::Event { let widget::UpdateArgs { id, state, ui, rect, .. } = args; let ToggleButton { mut value, f_image, t_image, .. } = self; // Check if the button was clicked. // (Can't use `.set().was_clicked()` because we are changing the image after // setting the widget, which causes flickering since it takes a frame to // change after the mouse button is lifted). if ui.widget_input(state.ids.button).clicks().left().count() % 2 == 1 { value = !value; } let image = if value { t_image } else { f_image }; let (x, y, w, h) = rect.x_y_w_h(); // Button let mut button = button::Button::image(image.image_id) .x_y(x, y) .w_h(w, h) .parent(id); button.show = image; button.set(state.ids.button, ui); value } }