// 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 with a specific identity and capable of notifying the workspace // 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.) by the program manager, bypassing // associated view(s) // - Have special rendering methods that the program manager requires them to implement 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 use collections::HashMap; use gpui::{AnyModelHandle, Entity, ModelHandle, View, ViewContext}; /// This struct is going to be the starting point for the 'program manager' feature that will /// eventually be implemented to provide a collaborative way of engaging with identity-having /// features like the terminal. pub struct ProgramManager { // TODO: Make this a hashset or something modals: HashMap, } impl ProgramManager { pub fn insert_or_replace( window: usize, program: ModelHandle, cx: &mut ViewContext, ) -> Option { cx.update_global::(|pm, _| { pm.insert_or_replace_internal::(window, program) }) } pub fn remove( window: usize, cx: &mut ViewContext, ) -> Option> { cx.update_global::(|pm, _| pm.remove_internal::(window)) } pub fn new() -> Self { Self { modals: Default::default(), } } /// Inserts or replaces the model at the given location. fn insert_or_replace_internal( &mut self, window: usize, program: ModelHandle, ) -> Option { self.modals.insert(window, AnyModelHandle::from(program)) } /// Remove the program associated with this window, if it's of the given type fn remove_internal(&mut self, window: usize) -> Option> { let program = self.modals.remove(&window); if let Some(program) = program { if program.is::() { // Guaranteed to be some, but leave it in the option // anyway for the API program.downcast() } else { // Model is of the incorrect type, put it back self.modals.insert(window, program); None } } else { None } } }