use std::cell::RefCell;
use std::collections::HashMap;
use std::collections::HashSet;
use crate::core::callbacks::*;
use crate::core::point::*;
use crate::core::widget_store::*;
use crate::widget::widget::*;
use piston_window::*;
pub struct Pushrod {
window: PistonWindow,
pub widget_store: RefCell<WidgetStore>,
}
impl Pushrod {
pub fn new(window: PistonWindow) -> Self {
Self {
window,
widget_store: RefCell::new(WidgetStore::new()),
}
}
pub fn get_factory(&mut self) -> &mut GfxFactory {
&mut self.window.factory
}
pub fn add_widget(&mut self, name: &str, widget: Box<dyn Widget>) -> i32 {
self.widget_store.borrow_mut().add_widget(name, widget)
}
pub fn add_widget_to_parent(
&mut self,
name: &str,
widget: Box<dyn Widget>,
parent_id: i32,
) -> i32 {
self.widget_store
.borrow_mut()
.add_widget_to_parent(name, widget, parent_id)
}
fn handle_draw(&mut self, event: &Event) {
let widgets = &mut self.widget_store.borrow_mut();
self.window.draw_2d(event, |c, g| widgets.draw(0, c, g));
}
fn handle_event(
&mut self,
widget_id: i32,
event_handler: &mut PushrodCallbackEvents,
event: CallbackEvent,
) {
if widget_id == -1 {
return;
}
let injectable_event = self
.widget_store
.borrow_mut()
.handle_event(widget_id, event.clone());
event_handler.handle_event(event.clone(), &mut self.widget_store.borrow_mut());
match injectable_event {
Some(new_event) => {
event_handler.handle_event(new_event.clone(), &mut self.widget_store.borrow_mut())
}
None => (),
}
}
fn handle_resize(&mut self, width: u32, height: u32) {
eprintln!("[Resize] W={} H={}", width, height);
}
pub fn run(&mut self, event_handler: &mut PushrodCallbackEvents) {
let mut last_widget_id = -1;
let mut previous_mouse_position: Point = make_origin_point();
let mut button_map: HashMap<i32, HashSet<Button>> = HashMap::new();
let injectable_map: Vec<i32> = self
.widget_store
.borrow_mut()
.widgets
.iter()
.filter(|x| x.widget.borrow_mut().injects_events())
.map(|x| x.widget_id)
.collect();
eprintln!("Injectable Map: {:?}", injectable_map);
eprintln!("Window Size: {:?}", self.window.size());
eprintln!("Draw Size: {:?}", self.window.window.draw_size());
self.window.set_max_fps(30);
self.widget_store.borrow_mut().invalidate_all_widgets();
while let Some(ref event) = &self.window.next() {
event.mouse_cursor(|x, y| {
let mouse_point = make_point_f64(x, y);
if mouse_point.x != previous_mouse_position.x
|| mouse_point.y != previous_mouse_position.y
{
previous_mouse_position = mouse_point.clone();
let current_widget_id = self
.widget_store
.borrow_mut()
.get_widget_id_for_point(mouse_point.clone());
if current_widget_id != -1 {
self.handle_event(
current_widget_id,
event_handler,
CallbackEvent::MouseMoved {
widget_id: current_widget_id,
point: mouse_point.clone(),
},
);
}
if current_widget_id != last_widget_id {
if last_widget_id != -1 {
self.handle_event(
last_widget_id,
event_handler,
CallbackEvent::MouseExited {
widget_id: last_widget_id,
},
);
}
last_widget_id = current_widget_id;
if last_widget_id != -1 {
self.handle_event(
last_widget_id,
event_handler,
CallbackEvent::MouseEntered {
widget_id: last_widget_id,
},
);
}
}
}
});
event.mouse_scroll(|x, y| {
let mouse_point = make_point_f64(x, y);
if last_widget_id != -1 {
self.handle_event(
last_widget_id,
event_handler,
CallbackEvent::MouseScrolled {
widget_id: last_widget_id,
point: mouse_point.clone(),
},
);
}
});
event.button(|args| match args.state {
ButtonState::Press => {
button_map
.entry(last_widget_id)
.or_insert(HashSet::new())
.insert(args.button);
self.handle_event(
last_widget_id,
event_handler,
CallbackEvent::MouseButtonDown {
widget_id: last_widget_id,
button: args.button,
},
);
}
ButtonState::Release => {
let button_set = button_map.entry(last_widget_id).or_insert(HashSet::new());
if button_set.contains(&args.button) {
button_set.remove(&args.button);
self.handle_event(
last_widget_id,
event_handler,
CallbackEvent::MouseButtonUpInside {
widget_id: last_widget_id,
button: args.button,
},
);
} else {
for (widget_id, button_set) in button_map.iter_mut() {
if button_set.contains(&args.button) {
self.handle_event(
*widget_id,
event_handler,
CallbackEvent::MouseButtonUpOutside {
widget_id: *widget_id,
button: args.button,
},
);
button_set.remove(&args.button);
}
}
}
}
});
event.resize(|w, h| {
self.handle_resize(w as u32, h as u32);
event_handler.handle_event(
CallbackEvent::WindowResized {
size: crate::core::point::Size {
w: w as i32,
h: h as i32,
},
},
&mut self.widget_store.borrow_mut(),
);
});
event.focus(|focused| {
self.handle_event(
last_widget_id,
event_handler,
CallbackEvent::WindowFocused { flag: focused },
);
});
match event {
Event::Input(Input::Button(ButtonArgs {
state,
button: Button::Keyboard(key),
scancode: _,
})) => {
self.handle_event(
last_widget_id,
event_handler,
CallbackEvent::KeyPressed {
widget_id: last_widget_id,
key: *key,
state: *state,
},
);
}
_ => {}
};
event.resize(|_, _| {
self.widget_store.borrow_mut().invalidate_all_widgets();
});
event.render(|_| {
self.widget_store.borrow_mut().invalidate_all_widgets();
injectable_map.iter().for_each(|widget_id| {
let injectable_event = self
.widget_store
.borrow_mut()
.get_widget_for_id(*widget_id)
.borrow_mut()
.inject_event(*widget_id);
match injectable_event {
Some(x) => {
self.handle_event(*widget_id, event_handler, x.clone());
self.widget_store.borrow_mut().inject_event(x.clone());
}
None => (),
}
});
self.handle_draw(&event);
});
}
}
}