rpg_base/rpg_components/src/items/tooltip.rs

145 lines
3.9 KiB
Rust

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<Grid>,
gui: Arc<GuiBuilder>,
}
impl Tooltip {
pub fn new(grid: Arc<Grid>, gui: Arc<GuiBuilder>) -> 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<Arc<GuiBuilder>> for Tooltip {
fn into(self) -> Arc<GuiBuilder> {
self.gui
}
}