From 0a9fb3978befe19d00a1ad99b36b9f8e20a2e55a Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Wed, 15 Nov 2023 21:01:00 -0700 Subject: [PATCH] Enable panel switching --- crates/collab_ui2/src/collab_panel.rs | 33 ++++--- crates/collab_ui2/src/collab_titlebar_item.rs | 14 ++- crates/editor2/src/editor.rs | 4 +- crates/editor2/src/element.rs | 10 ++- crates/gpui2/src/elements/div.rs | 5 +- crates/gpui2/src/window.rs | 7 +- crates/project_panel2/src/project_panel.rs | 15 +++- crates/ui2/src/components/button.rs | 2 +- crates/ui2/src/components/icon.rs | 2 + crates/ui2/src/components/icon_button.rs | 36 ++++---- crates/ui2/src/components/tooltip.rs | 44 +++++++++- crates/workspace2/src/dock.rs | 65 +++++++++----- crates/workspace2/src/pane.rs | 4 +- crates/workspace2/src/status_bar.rs | 7 +- crates/workspace2/src/workspace2.rs | 86 +++++++++---------- 15 files changed, 203 insertions(+), 131 deletions(-) diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 51d4b436e2..36fd8bd638 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -158,8 +158,9 @@ actions!( use std::sync::Arc; use gpui::{ - actions, div, AppContext, AsyncWindowContext, Div, EventEmitter, FocusHandle, ParentComponent, - Render, Task, View, ViewContext, VisualContext, WeakView, + actions, div, AppContext, AsyncWindowContext, Div, EventEmitter, FocusHandle, Focusable, + InteractiveComponent, ParentComponent, Render, Task, View, ViewContext, VisualContext, + WeakView, }; use project::Fs; use settings::Settings; @@ -171,6 +172,12 @@ use workspace::{ use crate::CollaborationPanelSettings; pub fn init(cx: &mut AppContext) { + cx.observe_new_views(|workspace: &mut Workspace, _| { + workspace.register_action(|workspace, _: &ToggleFocus, cx| { + workspace.toggle_panel_focus::(cx); + }); + }) + .detach(); // contact_finder::init(cx); // channel_modal::init(cx); // channel_view::init(cx); @@ -3293,10 +3300,13 @@ impl CollabPanel { // } impl Render for CollabPanel { - type Element = Div; + type Element = Focusable>; fn render(&mut self, _cx: &mut ViewContext) -> Self::Element { - div().child("COLLAB PANEL") + div() + .key_context("CollabPanel") + .track_focus(&self.focus_handle) + .child("COLLAB PANEL") } } @@ -3430,17 +3440,14 @@ impl Panel for CollabPanel { cx.notify(); } - fn icon_path(&self, cx: &gpui::WindowContext) -> Option<&'static str> { + fn icon(&self, cx: &gpui::WindowContext) -> Option { CollaborationPanelSettings::get_global(cx) .button - .then(|| "icons/user_group_16.svg") + .then(|| ui::Icon::Collab) } - fn icon_tooltip(&self) -> (String, Option>) { - ( - "Collaboration Panel".to_string(), - Some(Box::new(ToggleFocus)), - ) + fn toggle_action(&self) -> Box { + Box::new(ToggleFocus) } fn has_focus(&self, cx: &gpui::WindowContext) -> bool { @@ -3448,10 +3455,10 @@ impl Panel for CollabPanel { } fn persistent_name(&self) -> &'static str { - "Collab Panel" + "Collaboration Panel" } - fn focus_handle(&self, cx: &ui::prelude::WindowContext) -> gpui::FocusHandle { + fn focus_handle(&self, _cx: &ui::prelude::WindowContext) -> gpui::FocusHandle { self.focus_handle.clone() } } diff --git a/crates/collab_ui2/src/collab_titlebar_item.rs b/crates/collab_ui2/src/collab_titlebar_item.rs index c1b7928209..c9d16c7a5d 100644 --- a/crates/collab_ui2/src/collab_titlebar_item.rs +++ b/crates/collab_ui2/src/collab_titlebar_item.rs @@ -37,7 +37,7 @@ use gpui::{ }; use project::Project; use theme::ActiveTheme; -use ui::{h_stack, Button, ButtonVariant, KeyBinding, Label, TextColor, TextTooltip}; +use ui::{h_stack, Button, ButtonVariant, KeyBinding, Label, TextColor, Tooltip}; use workspace::Workspace; // const MAX_PROJECT_NAME_LENGTH: usize = 40; @@ -111,18 +111,14 @@ impl Render for CollabTitlebarItem { .variant(ButtonVariant::Ghost) .color(Some(TextColor::Player(0))), ) - .tooltip(move |_, cx| { - cx.build_view(|_| TextTooltip::new("Toggle following")) - }), + .tooltip(move |_, cx| Tooltip::text("Toggle following", cx)), ) // TODO - Add project menu .child( div() .id("titlebar_project_menu_button") .child(Button::new("project_name").variant(ButtonVariant::Ghost)) - .tooltip(move |_, cx| { - cx.build_view(|_| TextTooltip::new("Recent Projects")) - }), + .tooltip(move |_, cx| Tooltip::text("Recent Projects", cx)), ) // TODO - Add git menu .child( @@ -137,9 +133,8 @@ impl Render for CollabTitlebarItem { // todo!() Replace with real action. #[gpui::action] struct NoAction {} - cx.build_view(|_| { - TextTooltip::new("Recent Branches") + Tooltip::new("Recent Branches") .key_binding(KeyBinding::new(gpui::KeyBinding::new( "cmd-b", NoAction {}, @@ -147,6 +142,7 @@ impl Render for CollabTitlebarItem { ))) .meta("Only local branches shown") }) + .into() }), ), ) // self.titlebar_item diff --git a/crates/editor2/src/editor.rs b/crates/editor2/src/editor.rs index af7da8e837..ba02d567fa 100644 --- a/crates/editor2/src/editor.rs +++ b/crates/editor2/src/editor.rs @@ -97,7 +97,7 @@ use text::{OffsetUtf16, Rope}; use theme::{ ActiveTheme, DiagnosticStyle, PlayerColor, SyntaxTheme, Theme, ThemeColors, ThemeSettings, }; -use ui::{v_stack, HighlightedLabel, IconButton, StyledExt, TextTooltip}; +use ui::{v_stack, HighlightedLabel, IconButton, StyledExt, Tooltip}; use util::{post_inc, RangeExt, ResultExt, TryFutureExt}; use workspace::{ item::{ItemEvent, ItemHandle}, @@ -9985,7 +9985,7 @@ pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> Rend .on_click(move |_, _, cx| { cx.write_to_clipboard(ClipboardItem::new(message.clone())); }) - .tooltip(|_, cx| cx.build_view(|cx| TextTooltip::new("Copy diagnostic message"))) + .tooltip(|_, cx| Tooltip::text("Copy diagnostic message", cx)) .render() }) } diff --git a/crates/editor2/src/element.rs b/crates/editor2/src/element.rs index 4d9a516f2b..00147f964f 100644 --- a/crates/editor2/src/element.rs +++ b/crates/editor2/src/element.rs @@ -12,8 +12,8 @@ use crate::{ }, scroll::scroll_amount::ScrollAmount, CursorShape, DisplayPoint, Editor, EditorMode, EditorSettings, EditorSnapshot, EditorStyle, - HalfPageDown, HalfPageUp, LineDown, LineUp, MoveDown, PageDown, PageUp, Point, SelectPhase, - Selection, SoftWrap, ToPoint, MAX_LINE_LEN, + HalfPageDown, HalfPageUp, LineDown, LineUp, MoveDown, OpenExcerpts, PageDown, PageUp, Point, + SelectPhase, Selection, SoftWrap, ToPoint, MAX_LINE_LEN, }; use anyhow::Result; use collections::{BTreeMap, HashMap}; @@ -45,7 +45,7 @@ use std::{ }; use sum_tree::Bias; use theme::{ActiveTheme, PlayerColor}; -use ui::{h_stack, IconButton}; +use ui::{h_stack, IconButton, Tooltip}; use util::ResultExt; use workspace::item::Item; @@ -2036,7 +2036,9 @@ impl EditorElement { .on_click(move |editor: &mut Editor, cx| { editor.jump(jump_path.clone(), jump_position, jump_anchor, cx); }) - .tooltip("Jump to Buffer") // todo!(pass an action as well to show key binding) + .tooltip(move |_, cx| { + Tooltip::for_action("Jump to Buffer", &OpenExcerpts, cx) + }) }); let element = if *starts_new_buffer { diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index 1f9b2b020a..fd1bf8e146 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -408,13 +408,12 @@ pub trait StatefulInteractiveComponent>: InteractiveCo self } - fn tooltip( + fn tooltip( mut self, - build_tooltip: impl Fn(&mut V, &mut ViewContext) -> View + 'static, + build_tooltip: impl Fn(&mut V, &mut ViewContext) -> AnyView + 'static, ) -> Self where Self: Sized, - W: 'static + Render, { debug_assert!( self.interactivity().tooltip_builder.is_none(), diff --git a/crates/gpui2/src/window.rs b/crates/gpui2/src/window.rs index 0563c107c0..40391ba797 100644 --- a/crates/gpui2/src/window.rs +++ b/crates/gpui2/src/window.rs @@ -1092,8 +1092,11 @@ impl<'a> WindowContext<'a> { } else if let Some(active_tooltip) = self.app.active_tooltip.take() { self.with_z_index(1, |cx| { cx.with_element_offset(active_tooltip.cursor_offset, |cx| { - let available_space = - size(AvailableSpace::MinContent, AvailableSpace::MinContent); + let available_space = Size { + width: cx.window.viewport_size.width - active_tooltip.cursor_offset.x, + height: cx.window.viewport_size.height - active_tooltip.cursor_offset.y, + } + .map(Into::into); active_tooltip.view.draw(available_space, cx); }); }); diff --git a/crates/project_panel2/src/project_panel.rs b/crates/project_panel2/src/project_panel.rs index 79a0f344ae..03d8f54353 100644 --- a/crates/project_panel2/src/project_panel.rs +++ b/crates/project_panel2/src/project_panel.rs @@ -130,6 +130,13 @@ pub fn init_settings(cx: &mut AppContext) { pub fn init(assets: impl AssetSource, cx: &mut AppContext) { init_settings(cx); file_associations::init(assets, cx); + + cx.observe_new_views(|workspace: &mut Workspace, _| { + workspace.register_action(|workspace, _: &ToggleFocus, cx| { + workspace.toggle_panel_focus::(cx); + }); + }) + .detach(); } #[derive(Debug)] @@ -1516,12 +1523,12 @@ impl workspace::dock::Panel for ProjectPanel { cx.notify(); } - fn icon_path(&self, _: &WindowContext) -> Option<&'static str> { - Some("icons/project.svg") + fn icon(&self, _: &WindowContext) -> Option { + Some(ui::Icon::FileTree) } - fn icon_tooltip(&self) -> (String, Option>) { - ("Project Panel".into(), Some(Box::new(ToggleFocus))) + fn toggle_action(&self) -> Box { + Box::new(ToggleFocus) } // fn should_change_position_on_event(event: &Self::Event) -> bool { diff --git a/crates/ui2/src/components/button.rs b/crates/ui2/src/components/button.rs index 8eff92f11a..397ce4f4c4 100644 --- a/crates/ui2/src/components/button.rs +++ b/crates/ui2/src/components/button.rs @@ -61,7 +61,7 @@ impl ButtonVariant { } } -pub type ClickHandler = Arc) + Send + Sync>; +pub type ClickHandler = Arc)>; struct ButtonHandlers { click: Option>, diff --git a/crates/ui2/src/components/icon.rs b/crates/ui2/src/components/icon.rs index a0ef496d18..61aa234978 100644 --- a/crates/ui2/src/components/icon.rs +++ b/crates/ui2/src/components/icon.rs @@ -25,6 +25,7 @@ pub enum Icon { ChevronRight, ChevronUp, Close, + Collab, Dash, Exit, ExclamationTriangle, @@ -83,6 +84,7 @@ impl Icon { Icon::ChevronRight => "icons/chevron_right.svg", Icon::ChevronUp => "icons/chevron_up.svg", Icon::Close => "icons/x.svg", + Icon::Collab => "icons/user_group_16.svg", Icon::Dash => "icons/dash.svg", Icon::Exit => "icons/exit.svg", Icon::ExclamationTriangle => "icons/warning.svg", diff --git a/crates/ui2/src/components/icon_button.rs b/crates/ui2/src/components/icon_button.rs index 7afaa12243..4408c51f62 100644 --- a/crates/ui2/src/components/icon_button.rs +++ b/crates/ui2/src/components/icon_button.rs @@ -1,5 +1,5 @@ -use crate::{h_stack, prelude::*, ClickHandler, Icon, IconElement, TextTooltip}; -use gpui::{prelude::*, MouseButton, VisualContext}; +use crate::{h_stack, prelude::*, ClickHandler, Icon, IconElement}; +use gpui::{prelude::*, AnyView, MouseButton}; use std::sync::Arc; struct IconButtonHandlers { @@ -19,7 +19,7 @@ pub struct IconButton { color: TextColor, variant: ButtonVariant, state: InteractionState, - tooltip: Option, + tooltip: Option) -> AnyView + 'static>>, handlers: IconButtonHandlers, } @@ -56,22 +56,23 @@ impl IconButton { self } - pub fn tooltip(mut self, tooltip: impl Into) -> Self { - self.tooltip = Some(tooltip.into()); + pub fn tooltip( + mut self, + tooltip: impl Fn(&mut V, &mut ViewContext) -> AnyView + 'static, + ) -> Self { + self.tooltip = Some(Box::new(tooltip)); self } - pub fn on_click( - mut self, - handler: impl 'static + Fn(&mut V, &mut ViewContext) + Send + Sync, - ) -> Self { + pub fn on_click(mut self, handler: impl 'static + Fn(&mut V, &mut ViewContext)) -> Self { self.handlers.click = Some(Arc::new(handler)); self } - fn render(self, _view: &mut V, cx: &mut ViewContext) -> impl Component { + fn render(mut self, _view: &mut V, cx: &mut ViewContext) -> impl Component { let icon_color = match (self.state, self.color) { (InteractionState::Disabled, _) => TextColor::Disabled, + (InteractionState::Active, _) => TextColor::Error, _ => self.color, }; @@ -99,15 +100,16 @@ impl IconButton { .child(IconElement::new(self.icon).color(icon_color)); if let Some(click_handler) = self.handlers.click.clone() { - button = button.on_mouse_down(MouseButton::Left, move |state, event, cx| { - cx.stop_propagation(); - click_handler(state, cx); - }); + button = button + .on_mouse_down(MouseButton::Left, move |state, event, cx| { + cx.stop_propagation(); + click_handler(state, cx); + }) + .cursor_pointer(); } - if let Some(tooltip) = self.tooltip.clone() { - button = - button.tooltip(move |_, cx| cx.build_view(|cx| TextTooltip::new(tooltip.clone()))); + if let Some(tooltip) = self.tooltip.take() { + button = button.tooltip(move |view: &mut V, cx| (tooltip)(view, cx)) } button diff --git a/crates/ui2/src/components/tooltip.rs b/crates/ui2/src/components/tooltip.rs index 8463ed7ba4..c4366234c5 100644 --- a/crates/ui2/src/components/tooltip.rs +++ b/crates/ui2/src/components/tooltip.rs @@ -1,17 +1,53 @@ -use gpui::{Div, Render}; +use gpui::{Action, AnyView, Div, Render, VisualContext}; use settings2::Settings; use theme2::{ActiveTheme, ThemeSettings}; use crate::prelude::*; use crate::{h_stack, v_stack, KeyBinding, Label, LabelSize, StyledExt, TextColor}; -pub struct TextTooltip { +pub struct Tooltip { title: SharedString, meta: Option, key_binding: Option, } -impl TextTooltip { +impl Tooltip { + pub fn text(title: impl Into, cx: &mut WindowContext) -> AnyView { + cx.build_view(|cx| Self { + title: title.into(), + meta: None, + key_binding: None, + }) + .into() + } + + pub fn for_action( + title: impl Into, + action: &dyn Action, + cx: &mut WindowContext, + ) -> AnyView { + cx.build_view(|cx| Self { + title: title.into(), + meta: None, + key_binding: KeyBinding::for_action(action, cx), + }) + .into() + } + + pub fn with_meta( + title: impl Into, + action: Option<&dyn Action>, + meta: impl Into, + cx: &mut WindowContext, + ) -> AnyView { + cx.build_view(|cx| Self { + title: title.into(), + meta: Some(meta.into()), + key_binding: action.and_then(|action| KeyBinding::for_action(action, cx)), + }) + .into() + } + pub fn new(title: impl Into) -> Self { Self { title: title.into(), @@ -31,7 +67,7 @@ impl TextTooltip { } } -impl Render for TextTooltip { +impl Render for Tooltip { type Element = Div; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { diff --git a/crates/workspace2/src/dock.rs b/crates/workspace2/src/dock.rs index 455148391b..0ebf0cd516 100644 --- a/crates/workspace2/src/dock.rs +++ b/crates/workspace2/src/dock.rs @@ -7,6 +7,7 @@ use gpui::{ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::sync::Arc; +use ui::{h_stack, IconButton, InteractionState, Tooltip}; pub enum PanelEvent { ChangePosition, @@ -24,8 +25,8 @@ pub trait Panel: Render + EventEmitter { fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext); fn size(&self, cx: &WindowContext) -> f32; fn set_size(&mut self, size: Option, cx: &mut ViewContext); - fn icon_path(&self, cx: &WindowContext) -> Option<&'static str>; - fn icon_tooltip(&self) -> (String, Option>); + fn icon(&self, cx: &WindowContext) -> Option; + fn toggle_action(&self) -> Box; fn icon_label(&self, _: &WindowContext) -> Option { None } @@ -49,8 +50,8 @@ pub trait PanelHandle: Send + Sync { fn set_active(&self, active: bool, cx: &mut WindowContext); fn size(&self, cx: &WindowContext) -> f32; fn set_size(&self, size: Option, cx: &mut WindowContext); - fn icon_path(&self, cx: &WindowContext) -> Option<&'static str>; - fn icon_tooltip(&self, cx: &WindowContext) -> (String, Option>); + fn icon(&self, cx: &WindowContext) -> Option; + fn toggle_action(&self, cx: &WindowContext) -> Box; fn icon_label(&self, cx: &WindowContext) -> Option; fn has_focus(&self, cx: &WindowContext) -> bool; fn focus_handle(&self, cx: &WindowContext) -> FocusHandle; @@ -101,12 +102,12 @@ where self.update(cx, |this, cx| this.set_size(size, cx)) } - fn icon_path(&self, cx: &WindowContext) -> Option<&'static str> { - self.read(cx).icon_path(cx) + fn icon(&self, cx: &WindowContext) -> Option { + self.read(cx).icon(cx) } - fn icon_tooltip(&self, cx: &WindowContext) -> (String, Option>) { - self.read(cx).icon_tooltip() + fn toggle_action(&self, cx: &WindowContext) -> Box { + self.read(cx).toggle_action() } fn icon_label(&self, cx: &WindowContext) -> Option { @@ -214,11 +215,11 @@ impl Dock { // .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.to_any().downcast::().is_ok()) + } pub fn panel_index_for_ui_name(&self, _ui_name: &str, _cx: &AppContext) -> Option { todo!() @@ -644,11 +645,28 @@ impl Render for PanelButtons { fn render(&mut self, cx: &mut ViewContext) -> Self::Element { // todo!() let dock = self.dock.read(cx); - div().children( - dock.panel_entries - .iter() - .map(|panel| panel.panel.persistent_name(cx)), - ) + let active_index = dock.active_panel_index; + let is_open = dock.is_open; + + let buttons = dock + .panel_entries + .iter() + .enumerate() + .filter_map(|(i, panel)| { + let icon = panel.panel.icon(cx)?; + let name = panel.panel.persistent_name(cx); + let action = panel.panel.toggle_action(cx); + let action2 = action.boxed_clone(); + + let mut button = IconButton::new(panel.panel.persistent_name(cx), icon) + .when(i == active_index, |el| el.state(InteractionState::Active)) + .on_click(move |this, cx| cx.dispatch_action(action.boxed_clone())) + .tooltip(move |_, cx| Tooltip::for_action(name, &*action2, cx)); + + Some(button) + }); + + h_stack().children(buttons) } } @@ -665,7 +683,7 @@ impl StatusItemView for PanelButtons { #[cfg(any(test, feature = "test-support"))] pub mod test { use super::*; - use gpui::{div, Div, ViewContext, WindowContext}; + use gpui::{actions, div, Div, ViewContext, WindowContext}; pub struct TestPanel { pub position: DockPosition, @@ -674,6 +692,7 @@ pub mod test { pub has_focus: bool, pub size: f32, } + actions!(ToggleTestPanel); impl EventEmitter for TestPanel {} @@ -723,12 +742,12 @@ pub mod test { self.size = size.unwrap_or(300.); } - fn icon_path(&self, _: &WindowContext) -> Option<&'static str> { - Some("icons/test_panel.svg") + fn icon(&self, _: &WindowContext) -> Option { + None } - fn icon_tooltip(&self) -> (String, Option>) { - ("Test Panel".into(), None) + fn toggle_action(&self) -> Box { + ToggleTestPanel.boxed_clone() } fn is_zoomed(&self, _: &WindowContext) -> bool { diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 668ce2f207..e55d450961 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -25,7 +25,7 @@ use std::{ }, }; use ui::v_stack; -use ui::{prelude::*, Icon, IconButton, IconElement, TextColor, TextTooltip}; +use ui::{prelude::*, Icon, IconButton, IconElement, TextColor, Tooltip}; use util::truncate_and_remove_front; #[derive(PartialEq, Clone, Copy, Deserialize, Debug)] @@ -1396,7 +1396,7 @@ impl Pane { .id(item.id()) .cursor_pointer() .when_some(item.tab_tooltip_text(cx), |div, text| { - div.tooltip(move |_, cx| cx.build_view(|cx| TextTooltip::new(text.clone()))) + div.tooltip(move |_, cx| cx.build_view(|cx| Tooltip::new(text.clone())).into()) }) // .on_drag(move |pane, cx| pane.render_tab(ix, item.boxed_clone(), detail, cx)) // .drag_over::(|d| d.bg(cx.theme().colors().element_drop_target)) diff --git a/crates/workspace2/src/status_bar.rs b/crates/workspace2/src/status_bar.rs index 5dccac243f..38356dd3d1 100644 --- a/crates/workspace2/src/status_bar.rs +++ b/crates/workspace2/src/status_bar.rs @@ -6,6 +6,7 @@ use gpui::{ WindowContext, }; use theme2::ActiveTheme; +use ui::h_stack; use util::ResultExt; pub trait StatusItemView: Render { @@ -53,16 +54,14 @@ impl Render for StatusBar { impl StatusBar { fn render_left_tools(&self, cx: &mut ViewContext) -> impl Component { - div() - .flex() + h_stack() .items_center() .gap_1() .children(self.left_items.iter().map(|item| item.to_any())) } fn render_right_tools(&self, cx: &mut ViewContext) -> impl Component { - div() - .flex() + h_stack() .items_center() .gap_2() .children(self.right_items.iter().map(|item| item.to_any())) diff --git a/crates/workspace2/src/workspace2.rs b/crates/workspace2/src/workspace2.rs index 5213a1f83d..22fe342bfc 100644 --- a/crates/workspace2/src/workspace2.rs +++ b/crates/workspace2/src/workspace2.rs @@ -29,7 +29,7 @@ use client2::{ Client, TypedEnvelope, UserStore, }; use collections::{hash_map, HashMap, HashSet}; -use dock::{Dock, DockPosition, Panel, PanelButtons, PanelHandle as _}; +use dock::{Dock, DockPosition, Panel, PanelButtons, PanelHandle}; use futures::{ channel::{mpsc, oneshot}, future::try_join_all, @@ -1599,52 +1599,52 @@ impl Workspace { // .downcast() // } - // /// Focus the panel of the given type if it isn't already focused. If it is - // /// already focused, then transfer focus back to the workspace center. - // pub fn toggle_panel_focus(&mut self, cx: &mut ViewContext) { - // self.focus_or_unfocus_panel::(cx, |panel, cx| !panel.has_focus(cx)); - // } + /// Focus the panel of the given type if it isn't already focused. If it is + /// already focused, then transfer focus back to the workspace center. + pub fn toggle_panel_focus(&mut self, cx: &mut ViewContext) { + self.focus_or_unfocus_panel::(cx, |panel, cx| !panel.has_focus(cx)); + } - // /// Focus or unfocus the given panel type, depending on the given callback. - // fn focus_or_unfocus_panel( - // &mut self, - // cx: &mut ViewContext, - // should_focus: impl Fn(&dyn PanelHandle, &mut ViewContext) -> bool, - // ) -> Option> { - // for dock in [&self.left_dock, &self.bottom_dock, &self.right_dock] { - // if let Some(panel_index) = dock.read(cx).panel_index_for_type::() { - // let mut focus_center = false; - // let mut reveal_dock = false; - // let panel = dock.update(cx, |dock, cx| { - // dock.activate_panel(panel_index, cx); + /// Focus or unfocus the given panel type, depending on the given callback. + fn focus_or_unfocus_panel( + &mut self, + cx: &mut ViewContext, + should_focus: impl Fn(&dyn PanelHandle, &mut ViewContext) -> bool, + ) -> Option> { + for dock in [&self.left_dock, &self.bottom_dock, &self.right_dock] { + if let Some(panel_index) = dock.read(cx).panel_index_for_type::() { + let mut focus_center = false; + let mut reveal_dock = false; + let panel = dock.update(cx, |dock, cx| { + dock.activate_panel(panel_index, cx); - // let panel = dock.active_panel().cloned(); - // if let Some(panel) = panel.as_ref() { - // if should_focus(&**panel, cx) { - // dock.set_open(true, cx); - // cx.focus(panel.as_any()); - // reveal_dock = true; - // } else { - // // if panel.is_zoomed(cx) { - // // dock.set_open(false, cx); - // // } - // focus_center = true; - // } - // } - // panel - // }); + let panel = dock.active_panel().cloned(); + if let Some(panel) = panel.as_ref() { + if should_focus(&**panel, cx) { + dock.set_open(true, cx); + panel.focus_handle(cx).focus(cx); + reveal_dock = true; + } else { + // if panel.is_zoomed(cx) { + // dock.set_open(false, cx); + // } + focus_center = true; + } + } + panel + }); - // if focus_center { - // cx.focus_self(); - // } + if focus_center { + self.active_pane.update(cx, |pane, cx| pane.focus(cx)) + } - // self.serialize_workspace(cx); - // cx.notify(); - // return panel; - // } - // } - // None - // } + self.serialize_workspace(cx); + cx.notify(); + return panel; + } + } + None + } // pub fn panel(&self, cx: &WindowContext) -> Option> { // for dock in [&self.left_dock, &self.bottom_dock, &self.right_dock] {