use fltk_sys::fl;
use crate::{
draw::{Coordinates, Rect},
prelude::{FltkError, FltkErrorKind},
};
type Coord = Coordinates<i32>;
#[derive(Debug, Copy, Clone)]
pub struct Screen {
pub n: i32,
}
impl Screen {
pub fn all_screens() -> Vec<Screen> {
let mut screens: Vec<Self> = vec![];
for n in 0..Self::count() {
screens.push(Self::new(n).unwrap());
}
screens
}
pub fn new(number: i32) -> Result<Screen, FltkError> {
let s = Screen { n: number };
if s.is_valid() {
Ok(s)
} else {
Err(FltkError::Internal(FltkErrorKind::ResourceNotFound))
}
}
pub fn new_at<C: Into<Coord> + Copy>(pos: C) -> Result<Screen, FltkError> {
let pos: Coord = pos.into();
let s = Screen {
n: unsafe { fl::Fl_screen_num(pos.x, pos.y) },
};
if Self::is_coord_inside_any_work_area(pos) {
Ok(s)
} else {
Err(FltkError::Internal(FltkErrorKind::ResourceNotFound))
}
}
pub fn new_inside<R: Into<Rect> + Copy>(rect: R) -> Result<Screen, FltkError> {
let r: Rect = rect.into();
let s = Screen {
n: unsafe { fl::Fl_screen_num_inside(r.x, r.y, r.w, r.h) },
};
if Self::is_rect_inside_any_work_area(r) {
Ok(s)
} else {
Err(FltkError::Internal(FltkErrorKind::ResourceNotFound))
}
}
pub fn scaling_supported() -> bool {
unsafe { fl::Fl_screen_scaling_supported() != 0 }
}
pub fn scaling_supported_separately() -> bool {
unsafe { fl::Fl_screen_scaling_supported() == 2 }
}
pub fn count() -> i32 {
unsafe { fl::Fl_screen_count() }
}
pub fn num_at<C: Into<Coord> + Copy>(pos: C) -> Result<i32, FltkError> {
let pos: Coord = pos.into();
if Self::is_coord_inside_any_work_area(pos) {
Ok(unsafe { fl::Fl_screen_num(pos.x, pos.y) })
} else {
Err(FltkError::Internal(FltkErrorKind::ResourceNotFound))
}
}
pub fn work_area_at<C: Into<Coord> + Copy>(pos: C) -> Result<Rect, FltkError> {
let pos: Coord = pos.into();
if Self::is_coord_inside_any_work_area(pos) {
let (mut x, mut y, mut w, mut h) = (0, 0, 0, 0);
unsafe { fl::Fl_screen_work_area_at(&mut x, &mut y, &mut w, &mut h, pos.x, pos.y) }
Ok(Rect { x, y, w, h })
} else {
Err(FltkError::Internal(FltkErrorKind::ResourceNotFound))
}
}
pub fn work_area_mouse() -> Rect {
let (mut x, mut y, mut w, mut h) = (0, 0, 0, 0);
unsafe { fl::Fl_screen_work_area_mouse(&mut x, &mut y, &mut w, &mut h) }
Rect { x, y, w, h }
}
pub fn work_area_num(number: i32) -> Result<Rect, FltkError> {
let s = Screen { n: number };
if s.is_valid() {
let (mut x, mut y, mut w, mut h) = (0, 0, 0, 0);
unsafe { fl::Fl_screen_work_area(&mut x, &mut y, &mut w, &mut h, number) }
Ok(Rect { x, y, w, h })
} else {
Err(FltkError::Internal(FltkErrorKind::ResourceNotFound))
}
}
pub fn xywh_at<C: Into<Coord> + Copy>(pos: C) -> Result<Rect, FltkError> {
let pos: Coord = pos.into();
if Self::is_coord_inside_any_xywh(pos) {
let (mut x, mut y, mut w, mut h) = (0, 0, 0, 0);
unsafe { fl::Fl_screen_xywh_at(&mut x, &mut y, &mut w, &mut h, pos.x, pos.y) }
Ok(Rect { x, y, w, h })
} else {
Err(FltkError::Internal(FltkErrorKind::ResourceNotFound))
}
}
pub fn xywh_inside<R: Into<Rect> + Copy>(rect: R) -> Result<Rect, FltkError> {
let r: Rect = rect.into();
if Self::is_rect_inside_any_xywh(r) {
let (mut x, mut y, mut w, mut h) = (0, 0, 0, 0);
unsafe { fl::Fl_screen_xywh_inside(&mut x, &mut y, &mut w, &mut h, r.x, r.y, r.w, r.h) }
Ok(Rect { x, y, w, h })
} else {
Err(FltkError::Internal(FltkErrorKind::ResourceNotFound))
}
}
pub fn xywh_mouse() -> Rect {
let (mut x, mut y, mut w, mut h) = (0, 0, 0, 0);
unsafe { fl::Fl_screen_xywh_mouse(&mut x, &mut y, &mut w, &mut h) }
Rect { x, y, w, h }
}
pub fn xywh_num(number: i32) -> Result<Rect, FltkError> {
let s = Screen { n: number };
if s.is_valid() {
let (mut x, mut y, mut w, mut h) = (0, 0, 0, 0);
unsafe {
fl::Fl_screen_xywh(&mut x, &mut y, &mut w, &mut h, number);
}
Ok(Rect { x, y, w, h })
} else {
Err(FltkError::Internal(FltkErrorKind::ResourceNotFound))
}
}
pub fn keyboard_scaling(value: bool) {
unsafe { fl::Fl_keyboard_screen_scaling(value as _) }
}
pub fn is_valid(&self) -> bool {
self.n >= 0 && self.n < Self::count()
}
pub fn dpi(&self) -> (f32, f32) {
let mut h: f32 = 0.;
let mut v: f32 = 0.;
unsafe {
fl::Fl_screen_dpi(&mut h, &mut v, self.n);
}
(h, v)
}
pub fn set_scale(&self, factor: f32) {
unsafe { fl::Fl_set_screen_scale(self.n, factor) }
}
pub fn scale(&self) -> f32 {
unsafe { fl::Fl_screen_scale(self.n) }
}
pub fn work_area(&self) -> Rect {
let (mut x, mut y, mut w, mut h) = (0, 0, 0, 0);
unsafe { fl::Fl_screen_work_area(&mut x, &mut y, &mut w, &mut h, self.n) }
Rect { x, y, w, h }
}
pub fn y(&self) -> i32 {
self.work_area().y
}
pub fn x(&self) -> i32 {
self.work_area().x
}
pub fn w(&self) -> i32 {
self.work_area().w
}
pub fn h(&self) -> i32 {
self.work_area().h
}
pub fn top_left(&self) -> Coord {
self.work_area().top_left()
}
pub fn bottom_right(&self) -> Coord {
self.work_area().bottom_right()
}
fn is_coord_inside_any_work_area<C: Into<Coord> + Copy>(c: C) -> bool {
let c: Coord = c.into();
let main_wa: Rect = screen_work_area(0).into();
!(screen_num(c.x, c.y) == 0
&& (c.x < main_wa.x
|| c.y < main_wa.y
|| c.x >= main_wa.bottom_right().x
|| c.y >= main_wa.bottom_right().y))
}
fn is_rect_inside_any_work_area<R: Into<Rect> + Copy>(r: R) -> bool {
let r: Rect = r.into();
Self::is_coord_inside_any_work_area(r.top_left())
&& Self::is_coord_inside_any_work_area(r.bottom_right())
}
fn is_coord_inside_any_xywh<C: Into<Coord> + Copy>(c: C) -> bool {
let c: Coord = c.into();
let main_xywh: Rect = screen_xywh(0).into();
!(screen_num(c.x, c.y) == 0
&& (c.x < main_xywh.x
|| c.y < main_xywh.y
|| c.x >= main_xywh.bottom_right().x
|| c.y >= main_xywh.bottom_right().y))
}
fn is_rect_inside_any_xywh<R: Into<Rect> + Copy>(r: R) -> bool {
let r: Rect = r.into();
Self::is_coord_inside_any_xywh(r.top_left())
&& Self::is_coord_inside_any_xywh(r.bottom_right())
}
}
pub fn screen_size() -> (f64, f64) {
unsafe { ((fl::Fl_screen_w() as f64), (fl::Fl_screen_h() as f64)) }
}
pub fn screen_coords() -> (i32, i32) {
unsafe { (fl::Fl_screen_x(), fl::Fl_screen_y()) }
}
pub fn set_screen_scale(n: i32, factor: f32) {
unsafe { fl::Fl_set_screen_scale(n, factor) }
}
pub fn screen_scale(screen_num: i32) -> f32 {
unsafe { fl::Fl_screen_scale(screen_num) }
}
pub fn screen_scaling_supported() -> bool {
unsafe { fl::Fl_screen_scaling_supported() != 0 }
}
pub fn screen_count() -> i32 {
unsafe { fl::Fl_screen_count() }
}
pub fn screen_num(x: i32, y: i32) -> i32 {
unsafe { fl::Fl_screen_num(x, y) }
}
pub fn screen_num_inside<R: Into<Rect> + Copy>(rect: R) -> i32 {
let r: Rect = rect.into();
unsafe { fl::Fl_screen_num_inside(r.x, r.y, r.w, r.h) }
}
pub fn screen_dpi(screen_num: i32) -> (f32, f32) {
let (mut h, mut v) = (0_f32, 0_f32);
unsafe {
fl::Fl_screen_dpi(&mut h, &mut v, screen_num);
}
(h, v)
}
pub fn screen_xywh(screen_num: i32) -> (i32, i32, i32, i32) {
let (mut x, mut y, mut w, mut h) = (0, 0, 0, 0);
unsafe {
fl::Fl_screen_xywh(&mut x, &mut y, &mut w, &mut h, screen_num);
}
(x, y, w, h)
}
pub fn screen_work_area(screen_num: i32) -> (i32, i32, i32, i32) {
let (mut x, mut y, mut w, mut h) = (0, 0, 0, 0);
unsafe {
fl::Fl_screen_work_area(&mut x, &mut y, &mut w, &mut h, screen_num);
}
(x, y, w, h)
}
pub fn keyboard_screen_scaling(value: bool) {
unsafe { fl::Fl_keyboard_screen_scaling(value as _) }
}