use sdl2::rect::Rect;
use sdl2::render::{Canvas, Texture};
use sdl2::video::Window;
use crate::render::callbacks::*;
use crate::render::layout_cache::LayoutContainer;
use crate::render::texture_cache::TextureCache;
use crate::render::texture_store::TextureStore;
use crate::render::widget_cache::WidgetContainer;
use crate::render::widget_config::*;
use crate::render::{Points, Size};
use sdl2::event::Event;
use sdl2::pixels::Color;
use std::any::Any;
use std::collections::HashMap;
pub trait Widget {
fn as_any(&mut self) -> &mut dyn Any;
fn draw(&mut self, _c: &mut Canvas<Window>, _t: &mut TextureCache) -> Option<&Texture> {
None
}
fn get_config(&mut self) -> &mut WidgetConfig;
fn get_system_properties(&mut self) -> &mut HashMap<i32, String>;
fn get_callbacks(&mut self) -> &mut CallbackRegistry;
fn mouse_entered(&mut self, _widgets: &[WidgetContainer], _layouts: &[LayoutContainer]) {
self.mouse_entered_callback(_widgets, _layouts);
}
fn mouse_exited(&mut self, _widgets: &[WidgetContainer], _layouts: &[LayoutContainer]) {
self.mouse_exited_callback(_widgets, _layouts);
}
fn mouse_moved(
&mut self,
_widgets: &[WidgetContainer],
_layouts: &[LayoutContainer],
_points: Points,
) {
self.mouse_moved_callback(_widgets, _layouts, _points);
}
fn mouse_scrolled(
&mut self,
_widgets: &[WidgetContainer],
_layouts: &[LayoutContainer],
_points: Points,
) {
self.mouse_scrolled_callback(_widgets, _layouts, _points);
}
fn button_clicked(
&mut self,
_widgets: &[WidgetContainer],
_layouts: &[LayoutContainer],
_button: u8,
_clicks: u8,
_state: bool,
) {
self.button_clicked_callback(_widgets, _layouts, _button, _clicks, _state);
}
fn tick(&mut self, _widgets: &[WidgetContainer], _layouts: &[LayoutContainer]) {
self.tick_callback(_widgets, _layouts);
}
fn other_event(
&mut self,
_widgets: &[WidgetContainer],
_layouts: &[LayoutContainer],
_event: Event,
) {
eprintln!("Other event: {:?}", _event);
}
fn tick_callback(&mut self, _widgets: &[WidgetContainer], _layouts: &[LayoutContainer]) {}
fn mouse_entered_callback(
&mut self,
_widgets: &[WidgetContainer],
_layouts: &[LayoutContainer],
) {
}
fn mouse_exited_callback(
&mut self,
_widgets: &[WidgetContainer],
_layouts: &[LayoutContainer],
) {
}
fn mouse_moved_callback(
&mut self,
_widgets: &[WidgetContainer],
_layouts: &[LayoutContainer],
_points: Points,
) {
}
fn mouse_scrolled_callback(
&mut self,
_widgets: &[WidgetContainer],
_layouts: &[LayoutContainer],
_points: Points,
) {
}
fn button_clicked_callback(
&mut self,
_widgets: &[WidgetContainer],
_layouts: &[LayoutContainer],
_button: u8,
_clicks: u8,
_state: bool,
) {
}
fn on_config_changed(&mut self, _k: u8, _v: Config) {}
fn set_point(&mut self, config: u8, x: i32, y: i32) {
self.get_config().set_point(config, x, y);
self.on_config_changed(config, Config::Points(vec![x, y]));
}
fn set_color(&mut self, config: u8, color: Color) {
self.get_config().set_color(config, color);
self.on_config_changed(config, Config::Color(color));
}
fn set_numeric(&mut self, config: u8, value: i32) {
self.get_config().set_numeric(config, value);
self.on_config_changed(config, Config::Numeric(value));
}
fn set_text(&mut self, config: u8, text: String) {
self.get_config().set_text(config, text.clone());
self.on_config_changed(config, Config::Text(text));
}
fn set_toggle(&mut self, config: u8, flag: bool) {
self.get_config().set_toggle(config, flag);
self.on_config_changed(config, Config::Toggle(flag));
}
fn set_compass(&mut self, config: u8, value: CompassPosition) {
self.get_config().set_compass(config, value);
self.on_config_changed(config, Config::CompassPosition(value));
}
fn get_point(&mut self, k: u8) -> Points {
self.get_config().get_point(k)
}
fn get_size(&mut self, k: u8) -> Size {
self.get_config().get_size(k)
}
fn get_color(&mut self, k: u8) -> Color {
self.get_config().get_color(k)
}
fn get_numeric(&mut self, k: u8) -> i32 {
self.get_config().get_numeric(k)
}
fn get_text(&mut self, k: u8) -> String {
self.get_config().get_text(k)
}
fn get_toggle(&mut self, k: u8) -> bool {
self.get_config().get_toggle(k)
}
fn get_compass(&mut self, k: u8) -> CompassPosition {
self.get_config().get_compass(k)
}
fn set_origin(&mut self, _origin: Points) {
let old_origin = self.get_config().get_point(CONFIG_ORIGIN);
if _origin[0] != old_origin[0] || _origin[1] != old_origin[1] {
self.get_config()
.set_point(CONFIG_ORIGIN, _origin[0], _origin[1]);
self.get_config().set_invalidated(true);
}
}
fn set_size(&mut self, _size: Vec<u32>) {
let old_size = self.get_config().get_size(CONFIG_SIZE);
if _size[0] != old_size[0] || _size[1] != old_size[1] {
self.get_config().set_size(CONFIG_SIZE, _size[0], _size[1]);
self.get_config().set_invalidated(true);
}
}
fn get_drawing_area(&mut self) -> Rect {
Rect::new(
self.get_config().to_x(0),
self.get_config().to_y(0),
self.get_config().get_size(CONFIG_SIZE)[0],
self.get_config().get_size(CONFIG_SIZE)[1],
)
}
fn is_invalidated(&mut self) -> bool {
self.get_config().invalidated()
}
fn set_invalidated(&mut self, flag: bool) {
self.get_config().set_invalidated(flag);
}
}
pub struct BaseWidget {
config: WidgetConfig,
system_properties: HashMap<i32, String>,
callback_registry: CallbackRegistry,
texture_store: TextureStore,
}
impl BaseWidget {
pub fn new(points: Points, size: Size) -> Self {
Self {
config: WidgetConfig::new(points, size),
system_properties: HashMap::new(),
callback_registry: CallbackRegistry::new(),
texture_store: TextureStore::default(),
}
}
}
impl Widget for BaseWidget {
fn draw(&mut self, c: &mut Canvas<Window>, _t: &mut TextureCache) -> Option<&Texture> {
if self.get_config().invalidated() {
let bounds = self.get_config().get_size(CONFIG_SIZE);
self.texture_store
.create_or_resize_texture(c, bounds[0] as u32, bounds[1] as u32);
let base_color = self.get_config().get_color(CONFIG_COLOR_BASE);
let border_color = self.get_config().get_color(CONFIG_COLOR_BORDER);
c.with_texture_canvas(self.texture_store.get_mut_ref(), |texture| {
texture.set_draw_color(base_color);
texture.clear();
texture.set_draw_color(border_color);
texture
.draw_rect(Rect::new(0, 0, bounds[0], bounds[1]))
.unwrap();
})
.unwrap();
}
self.texture_store.get_optional_ref()
}
default_widget_functions!();
default_widget_properties!();
default_widget_callbacks!();
}