2020-04-17 21:30:01 +00:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
use parking_lot::Mutex;
|
2020-04-17 13:33:52 +00:00
|
|
|
|
|
|
|
use crate::*;
|
|
|
|
|
|
|
|
/// Contains the input, style and output of all GUI commands.
|
|
|
|
pub struct Context {
|
|
|
|
/// The default style for new regions
|
|
|
|
pub(crate) style: Mutex<Style>,
|
|
|
|
pub(crate) fonts: Arc<Fonts>,
|
|
|
|
pub(crate) input: GuiInput,
|
|
|
|
pub(crate) memory: Mutex<Memory>,
|
|
|
|
pub(crate) graphics: Mutex<GraphicLayers>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Clone for Context {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
Context {
|
|
|
|
style: Mutex::new(self.style()),
|
|
|
|
fonts: self.fonts.clone(),
|
|
|
|
input: self.input,
|
2020-04-17 21:30:01 +00:00
|
|
|
memory: Mutex::new(self.memory.lock().clone()),
|
|
|
|
graphics: Mutex::new(self.graphics.lock().clone()),
|
2020-04-17 13:33:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Context {
|
|
|
|
pub fn new(pixels_per_point: f32) -> Context {
|
|
|
|
Context {
|
|
|
|
style: Default::default(),
|
|
|
|
fonts: Arc::new(Fonts::new(pixels_per_point)),
|
|
|
|
input: Default::default(),
|
|
|
|
memory: Default::default(),
|
|
|
|
graphics: Default::default(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn input(&self) -> &GuiInput {
|
|
|
|
&self.input
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn style(&self) -> Style {
|
2020-04-17 21:30:01 +00:00
|
|
|
*self.style.lock()
|
2020-04-17 13:33:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_style(&self, style: Style) {
|
2020-04-17 21:30:01 +00:00
|
|
|
*self.style.lock() = style;
|
2020-04-17 13:33:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: move
|
|
|
|
pub fn new_frame(&mut self, gui_input: GuiInput) {
|
|
|
|
self.input = gui_input;
|
|
|
|
if !gui_input.mouse_down || gui_input.mouse_pos.is_none() {
|
2020-04-17 21:30:01 +00:00
|
|
|
self.memory.lock().active_id = None;
|
2020-04-17 13:33:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-17 21:22:28 +00:00
|
|
|
pub fn drain_paint_lists(&self) -> Vec<PaintCmd> {
|
2020-04-17 21:30:01 +00:00
|
|
|
let memory = self.memory.lock();
|
|
|
|
self.graphics.lock().drain(&memory.window_order).collect()
|
2020-04-17 21:22:28 +00:00
|
|
|
}
|
|
|
|
|
2020-04-17 13:33:52 +00:00
|
|
|
/// Is the user interacting with anything?
|
|
|
|
pub fn any_active(&self) -> bool {
|
2020-04-17 21:30:01 +00:00
|
|
|
self.memory.lock().active_id.is_some()
|
2020-04-17 13:33:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn interact(&self, layer: Layer, rect: Rect, interaction_id: Option<Id>) -> InteractInfo {
|
2020-04-17 21:30:01 +00:00
|
|
|
let mut memory = self.memory.lock();
|
2020-04-17 13:33:52 +00:00
|
|
|
|
|
|
|
let hovered = if let Some(mouse_pos) = self.input.mouse_pos {
|
|
|
|
if rect.contains(mouse_pos) {
|
|
|
|
let is_something_else_active =
|
|
|
|
memory.active_id.is_some() && memory.active_id != interaction_id;
|
|
|
|
|
|
|
|
!is_something_else_active && layer == memory.layer_at(mouse_pos)
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
};
|
|
|
|
let active = if interaction_id.is_some() {
|
|
|
|
if hovered && self.input.mouse_clicked {
|
|
|
|
memory.active_id = interaction_id;
|
|
|
|
}
|
|
|
|
memory.active_id == interaction_id
|
|
|
|
} else {
|
|
|
|
false
|
|
|
|
};
|
|
|
|
|
|
|
|
let clicked = hovered && self.input.mouse_released;
|
|
|
|
|
|
|
|
InteractInfo {
|
|
|
|
rect,
|
|
|
|
hovered,
|
|
|
|
clicked,
|
|
|
|
active,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Context {
|
|
|
|
pub fn style_ui(&self, region: &mut Region) {
|
|
|
|
let mut style = self.style();
|
|
|
|
style.ui(region);
|
|
|
|
self.set_style(style);
|
|
|
|
}
|
|
|
|
}
|