1use crate::root::WindowState;
2use crate::{
3 Placement,
4 dialog::{AlertDialog, Dialog},
5 input::AnyInputState,
6 notification::Notification,
7 sheet::Sheet,
8};
9use gpui::{App, ElementId, Entity, Window};
10use std::rc::Rc;
11
12pub trait WindowExt: Sized {
14 fn open_sheet<F>(&mut self, cx: &mut App, build: F)
16 where
17 F: Fn(Sheet, &mut Window, &mut App) -> Sheet + 'static;
18
19 fn open_sheet_at<F>(&mut self, placement: Placement, cx: &mut App, build: F)
21 where
22 F: Fn(Sheet, &mut Window, &mut App) -> Sheet + 'static;
23
24 fn has_active_sheet(&mut self, cx: &mut App) -> bool;
26
27 fn close_sheet(&mut self, cx: &mut App);
29
30 fn open_dialog<F>(&mut self, cx: &mut App, build: F)
32 where
33 F: Fn(Dialog, &mut Window, &mut App) -> Dialog + 'static;
34
35 fn open_alert_dialog<F>(&mut self, cx: &mut App, build: F)
53 where
54 F: Fn(AlertDialog, &mut Window, &mut App) -> AlertDialog + 'static;
55
56 fn has_active_dialog(&mut self, cx: &mut App) -> bool;
58
59 fn close_dialog(&mut self, cx: &mut App);
61
62 fn close_all_dialogs(&mut self, cx: &mut App);
64
65 fn push_notification(&mut self, note: impl Into<Notification>, cx: &mut App);
67
68 fn remove_notification<T: Sized + 'static>(&mut self, cx: &mut App);
71
72 fn remove_notification1<T: Sized + 'static>(&mut self, key: impl Into<ElementId>, cx: &mut App);
74
75 fn clear_notifications(&mut self, cx: &mut App);
77
78 fn notifications(&mut self, cx: &mut App) -> Rc<Vec<Entity<Notification>>>;
80
81 fn focused_input(&mut self, cx: &mut App) -> Option<AnyInputState>;
88 fn has_focused_input(&mut self, cx: &mut App) -> bool;
90}
91
92impl WindowExt for Window {
93 #[inline]
94 fn open_sheet<F>(&mut self, cx: &mut App, build: F)
95 where
96 F: Fn(Sheet, &mut Window, &mut App) -> Sheet + 'static,
97 {
98 self.open_sheet_at(Placement::Right, cx, build)
99 }
100
101 #[inline]
102 fn open_sheet_at<F>(&mut self, placement: Placement, cx: &mut App, build: F)
103 where
104 F: Fn(Sheet, &mut Window, &mut App) -> Sheet + 'static,
105 {
106 WindowState::update(self, cx, move |root, window, cx| {
107 root.open_sheet_at(placement, build, window, cx);
108 })
109 }
110
111 #[inline]
112 fn has_active_sheet(&mut self, cx: &mut App) -> bool {
113 WindowState::read(self, cx).active_sheet.is_some()
114 }
115
116 #[inline]
117 fn close_sheet(&mut self, cx: &mut App) {
118 WindowState::update(self, cx, |root, window, cx| {
119 root.close_sheet(window, cx);
120 })
121 }
122
123 #[inline]
124 fn open_dialog<F>(&mut self, cx: &mut App, build: F)
125 where
126 F: Fn(Dialog, &mut Window, &mut App) -> Dialog + 'static,
127 {
128 WindowState::update(self, cx, move |root, window, cx| {
129 root.open_dialog(build, window, cx);
130 })
131 }
132
133 #[inline]
134 fn open_alert_dialog<F>(&mut self, cx: &mut App, build: F)
135 where
136 F: Fn(AlertDialog, &mut Window, &mut App) -> AlertDialog + 'static,
137 {
138 self.open_dialog(cx, move |_, window, cx| {
139 build(AlertDialog::new(cx), window, cx).build_surface(window, cx)
140 })
141 }
142
143 #[inline]
144 fn has_active_dialog(&mut self, cx: &mut App) -> bool {
145 !WindowState::read(self, cx).active_dialogs.is_empty()
146 }
147
148 #[inline]
149 fn close_dialog(&mut self, cx: &mut App) {
150 WindowState::update(self, cx, |root, window, cx| {
151 root.close_dialog(window, cx);
152 })
153 }
154
155 #[inline]
156 fn close_all_dialogs(&mut self, cx: &mut App) {
157 WindowState::update(self, cx, |root, window, cx| {
158 root.close_all_dialogs(window, cx);
159 })
160 }
161
162 #[inline]
163 fn push_notification(&mut self, note: impl Into<Notification>, cx: &mut App) {
164 let note = note.into();
165 WindowState::update(self, cx, |root, window, cx| {
166 root.push_notification(note, window, cx);
167 })
168 }
169
170 #[inline]
171 fn remove_notification<T: Sized + 'static>(&mut self, cx: &mut App) {
172 WindowState::update(self, cx, |root, window, cx| {
173 root.remove_notification::<T>(window, cx);
174 })
175 }
176
177 #[inline]
178 fn remove_notification1<T: Sized + 'static>(
179 &mut self,
180 key: impl Into<ElementId>,
181 cx: &mut App,
182 ) {
183 let key = key.into();
184 WindowState::update(self, cx, |root, window, cx| {
185 root.remove_notification1::<T>(key, window, cx);
186 })
187 }
188
189 #[inline]
190 fn clear_notifications(&mut self, cx: &mut App) {
191 WindowState::update(self, cx, |root, window, cx| {
192 root.clear_notifications(window, cx);
193 })
194 }
195
196 #[inline]
197 fn notifications(&mut self, cx: &mut App) -> Rc<Vec<Entity<Notification>>> {
198 Rc::new(
199 WindowState::read(self, cx)
200 .notification
201 .read(cx)
202 .notifications(),
203 )
204 }
205
206 #[inline]
207 fn has_focused_input(&mut self, cx: &mut App) -> bool {
208 self.focused_input(cx).is_some()
209 }
210
211 fn focused_input(&mut self, cx: &mut App) -> Option<AnyInputState> {
212 let state = WindowState::read(self, cx).focused_input.clone()?;
213 if state.focus_handle(cx).is_focused(self) {
214 return Some(state);
215 }
216
217 WindowState::try_update(self, cx, |root, _, cx| {
220 if root.focused_input.as_ref() == Some(&state) {
221 root.focused_input = None;
222 cx.notify();
223 }
224 });
225 None
226 }
227}