modal_layer.rs

  1use std::{any::TypeId, sync::Arc};
  2
  3use gpui::{
  4    div, hsla, px, red, AnyView, AppContext, Component, DispatchPhase, Div, ParentElement, Render,
  5    StatelessInteractive, Styled, View, ViewContext,
  6};
  7use ui::v_stack;
  8
  9use crate::Workspace;
 10
 11pub struct ModalRegistry {
 12    registered_modals: Vec<(TypeId, Box<dyn Fn(Div<Workspace>) -> Div<Workspace>>)>,
 13}
 14
 15pub trait Modal {}
 16
 17#[derive(Clone)]
 18pub struct ModalLayer {
 19    open_modal: Option<AnyView>,
 20}
 21
 22pub fn init_modal_registry(cx: &mut AppContext) {
 23    cx.set_global(ModalRegistry {
 24        registered_modals: Vec::new(),
 25    });
 26}
 27
 28struct ToggleModal {
 29    name: String,
 30}
 31
 32impl ModalRegistry {
 33    pub fn register_modal<A: 'static, V, B>(&mut self, action: A, build_view: B)
 34    where
 35        V: Render,
 36        B: Fn(&Workspace, &mut ViewContext<Workspace>) -> Option<View<V>> + 'static,
 37    {
 38        let build_view = Arc::new(build_view);
 39
 40        self.registered_modals.push((
 41            TypeId::of::<A>(),
 42            Box::new(move |mut div| {
 43                let build_view = build_view.clone();
 44
 45                div.on_action(
 46                    move |workspace: &mut Workspace,
 47                          event: &A,
 48                          phase: DispatchPhase,
 49                          cx: &mut ViewContext<Workspace>| {
 50                        if phase == DispatchPhase::Capture {
 51                            return;
 52                        }
 53
 54                        let Some(new_modal) = (build_view)(workspace, cx) else {
 55                            return;
 56                        };
 57
 58                        workspace.modal_layer.update(cx, |modal_layer, _| {
 59                            modal_layer.open_modal = Some(new_modal.into());
 60                        });
 61
 62                        cx.notify();
 63                    },
 64                )
 65            }),
 66        ));
 67    }
 68}
 69
 70impl ModalLayer {
 71    pub fn new() -> Self {
 72        Self { open_modal: None }
 73    }
 74
 75    // Workspace
 76    // - ModalLayer parent
 77    // - - container
 78    // - - - modal
 79    // - - - content of the modal
 80    // - - content of the workspace
 81
 82    // app
 83    // workspace
 84    // container some layer that contains all modals and is 100% wide and high
 85    // modal (this has a shadow, some witdht)
 86    // whatever
 87
 88    pub fn render(&self, workspace: &Workspace, cx: &ViewContext<Workspace>) -> Div<Workspace> {
 89        let mut parent = div().relative().bg(red()).size_full();
 90
 91        for (_, action) in cx.global::<ModalRegistry>().registered_modals.iter() {
 92            parent = (action)(parent);
 93        }
 94
 95        parent.when_some(self.open_modal.as_ref(), |parent, open_modal| {
 96            let container1 = div()
 97                .absolute()
 98                .flex()
 99                .flex_col()
100                .items_center()
101                .size_full()
102                .top_0()
103                .left_0()
104                .z_index(400);
105
106            // transparent layer
107            let container2 = v_stack()
108                .bg(hsla(0.5, 0.5, 0.5, 0.5))
109                .h(px(0.0))
110                .relative()
111                .top_20();
112
113            parent.child(container1.child(container2.child(open_modal.clone())))
114        })
115    }
116}
117
118// impl Render for ModalLayer {
119//     type Element = Div<Self>;
120
121//     fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
122//         let mut div = div();
123//         for (type_id, build_view) in cx.global::<ModalRegistry>().registered_modals {
124//             div = div.useful_on_action(
125//                 type_id,
126//                 Box::new(|this, _: dyn Any, phase, cx: &mut ViewContext<Self>| {
127//                     if phase == DispatchPhase::Capture {
128//                         return;
129//                     }
130//                     self.workspace.update(cx, |workspace, cx| {
131//                         self.open_modal = Some(build_view(workspace, cx));
132//                     });
133//                     cx.notify();
134//                 }),
135//             )
136//         }
137
138//         div
139//     }
140// }