layer_shika_domain/value_objects/
popup_request.rs

1#![allow(clippy::pub_use)]
2
3pub use super::handle::PopupHandle;
4use super::popup_positioning_mode::PopupPositioningMode;
5
6/// Configuration for showing a popup window
7///
8/// Use `PopupRequest::builder()` to construct with fluent API.
9#[derive(Debug, Clone)]
10pub struct PopupRequest {
11    pub component: String,
12    pub placement: PopupPlacement,
13    pub size: PopupSize,
14    pub mode: PopupPositioningMode,
15    pub grab: bool,
16    pub close_callback: Option<String>,
17    pub resize_callback: Option<String>,
18}
19
20impl PopupRequest {
21    #[must_use]
22    pub fn new(
23        component: String,
24        placement: PopupPlacement,
25        size: PopupSize,
26        mode: PopupPositioningMode,
27    ) -> Self {
28        Self {
29            component,
30            placement,
31            size,
32            mode,
33            grab: false,
34            close_callback: None,
35            resize_callback: None,
36        }
37    }
38
39    #[must_use]
40    pub fn builder(component: String) -> PopupRequestBuilder {
41        PopupRequestBuilder::new(component)
42    }
43}
44
45/// Where to position a popup relative to the surface
46#[derive(Debug, Clone, Copy)]
47pub enum PopupPlacement {
48    /// At absolute logical position
49    AtPosition { x: f32, y: f32 },
50    /// At current cursor position
51    AtCursor,
52    /// Relative to a logical rectangle
53    AtRect { x: f32, y: f32, w: f32, h: f32 },
54}
55
56impl PopupPlacement {
57    #[must_use]
58    pub const fn at_position(x: f32, y: f32) -> Self {
59        Self::AtPosition { x, y }
60    }
61
62    #[must_use]
63    pub const fn at_cursor() -> Self {
64        Self::AtCursor
65    }
66
67    #[must_use]
68    pub const fn at_rect(x: f32, y: f32, w: f32, h: f32) -> Self {
69        Self::AtRect { x, y, w, h }
70    }
71
72    #[must_use]
73    pub const fn position(&self) -> (f32, f32) {
74        match *self {
75            Self::AtPosition { x, y } | Self::AtRect { x, y, .. } => (x, y),
76            Self::AtCursor => (0.0, 0.0),
77        }
78    }
79}
80
81/// How to size a popup window
82#[derive(Debug, Clone, Copy)]
83pub enum PopupSize {
84    /// Fixed width and height in logical pixels
85    Fixed { w: f32, h: f32 },
86    /// Size automatically based on content
87    Content,
88}
89
90impl PopupSize {
91    #[must_use]
92    pub const fn fixed(w: f32, h: f32) -> Self {
93        Self::Fixed { w, h }
94    }
95
96    #[must_use]
97    pub const fn content() -> Self {
98        Self::Content
99    }
100
101    #[must_use]
102    pub const fn dimensions(&self) -> Option<(f32, f32)> {
103        match *self {
104            Self::Fixed { w, h } => Some((w, h)),
105            Self::Content => None,
106        }
107    }
108}
109
110pub struct PopupRequestBuilder {
111    component: String,
112    placement: PopupPlacement,
113    size: PopupSize,
114    mode: PopupPositioningMode,
115    grab: bool,
116    close_callback: Option<String>,
117    resize_callback: Option<String>,
118}
119
120impl PopupRequestBuilder {
121    #[must_use]
122    pub fn new(component: String) -> Self {
123        Self {
124            component,
125            placement: PopupPlacement::AtCursor,
126            size: PopupSize::Content,
127            mode: PopupPositioningMode::default(),
128            grab: false,
129            close_callback: None,
130            resize_callback: None,
131        }
132    }
133
134    #[must_use]
135    pub const fn placement(mut self, placement: PopupPlacement) -> Self {
136        self.placement = placement;
137        self
138    }
139
140    #[must_use]
141    pub const fn size(mut self, size: PopupSize) -> Self {
142        self.size = size;
143        self
144    }
145
146    #[must_use]
147    pub const fn mode(mut self, mode: PopupPositioningMode) -> Self {
148        self.mode = mode;
149        self
150    }
151
152    #[must_use]
153    pub const fn grab(mut self, grab: bool) -> Self {
154        self.grab = grab;
155        self
156    }
157
158    #[must_use]
159    pub fn close_on(mut self, callback_name: impl Into<String>) -> Self {
160        self.close_callback = Some(callback_name.into());
161        self
162    }
163
164    #[must_use]
165    pub fn resize_on(mut self, callback_name: impl Into<String>) -> Self {
166        self.resize_callback = Some(callback_name.into());
167        self
168    }
169
170    #[must_use]
171    pub fn build(self) -> PopupRequest {
172        PopupRequest {
173            component: self.component,
174            placement: self.placement,
175            size: self.size,
176            mode: self.mode,
177            grab: self.grab,
178            close_callback: self.close_callback,
179            resize_callback: self.resize_callback,
180        }
181    }
182}