1use crate::Workspace;
2use gpui::{
3 div, px, AnyView, Component, Div, EventEmitter, ParentElement, Render, StatefulInteractivity,
4 StatelessInteractive, Styled, Subscription, View, ViewContext,
5};
6use std::{any::TypeId, sync::Arc};
7use ui::v_stack;
8
9pub struct ModalLayer {
10 open_modal: Option<AnyView>,
11 subscription: Option<Subscription>,
12 registered_modals: Vec<(
13 TypeId,
14 Box<
15 dyn Fn(
16 Div<Workspace, StatefulInteractivity<Workspace>>,
17 ) -> Div<Workspace, StatefulInteractivity<Workspace>>,
18 >,
19 )>,
20}
21
22pub enum ModalEvent {
23 Dismissed,
24}
25
26impl ModalLayer {
27 pub fn new() -> Self {
28 Self {
29 open_modal: None,
30 subscription: None,
31 registered_modals: Vec::new(),
32 }
33 }
34
35 pub fn register_modal<A: 'static, V, B>(&mut self, action: A, build_view: B)
36 where
37 V: EventEmitter<ModalEvent> + Render,
38 B: Fn(&mut Workspace, &mut ViewContext<Workspace>) -> Option<View<V>> + 'static,
39 {
40 let build_view = Arc::new(build_view);
41
42 self.registered_modals.push((
43 TypeId::of::<A>(),
44 Box::new(move |mut div| {
45 let build_view = build_view.clone();
46
47 div.on_action(move |workspace, event: &A, cx| {
48 let Some(new_modal) = (build_view)(workspace, cx) else {
49 return;
50 };
51 workspace.modal_layer().show_modal(new_modal, cx);
52 })
53 }),
54 ));
55 }
56
57 pub fn show_modal<V>(&mut self, new_modal: View<V>, cx: &mut ViewContext<Workspace>)
58 where
59 V: EventEmitter<ModalEvent> + Render,
60 {
61 self.subscription = Some(cx.subscribe(&new_modal, |this, modal, e, cx| match e {
62 ModalEvent::Dismissed => this.modal_layer().hide_modal(cx),
63 }));
64 self.open_modal = Some(new_modal.into());
65 cx.notify();
66 }
67
68 pub fn hide_modal(&mut self, cx: &mut ViewContext<Workspace>) {
69 self.open_modal.take();
70 self.subscription.take();
71 cx.notify();
72 }
73
74 pub fn wrapper_element(
75 &self,
76 cx: &ViewContext<Workspace>,
77 ) -> Div<Workspace, StatefulInteractivity<Workspace>> {
78 let mut parent = div().id("modal layer").relative().size_full();
79
80 for (_, action) in self.registered_modals.iter() {
81 parent = (action)(parent);
82 }
83
84 parent.when_some(self.open_modal.as_ref(), |parent, open_modal| {
85 let container1 = div()
86 .absolute()
87 .flex()
88 .flex_col()
89 .items_center()
90 .size_full()
91 .top_0()
92 .left_0()
93 .z_index(400);
94
95 // transparent layer
96 let container2 = v_stack().h(px(0.0)).relative().top_20();
97
98 parent.child(container1.child(container2.child(open_modal.clone())))
99 })
100 }
101}
102
103// impl Render for ModalLayer {
104// type Element = Div<Self>;
105
106// fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
107// let mut div = div();
108// for (type_id, build_view) in cx.global::<ModalRegistry>().registered_modals {
109// div = div.useful_on_action(
110// type_id,
111// Box::new(|this, _: dyn Any, phase, cx: &mut ViewContext<Self>| {
112// if phase == DispatchPhase::Capture {
113// return;
114// }
115// self.workspace.update(cx, |workspace, cx| {
116// self.open_modal = Some(build_view(workspace, cx));
117// });
118// cx.notify();
119// }),
120// )
121// }
122
123// div
124// }
125// }