@@ -2,7 +2,7 @@ use crate::Workspace;
use gpui::{
div, px, AnyView, Component, Div, EventEmitter, FocusHandle, ParentElement, Render,
StatefulInteractivity, StatelessInteractive, Styled, Subscription, View, ViewContext,
- WindowContext,
+ VisualContext, WindowContext,
};
use std::{any::TypeId, sync::Arc};
use ui::v_stack;
@@ -16,14 +16,6 @@ pub struct ActiveModal {
pub struct ModalLayer {
active_modal: Option<ActiveModal>,
- registered_modals: Vec<(
- TypeId,
- Box<
- dyn Fn(
- Div<Workspace, StatefulInteractivity<Workspace>>,
- ) -> Div<Workspace, StatefulInteractivity<Workspace>>,
- >,
- )>,
}
pub trait Modal: Render + EventEmitter<ModalEvent> {
@@ -36,35 +28,13 @@ pub enum ModalEvent {
impl ModalLayer {
pub fn new() -> Self {
- Self {
- active_modal: None,
- registered_modals: Vec::new(),
- }
+ Self { active_modal: None }
}
- pub fn register_modal<A: 'static, V, B>(&mut self, action: A, build_view: B)
+ pub fn toggle_modal<V, B>(&mut self, cx: &mut ViewContext<Workspace>, build_view: B)
where
V: Modal,
- B: Fn(&mut WindowContext) -> Option<View<V>> + 'static,
- {
- let build_view = Arc::new(build_view);
-
- self.registered_modals.push((
- TypeId::of::<A>(),
- Box::new(move |mut div| {
- let build_view = build_view.clone();
-
- div.on_action(move |workspace, event: &A, cx| {
- workspace.modal_layer().toggle_modal(build_view.clone(), cx)
- })
- }),
- ));
- }
-
- pub fn toggle_modal<V, B>(&mut self, build_view: Arc<B>, cx: &mut ViewContext<Workspace>)
- where
- V: Modal,
- B: Fn(&mut WindowContext) -> Option<View<V>> + 'static,
+ B: FnOnce(&mut ViewContext<V>) -> V,
{
let previous_focus = cx.focused();
@@ -74,28 +44,23 @@ impl ModalLayer {
return;
}
}
- let Some(new_modal) = (build_view)(cx) else {
- return;
- };
- self.show_modal(previous_focus, new_modal, cx);
+ let new_modal = cx.build_view(build_view);
+ self.show_modal(new_modal, cx);
}
- pub fn show_modal<V>(
- &mut self,
- previous_focus: Option<FocusHandle>,
- new_modal: View<V>,
- cx: &mut ViewContext<Workspace>,
- ) where
+ pub fn show_modal<V>(&mut self, new_modal: View<V>, cx: &mut ViewContext<Workspace>)
+ where
V: Modal,
{
self.active_modal = Some(ActiveModal {
modal: new_modal.clone().into(),
- subscription: cx.subscribe(&new_modal, |this, modal, e, cx| match e {
- ModalEvent::Dismissed => this.modal_layer().hide_modal(cx),
+ subscription: cx.subscribe(&new_modal, |workspace, modal, e, cx| match e {
+ ModalEvent::Dismissed => workspace.modal_layer.hide_modal(cx),
}),
- previous_focus_handle: previous_focus,
+ previous_focus_handle: cx.focused(),
focus_handle: cx.focus_handle(),
});
+ new_modal.update(cx, |modal, cx| modal.focus(cx));
cx.notify();
}
@@ -115,12 +80,7 @@ impl ModalLayer {
&self,
cx: &ViewContext<Workspace>,
) -> Div<Workspace, StatefulInteractivity<Workspace>> {
- let mut parent = div().id("modal layer").relative().size_full();
-
- for (_, action) in self.registered_modals.iter() {
- parent = (action)(parent);
- }
-
+ let parent = div().id("boop");
parent.when_some(self.active_modal.as_ref(), |parent, open_modal| {
let container1 = div()
.absolute()
@@ -137,8 +97,8 @@ impl ModalLayer {
.relative()
.top_20()
.track_focus(&open_modal.focus_handle)
- .on_mouse_down_out(|workspace: &mut Workspace, _, cx| {
- workspace.modal_layer().hide_modal(cx);
+ .on_mouse_down_out(|workspace: &mut Workspace, event, cx| {
+ workspace.modal_layer.hide_modal(cx);
});
parent.child(container1.child(container2.child(open_modal.modal.clone())))
@@ -36,11 +36,12 @@ use futures::{
Future, FutureExt, StreamExt,
};
use gpui::{
- actions, div, point, rems, size, AnyModel, AnyView, AnyWeakView, AppContext, AsyncAppContext,
- AsyncWindowContext, Bounds, Component, DispatchContext, Div, Entity, EntityId, EventEmitter,
- FocusHandle, GlobalPixels, Model, ModelContext, ParentElement, Point, Render, Size,
- StatefulInteractive, StatefulInteractivity, Styled, Subscription, Task, View, ViewContext,
- VisualContext, WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions,
+ actions, div, point, rems, size, Action, AnyModel, AnyView, AnyWeakView, AppContext,
+ AsyncAppContext, AsyncWindowContext, Bounds, Component, DispatchContext, Div, Entity, EntityId,
+ EventEmitter, FocusHandle, GlobalPixels, Model, ModelContext, ParentElement, Point, Render,
+ Size, StatefulInteractive, StatefulInteractivity, StatelessInteractive, Styled, Subscription,
+ Task, View, ViewContext, VisualContext, WeakView, WindowBounds, WindowContext, WindowHandle,
+ WindowOptions,
};
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
use itertools::Itertools;
@@ -530,6 +531,13 @@ pub enum Event {
pub struct Workspace {
weak_self: WeakView<Self>,
focus_handle: FocusHandle,
+ workspace_actions: Vec<
+ Box<
+ dyn Fn(
+ Div<Workspace, StatefulInteractivity<Workspace>>,
+ ) -> Div<Workspace, StatefulInteractivity<Workspace>>,
+ >,
+ >,
zoomed: Option<AnyWeakView>,
zoomed_position: Option<DockPosition>,
center: PaneGroup,
@@ -775,13 +783,10 @@ impl Workspace {
leader_updates_tx,
subscriptions,
pane_history_timestamp,
+ workspace_actions: Default::default(),
}
}
- pub fn modal_layer(&mut self) -> &mut ModalLayer {
- &mut self.modal_layer
- }
-
fn new_local(
abs_paths: Vec<PathBuf>,
app_state: Arc<AppState>,
@@ -3495,6 +3500,34 @@ impl Workspace {
// )
// }
// }
+ pub fn register_action<A: Action>(
+ &mut self,
+ callback: impl Fn(&mut Self, &A, &mut ViewContext<Self>) + 'static,
+ ) {
+ let callback = Arc::new(callback);
+
+ self.workspace_actions.push(Box::new(move |div| {
+ let callback = callback.clone();
+ div.on_action(move |workspace, event, cx| (callback.clone())(workspace, event, cx))
+ }));
+ }
+
+ fn add_workspace_actions_listeners(
+ &self,
+ mut div: Div<Workspace, StatefulInteractivity<Workspace>>,
+ ) -> Div<Workspace, StatefulInteractivity<Workspace>> {
+ for action in self.workspace_actions.iter() {
+ div = (action)(div)
+ }
+ div
+ }
+
+ pub fn toggle_modal<V: Modal, B>(&mut self, cx: &mut ViewContext<Self>, build: B)
+ where
+ B: FnOnce(&mut ViewContext<V>) -> V,
+ {
+ self.modal_layer.toggle_modal(cx, build)
+ }
}
fn window_bounds_env_override(cx: &AsyncAppContext) -> Option<WindowBounds> {
@@ -3706,14 +3739,13 @@ fn notify_if_database_failed(workspace: WindowHandle<Workspace>, cx: &mut AsyncA
impl EventEmitter<Event> for Workspace {}
impl Render for Workspace {
- type Element = Div<Self, StatefulInteractivity<Self>>;
+ type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
let mut context = DispatchContext::default();
context.insert("Workspace");
cx.with_key_dispatch_context(context, |cx| {
div()
- .id("workspace")
.relative()
.size_full()
.flex()
@@ -3727,8 +3759,7 @@ impl Render for Workspace {
.child(self.render_titlebar(cx))
.child(
// todo! should this be a component a view?
- self.modal_layer
- .wrapper_element(cx)
+ self.add_workspace_actions_listeners(div().id("workspace"))
.relative()
.flex_1()
.w_full()
@@ -3737,6 +3768,7 @@ impl Render for Workspace {
.border_t()
.border_b()
.border_color(cx.theme().colors().border)
+ .child(self.modal_layer.wrapper_element(cx))
// .children(
// Some(
// Panel::new("project-panel-outer", cx)