diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 4c8bed04919d50a1dbe1b9a30b0246f5ac7ce8de..e9091d74c8001c59c03beb6c2e1f4101ae567035 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -5083,6 +5083,7 @@ impl Drop for AnyModelHandle { } } +#[derive(Hash, PartialEq, Eq, Debug)] pub struct AnyWeakModelHandle { model_id: usize, model_type: TypeId, @@ -5092,6 +5093,26 @@ impl AnyWeakModelHandle { pub fn upgrade(&self, cx: &impl UpgradeModelHandle) -> Option { cx.upgrade_any_model_handle(self) } + pub fn model_type(&self) -> TypeId { + self.model_type + } + + fn is(&self) -> bool { + TypeId::of::() == self.model_type + } + + pub fn downcast(&self) -> Option> { + if self.is::() { + let result = Some(WeakModelHandle { + model_id: self.model_id, + model_type: PhantomData, + }); + + result + } else { + None + } + } } impl From> for AnyWeakModelHandle { diff --git a/crates/terminal/src/modal.rs b/crates/terminal/src/modal.rs index 504a4b84ab12c8665afdb0b2fa95db199f5d4998..97dcd40afdb439cb557f882ef4885b777463112c 100644 --- a/crates/terminal/src/modal.rs +++ b/crates/terminal/src/modal.rs @@ -1,4 +1,9 @@ -use gpui::{ModelHandle, ViewContext}; +use std::{ + any::TypeId, + collections::{HashMap, HashSet}, +}; + +use gpui::{AnyWeakModelHandle, Entity, ModelHandle, ViewContext, WeakModelHandle}; use settings::{Settings, WorkingDirectory}; use workspace::Workspace; @@ -9,10 +14,59 @@ use crate::{ Event, Terminal, }; +// TODO: Need to put this basic structure in workspace, and make 'program handles' +// based off of the 'searchable item' pattern except with models this way, the workspace's clients +// can register their models as programs. +// Programs are: +// - Kept alive by the program manager, they need to emit an event to get dropped from it +// - Can be interacted with directly, (closed, activated), etc, bypassing associated view(s) +// - Have special rendering methods that the program manager offers to fill out the status bar +// - Can emit events for the program manager which: +// - Add a jewel (notification, change, etc.) +// - Drop the program +// - ??? +// - Program Manager is kept in a global, listens for window drop so it can drop all it's program handles +// - Start by making up the infrastructure, then just render the first item as the modal terminal in it's spot +// update), + +struct ProgramManager { + window_to_programs: HashMap>, +} + +impl ProgramManager { + pub fn add_program(&mut self, window: usize, program: WeakModelHandle) { + let mut programs = if let Some(programs) = self.window_to_programs.remove(&window) { + programs + } else { + HashSet::default() + }; + + programs.insert(AnyWeakModelHandle::from(program)); + self.window_to_programs.insert(window, programs); + } + + pub fn get_programs( + &self, + window: &usize, + ) -> impl Iterator> + '_ { + self.window_to_programs + .get(window) + .into_iter() + .flat_map(|programs| { + programs + .iter() + .filter(|program| program.model_type() != TypeId::of::()) + .map(|program| program.downcast().unwrap()) + }) + } +} + #[derive(Debug)] struct StoredTerminal(ModelHandle); pub fn deploy_modal(workspace: &mut Workspace, _: &DeployModal, cx: &mut ViewContext) { + // cx.window_id() + // Pull the terminal connection out of the global if it has been stored let possible_terminal = cx.update_default_global::, _, _>(|possible_connection, _| {