Compare commits
15 Commits
parse-bash
...
tab-bar-se
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e19f6416d4 | ||
|
|
6fb6cd3c5c | ||
|
|
0875257852 | ||
|
|
eb97c311c8 | ||
|
|
6422fdea9b | ||
|
|
9d684d7856 | ||
|
|
93978f6017 | ||
|
|
120ead9429 | ||
|
|
99a0356a56 | ||
|
|
94858caff5 | ||
|
|
ca9645c2bf | ||
|
|
b81e8971df | ||
|
|
ed2651d62a | ||
|
|
b8a6fc316f | ||
|
|
2fa9220f44 |
@@ -312,6 +312,16 @@
|
|||||||
"autosave": "off",
|
"autosave": "off",
|
||||||
// Settings related to the editor's tab bar.
|
// Settings related to the editor's tab bar.
|
||||||
"tab_bar": {
|
"tab_bar": {
|
||||||
|
// Where to show the tab bar in the editor.
|
||||||
|
// This setting can take three values:
|
||||||
|
//
|
||||||
|
// 1. Show tab bar at the top of the editor (default):
|
||||||
|
// "top"
|
||||||
|
// 2. Show tab bar at the bottom of the editor:
|
||||||
|
// "bottom"
|
||||||
|
// 3. Don't show the tab bar:
|
||||||
|
// "no"
|
||||||
|
"placement": "top",
|
||||||
// Whether or not to show the navigation history buttons.
|
// Whether or not to show the navigation history buttons.
|
||||||
"show_nav_history_buttons": true
|
"show_nav_history_buttons": true
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -630,6 +630,7 @@ mod tests {
|
|||||||
let http = FakeHttpClient::with_404_response();
|
let http = FakeHttpClient::with_404_response();
|
||||||
let client = Client::new(clock, http.clone(), cx);
|
let client = Client::new(clock, http.clone(), cx);
|
||||||
let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
|
let user_store = cx.new_model(|cx| UserStore::new(client.clone(), cx));
|
||||||
|
workspace::init_settings(cx);
|
||||||
theme::init(theme::LoadThemes::JustBase, cx);
|
theme::init(theme::LoadThemes::JustBase, cx);
|
||||||
Project::init_settings(cx);
|
Project::init_settings(cx);
|
||||||
language::init(cx);
|
language::init(cx);
|
||||||
|
|||||||
@@ -1821,6 +1821,7 @@ pub mod tests {
|
|||||||
cx.set_global(settings);
|
cx.set_global(settings);
|
||||||
language::init(cx);
|
language::init(cx);
|
||||||
crate::init(cx);
|
crate::init(cx);
|
||||||
|
workspace::init_settings(cx);
|
||||||
Project::init_settings(cx);
|
Project::init_settings(cx);
|
||||||
theme::init(LoadThemes::JustBase, cx);
|
theme::init(LoadThemes::JustBase, cx);
|
||||||
cx.update_global::<SettingsStore, _>(|store, cx| {
|
cx.update_global::<SettingsStore, _>(|store, cx| {
|
||||||
|
|||||||
@@ -130,12 +130,11 @@ use ui::{
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
};
|
};
|
||||||
use util::{defer, maybe, post_inc, RangeExt, ResultExt, TryFutureExt};
|
use util::{defer, maybe, post_inc, RangeExt, ResultExt, TryFutureExt};
|
||||||
use workspace::item::ItemHandle;
|
|
||||||
use workspace::notifications::NotificationId;
|
|
||||||
use workspace::{
|
use workspace::{
|
||||||
searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace, WorkspaceId,
|
item::ItemHandle, notifications::NotificationId, searchable::SearchEvent, ItemNavHistory,
|
||||||
|
OpenInTerminal, OpenTerminal, SplitDirection, TabBarPlacement, TabBarSettings, Toast, ViewId,
|
||||||
|
Workspace, WorkspaceId,
|
||||||
};
|
};
|
||||||
use workspace::{OpenInTerminal, OpenTerminal, Toast};
|
|
||||||
|
|
||||||
use crate::hover_links::find_url;
|
use crate::hover_links::find_url;
|
||||||
|
|
||||||
@@ -419,6 +418,7 @@ pub struct Editor {
|
|||||||
hovered_cursors: HashMap<HoveredCursor, Task<()>>,
|
hovered_cursors: HashMap<HoveredCursor, Task<()>>,
|
||||||
pub show_local_selections: bool,
|
pub show_local_selections: bool,
|
||||||
mode: EditorMode,
|
mode: EditorMode,
|
||||||
|
tab_bar_placement: TabBarPlacement,
|
||||||
show_breadcrumbs: bool,
|
show_breadcrumbs: bool,
|
||||||
show_gutter: bool,
|
show_gutter: bool,
|
||||||
show_wrap_guides: Option<bool>,
|
show_wrap_guides: Option<bool>,
|
||||||
@@ -1453,6 +1453,7 @@ impl Editor {
|
|||||||
blink_manager: blink_manager.clone(),
|
blink_manager: blink_manager.clone(),
|
||||||
show_local_selections: true,
|
show_local_selections: true,
|
||||||
mode,
|
mode,
|
||||||
|
tab_bar_placement: TabBarSettings::get_global(cx).placement,
|
||||||
show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs,
|
show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs,
|
||||||
show_gutter: mode == EditorMode::Full,
|
show_gutter: mode == EditorMode::Full,
|
||||||
show_wrap_guides: None,
|
show_wrap_guides: None,
|
||||||
@@ -9620,6 +9621,7 @@ impl Editor {
|
|||||||
let editor_settings = EditorSettings::get_global(cx);
|
let editor_settings = EditorSettings::get_global(cx);
|
||||||
self.scroll_manager.vertical_scroll_margin = editor_settings.vertical_scroll_margin;
|
self.scroll_manager.vertical_scroll_margin = editor_settings.vertical_scroll_margin;
|
||||||
self.show_breadcrumbs = editor_settings.toolbar.breadcrumbs;
|
self.show_breadcrumbs = editor_settings.toolbar.breadcrumbs;
|
||||||
|
self.tab_bar_placement = TabBarSettings::get_global(cx).placement;
|
||||||
|
|
||||||
if self.mode == EditorMode::Full {
|
if self.mode == EditorMode::Full {
|
||||||
let inline_blame_enabled = ProjectSettings::get_global(cx).git.inline_blame_enabled();
|
let inline_blame_enabled = ProjectSettings::get_global(cx).git.inline_blame_enabled();
|
||||||
|
|||||||
@@ -19,7 +19,10 @@ use language::{
|
|||||||
use project::{search::SearchQuery, FormatTrigger, Item as _, Project, ProjectPath};
|
use project::{search::SearchQuery, FormatTrigger, Item as _, Project, ProjectPath};
|
||||||
use rpc::proto::{self, update_view, PeerId};
|
use rpc::proto::{self, update_view, PeerId};
|
||||||
use settings::Settings;
|
use settings::Settings;
|
||||||
use workspace::item::{ItemSettings, TabContentParams};
|
use workspace::{
|
||||||
|
item::{TabContentParams, TabsSettings},
|
||||||
|
TabBarPlacement,
|
||||||
|
};
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
@@ -596,7 +599,7 @@ impl Item for Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement {
|
fn tab_content(&self, params: TabContentParams, cx: &WindowContext) -> AnyElement {
|
||||||
let label_color = if ItemSettings::get_global(cx).git_status {
|
let label_color = if TabsSettings::get_global(cx).git_status {
|
||||||
self.buffer()
|
self.buffer()
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.as_singleton()
|
.as_singleton()
|
||||||
@@ -799,6 +802,10 @@ impl Item for Editor {
|
|||||||
self.pixel_position_of_newest_cursor
|
self.pixel_position_of_newest_cursor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tab_bar_placement(&self) -> TabBarPlacement {
|
||||||
|
self.tab_bar_placement
|
||||||
|
}
|
||||||
|
|
||||||
fn breadcrumb_location(&self) -> ToolbarItemLocation {
|
fn breadcrumb_location(&self) -> ToolbarItemLocation {
|
||||||
if self.show_breadcrumbs {
|
if self.show_breadcrumbs {
|
||||||
ToolbarItemLocation::PrimaryLeft
|
ToolbarItemLocation::PrimaryLeft
|
||||||
|
|||||||
@@ -1032,6 +1032,7 @@ mod tests {
|
|||||||
theme::init(theme::LoadThemes::JustBase, cx);
|
theme::init(theme::LoadThemes::JustBase, cx);
|
||||||
language::init(cx);
|
language::init(cx);
|
||||||
crate::init(cx);
|
crate::init(cx);
|
||||||
|
workspace::init_settings(cx);
|
||||||
Project::init_settings(cx);
|
Project::init_settings(cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ fn init_test(cx: &mut gpui::TestAppContext) {
|
|||||||
release_channel::init("0.0.0", cx);
|
release_channel::init("0.0.0", cx);
|
||||||
language::init(cx);
|
language::init(cx);
|
||||||
client::init_settings(cx);
|
client::init_settings(cx);
|
||||||
|
workspace::init_settings(cx);
|
||||||
Project::init_settings(cx);
|
Project::init_settings(cx);
|
||||||
editor::init_settings(cx);
|
editor::init_settings(cx);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1106,7 +1106,7 @@ mod tests {
|
|||||||
let store = settings::SettingsStore::test(cx);
|
let store = settings::SettingsStore::test(cx);
|
||||||
cx.set_global(store);
|
cx.set_global(store);
|
||||||
editor::init(cx);
|
editor::init(cx);
|
||||||
|
workspace::init_settings(cx);
|
||||||
language::init(cx);
|
language::init(cx);
|
||||||
Project::init_settings(cx);
|
Project::init_settings(cx);
|
||||||
theme::init(theme::LoadThemes::JustBase, cx);
|
theme::init(theme::LoadThemes::JustBase, cx);
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
|
use crate::TabBarPlacement;
|
||||||
|
use crate::{prelude::*, BASE_REM_SIZE_IN_PX};
|
||||||
|
|
||||||
use gpui::{AnyElement, IntoElement, Stateful};
|
use gpui::{AnyElement, IntoElement, Stateful};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
|
||||||
use crate::{prelude::*, BASE_REM_SIZE_IN_PX};
|
|
||||||
|
|
||||||
/// The position of a [`Tab`] within a list of tabs.
|
/// The position of a [`Tab`] within a list of tabs.
|
||||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum TabPosition {
|
pub enum TabPosition {
|
||||||
@@ -30,6 +31,7 @@ pub enum TabCloseSide {
|
|||||||
pub struct Tab {
|
pub struct Tab {
|
||||||
div: Stateful<Div>,
|
div: Stateful<Div>,
|
||||||
selected: bool,
|
selected: bool,
|
||||||
|
tab_bar_placement: TabBarPlacement,
|
||||||
position: TabPosition,
|
position: TabPosition,
|
||||||
close_side: TabCloseSide,
|
close_side: TabCloseSide,
|
||||||
start_slot: Option<AnyElement>,
|
start_slot: Option<AnyElement>,
|
||||||
@@ -45,6 +47,7 @@ impl Tab {
|
|||||||
.id(id.clone())
|
.id(id.clone())
|
||||||
.debug_selector(|| format!("TAB-{}", id)),
|
.debug_selector(|| format!("TAB-{}", id)),
|
||||||
selected: false,
|
selected: false,
|
||||||
|
tab_bar_placement: TabBarPlacement::Top,
|
||||||
position: TabPosition::First,
|
position: TabPosition::First,
|
||||||
close_side: TabCloseSide::End,
|
close_side: TabCloseSide::End,
|
||||||
start_slot: None,
|
start_slot: None,
|
||||||
@@ -57,6 +60,11 @@ impl Tab {
|
|||||||
|
|
||||||
const CONTENT_HEIGHT_IN_REMS: f32 = 28. / BASE_REM_SIZE_IN_PX;
|
const CONTENT_HEIGHT_IN_REMS: f32 = 28. / BASE_REM_SIZE_IN_PX;
|
||||||
|
|
||||||
|
pub fn tab_bar_placement(mut self, tab_bar_placement: TabBarPlacement) -> Self {
|
||||||
|
self.tab_bar_placement = tab_bar_placement;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn position(mut self, position: TabPosition) -> Self {
|
pub fn position(mut self, position: TabPosition) -> Self {
|
||||||
self.position = position;
|
self.position = position;
|
||||||
self
|
self
|
||||||
@@ -117,6 +125,9 @@ impl RenderOnce for Tab {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let placement_top = self.tab_bar_placement == TabBarPlacement::Top;
|
||||||
|
let placement_bottom = self.tab_bar_placement == TabBarPlacement::Bottom;
|
||||||
|
|
||||||
self.div
|
self.div
|
||||||
.h(rems(Self::CONTAINER_HEIGHT_IN_REMS))
|
.h(rems(Self::CONTAINER_HEIGHT_IN_REMS))
|
||||||
.bg(tab_bg)
|
.bg(tab_bg)
|
||||||
@@ -124,21 +135,46 @@ impl RenderOnce for Tab {
|
|||||||
.map(|this| match self.position {
|
.map(|this| match self.position {
|
||||||
TabPosition::First => {
|
TabPosition::First => {
|
||||||
if self.selected {
|
if self.selected {
|
||||||
this.pl_px().border_r().pb_px()
|
this.pl_px()
|
||||||
|
.border_r()
|
||||||
|
.when(placement_top, Styled::pb_px)
|
||||||
|
.when(placement_bottom, Styled::pt_px)
|
||||||
} else {
|
} else {
|
||||||
this.pl_px().pr_px().border_b()
|
this.pl_px()
|
||||||
|
.pr_px()
|
||||||
|
.when(placement_top, Styled::border_b)
|
||||||
|
.when(placement_bottom, Styled::border_t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TabPosition::Last => {
|
TabPosition::Last => {
|
||||||
if self.selected {
|
if self.selected {
|
||||||
this.border_l().border_r().pb_px()
|
this.border_l()
|
||||||
|
.border_r()
|
||||||
|
.when(placement_top, Styled::pb_px)
|
||||||
|
.when(placement_bottom, Styled::pt_px)
|
||||||
} else {
|
} else {
|
||||||
this.pr_px().pl_px().border_b().border_r()
|
this.pr_px()
|
||||||
|
.pl_px()
|
||||||
|
.border_r()
|
||||||
|
.when(placement_top, Styled::border_b)
|
||||||
|
.when(placement_bottom, Styled::border_t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TabPosition::Middle(Ordering::Equal) => this.border_l().border_r().pb_px(),
|
TabPosition::Middle(Ordering::Equal) => this
|
||||||
TabPosition::Middle(Ordering::Less) => this.border_l().pr_px().border_b(),
|
.border_l()
|
||||||
TabPosition::Middle(Ordering::Greater) => this.border_r().pl_px().border_b(),
|
.border_r()
|
||||||
|
.when(placement_top, Styled::pb_px)
|
||||||
|
.when(placement_bottom, Styled::pt_px),
|
||||||
|
TabPosition::Middle(Ordering::Less) => this
|
||||||
|
.border_l()
|
||||||
|
.pr_px()
|
||||||
|
.when(placement_top, Styled::border_b)
|
||||||
|
.when(placement_bottom, Styled::border_t),
|
||||||
|
TabPosition::Middle(Ordering::Greater) => this
|
||||||
|
.border_r()
|
||||||
|
.pl_px()
|
||||||
|
.when(placement_top, Styled::border_b)
|
||||||
|
.when(placement_bottom, Styled::border_t),
|
||||||
})
|
})
|
||||||
.cursor_pointer()
|
.cursor_pointer()
|
||||||
.child(
|
.child(
|
||||||
|
|||||||
@@ -3,9 +3,19 @@ use smallvec::SmallVec;
|
|||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
/// Placement of the tab bar in relation to the main content area.
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub enum TabBarPlacement {
|
||||||
|
/// On top.
|
||||||
|
Top,
|
||||||
|
/// At the bottom.
|
||||||
|
Bottom,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(IntoElement)]
|
#[derive(IntoElement)]
|
||||||
pub struct TabBar {
|
pub struct TabBar {
|
||||||
id: ElementId,
|
id: ElementId,
|
||||||
|
placement: TabBarPlacement,
|
||||||
start_children: SmallVec<[AnyElement; 2]>,
|
start_children: SmallVec<[AnyElement; 2]>,
|
||||||
children: SmallVec<[AnyElement; 2]>,
|
children: SmallVec<[AnyElement; 2]>,
|
||||||
end_children: SmallVec<[AnyElement; 2]>,
|
end_children: SmallVec<[AnyElement; 2]>,
|
||||||
@@ -16,6 +26,7 @@ impl TabBar {
|
|||||||
pub fn new(id: impl Into<ElementId>) -> Self {
|
pub fn new(id: impl Into<ElementId>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
|
placement: TabBarPlacement::Top,
|
||||||
start_children: SmallVec::new(),
|
start_children: SmallVec::new(),
|
||||||
children: SmallVec::new(),
|
children: SmallVec::new(),
|
||||||
end_children: SmallVec::new(),
|
end_children: SmallVec::new(),
|
||||||
@@ -23,6 +34,11 @@ impl TabBar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn placement(mut self, placement: TabBarPlacement) -> Self {
|
||||||
|
self.placement = placement;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn track_scroll(mut self, scroll_handle: ScrollHandle) -> Self {
|
pub fn track_scroll(mut self, scroll_handle: ScrollHandle) -> Self {
|
||||||
self.scroll_handle = Some(scroll_handle);
|
self.scroll_handle = Some(scroll_handle);
|
||||||
self
|
self
|
||||||
@@ -90,6 +106,9 @@ impl ParentElement for TabBar {
|
|||||||
|
|
||||||
impl RenderOnce for TabBar {
|
impl RenderOnce for TabBar {
|
||||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||||
|
let placement_top = self.placement == TabBarPlacement::Top;
|
||||||
|
let placement_bottom = self.placement == TabBarPlacement::Bottom;
|
||||||
|
|
||||||
div()
|
div()
|
||||||
.id(self.id)
|
.id(self.id)
|
||||||
.group("tab_bar")
|
.group("tab_bar")
|
||||||
@@ -104,7 +123,8 @@ impl RenderOnce for TabBar {
|
|||||||
.flex_none()
|
.flex_none()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.px_1()
|
.px_1()
|
||||||
.border_b()
|
.when(placement_top, Styled::border_b)
|
||||||
|
.when(placement_bottom, Styled::border_t)
|
||||||
.border_r()
|
.border_r()
|
||||||
.border_color(cx.theme().colors().border)
|
.border_color(cx.theme().colors().border)
|
||||||
.children(self.start_children),
|
.children(self.start_children),
|
||||||
@@ -122,7 +142,8 @@ impl RenderOnce for TabBar {
|
|||||||
.top_0()
|
.top_0()
|
||||||
.left_0()
|
.left_0()
|
||||||
.size_full()
|
.size_full()
|
||||||
.border_b()
|
.when(placement_top, Styled::border_b)
|
||||||
|
.when(placement_bottom, Styled::border_t)
|
||||||
.border_color(cx.theme().colors().border),
|
.border_color(cx.theme().colors().border),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
@@ -142,7 +163,8 @@ impl RenderOnce for TabBar {
|
|||||||
.flex_none()
|
.flex_none()
|
||||||
.gap_1()
|
.gap_1()
|
||||||
.px_1()
|
.px_1()
|
||||||
.border_b()
|
.when(placement_top, Styled::border_b)
|
||||||
|
.when(placement_bottom, Styled::border_t)
|
||||||
.border_l()
|
.border_l()
|
||||||
.border_color(cx.theme().colors().border)
|
.border_color(cx.theme().colors().border)
|
||||||
.children(self.end_children),
|
.children(self.end_children),
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use crate::{
|
|||||||
pane::{self, Pane},
|
pane::{self, Pane},
|
||||||
persistence::model::ItemId,
|
persistence::model::ItemId,
|
||||||
searchable::SearchableItemHandle,
|
searchable::SearchableItemHandle,
|
||||||
workspace_settings::{AutosaveSetting, WorkspaceSettings},
|
workspace_settings::{AutosaveSetting, TabBarPlacement, WorkspaceSettings},
|
||||||
DelayedDebouncedEditAction, FollowableItemBuilders, ItemNavHistory, ToolbarItemLocation,
|
DelayedDebouncedEditAction, FollowableItemBuilders, ItemNavHistory, ToolbarItemLocation,
|
||||||
ViewId, Workspace, WorkspaceId,
|
ViewId, Workspace, WorkspaceId,
|
||||||
};
|
};
|
||||||
@@ -36,7 +36,7 @@ use ui::Element as _;
|
|||||||
pub const LEADER_UPDATE_THROTTLE: Duration = Duration::from_millis(200);
|
pub const LEADER_UPDATE_THROTTLE: Duration = Duration::from_millis(200);
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct ItemSettings {
|
pub struct TabsSettings {
|
||||||
pub git_status: bool,
|
pub git_status: bool,
|
||||||
pub close_position: ClosePosition,
|
pub close_position: ClosePosition,
|
||||||
}
|
}
|
||||||
@@ -65,10 +65,10 @@ impl ClosePosition {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
||||||
pub struct ItemSettingsContent {
|
pub struct TabsSettingsContent {
|
||||||
/// Whether to show the Git file status on a tab item.
|
/// Whether to show the Git file status on a tab item.
|
||||||
///
|
///
|
||||||
/// Default: true
|
/// Default: false
|
||||||
git_status: Option<bool>,
|
git_status: Option<bool>,
|
||||||
/// Position of the close button in a tab.
|
/// Position of the close button in a tab.
|
||||||
///
|
///
|
||||||
@@ -89,10 +89,10 @@ pub struct PreviewTabsSettingsContent {
|
|||||||
enable_preview_from_file_finder: Option<bool>,
|
enable_preview_from_file_finder: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Settings for ItemSettings {
|
impl Settings for TabsSettings {
|
||||||
const KEY: Option<&'static str> = Some("tabs");
|
const KEY: Option<&'static str> = Some("tabs");
|
||||||
|
|
||||||
type FileContent = ItemSettingsContent;
|
type FileContent = TabsSettingsContent;
|
||||||
|
|
||||||
fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
|
fn load(sources: SettingsSources<Self::FileContent>, _: &mut AppContext) -> Result<Self> {
|
||||||
sources.json_merge()
|
sources.json_merge()
|
||||||
@@ -225,6 +225,10 @@ pub trait Item: FocusableView + EventEmitter<Self::Event> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tab_bar_placement(&self) -> TabBarPlacement {
|
||||||
|
TabBarPlacement::Top
|
||||||
|
}
|
||||||
|
|
||||||
fn breadcrumb_location(&self) -> ToolbarItemLocation {
|
fn breadcrumb_location(&self) -> ToolbarItemLocation {
|
||||||
ToolbarItemLocation::Hidden
|
ToolbarItemLocation::Hidden
|
||||||
}
|
}
|
||||||
@@ -320,6 +324,7 @@ pub trait ItemHandle: 'static + Send {
|
|||||||
callback: Box<dyn FnOnce(&mut AppContext) + Send>,
|
callback: Box<dyn FnOnce(&mut AppContext) + Send>,
|
||||||
) -> gpui::Subscription;
|
) -> gpui::Subscription;
|
||||||
fn to_searchable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>>;
|
fn to_searchable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>>;
|
||||||
|
fn tab_bar_placement(&self, cx: &AppContext) -> TabBarPlacement;
|
||||||
fn breadcrumb_location(&self, cx: &AppContext) -> ToolbarItemLocation;
|
fn breadcrumb_location(&self, cx: &AppContext) -> ToolbarItemLocation;
|
||||||
fn breadcrumbs(&self, theme: &Theme, cx: &AppContext) -> Option<Vec<BreadcrumbText>>;
|
fn breadcrumbs(&self, theme: &Theme, cx: &AppContext) -> Option<Vec<BreadcrumbText>>;
|
||||||
fn serialized_item_kind(&self) -> Option<&'static str>;
|
fn serialized_item_kind(&self) -> Option<&'static str>;
|
||||||
@@ -678,6 +683,10 @@ impl<T: Item> ItemHandle for View<T> {
|
|||||||
self.read(cx).as_searchable(self)
|
self.read(cx).as_searchable(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn tab_bar_placement(&self, cx: &AppContext) -> TabBarPlacement {
|
||||||
|
self.read(cx).tab_bar_placement()
|
||||||
|
}
|
||||||
|
|
||||||
fn breadcrumb_location(&self, cx: &AppContext) -> ToolbarItemLocation {
|
fn breadcrumb_location(&self, cx: &AppContext) -> ToolbarItemLocation {
|
||||||
self.read(cx).breadcrumb_location()
|
self.read(cx).breadcrumb_location()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
item::{
|
item::{
|
||||||
ClosePosition, Item, ItemHandle, ItemSettings, PreviewTabsSettings, TabContentParams,
|
ClosePosition, Item, ItemHandle, PreviewTabsSettings, TabContentParams, TabsSettings,
|
||||||
WeakItemHandle,
|
WeakItemHandle,
|
||||||
},
|
},
|
||||||
toolbar::Toolbar,
|
toolbar::Toolbar,
|
||||||
workspace_settings::{AutosaveSetting, TabBarSettings, WorkspaceSettings},
|
workspace_settings::{AutosaveSetting, TabBarPlacement, TabBarSettings, WorkspaceSettings},
|
||||||
NewCenterTerminal, NewFile, NewSearch, OpenInTerminal, OpenTerminal, OpenVisible,
|
NewCenterTerminal, NewFile, NewSearch, OpenInTerminal, OpenTerminal, OpenVisible,
|
||||||
SplitDirection, ToggleZoom, Workspace,
|
SplitDirection, ToggleZoom, Workspace,
|
||||||
};
|
};
|
||||||
@@ -1423,6 +1423,7 @@ impl Pane {
|
|||||||
ix: usize,
|
ix: usize,
|
||||||
item: &Box<dyn ItemHandle>,
|
item: &Box<dyn ItemHandle>,
|
||||||
detail: usize,
|
detail: usize,
|
||||||
|
tab_bar_placement: ui::TabBarPlacement,
|
||||||
cx: &mut ViewContext<'_, Pane>,
|
cx: &mut ViewContext<'_, Pane>,
|
||||||
) -> impl IntoElement {
|
) -> impl IntoElement {
|
||||||
let is_active = ix == self.active_item_index;
|
let is_active = ix == self.active_item_index;
|
||||||
@@ -1439,7 +1440,7 @@ impl Pane {
|
|||||||
},
|
},
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
let close_side = &ItemSettings::get_global(cx).close_position;
|
let close_side = &TabsSettings::get_global(cx).close_position;
|
||||||
let indicator = render_item_indicator(item.boxed_clone(), cx);
|
let indicator = render_item_indicator(item.boxed_clone(), cx);
|
||||||
let item_id = item.item_id();
|
let item_id = item.item_id();
|
||||||
let is_first_item = ix == 0;
|
let is_first_item = ix == 0;
|
||||||
@@ -1447,6 +1448,7 @@ impl Pane {
|
|||||||
let position_relative_to_active_item = ix.cmp(&self.active_item_index);
|
let position_relative_to_active_item = ix.cmp(&self.active_item_index);
|
||||||
|
|
||||||
let tab = Tab::new(ix)
|
let tab = Tab::new(ix)
|
||||||
|
.tab_bar_placement(tab_bar_placement)
|
||||||
.position(if is_first_item {
|
.position(if is_first_item {
|
||||||
TabPosition::First
|
TabPosition::First
|
||||||
} else if is_last_item {
|
} else if is_last_item {
|
||||||
@@ -1659,8 +1661,20 @@ impl Pane {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_tab_bar(&mut self, cx: &mut ViewContext<'_, Pane>) -> impl IntoElement {
|
fn need_tab_bar_at(&self, placement: TabBarPlacement, cx: &mut ViewContext<'_, Pane>) -> bool {
|
||||||
|
let Some(item) = self.active_item() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
item.tab_bar_placement(cx) == placement
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_tab_bar(
|
||||||
|
&mut self,
|
||||||
|
placement: ui::TabBarPlacement,
|
||||||
|
cx: &mut ViewContext<'_, Pane>,
|
||||||
|
) -> impl IntoElement {
|
||||||
TabBar::new("tab_bar")
|
TabBar::new("tab_bar")
|
||||||
|
.placement(placement)
|
||||||
.track_scroll(self.tab_bar_scroll_handle.clone())
|
.track_scroll(self.tab_bar_scroll_handle.clone())
|
||||||
.when(
|
.when(
|
||||||
self.display_nav_history_buttons.unwrap_or_default(),
|
self.display_nav_history_buttons.unwrap_or_default(),
|
||||||
@@ -1704,7 +1718,7 @@ impl Pane {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.zip(tab_details(&self.items, cx))
|
.zip(tab_details(&self.items, cx))
|
||||||
.map(|((ix, item), detail)| self.render_tab(ix, item, detail, cx)),
|
.map(|((ix, item), detail)| self.render_tab(ix, item, detail, placement, cx)),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
@@ -2042,8 +2056,8 @@ impl Render for Pane {
|
|||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.when(self.active_item().is_some(), |pane| {
|
.when(self.need_tab_bar_at(TabBarPlacement::Top, cx), |pane| {
|
||||||
pane.child(self.render_tab_bar(cx))
|
pane.child(self.render_tab_bar(ui::TabBarPlacement::Top, cx))
|
||||||
})
|
})
|
||||||
.child({
|
.child({
|
||||||
let has_worktrees = self.project.read(cx).worktrees().next().is_some();
|
let has_worktrees = self.project.read(cx).worktrees().next().is_some();
|
||||||
@@ -2113,6 +2127,9 @@ impl Render for Pane {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
.when(self.need_tab_bar_at(TabBarPlacement::Bottom, cx), |pane| {
|
||||||
|
pane.child(self.render_tab_bar(ui::TabBarPlacement::Bottom, cx))
|
||||||
|
})
|
||||||
.on_mouse_down(
|
.on_mouse_down(
|
||||||
MouseButton::Navigate(NavigationDirection::Back),
|
MouseButton::Navigate(NavigationDirection::Back),
|
||||||
cx.listener(|pane, _, cx| {
|
cx.listener(|pane, _, cx| {
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ use gpui::{
|
|||||||
Size, Subscription, Task, View, WeakView, WindowHandle, WindowOptions,
|
Size, Subscription, Task, View, WeakView, WindowHandle, WindowOptions,
|
||||||
};
|
};
|
||||||
use item::{
|
use item::{
|
||||||
FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, PreviewTabsSettings,
|
FollowableItem, FollowableItemHandle, Item, ItemHandle, PreviewTabsSettings, ProjectItem,
|
||||||
ProjectItem,
|
TabsSettings,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use language::{LanguageRegistry, Rope};
|
use language::{LanguageRegistry, Rope};
|
||||||
@@ -85,7 +85,7 @@ use ui::{
|
|||||||
use util::{maybe, ResultExt};
|
use util::{maybe, ResultExt};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
pub use workspace_settings::{
|
pub use workspace_settings::{
|
||||||
AutosaveSetting, RestoreOnStartupBehaviour, TabBarSettings, WorkspaceSettings,
|
AutosaveSetting, RestoreOnStartupBehaviour, TabBarPlacement, TabBarSettings, WorkspaceSettings,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::notifications::NotificationId;
|
use crate::notifications::NotificationId;
|
||||||
@@ -265,7 +265,8 @@ impl Column for WorkspaceId {
|
|||||||
}
|
}
|
||||||
pub fn init_settings(cx: &mut AppContext) {
|
pub fn init_settings(cx: &mut AppContext) {
|
||||||
WorkspaceSettings::register(cx);
|
WorkspaceSettings::register(cx);
|
||||||
ItemSettings::register(cx);
|
TabsSettings::register(cx);
|
||||||
|
TabsSettings::register(cx);
|
||||||
PreviewTabsSettings::register(cx);
|
PreviewTabsSettings::register(cx);
|
||||||
TabBarSettings::register(cx);
|
TabBarSettings::register(cx);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,13 +58,30 @@ pub struct WorkspaceSettingsContent {
|
|||||||
pub drop_target_size: Option<f32>,
|
pub drop_target_size: Option<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The tab bar placement in a pane.
|
||||||
|
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum TabBarPlacement {
|
||||||
|
/// Don't show tab bar.
|
||||||
|
No,
|
||||||
|
/// Place tab bar on top of the pane.
|
||||||
|
Top,
|
||||||
|
/// Place tab bar at the bottom of the pane.
|
||||||
|
Bottom,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct TabBarSettings {
|
pub struct TabBarSettings {
|
||||||
|
pub placement: TabBarPlacement,
|
||||||
pub show_nav_history_buttons: bool,
|
pub show_nav_history_buttons: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
|
||||||
pub struct TabBarSettingsContent {
|
pub struct TabBarSettingsContent {
|
||||||
|
/// Where to place tab bar in the editor.
|
||||||
|
///
|
||||||
|
/// Default: top
|
||||||
|
pub placement: Option<TabBarPlacement>,
|
||||||
/// Whether or not to show the navigation history buttons in the tab bar.
|
/// Whether or not to show the navigation history buttons in the tab bar.
|
||||||
///
|
///
|
||||||
/// Default: true
|
/// Default: true
|
||||||
|
|||||||
@@ -304,6 +304,104 @@ List of `string` values
|
|||||||
|
|
||||||
`boolean` values
|
`boolean` values
|
||||||
|
|
||||||
|
## Editor Tab Bar
|
||||||
|
|
||||||
|
- Description: Settings related to the editor's tab bar.
|
||||||
|
- Settings: `tab_bar`
|
||||||
|
- Default:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"tab_bar": {
|
||||||
|
"placement": "top",
|
||||||
|
"show_nav_history_buttons": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Placement
|
||||||
|
|
||||||
|
- Description: Where to place the editor tab bar.
|
||||||
|
- Setting: `placement`
|
||||||
|
- Default: `top`
|
||||||
|
|
||||||
|
**Options**
|
||||||
|
|
||||||
|
1. Place the tab bar on top of the editor:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"placement": "top"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Place the tab bar at the bottom of the editor:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"placement": "bottom"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Hide the tab bar:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"placement": "no"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Navigation History Buttons
|
||||||
|
|
||||||
|
- Description: Whether to show the navigation history buttons.
|
||||||
|
- Setting: `show_nav_history_buttons`
|
||||||
|
- Default: `true`
|
||||||
|
|
||||||
|
**Options**
|
||||||
|
|
||||||
|
`boolean` values
|
||||||
|
|
||||||
|
## Editor Tabs
|
||||||
|
|
||||||
|
- Description: Configuration for the editor tabs.
|
||||||
|
- Setting: `tabs`
|
||||||
|
- Default:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"tabs": {
|
||||||
|
"close_position": "right",
|
||||||
|
"git_status": false
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
### Close Position
|
||||||
|
|
||||||
|
- Description: Where to display close button within a tab.
|
||||||
|
- Setting: `close_position`
|
||||||
|
- Default: `right`
|
||||||
|
|
||||||
|
**Options**
|
||||||
|
|
||||||
|
1. Display the close button on the right:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"close_position": "right"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Display the close button on the left:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"close_position": "left"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Git Status
|
||||||
|
|
||||||
|
- Description: Whether or not to show Git file status in tab.
|
||||||
|
- Setting: `git_status`
|
||||||
|
- Default: `false`
|
||||||
|
|
||||||
## Editor Toolbar
|
## Editor Toolbar
|
||||||
|
|
||||||
- Description: Whether or not to show various elements in the editor toolbar.
|
- Description: Whether or not to show various elements in the editor toolbar.
|
||||||
|
|||||||
Reference in New Issue
Block a user