rgpui 0.1.1

GUI UI framework
Documentation
//! 窗口位置计算器
//!
//! 根据语义化 [`WindowPosition`] 计算窗口边界。

use crate::{Bounds, Pixels, PlatformDisplay, Point, Size, WindowPosition, point};
use std::rc::Rc;

/// 根据所需大小和语义位置计算窗口边界。
pub fn compute_window_bounds(
    size: Size<Pixels>,
    position: &WindowPosition,
    displays: &[Rc<dyn PlatformDisplay>],
    primary_display: Option<&Rc<dyn PlatformDisplay>>,
) -> Bounds<Pixels> {
    match position {
        WindowPosition::Center => {
            if let Some(display) = primary_display {
                center_in(size, display.bounds())
            } else {
                Bounds::new(Point::default(), size)
            }
        }
        WindowPosition::CenterOnDisplay(id) => {
            let display_bounds = displays.iter().find(|d| d.id() == *id).map(|d| d.bounds());
            if let Some(bounds) = display_bounds {
                center_in(size, bounds)
            } else if let Some(display) = primary_display {
                center_in(size, display.bounds())
            } else {
                Bounds::new(Point::default(), size)
            }
        }
        WindowPosition::TrayCenter(tray_bounds) => {
            // 在托盘图标上方居中显示窗口
            let x = tray_bounds.origin.x + (tray_bounds.size.width - size.width) * 0.5;
            let y = tray_bounds.origin.y + tray_bounds.size.height;
            Bounds::new(point(x, y), size)
        }
        WindowPosition::TopRight { margin } => {
            corner_position(size, primary_display, *margin, true, false)
        }
        WindowPosition::BottomRight { margin } => {
            corner_position(size, primary_display, *margin, true, true)
        }
        WindowPosition::TopLeft { margin } => {
            corner_position(size, primary_display, *margin, false, false)
        }
        WindowPosition::BottomLeft { margin } => {
            corner_position(size, primary_display, *margin, false, true)
        }
    }
}

/// 在给定显示区域内居中
fn center_in(size: Size<Pixels>, display: Bounds<Pixels>) -> Bounds<Pixels> {
    let x = display.origin.x + (display.size.width - size.width) * 0.5;
    let y = display.origin.y + (display.size.height - size.height) * 0.5;
    Bounds::new(point(x, y), size)
}

/// 计算角落位置
fn corner_position(
    size: Size<Pixels>,
    primary_display: Option<&Rc<dyn PlatformDisplay>>,
    margin: Pixels,
    right: bool,
    bottom: bool,
) -> Bounds<Pixels> {
    if let Some(display) = primary_display {
        let db = display.bounds();
        let x = if right {
            db.origin.x + db.size.width - size.width - margin
        } else {
            db.origin.x + margin
        };
        let y = if bottom {
            db.origin.y + db.size.height - size.height - margin
        } else {
            db.origin.y + margin
        };
        Bounds::new(point(x, y), size)
    } else {
        Bounds::new(Point::default(), size)
    }
}