freya_components/
popup.rs1use freya_animation::prelude::*;
2use freya_core::prelude::*;
3use torin::{
4 prelude::{
5 Alignment,
6 Position,
7 },
8 size::Size,
9};
10
11use crate::{
12 get_theme,
13 theming::component_themes::{
14 PopupTheme,
15 PopupThemePartial,
16 },
17};
18
19#[derive(Clone, PartialEq)]
21pub struct PopupBackground {
22 pub children: Element,
23 pub on_press: EventHandler<Event<PressEventData>>,
24}
25
26impl PopupBackground {
27 pub fn new(
28 children: Element,
29 on_press: impl Into<EventHandler<Event<PressEventData>>>,
30 ) -> Self {
31 Self {
32 children,
33 on_press: on_press.into(),
34 }
35 }
36}
37
38impl Render for PopupBackground {
39 fn render(&self) -> impl IntoElement {
40 let animation = use_animation(|conf| {
41 conf.on_creation(OnCreation::Run);
42 AnimColor::new((0, 0, 0, 0), (0, 0, 0, 150)).time(150)
43 });
44 let background = animation.get().value();
45 let on_press = self.on_press.clone();
46
47 rect()
48 .layer(2000)
49 .position(Position::new_global())
50 .child(
51 rect()
52 .on_press(on_press)
53 .position(Position::new_global().top(0.).left(0.))
54 .height(Size::window_percent(100.))
55 .width(Size::window_percent(100.))
56 .background(background),
57 )
58 .child(
59 rect()
60 .position(Position::new_global().top(0.).left(0.))
61 .height(Size::window_percent(100.))
62 .width(Size::window_percent(100.))
63 .center()
64 .child(self.children.clone()),
65 )
66 }
67}
68
69#[derive(Clone, PartialEq)]
71pub struct Popup {
72 pub(crate) theme: Option<PopupThemePartial>,
73 children: Vec<Element>,
74 on_close_request: Option<EventHandler<()>>,
75 close_on_escape_key: bool,
76 key: DiffKey,
77}
78
79impl KeyExt for Popup {
80 fn write_key(&mut self) -> &mut DiffKey {
81 &mut self.key
82 }
83}
84
85impl Default for Popup {
86 fn default() -> Self {
87 Self::new()
88 }
89}
90
91impl Popup {
92 pub fn new() -> Self {
93 Self {
94 theme: None,
95 children: vec![],
96 on_close_request: None,
97 close_on_escape_key: true,
98 key: DiffKey::None,
99 }
100 }
101
102 pub fn on_close_request(mut self, on_close_request: impl Into<EventHandler<()>>) -> Self {
103 self.on_close_request = Some(on_close_request.into());
104 self
105 }
106}
107
108impl ChildrenExt for Popup {
109 fn get_children(&mut self) -> &mut Vec<Element> {
110 &mut self.children
111 }
112}
113
114impl Render for Popup {
115 fn render(&self) -> impl IntoElement {
116 let animations = use_animation(|conf| {
117 conf.on_creation(OnCreation::Run);
118 (
119 AnimNum::new(0.85, 1.)
120 .time(250)
121 .ease(Ease::Out)
122 .function(Function::Expo),
123 AnimNum::new(0.2, 1.)
124 .time(250)
125 .ease(Ease::Out)
126 .function(Function::Expo),
127 )
128 });
129
130 let PopupTheme { background, color } = get_theme!(&self.theme, popup);
131
132 let (scale, opacity) = &*animations.read();
133
134 let request_to_close = {
135 let handler = self.on_close_request.clone();
136 move || {
137 if let Some(h) = &handler {
138 h.call(());
139 }
140 }
141 };
142
143 let on_global_key_down = {
144 let close = self.close_on_escape_key;
145 let req = request_to_close.clone();
146 move |e: Event<KeyboardEventData>| {
147 if close && e.key == Key::Escape {
148 req();
149 }
150 }
151 };
152
153 PopupBackground::new(
154 rect()
155 .scale((scale.value(), scale.value()))
156 .opacity(opacity.value())
157 .corner_radius(12.)
158 .background(background)
159 .color(color)
160 .shadow(Shadow::new().y(4.).blur(5.).color((0, 0, 0, 30)))
161 .width(Size::px(500.))
162 .height(Size::auto())
163 .spacing(4.)
164 .padding(8.)
165 .on_global_key_down(on_global_key_down)
166 .children(self.children.clone())
167 .into(),
168 move |_| {
169 request_to_close();
170 },
171 )
172 }
173
174 fn render_key(&self) -> DiffKey {
175 self.key.clone().or(self.default_key())
176 }
177}
178
179#[derive(PartialEq)]
181pub struct PopupTitle {
182 text: ReadState<String>,
183}
184
185impl PopupTitle {
186 pub fn new(text: impl Into<ReadState<String>>) -> Self {
187 Self { text: text.into() }
188 }
189}
190
191impl Render for PopupTitle {
192 fn render(&self) -> impl IntoElement {
193 rect().font_size(18.).padding(8.).child(
194 label()
195 .width(Size::fill())
196 .text(self.text.read().to_string()),
197 )
198 }
199}
200
201#[derive(Clone, PartialEq)]
203pub struct PopupContent {
204 children: Vec<Element>,
205}
206impl Default for PopupContent {
207 fn default() -> Self {
208 Self::new()
209 }
210}
211
212impl PopupContent {
213 pub fn new() -> Self {
214 Self { children: vec![] }
215 }
216}
217
218impl ChildrenExt for PopupContent {
219 fn get_children(&mut self) -> &mut Vec<Element> {
220 &mut self.children
221 }
222}
223
224impl Render for PopupContent {
225 fn render(&self) -> impl IntoElement {
226 rect()
227 .font_size(15.)
228 .padding(8.)
229 .children(self.children.clone())
230 }
231}
232
233#[derive(Clone, PartialEq)]
235pub struct PopupButtons {
236 pub children: Vec<Element>,
237}
238
239impl Default for PopupButtons {
240 fn default() -> Self {
241 Self::new()
242 }
243}
244
245impl PopupButtons {
246 pub fn new() -> Self {
247 Self { children: vec![] }
248 }
249}
250
251impl ChildrenExt for PopupButtons {
252 fn get_children(&mut self) -> &mut Vec<Element> {
253 &mut self.children
254 }
255}
256
257impl Render for PopupButtons {
258 fn render(&self) -> impl IntoElement {
259 rect()
260 .width(Size::fill())
261 .main_align(Alignment::End)
262 .padding(8.)
263 .spacing(4.)
264 .horizontal()
265 .children(self.children.clone())
266 }
267}