use std::cell::RefCell;
use crate::render::layout_cache::LayoutContainer;
use crate::render::texture_cache::TextureCache;
use crate::render::widget::Widget;
use crate::render::widget_config::{CONFIG_ORIGIN, CONFIG_SIZE};
use sdl2::event::Event;
use sdl2::pixels::Color;
use sdl2::rect::Rect;
use sdl2::render::Canvas;
use sdl2::video::Window;
pub struct WidgetContainer {
pub widget: RefCell<Box<dyn Widget>>,
widget_name: String,
pub origin: Vec<i32>,
widget_id: i32,
parent_id: i32,
}
impl WidgetContainer {
pub fn new(
widget: Box<dyn Widget>,
widget_name: String,
origin: Vec<i32>,
widget_id: i32,
parent_id: i32,
) -> Self {
Self {
widget: RefCell::new(widget),
widget_name,
origin,
widget_id,
parent_id,
}
}
pub fn get_widget_name(&self) -> String {
self.widget_name.clone()
}
pub fn get_widget_id(&self) -> i32 {
self.widget_id
}
pub fn get_parent_id(&self) -> i32 {
self.parent_id
}
}
pub struct WidgetCache {
cache: Vec<WidgetContainer>,
texture_cache: TextureCache,
}
impl WidgetCache {
pub fn new() -> Self {
Self {
cache: Vec::new(),
texture_cache: TextureCache::new(),
}
}
pub fn add_widget(&mut self, mut widget: Box<dyn Widget>, widget_name: String) -> i32 {
let origin = widget.get_config().get_point(CONFIG_ORIGIN);
let widget_id = self.cache.len();
self.cache.push(WidgetContainer::new(
widget,
widget_name,
origin,
widget_id as i32,
0,
));
(self.cache.len() - 1) as i32
}
pub fn find_widget(&mut self, x: i32, y: i32) -> i32 {
let mut found_widget_id: i32 = 0;
for i in 0..self.cache.len() {
if !self.is_hidden(i as i32) {
let start_x: i32 = self.cache[i]
.widget
.borrow_mut()
.get_config()
.get_point(CONFIG_ORIGIN)[0];
let start_y: i32 = self.cache[i]
.widget
.borrow_mut()
.get_config()
.get_point(CONFIG_ORIGIN)[1];
let end_x: i32 = start_x
+ (self.cache[i]
.widget
.borrow_mut()
.get_config()
.get_size(CONFIG_SIZE)[0] as i32);
let end_y: i32 = start_y
+ (self.cache[i]
.widget
.borrow_mut()
.get_config()
.get_size(CONFIG_SIZE)[1] as i32);
if x >= start_x && x <= end_x && y >= start_y && y <= end_y {
found_widget_id = i as i32;
}
}
}
found_widget_id
}
pub fn get_container_by_id(&mut self, id: i32) -> &mut WidgetContainer {
&mut self.cache[id as usize]
}
pub fn get_container_by_name(&mut self, name: String) -> &mut WidgetContainer {
let cache_size = self.cache.len();
for i in 0..cache_size {
if self.cache[i].get_widget_name() == name {
return self.get_container_by_id(i as i32);
}
}
self.get_container_by_id(0 as i32)
}
pub fn button_clicked(
&mut self,
widget_id: i32,
button: u8,
clicks: u8,
state: bool,
cache: &[LayoutContainer],
) {
if widget_id == -1 {
for i in 0..self.cache.len() {
if !self.is_hidden(i as i32) && self.is_enabled(i as i32) {
self.cache[i as usize].widget.borrow_mut().button_clicked(
&self.cache,
cache,
button,
clicks,
state,
);
}
}
} else if !self.is_hidden(widget_id) && self.is_enabled(widget_id) {
self.cache[widget_id as usize]
.widget
.borrow_mut()
.button_clicked(&self.cache, cache, button, clicks, state);
}
}
pub fn mouse_moved(&mut self, widget_id: i32, points: Vec<i32>, cache: &[LayoutContainer]) {
if !self.is_hidden(widget_id) && self.is_enabled(widget_id) {
self.cache[widget_id as usize]
.widget
.borrow_mut()
.mouse_moved(&self.cache, cache, points);
}
}
pub fn mouse_scrolled(&mut self, widget_id: i32, points: Vec<i32>, cache: &[LayoutContainer]) {
if !self.is_hidden(widget_id) && self.is_enabled(widget_id) {
self.cache[widget_id as usize]
.widget
.borrow_mut()
.mouse_scrolled(&self.cache, cache, points);
}
}
pub fn mouse_exited(&mut self, widget_id: i32, cache: &[LayoutContainer]) {
if !self.is_hidden(widget_id) && self.is_enabled(widget_id) {
self.cache[widget_id as usize]
.widget
.borrow_mut()
.mouse_exited(&self.cache, cache);
}
}
pub fn mouse_entered(&mut self, widget_id: i32, cache: &[LayoutContainer]) {
if !self.is_hidden(widget_id) && self.is_enabled(widget_id) {
self.cache[widget_id as usize]
.widget
.borrow_mut()
.mouse_entered(&self.cache, cache);
}
}
pub fn tick(&mut self, _cache: &[LayoutContainer]) {
let cache_size = self.cache.len();
for i in 0..cache_size {
if !self.is_hidden(i as i32) {
self.cache[i].widget.borrow_mut().tick(&self.cache, _cache);
}
}
}
pub fn other_event(&mut self, widget_id: i32, event: Event, cache: &[LayoutContainer]) {
if !self.is_hidden(widget_id) && self.is_enabled(widget_id) {
self.cache[widget_id as usize]
.widget
.borrow_mut()
.other_event(&self.cache, cache, event);
}
}
pub fn draw_loop(&mut self, c: &mut Canvas<Window>) -> bool {
let cache_size = self.cache.len();
for i in 0..cache_size {
if self.cache[i].widget.borrow_mut().is_invalidated() {
self.draw(0, c);
return true;
}
}
false
}
pub fn borrow_cache(&mut self) -> &[WidgetContainer] {
&self.cache
}
fn get_children_of(&mut self, widget_id: i32) -> Vec<i32> {
self.cache
.iter()
.filter(|x| x.parent_id == widget_id)
.map(|x| x.widget_id)
.collect()
}
fn draw(&mut self, widget_id: i32, c: &mut Canvas<Window>) {
let parents_of_widget = self.get_children_of(widget_id);
if parents_of_widget.is_empty() {
return;
}
for paint_id in &parents_of_widget {
let paint_widget = &mut self.cache[*paint_id as usize];
let is_hidden = paint_widget.widget.borrow_mut().get_config().is_hidden();
let is_enabled = paint_widget.widget.borrow_mut().get_config().is_enabled();
let widget_x = paint_widget.widget.borrow_mut().get_config().to_x(0);
let widget_y = paint_widget.widget.borrow_mut().get_config().to_y(0);
let widget_w = paint_widget
.widget
.borrow_mut()
.get_config()
.get_size(CONFIG_SIZE)[0];
let widget_h = paint_widget
.widget
.borrow_mut()
.get_config()
.get_size(CONFIG_SIZE)[1];
if !is_hidden {
match paint_widget
.widget
.borrow_mut()
.draw(c, &mut self.texture_cache)
{
Some(texture) => {
c.copy(
texture,
None,
Rect::new(widget_x, widget_y, widget_w, widget_h),
)
.unwrap();
}
None => eprintln!("No texture presented: ID={}", paint_id),
};
paint_widget.widget.borrow_mut().set_invalidated(false);
}
if *paint_id != widget_id {
self.draw(*paint_id, c);
}
if !is_enabled {
c.set_draw_color(Color::RGBA(0, 0, 0, 128));
c.draw_rect(Rect::new(widget_x, widget_y, widget_w, widget_h))
.unwrap();
}
}
}
fn is_hidden(&self, widget_id: i32) -> bool {
self.cache[widget_id as usize]
.widget
.borrow_mut()
.get_config()
.is_hidden()
}
fn is_enabled(&self, widget_id: i32) -> bool {
self.cache[widget_id as usize]
.widget
.borrow_mut()
.get_config()
.is_enabled()
}
}
impl Default for WidgetCache {
fn default() -> Self {
Self::new()
}
}