use std::{ collections::HashSet, hash::Hash, sync::{Arc, Mutex}, }; use crate::{ color::{self, Color}, font::TextFragment, fonts::{Fonts, TextStyle}, math::*, style::Style, types::*, widgets::{Label, Widget}, }; // ---------------------------------------------------------------------------- // TODO: rename GuiResponse pub struct GuiResponse { /// The mouse is hovering above this pub hovered: bool, /// The mouse went got pressed on this thing this frame pub clicked: bool, /// The mouse is interacting with this thing (e.g. dragging it) pub active: bool, /// The region of the screen we are talking about pub rect: Rect, /// Used for showing a popup (if any) data: Arc, } impl GuiResponse { /// Show some stuff if the item was hovered pub fn tooltip(&mut self, add_contents: F) -> &mut Self where F: FnOnce(&mut Region), { if self.hovered { if let Some(mouse_pos) = self.data.input().mouse_pos { let window_pos = mouse_pos + vec2(16.0, 16.0); show_popup(&self.data, window_pos, add_contents); } } self } /// Show this text if the item was hovered pub fn tooltip_text>(&mut self, text: S) -> &mut Self { self.tooltip(|popup| { popup.add(Label::new(text)); }) } } // ---------------------------------------------------------------------------- #[derive(Clone, Debug, Default)] pub struct Memory { /// The widget being interacted with (e.g. dragged, in case of a slider). active_id: Option, /// Which foldable regions are open. open_foldables: HashSet, } // ---------------------------------------------------------------------------- #[derive(Clone, Copy, Debug, PartialEq)] pub enum Direction { Horizontal, Vertical, } impl Default for Direction { fn default() -> Direction { Direction::Vertical } } #[derive(Clone, Copy, Debug, PartialEq)] pub enum Align { /// Left/Top Min, /// Note: requires a bounded/known available_width. Center, /// Right/Bottom /// Note: requires a bounded/known available_width. Max, } impl Default for Align { fn default() -> Align { Align::Min } } // ---------------------------------------------------------------------------- pub type Id = u64; pub fn make_id(source: &H) -> Id { use std::hash::Hasher; let mut hasher = std::collections::hash_map::DefaultHasher::new(); source.hash(&mut hasher); hasher.finish() } // ---------------------------------------------------------------------------- /// TODO: improve this #[derive(Clone, Default)] pub struct GraphicLayers { pub(crate) graphics: Vec, pub(crate) hovering_graphics: Vec, } impl GraphicLayers { pub fn drain(&mut self) -> impl ExactSizeIterator { // TODO: there must be a nicer way to do this? let mut all_commands: Vec<_> = self.graphics.drain(..).collect(); all_commands.extend(self.hovering_graphics.drain(..)); all_commands.into_iter() } } // ---------------------------------------------------------------------------- // TODO: give a better name. /// Contains the input, style and output of all GUI commands. pub struct Data { /// The default style for new regions pub(crate) style: Mutex