diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index 5445f8905095d24bd89068d574270bfb7dadafdd..5165c970afc33935d92bf3d5b6a97b498fcfb5e7 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -1,14 +1,13 @@ -use crate::{StatusItemView, Workspace, WorkspaceBounds}; +use crate::{Axis, Workspace}; use gpui2::{ - elements::*, platform::CursorStyle, platform::MouseButton, Action, AnyViewHandle, AppContext, - Axis, Entity, Subscription, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext, + Action, AnyElement, AnyView, AppContext, Render, Subscription, View, ViewContext, WeakView, + WindowContext, }; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use std::rc::Rc; -use theme2::ThemeSettings; +use std::sync::Arc; -pub trait Panel: View { +pub trait Panel: Render { fn position(&self, cx: &WindowContext) -> DockPosition; fn position_is_valid(&self, position: DockPosition) -> bool; fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext); @@ -55,10 +54,10 @@ pub trait PanelHandle { fn icon_tooltip(&self, cx: &WindowContext) -> (String, Option>); fn icon_label(&self, cx: &WindowContext) -> Option; fn has_focus(&self, cx: &WindowContext) -> bool; - fn as_any(&self) -> &AnyViewHandle; + fn to_any(&self) -> AnyView; } -impl PanelHandle for ViewHandle +impl PanelHandle for View where T: Panel, { @@ -114,14 +113,14 @@ where self.read(cx).has_focus(cx) } - fn as_any(&self) -> &AnyViewHandle { - self + fn to_any(&self) -> AnyView { + self.clone().into_any() } } -impl From<&dyn PanelHandle> for AnyViewHandle { +impl From<&dyn PanelHandle> for AnyView { fn from(val: &dyn PanelHandle) -> Self { - val.as_any().clone() + val.to_any() } } @@ -149,13 +148,14 @@ impl DockPosition { } } - fn to_resize_handle_side(self) -> HandleSide { - match self { - Self::Left => HandleSide::Right, - Self::Bottom => HandleSide::Top, - Self::Right => HandleSide::Left, - } - } + // todo!() + // fn to_resize_handle_side(self) -> HandleSide { + // match self { + // Self::Left => HandleSide::Right, + // Self::Bottom => HandleSide::Top, + // Self::Right => HandleSide::Left, + // } + // } pub fn axis(&self) -> Axis { match self { @@ -166,14 +166,15 @@ impl DockPosition { } struct PanelEntry { - panel: Rc, - context_menu: ViewHandle, + panel: Arc, + // todo!() + // context_menu: View, _subscriptions: [Subscription; 2], } pub struct PanelButtons { - dock: ViewHandle, - workspace: WeakViewHandle, + dock: View, + workspace: WeakView, } impl Dock { @@ -199,7 +200,7 @@ impl Dock { .map_or(false, |panel| panel.has_focus(cx)) } - pub fn panel(&self) -> Option> { + pub fn panel(&self) -> Option> { self.panel_entries .iter() .find_map(|entry| entry.panel.as_any().clone().downcast()) @@ -212,10 +213,11 @@ impl Dock { } pub fn panel_index_for_ui_name(&self, ui_name: &str, cx: &AppContext) -> Option { - self.panel_entries.iter().position(|entry| { - let panel = entry.panel.as_any(); - cx.view_ui_name(panel.window(), panel.id()) == Some(ui_name) - }) + 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 { @@ -233,12 +235,7 @@ impl Dock { } } - pub fn set_panel_zoomed( - &mut self, - panel: &AnyViewHandle, - zoomed: bool, - cx: &mut ViewContext, - ) { + 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) { @@ -260,7 +257,7 @@ impl Dock { } } - pub(crate) fn add_panel(&mut self, panel: ViewHandle, cx: &mut ViewContext) { + 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| { @@ -284,18 +281,19 @@ impl Dock { let dock_view_id = cx.view_id(); self.panel_entries.push(PanelEntry { - panel: Rc::new(panel), - context_menu: cx.add_view(|cx| { - let mut menu = ContextMenu::new(dock_view_id, cx); - menu.set_position_mode(OverlayPositionMode::Local); - menu - }), + 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: &ViewHandle, cx: &mut ViewContext) { + pub fn remove_panel(&mut self, panel: &View, cx: &mut ViewContext) { if let Some(panel_ix) = self .panel_entries .iter() @@ -331,12 +329,12 @@ impl Dock { } } - pub fn visible_panel(&self) -> Option<&Rc> { + pub fn visible_panel(&self) -> Option<&Arc> { let entry = self.visible_entry()?; Some(&entry.panel) } - pub fn active_panel(&self) -> Option<&Rc> { + pub fn active_panel(&self) -> Option<&Arc> { Some(&self.panel_entries.get(self.active_panel_index)?.panel) } @@ -348,7 +346,7 @@ impl Dock { } } - pub fn zoomed_panel(&self, cx: &WindowContext) -> Option> { + pub fn zoomed_panel(&self, cx: &WindowContext) -> Option> { let entry = self.visible_entry()?; if entry.panel.is_zoomed(cx) { Some(entry.panel.clone()) @@ -382,227 +380,218 @@ impl Dock { } pub fn render_placeholder(&self, cx: &WindowContext) -> AnyElement { - 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() - } - } - - fn style(&self, cx: &WindowContext) -> ContainerStyle { - let theme = &settings::get::(cx).theme; - let style = match self.position { - DockPosition::Left => theme.workspace.dock.left, - DockPosition::Bottom => theme.workspace.dock.bottom, - DockPosition::Right => theme.workspace.dock.right, - }; - style + 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() + // } } } -impl Entity for Dock { - type Event = (); -} - -impl View for Dock { - fn ui_name() -> &'static str { - "Dock" - } - - fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - if let Some(active_entry) = self.visible_entry() { - let style = self.style(cx); - ChildView::new(active_entry.panel.as_any(), cx) - .contained() - .with_style(style) - .resizable::( - self.position.to_resize_handle_side(), - active_entry.panel.size(cx), - |dock: &mut Self, size, cx| dock.resize_active_panel(size, cx), - ) - .into_any() - } else { - Empty::new().into_any() - } - } - - fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - if cx.is_self_focused() { - if let Some(active_entry) = self.visible_entry() { - cx.focus(active_entry.panel.as_any()); - } else { - cx.focus_parent(); - } - } - } -} - -impl PanelButtons { - pub fn new( - dock: ViewHandle, - workspace: WeakViewHandle, - cx: &mut ViewContext, - ) -> Self { - cx.observe(&dock, |_, _, cx| cx.notify()).detach(); - Self { dock, workspace } - } -} - -impl Entity for PanelButtons { - type Event = (); -} - -impl View for PanelButtons { - fn ui_name() -> &'static str { - "PanelButtons" - } - - fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let theme = &settings::get::(cx).theme; - let tooltip_style = theme.tooltip.clone(); - let theme = &theme.workspace.status_bar.panel_buttons; - let button_style = theme.button.clone(); - let dock = self.dock.read(cx); - let active_ix = dock.active_panel_index; - let is_open = dock.is_open; - let dock_position = dock.position; - let group_style = match dock_position { - DockPosition::Left => theme.group_left, - DockPosition::Bottom => theme.group_bottom, - DockPosition::Right => theme.group_right, - }; - let menu_corner = match dock_position { - DockPosition::Left => AnchorCorner::BottomLeft, - DockPosition::Bottom | DockPosition::Right => AnchorCorner::BottomRight, - }; - - let panels = dock - .panel_entries - .iter() - .map(|item| (item.panel.clone(), item.context_menu.clone())) - .collect::>(); - Flex::row() - .with_children(panels.into_iter().enumerate().filter_map( - |(panel_ix, (view, context_menu))| { - let icon_path = view.icon_path(cx)?; - let is_active = is_open && panel_ix == active_ix; - let (tooltip, tooltip_action) = if is_active { - ( - format!("Close {} dock", dock_position.to_label()), - Some(match dock_position { - DockPosition::Left => crate::ToggleLeftDock.boxed_clone(), - DockPosition::Bottom => crate::ToggleBottomDock.boxed_clone(), - DockPosition::Right => crate::ToggleRightDock.boxed_clone(), - }), - ) - } else { - view.icon_tooltip(cx) - }; - Some( - Stack::new() - .with_child( - MouseEventHandler::new::(panel_ix, cx, |state, cx| { - let style = button_style.in_state(is_active); - - let style = style.style_for(state); - Flex::row() - .with_child( - Svg::new(icon_path) - .with_color(style.icon_color) - .constrained() - .with_width(style.icon_size) - .aligned(), - ) - .with_children(if let Some(label) = view.icon_label(cx) { - Some( - Label::new(label, style.label.text.clone()) - .contained() - .with_style(style.label.container) - .aligned(), - ) - } else { - None - }) - .constrained() - .with_height(style.icon_size) - .contained() - .with_style(style.container) - }) - .with_cursor_style(CursorStyle::PointingHand) - .on_click(MouseButton::Left, { - let tooltip_action = - tooltip_action.as_ref().map(|action| action.boxed_clone()); - move |_, this, cx| { - if let Some(tooltip_action) = &tooltip_action { - let window = cx.window(); - let view_id = this.workspace.id(); - let tooltip_action = tooltip_action.boxed_clone(); - cx.spawn(|_, mut cx| async move { - window.dispatch_action( - view_id, - &*tooltip_action, - &mut cx, - ); - }) - .detach(); - } - } - }) - .on_click(MouseButton::Right, { - let view = view.clone(); - let menu = context_menu.clone(); - move |_, _, cx| { - const POSITIONS: [DockPosition; 3] = [ - DockPosition::Left, - DockPosition::Right, - DockPosition::Bottom, - ]; - - menu.update(cx, |menu, cx| { - let items = POSITIONS - .into_iter() - .filter(|position| { - *position != dock_position - && view.position_is_valid(*position, cx) - }) - .map(|position| { - let view = view.clone(); - ContextMenuItem::handler( - format!("Dock {}", position.to_label()), - move |cx| view.set_position(position, cx), - ) - }) - .collect(); - menu.show(Default::default(), menu_corner, items, cx); - }) - } - }) - .with_tooltip::( - panel_ix, - tooltip, - tooltip_action, - tooltip_style.clone(), - cx, - ), - ) - .with_child(ChildView::new(&context_menu, cx)), - ) - }, - )) - .contained() - .with_style(group_style) - .into_any() - } -} +// todo!() +// impl View for Dock { +// fn ui_name() -> &'static str { +// "Dock" +// } + +// fn render(&mut self, cx: &mut ViewContext) -> AnyElement { +// if let Some(active_entry) = self.visible_entry() { +// let style = self.style(cx); +// ChildView::new(active_entry.panel.as_any(), cx) +// .contained() +// .with_style(style) +// .resizable::( +// self.position.to_resize_handle_side(), +// active_entry.panel.size(cx), +// |dock: &mut Self, size, cx| dock.resize_active_panel(size, cx), +// ) +// .into_any() +// } else { +// Empty::new().into_any() +// } +// } + +// fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { +// if cx.is_self_focused() { +// if let Some(active_entry) = self.visible_entry() { +// cx.focus(active_entry.panel.as_any()); +// } else { +// cx.focus_parent(); +// } +// } +// } +// } + +// todo!() +// impl PanelButtons { +// pub fn new( +// dock: View, +// workspace: WeakViewHandle, +// cx: &mut ViewContext, +// ) -> Self { +// cx.observe(&dock, |_, _, cx| cx.notify()).detach(); +// Self { dock, workspace } +// } +// } + +// todo!() +// impl Entity for PanelButtons { +// type Event = (); +// } + +// todo!() +// impl View for PanelButtons { +// fn ui_name() -> &'static str { +// "PanelButtons" +// } + +// fn render(&mut self, cx: &mut ViewContext) -> AnyElement { +// let theme = &settings::get::(cx).theme; +// let tooltip_style = theme.tooltip.clone(); +// let theme = &theme.workspace.status_bar.panel_buttons; +// let button_style = theme.button.clone(); +// let dock = self.dock.read(cx); +// let active_ix = dock.active_panel_index; +// let is_open = dock.is_open; +// let dock_position = dock.position; +// let group_style = match dock_position { +// DockPosition::Left => theme.group_left, +// DockPosition::Bottom => theme.group_bottom, +// DockPosition::Right => theme.group_right, +// }; +// let menu_corner = match dock_position { +// DockPosition::Left => AnchorCorner::BottomLeft, +// DockPosition::Bottom | DockPosition::Right => AnchorCorner::BottomRight, +// }; + +// let panels = dock +// .panel_entries +// .iter() +// .map(|item| (item.panel.clone(), item.context_menu.clone())) +// .collect::>(); +// Flex::row() +// .with_children(panels.into_iter().enumerate().filter_map( +// |(panel_ix, (view, context_menu))| { +// let icon_path = view.icon_path(cx)?; +// let is_active = is_open && panel_ix == active_ix; +// let (tooltip, tooltip_action) = if is_active { +// ( +// format!("Close {} dock", dock_position.to_label()), +// Some(match dock_position { +// DockPosition::Left => crate::ToggleLeftDock.boxed_clone(), +// DockPosition::Bottom => crate::ToggleBottomDock.boxed_clone(), +// DockPosition::Right => crate::ToggleRightDock.boxed_clone(), +// }), +// ) +// } else { +// view.icon_tooltip(cx) +// }; +// Some( +// Stack::new() +// .with_child( +// MouseEventHandler::new::(panel_ix, cx, |state, cx| { +// let style = button_style.in_state(is_active); + +// let style = style.style_for(state); +// Flex::row() +// .with_child( +// Svg::new(icon_path) +// .with_color(style.icon_color) +// .constrained() +// .with_width(style.icon_size) +// .aligned(), +// ) +// .with_children(if let Some(label) = view.icon_label(cx) { +// Some( +// Label::new(label, style.label.text.clone()) +// .contained() +// .with_style(style.label.container) +// .aligned(), +// ) +// } else { +// None +// }) +// .constrained() +// .with_height(style.icon_size) +// .contained() +// .with_style(style.container) +// }) +// .with_cursor_style(CursorStyle::PointingHand) +// .on_click(MouseButton::Left, { +// let tooltip_action = +// tooltip_action.as_ref().map(|action| action.boxed_clone()); +// move |_, this, cx| { +// if let Some(tooltip_action) = &tooltip_action { +// let window = cx.window(); +// let view_id = this.workspace.id(); +// let tooltip_action = tooltip_action.boxed_clone(); +// cx.spawn(|_, mut cx| async move { +// window.dispatch_action( +// view_id, +// &*tooltip_action, +// &mut cx, +// ); +// }) +// .detach(); +// } +// } +// }) +// .on_click(MouseButton::Right, { +// let view = view.clone(); +// let menu = context_menu.clone(); +// move |_, _, cx| { +// const POSITIONS: [DockPosition; 3] = [ +// DockPosition::Left, +// DockPosition::Right, +// DockPosition::Bottom, +// ]; + +// menu.update(cx, |menu, cx| { +// let items = POSITIONS +// .into_iter() +// .filter(|position| { +// *position != dock_position +// && view.position_is_valid(*position, cx) +// }) +// .map(|position| { +// let view = view.clone(); +// ContextMenuItem::handler( +// format!("Dock {}", position.to_label()), +// move |cx| view.set_position(position, cx), +// ) +// }) +// .collect(); +// menu.show(Default::default(), menu_corner, items, cx); +// }) +// } +// }) +// .with_tooltip::( +// panel_ix, +// tooltip, +// tooltip_action, +// tooltip_style.clone(), +// cx, +// ), +// ) +// .with_child(ChildView::new(&context_menu, cx)), +// ) +// }, +// )) +// .contained() +// .with_style(group_style) +// .into_any() +// } +// } impl StatusItemView for PanelButtons { fn set_active_pane_item( @@ -616,7 +605,7 @@ impl StatusItemView for PanelButtons { #[cfg(any(test, feature = "test-support"))] pub mod test { use super::*; - use gpui2::{ViewContext, WindowContext}; + use gpui2::{div, Div, ViewContext, WindowContext}; #[derive(Debug)] pub enum TestPanelEvent { @@ -648,31 +637,16 @@ pub mod test { } } - impl Entity for TestPanel { - type Event = TestPanelEvent; - } - - impl View for TestPanel { - fn ui_name() -> &'static str { - "TestPanel" - } - - fn render(&mut self, _: &mut ViewContext<'_, '_, Self>) -> AnyElement { - Empty::new().into_any() - } - - fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { - self.has_focus = true; - cx.emit(TestPanelEvent::Focus); - } + impl Render for TestPanel { + type Element = Div; - fn focus_out(&mut self, _: AnyViewHandle, _: &mut ViewContext) { - self.has_focus = false; + fn render(&mut self, cx: &mut ViewContext) -> Self::Element { + div() } } impl Panel for TestPanel { - fn position(&self, _: &gpui::WindowContext) -> super::DockPosition { + fn position(&self, _: &gpui2::WindowContext) -> super::DockPosition { self.position } diff --git a/crates/workspace2/src/status_bar.rs b/crates/workspace2/src/status_bar.rs index b62dae2114084460f4c2a9a49aa5054073fba7c4..b68b366c7cae59c8cb4430f468bc871f28dad119 100644 --- a/crates/workspace2/src/status_bar.rs +++ b/crates/workspace2/src/status_bar.rs @@ -1,18 +1,8 @@ -use std::ops::Range; - use crate::{ItemHandle, Pane}; -use gpui::{ - elements::*, - geometry::{ - rect::RectF, - vector::{vec2f, Vector2F}, - }, - json::{json, ToJson}, - AnyElement, AnyViewHandle, Entity, SizeConstraint, Subscription, View, ViewContext, ViewHandle, - WindowContext, -}; +use gpui2::{AnyView, Render, Subscription, View, ViewContext, WindowContext}; +use std::ops::Range; -pub trait StatusItemView: View { +pub trait StatusItemView: Render { fn set_active_pane_item( &mut self, active_pane_item: Option<&dyn crate::ItemHandle>, @@ -21,7 +11,7 @@ pub trait StatusItemView: View { } trait StatusItemViewHandle { - fn as_any(&self) -> &AnyViewHandle; + fn to_any(&self) -> AnyView; fn set_active_pane_item( &self, active_pane_item: Option<&dyn ItemHandle>, @@ -33,50 +23,47 @@ trait StatusItemViewHandle { pub struct StatusBar { left_items: Vec>, right_items: Vec>, - active_pane: ViewHandle, + active_pane: View, _observe_active_pane: Subscription, } -impl Entity for StatusBar { - type Event = (); -} - -impl View for StatusBar { - fn ui_name() -> &'static str { - "StatusBar" - } - - fn render(&mut self, cx: &mut ViewContext) -> AnyElement { - let theme = &theme::current(cx).workspace.status_bar; - - StatusBarElement { - left: Flex::row() - .with_children(self.left_items.iter().map(|i| { - ChildView::new(i.as_any(), cx) - .aligned() - .contained() - .with_margin_right(theme.item_spacing) - })) - .into_any(), - right: Flex::row() - .with_children(self.right_items.iter().rev().map(|i| { - ChildView::new(i.as_any(), cx) - .aligned() - .contained() - .with_margin_left(theme.item_spacing) - })) - .into_any(), - } - .contained() - .with_style(theme.container) - .constrained() - .with_height(theme.height) - .into_any() - } -} +// todo!() +// impl View for StatusBar { +// fn ui_name() -> &'static str { +// "StatusBar" +// } + +// fn render(&mut self, cx: &mut ViewContext) -> AnyElement { +// let theme = &theme::current(cx).workspace.status_bar; + +// StatusBarElement { +// left: Flex::row() +// .with_children(self.left_items.iter().map(|i| { +// ChildView::new(i.as_any(), cx) +// .aligned() +// .contained() +// .with_margin_right(theme.item_spacing) +// })) +// .into_any(), +// right: Flex::row() +// .with_children(self.right_items.iter().rev().map(|i| { +// ChildView::new(i.as_any(), cx) +// .aligned() +// .contained() +// .with_margin_left(theme.item_spacing) +// })) +// .into_any(), +// } +// .contained() +// .with_style(theme.container) +// .constrained() +// .with_height(theme.height) +// .into_any() +// } +// } impl StatusBar { - pub fn new(active_pane: &ViewHandle, cx: &mut ViewContext) -> Self { + pub fn new(active_pane: &View, cx: &mut ViewContext) -> Self { let mut this = Self { left_items: Default::default(), right_items: Default::default(), @@ -88,7 +75,7 @@ impl StatusBar { this } - pub fn add_left_item(&mut self, item: ViewHandle, cx: &mut ViewContext) + pub fn add_left_item(&mut self, item: View, cx: &mut ViewContext) where T: 'static + StatusItemView, { @@ -96,7 +83,7 @@ impl StatusBar { cx.notify(); } - pub fn item_of_type(&self) -> Option> { + pub fn item_of_type(&self) -> Option> { self.left_items .iter() .chain(self.right_items.iter()) @@ -146,7 +133,7 @@ impl StatusBar { cx.notify(); } - pub fn add_right_item(&mut self, item: ViewHandle, cx: &mut ViewContext) + pub fn add_right_item(&mut self, item: View, cx: &mut ViewContext) where T: 'static + StatusItemView, { diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 723a922bc65d467c3f286984ebc4ca2b25dfdfb2..3e1578f77985186ccbb6962a5b9d1a8977416a2b 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -1,4 +1,4 @@ -// pub mod dock; +pub mod dock; pub mod item; // pub mod notifications; pub mod pane; @@ -6,7 +6,7 @@ pub mod pane_group; mod persistence; pub mod searchable; // pub mod shared_screen; -// mod status_bar; +mod status_bar; mod toolbar; mod workspace_settings; @@ -37,7 +37,7 @@ pub use toolbar::{ToolbarItemLocation, ToolbarItemView}; use util::ResultExt; use crate::persistence::model::{ - DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup, + DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup, SerializedWorkspace, }; // lazy_static! {