use gl::types::GLuint;
use graphics::*;
use opengl_graphics::GlGraphics;
use std::cell::RefCell;
use crate::core::callbacks::CallbackEvent;
use crate::core::layout_manager::*;
use crate::core::point::*;
use crate::widget::config::*;
use crate::widget::widget::*;
pub struct WidgetContainer {
pub widget: RefCell<Box<dyn Widget>>,
widget_name: String,
pub widget_id: i32,
parent_id: i32,
}
pub struct LayoutManagerContainer {
pub container_id: i32,
pub widget_ids: RefCell<Vec<i32>>,
pub widget_positions: RefCell<Vec<Point>>,
pub layout_manager: RefCell<Box<dyn LayoutManager>>,
}
pub struct WidgetStore {
pub widgets: Vec<WidgetContainer>,
pub layout_managers: Vec<LayoutManagerContainer>,
}
impl WidgetStore {
pub fn new() -> Self {
let mut widgets_list: Vec<WidgetContainer> = Vec::new();
let mut base_widget = CanvasWidget::new();
base_widget.config().set(
CONFIG_BODY_SIZE,
Config::Size(crate::core::point::Size { w: 800, h: 600 }),
);
widgets_list.push(WidgetContainer {
widget: RefCell::new(Box::new(base_widget)),
widget_name: String::from("_WidgetStoreBase"),
widget_id: 0,
parent_id: 0,
});
Self {
widgets: widgets_list,
layout_managers: Vec::new(),
}
}
pub fn invalidate_all_widgets(&mut self) {
self.widgets
.iter_mut()
.for_each(|x| x.widget.borrow_mut().invalidate());
}
pub fn needs_repaint(&mut self) -> bool {
self.widgets
.iter_mut()
.map(|x| x.widget.borrow_mut().is_invalidated())
.find(|x| x == &true)
.unwrap_or(false)
}
pub fn add_widget(&mut self, name: &str, widget: Box<dyn Widget>) -> i32 {
let widget_size = self.widgets.len() as i32;
let container = WidgetContainer {
widget: RefCell::new(widget),
widget_name: String::from(name),
widget_id: widget_size,
parent_id: 0,
};
container
.widget
.borrow_mut()
.config()
.set_numeric(CONFIG_WIDGET_ID, widget_size as u64);
self.widgets.push(container);
widget_size
}
pub fn add_widget_to_parent(
&mut self,
name: &str,
widget: Box<dyn Widget>,
parent_id: i32,
) -> i32 {
let widget_size = self.widgets.len() as i32;
let container = WidgetContainer {
widget: RefCell::new(widget),
widget_name: String::from(name),
widget_id: widget_size,
parent_id,
};
container
.widget
.borrow_mut()
.config()
.set_numeric(CONFIG_WIDGET_ID, widget_size as u64);
self.widgets.push(container);
widget_size
}
pub fn get_parent_of(&mut self, widget_id: i32) -> i32 {
if widget_id <= 0 {
0
} else {
self.widgets[widget_id as usize].parent_id
}
}
pub fn get_children_of(&self, parent_id: i32) -> Vec<i32> {
self.widgets
.iter()
.filter(|x| x.parent_id == parent_id)
.map(|x| x.widget_id)
.collect()
}
pub fn get_widget_id_for_point(&mut self, point: Point) -> i32 {
let mut found_id = -1;
for (pos, obj) in self.widgets.iter_mut().enumerate() {
let hidden = *&obj
.widget
.borrow_mut()
.config()
.get_toggle(CONFIG_WIDGET_HIDDEN);
let disabled = *&obj
.widget
.borrow_mut()
.config()
.get_toggle(CONFIG_WIDGET_DISABLED);
if !hidden && !disabled {
let widget_point = &obj.widget.borrow_mut().config().get_point(CONFIG_ORIGIN);
let widget_size: crate::core::point::Size =
obj.widget.borrow_mut().config().get_size(CONFIG_BODY_SIZE);
if widget_size.w > 0 && widget_size.h > 0 {
if point.x >= widget_point.x
&& point.x <= widget_point.x + widget_size.w
&& point.y >= widget_point.y
&& point.y <= widget_point.y + widget_size.h
{
found_id = pos as i32;
}
}
}
}
found_id
}
pub fn get_name_for_widget_id(&mut self, widget_id: i32) -> &str {
self.widgets[widget_id as usize].widget_name.as_str()
}
pub fn get_widget_id_for_name(&mut self, name: &str) -> i32 {
match self
.widgets
.iter_mut()
.find(|x| x.widget_name == String::from(name))
{
Some(x) => x.widget_id,
None => 0,
}
}
pub fn get_widget_for_name(&mut self, name: &str) -> &RefCell<Box<dyn Widget>> {
let widget_id = match self
.widgets
.iter_mut()
.find(|x| x.widget_name == String::from(name))
{
Some(x) => x.widget_id,
None => 0,
};
self.get_widget_for_id(widget_id)
}
pub fn get_widget_for_id(&mut self, id: i32) -> &RefCell<Box<dyn Widget>> {
&self.widgets[id as usize].widget
}
pub fn handle_event(&mut self, widget_id: i32, event: CallbackEvent) -> Option<CallbackEvent> {
self.widgets[widget_id as usize]
.widget
.borrow_mut()
.handle_event(false, event)
}
pub fn inject_event(&mut self, event: CallbackEvent) {
self.widgets.iter_mut().for_each(|x| {
x.widget.borrow_mut().handle_event(true, event.clone());
});
}
pub fn add_layout_manager(&mut self, manager: Box<dyn LayoutManager>) -> i32 {
let managers_size = self.layout_managers.len() as i32;
self.layout_managers.push(LayoutManagerContainer {
container_id: managers_size,
widget_ids: RefCell::new(Vec::new()),
widget_positions: RefCell::new(Vec::new()),
layout_manager: RefCell::new(manager),
});
managers_size
}
fn get_widget_origins(&mut self, manager_id: i32) -> Vec<Point> {
let mut widget_ids_copy = self.layout_managers[manager_id as usize]
.widget_ids
.borrow_mut()
.clone();
widget_ids_copy
.iter_mut()
.map(|x| {
self.get_widget_for_id(*x)
.borrow_mut()
.config()
.get_point(CONFIG_ORIGIN)
})
.collect()
}
fn get_widget_sizes(&mut self, manager_id: i32) -> Vec<Size> {
let mut widget_ids_copy = self.layout_managers[manager_id as usize]
.widget_ids
.borrow_mut()
.clone();
widget_ids_copy
.iter_mut()
.map(|x| {
self.get_widget_for_id(*x)
.borrow_mut()
.config()
.get_size(CONFIG_BODY_SIZE)
})
.collect()
}
pub fn do_layout_for_manager(&mut self, manager_id: i32) {
let widget_origins = self.get_widget_origins(manager_id);
let widget_sizes = self.get_widget_sizes(manager_id);
let widget_positions = self.layout_managers[manager_id as usize]
.widget_positions
.borrow()
.clone();
let container_widget_id = self.layout_managers[manager_id as usize]
.layout_manager
.borrow_mut()
.get_widget_id();
let master_container_origin = self
.get_widget_for_id(container_widget_id)
.borrow_mut()
.config()
.get_point(CONFIG_ORIGIN);
let master_container_size = self
.get_widget_for_id(container_widget_id)
.borrow_mut()
.config()
.get_size(CONFIG_BODY_SIZE);
let adjusted_sizes = self.layout_managers[manager_id as usize]
.layout_manager
.borrow_mut()
.do_layout(
master_container_origin,
master_container_size,
LayoutManagerCoordinates {
widget_origins,
widget_sizes,
widget_positions,
},
);
self.layout_managers[manager_id as usize].widget_positions =
RefCell::new(adjusted_sizes.widget_positions.clone());
let num_widgets = adjusted_sizes.widget_positions.len();
for x in 0..num_widgets {
let widget_id = self.layout_managers[manager_id as usize]
.widget_ids
.borrow_mut()[x as usize];
let point: Point = adjusted_sizes.widget_origins[x].clone();
let size: Size = adjusted_sizes.widget_sizes[x].clone();
let mut widget = self.get_widget_for_id(widget_id).borrow_mut();
widget.config().set_point(CONFIG_ORIGIN, point.x, point.y);
widget.config().set_size(CONFIG_BODY_SIZE, size.w, size.h);
}
eprintln!("Doing manager layout.");
}
pub fn add_widget_to_layout_manager(
&mut self,
name: &str,
widget: Box<dyn Widget>,
manager_id: i32,
position: Point,
) -> i32 {
let layout_container = &self.layout_managers[manager_id as usize];
let layout_manager = layout_container.layout_manager.borrow();
let layout_manager_widget_id = layout_manager.get_widget_id();
eprintln!(
"Add to layout manager: widget id={}",
layout_manager_widget_id
);
let widget_size = self.widgets.len() as i32;
let container = WidgetContainer {
widget: RefCell::new(widget),
widget_name: String::from(name),
widget_id: widget_size,
parent_id: layout_manager_widget_id,
};
container
.widget
.borrow_mut()
.config()
.set_numeric(CONFIG_WIDGET_ID, widget_size as u64);
self.widgets.push(container);
eprintln!("Added widget ID: id={}", widget_size);
layout_container.widget_ids.borrow_mut().push(widget_size);
layout_container
.widget_positions
.borrow_mut()
.push(position);
widget_size
}
pub fn resize_layout_managers(&mut self, _w: u32, _h: u32) {
let num_layout_managers = self.layout_managers.len();
for pos in 0..num_layout_managers {
let _layout_manager = self.layout_managers[pos as usize]
.layout_manager
.borrow_mut();
eprintln!("WARNING: Unimplemented resize_layout_managers");
}
}
pub fn set_hidden(&mut self, widget_id: i32, state: bool) {
if widget_id != 0 {
let children = self.get_children_of(widget_id);
children.iter().for_each(|w_id| {
if *w_id != 0 && *w_id != widget_id {
&self.widgets[*w_id as usize]
.widget
.borrow_mut()
.set_toggle(CONFIG_WIDGET_HIDDEN, state);
self.set_hidden(*w_id, state);
}
});
&self.widgets[widget_id as usize]
.widget
.borrow_mut()
.set_toggle(CONFIG_WIDGET_HIDDEN, state);
}
}
pub fn draw(&mut self, widget_id: i32, c: Context, g: &mut GlGraphics, original_fbo: GLuint) {
let parents_of_widget = self.get_children_of(widget_id);
if parents_of_widget.len() == 0 {
return;
}
for pos in 0..parents_of_widget.len() {
c.reset();
let paint_id = parents_of_widget[pos];
let paint_widget = &mut self.widgets[paint_id as usize];
let is_hidden = paint_widget
.widget
.borrow_mut()
.config()
.get_toggle(CONFIG_WIDGET_HIDDEN);
let is_invalidated = *&paint_widget.widget.borrow_mut().is_invalidated();
if !is_hidden && is_invalidated {
let origin: Point = paint_widget
.widget
.borrow_mut()
.config()
.get_point(CONFIG_ORIGIN);
let new_context: Context = Context {
viewport: c.viewport,
view: c.view,
transform: c.transform.trans(origin.x as f64, origin.y as f64),
draw_state: c.draw_state,
};
&paint_widget
.widget
.borrow_mut()
.draw(new_context, g, &c.draw_state);
if paint_widget
.widget
.borrow_mut()
.config()
.get_toggle(CONFIG_WIDGET_DISABLED)
{
&paint_widget
.widget
.borrow_mut()
.draw_disabled(new_context, g, &c.draw_state);
}
}
if parents_of_widget[pos] != widget_id {
self.draw(paint_id, c, g, original_fbo);
}
}
}
}