mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-05 10:20:51 +00:00
Show a panel/pane as zoomed only if it's the active item in workspace
This commit is contained in:
parent
f87ae6032e
commit
981129ef8e
7 changed files with 195 additions and 109 deletions
|
@ -4224,7 +4224,7 @@ impl<T> Hash for WeakViewHandle<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||||
pub struct AnyWeakViewHandle {
|
pub struct AnyWeakViewHandle {
|
||||||
window_id: usize,
|
window_id: usize,
|
||||||
view_id: usize,
|
view_id: usize,
|
||||||
|
|
|
@ -13,7 +13,7 @@ use gpui::{
|
||||||
keymap_matcher::KeymapContext,
|
keymap_matcher::KeymapContext,
|
||||||
platform::{CursorStyle, MouseButton, PromptLevel},
|
platform::{CursorStyle, MouseButton, PromptLevel},
|
||||||
AnyElement, AppContext, ClipboardItem, Element, Entity, ModelHandle, Task, View, ViewContext,
|
AnyElement, AppContext, ClipboardItem, Element, Entity, ModelHandle, Task, View, ViewContext,
|
||||||
ViewHandle, WeakViewHandle,
|
ViewHandle, WeakViewHandle, WindowContext,
|
||||||
};
|
};
|
||||||
use menu::{Confirm, SelectNext, SelectPrev};
|
use menu::{Confirm, SelectNext, SelectPrev};
|
||||||
use project::{Entry, EntryKind, Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId};
|
use project::{Entry, EntryKind, Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId};
|
||||||
|
@ -48,6 +48,7 @@ pub struct ProjectPanel {
|
||||||
context_menu: ViewHandle<ContextMenu>,
|
context_menu: ViewHandle<ContextMenu>,
|
||||||
dragged_entry_destination: Option<Arc<Path>>,
|
dragged_entry_destination: Option<Arc<Path>>,
|
||||||
workspace: WeakViewHandle<Workspace>,
|
workspace: WeakViewHandle<Workspace>,
|
||||||
|
has_focus: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
|
@ -139,6 +140,7 @@ pub enum Event {
|
||||||
focus_opened_item: bool,
|
focus_opened_item: bool,
|
||||||
},
|
},
|
||||||
DockPositionChanged,
|
DockPositionChanged,
|
||||||
|
Focus,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProjectPanel {
|
impl ProjectPanel {
|
||||||
|
@ -214,6 +216,7 @@ impl ProjectPanel {
|
||||||
context_menu: cx.add_view(|cx| ContextMenu::new(view_id, cx)),
|
context_menu: cx.add_view(|cx| ContextMenu::new(view_id, cx)),
|
||||||
dragged_entry_destination: None,
|
dragged_entry_destination: None,
|
||||||
workspace: workspace.weak_handle(),
|
workspace: workspace.weak_handle(),
|
||||||
|
has_focus: false,
|
||||||
};
|
};
|
||||||
this.update_visible_entries(None, cx);
|
this.update_visible_entries(None, cx);
|
||||||
|
|
||||||
|
@ -259,7 +262,7 @@ impl ProjectPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::DockPositionChanged => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
@ -1338,6 +1341,17 @@ impl View for ProjectPanel {
|
||||||
Self::reset_to_default_keymap_context(keymap);
|
Self::reset_to_default_keymap_context(keymap);
|
||||||
keymap.add_identifier("menu");
|
keymap.add_identifier("menu");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
|
if !self.has_focus {
|
||||||
|
self.has_focus = true;
|
||||||
|
cx.emit(Event::Focus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn focus_out(&mut self, _: gpui::AnyViewHandle, _: &mut ViewContext<Self>) {
|
||||||
|
self.has_focus = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entity for ProjectPanel {
|
impl Entity for ProjectPanel {
|
||||||
|
@ -1345,7 +1359,7 @@ impl Entity for ProjectPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl workspace::dock::Panel for ProjectPanel {
|
impl workspace::dock::Panel for ProjectPanel {
|
||||||
fn position(&self, cx: &gpui::WindowContext) -> DockPosition {
|
fn position(&self, cx: &WindowContext) -> DockPosition {
|
||||||
let settings = cx.global::<Settings>();
|
let settings = cx.global::<Settings>();
|
||||||
match settings.project_panel.dock {
|
match settings.project_panel.dock {
|
||||||
settings::ProjectPanelDockPosition::Left => DockPosition::Left,
|
settings::ProjectPanelDockPosition::Left => DockPosition::Left,
|
||||||
|
@ -1369,7 +1383,7 @@ impl workspace::dock::Panel for ProjectPanel {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_size(&self, cx: &gpui::WindowContext) -> f32 {
|
fn default_size(&self, cx: &WindowContext) -> f32 {
|
||||||
cx.global::<Settings>().project_panel.default_width
|
cx.global::<Settings>().project_panel.default_width
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1395,13 +1409,21 @@ impl workspace::dock::Panel for ProjectPanel {
|
||||||
matches!(event, Event::DockPositionChanged)
|
matches!(event, Event::DockPositionChanged)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_activate_on_event(&self, _: &Self::Event, _: &AppContext) -> bool {
|
fn should_activate_on_event(_: &Self::Event) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_close_on_event(&self, _: &Self::Event, _: &AppContext) -> bool {
|
fn should_close_on_event(_: &Self::Event) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn has_focus(&self, _: &WindowContext) -> bool {
|
||||||
|
self.has_focus
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_focus_event(event: &Self::Event) -> bool {
|
||||||
|
matches!(event, Event::Focus)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClipboardEntry {
|
impl ClipboardEntry {
|
||||||
|
|
|
@ -20,6 +20,7 @@ pub enum Event {
|
||||||
DockPositionChanged,
|
DockPositionChanged,
|
||||||
ZoomIn,
|
ZoomIn,
|
||||||
ZoomOut,
|
ZoomOut,
|
||||||
|
Focus,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TerminalPanel {
|
pub struct TerminalPanel {
|
||||||
|
@ -100,6 +101,7 @@ impl TerminalPanel {
|
||||||
pane::Event::Remove => cx.emit(Event::Close),
|
pane::Event::Remove => cx.emit(Event::Close),
|
||||||
pane::Event::ZoomIn => cx.emit(Event::ZoomIn),
|
pane::Event::ZoomIn => cx.emit(Event::ZoomIn),
|
||||||
pane::Event::ZoomOut => cx.emit(Event::ZoomOut),
|
pane::Event::ZoomOut => cx.emit(Event::ZoomOut),
|
||||||
|
pane::Event::Focus => cx.emit(Event::Focus),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -149,6 +151,10 @@ impl View for TerminalPanel {
|
||||||
if self.pane.read(cx).items_len() == 0 {
|
if self.pane.read(cx).items_len() == 0 {
|
||||||
self.add_terminal(&Default::default(), cx)
|
self.add_terminal(&Default::default(), cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cx.is_self_focused() {
|
||||||
|
cx.focus(&self.pane);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +217,7 @@ impl Panel for TerminalPanel {
|
||||||
"Terminals".to_string()
|
"Terminals".to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn icon_label(&self, cx: &AppContext) -> Option<String> {
|
fn icon_label(&self, cx: &WindowContext) -> Option<String> {
|
||||||
let count = self.pane.read(cx).items_len();
|
let count = self.pane.read(cx).items_len();
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
None
|
None
|
||||||
|
@ -224,11 +230,19 @@ impl Panel for TerminalPanel {
|
||||||
matches!(event, Event::DockPositionChanged)
|
matches!(event, Event::DockPositionChanged)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_activate_on_event(&self, _: &Self::Event, _: &AppContext) -> bool {
|
fn should_activate_on_event(_: &Self::Event) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_close_on_event(&self, event: &Event, _: &AppContext) -> bool {
|
fn should_close_on_event(event: &Event) -> bool {
|
||||||
matches!(event, Event::Close)
|
matches!(event, Event::Close)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn has_focus(&self, cx: &WindowContext) -> bool {
|
||||||
|
self.pane.read(cx).has_focus()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_focus_event(event: &Self::Event) -> bool {
|
||||||
|
matches!(event, Event::Focus)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use crate::{StatusItemView, Workspace};
|
use crate::{StatusItemView, Workspace};
|
||||||
use context_menu::{ContextMenu, ContextMenuItem};
|
use context_menu::{ContextMenu, ContextMenuItem};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
elements::*, impl_actions, platform::CursorStyle, platform::MouseButton, AnyViewHandle,
|
elements::*, impl_actions, platform::CursorStyle, platform::MouseButton, AnyViewHandle, Axis,
|
||||||
AppContext, Axis, Entity, Subscription, View, ViewContext, ViewHandle, WeakViewHandle,
|
Entity, Subscription, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext,
|
||||||
WindowContext,
|
|
||||||
};
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
|
@ -16,15 +15,17 @@ pub trait Panel: View {
|
||||||
fn default_size(&self, cx: &WindowContext) -> f32;
|
fn default_size(&self, cx: &WindowContext) -> f32;
|
||||||
fn icon_path(&self) -> &'static str;
|
fn icon_path(&self) -> &'static str;
|
||||||
fn icon_tooltip(&self) -> String;
|
fn icon_tooltip(&self) -> String;
|
||||||
fn icon_label(&self, _: &AppContext) -> Option<String> {
|
fn icon_label(&self, _: &WindowContext) -> Option<String> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn should_change_position_on_event(_: &Self::Event) -> bool;
|
fn should_change_position_on_event(_: &Self::Event) -> bool;
|
||||||
fn should_zoom_in_on_event(_: &Self::Event) -> bool;
|
fn should_zoom_in_on_event(_: &Self::Event) -> bool;
|
||||||
fn should_zoom_out_on_event(_: &Self::Event) -> bool;
|
fn should_zoom_out_on_event(_: &Self::Event) -> bool;
|
||||||
fn set_zoomed(&mut self, zoomed: bool, cx: &mut ViewContext<Self>);
|
fn set_zoomed(&mut self, zoomed: bool, cx: &mut ViewContext<Self>);
|
||||||
fn should_activate_on_event(&self, _: &Self::Event, _: &AppContext) -> bool;
|
fn should_activate_on_event(_: &Self::Event) -> bool;
|
||||||
fn should_close_on_event(&self, _: &Self::Event, _: &AppContext) -> bool;
|
fn should_close_on_event(_: &Self::Event) -> bool;
|
||||||
|
fn has_focus(&self, cx: &WindowContext) -> bool;
|
||||||
|
fn is_focus_event(_: &Self::Event) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait PanelHandle {
|
pub trait PanelHandle {
|
||||||
|
@ -37,7 +38,7 @@ pub trait PanelHandle {
|
||||||
fn icon_path(&self, cx: &WindowContext) -> &'static str;
|
fn icon_path(&self, cx: &WindowContext) -> &'static str;
|
||||||
fn icon_tooltip(&self, cx: &WindowContext) -> String;
|
fn icon_tooltip(&self, cx: &WindowContext) -> String;
|
||||||
fn icon_label(&self, cx: &WindowContext) -> Option<String>;
|
fn icon_label(&self, cx: &WindowContext) -> Option<String>;
|
||||||
fn is_focused(&self, cx: &WindowContext) -> bool;
|
fn has_focus(&self, cx: &WindowContext) -> bool;
|
||||||
fn as_any(&self) -> &AnyViewHandle;
|
fn as_any(&self) -> &AnyViewHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,8 +82,8 @@ where
|
||||||
self.read(cx).icon_label(cx)
|
self.read(cx).icon_label(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_focused(&self, cx: &WindowContext) -> bool {
|
fn has_focus(&self, cx: &WindowContext) -> bool {
|
||||||
ViewHandle::is_focused(self, cx)
|
self.read(cx).has_focus(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &AnyViewHandle {
|
fn as_any(&self) -> &AnyViewHandle {
|
||||||
|
@ -170,6 +171,11 @@ impl Dock {
|
||||||
self.is_open
|
self.is_open
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_focus(&self, cx: &WindowContext) -> bool {
|
||||||
|
self.active_panel()
|
||||||
|
.map_or(false, |panel| panel.has_focus(cx))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn active_panel_index(&self) -> usize {
|
pub fn active_panel_index(&self) -> usize {
|
||||||
self.active_panel_index
|
self.active_panel_index
|
||||||
}
|
}
|
||||||
|
@ -220,7 +226,7 @@ impl Dock {
|
||||||
let subscriptions = [
|
let subscriptions = [
|
||||||
cx.observe(&panel, |_, _, cx| cx.notify()),
|
cx.observe(&panel, |_, _, cx| cx.notify()),
|
||||||
cx.subscribe(&panel, |this, panel, event, cx| {
|
cx.subscribe(&panel, |this, panel, event, cx| {
|
||||||
if panel.read(cx).should_activate_on_event(event, cx) {
|
if T::should_activate_on_event(event) {
|
||||||
if let Some(ix) = this
|
if let Some(ix) = this
|
||||||
.panel_entries
|
.panel_entries
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -230,7 +236,7 @@ impl Dock {
|
||||||
this.activate_panel(ix, cx);
|
this.activate_panel(ix, cx);
|
||||||
cx.focus(&panel);
|
cx.focus(&panel);
|
||||||
}
|
}
|
||||||
} else if panel.read(cx).should_close_on_event(event, cx)
|
} else if T::should_close_on_event(event)
|
||||||
&& this.active_panel().map_or(false, |p| p.id() == panel.id())
|
&& this.active_panel().map_or(false, |p| p.id() == panel.id())
|
||||||
{
|
{
|
||||||
this.set_open(false, cx);
|
this.set_open(false, cx);
|
||||||
|
@ -302,10 +308,10 @@ impl Dock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn zoomed_panel(&self) -> Option<AnyViewHandle> {
|
pub fn zoomed_panel(&self) -> Option<Rc<dyn PanelHandle>> {
|
||||||
let entry = self.active_entry()?;
|
let entry = self.active_entry()?;
|
||||||
if entry.zoomed {
|
if entry.zoomed {
|
||||||
Some(entry.panel.as_any().clone())
|
Some(entry.panel.clone())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -344,6 +350,24 @@ impl Dock {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn render_placeholder(&self, cx: &WindowContext) -> AnyElement<Workspace> {
|
||||||
|
if let Some(active_entry) = self.active_entry() {
|
||||||
|
let style = &cx.global::<Settings>().theme.workspace.dock;
|
||||||
|
Empty::new()
|
||||||
|
.into_any()
|
||||||
|
.contained()
|
||||||
|
.with_style(style.container)
|
||||||
|
.resizable(
|
||||||
|
self.position.to_resize_handle_side(),
|
||||||
|
active_entry.size,
|
||||||
|
|_, _, _| {},
|
||||||
|
)
|
||||||
|
.into_any()
|
||||||
|
} else {
|
||||||
|
Empty::new().into_any()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Entity for Dock {
|
impl Entity for Dock {
|
||||||
|
@ -357,21 +381,16 @@ impl View for Dock {
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
|
||||||
if let Some(active_entry) = self.active_entry() {
|
if let Some(active_entry) = self.active_entry() {
|
||||||
if active_entry.zoomed {
|
let style = &cx.global::<Settings>().theme.workspace.dock;
|
||||||
Empty::new().into_any()
|
ChildView::new(active_entry.panel.as_any(), cx)
|
||||||
} else {
|
.contained()
|
||||||
let size = self.active_panel_size().unwrap();
|
.with_style(style.container)
|
||||||
let style = &cx.global::<Settings>().theme.workspace.dock;
|
.resizable(
|
||||||
ChildView::new(active_entry.panel.as_any(), cx)
|
self.position.to_resize_handle_side(),
|
||||||
.contained()
|
active_entry.size,
|
||||||
.with_style(style.container)
|
|dock: &mut Self, size, cx| dock.resize_active_panel(size, cx),
|
||||||
.resizable(
|
)
|
||||||
self.position.to_resize_handle_side(),
|
.into_any()
|
||||||
size,
|
|
||||||
|dock: &mut Self, size, cx| dock.resize_active_panel(size, cx),
|
|
||||||
)
|
|
||||||
.into_any()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Empty::new().into_any()
|
Empty::new().into_any()
|
||||||
}
|
}
|
||||||
|
@ -604,12 +623,20 @@ pub(crate) mod test {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_activate_on_event(&self, event: &Self::Event, _: &gpui::AppContext) -> bool {
|
fn should_activate_on_event(event: &Self::Event) -> bool {
|
||||||
matches!(event, TestPanelEvent::Activated)
|
matches!(event, TestPanelEvent::Activated)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_close_on_event(&self, event: &Self::Event, _: &gpui::AppContext) -> bool {
|
fn should_close_on_event(event: &Self::Event) -> bool {
|
||||||
matches!(event, TestPanelEvent::Closed)
|
matches!(event, TestPanelEvent::Closed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn has_focus(&self, _cx: &WindowContext) -> bool {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_focus_event(_: &Self::Event) -> bool {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1699,7 +1699,11 @@ impl View for Pane {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
self.has_focus = true;
|
if !self.has_focus {
|
||||||
|
self.has_focus = true;
|
||||||
|
cx.emit(Event::Focus);
|
||||||
|
}
|
||||||
|
|
||||||
self.toolbar.update(cx, |toolbar, cx| {
|
self.toolbar.update(cx, |toolbar, cx| {
|
||||||
toolbar.pane_focus_update(true, cx);
|
toolbar.pane_focus_update(true, cx);
|
||||||
});
|
});
|
||||||
|
@ -1725,8 +1729,6 @@ impl View for Pane {
|
||||||
.insert(active_item.id(), focused.downgrade());
|
.insert(active_item.id(), focused.downgrade());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.emit(Event::Focus);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
|
||||||
|
|
|
@ -7,7 +7,7 @@ use gpui::{
|
||||||
elements::*,
|
elements::*,
|
||||||
geometry::{rect::RectF, vector::Vector2F},
|
geometry::{rect::RectF, vector::Vector2F},
|
||||||
platform::{CursorStyle, MouseButton},
|
platform::{CursorStyle, MouseButton},
|
||||||
Axis, Border, ModelHandle, ViewContext, ViewHandle,
|
AnyViewHandle, Axis, Border, ModelHandle, ViewContext, ViewHandle,
|
||||||
};
|
};
|
||||||
use project::Project;
|
use project::Project;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -72,6 +72,7 @@ impl PaneGroup {
|
||||||
follower_states: &FollowerStatesByLeader,
|
follower_states: &FollowerStatesByLeader,
|
||||||
active_call: Option<&ModelHandle<ActiveCall>>,
|
active_call: Option<&ModelHandle<ActiveCall>>,
|
||||||
active_pane: &ViewHandle<Pane>,
|
active_pane: &ViewHandle<Pane>,
|
||||||
|
zoomed: Option<&AnyViewHandle>,
|
||||||
app_state: &Arc<AppState>,
|
app_state: &Arc<AppState>,
|
||||||
cx: &mut ViewContext<Workspace>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
) -> AnyElement<Workspace> {
|
) -> AnyElement<Workspace> {
|
||||||
|
@ -81,6 +82,7 @@ impl PaneGroup {
|
||||||
follower_states,
|
follower_states,
|
||||||
active_call,
|
active_call,
|
||||||
active_pane,
|
active_pane,
|
||||||
|
zoomed,
|
||||||
app_state,
|
app_state,
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
|
@ -135,6 +137,7 @@ impl Member {
|
||||||
follower_states: &FollowerStatesByLeader,
|
follower_states: &FollowerStatesByLeader,
|
||||||
active_call: Option<&ModelHandle<ActiveCall>>,
|
active_call: Option<&ModelHandle<ActiveCall>>,
|
||||||
active_pane: &ViewHandle<Pane>,
|
active_pane: &ViewHandle<Pane>,
|
||||||
|
zoomed: Option<&AnyViewHandle>,
|
||||||
app_state: &Arc<AppState>,
|
app_state: &Arc<AppState>,
|
||||||
cx: &mut ViewContext<Workspace>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
) -> AnyElement<Workspace> {
|
) -> AnyElement<Workspace> {
|
||||||
|
@ -142,7 +145,7 @@ impl Member {
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Member::Pane(pane) => {
|
Member::Pane(pane) => {
|
||||||
let pane_element = if pane.read(cx).is_zoomed() {
|
let pane_element = if Some(&**pane) == zoomed {
|
||||||
Empty::new().into_any()
|
Empty::new().into_any()
|
||||||
} else {
|
} else {
|
||||||
ChildView::new(pane, cx).into_any()
|
ChildView::new(pane, cx).into_any()
|
||||||
|
@ -274,6 +277,7 @@ impl Member {
|
||||||
follower_states,
|
follower_states,
|
||||||
active_call,
|
active_call,
|
||||||
active_pane,
|
active_pane,
|
||||||
|
zoomed,
|
||||||
app_state,
|
app_state,
|
||||||
cx,
|
cx,
|
||||||
),
|
),
|
||||||
|
@ -378,6 +382,7 @@ impl PaneAxis {
|
||||||
follower_state: &FollowerStatesByLeader,
|
follower_state: &FollowerStatesByLeader,
|
||||||
active_call: Option<&ModelHandle<ActiveCall>>,
|
active_call: Option<&ModelHandle<ActiveCall>>,
|
||||||
active_pane: &ViewHandle<Pane>,
|
active_pane: &ViewHandle<Pane>,
|
||||||
|
zoomed: Option<&AnyViewHandle>,
|
||||||
app_state: &Arc<AppState>,
|
app_state: &Arc<AppState>,
|
||||||
cx: &mut ViewContext<Workspace>,
|
cx: &mut ViewContext<Workspace>,
|
||||||
) -> AnyElement<Workspace> {
|
) -> AnyElement<Workspace> {
|
||||||
|
@ -395,6 +400,7 @@ impl PaneAxis {
|
||||||
follower_state,
|
follower_state,
|
||||||
active_call,
|
active_call,
|
||||||
active_pane,
|
active_pane,
|
||||||
|
zoomed,
|
||||||
app_state,
|
app_state,
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
|
|
|
@ -893,6 +893,8 @@ impl Workspace {
|
||||||
dock.update(cx, |dock, cx| dock.set_panel_zoomed(&panel, true, cx));
|
dock.update(cx, |dock, cx| dock.set_panel_zoomed(&panel, true, cx));
|
||||||
} else if T::should_zoom_out_on_event(event) {
|
} else if T::should_zoom_out_on_event(event) {
|
||||||
this.zoom_out(cx);
|
this.zoom_out(cx);
|
||||||
|
} else if T::is_focus_event(event) {
|
||||||
|
cx.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1309,16 +1311,42 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zoomed(&self, cx: &AppContext) -> Option<AnyViewHandle> {
|
fn zoomed(&self, cx: &WindowContext) -> Option<AnyViewHandle> {
|
||||||
self.left_dock
|
self.zoomed_panel_for_dock(DockPosition::Left, cx)
|
||||||
.read(cx)
|
.or_else(|| self.zoomed_panel_for_dock(DockPosition::Bottom, cx))
|
||||||
.zoomed_panel()
|
.or_else(|| self.zoomed_panel_for_dock(DockPosition::Right, cx))
|
||||||
.or(self.bottom_dock.read(cx).zoomed_panel())
|
.or_else(|| self.zoomed_pane(cx))
|
||||||
.or(self.right_dock.read(cx).zoomed_panel())
|
}
|
||||||
.or_else(|| {
|
|
||||||
let pane = self.panes.iter().find(|pane| pane.read(cx).is_zoomed())?;
|
fn zoomed_panel_for_dock(
|
||||||
Some(pane.clone().into_any())
|
&self,
|
||||||
})
|
position: DockPosition,
|
||||||
|
cx: &WindowContext,
|
||||||
|
) -> Option<AnyViewHandle> {
|
||||||
|
let (dock, other_docks) = match position {
|
||||||
|
DockPosition::Left => (&self.left_dock, [&self.bottom_dock, &self.right_dock]),
|
||||||
|
DockPosition::Bottom => (&self.bottom_dock, [&self.left_dock, &self.right_dock]),
|
||||||
|
DockPosition::Right => (&self.right_dock, [&self.left_dock, &self.bottom_dock]),
|
||||||
|
};
|
||||||
|
|
||||||
|
let zoomed_panel = dock.read(&cx).zoomed_panel()?;
|
||||||
|
if other_docks.iter().all(|dock| !dock.read(cx).has_focus(cx))
|
||||||
|
&& !self.active_pane.read(cx).has_focus()
|
||||||
|
{
|
||||||
|
Some(zoomed_panel.as_any().clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn zoomed_pane(&self, cx: &WindowContext) -> Option<AnyViewHandle> {
|
||||||
|
let active_pane = self.active_pane.read(cx);
|
||||||
|
let docks = [&self.left_dock, &self.bottom_dock, &self.right_dock];
|
||||||
|
if active_pane.is_zoomed() && docks.iter().all(|dock| !dock.read(cx).has_focus(cx)) {
|
||||||
|
Some(self.active_pane.clone().into_any())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn items<'a>(
|
pub fn items<'a>(
|
||||||
|
@ -1433,7 +1461,7 @@ impl Workspace {
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(active_item) = active_item {
|
if let Some(active_item) = active_item {
|
||||||
if active_item.is_focused(cx) {
|
if active_item.has_focus(cx) {
|
||||||
cx.focus_self();
|
cx.focus_self();
|
||||||
} else {
|
} else {
|
||||||
cx.focus(active_item.as_any());
|
cx.focus(active_item.as_any());
|
||||||
|
@ -1464,7 +1492,7 @@ impl Workspace {
|
||||||
dock.active_panel().cloned()
|
dock.active_panel().cloned()
|
||||||
});
|
});
|
||||||
if let Some(active_item) = active_item {
|
if let Some(active_item) = active_item {
|
||||||
if active_item.is_focused(cx) {
|
if active_item.has_focus(cx) {
|
||||||
cx.focus_self();
|
cx.focus_self();
|
||||||
} else {
|
} else {
|
||||||
cx.focus(active_item.as_any());
|
cx.focus(active_item.as_any());
|
||||||
|
@ -1663,7 +1691,6 @@ impl Workspace {
|
||||||
});
|
});
|
||||||
self.active_item_path_changed(cx);
|
self.active_item_path_changed(cx);
|
||||||
self.last_active_center_pane = Some(pane.downgrade());
|
self.last_active_center_pane = Some(pane.downgrade());
|
||||||
cx.notify();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.update_followers(
|
self.update_followers(
|
||||||
|
@ -1677,6 +1704,8 @@ impl Workspace {
|
||||||
}),
|
}),
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_pane_event(
|
fn handle_pane_event(
|
||||||
|
@ -1716,9 +1745,11 @@ impl Workspace {
|
||||||
self.handle_pane_focused(pane.clone(), cx);
|
self.handle_pane_focused(pane.clone(), cx);
|
||||||
}
|
}
|
||||||
pane::Event::ZoomIn => {
|
pane::Event::ZoomIn => {
|
||||||
self.zoom_out(cx);
|
if pane == self.active_pane {
|
||||||
pane.update(cx, |pane, cx| pane.set_zoomed(true, cx));
|
self.zoom_out(cx);
|
||||||
cx.notify();
|
pane.update(cx, |pane, cx| pane.set_zoomed(true, cx));
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pane::Event::ZoomOut => self.zoom_out(cx),
|
pane::Event::ZoomOut => self.zoom_out(cx),
|
||||||
}
|
}
|
||||||
|
@ -2646,6 +2677,33 @@ impl Workspace {
|
||||||
});
|
});
|
||||||
Self::new(None, 0, project, app_state, cx)
|
Self::new(None, 0, project, app_state, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_dock(&self, position: DockPosition, cx: &WindowContext) -> Option<AnyElement<Self>> {
|
||||||
|
let dock = match position {
|
||||||
|
DockPosition::Left => &self.left_dock,
|
||||||
|
DockPosition::Right => &self.right_dock,
|
||||||
|
DockPosition::Bottom => &self.bottom_dock,
|
||||||
|
};
|
||||||
|
let active_panel = dock.read(cx).active_panel()?;
|
||||||
|
let element = if Some(active_panel.as_any()) == self.zoomed(cx).as_ref() {
|
||||||
|
dock.read(cx).render_placeholder(cx)
|
||||||
|
} else {
|
||||||
|
ChildView::new(dock, cx).into_any()
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(
|
||||||
|
element
|
||||||
|
.constrained()
|
||||||
|
.dynamically(move |constraint, _, cx| match position {
|
||||||
|
DockPosition::Left | DockPosition::Right => SizeConstraint::new(
|
||||||
|
Vector2F::new(20., constraint.min.y()),
|
||||||
|
Vector2F::new(cx.window_size().x() * 0.8, constraint.max.y()),
|
||||||
|
),
|
||||||
|
_ => constraint,
|
||||||
|
})
|
||||||
|
.into_any(),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn notify_if_database_failed(workspace: &WeakViewHandle<Workspace>, cx: &mut AsyncAppContext) {
|
fn notify_if_database_failed(workspace: &WeakViewHandle<Workspace>, cx: &mut AsyncAppContext) {
|
||||||
|
@ -2702,25 +2760,7 @@ impl View for Workspace {
|
||||||
.with_child({
|
.with_child({
|
||||||
let project = self.project.clone();
|
let project = self.project.clone();
|
||||||
Flex::row()
|
Flex::row()
|
||||||
.with_children(
|
.with_children(self.render_dock(DockPosition::Left, cx))
|
||||||
if self.left_dock.read(cx).active_panel().is_some() {
|
|
||||||
Some(
|
|
||||||
ChildView::new(&self.left_dock, cx)
|
|
||||||
.constrained()
|
|
||||||
.dynamically(|constraint, _, cx| {
|
|
||||||
SizeConstraint::new(
|
|
||||||
Vector2F::new(20., constraint.min.y()),
|
|
||||||
Vector2F::new(
|
|
||||||
cx.window_size().x() * 0.8,
|
|
||||||
constraint.max.y(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.with_child(
|
.with_child(
|
||||||
Flex::column()
|
Flex::column()
|
||||||
.with_child(
|
.with_child(
|
||||||
|
@ -2730,44 +2770,18 @@ impl View for Workspace {
|
||||||
&self.follower_states_by_leader,
|
&self.follower_states_by_leader,
|
||||||
self.active_call(),
|
self.active_call(),
|
||||||
self.active_pane(),
|
self.active_pane(),
|
||||||
|
self.zoomed(cx).as_ref(),
|
||||||
&self.app_state,
|
&self.app_state,
|
||||||
cx,
|
cx,
|
||||||
))
|
))
|
||||||
.flex(1., true),
|
.flex(1., true),
|
||||||
)
|
)
|
||||||
.with_children(
|
.with_children(
|
||||||
if self
|
self.render_dock(DockPosition::Bottom, cx),
|
||||||
.bottom_dock
|
|
||||||
.read(cx)
|
|
||||||
.active_panel()
|
|
||||||
.is_some()
|
|
||||||
{
|
|
||||||
Some(ChildView::new(&self.bottom_dock, cx))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.flex(1., true),
|
.flex(1., true),
|
||||||
)
|
)
|
||||||
.with_children(
|
.with_children(self.render_dock(DockPosition::Right, cx))
|
||||||
if self.right_dock.read(cx).active_panel().is_some() {
|
|
||||||
Some(
|
|
||||||
ChildView::new(&self.right_dock, cx)
|
|
||||||
.constrained()
|
|
||||||
.dynamically(|constraint, _, cx| {
|
|
||||||
SizeConstraint::new(
|
|
||||||
Vector2F::new(20., constraint.min.y()),
|
|
||||||
Vector2F::new(
|
|
||||||
cx.window_size().x() * 0.8,
|
|
||||||
constraint.max.y(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.with_child(Overlay::new(
|
.with_child(Overlay::new(
|
||||||
Stack::new()
|
Stack::new()
|
||||||
|
@ -2810,6 +2824,7 @@ impl View for Workspace {
|
||||||
if cx.is_self_focused() {
|
if cx.is_self_focused() {
|
||||||
cx.focus(&self.active_pane);
|
cx.focus(&self.active_pane);
|
||||||
}
|
}
|
||||||
|
cx.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue