Merge branch 'main' into vim-search

This commit is contained in:
Conrad Irwin 2023-07-19 09:48:25 -06:00
commit 98b8008bcc
48 changed files with 2447 additions and 968 deletions

View file

@ -10,6 +10,9 @@ use gpui::{
ViewContext, ViewHandle, WeakViewHandle, WindowContext,
};
use project::{Project, ProjectEntryId, ProjectPath};
use schemars::JsonSchema;
use serde_derive::{Deserialize, Serialize};
use settings::Setting;
use smallvec::SmallVec;
use std::{
any::{Any, TypeId},
@ -27,6 +30,49 @@ use std::{
};
use theme::Theme;
#[derive(Deserialize)]
pub struct ItemSettings {
pub git_status: bool,
pub close_position: ClosePosition,
}
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum ClosePosition {
Left,
#[default]
Right,
}
impl ClosePosition {
pub fn right(&self) -> bool {
match self {
ClosePosition::Left => false,
ClosePosition::Right => true,
}
}
}
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
pub struct ItemSettingsContent {
git_status: Option<bool>,
close_position: Option<ClosePosition>,
}
impl Setting for ItemSettings {
const KEY: Option<&'static str> = Some("tabs");
type FileContent = ItemSettingsContent;
fn load(
default_value: &Self::FileContent,
user_values: &[&Self::FileContent],
_: &gpui::AppContext,
) -> anyhow::Result<Self> {
Self::load_via_json_merge(default_value, user_values)
}
}
#[derive(Eq, PartialEq, Hash, Debug)]
pub enum ItemEvent {
CloseItem,

View file

@ -3,14 +3,16 @@ mod dragged_item_receiver;
use super::{ItemHandle, SplitDirection};
pub use crate::toolbar::Toolbar;
use crate::{
item::WeakItemHandle, notify_of_new_dock, AutosaveSetting, Item, NewCenterTerminal, NewFile,
NewSearch, ToggleZoom, Workspace, WorkspaceSettings,
item::{ItemSettings, WeakItemHandle},
notify_of_new_dock, AutosaveSetting, Item, NewCenterTerminal, NewFile, NewSearch, ToggleZoom,
Workspace, WorkspaceSettings,
};
use anyhow::Result;
use collections::{HashMap, HashSet, VecDeque};
use context_menu::{ContextMenu, ContextMenuItem};
use drag_and_drop::{DragAndDrop, Draggable};
use dragged_item_receiver::dragged_item_receiver;
use fs::repository::GitFileStatus;
use futures::StreamExt;
use gpui::{
actions,
@ -866,6 +868,7 @@ impl Pane {
.paths_by_item
.get(&item.id())
.and_then(|(_, abs_path)| abs_path.clone());
self.nav_history
.0
.borrow_mut()
@ -1157,6 +1160,11 @@ impl Pane {
.zip(self.tab_details(cx))
.enumerate()
{
let git_status = item
.project_path(cx)
.and_then(|path| self.project.read(cx).entry_for_path(&path, cx))
.and_then(|entry| entry.git_status());
let detail = if detail == 0 { None } else { Some(detail) };
let tab_active = ix == self.active_item_index;
@ -1174,9 +1182,21 @@ impl Pane {
let tab_tooltip_text =
item.tab_tooltip_text(cx).map(|text| text.into_owned());
let mut tab_style = theme
.workspace
.tab_bar
.tab_style(pane_active, tab_active)
.clone();
let should_show_status = settings::get::<ItemSettings>(cx).git_status;
if should_show_status && git_status != None {
tab_style.label.text.color = match git_status.unwrap() {
GitFileStatus::Added => tab_style.git.inserted,
GitFileStatus::Modified => tab_style.git.modified,
GitFileStatus::Conflict => tab_style.git.conflict,
};
}
move |mouse_state, cx| {
let tab_style =
theme.workspace.tab_bar.tab_style(pane_active, tab_active);
let hovered = mouse_state.hovered();
enum Tab {}
@ -1188,7 +1208,7 @@ impl Pane {
ix == 0,
detail,
hovered,
tab_style,
&tab_style,
cx,
)
})
@ -1350,81 +1370,94 @@ impl Pane {
container.border.left = false;
}
Flex::row()
.with_child({
let diameter = 7.0;
let icon_color = if item.has_conflict(cx) {
Some(tab_style.icon_conflict)
} else if item.is_dirty(cx) {
Some(tab_style.icon_dirty)
} else {
None
};
let buffer_jewel_element = {
let diameter = 7.0;
let icon_color = if item.has_conflict(cx) {
Some(tab_style.icon_conflict)
} else if item.is_dirty(cx) {
Some(tab_style.icon_dirty)
} else {
None
};
Canvas::new(move |scene, bounds, _, _, _| {
if let Some(color) = icon_color {
let square = RectF::new(bounds.origin(), vec2f(diameter, diameter));
scene.push_quad(Quad {
bounds: square,
background: Some(color),
border: Default::default(),
corner_radius: diameter / 2.,
});
}
})
.constrained()
.with_width(diameter)
.with_height(diameter)
.aligned()
Canvas::new(move |scene, bounds, _, _, _| {
if let Some(color) = icon_color {
let square = RectF::new(bounds.origin(), vec2f(diameter, diameter));
scene.push_quad(Quad {
bounds: square,
background: Some(color),
border: Default::default(),
corner_radius: diameter / 2.,
});
}
})
.with_child(title.aligned().contained().with_style(ContainerStyle {
margin: Margin {
left: tab_style.spacing,
right: tab_style.spacing,
..Default::default()
},
.constrained()
.with_width(diameter)
.with_height(diameter)
.aligned()
};
let title_element = title.aligned().contained().with_style(ContainerStyle {
margin: Margin {
left: tab_style.spacing,
right: tab_style.spacing,
..Default::default()
}))
.with_child(
if hovered {
let item_id = item.id();
enum TabCloseButton {}
let icon = Svg::new("icons/x_mark_8.svg");
MouseEventHandler::<TabCloseButton, _>::new(item_id, cx, |mouse_state, _| {
if mouse_state.hovered() {
icon.with_color(tab_style.icon_close_active)
} else {
icon.with_color(tab_style.icon_close)
}
})
.with_padding(Padding::uniform(4.))
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, {
let pane = pane.clone();
move |_, _, cx| {
let pane = pane.clone();
cx.window_context().defer(move |cx| {
if let Some(pane) = pane.upgrade(cx) {
pane.update(cx, |pane, cx| {
pane.close_item_by_id(item_id, cx).detach_and_log_err(cx);
});
}
},
..Default::default()
});
let close_element = if hovered {
let item_id = item.id();
enum TabCloseButton {}
let icon = Svg::new("icons/x_mark_8.svg");
MouseEventHandler::<TabCloseButton, _>::new(item_id, cx, |mouse_state, _| {
if mouse_state.hovered() {
icon.with_color(tab_style.icon_close_active)
} else {
icon.with_color(tab_style.icon_close)
}
})
.with_padding(Padding::uniform(4.))
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, {
let pane = pane.clone();
move |_, _, cx| {
let pane = pane.clone();
cx.window_context().defer(move |cx| {
if let Some(pane) = pane.upgrade(cx) {
pane.update(cx, |pane, cx| {
pane.close_item_by_id(item_id, cx).detach_and_log_err(cx);
});
}
})
.into_any_named("close-tab-icon")
.constrained()
} else {
Empty::new().constrained()
});
}
.with_width(tab_style.close_icon_width)
.aligned(),
)
.contained()
.with_style(container)
})
.into_any_named("close-tab-icon")
.constrained()
.with_height(tab_style.height)
.into_any()
} else {
Empty::new().constrained()
}
.with_width(tab_style.close_icon_width)
.aligned();
let close_right = settings::get::<ItemSettings>(cx).close_position.right();
if close_right {
Flex::row()
.with_child(buffer_jewel_element)
.with_child(title_element)
.with_child(close_element)
} else {
Flex::row()
.with_child(close_element)
.with_child(title_element)
.with_child(buffer_jewel_element)
}
.contained()
.with_style(container)
.constrained()
.with_height(tab_style.height)
.into_any()
}
pub fn render_tab_bar_button<

View file

@ -203,6 +203,7 @@ pub type WorkspaceId = i64;
pub fn init_settings(cx: &mut AppContext) {
settings::register::<WorkspaceSettings>(cx);
settings::register::<item::ItemSettings>(cx);
}
pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {