use crate::render::callbacks::CallbackRegistry;
use crate::render::widget::*;
use crate::render::widget_cache::WidgetContainer;
use crate::render::widget_config::*;
use crate::render::Points;
use sdl2::render::Canvas;
use sdl2::video::Window;
use crate::widgets::text_widget::{TextJustify, TextWidget};
use sdl2::pixels::Color;
use std::collections::HashMap;
pub type OnToggleCallbackType =
Option<Box<dyn FnMut(&mut ToggleButtonWidget, &[WidgetContainer], bool)>>;
pub struct ToggleButtonWidget {
config: WidgetConfig,
system_properties: HashMap<i32, String>,
callback_registry: CallbackRegistry,
base_widget: BaseWidget,
text_widget: TextWidget,
active: bool,
selected: bool,
in_bounds: bool,
on_toggle: OnToggleCallbackType,
}
impl ToggleButtonWidget {
pub fn new(
x: i32,
y: i32,
w: u32,
h: u32,
text: String,
font_size: i32,
selected: bool,
) -> Self {
let mut base_widget = BaseWidget::new(x, y, w, h);
let mut text_widget = TextWidget::new(
String::from("assets/OpenSans-Regular.ttf"),
sdl2::ttf::FontStyle::NORMAL,
font_size,
TextJustify::Center,
text.clone(),
x + 2,
y + 2,
w - 4,
h - 4,
);
let base_color = if selected {
Color::RGB(0, 0, 0)
} else {
Color::RGB(255, 255, 255)
};
let text_color = if selected {
Color::RGB(255, 255, 255)
} else {
Color::RGB(0, 0, 0)
};
let mut config = WidgetConfig::new(x, y, w, h);
base_widget.set_color(CONFIG_COLOR_BASE, base_color);
base_widget.set_color(CONFIG_COLOR_BORDER, Color::RGB(0, 0, 0));
base_widget.set_numeric(CONFIG_BORDER_WIDTH, 2);
text_widget.set_color(CONFIG_COLOR_BASE, base_color);
text_widget.set_color(CONFIG_COLOR_TEXT, text_color);
config.set_toggle(CONFIG_SELECTED_STATE, selected);
Self {
config,
system_properties: HashMap::new(),
callback_registry: CallbackRegistry::new(),
base_widget,
text_widget,
active: false,
selected,
in_bounds: false,
on_toggle: None,
}
}
fn draw_hovered(&mut self) {
let base_color = if self.selected {
Color::RGB(255, 255, 255)
} else {
Color::RGB(0, 0, 0)
};
let text_color = if self.selected {
Color::RGB(0, 0, 0)
} else {
Color::RGB(255, 255, 255)
};
self.base_widget.set_color(CONFIG_COLOR_BASE, base_color);
self.text_widget.set_color(CONFIG_COLOR_TEXT, text_color);
self.text_widget.set_color(CONFIG_COLOR_BASE, base_color);
self.get_config().set_invalidate(true);
}
fn draw_unhovered(&mut self) {
let base_color = if self.selected {
Color::RGB(0, 0, 0)
} else {
Color::RGB(255, 255, 255)
};
let text_color = if self.selected {
Color::RGB(255, 255, 255)
} else {
Color::RGB(0, 0, 0)
};
self.base_widget.set_color(CONFIG_COLOR_BASE, base_color);
self.text_widget.set_color(CONFIG_COLOR_TEXT, text_color);
self.text_widget.set_color(CONFIG_COLOR_BASE, base_color);
self.get_config().set_invalidate(true);
}
pub fn on_toggle<F>(&mut self, callback: F)
where
F: FnMut(&mut ToggleButtonWidget, &[WidgetContainer], bool) + 'static,
{
self.on_toggle = Some(Box::new(callback));
}
fn call_toggle_callback(&mut self, widgets: &[WidgetContainer]) {
if let Some(mut cb) = self.on_toggle.take() {
cb(self, widgets, self.selected);
self.on_toggle = Some(cb);
}
}
}
impl Widget for ToggleButtonWidget {
fn draw(&mut self, c: &mut Canvas<Window>) {
self.base_widget.draw(c);
self.text_widget.draw(c);
}
fn mouse_entered(&mut self, _widgets: &[WidgetContainer]) {
if self.active {
self.draw_hovered();
}
self.in_bounds = true;
self.mouse_entered_callback(_widgets);
}
fn mouse_exited(&mut self, _widgets: &[WidgetContainer]) {
if self.active {
self.draw_unhovered();
}
self.in_bounds = false;
self.mouse_exited_callback(_widgets);
}
fn button_clicked(
&mut self,
_widgets: &[WidgetContainer],
_button: u8,
_clicks: u8,
_state: bool,
) {
if _button == 1 {
if _state {
self.draw_hovered();
self.active = true;
} else {
self.active = false;
if self.in_bounds {
self.selected = !self.selected;
self.set_toggle(CONFIG_SELECTED_STATE, self.selected);
self.call_toggle_callback(_widgets);
}
}
}
self.button_clicked_callback(_widgets, _button, _clicks, _state);
}
default_widget_properties!();
default_widget_callbacks!();
}