Restore zoom buttons in pane tab bars, fix + button in the terminal one (#3780)

Release Notes:

- N/A
This commit is contained in:
Kirill Bulatov
2023-12-22 15:48:38 +02:00
committed by GitHub
2 changed files with 103 additions and 158 deletions
+29 -43
View File
@@ -4,13 +4,14 @@ use crate::TerminalView;
use db::kvp::KEY_VALUE_STORE; use db::kvp::KEY_VALUE_STORE;
use gpui::{ use gpui::{
actions, div, serde_json, AppContext, AsyncWindowContext, Div, Entity, EventEmitter, actions, div, serde_json, AppContext, AsyncWindowContext, Div, Entity, EventEmitter,
ExternalPaths, FocusHandle, FocusableView, ParentElement, Render, Styled, Subscription, Task, ExternalPaths, FocusHandle, FocusableView, IntoElement, ParentElement, Render, Styled,
View, ViewContext, VisualContext, WeakView, WindowContext, Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext,
}; };
use project::Fs; use project::Fs;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use settings::{Settings, SettingsStore}; use settings::{Settings, SettingsStore};
use terminal::terminal_settings::{TerminalDockPosition, TerminalSettings}; use terminal::terminal_settings::{TerminalDockPosition, TerminalSettings};
use ui::{h_stack, ButtonCommon, Clickable, IconButton, IconSize, Selectable, Tooltip};
use util::{ResultExt, TryFutureExt}; use util::{ResultExt, TryFutureExt};
use workspace::{ use workspace::{
dock::{DockPosition, Panel, PanelEvent}, dock::{DockPosition, Panel, PanelEvent},
@@ -51,9 +52,8 @@ pub struct TerminalPanel {
impl TerminalPanel { impl TerminalPanel {
fn new(workspace: &Workspace, cx: &mut ViewContext<Self>) -> Self { fn new(workspace: &Workspace, cx: &mut ViewContext<Self>) -> Self {
let _weak_self = cx.view().downgrade(); let terminal_panel = cx.view().clone();
let pane = cx.build_view(|cx| { let pane = cx.build_view(|cx| {
let _window = cx.window_handle();
let mut pane = Pane::new( let mut pane = Pane::new(
workspace.weak_handle(), workspace.weak_handle(),
workspace.project().clone(), workspace.project().clone(),
@@ -74,45 +74,31 @@ impl TerminalPanel {
); );
pane.set_can_split(false, cx); pane.set_can_split(false, cx);
pane.set_can_navigate(false, cx); pane.set_can_navigate(false, cx);
// todo!() pane.set_render_tab_bar_buttons(cx, move |pane, cx| {
// pane.set_render_tab_bar_buttons(cx, move |pane, cx| { h_stack()
// let this = weak_self.clone(); .child(
// Flex::row() IconButton::new("plus", Icon::Plus)
// .with_child(Pane::render_tab_bar_button( .icon_size(IconSize::Small)
// 0, .on_click(cx.listener_for(&terminal_panel, |terminal_panel, _, cx| {
// "icons/plus.svg", terminal_panel.add_terminal(None, cx);
// false, }))
// Some(("New Terminal", Some(Box::new(workspace::NewTerminal)))), .tooltip(|cx| Tooltip::text("New Terminal", cx)),
// cx, )
// move |_, cx| { .child({
// let this = this.clone(); let zoomed = pane.is_zoomed();
// cx.window_context().defer(move |cx| { IconButton::new("toggle_zoom", Icon::Maximize)
// if let Some(this) = this.upgrade() { .icon_size(IconSize::Small)
// this.update(cx, |this, cx| { .selected(zoomed)
// this.add_terminal(None, cx); .selected_icon(Icon::Minimize)
// }); .on_click(cx.listener(|pane, _, cx| {
// } pane.toggle_zoom(&workspace::ToggleZoom, cx);
// }) }))
// }, .tooltip(move |cx| {
// |_, _| {}, Tooltip::text(if zoomed { "Zoom Out" } else { "Zoom In" }, cx)
// None, })
// )) })
// .with_child(Pane::render_tab_bar_button( .into_any_element()
// 1, });
// if pane.is_zoomed() {
// "icons/minimize.svg"
// } else {
// "icons/maximize.svg"
// },
// pane.is_zoomed(),
// Some(("Toggle Zoom".into(), Some(Box::new(workspace::ToggleZoom)))),
// cx,
// move |pane, cx| pane.toggle_zoom(&Default::default(), cx),
// |_, _| {},
// None,
// ))
// .into_any()
// });
// let buffer_search_bar = cx.build_view(search::BufferSearchBar::new); // let buffer_search_bar = cx.build_view(search::BufferSearchBar::new);
// pane.toolbar() // pane.toolbar()
// .update(cx, |toolbar, cx| toolbar.add_item(buffer_search_bar, cx)); // .update(cx, |toolbar, cx| toolbar.add_item(buffer_search_bar, cx));
+74 -115
View File
@@ -7,7 +7,7 @@ use crate::{
use anyhow::Result; use anyhow::Result;
use collections::{HashMap, HashSet, VecDeque}; use collections::{HashMap, HashSet, VecDeque};
use gpui::{ use gpui::{
actions, impl_actions, overlay, prelude::*, Action, AnchorCorner, AppContext, actions, impl_actions, overlay, prelude::*, Action, AnchorCorner, AnyElement, AppContext,
AsyncWindowContext, DismissEvent, Div, DragMoveEvent, EntityId, EventEmitter, FocusHandle, AsyncWindowContext, DismissEvent, Div, DragMoveEvent, EntityId, EventEmitter, FocusHandle,
Focusable, FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point, PromptLevel, Focusable, FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point, PromptLevel,
Render, ScrollHandle, Subscription, Task, View, ViewContext, VisualContext, WeakView, Render, ScrollHandle, Subscription, Task, View, ViewContext, VisualContext, WeakView,
@@ -21,6 +21,7 @@ use std::{
any::Any, any::Any,
cmp, fmt, mem, cmp, fmt, mem,
path::{Path, PathBuf}, path::{Path, PathBuf},
rc::Rc,
sync::{ sync::{
atomic::{AtomicUsize, Ordering}, atomic::{AtomicUsize, Ordering},
Arc, Arc,
@@ -183,7 +184,7 @@ pub struct Pane {
drag_split_direction: Option<SplitDirection>, drag_split_direction: Option<SplitDirection>,
can_drop_predicate: Option<Arc<dyn Fn(&dyn Any, &mut WindowContext) -> bool>>, can_drop_predicate: Option<Arc<dyn Fn(&dyn Any, &mut WindowContext) -> bool>>,
can_split: bool, can_split: bool,
// render_tab_bar_buttons: Rc<dyn Fn(&mut Pane, &mut ViewContext<Pane>) -> AnyElement<Pane>>, render_tab_bar_buttons: Rc<dyn Fn(&mut Pane, &mut ViewContext<Pane>) -> AnyElement>,
_subscriptions: Vec<Subscription>, _subscriptions: Vec<Subscription>,
tab_bar_scroll_handle: ScrollHandle, tab_bar_scroll_handle: ScrollHandle,
} }
@@ -374,63 +375,66 @@ impl Pane {
project, project,
can_drop_predicate, can_drop_predicate,
can_split: true, can_split: true,
// render_tab_bar_buttons: Rc::new(move |pane, cx| { render_tab_bar_buttons: Rc::new(move |pane, cx| {
// Flex::row() h_stack()
// // New menu .child(
// .with_child(Self::render_tab_bar_button( IconButton::new("plus", Icon::Plus)
// 0, .icon_size(IconSize::Small)
// "icons/plus.svg", .on_click(cx.listener(|pane, _, cx| {
// false, let menu = ContextMenu::build(cx, |menu, _| {
// Some(("New...".into(), None)), menu.action("New File", NewFile.boxed_clone())
// cx, .action("New Terminal", NewCenterTerminal.boxed_clone())
// |pane, cx| pane.deploy_new_menu(cx), .action("New Search", NewSearch.boxed_clone())
// |pane, cx| { });
// pane.tab_bar_context_menu cx.subscribe(&menu, |pane, _, _: &DismissEvent, cx| {
// .handle pane.focus(cx);
// .update(cx, |menu, _| menu.delay_cancel()) pane.new_item_menu = None;
// }, })
// pane.tab_bar_context_menu .detach();
// .handle_if_kind(TabBarContextMenuKind::New), pane.new_item_menu = Some(menu);
// )) }))
// .with_child(Self::render_tab_bar_button( .tooltip(|cx| Tooltip::text("New...", cx)),
// 1, )
// "icons/split.svg", .when_some(pane.new_item_menu.as_ref(), |el, new_item_menu| {
// false, el.child(Self::render_menu_overlay(new_item_menu))
// Some(("Split Pane".into(), None)), })
// cx, .child(
// |pane, cx| pane.deploy_split_menu(cx), IconButton::new("split", Icon::Split)
// |pane, cx| { .icon_size(IconSize::Small)
// pane.tab_bar_context_menu .on_click(cx.listener(|pane, _, cx| {
// .handle let menu = ContextMenu::build(cx, |menu, _| {
// .update(cx, |menu, _| menu.delay_cancel()) menu.action("Split Right", SplitRight.boxed_clone())
// }, .action("Split Left", SplitLeft.boxed_clone())
// pane.tab_bar_context_menu .action("Split Up", SplitUp.boxed_clone())
// .handle_if_kind(TabBarContextMenuKind::Split), .action("Split Down", SplitDown.boxed_clone())
// )) });
// .with_child({ cx.subscribe(&menu, |pane, _, _: &DismissEvent, cx| {
// let icon_path; pane.focus(cx);
// let tooltip_label; pane.split_item_menu = None;
// if pane.is_zoomed() { })
// icon_path = "icons/minimize.svg"; .detach();
// tooltip_label = "Zoom In"; pane.split_item_menu = Some(menu);
// } else { }))
// icon_path = "icons/maximize.svg"; .tooltip(|cx| Tooltip::text("Split Pane", cx)),
// tooltip_label = "Zoom In"; )
// } .child({
let zoomed = pane.is_zoomed();
// Pane::render_tab_bar_button( IconButton::new("toggle_zoom", Icon::Maximize)
// 2, .icon_size(IconSize::Small)
// icon_path, .selected(zoomed)
// pane.is_zoomed(), .selected_icon(Icon::Minimize)
// Some((tooltip_label, Some(Box::new(ToggleZoom)))), .on_click(cx.listener(|pane, _, cx| {
// cx, pane.toggle_zoom(&crate::ToggleZoom, cx);
// move |pane, cx| pane.toggle_zoom(&Default::default(), cx), }))
// move |_, _| {}, .tooltip(move |cx| {
// None, Tooltip::text(if zoomed { "Zoom Out" } else { "Zoom In" }, cx)
// ) })
// }) })
// .into_any() .when_some(pane.split_item_menu.as_ref(), |el, split_item_menu| {
// }), el.child(Self::render_menu_overlay(split_item_menu))
})
.into_any_element()
}),
_subscriptions: subscriptions, _subscriptions: subscriptions,
} }
} }
@@ -510,13 +514,13 @@ impl Pane {
cx.notify(); cx.notify();
} }
// pub fn set_render_tab_bar_buttons<F>(&mut self, cx: &mut ViewContext<Self>, render: F) pub fn set_render_tab_bar_buttons<F>(&mut self, cx: &mut ViewContext<Self>, render: F)
// where where
// F: 'static + Fn(&mut Pane, &mut ViewContext<Pane>) -> AnyElement<Pane>, F: 'static + Fn(&mut Pane, &mut ViewContext<Pane>) -> AnyElement,
// { {
// self.render_tab_bar_buttons = Rc::new(render); self.render_tab_bar_buttons = Rc::new(render);
// cx.notify(); cx.notify();
// } }
pub fn nav_history_for_item<T: Item>(&self, item: &View<T>) -> ItemNavHistory { pub fn nav_history_for_item<T: Item>(&self, item: &View<T>) -> ItemNavHistory {
ItemNavHistory { ItemNavHistory {
@@ -1672,55 +1676,10 @@ impl Pane {
.disabled(!self.can_navigate_forward()) .disabled(!self.can_navigate_forward())
.tooltip(|cx| Tooltip::for_action("Go Forward", &GoForward, cx)), .tooltip(|cx| Tooltip::for_action("Go Forward", &GoForward, cx)),
) )
.end_child( .end_child({
div() let render_tab_buttons = self.render_tab_bar_buttons.clone();
.child( render_tab_buttons(self, cx)
IconButton::new("plus", Icon::Plus) })
.icon_size(IconSize::Small)
.on_click(cx.listener(|this, _, cx| {
let menu = ContextMenu::build(cx, |menu, _| {
menu.action("New File", NewFile.boxed_clone())
.action("New Terminal", NewCenterTerminal.boxed_clone())
.action("New Search", NewSearch.boxed_clone())
});
cx.subscribe(&menu, |this, _, _: &DismissEvent, cx| {
this.focus(cx);
this.new_item_menu = None;
})
.detach();
this.new_item_menu = Some(menu);
}))
.tooltip(|cx| Tooltip::text("New...", cx)),
)
.when_some(self.new_item_menu.as_ref(), |el, new_item_menu| {
el.child(Self::render_menu_overlay(new_item_menu))
}),
)
.end_child(
div()
.child(
IconButton::new("split", Icon::Split)
.icon_size(IconSize::Small)
.on_click(cx.listener(|this, _, cx| {
let menu = ContextMenu::build(cx, |menu, _| {
menu.action("Split Right", SplitRight.boxed_clone())
.action("Split Left", SplitLeft.boxed_clone())
.action("Split Up", SplitUp.boxed_clone())
.action("Split Down", SplitDown.boxed_clone())
});
cx.subscribe(&menu, |this, _, _: &DismissEvent, cx| {
this.focus(cx);
this.split_item_menu = None;
})
.detach();
this.split_item_menu = Some(menu);
}))
.tooltip(|cx| Tooltip::text("Split Pane", cx)),
)
.when_some(self.split_item_menu.as_ref(), |el, split_item_menu| {
el.child(Self::render_menu_overlay(split_item_menu))
}),
)
.children( .children(
self.items self.items
.iter() .iter()