From 420253a75295596fb7fb9aeac025f992f428115a Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Fri, 22 Dec 2023 15:32:47 +0200 Subject: [PATCH] Restore zoom buttons in pane tab bars, fix + button in the terminal one --- crates/terminal_view2/src/terminal_panel.rs | 72 +++----- crates/workspace2/src/pane.rs | 189 ++++++++------------ 2 files changed, 103 insertions(+), 158 deletions(-) diff --git a/crates/terminal_view2/src/terminal_panel.rs b/crates/terminal_view2/src/terminal_panel.rs index 3c7b2a2e0e9d1e1d8f7a37311e4923c996da5e8b..def56f376024c16a4061b3b2cffb8d2da620bfd1 100644 --- a/crates/terminal_view2/src/terminal_panel.rs +++ b/crates/terminal_view2/src/terminal_panel.rs @@ -4,13 +4,14 @@ use crate::TerminalView; use db::kvp::KEY_VALUE_STORE; use gpui::{ actions, div, serde_json, AppContext, AsyncWindowContext, Div, Entity, EventEmitter, - ExternalPaths, FocusHandle, FocusableView, ParentElement, Render, Styled, Subscription, Task, - View, ViewContext, VisualContext, WeakView, WindowContext, + ExternalPaths, FocusHandle, FocusableView, IntoElement, ParentElement, Render, Styled, + Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext, }; use project::Fs; use serde::{Deserialize, Serialize}; use settings::{Settings, SettingsStore}; use terminal::terminal_settings::{TerminalDockPosition, TerminalSettings}; +use ui::{h_stack, ButtonCommon, Clickable, IconButton, IconSize, Selectable, Tooltip}; use util::{ResultExt, TryFutureExt}; use workspace::{ dock::{DockPosition, Panel, PanelEvent}, @@ -51,9 +52,8 @@ pub struct TerminalPanel { impl TerminalPanel { fn new(workspace: &Workspace, cx: &mut ViewContext) -> Self { - let _weak_self = cx.view().downgrade(); + let terminal_panel = cx.view().clone(); let pane = cx.build_view(|cx| { - let _window = cx.window_handle(); let mut pane = Pane::new( workspace.weak_handle(), workspace.project().clone(), @@ -74,45 +74,31 @@ impl TerminalPanel { ); pane.set_can_split(false, cx); pane.set_can_navigate(false, cx); - // todo!() - // pane.set_render_tab_bar_buttons(cx, move |pane, cx| { - // let this = weak_self.clone(); - // Flex::row() - // .with_child(Pane::render_tab_bar_button( - // 0, - // "icons/plus.svg", - // false, - // Some(("New Terminal", Some(Box::new(workspace::NewTerminal)))), - // cx, - // move |_, cx| { - // let this = this.clone(); - // cx.window_context().defer(move |cx| { - // if let Some(this) = this.upgrade() { - // this.update(cx, |this, cx| { - // this.add_terminal(None, cx); - // }); - // } - // }) - // }, - // |_, _| {}, - // None, - // )) - // .with_child(Pane::render_tab_bar_button( - // 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() - // }); + pane.set_render_tab_bar_buttons(cx, move |pane, cx| { + h_stack() + .child( + IconButton::new("plus", Icon::Plus) + .icon_size(IconSize::Small) + .on_click(cx.listener_for(&terminal_panel, |terminal_panel, _, cx| { + terminal_panel.add_terminal(None, cx); + })) + .tooltip(|cx| Tooltip::text("New Terminal", cx)), + ) + .child({ + let zoomed = pane.is_zoomed(); + IconButton::new("toggle_zoom", Icon::Maximize) + .icon_size(IconSize::Small) + .selected(zoomed) + .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) + }) + }) + .into_any_element() + }); // let buffer_search_bar = cx.build_view(search::BufferSearchBar::new); // pane.toolbar() // .update(cx, |toolbar, cx| toolbar.add_item(buffer_search_bar, cx)); diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 911c292133a150712106c8b4776617ff7aca5e6b..86894dee46daea3d389141e6a8cc4273ae773603 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -7,7 +7,7 @@ use crate::{ use anyhow::Result; use collections::{HashMap, HashSet, VecDeque}; 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, Focusable, FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point, PromptLevel, Render, ScrollHandle, Subscription, Task, View, ViewContext, VisualContext, WeakView, @@ -21,6 +21,7 @@ use std::{ any::Any, cmp, fmt, mem, path::{Path, PathBuf}, + rc::Rc, sync::{ atomic::{AtomicUsize, Ordering}, Arc, @@ -183,7 +184,7 @@ pub struct Pane { drag_split_direction: Option, can_drop_predicate: Option bool>>, can_split: bool, - // render_tab_bar_buttons: Rc) -> AnyElement>, + render_tab_bar_buttons: Rc) -> AnyElement>, _subscriptions: Vec, tab_bar_scroll_handle: ScrollHandle, } @@ -374,63 +375,66 @@ impl Pane { project, can_drop_predicate, can_split: true, - // render_tab_bar_buttons: Rc::new(move |pane, cx| { - // Flex::row() - // // New menu - // .with_child(Self::render_tab_bar_button( - // 0, - // "icons/plus.svg", - // false, - // Some(("New...".into(), None)), - // cx, - // |pane, cx| pane.deploy_new_menu(cx), - // |pane, cx| { - // pane.tab_bar_context_menu - // .handle - // .update(cx, |menu, _| menu.delay_cancel()) - // }, - // pane.tab_bar_context_menu - // .handle_if_kind(TabBarContextMenuKind::New), - // )) - // .with_child(Self::render_tab_bar_button( - // 1, - // "icons/split.svg", - // false, - // Some(("Split Pane".into(), None)), - // cx, - // |pane, cx| pane.deploy_split_menu(cx), - // |pane, cx| { - // pane.tab_bar_context_menu - // .handle - // .update(cx, |menu, _| menu.delay_cancel()) - // }, - // pane.tab_bar_context_menu - // .handle_if_kind(TabBarContextMenuKind::Split), - // )) - // .with_child({ - // let icon_path; - // let tooltip_label; - // if pane.is_zoomed() { - // icon_path = "icons/minimize.svg"; - // tooltip_label = "Zoom In"; - // } else { - // icon_path = "icons/maximize.svg"; - // tooltip_label = "Zoom In"; - // } - - // Pane::render_tab_bar_button( - // 2, - // icon_path, - // pane.is_zoomed(), - // Some((tooltip_label, Some(Box::new(ToggleZoom)))), - // cx, - // move |pane, cx| pane.toggle_zoom(&Default::default(), cx), - // move |_, _| {}, - // None, - // ) - // }) - // .into_any() - // }), + render_tab_bar_buttons: Rc::new(move |pane, cx| { + h_stack() + .child( + IconButton::new("plus", Icon::Plus) + .icon_size(IconSize::Small) + .on_click(cx.listener(|pane, _, 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, |pane, _, _: &DismissEvent, cx| { + pane.focus(cx); + pane.new_item_menu = None; + }) + .detach(); + pane.new_item_menu = Some(menu); + })) + .tooltip(|cx| Tooltip::text("New...", cx)), + ) + .when_some(pane.new_item_menu.as_ref(), |el, new_item_menu| { + el.child(Self::render_menu_overlay(new_item_menu)) + }) + .child( + IconButton::new("split", Icon::Split) + .icon_size(IconSize::Small) + .on_click(cx.listener(|pane, _, 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, |pane, _, _: &DismissEvent, cx| { + pane.focus(cx); + pane.split_item_menu = None; + }) + .detach(); + pane.split_item_menu = Some(menu); + })) + .tooltip(|cx| Tooltip::text("Split Pane", cx)), + ) + .child({ + let zoomed = pane.is_zoomed(); + IconButton::new("toggle_zoom", Icon::Maximize) + .icon_size(IconSize::Small) + .selected(zoomed) + .selected_icon(Icon::Minimize) + .on_click(cx.listener(|pane, _, cx| { + pane.toggle_zoom(&crate::ToggleZoom, cx); + })) + .tooltip(move |cx| { + Tooltip::text(if zoomed { "Zoom Out" } else { "Zoom In" }, cx) + }) + }) + .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, } } @@ -510,13 +514,13 @@ impl Pane { cx.notify(); } - // pub fn set_render_tab_bar_buttons(&mut self, cx: &mut ViewContext, render: F) - // where - // F: 'static + Fn(&mut Pane, &mut ViewContext) -> AnyElement, - // { - // self.render_tab_bar_buttons = Rc::new(render); - // cx.notify(); - // } + pub fn set_render_tab_bar_buttons(&mut self, cx: &mut ViewContext, render: F) + where + F: 'static + Fn(&mut Pane, &mut ViewContext) -> AnyElement, + { + self.render_tab_bar_buttons = Rc::new(render); + cx.notify(); + } pub fn nav_history_for_item(&self, item: &View) -> ItemNavHistory { ItemNavHistory { @@ -1672,55 +1676,10 @@ impl Pane { .disabled(!self.can_navigate_forward()) .tooltip(|cx| Tooltip::for_action("Go Forward", &GoForward, cx)), ) - .end_child( - div() - .child( - 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)) - }), - ) + .end_child({ + let render_tab_buttons = self.render_tab_bar_buttons.clone(); + render_tab_buttons(self, cx) + }) .children( self.items .iter()