diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index 33edc27e62..e8be64393f 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -1,6 +1,7 @@ use crate::{status_bar::StatusItemView, Axis, Workspace}; use gpui2::{ - Action, AnyView, EventEmitter, Render, Subscription, View, ViewContext, WeakView, WindowContext, + Action, AnyView, Div, EventEmitter, Render, Subscription, View, ViewContext, WeakView, + WindowContext, }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -176,226 +177,226 @@ pub struct PanelButtons { workspace: WeakView, } -// impl Dock { -// pub fn new(position: DockPosition) -> Self { -// Self { -// position, -// panel_entries: Default::default(), -// active_panel_index: 0, -// is_open: false, -// } -// } +impl Dock { + // pub fn new(position: DockPosition) -> Self { + // Self { + // position, + // panel_entries: Default::default(), + // active_panel_index: 0, + // is_open: false, + // } + // } -// pub fn position(&self) -> DockPosition { -// self.position -// } + // pub fn position(&self) -> DockPosition { + // self.position + // } -// pub fn is_open(&self) -> bool { -// self.is_open -// } + pub fn is_open(&self) -> bool { + self.is_open + } -// pub fn has_focus(&self, cx: &WindowContext) -> bool { -// self.visible_panel() -// .map_or(false, |panel| panel.has_focus(cx)) -// } + // pub fn has_focus(&self, cx: &WindowContext) -> bool { + // self.visible_panel() + // .map_or(false, |panel| panel.has_focus(cx)) + // } -// pub fn panel(&self) -> Option> { -// self.panel_entries -// .iter() -// .find_map(|entry| entry.panel.as_any().clone().downcast()) -// } + // pub fn panel(&self) -> Option> { + // self.panel_entries + // .iter() + // .find_map(|entry| entry.panel.as_any().clone().downcast()) + // } -// pub fn panel_index_for_type(&self) -> Option { -// self.panel_entries -// .iter() -// .position(|entry| entry.panel.as_any().is::()) -// } + // pub fn panel_index_for_type(&self) -> Option { + // self.panel_entries + // .iter() + // .position(|entry| entry.panel.as_any().is::()) + // } -// pub fn panel_index_for_ui_name(&self, ui_name: &str, cx: &AppContext) -> Option { -// todo!() -// // self.panel_entries.iter().position(|entry| { -// // let panel = entry.panel.as_any(); -// // cx.view_ui_name(panel.window(), panel.id()) == Some(ui_name) -// // }) -// } + // pub fn panel_index_for_ui_name(&self, ui_name: &str, cx: &AppContext) -> Option { + // todo!() + // // self.panel_entries.iter().position(|entry| { + // // let panel = entry.panel.as_any(); + // // cx.view_ui_name(panel.window(), panel.id()) == Some(ui_name) + // // }) + // } -// pub fn active_panel_index(&self) -> usize { -// self.active_panel_index -// } + // pub fn active_panel_index(&self) -> usize { + // self.active_panel_index + // } -// pub(crate) fn set_open(&mut self, open: bool, cx: &mut ViewContext) { -// if open != self.is_open { -// self.is_open = open; -// if let Some(active_panel) = self.panel_entries.get(self.active_panel_index) { -// active_panel.panel.set_active(open, cx); -// } + // pub(crate) fn set_open(&mut self, open: bool, cx: &mut ViewContext) { + // if open != self.is_open { + // self.is_open = open; + // if let Some(active_panel) = self.panel_entries.get(self.active_panel_index) { + // active_panel.panel.set_active(open, cx); + // } -// cx.notify(); -// } -// } + // cx.notify(); + // } + // } -// pub fn set_panel_zoomed(&mut self, panel: &AnyView, zoomed: bool, cx: &mut ViewContext) { -// for entry in &mut self.panel_entries { -// if entry.panel.as_any() == panel { -// if zoomed != entry.panel.is_zoomed(cx) { -// entry.panel.set_zoomed(zoomed, cx); -// } -// } else if entry.panel.is_zoomed(cx) { -// entry.panel.set_zoomed(false, cx); -// } -// } + // pub fn set_panel_zoomed(&mut self, panel: &AnyView, zoomed: bool, cx: &mut ViewContext) { + // for entry in &mut self.panel_entries { + // if entry.panel.as_any() == panel { + // if zoomed != entry.panel.is_zoomed(cx) { + // entry.panel.set_zoomed(zoomed, cx); + // } + // } else if entry.panel.is_zoomed(cx) { + // entry.panel.set_zoomed(false, cx); + // } + // } -// cx.notify(); -// } + // cx.notify(); + // } -// pub fn zoom_out(&mut self, cx: &mut ViewContext) { -// for entry in &mut self.panel_entries { -// if entry.panel.is_zoomed(cx) { -// entry.panel.set_zoomed(false, cx); -// } -// } -// } + // pub fn zoom_out(&mut self, cx: &mut ViewContext) { + // for entry in &mut self.panel_entries { + // if entry.panel.is_zoomed(cx) { + // entry.panel.set_zoomed(false, cx); + // } + // } + // } -// pub(crate) fn add_panel(&mut self, panel: View, cx: &mut ViewContext) { -// let subscriptions = [ -// cx.observe(&panel, |_, _, cx| cx.notify()), -// cx.subscribe(&panel, |this, panel, event, cx| { -// if T::should_activate_on_event(event) { -// if let Some(ix) = this -// .panel_entries -// .iter() -// .position(|entry| entry.panel.id() == panel.id()) -// { -// this.set_open(true, cx); -// this.activate_panel(ix, cx); -// cx.focus(&panel); -// } -// } else if T::should_close_on_event(event) -// && this.visible_panel().map_or(false, |p| p.id() == panel.id()) -// { -// this.set_open(false, cx); -// } -// }), -// ]; + // pub(crate) fn add_panel(&mut self, panel: View, cx: &mut ViewContext) { + // let subscriptions = [ + // cx.observe(&panel, |_, _, cx| cx.notify()), + // cx.subscribe(&panel, |this, panel, event, cx| { + // if T::should_activate_on_event(event) { + // if let Some(ix) = this + // .panel_entries + // .iter() + // .position(|entry| entry.panel.id() == panel.id()) + // { + // this.set_open(true, cx); + // this.activate_panel(ix, cx); + // cx.focus(&panel); + // } + // } else if T::should_close_on_event(event) + // && this.visible_panel().map_or(false, |p| p.id() == panel.id()) + // { + // this.set_open(false, cx); + // } + // }), + // ]; -// let dock_view_id = cx.view_id(); -// self.panel_entries.push(PanelEntry { -// panel: Arc::new(panel), -// // todo!() -// // context_menu: cx.add_view(|cx| { -// // let mut menu = ContextMenu::new(dock_view_id, cx); -// // menu.set_position_mode(OverlayPositionMode::Local); -// // menu -// // }), -// _subscriptions: subscriptions, -// }); -// cx.notify() -// } + // let dock_view_id = cx.view_id(); + // self.panel_entries.push(PanelEntry { + // panel: Arc::new(panel), + // // todo!() + // // context_menu: cx.add_view(|cx| { + // // let mut menu = ContextMenu::new(dock_view_id, cx); + // // menu.set_position_mode(OverlayPositionMode::Local); + // // menu + // // }), + // _subscriptions: subscriptions, + // }); + // cx.notify() + // } -// pub fn remove_panel(&mut self, panel: &View, cx: &mut ViewContext) { -// if let Some(panel_ix) = self -// .panel_entries -// .iter() -// .position(|entry| entry.panel.id() == panel.id()) -// { -// if panel_ix == self.active_panel_index { -// self.active_panel_index = 0; -// self.set_open(false, cx); -// } else if panel_ix < self.active_panel_index { -// self.active_panel_index -= 1; -// } -// self.panel_entries.remove(panel_ix); -// cx.notify(); -// } -// } + // pub fn remove_panel(&mut self, panel: &View, cx: &mut ViewContext) { + // if let Some(panel_ix) = self + // .panel_entries + // .iter() + // .position(|entry| entry.panel.id() == panel.id()) + // { + // if panel_ix == self.active_panel_index { + // self.active_panel_index = 0; + // self.set_open(false, cx); + // } else if panel_ix < self.active_panel_index { + // self.active_panel_index -= 1; + // } + // self.panel_entries.remove(panel_ix); + // cx.notify(); + // } + // } -// pub fn panels_len(&self) -> usize { -// self.panel_entries.len() -// } + // pub fn panels_len(&self) -> usize { + // self.panel_entries.len() + // } -// pub fn activate_panel(&mut self, panel_ix: usize, cx: &mut ViewContext) { -// if panel_ix != self.active_panel_index { -// if let Some(active_panel) = self.panel_entries.get(self.active_panel_index) { -// active_panel.panel.set_active(false, cx); -// } + // pub fn activate_panel(&mut self, panel_ix: usize, cx: &mut ViewContext) { + // if panel_ix != self.active_panel_index { + // if let Some(active_panel) = self.panel_entries.get(self.active_panel_index) { + // active_panel.panel.set_active(false, cx); + // } -// self.active_panel_index = panel_ix; -// if let Some(active_panel) = self.panel_entries.get(self.active_panel_index) { -// active_panel.panel.set_active(true, cx); -// } + // self.active_panel_index = panel_ix; + // if let Some(active_panel) = self.panel_entries.get(self.active_panel_index) { + // active_panel.panel.set_active(true, cx); + // } -// cx.notify(); -// } -// } + // cx.notify(); + // } + // } -// pub fn visible_panel(&self) -> Option<&Arc> { -// let entry = self.visible_entry()?; -// Some(&entry.panel) -// } + pub fn visible_panel(&self) -> Option<&Arc> { + let entry = self.visible_entry()?; + Some(&entry.panel) + } -// pub fn active_panel(&self) -> Option<&Arc> { -// Some(&self.panel_entries.get(self.active_panel_index)?.panel) -// } + // pub fn active_panel(&self) -> Option<&Arc> { + // Some(&self.panel_entries.get(self.active_panel_index)?.panel) + // } -// fn visible_entry(&self) -> Option<&PanelEntry> { -// if self.is_open { -// self.panel_entries.get(self.active_panel_index) -// } else { -// None -// } -// } + fn visible_entry(&self) -> Option<&PanelEntry> { + if self.is_open { + self.panel_entries.get(self.active_panel_index) + } else { + None + } + } -// pub fn zoomed_panel(&self, cx: &WindowContext) -> Option> { -// let entry = self.visible_entry()?; -// if entry.panel.is_zoomed(cx) { -// Some(entry.panel.clone()) -// } else { -// None -// } -// } + // pub fn zoomed_panel(&self, cx: &WindowContext) -> Option> { + // let entry = self.visible_entry()?; + // if entry.panel.is_zoomed(cx) { + // Some(entry.panel.clone()) + // } else { + // None + // } + // } -// pub fn panel_size(&self, panel: &dyn PanelHandle, cx: &WindowContext) -> Option { -// self.panel_entries -// .iter() -// .find(|entry| entry.panel.id() == panel.id()) -// .map(|entry| entry.panel.size(cx)) -// } + // pub fn panel_size(&self, panel: &dyn PanelHandle, cx: &WindowContext) -> Option { + // self.panel_entries + // .iter() + // .find(|entry| entry.panel.id() == panel.id()) + // .map(|entry| entry.panel.size(cx)) + // } -// pub fn active_panel_size(&self, cx: &WindowContext) -> Option { -// if self.is_open { -// self.panel_entries -// .get(self.active_panel_index) -// .map(|entry| entry.panel.size(cx)) -// } else { -// None -// } -// } + // pub fn active_panel_size(&self, cx: &WindowContext) -> Option { + // if self.is_open { + // self.panel_entries + // .get(self.active_panel_index) + // .map(|entry| entry.panel.size(cx)) + // } else { + // None + // } + // } -// pub fn resize_active_panel(&mut self, size: Option, cx: &mut ViewContext) { -// if let Some(entry) = self.panel_entries.get_mut(self.active_panel_index) { -// entry.panel.set_size(size, cx); -// cx.notify(); -// } -// } + // pub fn resize_active_panel(&mut self, size: Option, cx: &mut ViewContext) { + // if let Some(entry) = self.panel_entries.get_mut(self.active_panel_index) { + // entry.panel.set_size(size, cx); + // cx.notify(); + // } + // } -// pub fn render_placeholder(&self, cx: &WindowContext) -> AnyElement { -// todo!() -// if let Some(active_entry) = self.visible_entry() { -// Empty::new() -// .into_any() -// .contained() -// .with_style(self.style(cx)) -// .resizable::( -// self.position.to_resize_handle_side(), -// active_entry.panel.size(cx), -// |_, _, _| {}, -// ) -// .into_any() -// } else { -// Empty::new().into_any() -// } -// } -// } + // pub fn render_placeholder(&self, cx: &WindowContext) -> AnyElement { + // todo!() + // if let Some(active_entry) = self.visible_entry() { + // Empty::new() + // .into_any() + // .contained() + // .with_style(self.style(cx)) + // .resizable::( + // self.position.to_resize_handle_side(), + // active_entry.panel.size(cx), + // |_, _, _| {}, + // ) + // .into_any() + // } else { + // Empty::new().into_any() + // } + // } +} // todo!() // impl View for Dock { @@ -596,15 +597,23 @@ impl EventEmitter for PanelButtons { // } // } -// impl StatusItemView for PanelButtons { -// fn set_active_pane_item( -// &mut self, -// active_pane_item: Option<&dyn crate::ItemHandle>, -// cx: &mut ViewContext, -// ) { -// todo!() -// } -// } +impl Render for PanelButtons { + type Element = Div; + + fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + todo!() + } +} + +impl StatusItemView for PanelButtons { + fn set_active_pane_item( + &mut self, + active_pane_item: Option<&dyn crate::ItemHandle>, + cx: &mut ViewContext, + ) { + todo!() + } +} #[cfg(any(test, feature = "test-support"))] pub mod test { diff --git a/crates/workspace2/src/item.rs b/crates/workspace2/src/item.rs index 554a7aadb6..ccf6adfdda 100644 --- a/crates/workspace2/src/item.rs +++ b/crates/workspace2/src/item.rs @@ -691,58 +691,58 @@ pub trait FollowableItemHandle: ItemHandle { fn is_project_item(&self, cx: &AppContext) -> bool; } -// impl FollowableItemHandle for View { -// fn remote_id(&self, client: &Arc, cx: &AppContext) -> Option { -// self.read(cx).remote_id().or_else(|| { -// client.peer_id().map(|creator| ViewId { -// creator, -// id: self.id() as u64, -// }) -// }) -// } +impl FollowableItemHandle for View { + fn remote_id(&self, client: &Arc, cx: &AppContext) -> Option { + self.read(cx).remote_id().or_else(|| { + client.peer_id().map(|creator| ViewId { + creator, + id: self.id() as u64, + }) + }) + } -// fn set_leader_peer_id(&self, leader_peer_id: Option, cx: &mut WindowContext) { -// self.update(cx, |this, cx| this.set_leader_peer_id(leader_peer_id, cx)) -// } + fn set_leader_peer_id(&self, leader_peer_id: Option, cx: &mut WindowContext) { + self.update(cx, |this, cx| this.set_leader_peer_id(leader_peer_id, cx)) + } -// fn to_state_proto(&self, cx: &AppContext) -> Option { -// self.read(cx).to_state_proto(cx) -// } + fn to_state_proto(&self, cx: &AppContext) -> Option { + self.read(cx).to_state_proto(cx) + } -// fn add_event_to_update_proto( -// &self, -// event: &dyn Any, -// update: &mut Option, -// cx: &AppContext, -// ) -> bool { -// if let Some(event) = event.downcast_ref() { -// self.read(cx).add_event_to_update_proto(event, update, cx) -// } else { -// false -// } -// } + fn add_event_to_update_proto( + &self, + event: &dyn Any, + update: &mut Option, + cx: &AppContext, + ) -> bool { + if let Some(event) = event.downcast_ref() { + self.read(cx).add_event_to_update_proto(event, update, cx) + } else { + false + } + } -// fn apply_update_proto( -// &self, -// project: &Model, -// message: proto::update_view::Variant, -// cx: &mut WindowContext, -// ) -> Task> { -// self.update(cx, |this, cx| this.apply_update_proto(project, message, cx)) -// } + fn apply_update_proto( + &self, + project: &Model, + message: proto::update_view::Variant, + cx: &mut WindowContext, + ) -> Task> { + self.update(cx, |this, cx| this.apply_update_proto(project, message, cx)) + } -// fn should_unfollow_on_event(&self, event: &dyn Any, cx: &AppContext) -> bool { -// if let Some(event) = event.downcast_ref() { -// T::should_unfollow_on_event(event, cx) -// } else { -// false -// } -// } + fn should_unfollow_on_event(&self, event: &dyn Any, cx: &AppContext) -> bool { + if let Some(event) = event.downcast_ref() { + T::should_unfollow_on_event(event, cx) + } else { + false + } + } -// fn is_project_item(&self, cx: &AppContext) -> bool { -// self.read(cx).is_project_item(cx) -// } -// } + fn is_project_item(&self, cx: &AppContext) -> bool { + self.read(cx).is_project_item(cx) + } +} // #[cfg(any(test, feature = "test-support"))] // pub mod test { diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 9325f58b37..fc74139238 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -178,7 +178,7 @@ pub struct Pane { // tab_context_menu: ViewHandle, // workspace: WeakView, project: Model, - // has_focus: bool, + has_focus: bool, // can_drop: Rc, &WindowContext) -> bool>, // can_split: bool, // render_tab_bar_buttons: Rc) -> AnyElement>, @@ -348,7 +348,7 @@ impl Pane { // tab_context_menu: cx.add_view(|cx| ContextMenu::new(pane_view_id, cx)), // workspace, project, - // has_focus: false, + has_focus: false, // can_drop: Rc::new(|_, _| true), // can_split: true, // render_tab_bar_buttons: Rc::new(move |pane, cx| { @@ -415,9 +415,9 @@ impl Pane { // &self.workspace // } - // pub fn has_focus(&self) -> bool { - // self.has_focus - // } + pub fn has_focus(&self) -> bool { + self.has_focus + } // pub fn active_item_index(&self) -> usize { // self.active_item_index @@ -614,9 +614,9 @@ impl Pane { self.items.len() } - // pub fn items(&self) -> impl Iterator> + DoubleEndedIterator { - // self.items.iter() - // } + pub fn items(&self) -> impl Iterator> + DoubleEndedIterator { + self.items.iter() + } // pub fn items_of_type(&self) -> impl '_ + Iterator> { // self.items diff --git a/crates/workspace2/src/pane_group.rs b/crates/workspace2/src/pane_group.rs index 964194ef22..4d71cf397b 100644 --- a/crates/workspace2/src/pane_group.rs +++ b/crates/workspace2/src/pane_group.rs @@ -2,22 +2,24 @@ use crate::{AppState, FollowerState, Pane, Workspace}; use anyhow::{anyhow, Result}; use call2::ActiveCall; use collections::HashMap; -use gpui2::{size, AnyElement, AnyView, Bounds, Handle, Model, Pixels, Point, View, ViewContext}; +use gpui2::{point, size, AnyElement, AnyView, Bounds, Model, Pixels, Point, View, ViewContext}; +use parking_lot::Mutex; use project2::Project; use serde::Deserialize; -use std::{cell::RefCell, rc::Rc, sync::Arc}; +use std::sync::Arc; use theme2::Theme; const HANDLE_HITBOX_SIZE: f32 = 4.0; const HORIZONTAL_MIN_SIZE: f32 = 80.; const VERTICAL_MIN_SIZE: f32 = 100.; +#[derive(Copy, Clone, PartialEq, Eq)] pub enum Axis { Vertical, Horizontal, } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, PartialEq)] pub struct PaneGroup { pub(crate) root: Member, } @@ -305,18 +307,24 @@ impl Member { } } -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone)] pub(crate) struct PaneAxis { pub axis: Axis, pub members: Vec, - pub flexes: Rc>>, - pub bounding_boxes: Rc>>>>, + pub flexes: Arc>>, + pub bounding_boxes: Arc>>>>, +} + +impl PartialEq for PaneAxis { + fn eq(&self, other: &Self) -> bool { + todo!() + } } impl PaneAxis { pub fn new(axis: Axis, members: Vec) -> Self { - let flexes = Rc::new(RefCell::new(vec![1.; members.len()])); - let bounding_boxes = Rc::new(RefCell::new(vec![None; members.len()])); + let flexes = Arc::new(Mutex::new(vec![1.; members.len()])); + let bounding_boxes = Arc::new(Mutex::new(vec![None; members.len()])); Self { axis, members, @@ -329,8 +337,8 @@ impl PaneAxis { let flexes = flexes.unwrap_or_else(|| vec![1.; members.len()]); debug_assert!(members.len() == flexes.len()); - let flexes = Rc::new(RefCell::new(flexes)); - let bounding_boxes = Rc::new(RefCell::new(vec![None; members.len()])); + let flexes = Arc::new(Mutex::new(flexes)); + let bounding_boxes = Arc::new(Mutex::new(vec![None; members.len()])); Self { axis, members, @@ -360,7 +368,7 @@ impl PaneAxis { } self.members.insert(idx, Member::Pane(new_pane.clone())); - *self.flexes.borrow_mut() = vec![1.; self.members.len()]; + *self.flexes.lock() = vec![1.; self.members.len()]; } else { *member = Member::new_axis(old_pane.clone(), new_pane.clone(), direction); @@ -400,12 +408,12 @@ impl PaneAxis { if found_pane { if let Some(idx) = remove_member { self.members.remove(idx); - *self.flexes.borrow_mut() = vec![1.; self.members.len()]; + *self.flexes.lock() = vec![1.; self.members.len()]; } if self.members.len() == 1 { let result = self.members.pop(); - *self.flexes.borrow_mut() = vec![1.; self.members.len()]; + *self.flexes.lock() = vec![1.; self.members.len()]; Ok(result) } else { Ok(None) @@ -431,13 +439,13 @@ impl PaneAxis { } fn bounding_box_for_pane(&self, pane: &View) -> Option> { - debug_assert!(self.members.len() == self.bounding_boxes.borrow().len()); + debug_assert!(self.members.len() == self.bounding_boxes.lock().len()); for (idx, member) in self.members.iter().enumerate() { match member { Member::Pane(found) => { if pane == found { - return self.bounding_boxes.borrow()[idx]; + return self.bounding_boxes.lock()[idx]; } } Member::Axis(axis) => { @@ -451,9 +459,9 @@ impl PaneAxis { } fn pane_at_pixel_position(&self, coordinate: Point) -> Option<&View> { - debug_assert!(self.members.len() == self.bounding_boxes.borrow().len()); + debug_assert!(self.members.len() == self.bounding_boxes.lock().len()); - let bounding_boxes = self.bounding_boxes.borrow(); + let bounding_boxes = self.bounding_boxes.lock(); for (idx, member) in self.members.iter().enumerate() { if let Some(coordinates) = bounding_boxes[idx] { @@ -480,7 +488,7 @@ impl PaneAxis { app_state: &Arc, cx: &mut ViewContext, ) -> AnyElement { - debug_assert!(self.members.len() == self.flexes.borrow().len()); + debug_assert!(self.members.len() == self.flexes.lock().len()); todo!() // let mut pane_axis = PaneAxisElement::new( @@ -546,32 +554,32 @@ impl SplitDirection { [Self::Up, Self::Down, Self::Left, Self::Right] } - pub fn edge(&self, rect: Bounds) -> f32 { + pub fn edge(&self, rect: Bounds) -> Pixels { match self { - Self::Up => rect.min_y(), - Self::Down => rect.max_y(), - Self::Left => rect.min_x(), - Self::Right => rect.max_x(), + Self::Up => rect.origin.y, + Self::Down => rect.lower_left().y, + Self::Left => rect.lower_left().x, + Self::Right => rect.lower_right().x, } } pub fn along_edge(&self, bounds: Bounds, length: Pixels) -> Bounds { match self { Self::Up => Bounds { - origin: bounds.origin(), - size: size(bounds.width(), length), + origin: bounds.origin, + size: size(bounds.size.width, length), }, Self::Down => Bounds { - origin: size(bounds.min_x(), bounds.max_y() - length), - size: size(bounds.width(), length), + origin: point(bounds.lower_left().x, bounds.lower_left().y - length), + size: size(bounds.size.width, length), }, Self::Left => Bounds { - origin: bounds.origin(), - size: size(length, bounds.height()), + origin: bounds.origin, + size: size(length, bounds.size.height), }, Self::Right => Bounds { - origin: size(bounds.max_x() - length, bounds.min_y()), - size: size(length, bounds.height()), + origin: point(bounds.lower_right().x - length, bounds.lower_left().y), + size: size(length, bounds.size.height), }, } } diff --git a/crates/workspace2/src/persistence/model.rs b/crates/workspace2/src/persistence/model.rs index 4323e6dae0..6e6cb8e55c 100644 --- a/crates/workspace2/src/persistence/model.rs +++ b/crates/workspace2/src/persistence/model.rs @@ -55,7 +55,7 @@ impl Column for WorkspaceLocation { } } -#[derive(Debug, PartialEq, Clone)] +#[derive(PartialEq, Clone)] pub struct SerializedWorkspace { pub id: WorkspaceId, pub location: WorkspaceLocation, @@ -127,7 +127,7 @@ impl Bind for DockData { } } -#[derive(Debug, PartialEq, Clone)] +#[derive(PartialEq, Clone)] pub enum SerializedPaneGroup { Group { axis: Axis, diff --git a/crates/workspace2/src/searchable.rs b/crates/workspace2/src/searchable.rs index 591fab5cd9..7b911b75d0 100644 --- a/crates/workspace2/src/searchable.rs +++ b/crates/workspace2/src/searchable.rs @@ -1,6 +1,6 @@ use std::{any::Any, sync::Arc}; -use gpui2::{AppContext, Subscription, Task, View, ViewContext, WindowContext}; +use gpui2::{AnyView, AppContext, Subscription, Task, View, ViewContext, WindowContext}; use project2::search::SearchQuery; use crate::{ @@ -95,7 +95,7 @@ pub trait SearchableItemHandle: ItemHandle { fn subscribe_to_search_events( &self, cx: &mut WindowContext, - handler: Box, + handler: Box, ) -> Subscription; fn clear_matches(&self, cx: &mut WindowContext); fn update_matches(&self, matches: &Vec>, cx: &mut WindowContext); @@ -130,7 +130,8 @@ pub trait SearchableItemHandle: ItemHandle { impl SearchableItemHandle for View { fn downgrade(&self) -> Box { - Box::new(self.downgrade()) + // Box::new(self.downgrade()) + todo!() } fn boxed_clone(&self) -> Box { @@ -144,7 +145,7 @@ impl SearchableItemHandle for View { fn subscribe_to_search_events( &self, cx: &mut WindowContext, - handler: Box, + handler: Box, ) -> Subscription { cx.subscribe(self, move |handle, event, cx| { let search_event = handle.update(cx, |handle, cx| handle.to_search_event(event, cx)); @@ -198,7 +199,7 @@ impl SearchableItemHandle for View { cx: &mut WindowContext, ) -> Task>> { let matches = self.update(cx, |this, cx| this.find_matches(query, cx)); - cx.foreground().spawn(async { + cx.spawn_on_main(|cx| async { let matches = matches.await; matches .into_iter() @@ -231,23 +232,21 @@ fn downcast_matches(matches: &Vec>) -> Vec> for AnyViewHandle { -// fn from(this: Box) -> Self { -// this.as_any().clone() -// } -// } +impl From> for AnyView { + fn from(this: Box) -> Self { + this.to_any().clone() + } +} -// todo!() -// impl From<&Box> for AnyViewHandle { -// fn from(this: &Box) -> Self { -// this.as_any().clone() -// } -// } +impl From<&Box> for AnyView { + fn from(this: &Box) -> Self { + this.to_any().clone() + } +} impl PartialEq for Box { fn eq(&self, other: &Self) -> bool { - self.id() == other.id() && self.window() == other.window() + self.id() == other.id() } } @@ -256,24 +255,23 @@ impl Eq for Box {} pub trait WeakSearchableItemHandle: WeakItemHandle { fn upgrade(&self, cx: &AppContext) -> Option>; - // todo!() - // fn into_any(self) -> AnyWeakViewHandle; + // fn into_any(self) -> AnyWeakView; } // todo!() -// impl WeakSearchableItemHandle for WeakViewHandle { +// impl WeakSearchableItemHandle for WeakView { // fn upgrade(&self, cx: &AppContext) -> Option> { // Some(Box::new(self.upgrade(cx)?)) // } -// fn into_any(self) -> AnyWeakViewHandle { -// self.into_any() -// } +// // fn into_any(self) -> AnyView { +// // self.into_any() +// // } // } impl PartialEq for Box { fn eq(&self, other: &Self) -> bool { - self.id() == other.id() && self.window() == other.window() + self.id() == other.id() } } @@ -281,6 +279,6 @@ impl Eq for Box {} impl std::hash::Hash for Box { fn hash(&self, state: &mut H) { - (self.id(), self.window().id()).hash(state) + self.id().hash(state) } } diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 3e1578f779..fda2b189ff 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -11,21 +11,25 @@ mod toolbar; mod workspace_settings; use anyhow::{anyhow, Result}; +use call2::ActiveCall; use client2::{ proto::{self, PeerId}, Client, UserStore, }; use collections::{HashMap, HashSet}; +use dock::Dock; use futures::{channel::oneshot, FutureExt}; use gpui2::{ - AnyModel, AnyView, AppContext, AsyncAppContext, DisplayId, MainThread, Model, Task, View, - ViewContext, VisualContext, WeakModel, WeakView, WindowBounds, WindowHandle, WindowOptions, + AnyModel, AnyView, AppContext, AsyncAppContext, DisplayId, EventEmitter, MainThread, Model, + Subscription, Task, View, ViewContext, VisualContext, WeakModel, WeakView, WindowBounds, + WindowHandle, WindowOptions, }; use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem}; use language2::LanguageRegistry; use node_runtime::NodeRuntime; pub use pane::*; pub use pane_group::*; +use persistence::model::{ItemId, WorkspaceLocation}; use project2::{Project, ProjectEntryId, ProjectPath, Worktree}; use std::{ any::TypeId, @@ -37,7 +41,8 @@ pub use toolbar::{ToolbarItemLocation, ToolbarItemView}; use util::ResultExt; use crate::persistence::model::{ - DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup, SerializedWorkspace, + DockData, DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup, + SerializedWorkspace, }; // lazy_static! { @@ -386,14 +391,13 @@ type ItemDeserializers = HashMap< ) -> Task>>, >; pub fn register_deserializable_item(cx: &mut AppContext) { - cx.update_default_global(|deserializers: &mut ItemDeserializers, _cx| { + cx.update_global(|deserializers: &mut ItemDeserializers, _cx| { if let Some(serialized_item_kind) = I::serialized_item_kind() { deserializers.insert( Arc::from(serialized_item_kind), |project, workspace, workspace_id, item_id, cx| { let task = I::deserialize(project, workspace, workspace_id, item_id, cx); - cx.foreground() - .spawn(async { Ok(Box::new(task.await?) as Box<_>) }) + cx.spawn_on_main(|cx| async { Ok(Box::new(task.await?) as Box<_>) }) }, ); } @@ -426,6 +430,7 @@ struct Follower { peer_id: PeerId, } +// todo!() // impl AppState { // #[cfg(any(test, feature = "test-support"))] // pub fn test(cx: &mut AppContext) -> Arc { @@ -476,7 +481,7 @@ impl DelayedDebouncedEditAction { fn fire_new(&mut self, delay: Duration, cx: &mut ViewContext, func: F) where - F: 'static + FnOnce(&mut Workspace, &mut ViewContext) -> Task>, + F: 'static + Send + FnOnce(&mut Workspace, &mut ViewContext) -> Task>, { if let Some(channel) = self.cancel_channel.take() { _ = channel.send(()); @@ -517,7 +522,7 @@ pub struct Workspace { // modal: Option, // zoomed: Option, // zoomed_position: Option, - // center: PaneGroup, + center: PaneGroup, left_dock: View, bottom_dock: View, right_dock: View, @@ -533,9 +538,9 @@ pub struct Workspace { follower_states: HashMap, FollowerState>, last_leaders_by_pane: HashMap, PeerId>, // window_edited: bool, - // active_call: Option<(ModelHandle, Vec)>, + active_call: Option<(Model, Vec)>, // leader_updates_tx: mpsc::UnboundedSender<(PeerId, proto::UpdateFollowers)>, - // database_id: WorkspaceId, + database_id: WorkspaceId, app_state: Arc, // subscriptions: Vec, // _apply_leader_updates: Task>, @@ -1925,19 +1930,21 @@ impl Workspace { // } fn add_pane(&mut self, cx: &mut ViewContext) -> View { - let pane = cx.build_view(|cx| { - Pane::new( - self.weak_handle(), - self.project.clone(), - self.pane_history_timestamp.clone(), - cx, - ) - }); - cx.subscribe(&pane, Self::handle_pane_event).detach(); - self.panes.push(pane.clone()); - cx.focus(&pane); - cx.emit(Event::PaneAdded(pane.clone())); - pane + todo!() + // let pane = cx.build_view(|cx| { + // Pane::new( + // self.weak_handle(), + // self.project.clone(), + // self.pane_history_timestamp.clone(), + // cx, + // ) + // }); + // cx.subscribe(&pane, Self::handle_pane_event).detach(); + // self.panes.push(pane.clone()); + // todo!() + // cx.focus(&pane); + // cx.emit(Event::PaneAdded(pane.clone())); + // pane } // pub fn add_item_to_center( @@ -2083,19 +2090,19 @@ impl Workspace { ) -> Task< Result<( ProjectEntryId, - impl 'static + FnOnce(&mut ViewContext) -> Box, + impl 'static + Send + FnOnce(&mut ViewContext) -> Box, )>, > { let project = self.project().clone(); let project_item = project.update(cx, |project, cx| project.open_path(path, cx)); - cx.spawn(|_, mut cx| async move { + cx.spawn(|_, cx| async move { let (project_entry_id, project_item) = project_item.await?; let build_item = cx.update(|cx| { cx.default_global::() - .get(&project_item.model_type()) + .get(&project_item.type_id()) .ok_or_else(|| anyhow!("no item builder for project item")) .cloned() - })?; + })??; let build_item = move |cx: &mut ViewContext| build_item(project, project_item, cx); Ok((project_entry_id, build_item)) @@ -3012,14 +3019,14 @@ impl Workspace { &self, project_only: bool, update: proto::update_followers::Variant, - cx: &AppContext, + cx: &mut AppContext, ) -> Option<()> { let project_id = if project_only { self.project.read(cx).remote_id() } else { None }; - self.app_state().workspace_store.read_with(cx, |store, cx| { + self.app_state().workspace_store.update(cx, |store, cx| { store.update_followers(project_id, update, cx) }) } @@ -3141,9 +3148,9 @@ impl Workspace { // } // } - // fn active_call(&self) -> Option<&ModelHandle> { - // self.active_call.as_ref().map(|(call, _)| call) - // } + fn active_call(&self) -> Option<&Model> { + self.active_call.as_ref().map(|(call, _)| call) + } // fn on_active_call_event( // &mut self, @@ -3164,21 +3171,21 @@ impl Workspace { // self.database_id // } - // fn location(&self, cx: &AppContext) -> Option { - // let project = self.project().read(cx); + fn location(&self, cx: &AppContext) -> Option { + let project = self.project().read(cx); - // if project.is_local() { - // Some( - // project - // .visible_worktrees(cx) - // .map(|worktree| worktree.read(cx).abs_path()) - // .collect::>() - // .into(), - // ) - // } else { - // None - // } - // } + if project.is_local() { + Some( + project + .visible_worktrees(cx) + .map(|worktree| worktree.read(cx).abs_path()) + .collect::>() + .into(), + ) + } else { + None + } + } // fn remove_panes(&mut self, member: Member, cx: &mut ViewContext) { // match member { @@ -3193,14 +3200,17 @@ impl Workspace { // } // } - // fn force_remove_pane(&mut self, pane: &View, cx: &mut ViewContext) { - // self.panes.retain(|p| p != pane); - // cx.focus(self.panes.last().unwrap()); - // if self.last_active_center_pane == Some(pane.downgrade()) { - // self.last_active_center_pane = None; - // } - // cx.notify(); - // } + fn force_remove_pane(&mut self, pane: &View, cx: &mut ViewContext) { + self.panes.retain(|p| p != pane); + if true { + todo!() + // cx.focus(self.panes.last().unwrap()); + } + if self.last_active_center_pane == Some(pane.downgrade()) { + self.last_active_center_pane = None; + } + cx.notify(); + } // fn schedule_serialize(&mut self, cx: &mut ViewContext) { // self._schedule_serialize = Some(cx.spawn(|this, cx| async move { @@ -3248,7 +3258,7 @@ impl Workspace { .iter() .map(|member| build_serialized_pane_group(member, cx)) .collect::>(), - flexes: Some(flexes.borrow().clone()), + flexes: Some(flexes.lock().clone()), }, Member::Pane(pane_handle) => { SerializedPaneGroup::Pane(serialize_pane_handle(&pane_handle, cx)) @@ -3260,10 +3270,11 @@ impl Workspace { let left_dock = this.left_dock.read(cx); let left_visible = left_dock.is_open(); let left_active_panel = left_dock.visible_panel().and_then(|panel| { - Some( - cx.view_ui_name(panel.as_any().window(), panel.id())? - .to_string(), - ) + todo!() + // Some( + // cx.view_ui_name(panel.as_any().window(), panel.id())? + // .to_string(), + // ) }); let left_dock_zoom = left_dock .visible_panel() @@ -3273,10 +3284,11 @@ impl Workspace { let right_dock = this.right_dock.read(cx); let right_visible = right_dock.is_open(); let right_active_panel = right_dock.visible_panel().and_then(|panel| { - Some( - cx.view_ui_name(panel.as_any().window(), panel.id())? - .to_string(), - ) + todo!() + // Some( + // cx.view_ui_name(panel.as_any().window(), panel.id())? + // .to_string(), + // ) }); let right_dock_zoom = right_dock .visible_panel() @@ -3286,10 +3298,11 @@ impl Workspace { let bottom_dock = this.bottom_dock.read(cx); let bottom_visible = bottom_dock.is_open(); let bottom_active_panel = bottom_dock.visible_panel().and_then(|panel| { - Some( - cx.view_ui_name(panel.as_any().window(), panel.id())? - .to_string(), - ) + todo!() + // Some( + // cx.view_ui_name(panel.as_any().window(), panel.id())? + // .to_string(), + // ) }); let bottom_dock_zoom = bottom_dock .visible_panel() @@ -3332,8 +3345,7 @@ impl Workspace { docks, }; - cx.background() - .spawn(persistence::DB.save_workspace(serialized_workspace)) + cx.spawn(|_, _| persistence::DB.save_workspace(serialized_workspace)) .detach(); } } @@ -3719,6 +3731,11 @@ impl Workspace { // .log_err(); // } +impl EventEmitter for Workspace { + type Event = Event; +} + +// todo!() // impl Entity for Workspace { // type Event = Event; @@ -3869,54 +3886,55 @@ impl Workspace { // } // } -// impl WorkspaceStore { -// pub fn new(client: Arc, cx: &mut ModelContext) -> Self { -// Self { -// workspaces: Default::default(), -// followers: Default::default(), -// _subscriptions: vec![ -// client.add_request_handler(cx.handle(), Self::handle_follow), -// client.add_message_handler(cx.handle(), Self::handle_unfollow), -// client.add_message_handler(cx.handle(), Self::handle_update_followers), -// ], -// client, -// } -// } +impl WorkspaceStore { + // pub fn new(client: Arc, cx: &mut ModelContext) -> Self { + // Self { + // workspaces: Default::default(), + // followers: Default::default(), + // _subscriptions: vec![ + // client.add_request_handler(cx.handle(), Self::handle_follow), + // client.add_message_handler(cx.handle(), Self::handle_unfollow), + // client.add_message_handler(cx.handle(), Self::handle_update_followers), + // ], + // client, + // } + // } -// pub fn update_followers( -// &self, -// project_id: Option, -// update: proto::update_followers::Variant, -// cx: &AppContext, -// ) -> Option<()> { -// if !cx.has_global::>() { -// return None; -// } + pub fn update_followers( + &self, + project_id: Option, + update: proto::update_followers::Variant, + cx: &AppContext, + ) -> Option<()> { + if !cx.has_global::>() { + return None; + } -// let room_id = ActiveCall::global(cx).read(cx).room()?.read(cx).id(); -// let follower_ids: Vec<_> = self -// .followers -// .iter() -// .filter_map(|follower| { -// if follower.project_id == project_id || project_id.is_none() { -// Some(follower.peer_id.into()) -// } else { -// None -// } -// }) -// .collect(); -// if follower_ids.is_empty() { -// return None; -// } -// self.client -// .send(proto::UpdateFollowers { -// room_id, -// project_id, -// follower_ids, -// variant: Some(update), -// }) -// .log_err() -// } + let room_id = ActiveCall::global(cx).read(cx).room()?.read(cx).id(); + let follower_ids: Vec<_> = self + .followers + .iter() + .filter_map(|follower| { + if follower.project_id == project_id || project_id.is_none() { + Some(follower.peer_id.into()) + } else { + None + } + }) + .collect(); + if follower_ids.is_empty() { + return None; + } + self.client + .send(proto::UpdateFollowers { + room_id, + project_id, + follower_ids, + variant: Some(update), + }) + .log_err() + } +} // async fn handle_follow( // this: ModelHandle, @@ -4303,13 +4321,14 @@ pub fn open_paths( .await; if let Some(existing) = existing { - Ok(( - existing.clone(), - cx.update_window_root(&existing, |workspace, cx| { - workspace.open_paths(abs_paths, true, cx) - })? - .await, - )) + // Ok(( + // existing.clone(), + // cx.update_window_root(&existing, |workspace, cx| { + // workspace.open_paths(abs_paths, true, cx) + // })? + // .await, + // )) + todo!() } else { todo!() // Ok(cx