perspective_viewer/utils/
modal_position.rs1use perspective_js::utils::global;
14use web_sys::*;
15
16#[derive(Clone, Copy, Debug, Default)]
18pub enum ModalAnchor {
19 BottomRightTopLeft,
20 BottomRightBottomLeft,
21 BottomRightTopRight,
22 BottomLeftTopLeft,
23 TopRightTopLeft,
24 TopRightBottomRight,
25
26 #[default]
27 TopLeftBottomLeft,
28}
29
30impl ModalAnchor {
31 pub const fn is_rev_vert(&self) -> bool {
32 matches!(
33 self,
34 Self::BottomLeftTopLeft
35 | Self::BottomRightBottomLeft
36 | Self::BottomRightTopLeft
37 | Self::BottomRightTopRight
38 )
39 }
40}
41
42pub fn calc_relative_position(
46 elem: &HtmlElement,
47 _top: f64,
48 left: f64,
49 height: f64,
50 width: f64,
51) -> ModalAnchor {
52 let window = global::window();
53 let rect = elem.get_bounding_client_rect();
54 let inner_width = window.inner_width().unwrap().as_f64().unwrap();
55 let inner_height = window.inner_height().unwrap().as_f64().unwrap();
56 let rect_top = rect.top();
57 let rect_height = rect.height();
58 let rect_width = rect.width();
59 let rect_left = rect.left();
60
61 let elem_over_y = inner_height < rect_top + rect_height;
62 let elem_over_x = inner_width < rect_left + rect_width;
63 let target_over_x = inner_width < rect_left + width;
64 let target_over_y = inner_height < rect_top + height;
65
66 match (elem_over_y, elem_over_x, target_over_x, target_over_y) {
68 (true, _, true, true) => ModalAnchor::BottomRightTopLeft,
69 (true, _, true, false) => ModalAnchor::BottomRightBottomLeft,
70 (true, true, false, _) => {
71 if left + width - rect_width > 0.0 {
72 ModalAnchor::BottomRightTopRight
73 } else {
74 ModalAnchor::BottomLeftTopLeft
75 }
76 },
77 (true, false, false, _) => ModalAnchor::BottomLeftTopLeft,
78 (false, true, true, _) => ModalAnchor::TopRightTopLeft,
79 (false, true, false, _) => {
80 if left + width - rect_width > 0.0 {
81 ModalAnchor::TopRightBottomRight
82 } else {
83 ModalAnchor::TopLeftBottomLeft
84 }
85 },
86 _ => ModalAnchor::TopLeftBottomLeft,
87 }
88}
89
90pub fn calc_anchor_position(anchor: ModalAnchor, target: &DomRect, modal: &DomRect) -> (f64, f64) {
94 let height = target.height();
95 let width = target.width();
96 let top = target.top();
97 let left = target.left();
98 let rect_height = modal.height();
99 let rect_width = modal.width();
100
101 match anchor {
102 ModalAnchor::BottomRightTopLeft => (top - rect_height, left - rect_width + 1.0),
103 ModalAnchor::BottomRightBottomLeft => (top - rect_height + height, left - rect_width + 1.0),
104 ModalAnchor::BottomRightTopRight => (top - rect_height + 1.0, left + width - rect_width),
105 ModalAnchor::BottomLeftTopLeft => (top - rect_height + 1.0, left),
106 ModalAnchor::TopRightTopLeft => (top, left - rect_width + 1.0),
107 ModalAnchor::TopRightBottomRight => (top + height - 1.0, left + width - rect_width),
108 ModalAnchor::TopLeftBottomLeft => (top + height - 1.0, left),
109 }
110}