sge_ui 1.2.0

UI library for SGE
Documentation
use std::cell::Cell;

use sge_input::last_cursor_pos;
use sge_vectors::vec2;

use super::*;

#[derive(Debug)]
pub struct Tooltip {
    inner: Child,
    overlay: Child,
    positioning: TooltipPosition,
    offset: f32,
    overlay_area: Cell<Area>,
}

#[derive(Debug, Clone, Copy)]
pub enum TooltipPosition {
    Top,
    Left,
    Bottom,
    Right,
    BelowCursorRight,
    AboveCursorRight,
    BelowCursorLeft,
    AboveCursorLeft,
}

impl Tooltip {
    pub fn new(inner: Child, overlay: Child, offset: f32, positioning: TooltipPosition) -> UiRef {
        Self {
            inner: inner,
            overlay: overlay,
            positioning,
            offset,
            overlay_area: Area::new(Vec2::ZERO, Vec2::ZERO).into(),
        }
        .to_ref()
    }

    pub(crate) fn actually_draw(&self) {
        draw_ui_in_area(self.overlay, self.overlay_area.get());
    }
}

impl UiNode for Tooltip {
    fn draw(&self, area: Area, ui: &UiState) -> Vec2 {
        let size = self.inner.draw(area, ui);

        let child_area = Area::new(area.top_left, size);
        if ui.is_hovered(child_area) {
            let size = self.overlay.preferred_dimensions();
            let pos = match self.positioning {
                TooltipPosition::Top => Vec2::new(
                    child_area.top_left.x + (child_area.width() - size.x) / 2.0,
                    child_area.top() - size.y - self.offset,
                ),
                TooltipPosition::Left => Vec2::new(
                    child_area.left() - size.x - self.offset,
                    child_area.top_left.y + (child_area.height() - size.y) / 2.0,
                ),
                TooltipPosition::Bottom => Vec2::new(
                    child_area.top_left.x + (child_area.width() - size.x) / 2.0,
                    child_area.bottom() + self.offset,
                ),
                TooltipPosition::Right => Vec2::new(
                    child_area.right() + self.offset,
                    child_area.top_left.y + (child_area.height() - size.y) / 2.0,
                ),
                TooltipPosition::AboveCursorRight => last_cursor_pos() - vec2(0.0, size.y),
                TooltipPosition::BelowCursorRight => last_cursor_pos(),
                TooltipPosition::AboveCursorLeft => last_cursor_pos() - size,
                TooltipPosition::BelowCursorLeft => last_cursor_pos() - vec2(size.x, 0.0),
            };

            self.overlay_area.set(Area::new(pos, size));
            get_ui_storage().tooltips.push(self as *const Self);
        }

        size
    }

    fn preferred_dimensions(&self) -> Vec2 {
        self.inner.preferred_dimensions()
    }

    fn size(&self, area: Area) -> Vec2 {
        self.inner.size(area)
    }
}