Compare commits
14 Commits
mcp2
...
add-git-pa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d95267b88a | ||
|
|
c7641b31e0 | ||
|
|
18c41e79d8 | ||
|
|
2367ffdd49 | ||
|
|
64552b964c | ||
|
|
5779773232 | ||
|
|
8afa3638a4 | ||
|
|
66bb55087e | ||
|
|
1918c72d83 | ||
|
|
8e890c8520 | ||
|
|
c741298fff | ||
|
|
446e64fde7 | ||
|
|
c01a039853 | ||
|
|
980f78524e |
@@ -41,7 +41,8 @@ use language_model::{
|
||||
use menu::{Confirm, SecondaryConfirm, SelectFirst, SelectLast, SelectNext, SelectPrevious};
|
||||
use multi_buffer::ExcerptInfo;
|
||||
use panel::{
|
||||
panel_editor_container, panel_editor_style, panel_filled_button, panel_icon_button, PanelHeader,
|
||||
panel_button, panel_editor_container, panel_editor_style, panel_filled_button,
|
||||
panel_icon_button, PanelHeader,
|
||||
};
|
||||
use project::{
|
||||
git::{GitEvent, Repository},
|
||||
@@ -198,6 +199,21 @@ pub struct GitStatusEntry {
|
||||
pub(crate) staging: StageStatus,
|
||||
}
|
||||
|
||||
impl GitStatusEntry {
|
||||
fn display_name(&self) -> String {
|
||||
self.worktree_path
|
||||
.file_name()
|
||||
.map(|name| name.to_string_lossy().into_owned())
|
||||
.unwrap_or_else(|| self.worktree_path.to_string_lossy().into_owned())
|
||||
}
|
||||
|
||||
fn parent_dir(&self) -> Option<String> {
|
||||
self.worktree_path
|
||||
.parent()
|
||||
.map(|parent| parent.to_string_lossy().into_owned())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
enum TargetStatus {
|
||||
Staged,
|
||||
@@ -239,7 +255,9 @@ pub struct GitPanel {
|
||||
pending_serialization: Task<Option<()>>,
|
||||
pub(crate) project: Entity<Project>,
|
||||
scroll_handle: UniformListScrollHandle,
|
||||
scrollbar_state: ScrollbarState,
|
||||
vertical_scrollbar_state: ScrollbarState,
|
||||
horizontal_scrollbar_state: ScrollbarState,
|
||||
max_width_item_index: Option<usize>,
|
||||
selected_entry: Option<usize>,
|
||||
marked_entries: Vec<usize>,
|
||||
show_scrollbar: bool,
|
||||
@@ -346,7 +364,9 @@ impl GitPanel {
|
||||
)
|
||||
.detach();
|
||||
|
||||
let scrollbar_state =
|
||||
let vertical_scrollbar_state =
|
||||
ScrollbarState::new(scroll_handle.clone()).parent_entity(&cx.entity());
|
||||
let horizontal_scrollbar_state =
|
||||
ScrollbarState::new(scroll_handle.clone()).parent_entity(&cx.entity());
|
||||
|
||||
let mut git_panel = Self {
|
||||
@@ -372,7 +392,9 @@ impl GitPanel {
|
||||
single_tracked_entry: None,
|
||||
project,
|
||||
scroll_handle,
|
||||
scrollbar_state,
|
||||
vertical_scrollbar_state,
|
||||
horizontal_scrollbar_state,
|
||||
max_width_item_index: None,
|
||||
selected_entry: None,
|
||||
marked_entries: Vec::new(),
|
||||
show_scrollbar: false,
|
||||
@@ -1994,6 +2016,7 @@ impl GitPanel {
|
||||
let mut conflict_entries = Vec::new();
|
||||
let mut last_staged = None;
|
||||
let mut staged_count = 0;
|
||||
let mut max_width_item: Option<(RepoPath, usize)> = None;
|
||||
|
||||
let Some(repo) = self.active_repository.as_ref() else {
|
||||
// Just clear entries if no repository is active.
|
||||
@@ -2039,6 +2062,21 @@ impl GitPanel {
|
||||
last_staged = Some(entry.clone());
|
||||
}
|
||||
|
||||
let width_estimate = Self::item_width_estimate(
|
||||
entry.parent_dir().map(|s| s.len()).unwrap_or(0),
|
||||
entry.display_name().len(),
|
||||
);
|
||||
|
||||
match max_width_item.as_mut() {
|
||||
Some((repo_path, estimate)) => {
|
||||
if width_estimate > *estimate {
|
||||
*repo_path = entry.repo_path.clone();
|
||||
*estimate = width_estimate;
|
||||
}
|
||||
}
|
||||
None => max_width_item = Some((entry.repo_path.clone(), width_estimate)),
|
||||
}
|
||||
|
||||
if is_conflict {
|
||||
conflict_entries.push(entry);
|
||||
} else if is_new {
|
||||
@@ -2111,6 +2149,15 @@ impl GitPanel {
|
||||
.extend(new_entries.into_iter().map(GitListEntry::GitStatusEntry));
|
||||
}
|
||||
|
||||
if let Some((repo_path, _)) = max_width_item {
|
||||
self.max_width_item_index = self.entries.iter().position(|entry| match entry {
|
||||
GitListEntry::GitStatusEntry(git_status_entry) => {
|
||||
git_status_entry.repo_path == repo_path
|
||||
}
|
||||
GitListEntry::Header(_) => false,
|
||||
});
|
||||
}
|
||||
|
||||
self.update_counts(repo);
|
||||
|
||||
self.select_first_entry_if_none(cx);
|
||||
@@ -2272,6 +2319,12 @@ impl GitPanel {
|
||||
self.has_staged_changes()
|
||||
}
|
||||
|
||||
// eventually we'll need to take depth into account here
|
||||
// if we add a tree view
|
||||
fn item_width_estimate(path: usize, file_name: usize) -> usize {
|
||||
path + file_name
|
||||
}
|
||||
|
||||
pub(crate) fn render_generate_commit_message_button(
|
||||
&self,
|
||||
cx: &Context<Self>,
|
||||
@@ -2422,8 +2475,10 @@ impl GitPanel {
|
||||
}
|
||||
|
||||
self.panel_header_container(window, cx)
|
||||
.px_2()
|
||||
.child(
|
||||
Button::new("diff", "Open diff")
|
||||
panel_button("Open Diff")
|
||||
.color(Color::Muted)
|
||||
.tooltip(Tooltip::for_action_title("Open diff", &Diff))
|
||||
.on_click(|_, _, cx| {
|
||||
cx.defer(|cx| {
|
||||
@@ -2433,7 +2488,7 @@ impl GitPanel {
|
||||
)
|
||||
.child(div().flex_grow()) // spacer
|
||||
.child(
|
||||
Button::new("stage-unstage-all", text)
|
||||
panel_filled_button(text)
|
||||
.tooltip(Tooltip::for_action_title(tooltip, action.as_ref()))
|
||||
.on_click(move |_, _, cx| {
|
||||
let action = action.boxed_clone();
|
||||
@@ -2586,15 +2641,14 @@ impl GitPanel {
|
||||
.items_center()
|
||||
.py_2()
|
||||
.px(px(8.))
|
||||
// .bg(cx.theme().colors().background)
|
||||
// .border_t_1()
|
||||
.border_color(cx.theme().colors().border)
|
||||
.gap_1p5()
|
||||
.child(
|
||||
div()
|
||||
.flex_grow()
|
||||
.overflow_hidden()
|
||||
.max_w(relative(0.6))
|
||||
.items_center()
|
||||
.max_w(relative(0.85))
|
||||
.h_full()
|
||||
.child(
|
||||
Label::new(commit.subject.clone())
|
||||
@@ -2658,12 +2712,12 @@ impl GitPanel {
|
||||
)
|
||||
}
|
||||
|
||||
fn render_scrollbar(&self, cx: &mut Context<Self>) -> Option<Stateful<Div>> {
|
||||
fn render_vertical_scrollbar(&self, cx: &mut Context<Self>) -> Option<Stateful<Div>> {
|
||||
let scroll_bar_style = self.show_scrollbar(cx);
|
||||
let show_container = matches!(scroll_bar_style, ShowScrollbar::Always);
|
||||
|
||||
if !self.should_show_scrollbar(cx)
|
||||
|| !(self.show_scrollbar || self.scrollbar_state.is_dragging())
|
||||
|| !(self.show_scrollbar || self.vertical_scrollbar_state.is_dragging())
|
||||
{
|
||||
return None;
|
||||
}
|
||||
@@ -2692,7 +2746,7 @@ impl GitPanel {
|
||||
.on_mouse_up(
|
||||
MouseButton::Left,
|
||||
cx.listener(|this, _, window, cx| {
|
||||
if !this.scrollbar_state.is_dragging()
|
||||
if !this.vertical_scrollbar_state.is_dragging()
|
||||
&& !this.focus_handle.contains_focused(window, cx)
|
||||
{
|
||||
this.hide_scrollbar(window, cx);
|
||||
@@ -2707,7 +2761,79 @@ impl GitPanel {
|
||||
}))
|
||||
.children(Scrollbar::vertical(
|
||||
// percentage as f32..end_offset as f32,
|
||||
self.scrollbar_state.clone(),
|
||||
self.vertical_scrollbar_state.clone(),
|
||||
)),
|
||||
)
|
||||
}
|
||||
|
||||
fn render_horizontal_scrollbar(&self, cx: &mut Context<Self>) -> Option<Stateful<Div>> {
|
||||
let scroll_bar_style = self.show_scrollbar(cx);
|
||||
let show_container = matches!(scroll_bar_style, ShowScrollbar::Always);
|
||||
|
||||
// if !self.should_show_scrollbar(cx)
|
||||
// || !(self.show_scrollbar || self.horizontal_scrollbar_state.is_dragging())
|
||||
// {
|
||||
// return None;
|
||||
// }
|
||||
|
||||
let scroll_handle = self.scroll_handle.0.borrow();
|
||||
dbg!(scroll_handle.last_item_size);
|
||||
// let longest_item_width = dbg!(scroll_handle.last_item_size)
|
||||
// .filter(|size| dbg!(px(10.) * size.contents.width > size.item.width))?
|
||||
// .contents
|
||||
// .width
|
||||
// .0 as f64;
|
||||
|
||||
// println!("Longest item width: {}", longest_item_width);
|
||||
// if longest_item_width < scroll_handle.base_handle.bounds().size.width.0 as f64 {
|
||||
// return None;
|
||||
// }
|
||||
|
||||
Some(
|
||||
div()
|
||||
.id("git-panel-horizontal-scroll")
|
||||
.occlude()
|
||||
.flex_none()
|
||||
.w_full()
|
||||
.cursor_default()
|
||||
.absolute()
|
||||
.bottom_1()
|
||||
.left_1()
|
||||
.right_1()
|
||||
.h(px(32.))
|
||||
// .when(show_container, |this| this.pt_1().pb_1p5())
|
||||
// .when(!show_container, |this| {
|
||||
// this.bottom_1().left_1().right_1().h(px(32.))
|
||||
// })
|
||||
.on_mouse_move(cx.listener(|_, _, _, cx| {
|
||||
cx.notify();
|
||||
cx.stop_propagation()
|
||||
}))
|
||||
.on_hover(|_, _, cx| {
|
||||
cx.stop_propagation();
|
||||
})
|
||||
.on_any_mouse_down(|_, _, cx| {
|
||||
cx.stop_propagation();
|
||||
})
|
||||
.on_mouse_up(
|
||||
MouseButton::Left,
|
||||
cx.listener(|this, _, window, cx| {
|
||||
if !this.horizontal_scrollbar_state.is_dragging()
|
||||
&& !this.focus_handle.contains_focused(window, cx)
|
||||
{
|
||||
this.hide_scrollbar(window, cx);
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
cx.stop_propagation();
|
||||
}),
|
||||
)
|
||||
.on_scroll_wheel(cx.listener(|_, _, _, cx| {
|
||||
cx.notify();
|
||||
}))
|
||||
.children(Scrollbar::horizontal(
|
||||
// percentage as f32..end_offset as f32,
|
||||
self.horizontal_scrollbar_state.clone(),
|
||||
)),
|
||||
)
|
||||
}
|
||||
@@ -2764,8 +2890,10 @@ impl GitPanel {
|
||||
let entry_count = self.entries.len();
|
||||
|
||||
h_flex()
|
||||
// .debug_below()
|
||||
.flex_1()
|
||||
.size_full()
|
||||
.flex_grow()
|
||||
.relative()
|
||||
.overflow_hidden()
|
||||
.child(
|
||||
uniform_list(cx.entity().clone(), "entries", entry_count, {
|
||||
@@ -2800,8 +2928,10 @@ impl GitPanel {
|
||||
}
|
||||
})
|
||||
.size_full()
|
||||
.flex_grow()
|
||||
.with_sizing_behavior(ListSizingBehavior::Auto)
|
||||
.with_horizontal_sizing_behavior(ListHorizontalSizingBehavior::Unconstrained)
|
||||
.with_width_from_item(self.max_width_item_index)
|
||||
.track_scroll(self.scroll_handle.clone()),
|
||||
)
|
||||
.on_mouse_down(
|
||||
@@ -2810,7 +2940,8 @@ impl GitPanel {
|
||||
this.deploy_panel_context_menu(event.position, window, cx)
|
||||
}),
|
||||
)
|
||||
.children(self.render_scrollbar(cx))
|
||||
// .children(self.render_vertical_scrollbar(cx))
|
||||
.children(self.render_horizontal_scrollbar(cx))
|
||||
}
|
||||
|
||||
fn entry_label(&self, label: impl Into<SharedString>, color: Color) -> Label {
|
||||
@@ -2936,17 +3067,16 @@ impl GitPanel {
|
||||
window: &Window,
|
||||
cx: &Context<Self>,
|
||||
) -> AnyElement {
|
||||
let display_name = entry
|
||||
.worktree_path
|
||||
.file_name()
|
||||
.map(|name| name.to_string_lossy().into_owned())
|
||||
.unwrap_or_else(|| entry.worktree_path.to_string_lossy().into_owned());
|
||||
let display_name = entry.display_name();
|
||||
|
||||
let worktree_path = entry.worktree_path.clone();
|
||||
let selected = self.selected_entry == Some(ix);
|
||||
let marked = self.marked_entries.contains(&ix);
|
||||
let status_style = GitPanelSettings::get_global(cx).status_style;
|
||||
let status = entry.status;
|
||||
let modifiers = self.current_modifiers;
|
||||
let shift_held = modifiers.shift;
|
||||
|
||||
let has_conflict = status.is_conflicted();
|
||||
let is_modified = status.is_modified();
|
||||
let is_deleted = status.is_deleted();
|
||||
@@ -3030,9 +3160,8 @@ impl GitPanel {
|
||||
el.border_color(cx.theme().colors().border_focused)
|
||||
})
|
||||
.px(rems(0.75)) // ~12px
|
||||
.overflow_hidden()
|
||||
.flex_none()
|
||||
.gap(DynamicSpacing::Base04.rems(cx))
|
||||
// .flex_none()
|
||||
.gap_1p5()
|
||||
.bg(base_bg)
|
||||
.hover(|this| this.bg(hover_bg))
|
||||
.active(|this| this.bg(active_bg))
|
||||
@@ -3077,6 +3206,7 @@ impl GitPanel {
|
||||
.flex_none()
|
||||
.occlude()
|
||||
.cursor_pointer()
|
||||
.ml_neg_0p5()
|
||||
.child(
|
||||
Checkbox::new(checkbox_id, is_staged)
|
||||
.disabled(!has_write_access)
|
||||
@@ -3098,26 +3228,44 @@ impl GitPanel {
|
||||
})
|
||||
})
|
||||
.tooltip(move |window, cx| {
|
||||
let tooltip_name = if entry_staging.is_fully_staged() {
|
||||
"Unstage"
|
||||
let is_staged = entry_staging.is_fully_staged();
|
||||
|
||||
let action = if is_staged { "Unstage" } else { "Stage" };
|
||||
let tooltip_name = if shift_held {
|
||||
format!("{} section", action)
|
||||
} else {
|
||||
"Stage"
|
||||
action.to_string()
|
||||
};
|
||||
|
||||
Tooltip::for_action(tooltip_name, &ToggleStaged, window, cx)
|
||||
let meta = if shift_held {
|
||||
format!(
|
||||
"Release shift to {} single entry",
|
||||
action.to_lowercase()
|
||||
)
|
||||
} else {
|
||||
format!("Shift click to {} section", action.to_lowercase())
|
||||
};
|
||||
|
||||
Tooltip::with_meta(
|
||||
tooltip_name,
|
||||
Some(&ToggleStaged),
|
||||
meta,
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(git_status_icon(status, cx))
|
||||
.child(git_status_icon(status))
|
||||
.child(
|
||||
h_flex()
|
||||
.items_center()
|
||||
.overflow_hidden()
|
||||
.when_some(worktree_path.parent(), |this, parent| {
|
||||
let parent_str = parent.to_string_lossy();
|
||||
if !parent_str.is_empty() {
|
||||
.flex_1()
|
||||
// .overflow_hidden()
|
||||
.when_some(entry.parent_dir(), |this, parent| {
|
||||
if !parent.is_empty() {
|
||||
this.child(
|
||||
self.entry_label(format!("{}/", parent_str), path_color)
|
||||
self.entry_label(format!("{}/", parent), path_color)
|
||||
.when(status.is_deleted(), |this| this.strikethrough()),
|
||||
)
|
||||
} else {
|
||||
@@ -3516,7 +3664,11 @@ impl RenderOnce for PanelRepoFooter {
|
||||
div().child(
|
||||
Icon::new(IconName::GitBranchSmall)
|
||||
.size(IconSize::Small)
|
||||
.color(Color::Muted),
|
||||
.color(if single_repo {
|
||||
Color::Disabled
|
||||
} else {
|
||||
Color::Muted
|
||||
}),
|
||||
),
|
||||
)
|
||||
.child(repo_selector)
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use ::settings::Settings;
|
||||
use git::{
|
||||
repository::{Branch, Upstream, UpstreamTracking, UpstreamTrackingStatus},
|
||||
status::FileStatus,
|
||||
status::{FileStatus, StatusCode, UnmergedStatus, UnmergedStatusCode},
|
||||
};
|
||||
use git_panel_settings::GitPanelSettings;
|
||||
use gpui::{App, Entity, FocusHandle};
|
||||
use project::Project;
|
||||
use project_diff::ProjectDiff;
|
||||
use ui::{ActiveTheme, Color, Icon, IconName, IntoElement, SharedString};
|
||||
use ui::prelude::*;
|
||||
use workspace::Workspace;
|
||||
|
||||
mod askpass_modal;
|
||||
@@ -84,30 +84,8 @@ pub fn init(cx: &mut App) {
|
||||
.detach();
|
||||
}
|
||||
|
||||
// TODO: Add updated status colors to theme
|
||||
pub fn git_status_icon(status: FileStatus, cx: &App) -> impl IntoElement {
|
||||
let (icon_name, color) = if status.is_conflicted() {
|
||||
(
|
||||
IconName::Warning,
|
||||
cx.theme().colors().version_control_conflict,
|
||||
)
|
||||
} else if status.is_deleted() {
|
||||
(
|
||||
IconName::SquareMinus,
|
||||
cx.theme().colors().version_control_deleted,
|
||||
)
|
||||
} else if status.is_modified() {
|
||||
(
|
||||
IconName::SquareDot,
|
||||
cx.theme().colors().version_control_modified,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
IconName::SquarePlus,
|
||||
cx.theme().colors().version_control_added,
|
||||
)
|
||||
};
|
||||
Icon::new(icon_name).color(Color::Custom(color))
|
||||
pub fn git_status_icon(status: FileStatus) -> impl IntoElement {
|
||||
GitStatusIcon::new(status)
|
||||
}
|
||||
|
||||
fn can_push_and_pull(project: &Entity<Project>, cx: &App) -> bool {
|
||||
@@ -449,3 +427,79 @@ mod remote_button {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(IntoElement, IntoComponent)]
|
||||
#[component(scope = "Version Control")]
|
||||
pub struct GitStatusIcon {
|
||||
status: FileStatus,
|
||||
}
|
||||
|
||||
impl GitStatusIcon {
|
||||
pub fn new(status: FileStatus) -> Self {
|
||||
Self { status }
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for GitStatusIcon {
|
||||
fn render(self, _window: &mut ui::Window, cx: &mut App) -> impl IntoElement {
|
||||
let status = self.status;
|
||||
|
||||
let (icon_name, color) = if status.is_conflicted() {
|
||||
(
|
||||
IconName::Warning,
|
||||
cx.theme().colors().version_control_conflict,
|
||||
)
|
||||
} else if status.is_deleted() {
|
||||
(
|
||||
IconName::SquareMinus,
|
||||
cx.theme().colors().version_control_deleted,
|
||||
)
|
||||
} else if status.is_modified() {
|
||||
(
|
||||
IconName::SquareDot,
|
||||
cx.theme().colors().version_control_modified,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
IconName::SquarePlus,
|
||||
cx.theme().colors().version_control_added,
|
||||
)
|
||||
};
|
||||
|
||||
Icon::new(icon_name).color(Color::Custom(color))
|
||||
}
|
||||
}
|
||||
|
||||
// View this component preview using `workspace: open component-preview`
|
||||
impl ComponentPreview for GitStatusIcon {
|
||||
fn preview(_window: &mut Window, _cx: &mut App) -> AnyElement {
|
||||
fn tracked_file_status(code: StatusCode) -> FileStatus {
|
||||
FileStatus::Tracked(git::status::TrackedStatus {
|
||||
index_status: code,
|
||||
worktree_status: code,
|
||||
})
|
||||
}
|
||||
|
||||
let modified = tracked_file_status(StatusCode::Modified);
|
||||
let added = tracked_file_status(StatusCode::Added);
|
||||
let deleted = tracked_file_status(StatusCode::Deleted);
|
||||
let conflict = UnmergedStatus {
|
||||
first_head: UnmergedStatusCode::Updated,
|
||||
second_head: UnmergedStatusCode::Updated,
|
||||
}
|
||||
.into();
|
||||
|
||||
v_flex()
|
||||
.gap_6()
|
||||
.children(vec![example_group(vec![
|
||||
single_example("Modified", GitStatusIcon::new(modified).into_any_element()),
|
||||
single_example("Added", GitStatusIcon::new(added).into_any_element()),
|
||||
single_example("Deleted", GitStatusIcon::new(deleted).into_any_element()),
|
||||
single_example(
|
||||
"Conflicted",
|
||||
GitStatusIcon::new(conflict).into_any_element(),
|
||||
),
|
||||
])])
|
||||
.into_any_element()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@ pub trait PanelHeader: workspace::Panel {
|
||||
.w_full()
|
||||
.px_1()
|
||||
.flex_none()
|
||||
.border_b_1()
|
||||
.border_color(cx.theme().colors().border)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -136,14 +136,10 @@ impl ThemeColors {
|
||||
terminal_ansi_dim_white: neutral().light().step_11(),
|
||||
link_text_hover: orange().light().step_10(),
|
||||
version_control_added: ADDED_COLOR,
|
||||
version_control_added_background: ADDED_COLOR.opacity(0.1),
|
||||
version_control_deleted: REMOVED_COLOR,
|
||||
version_control_deleted_background: REMOVED_COLOR.opacity(0.1),
|
||||
version_control_modified: MODIFIED_COLOR,
|
||||
version_control_modified_background: MODIFIED_COLOR.opacity(0.1),
|
||||
version_control_renamed: MODIFIED_COLOR,
|
||||
version_control_conflict: orange().light().step_12(),
|
||||
version_control_conflict_background: orange().light().step_12().opacity(0.1),
|
||||
version_control_ignored: gray().light().step_12(),
|
||||
}
|
||||
}
|
||||
@@ -253,14 +249,10 @@ impl ThemeColors {
|
||||
terminal_ansi_dim_white: neutral().dark().step_10(),
|
||||
link_text_hover: orange().dark().step_10(),
|
||||
version_control_added: ADDED_COLOR,
|
||||
version_control_added_background: ADDED_COLOR.opacity(0.1),
|
||||
version_control_deleted: REMOVED_COLOR,
|
||||
version_control_deleted_background: REMOVED_COLOR.opacity(0.1),
|
||||
version_control_modified: MODIFIED_COLOR,
|
||||
version_control_modified_background: MODIFIED_COLOR.opacity(0.1),
|
||||
version_control_renamed: MODIFIED_COLOR,
|
||||
version_control_conflict: orange().dark().step_12(),
|
||||
version_control_conflict_background: orange().dark().step_12().opacity(0.1),
|
||||
version_control_ignored: gray().dark().step_12(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,14 +190,10 @@ pub(crate) fn zed_default_dark() -> Theme {
|
||||
editor_foreground: hsla(218. / 360., 14. / 100., 71. / 100., 1.),
|
||||
link_text_hover: blue,
|
||||
version_control_added: ADDED_COLOR,
|
||||
version_control_added_background: ADDED_COLOR.opacity(0.1),
|
||||
version_control_deleted: REMOVED_COLOR,
|
||||
version_control_deleted_background: REMOVED_COLOR.opacity(0.1),
|
||||
version_control_modified: MODIFIED_COLOR,
|
||||
version_control_modified_background: MODIFIED_COLOR.opacity(0.1),
|
||||
version_control_renamed: MODIFIED_COLOR,
|
||||
version_control_conflict: crate::orange().light().step_12(),
|
||||
version_control_conflict_background: crate::orange().light().step_12().opacity(0.1),
|
||||
version_control_ignored: crate::gray().light().step_12(),
|
||||
},
|
||||
status: StatusColors {
|
||||
|
||||
@@ -557,26 +557,14 @@ pub struct ThemeColorsContent {
|
||||
#[serde(rename = "version_control.added")]
|
||||
pub version_control_added: Option<String>,
|
||||
|
||||
/// Added version control background color.
|
||||
#[serde(rename = "version_control.added_background")]
|
||||
pub version_control_added_background: Option<String>,
|
||||
|
||||
/// Deleted version control color.
|
||||
#[serde(rename = "version_control.deleted")]
|
||||
pub version_control_deleted: Option<String>,
|
||||
|
||||
/// Deleted version control background color.
|
||||
#[serde(rename = "version_control.deleted_background")]
|
||||
pub version_control_deleted_background: Option<String>,
|
||||
|
||||
/// Modified version control color.
|
||||
#[serde(rename = "version_control.modified")]
|
||||
pub version_control_modified: Option<String>,
|
||||
|
||||
/// Modified version control background color.
|
||||
#[serde(rename = "version_control.modified_background")]
|
||||
pub version_control_modified_background: Option<String>,
|
||||
|
||||
/// Renamed version control color.
|
||||
#[serde(rename = "version_control.renamed")]
|
||||
pub version_control_renamed: Option<String>,
|
||||
@@ -585,10 +573,6 @@ pub struct ThemeColorsContent {
|
||||
#[serde(rename = "version_control.conflict")]
|
||||
pub version_control_conflict: Option<String>,
|
||||
|
||||
/// Conflict version control background color.
|
||||
#[serde(rename = "version_control.conflict_background")]
|
||||
pub version_control_conflict_background: Option<String>,
|
||||
|
||||
/// Ignored version control color.
|
||||
#[serde(rename = "version_control.ignored")]
|
||||
pub version_control_ignored: Option<String>,
|
||||
@@ -1000,26 +984,14 @@ impl ThemeColorsContent {
|
||||
.version_control_added
|
||||
.as_ref()
|
||||
.and_then(|color| try_parse_color(color).ok()),
|
||||
version_control_added_background: self
|
||||
.version_control_added_background
|
||||
.as_ref()
|
||||
.and_then(|color| try_parse_color(color).ok()),
|
||||
version_control_deleted: self
|
||||
.version_control_deleted
|
||||
.as_ref()
|
||||
.and_then(|color| try_parse_color(color).ok()),
|
||||
version_control_deleted_background: self
|
||||
.version_control_deleted_background
|
||||
.as_ref()
|
||||
.and_then(|color| try_parse_color(color).ok()),
|
||||
version_control_modified: self
|
||||
.version_control_modified
|
||||
.as_ref()
|
||||
.and_then(|color| try_parse_color(color).ok()),
|
||||
version_control_modified_background: self
|
||||
.version_control_modified_background
|
||||
.as_ref()
|
||||
.and_then(|color| try_parse_color(color).ok()),
|
||||
version_control_renamed: self
|
||||
.version_control_renamed
|
||||
.as_ref()
|
||||
@@ -1028,10 +1000,6 @@ impl ThemeColorsContent {
|
||||
.version_control_conflict
|
||||
.as_ref()
|
||||
.and_then(|color| try_parse_color(color).ok()),
|
||||
version_control_conflict_background: self
|
||||
.version_control_conflict_background
|
||||
.as_ref()
|
||||
.and_then(|color| try_parse_color(color).ok()),
|
||||
version_control_ignored: self
|
||||
.version_control_ignored
|
||||
.as_ref()
|
||||
|
||||
@@ -246,22 +246,14 @@ pub struct ThemeColors {
|
||||
|
||||
/// Represents an added entry or hunk in vcs, like git.
|
||||
pub version_control_added: Hsla,
|
||||
/// Represents the line background of an added entry or hunk in vcs, like git.
|
||||
pub version_control_added_background: Hsla,
|
||||
/// Represents a deleted entry in version control systems.
|
||||
pub version_control_deleted: Hsla,
|
||||
/// Represents the background color for deleted entries in version control systems.
|
||||
pub version_control_deleted_background: Hsla,
|
||||
/// Represents a modified entry in version control systems.
|
||||
pub version_control_modified: Hsla,
|
||||
/// Represents the background color for modified entries in version control systems.
|
||||
pub version_control_modified_background: Hsla,
|
||||
/// Represents a renamed entry in version control systems.
|
||||
pub version_control_renamed: Hsla,
|
||||
/// Represents a conflicting entry in version control systems.
|
||||
pub version_control_conflict: Hsla,
|
||||
/// Represents the background color for conflicting entries in version control systems.
|
||||
pub version_control_conflict_background: Hsla,
|
||||
/// Represents an ignored entry in version control systems.
|
||||
pub version_control_ignored: Hsla,
|
||||
}
|
||||
@@ -366,14 +358,10 @@ pub enum ThemeColorField {
|
||||
TerminalAnsiDimWhite,
|
||||
LinkTextHover,
|
||||
VersionControlAdded,
|
||||
VersionControlAddedBackground,
|
||||
VersionControlDeleted,
|
||||
VersionControlDeletedBackground,
|
||||
VersionControlModified,
|
||||
VersionControlModifiedBackground,
|
||||
VersionControlRenamed,
|
||||
VersionControlConflict,
|
||||
VersionControlConflictBackground,
|
||||
VersionControlIgnored,
|
||||
}
|
||||
|
||||
@@ -485,20 +473,10 @@ impl ThemeColors {
|
||||
ThemeColorField::TerminalAnsiDimWhite => self.terminal_ansi_dim_white,
|
||||
ThemeColorField::LinkTextHover => self.link_text_hover,
|
||||
ThemeColorField::VersionControlAdded => self.version_control_added,
|
||||
ThemeColorField::VersionControlAddedBackground => self.version_control_added_background,
|
||||
ThemeColorField::VersionControlDeleted => self.version_control_deleted,
|
||||
ThemeColorField::VersionControlDeletedBackground => {
|
||||
self.version_control_deleted_background
|
||||
}
|
||||
ThemeColorField::VersionControlModified => self.version_control_modified,
|
||||
ThemeColorField::VersionControlModifiedBackground => {
|
||||
self.version_control_modified_background
|
||||
}
|
||||
ThemeColorField::VersionControlRenamed => self.version_control_renamed,
|
||||
ThemeColorField::VersionControlConflict => self.version_control_conflict,
|
||||
ThemeColorField::VersionControlConflictBackground => {
|
||||
self.version_control_conflict_background
|
||||
}
|
||||
ThemeColorField::VersionControlIgnored => self.version_control_ignored,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,7 @@ use crate::{
|
||||
prelude::*, Color, DynamicSpacing, ElevationIndex, IconPosition, KeyBinding,
|
||||
KeybindingPosition, TintColor,
|
||||
};
|
||||
use crate::{
|
||||
ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, IconName, IconSize, Label, LineHeightStyle,
|
||||
};
|
||||
use crate::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, IconName, IconSize, Label};
|
||||
|
||||
use super::button_icon::ButtonIcon;
|
||||
|
||||
@@ -448,7 +446,6 @@ impl RenderOnce for Button {
|
||||
.color(label_color)
|
||||
.size(self.label_size.unwrap_or_default())
|
||||
.when_some(self.alpha, |this, alpha| this.alpha(alpha))
|
||||
.line_height_style(LineHeightStyle::UiLabel)
|
||||
.when(self.truncate, |this| this.truncate()),
|
||||
)
|
||||
.children(self.key_binding),
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use gpui::{
|
||||
div, hsla, prelude::*, AnyElement, AnyView, CursorStyle, ElementId, Hsla, IntoElement, Styled,
|
||||
Window,
|
||||
div, hsla, prelude::*, AnyElement, AnyView, ElementId, Hsla, IntoElement, Styled, Window,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -141,14 +140,14 @@ impl Checkbox {
|
||||
|
||||
match self.style.clone() {
|
||||
ToggleStyle::Ghost => cx.theme().colors().border,
|
||||
ToggleStyle::ElevationBased(elevation) => elevation.on_elevation_bg(cx),
|
||||
ToggleStyle::ElevationBased(_) => cx.theme().colors().border,
|
||||
ToggleStyle::Custom(color) => color.opacity(0.3),
|
||||
}
|
||||
}
|
||||
|
||||
/// container size
|
||||
pub fn container_size(cx: &App) -> Rems {
|
||||
DynamicSpacing::Base20.rems(cx)
|
||||
pub fn container_size() -> Pixels {
|
||||
px(20.0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,21 +156,21 @@ impl RenderOnce for Checkbox {
|
||||
let group_id = format!("checkbox_group_{:?}", self.id);
|
||||
let color = if self.disabled {
|
||||
Color::Disabled
|
||||
} else if self.placeholder {
|
||||
Color::Placeholder
|
||||
} else {
|
||||
Color::Selected
|
||||
};
|
||||
let icon = match self.toggle_state {
|
||||
ToggleState::Selected => Some(if self.placeholder {
|
||||
Icon::new(IconName::Circle)
|
||||
.size(IconSize::XSmall)
|
||||
.color(color)
|
||||
} else {
|
||||
Icon::new(IconName::Check)
|
||||
.size(IconSize::Small)
|
||||
.color(color)
|
||||
}),
|
||||
ToggleState::Selected => {
|
||||
if self.placeholder {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
Icon::new(IconName::Check)
|
||||
.size(IconSize::Small)
|
||||
.color(color),
|
||||
)
|
||||
}
|
||||
}
|
||||
ToggleState::Indeterminate => {
|
||||
Some(Icon::new(IconName::Dash).size(IconSize::Small).color(color))
|
||||
}
|
||||
@@ -180,8 +179,9 @@ impl RenderOnce for Checkbox {
|
||||
|
||||
let bg_color = self.bg_color(cx);
|
||||
let border_color = self.border_color(cx);
|
||||
let hover_border_color = border_color.alpha(0.7);
|
||||
|
||||
let size = Self::container_size(cx);
|
||||
let size = Self::container_size();
|
||||
|
||||
let checkbox = h_flex()
|
||||
.id(self.id.clone())
|
||||
@@ -195,22 +195,27 @@ impl RenderOnce for Checkbox {
|
||||
.flex_none()
|
||||
.justify_center()
|
||||
.items_center()
|
||||
.m(DynamicSpacing::Base04.px(cx))
|
||||
.size(DynamicSpacing::Base16.rems(cx))
|
||||
.m_1()
|
||||
.size_4()
|
||||
.rounded_xs()
|
||||
.bg(bg_color)
|
||||
.border_1()
|
||||
.border_color(border_color)
|
||||
.when(self.disabled, |this| {
|
||||
this.cursor(CursorStyle::OperationNotAllowed)
|
||||
})
|
||||
.when(self.disabled, |this| this.cursor_not_allowed())
|
||||
.when(self.disabled, |this| {
|
||||
this.bg(cx.theme().colors().element_disabled.opacity(0.6))
|
||||
})
|
||||
.when(!self.disabled, |this| {
|
||||
this.group_hover(group_id.clone(), |el| {
|
||||
el.bg(cx.theme().colors().element_hover)
|
||||
})
|
||||
this.group_hover(group_id.clone(), |el| el.border_color(hover_border_color))
|
||||
})
|
||||
.when(self.placeholder, |this| {
|
||||
this.child(
|
||||
div()
|
||||
.flex_none()
|
||||
.rounded_full()
|
||||
.bg(color.color(cx).alpha(0.5))
|
||||
.size(px(4.)),
|
||||
)
|
||||
})
|
||||
.children(icon),
|
||||
);
|
||||
@@ -522,6 +527,12 @@ impl ComponentPreview for Checkbox {
|
||||
Checkbox::new("checkbox_unselected", ToggleState::Unselected)
|
||||
.into_any_element(),
|
||||
),
|
||||
single_example(
|
||||
"Placeholder",
|
||||
Checkbox::new("checkbox_indeterminate", ToggleState::Selected)
|
||||
.placeholder(true)
|
||||
.into_any_element(),
|
||||
),
|
||||
single_example(
|
||||
"Indeterminate",
|
||||
Checkbox::new("checkbox_indeterminate", ToggleState::Indeterminate)
|
||||
|
||||
Reference in New Issue
Block a user