use anyhow::{Result, bail}; use engine::prelude::*; use std::sync::Arc; pub struct FittingResult { pub fit: bool, pub start: i32, pub extent: u32, } pub struct Tooltip { grid: Arc, gui: Arc, } impl Tooltip { pub fn new(grid: Arc, gui: Arc) -> Self { Self { grid, gui } } pub fn enable(&self, gui_handler: &mut GuiHandler) -> Result<()> { self.gui.enable(gui_handler) } pub fn check_fitting( &self, gui_handler: &GuiHandler, ) -> Result<(FittingResult, FittingResult)> { if !self.grid.visible() { bail!("enable item tooltip first"); } let (x, y, w, h) = self.grid.position_extent(); Ok(( FittingResult { fit: (x + w as i32) <= gui_handler.width() as i32, start: x, extent: w, }, FittingResult { fit: (y + h as i32) <= gui_handler.height() as i32, start: y, extent: h, }, )) } pub fn move_to(&self, gui_handler: &mut GuiHandler, x: i32, y: i32) -> Result<()> { self.grid.change_position_unscaled(gui_handler, x, y) } pub fn position_extent(&self) -> (i32, i32, u32, u32) { self.grid.position_extent() } pub fn perform_single_check(&self, gui_handler: &mut GuiHandler, x: i32, y: i32) -> Result<()> { let (width_fitting, height_fitting) = self.check_fitting(gui_handler)?; let mut width_shift = None; let mut height_shift = None; let gui_pos = self.position_extent(); if !width_fitting.fit { width_shift = Some(x - gui_pos.2 as i32); } if !height_fitting.fit { height_shift = Some(y - gui_pos.3 as i32); } if width_shift.is_some() || height_shift.is_some() { self.move_to( gui_handler, width_shift.unwrap_or(gui_pos.0), height_shift.unwrap_or(gui_pos.1), )?; } Ok(()) } pub fn perform_double_check( &self, other: &Self, gui_handler: &mut GuiHandler, x: i32, spacing: u32, ) -> Result<()> { let (_left_width_fitting, left_height_fitting) = self.check_fitting(gui_handler)?; let (right_width_fitting, right_height_fitting) = other.check_fitting(gui_handler)?; let mut width_shift = None; let mut height_shift = None; let left_gui_pos = self.position_extent(); let right_gui_pos = other.position_extent(); if !right_width_fitting.fit { width_shift = Some(x - right_gui_pos.2 as i32 - spacing as i32); } let window_height = gui_handler.height(); if !left_height_fitting.fit { height_shift = Some(window_height as i32 - left_gui_pos.3 as i32 - spacing as i32); } if !right_height_fitting.fit { let right = window_height as i32 - right_gui_pos.3 as i32 - spacing as i32; match height_shift { Some(current) => { if current > right { height_shift = Some(right); } } None => { height_shift = Some(right); } } } if width_shift.is_some() || height_shift.is_some() { let width = width_shift.unwrap_or(right_gui_pos.0); let height = height_shift.unwrap_or(right_gui_pos.1); other.move_to(gui_handler, width, height)?; self.move_to( gui_handler, width - spacing as i32 - left_gui_pos.2 as i32, height, )?; } Ok(()) } } impl Into> for Tooltip { fn into(self) -> Arc { self.gui } }