diff --git a/crates/dock/src/dock.rs b/crates/dock/src/dock.rs index 1813149..1b40184 100644 --- a/crates/dock/src/dock.rs +++ b/crates/dock/src/dock.rs @@ -1,5 +1,3 @@ -//! Dock is a fixed container that places at left, bottom, right of the Windows. - use std::ops::Deref; use std::sync::Arc; diff --git a/crates/dock/src/lib.rs b/crates/dock/src/lib.rs index 1d5a461..cf839ee 100644 --- a/crates/dock/src/lib.rs +++ b/crates/dock/src/lib.rs @@ -15,7 +15,7 @@ use gpui::prelude::FluentBuilder; use gpui::{ AnyElement, AnyView, App, AppContext, Axis, Bounds, Context, Edges, Entity, EntityId, EventEmitter, InteractiveElement as _, IntoElement, ParentElement as _, Pixels, Render, - SharedString, Styled, Subscription, WeakEntity, Window, actions, div, + SharedString, Styled, Subscription, WeakEntity, Window, actions, div, px, }; use gpui_component::{ElementExt, Placement}; pub use panel::*; @@ -52,6 +52,9 @@ pub(crate) fn t(key: &'static str) -> &'static str { } } +/// The fixed height of the tab bar, which doubles as the window title bar. +pub(crate) const TAB_BAR_HEIGHT: Pixels = px(44.); + /// A host-owned drag item, dragged into the dock by the application. #[derive(Clone, Debug)] pub struct AnyDrag { @@ -115,9 +118,6 @@ pub struct DockArea { /// Lock panels layout, but allow to resize. locked: bool, - /// The panel style, default is [`PanelStyle::Default`](PanelStyle::Default). - pub(crate) panel_style: PanelStyle, - _subscriptions: Vec, } @@ -509,7 +509,6 @@ impl DockArea { toggle_button_panels: Edges::default(), toggle_button_visible: true, locked: false, - panel_style: PanelStyle::default(), _subscriptions: vec![], }; @@ -523,12 +522,6 @@ impl DockArea { self.bounds } - /// Set the panel style of the dock area. - pub fn panel_style(mut self, style: PanelStyle) -> Self { - self.panel_style = style; - self - } - /// Set version of the dock area. pub fn set_version(&mut self, version: usize, _: &mut Window, cx: &mut Context) { self.version = Some(version); diff --git a/crates/dock/src/panel.rs b/crates/dock/src/panel.rs index afd0cc9..141be9f 100644 --- a/crates/dock/src/panel.rs +++ b/crates/dock/src/panel.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use gpui::{ AnyElement, AnyView, App, AppContext as _, Context, Entity, EntityId, EventEmitter, - FocusHandle, Focusable, Global, Hsla, IntoElement, Render, SharedString, WeakEntity, Window, + FocusHandle, Focusable, Global, IntoElement, Render, SharedString, WeakEntity, Window, }; use gpui_component::button::Button; use gpui_component::menu::PopupMenu; @@ -18,21 +18,6 @@ pub enum PanelEvent { LayoutChanged, } -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -pub enum PanelStyle { - /// Display the TabBar when there are multiple tabs, otherwise display the simple title. - #[default] - Auto, - /// Always display the tab bar. - TabBar, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct TitleStyle { - pub background: Hsla, - pub foreground: Hsla, -} - #[derive(Clone, Copy, Default)] pub enum PanelControl { Both, @@ -74,11 +59,6 @@ pub trait Panel: EventEmitter + Render + Focusable { t("Dock.Unnamed") } - /// The theme of the panel title, default is `None`. - fn title_style(&self, cx: &App) -> Option { - None - } - /// The suffix of the panel title, default is `None`. /// /// This is used to add a suffix element to the panel title. @@ -182,7 +162,6 @@ pub trait PanelView: 'static + Send + Sync { fn tab_name(&self, cx: &App) -> Option; fn title(&self, window: &mut Window, cx: &mut App) -> AnyElement; fn title_suffix(&self, window: &mut Window, cx: &mut App) -> Option; - fn title_style(&self, cx: &App) -> Option; fn closable(&self, cx: &App) -> bool; fn zoomable(&self, cx: &App) -> Option; fn visible(&self, cx: &App) -> bool; @@ -222,10 +201,6 @@ impl PanelView for Entity { }) } - fn title_style(&self, cx: &App) -> Option { - self.read(cx).title_style(cx) - } - fn closable(&self, cx: &App) -> bool { self.read(cx).closable(cx) } diff --git a/crates/dock/src/tab_panel.rs b/crates/dock/src/tab_panel.rs index a2caa6a..cb13466 100644 --- a/crates/dock/src/tab_panel.rs +++ b/crates/dock/src/tab_panel.rs @@ -11,7 +11,7 @@ use gpui::{ DragMoveEvent, Empty, Entity, EntityId, EventEmitter, FocusHandle, Focusable, InteractiveElement as _, IntoElement, MouseButton, ParentElement, Pixels, Point, Render, ScrollHandle, SharedString, Stateful, StatefulInteractiveElement, StyleRefinement, Styled, - WeakEntity, Window, WindowControlArea, div, point, px, rems, + WeakEntity, Window, WindowControlArea, div, point, px, }; use gpui_component::animation::{Lerp, ease_out_cubic}; use gpui_component::button::{Button, ButtonVariants as _}; @@ -23,9 +23,9 @@ use gpui_component::{ use super::{ AnyDrag, ClosePanel, DockArea, DockEvent, DockPlacement, DropTarget, Panel, PanelControl, - PanelEvent, PanelState, PanelStyle, PanelView, StackPanel, ToggleZoom, + PanelEvent, PanelState, PanelView, StackPanel, ToggleZoom, }; -use crate::{PanelInfo, t, window_controls}; +use crate::{PanelInfo, TAB_BAR_HEIGHT, t, window_controls}; #[derive(Clone)] struct TabState { @@ -640,7 +640,7 @@ impl TabPanel { this.children( buttons .into_iter() - .map(|btn| btn.xsmall().ghost().tab_stop(false)), + .map(|btn| btn.small().ghost().tab_stop(false)), ) }) .map(|this| { @@ -656,7 +656,7 @@ impl TabPanel { this.child( Button::new(id) .icon(icon) - .xsmall() + .small() .ghost() .tab_stop(false) .tooltip_with_action(tooltip, &ToggleZoom, None) @@ -672,7 +672,7 @@ impl TabPanel { .child( Button::new("menu") .icon(IconName::Ellipsis) - .xsmall() + .small() .ghost() .tab_stop(false) .dropdown_menu({ @@ -743,7 +743,7 @@ impl TabPanel { Some( Button::new(SharedString::from(format!("toggle-dock:{:?}", placement))) .icon(icon) - .xsmall() + .small() .ghost() .tab_stop(false) .tooltip(match is_open { @@ -769,10 +769,6 @@ impl TabPanel { ) -> impl IntoElement { let view = cx.entity().clone(); - let Some(dock_area) = self.dock_area.upgrade() else { - return div().into_any_element(); - }; - let left_dock_button = self.render_dock_toggle_button(DockPlacement::Left, window, cx); let has_extend_dock_button = left_dock_button.is_some(); @@ -786,75 +782,6 @@ impl TabPanel { .and_then(|area| area.read(cx).left_dock.clone()) .is_none_or(|dock| !dock.read(cx).is_open()); - let panel_style = dock_area.read(cx).panel_style; - let visible_panels = self.visible_panels(cx).collect::>(); - - if visible_panels.len() == 1 && panel_style == PanelStyle::default() { - let panel = visible_panels.first().unwrap(); - - if !panel.visible(cx) { - return div().into_any_element(); - } - - let title_style = panel.title_style(cx); - - return title_bar_drag_handlers( - h_flex() - .id(("tab-panel-simple-title", cx.entity().entity_id())) - .justify_between() - .line_height(rems(1.0)) - .h(px(30.)) - .py_2() - .pl_3() - .pr_2() - .when(left_dock_button.is_some(), |this| this.pl_2()) - .when(needs_traffic_light_padding, |this| this.pl(px(80.))) - .when_some(title_style, |this, theme| { - this.bg(theme.background).text_color(theme.foreground) - }) - .when(has_extend_dock_button, |this| { - this.child( - h_flex() - .flex_shrink_0() - .mr_1() - .gap_1() - .children(left_dock_button), - ) - }) - .child( - div() - .id("tab") - .flex_1() - .min_w_16() - .overflow_hidden() - .text_ellipsis() - .whitespace_nowrap() - .child(panel.title(window, cx)) - .when(state.draggable, |this| { - this.on_drag( - DragPanel::new(panel.clone(), view), - |drag, offset, _, cx| { - cx.stop_propagation(); - drag.drag_offset.set(offset); - cx.new(|_| drag.clone()) - }, - ) - }), - ) - .children(panel.title_suffix(window, cx)) - .child( - h_flex() - .flex_shrink_0() - .ml_1() - .gap_1() - .child(self.render_toolbar(state, window, cx)), - ), - window, - cx, - ) - .into_any_element(); - } - if let Some(panel_ix) = self.pending_scroll_to_ix.take() && let Some(visible_ix) = self .panels @@ -920,6 +847,9 @@ impl TabPanel { }) .child( TabBar::new("tab-bar") + .h(TAB_BAR_HEIGHT) + .pill() + .small() .track_scroll(&self.tab_bar_scroll_handle) .when( has_extend_dock_button || needs_traffic_light_padding, @@ -931,7 +861,6 @@ impl TabPanel { // Right -1 for avoid border overlap with the first tab .right(-px(1.)) .h_full() - .bg(cx.theme().tokens.tab_bar) .px_2() .when(needs_traffic_light_padding, |this| { this.pl(px(80.)) @@ -1073,7 +1002,6 @@ impl TabPanel { .top_0() .right_0() .h_full() - .bg(cx.theme().tokens.tab_bar) .px_2() .gap_1() .on_prepaint({ @@ -1116,7 +1044,7 @@ impl TabPanel { return Empty {}.into_any_element(); }; - let is_render_in_tabs = self.panels.len() > 1 && self.inner_padding(cx); + let has_inner_padding = self.inner_padding(cx); let placeholder = self.drop_placeholder_animation; let placeholder_animation_name = self.drop_placeholder_animation_name.clone(); @@ -1125,7 +1053,7 @@ impl TabPanel { .id("active-panel") .group("") .flex_1() - .when(is_render_in_tabs, |this| this.pt_2()) + .when(has_inner_padding, |this| this.pt_2()) .child( div() .id("tab-content") diff --git a/crates/dock/src/window_controls.rs b/crates/dock/src/window_controls.rs index ee4617d..4a695be 100644 --- a/crates/dock/src/window_controls.rs +++ b/crates/dock/src/window_controls.rs @@ -5,6 +5,8 @@ use gpui::{ }; use gpui_component::{ActiveTheme, Icon, IconName, Sizable as _, h_flex}; +use crate::TAB_BAR_HEIGHT; + /// The standard width of a window control button. const CONTROL_WIDTH: f32 = 34.; @@ -145,6 +147,11 @@ pub(crate) fn window_controls(window: &mut Window, cx: &mut App) -> impl IntoEle .items_center() .flex_shrink_0() .h_full() + // Like native windows apps, the controls span the title bar but never + // grow past the tab bar height. + .when(cfg!(target_os = "windows"), |this| { + this.max_h(TAB_BAR_HEIGHT) + }) .border_l_1() .border_b_1() .border_color(cx.theme().border) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 84d15fd..35af735 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -19,9 +19,7 @@ pub struct Workspace { impl Workspace { pub fn new(window: &mut Window, cx: &mut Context) -> Self { - let dock = cx.new(|cx| { - DockArea::new("dock", Some(1), window, cx).panel_style(dock::PanelStyle::TabBar) - }); + let dock = cx.new(|cx| DockArea::new("dock", Some(1), window, cx)); let weak_dock = dock.downgrade(); let sidebar = cx.new(|cx| SidebarPanel::new(weak_dock.clone(), cx));