Detailed changes
@@ -57,6 +57,7 @@ use language::{
Diagnostic, IndentKind, IndentSize, Language, LanguageRegistry, LanguageServerName,
OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
};
+use lazy_static::lazy_static;
use link_go_to_definition::{GoToDefinitionLink, InlayHighlight, LinkGoToDefinitionState};
use lsp::{DiagnosticSeverity, Documentation, LanguageServerId};
use movement::TextLayoutDetails;
@@ -66,7 +67,7 @@ pub use multi_buffer::{
ToPoint,
};
use ordered_float::OrderedFloat;
-use parking_lot::RwLock;
+use parking_lot::{Mutex, RwLock};
use project::{FormatTrigger, Location, Project};
use rand::prelude::*;
use rpc::proto::*;
@@ -1,25 +1,55 @@
use editor::Editor;
use gpui::{
actions, div, AppContext, Div, EventEmitter, ParentElement, Render, SharedString,
- StatelessInteractive, Styled, View, ViewContext, VisualContext,
+ StatefulInteractivity, StatelessInteractive, Styled, View, ViewContext, VisualContext,
};
use text::Point;
use theme::ActiveTheme;
use ui::{h_stack, modal, v_stack, Label, LabelColor};
use util::paths::FILE_ROW_COLUMN_DELIMITER;
-use workspace::{ModalRegistry, Modal, ModalEvent};
+use workspace::{Modal, ModalEvent, Workspace};
actions!(Toggle);
pub fn init(cx: &mut AppContext) {
- cx.global_mut::<ModalRegistry>()
- .register_modal(Toggle, |workspace, cx| {
- let editor = workspace
- .active_item(cx)
- .and_then(|active_item| active_item.downcast::<Editor>())?;
-
- Some(cx.build_view(|cx| GoToLine::new(editor, cx)))
- });
+ cx.observe_new_views(
+ |workspace: &mut Workspace, _: &mut ViewContext<Workspace>| {
+ workspace
+ .modal_layer()
+ .register_modal(Toggle, |workspace, cx| {
+ let editor = workspace
+ .active_item(cx)
+ .and_then(|active_item| active_item.downcast::<Editor>())?;
+
+ Some(cx.build_view(|cx| GoToLine::new(editor, cx)))
+ });
+ dbg!("hey!");
+ },
+ )
+ .detach();
+
+ // // cx.window_global()
+ // // cx.window_global::<Workspace>
+ // // cx.window_global::<ActiveEditor>()
+ // Workspace::on_init(|workspace, cx| {
+ // workspace.on_open_item()
+ // });
+
+ // Editor::on_init(|editor, cx|{
+
+ // })
+
+ // Editor::register_action(|_editor, _: &Toggle, cx| {
+ // dbg!("HEY!");
+ // // let editor = cx.view();
+ // // cx.update_window(cx.window().handle(), |cx, view| {
+ // // let workspace = view.downcast::<Workspace>();
+ // // })
+ // // workspace.show_modal(cx.build_view(|cx| GoToLine::new(editor, cx)))
+ // })
+ // cx.global_mut::<ModalRegistry>()
+ // .register_modal(Toggle, |workspace, cx| {
+ // });
}
pub struct GoToLine {
@@ -128,13 +158,14 @@ impl Modal for GoToLine {
}
impl Render for GoToLine {
- type Element = Div<Self>;
+ type Element = Div<Self, StatefulInteractivity<Self>>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
modal(cx)
- .w_96()
+ .id("go to line")
.on_action(Self::cancel)
.on_action(Self::confirm)
+ .w_96()
.child(
v_stack()
.px_1()
@@ -18,8 +18,8 @@ use crate::{
AppMetadata, AssetSource, BackgroundExecutor, ClipboardItem, Context, DispatchPhase, DisplayId,
Entity, EventEmitter, FocusEvent, FocusHandle, FocusId, ForegroundExecutor, KeyBinding, Keymap,
LayoutId, PathPromptOptions, Pixels, Platform, PlatformDisplay, Point, Render, SubscriberSet,
- Subscription, SvgRenderer, Task, TextStyle, TextStyleRefinement, TextSystem, View, Window,
- WindowContext, WindowHandle, WindowId,
+ Subscription, SvgRenderer, Task, TextStyle, TextStyleRefinement, TextSystem, View, ViewContext,
+ Window, WindowContext, WindowHandle, WindowId,
};
use anyhow::{anyhow, Result};
use collections::{HashMap, HashSet, VecDeque};
@@ -167,6 +167,7 @@ type Handler = Box<dyn FnMut(&mut AppContext) -> bool + 'static>;
type Listener = Box<dyn FnMut(&dyn Any, &mut AppContext) -> bool + 'static>;
type QuitHandler = Box<dyn FnOnce(&mut AppContext) -> LocalBoxFuture<'static, ()> + 'static>;
type ReleaseListener = Box<dyn FnOnce(&mut dyn Any, &mut AppContext) + 'static>;
+type NewViewListener = Box<dyn FnMut(AnyView, &mut WindowContext) + 'static>;
// struct FrameConsumer {
// next_frame_callbacks: Vec<FrameCallback>,
@@ -193,6 +194,7 @@ pub struct AppContext {
pub(crate) text_style_stack: Vec<TextStyleRefinement>,
pub(crate) globals_by_type: HashMap<TypeId, AnyBox>,
pub(crate) entities: EntityMap,
+ pub(crate) new_view_observers: SubscriberSet<TypeId, NewViewListener>,
pub(crate) windows: SlotMap<WindowId, Option<Window>>,
pub(crate) keymap: Arc<Mutex<Keymap>>,
pub(crate) global_action_listeners:
@@ -251,6 +253,7 @@ impl AppContext {
text_style_stack: Vec::new(),
globals_by_type: HashMap::default(),
entities,
+ new_view_observers: SubscriberSet::new(),
windows: SlotMap::with_key(),
keymap: Arc::new(Mutex::new(Keymap::default())),
global_action_listeners: HashMap::default(),
@@ -599,6 +602,7 @@ impl AppContext {
fn apply_notify_effect(&mut self, emitter: EntityId) {
self.pending_notifications.remove(&emitter);
+
self.observers
.clone()
.retain(&emitter, |handler| handler(self));
@@ -828,6 +832,23 @@ impl AppContext {
self.globals_by_type.insert(global_type, lease.global);
}
+ pub fn observe_new_views<V: 'static>(
+ &mut self,
+ on_new: impl 'static + Fn(&mut V, &mut ViewContext<V>),
+ ) -> Subscription {
+ self.new_view_observers.insert(
+ TypeId::of::<V>(),
+ Box::new(move |any_view: AnyView, cx: &mut WindowContext| {
+ any_view
+ .downcast::<V>()
+ .unwrap()
+ .update(cx, |view_state, cx| {
+ on_new(view_state, cx);
+ })
+ }),
+ )
+ }
+
pub fn observe_release<E, T>(
&mut self,
handle: &E,
@@ -258,7 +258,7 @@ impl VisualContext for AsyncWindowContext {
build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V,
) -> Self::Result<View<V>>
where
- V: 'static,
+ V: 'static + Render,
{
self.window
.update(self, |_, cx| cx.build_view(build_view_state))
@@ -112,7 +112,7 @@ pub trait VisualContext: Context {
build_view: impl FnOnce(&mut ViewContext<'_, V>) -> V,
) -> Self::Result<View<V>>
where
- V: 'static;
+ V: 'static + Render;
fn update_view<V: 'static, R>(
&mut self,
@@ -414,10 +414,14 @@ pub trait ElementInteractivity<V: 'static>: 'static {
Box::new(move |_, key_down, context, phase, cx| {
if phase == DispatchPhase::Bubble {
let key_down = key_down.downcast_ref::<KeyDownEvent>().unwrap();
+ dbg!(key_down);
if let KeyMatch::Some(action) =
cx.match_keystroke(&global_id, &key_down.keystroke, context)
{
+ dbg!(&action);
return Some(action);
+ } else {
+ dbg!("none");
}
}
@@ -1411,7 +1411,7 @@ impl VisualContext for WindowContext<'_> {
build_view_state: impl FnOnce(&mut ViewContext<'_, V>) -> V,
) -> Self::Result<View<V>>
where
- V: 'static,
+ V: 'static + Render,
{
let slot = self.app.entities.reserve();
let view = View {
@@ -1419,7 +1419,16 @@ impl VisualContext for WindowContext<'_> {
};
let mut cx = ViewContext::new(&mut *self.app, &mut *self.window, &view);
let entity = build_view_state(&mut cx);
- self.entities.insert(slot, entity);
+ cx.entities.insert(slot, entity);
+
+ cx.new_view_observers
+ .clone()
+ .retain(&TypeId::of::<V>(), |observer| {
+ let any_view = AnyView::from(view.clone());
+ (observer)(any_view, self);
+ true
+ });
+
view
}
@@ -2102,7 +2111,7 @@ impl<V> Context for ViewContext<'_, V> {
}
impl<V: 'static> VisualContext for ViewContext<'_, V> {
- fn build_view<W: 'static>(
+ fn build_view<W: Render + 'static>(
&mut self,
build_view_state: impl FnOnce(&mut ViewContext<'_, W>) -> W,
) -> Self::Result<View<W>> {
@@ -407,6 +407,14 @@ impl Dock {
// }
}
+impl Render for Dock {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
+ todo!()
+ }
+}
+
// todo!()
// impl View for Dock {
// fn ui_name() -> &'static str {
@@ -1,25 +1,15 @@
use crate::Workspace;
use gpui::{
- div, px, AnyView, AppContext, Component, Div, EventEmitter, ParentElement, Render,
- StatelessInteractive, Styled, Subscription, View, ViewContext, WeakView,
+ div, px, AnyView, Component, Div, EventEmitter, ParentElement, Render, StatelessInteractive,
+ Styled, Subscription, View, ViewContext,
};
use std::{any::TypeId, sync::Arc};
use ui::v_stack;
-pub struct ModalRegistry {
- registered_modals: Vec<(TypeId, Box<dyn Fn(Div<Workspace>) -> Div<Workspace>>)>,
-}
-
pub struct ModalLayer {
- workspace: WeakView<Workspace>,
open_modal: Option<AnyView>,
subscription: Option<Subscription>,
-}
-
-pub fn init_modal_registry(cx: &mut AppContext) {
- cx.set_global(ModalRegistry {
- registered_modals: Vec::new(),
- });
+ registered_modals: Vec<(TypeId, Box<dyn Fn(Div<Workspace>) -> Div<Workspace>>)>,
}
pub enum ModalEvent {
@@ -30,7 +20,15 @@ pub trait Modal: EventEmitter + Render {
fn to_modal_event(&self, _: &Self::Event) -> Option<ModalEvent>;
}
-impl ModalRegistry {
+impl ModalLayer {
+ pub fn new() -> Self {
+ Self {
+ open_modal: None,
+ subscription: None,
+ registered_modals: Vec::new(),
+ }
+ }
+
pub fn register_modal<A: 'static, V, B>(&mut self, action: A, build_view: B)
where
V: Modal,
@@ -44,32 +42,19 @@ impl ModalRegistry {
let build_view = build_view.clone();
div.on_action(move |workspace, event: &A, cx| {
- let Some(new_modal) =
- (build_view)(workspace, cx) else {
- return
- };
- workspace.modal_layer.update(cx, |modal_layer, cx| {
- modal_layer.show_modal(new_modal, cx);
- })
+ let Some(new_modal) = (build_view)(workspace, cx) else {
+ return;
+ };
+ workspace.modal_layer().show_modal(new_modal, cx);
})
}),
));
}
-}
-
-impl ModalLayer {
- pub fn new(workspace: WeakView<Workspace>) -> Self {
- Self {
- workspace,
- open_modal: None,
- subscription: None,
- }
- }
- pub fn show_modal<V: Modal>(&mut self, new_modal: View<V>, cx: &mut ViewContext<Self>) {
+ pub fn show_modal<V: Modal>(&mut self, new_modal: View<V>, cx: &mut ViewContext<Workspace>) {
self.subscription = Some(cx.subscribe(&new_modal, |this, modal, e, cx| {
match modal.read(cx).to_modal_event(e) {
- Some(ModalEvent::Dismissed) => this.hide_modal(cx),
+ Some(ModalEvent::Dismissed) => this.modal_layer().hide_modal(cx),
None => {}
}
}));
@@ -77,16 +62,16 @@ impl ModalLayer {
cx.notify();
}
- pub fn hide_modal(&mut self, cx: &mut ViewContext<Self>) {
+ pub fn hide_modal(&mut self, cx: &mut ViewContext<Workspace>) {
self.open_modal.take();
self.subscription.take();
cx.notify();
}
- pub fn render(&self, cx: &ViewContext<Workspace>) -> Div<Workspace> {
+ pub fn wrapper_element(&self, cx: &ViewContext<Workspace>) -> Div<Workspace> {
let mut parent = div().relative().size_full();
- for (_, action) in cx.global::<ModalRegistry>().registered_modals.iter() {
+ for (_, action) in self.registered_modals.iter() {
parent = (action)(parent);
}
@@ -1,6 +1,7 @@
use crate::ItemHandle;
use gpui::{
- AnyView, AppContext, Entity, EntityId, EventEmitter, Render, View, ViewContext, WindowContext,
+ AnyView, AppContext, Div, Entity, EntityId, EventEmitter, Render, View, ViewContext,
+ WindowContext,
};
pub trait ToolbarItemView: Render + EventEmitter {
@@ -56,6 +57,14 @@ pub struct Toolbar {
items: Vec<(Box<dyn ToolbarItemViewHandle>, ToolbarItemLocation)>,
}
+impl Render for Toolbar {
+ type Element = Div<Self>;
+
+ fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
+ todo!()
+ }
+}
+
// todo!()
// impl View for Toolbar {
// fn ui_name() -> &'static str {
@@ -37,10 +37,10 @@ use futures::{
};
use gpui::{
div, point, size, AnyModel, AnyView, AnyWeakView, AppContext, AsyncAppContext,
- AsyncWindowContext, Bounds, Component, Div, Entity, EntityId, EventEmitter, FocusHandle,
- GlobalPixels, Model, ModelContext, ParentElement, Point, Render, Size, StatefulInteractive,
- Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowBounds,
- WindowContext, WindowHandle, WindowOptions,
+ AsyncWindowContext, Bounds, Component, Context, Div, Entity, EntityId, EventEmitter,
+ FocusHandle, GlobalPixels, Model, ModelContext, ParentElement, Point, Render, Size,
+ StatefulInteractive, Styled, Subscription, Task, View, ViewContext, VisualContext, WeakView,
+ WindowBounds, WindowContext, WindowHandle, WindowOptions,
};
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
use itertools::Itertools;
@@ -225,7 +225,6 @@ pub fn init_settings(cx: &mut AppContext) {
pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
init_settings(cx);
- init_modal_registry(cx);
pane::init(cx);
notifications::init(cx);
@@ -545,7 +544,7 @@ pub struct Workspace {
last_active_center_pane: Option<WeakView<Pane>>,
last_active_view_id: Option<proto::ViewId>,
status_bar: View<StatusBar>,
- modal_layer: View<ModalLayer>,
+ modal_layer: ModalLayer,
// titlebar_item: Option<AnyViewHandle>,
notifications: Vec<(TypeId, usize, Box<dyn NotificationHandle>)>,
project: Model<Project>,
@@ -697,7 +696,7 @@ impl Workspace {
});
let workspace_handle = cx.view().downgrade();
- let modal_layer = cx.build_view(|cx| ModalLayer::new(workspace_handle));
+ let modal_layer = ModalLayer::new();
// todo!()
// cx.update_default_global::<DragAndDrop<Workspace>, _, _>(|drag_and_drop, _| {
@@ -781,6 +780,10 @@ impl Workspace {
}
}
+ pub fn modal_layer(&mut self) -> &mut ModalLayer {
+ &mut self.modal_layer
+ }
+
fn new_local(
abs_paths: Vec<PathBuf>,
app_state: Arc<AppState>,
@@ -3707,9 +3710,9 @@ impl Render for Workspace {
.bg(cx.theme().colors().background)
.child(self.render_titlebar(cx))
.child(
+ // todo! should this be a component a view?
self.modal_layer
- .read(cx)
- .render(cx)
+ .wrapper_element(cx)
.relative()
.flex_1()
.w_full()