mirror of
https://github.com/zed-industries/zed.git
synced 2026-07-09 16:00:35 +00:00
Improve diff tabs toolbar design (#60464)
This PR adds a bunch of design improvements to the toolbar of (tab) views that display diffs: the uncommitted changes, branch diff, and agent diff tabs. This involves adjusting spacing, sizing, and other small tweaks across all of these views, including touching up the divider component API a little bit, adjusting Git icons design, adding diff stat numbers to the uncommitted changes tab so its consistent with the others, and more (e.g., moving the split buttons into its own component to ensure they look the same across all uses). Ended up also going on a slight de-tour to make all uses of the split button in the Git panel consistent design-wise. All in all, this is just tidying up the design of all of these surfaces that are all relatively similar. | Branch Diff | Uncommitted Diff | Single-file Diff | Git Panel | |--------|--------|--------|--------| | <img width="800" alt="Screenshot 2026-07-06 at 11 25@2x" src="https://github.com/user-attachments/assets/4ebf87e7-c52d-41d9-9de3-7944125114a1" /> | <img width="800" alt="Screenshot 2026-07-06 at 11 25 2@2x" src="https://github.com/user-attachments/assets/51ccd2eb-904b-455a-a708-b4cb50b3a7cb" /> | <img width="800" alt="Screenshot 2026-07-06 at 11 26@2x" src="https://github.com/user-attachments/assets/6ae7df68-d1bd-4d36-a250-ba16e43c4e8e" /> | <img width="800" alt="Screenshot 2026-07-06 at 11 26 2@2x" src="https://github.com/user-attachments/assets/e032bc60-4551-41f0-b578-90ed305167c2" /> | Release Notes: - Added diff stat numbers to the uncommitted changes view.
This commit is contained in:
parent
e58a02d974
commit
f16b46419d
18 changed files with 697 additions and 734 deletions
|
|
@ -1,4 +1,4 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.6667 2H3.33333C2.59695 2 2 2.59695 2 3.33333V12.6667C2 13.403 2.59695 14 3.33333 14H12.6667C13.403 14 14 13.403 14 12.6667V3.33333C14 2.59695 13.403 2 12.6667 2Z" stroke="black" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<circle cx="8" cy="8" r="1.25" fill="black" stroke="black" stroke-width="0.5"/>
|
||||
<path d="M11.8889 3H4.11111C3.49746 3 3 3.49746 3 4.11111V11.8889C3 12.5025 3.49746 13 4.11111 13H11.8889C12.5025 13 13 12.5025 13 11.8889V4.11111C13 3.49746 12.5025 3 11.8889 3Z" stroke="#DCE0E5" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M8 9C8.55228 9 9 8.55228 9 8C9 7.44772 8.55228 7 8 7C7.44772 7 7 7.44772 7 8C7 8.55228 7.44772 9 8 9Z" fill="#DCE0E5" stroke="#DCE0E5"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 514 B |
|
|
@ -1,4 +1,4 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.6667 2H3.33333C2.59695 2 2 2.59695 2 3.33333V12.6667C2 13.403 2.59695 14 3.33333 14H12.6667C13.403 14 14 13.403 14 12.6667V3.33333C14 2.59695 13.403 2 12.6667 2Z" stroke="black" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6 8H10" stroke="black" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M11.8889 3H4.11111C3.49746 3 3 3.49746 3 4.11111V11.8889C3 12.5025 3.49746 13 4.11111 13H11.8889C12.5025 13 13 12.5025 13 11.8889V4.11111C13 3.49746 12.5025 3 11.8889 3Z" stroke="#DCE0E5" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6 8H10" stroke="#DCE0E5" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 463 B After Width: | Height: | Size: 471 B |
|
|
@ -1,5 +1,5 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.6667 2H3.33333C2.59695 2 2 2.59695 2 3.33333V12.6667C2 13.403 2.59695 14 3.33333 14H12.6667C13.403 14 14 13.403 14 12.6667V3.33333C14 2.59695 13.403 2 12.6667 2Z" stroke="black" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6 8H10" stroke="black" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M8 6V10" stroke="black" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M11.8889 3H4.11111C3.49746 3 3 3.49746 3 4.11111V11.8889C3 12.5025 3.49746 13 4.11111 13H11.8889C12.5025 13 13 12.5025 13 11.8889V4.11111C13 3.49746 12.5025 3 11.8889 3Z" stroke="#DCE0E5" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6 8H10" stroke="#DCE0E5" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M8 6V10" stroke="#DCE0E5" stroke-width="1.2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 564 B After Width: | Height: | Size: 574 B |
|
|
@ -28,7 +28,7 @@ use std::{
|
|||
ops::Range,
|
||||
sync::Arc,
|
||||
};
|
||||
use ui::{CommonAnimationExt, IconButtonShape, KeyBinding, Tooltip, prelude::*, vertical_divider};
|
||||
use ui::{CommonAnimationExt, Divider, IconButtonShape, KeyBinding, Tooltip, prelude::*};
|
||||
use util::ResultExt;
|
||||
use workspace::{
|
||||
Item, ItemHandle, ItemNavHistory, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView,
|
||||
|
|
@ -1099,7 +1099,7 @@ impl Render for AgentDiffToolbar {
|
|||
}),
|
||||
)
|
||||
.into_any_element(),
|
||||
vertical_divider().into_any_element(),
|
||||
Divider::vertical().into_any_element(),
|
||||
h_flex()
|
||||
.gap_0p5()
|
||||
.child(
|
||||
|
|
@ -1141,7 +1141,7 @@ impl Render for AgentDiffToolbar {
|
|||
.mr_1()
|
||||
.gap_1()
|
||||
.children(content)
|
||||
.child(vertical_divider())
|
||||
.child(Divider::vertical())
|
||||
.when_some(editor.read(cx).workspace(), |this, _workspace| {
|
||||
this.child(
|
||||
IconButton::new("review", IconName::ListTodo)
|
||||
|
|
@ -1158,7 +1158,7 @@ impl Render for AgentDiffToolbar {
|
|||
}),
|
||||
)
|
||||
})
|
||||
.child(vertical_divider())
|
||||
.child(Divider::vertical())
|
||||
.on_action({
|
||||
let editor = editor.clone();
|
||||
move |_action: &OpenAgentDiff, window, cx| {
|
||||
|
|
|
|||
|
|
@ -4913,7 +4913,7 @@ impl ThreadView {
|
|||
);
|
||||
}),
|
||||
)
|
||||
.child(Divider::vertical().h_4())
|
||||
.child(Divider::vertical())
|
||||
.into_any_element(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ pub use editor_settings::{
|
|||
};
|
||||
pub use element::{
|
||||
CursorLayout, EditorElement, HighlightedRange, HighlightedRangeLine, PointForPosition,
|
||||
render_breadcrumb_text,
|
||||
file_status_label_color, render_breadcrumb_text,
|
||||
};
|
||||
pub use git::blame::BlameRenderer;
|
||||
pub(crate) use git::{DiffHunkKey, StoredReviewComment};
|
||||
|
|
@ -124,7 +124,7 @@ pub use multi_buffer::{
|
|||
MultiBufferOffset, MultiBufferOffsetUtf16, MultiBufferSnapshot, PathKey, RowInfo, ToOffset,
|
||||
ToPoint,
|
||||
};
|
||||
pub use split::{SplittableEditor, ToggleSplitDiff};
|
||||
pub use split::{DiffStyleControls, SplittableEditor, ToggleSplitDiff};
|
||||
pub use split_editor_view::SplitEditorView;
|
||||
pub use text::Bias;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ mod mouse;
|
|||
|
||||
#[cfg(test)]
|
||||
pub(crate) use header::StickyHeader;
|
||||
pub use header::file_status_label_color;
|
||||
pub(crate) use header::{header_jump_data, render_buffer_header};
|
||||
|
||||
use crate::{
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use text::BufferId;
|
|||
use theme::ActiveTheme;
|
||||
use ui::{
|
||||
ButtonLike, ContextMenu, DiffStat, Indicator, KeyBinding, Tooltip, prelude::*,
|
||||
right_click_menu, text_for_keystroke,
|
||||
right_click_menu, text_for_keystroke, utils::WithRemSize,
|
||||
};
|
||||
use util::ResultExt;
|
||||
use workspace::{ItemHandle, ItemSettings, OpenInTerminal, OpenTerminal, RevealInProjectPanel};
|
||||
|
|
@ -691,6 +691,9 @@ pub(crate) fn render_buffer_header(
|
|||
let opaque_window =
|
||||
cx.theme().window_background_appearance() == WindowBackgroundAppearance::Opaque;
|
||||
|
||||
let show_open_file_button =
|
||||
can_open_excerpts && relative_path.is_some() && (is_selected || header_hovered);
|
||||
|
||||
let header = div()
|
||||
.id(("buffer-header", buffer_id.to_proto()))
|
||||
.on_hover(move |hovered, _window, cx| {
|
||||
|
|
@ -713,7 +716,6 @@ pub(crate) fn render_buffer_header(
|
|||
.pr_2()
|
||||
.rounded_sm()
|
||||
.gap_1p5()
|
||||
.when(is_sticky && opaque_window, |el| el.shadow_md())
|
||||
.border_1()
|
||||
.map(|border| {
|
||||
let border_color =
|
||||
|
|
@ -724,10 +726,9 @@ pub(crate) fn render_buffer_header(
|
|||
};
|
||||
border.border_color(border_color)
|
||||
})
|
||||
.when(opaque_window, |el| {
|
||||
el.bg(colors.editor_subheader_background)
|
||||
})
|
||||
.hover(|style| style.bg(colors.element_hover))
|
||||
.when(is_sticky && opaque_window, |s| s.shadow_md())
|
||||
.when(opaque_window, |s| s.bg(colors.editor_subheader_background))
|
||||
.hover(|s| s.bg(colors.element_hover))
|
||||
.map(|header| {
|
||||
let editor = editor.clone();
|
||||
let buffer_id = for_excerpt.buffer_id();
|
||||
|
|
@ -906,46 +907,46 @@ pub(crate) fn render_buffer_header(
|
|||
})
|
||||
},
|
||||
))
|
||||
.when_some(diff_stat, |this, (added, removed)| {
|
||||
this.child(
|
||||
div().flex_shrink_0().child(
|
||||
DiffStat::new(
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.when_some(diff_stat, |this, (added, removed)| {
|
||||
let ui_font_size =
|
||||
theme_settings::ThemeSettings::get_global(cx)
|
||||
.ui_font_size(cx);
|
||||
this.child(WithRemSize::new(ui_font_size).child(DiffStat::new(
|
||||
("buffer-header-diff-stat", buffer_id.to_proto()),
|
||||
added as usize,
|
||||
removed as usize,
|
||||
)
|
||||
.label_size(LabelSize::Small),
|
||||
),
|
||||
)
|
||||
})
|
||||
.when(
|
||||
can_open_excerpts
|
||||
&& relative_path.is_some()
|
||||
&& (is_selected || header_hovered),
|
||||
|this| {
|
||||
this.child(
|
||||
Button::new("open-file-button", "Open File")
|
||||
.style(ButtonStyle::OutlinedGhost)
|
||||
.when(is_selected, |this| {
|
||||
this.key_binding(KeyBinding::for_action_in(
|
||||
&OpenExcerpts,
|
||||
&focus_handle,
|
||||
cx,
|
||||
)))
|
||||
})
|
||||
.when(show_open_file_button, |this| {
|
||||
this.child(
|
||||
Button::new("open-file-button", "Open File")
|
||||
.style(ButtonStyle::OutlinedCustom(
|
||||
cx.theme().colors().border.opacity(0.6),
|
||||
))
|
||||
})
|
||||
.on_click(window.listener_for(editor, {
|
||||
let jump_data = jump_data.clone();
|
||||
move |editor, e: &ClickEvent, window, cx| {
|
||||
editor.open_excerpts_common(
|
||||
Some(jump_data.clone()),
|
||||
e.modifiers().secondary(),
|
||||
window,
|
||||
.layer(ui::ElevationIndex::ElevatedSurface)
|
||||
.when(is_selected, |this| {
|
||||
this.key_binding(KeyBinding::for_action_in(
|
||||
&OpenExcerpts,
|
||||
&focus_handle,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
})),
|
||||
)
|
||||
},
|
||||
))
|
||||
})
|
||||
.on_click(window.listener_for(editor, {
|
||||
let jump_data = jump_data.clone();
|
||||
move |editor, e: &ClickEvent, window, cx| {
|
||||
editor.open_excerpts_common(
|
||||
Some(jump_data.clone()),
|
||||
e.modifiers().secondary(),
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
})),
|
||||
)
|
||||
}),
|
||||
)
|
||||
.on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
|
||||
.on_click(window.listener_for(editor, {
|
||||
|
|
@ -1086,7 +1087,7 @@ pub(crate) fn render_buffer_header(
|
|||
})
|
||||
}
|
||||
|
||||
fn file_status_label_color(file_status: Option<FileStatus>) -> Color {
|
||||
pub fn file_status_label_color(file_status: Option<FileStatus>) -> Color {
|
||||
file_status.map_or(Color::Default, |status| {
|
||||
if status.is_conflicted() {
|
||||
Color::Conflict
|
||||
|
|
|
|||
|
|
@ -6,9 +6,10 @@ use std::{
|
|||
use buffer_diff::{BufferDiff, BufferDiffSnapshot};
|
||||
use collections::HashMap;
|
||||
|
||||
use fs::Fs;
|
||||
use gpui::{
|
||||
Action, AppContext as _, Entity, EventEmitter, Focusable, Font, Pixels, Subscription,
|
||||
WeakEntity, canvas,
|
||||
Action, Entity, EventEmitter, Focusable, Font, Pixels, Subscription, WeakEntity, canvas,
|
||||
prelude::*,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use language::{Buffer, Capability, HighlightedText};
|
||||
|
|
@ -18,12 +19,10 @@ use multi_buffer::{
|
|||
};
|
||||
use project::Project;
|
||||
use rope::Point;
|
||||
use settings::{DiffViewStyle, SeedQuerySetting, Settings, SettingsStore};
|
||||
use settings::{DiffViewStyle, SeedQuerySetting, Settings, SettingsStore, update_settings_file};
|
||||
use text::{Bias, BufferId, OffsetRangeExt as _, Patch, ToPoint as _};
|
||||
use ui::{
|
||||
App, Context, InteractiveElement as _, IntoElement as _, ParentElement as _, Render,
|
||||
Styled as _, Window, div,
|
||||
};
|
||||
|
||||
use ui::{Toggleable as _, Tooltip, prelude::*, render_modifiers};
|
||||
|
||||
use crate::{
|
||||
display_map::CompanionExcerptPatch,
|
||||
|
|
@ -41,7 +40,7 @@ use crate::{
|
|||
actions::{DisableBreakpoint, EditLogBreakpoint, EnableBreakpoint, ToggleBreakpoint},
|
||||
display_map::Companion,
|
||||
};
|
||||
use zed_actions::assistant::InlineAssist;
|
||||
use zed_actions::{OpenSettingsAt, assistant::InlineAssist};
|
||||
|
||||
pub(crate) fn patches_for_lhs_range(
|
||||
rhs_snapshot: &MultiBufferSnapshot,
|
||||
|
|
@ -401,6 +400,124 @@ fn patch_for_excerpt(
|
|||
#[action(namespace = editor)]
|
||||
pub struct ToggleSplitDiff;
|
||||
|
||||
/// Unified/split diff view toggle buttons, shared by the toolbars of every
|
||||
/// diff view (project diff, branch diff, solo diff) so they can't drift apart.
|
||||
#[derive(gpui::IntoElement)]
|
||||
pub struct DiffStyleControls {
|
||||
splittable_editor: Entity<SplittableEditor>,
|
||||
}
|
||||
|
||||
impl DiffStyleControls {
|
||||
pub fn new(splittable_editor: Entity<SplittableEditor>) -> Self {
|
||||
Self { splittable_editor }
|
||||
}
|
||||
|
||||
fn set_diff_view_style(
|
||||
splittable_editor: &Entity<SplittableEditor>,
|
||||
diff_view_style: DiffViewStyle,
|
||||
window: &mut Window,
|
||||
cx: &mut App,
|
||||
) {
|
||||
update_settings_file(<dyn Fs>::global(cx), cx, move |settings, _| {
|
||||
settings.editor.diff_view_style = Some(diff_view_style);
|
||||
});
|
||||
|
||||
splittable_editor.update(cx, |editor, cx| {
|
||||
if editor.diff_view_style() != diff_view_style {
|
||||
editor.toggle_split(&ToggleSplitDiff, window, cx);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderOnce for DiffStyleControls {
|
||||
fn render(self, _window: &mut Window, cx: &mut App) -> impl gpui::IntoElement {
|
||||
let editor = self.splittable_editor.read(cx);
|
||||
let diff_view_style = editor.diff_view_style();
|
||||
let is_split_set = diff_view_style == DiffViewStyle::Split;
|
||||
let is_split_pending = is_split_set && !editor.is_split();
|
||||
let min_columns = EditorSettings::get_global(cx).minimum_split_diff_width as u32;
|
||||
|
||||
let split_icon = if is_split_pending {
|
||||
IconName::DiffSplitAuto
|
||||
} else {
|
||||
IconName::DiffSplit
|
||||
};
|
||||
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.child(
|
||||
IconButton::new("diff-style-unified", IconName::DiffUnified)
|
||||
.icon_size(IconSize::Small)
|
||||
.toggle_state(diff_view_style == DiffViewStyle::Unified)
|
||||
.tooltip(Tooltip::text("Unified"))
|
||||
.on_click({
|
||||
let splittable_editor = self.splittable_editor.clone();
|
||||
move |_, window, cx| {
|
||||
Self::set_diff_view_style(
|
||||
&splittable_editor,
|
||||
DiffViewStyle::Unified,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
IconButton::new("diff-style-split", split_icon)
|
||||
.icon_size(IconSize::Small)
|
||||
.toggle_state(is_split_set)
|
||||
.tooltip(Tooltip::element(move |_, cx| {
|
||||
let message = if is_split_pending {
|
||||
format!("Split when wider than {} columns", min_columns).into()
|
||||
} else {
|
||||
SharedString::from("Split")
|
||||
};
|
||||
|
||||
v_flex()
|
||||
.child(message)
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_0p5()
|
||||
.text_ui_sm(cx)
|
||||
.text_color(Color::Muted.color(cx))
|
||||
.children(render_modifiers(
|
||||
&gpui::Modifiers::secondary_key(),
|
||||
PlatformStyle::platform(),
|
||||
None,
|
||||
Some(TextSize::Small.rems(cx).into()),
|
||||
false,
|
||||
))
|
||||
.child("click to change min width"),
|
||||
)
|
||||
.into_any_element()
|
||||
}))
|
||||
.on_click({
|
||||
let splittable_editor = self.splittable_editor.clone();
|
||||
move |_, window, cx| {
|
||||
if window.modifiers().secondary() {
|
||||
window.dispatch_action(
|
||||
OpenSettingsAt {
|
||||
path: "minimum_split_diff_width".to_string(),
|
||||
target: None,
|
||||
}
|
||||
.boxed_clone(),
|
||||
cx,
|
||||
);
|
||||
} else {
|
||||
Self::set_diff_view_style(
|
||||
&splittable_editor,
|
||||
DiffViewStyle::Split,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SplittableEditor {
|
||||
rhs_multibuffer: Entity<MultiBuffer>,
|
||||
rhs_editor: Entity<Editor>,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ use git::{Amend, Commit, GenerateCommitMessage, Signoff};
|
|||
use project::DisableAiSettings;
|
||||
use settings::Settings;
|
||||
use ui::{
|
||||
ContextMenu, KeybindingHint, PopoverMenu, PopoverMenuHandle, SplitButton, Tooltip, prelude::*,
|
||||
ButtonLike, ContextMenu, ElevationIndex, KeybindingHint, PopoverMenu, PopoverMenuHandle,
|
||||
SplitButton, Tooltip, prelude::*,
|
||||
};
|
||||
use zed_actions::{DecreaseBufferFontSize, IncreaseBufferFontSize, ResetBufferFontSize};
|
||||
|
||||
|
|
@ -268,17 +269,14 @@ impl CommitModal {
|
|||
id: impl Into<ElementId>,
|
||||
keybinding_target: Option<FocusHandle>,
|
||||
) -> impl IntoElement {
|
||||
let menu_open = self.commit_menu_handle.is_deployed();
|
||||
|
||||
PopoverMenu::new(id.into())
|
||||
.trigger(
|
||||
ui::ButtonLike::new_rounded_right("commit-split-button-right")
|
||||
.layer(ui::ElevationIndex::ModalSurface)
|
||||
.size(ui::ButtonSize::None)
|
||||
.child(
|
||||
div()
|
||||
.px_1()
|
||||
.child(Icon::new(IconName::ChevronDown).size(IconSize::XSmall)),
|
||||
),
|
||||
)
|
||||
.with_handle(self.commit_menu_handle.clone())
|
||||
.trigger(crate::render_split_button_chevron_trigger(
|
||||
"modal-commit-split-button-right",
|
||||
menu_open,
|
||||
))
|
||||
.menu({
|
||||
let git_panel_entity = self.git_panel.clone();
|
||||
move |window, cx| {
|
||||
|
|
@ -327,7 +325,10 @@ impl CommitModal {
|
|||
}))
|
||||
}
|
||||
})
|
||||
.with_handle(self.commit_menu_handle.clone())
|
||||
.offset(gpui::Point {
|
||||
x: px(0.),
|
||||
y: px(2.),
|
||||
})
|
||||
.anchor(Anchor::TopRight)
|
||||
}
|
||||
|
||||
|
|
@ -370,13 +371,12 @@ impl CommitModal {
|
|||
.unwrap_or_else(|| "<no branch>".to_owned());
|
||||
|
||||
let branch_picker_button = Button::new("branch_picker_button", branch)
|
||||
.label_size(LabelSize::Small)
|
||||
.start_icon(
|
||||
Icon::new(IconName::GitBranch)
|
||||
.size(IconSize::Small)
|
||||
.color(Color::Placeholder),
|
||||
)
|
||||
.style(ButtonStyle::Transparent)
|
||||
.color(Color::Muted)
|
||||
.on_click(cx.listener(|_, _, window, cx| {
|
||||
window.dispatch_action(zed_actions::git::Branch.boxed_clone(), cx);
|
||||
}));
|
||||
|
|
@ -401,6 +401,7 @@ impl CommitModal {
|
|||
x: px(0.0),
|
||||
y: px(-2.0),
|
||||
});
|
||||
|
||||
let focus_handle = self.focus_handle(cx);
|
||||
|
||||
let close_kb_hint = ui::KeyBinding::for_action(&menu::Cancel, cx).map(|close_kb| {
|
||||
|
|
@ -409,13 +410,12 @@ impl CommitModal {
|
|||
|
||||
h_flex()
|
||||
.group("commit_editor_footer")
|
||||
.flex_none()
|
||||
.w_full()
|
||||
.items_center()
|
||||
.justify_between()
|
||||
.w_full()
|
||||
.h(px(self.properties.footer_height))
|
||||
.w_full()
|
||||
.gap_1()
|
||||
.flex_none()
|
||||
.justify_between()
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_1()
|
||||
|
|
@ -430,64 +430,53 @@ impl CommitModal {
|
|||
.children(generate_commit_message)
|
||||
.children(co_authors),
|
||||
)
|
||||
.child(div().flex_1())
|
||||
.child(
|
||||
h_flex()
|
||||
.items_center()
|
||||
.justify_end()
|
||||
.flex_none()
|
||||
.px_1()
|
||||
.gap_4()
|
||||
.child(close_kb_hint)
|
||||
.child(SplitButton::new(
|
||||
ui::ButtonLike::new_rounded_left(ElementId::Name(
|
||||
format!("split-button-left-{}", commit_label).into(),
|
||||
))
|
||||
.layer(ui::ElevationIndex::ModalSurface)
|
||||
.size(ui::ButtonSize::Compact)
|
||||
.child(
|
||||
div()
|
||||
.child(Label::new(commit_label).size(LabelSize::Small))
|
||||
.mr_0p5(),
|
||||
)
|
||||
.on_click(cx.listener(move |this, _: &ClickEvent, window, cx| {
|
||||
telemetry::event!("Git Committed", source = "Git Modal");
|
||||
this.git_panel.update(cx, |git_panel, cx| {
|
||||
git_panel.commit_changes(
|
||||
CommitOptions {
|
||||
amend: is_amend_pending,
|
||||
signoff: is_signoff_enabled,
|
||||
allow_empty: false,
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
});
|
||||
cx.emit(DismissEvent);
|
||||
}))
|
||||
.disabled(!can_commit)
|
||||
.tooltip({
|
||||
let focus_handle = focus_handle.clone();
|
||||
move |_window, cx| {
|
||||
if can_commit {
|
||||
Tooltip::with_meta_in(
|
||||
tooltip,
|
||||
Some(&git::Commit),
|
||||
format!(
|
||||
"git commit{}{}",
|
||||
if is_amend_pending { " --amend" } else { "" },
|
||||
if is_signoff_enabled { " --signoff" } else { "" }
|
||||
),
|
||||
&focus_handle.clone(),
|
||||
ButtonLike::new_rounded_left(format!("split-button-left-{}", commit_label))
|
||||
.layer(ElevationIndex::ModalSurface)
|
||||
.size(ButtonSize::Compact)
|
||||
.disabled(!can_commit)
|
||||
.child(Label::new(commit_label).size(LabelSize::Small).mr_0p5())
|
||||
.on_click(cx.listener(move |this, _: &ClickEvent, window, cx| {
|
||||
telemetry::event!("Git Committed", source = "Git Modal");
|
||||
this.git_panel.update(cx, |git_panel, cx| {
|
||||
git_panel.commit_changes(
|
||||
CommitOptions {
|
||||
amend: is_amend_pending,
|
||||
signoff: is_signoff_enabled,
|
||||
allow_empty: false,
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
)
|
||||
} else {
|
||||
Tooltip::simple(tooltip, cx)
|
||||
});
|
||||
cx.emit(DismissEvent);
|
||||
}))
|
||||
.tooltip({
|
||||
let focus_handle = focus_handle.clone();
|
||||
move |_window, cx| {
|
||||
if can_commit {
|
||||
Tooltip::with_meta_in(
|
||||
tooltip,
|
||||
Some(&git::Commit),
|
||||
format!(
|
||||
"git commit{}{}",
|
||||
if is_amend_pending { " --amend" } else { "" },
|
||||
if is_signoff_enabled { " --signoff" } else { "" }
|
||||
),
|
||||
&focus_handle.clone(),
|
||||
cx,
|
||||
)
|
||||
} else {
|
||||
Tooltip::simple(tooltip, cx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
}),
|
||||
self.render_git_commit_menu(
|
||||
ElementId::Name(format!("split-button-right-{}", commit_label).into()),
|
||||
format!("split-button-right-{}", commit_label),
|
||||
Some(focus_handle),
|
||||
)
|
||||
.into_any_element(),
|
||||
|
|
|
|||
|
|
@ -79,8 +79,9 @@ use theme_settings::ThemeSettings;
|
|||
use time::OffsetDateTime;
|
||||
use ui::{
|
||||
ButtonLike, Checkbox, ContextMenu, ContextMenuEntry, Divider, ElevationIndex,
|
||||
IndentGuideColors, KeyBinding, PopoverMenu, ProjectEmptyState, RenderedIndentGuide, ScrollAxes,
|
||||
Scrollbars, SplitButton, Tab, TintColor, Tooltip, WithScrollbar, prelude::*,
|
||||
IndentGuideColors, KeyBinding, PopoverMenu, PopoverMenuHandle, ProjectEmptyState,
|
||||
RenderedIndentGuide, ScrollAxes, Scrollbars, SplitButton, Tab, TintColor, Tooltip,
|
||||
WithScrollbar, prelude::*,
|
||||
};
|
||||
use util::paths::PathStyle;
|
||||
use util::{ResultExt, TryFutureExt, markdown::MarkdownInlineCode, maybe, rel_path::RelPath};
|
||||
|
|
@ -801,9 +802,11 @@ pub struct GitPanel {
|
|||
history_keyboard_nav: bool,
|
||||
_commit_message_buffer_subscription: Option<Subscription>,
|
||||
_repo_subscriptions: Vec<Subscription>,
|
||||
|
||||
_settings_subscription: Subscription,
|
||||
git_access: Option<GitAccess>,
|
||||
commit_menu_handle: PopoverMenuHandle<ContextMenu>,
|
||||
changes_actions_menu_handle: PopoverMenuHandle<ContextMenu>,
|
||||
remote_action_menu_handle: PopoverMenuHandle<ContextMenu>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
|
|
@ -1084,6 +1087,9 @@ impl GitPanel {
|
|||
_repo_subscriptions: Vec::new(),
|
||||
_settings_subscription,
|
||||
git_access: None,
|
||||
commit_menu_handle: PopoverMenuHandle::default(),
|
||||
changes_actions_menu_handle: PopoverMenuHandle::default(),
|
||||
remote_action_menu_handle: PopoverMenuHandle::default(),
|
||||
};
|
||||
|
||||
this.schedule_update(window, cx);
|
||||
|
|
@ -4867,21 +4873,14 @@ impl GitPanel {
|
|||
keybinding_target: Option<FocusHandle>,
|
||||
cx: &mut Context<Self>,
|
||||
) -> impl IntoElement {
|
||||
let menu_open = self.commit_menu_handle.is_deployed();
|
||||
|
||||
PopoverMenu::new(id.into())
|
||||
.trigger(
|
||||
ui::ButtonLike::new_rounded_right("commit-split-button-right")
|
||||
.layer(ui::ElevationIndex::ModalSurface)
|
||||
.size(ButtonSize::None)
|
||||
.child(
|
||||
h_flex()
|
||||
.px_1()
|
||||
.h_full()
|
||||
.justify_center()
|
||||
.border_l_1()
|
||||
.border_color(cx.theme().colors().border)
|
||||
.child(Icon::new(IconName::ChevronDown).size(IconSize::XSmall)),
|
||||
),
|
||||
)
|
||||
.trigger(crate::render_split_button_chevron_trigger(
|
||||
"commit-split-button-right",
|
||||
menu_open,
|
||||
))
|
||||
.with_handle(self.commit_menu_handle.clone())
|
||||
.menu({
|
||||
let git_panel = cx.entity();
|
||||
let has_previous_commit = self.head_commit(cx).is_some();
|
||||
|
|
@ -4923,6 +4922,10 @@ impl GitPanel {
|
|||
}
|
||||
})
|
||||
.anchor(Anchor::TopRight)
|
||||
.offset(gpui::Point {
|
||||
x: px(0.),
|
||||
y: px(2.),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn configure_commit_button(&self, cx: &mut Context<Self>) -> (bool, &'static str) {
|
||||
|
|
@ -5008,19 +5011,16 @@ impl GitPanel {
|
|||
let has_unstaged_changes = self.has_unstaged_changes();
|
||||
let has_new_changes = self.new_count > 0;
|
||||
let has_stash_items = self.stash_entries.entries.len() > 0;
|
||||
|
||||
let focus_handle = self.focus_handle.clone();
|
||||
let menu_open = self.changes_actions_menu_handle.is_deployed();
|
||||
|
||||
PopoverMenu::new(id.into())
|
||||
.trigger(
|
||||
ui::ButtonLike::new_rounded_right("git-changes-actions-split-button-right")
|
||||
.layer(ui::ElevationIndex::ModalSurface)
|
||||
.size(ButtonSize::None)
|
||||
.child(
|
||||
div()
|
||||
.px_1()
|
||||
.child(Icon::new(IconName::ChevronDown).size(IconSize::XSmall)),
|
||||
),
|
||||
)
|
||||
.trigger(crate::render_split_button_chevron_trigger(
|
||||
"changes-actions-split-button-right",
|
||||
menu_open,
|
||||
))
|
||||
.with_handle(self.changes_actions_menu_handle.clone())
|
||||
.menu(move |window, cx| {
|
||||
Some(git_panel_context_menu(
|
||||
has_tracked_changes,
|
||||
|
|
@ -5034,6 +5034,10 @@ impl GitPanel {
|
|||
))
|
||||
})
|
||||
.anchor(Anchor::TopRight)
|
||||
.offset(gpui::Point {
|
||||
x: px(0.),
|
||||
y: px(2.),
|
||||
})
|
||||
}
|
||||
|
||||
fn render_git_changes_actions_button(&self, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
|
|
@ -5158,6 +5162,7 @@ impl GitPanel {
|
|||
focus_handle,
|
||||
true,
|
||||
self.pending_remote_operation,
|
||||
self.remote_action_menu_handle.clone(),
|
||||
))
|
||||
})
|
||||
.into_any_element(),
|
||||
|
|
@ -5359,7 +5364,7 @@ impl GitPanel {
|
|||
Color::Default
|
||||
};
|
||||
|
||||
div()
|
||||
h_flex()
|
||||
.id("commit-wrapper")
|
||||
.on_hover(cx.listener(move |this, hovered, _, cx| {
|
||||
this.show_placeholders =
|
||||
|
|
@ -5367,57 +5372,55 @@ impl GitPanel {
|
|||
cx.notify()
|
||||
}))
|
||||
.child(SplitButton::new(
|
||||
ButtonLike::new_rounded_left(ElementId::Name(
|
||||
format!("split-button-left-{}", title).into(),
|
||||
))
|
||||
.layer(ElevationIndex::ModalSurface)
|
||||
.size(ButtonSize::Compact)
|
||||
.child(
|
||||
Label::new(title)
|
||||
.size(LabelSize::Small)
|
||||
.color(label_color)
|
||||
.mr_0p5(),
|
||||
)
|
||||
.on_click({
|
||||
let git_panel = cx.weak_entity();
|
||||
move |_, window, cx| {
|
||||
telemetry::event!("Git Committed", source = "Git Panel");
|
||||
git_panel
|
||||
.update(cx, |git_panel, cx| {
|
||||
git_panel.commit_changes(
|
||||
CommitOptions {
|
||||
amend,
|
||||
signoff,
|
||||
allow_empty: false,
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
})
|
||||
.disabled(!can_commit || self.modal_open)
|
||||
.tooltip({
|
||||
let handle = commit_tooltip_focus_handle.clone();
|
||||
move |_window, cx| {
|
||||
if can_commit {
|
||||
Tooltip::with_meta_in(
|
||||
tooltip,
|
||||
Some(&git::Commit),
|
||||
format!(
|
||||
"git commit{}{}",
|
||||
if amend { " --amend" } else { "" },
|
||||
if signoff { " --signoff" } else { "" }
|
||||
),
|
||||
&handle.clone(),
|
||||
cx,
|
||||
)
|
||||
} else {
|
||||
Tooltip::simple(tooltip, cx)
|
||||
ButtonLike::new_rounded_left(format!("split-button-left-{}", title))
|
||||
.layer(ElevationIndex::ModalSurface)
|
||||
.size(ButtonSize::Compact)
|
||||
.disabled(!can_commit || self.modal_open)
|
||||
.child(
|
||||
Label::new(title)
|
||||
.size(LabelSize::Small)
|
||||
.color(label_color)
|
||||
.mr_0p5(),
|
||||
)
|
||||
.on_click({
|
||||
let git_panel = cx.weak_entity();
|
||||
move |_, window, cx| {
|
||||
telemetry::event!("Git Committed", source = "Git Panel");
|
||||
git_panel
|
||||
.update(cx, |git_panel, cx| {
|
||||
git_panel.commit_changes(
|
||||
CommitOptions {
|
||||
amend,
|
||||
signoff,
|
||||
allow_empty: false,
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
}),
|
||||
})
|
||||
.tooltip({
|
||||
let handle = commit_tooltip_focus_handle.clone();
|
||||
move |_window, cx| {
|
||||
if can_commit {
|
||||
Tooltip::with_meta_in(
|
||||
tooltip,
|
||||
Some(&git::Commit),
|
||||
format!(
|
||||
"git commit{}{}",
|
||||
if amend { " --amend" } else { "" },
|
||||
if signoff { " --signoff" } else { "" }
|
||||
),
|
||||
&handle.clone(),
|
||||
cx,
|
||||
)
|
||||
} else {
|
||||
Tooltip::simple(tooltip, cx)
|
||||
}
|
||||
}
|
||||
}),
|
||||
self.render_git_commit_menu(
|
||||
ElementId::Name(format!("split-button-right-{}", title).into()),
|
||||
Some(commit_tooltip_focus_handle),
|
||||
|
|
@ -5615,7 +5618,11 @@ impl GitPanel {
|
|||
GitPanelTab::Changes,
|
||||
ActivateChangesTab.boxed_clone(),
|
||||
))
|
||||
.child(Divider::vertical().color(ui::DividerColor::BorderFaded))
|
||||
.child(
|
||||
Divider::vertical()
|
||||
.color(ui::DividerColor::BorderFaded)
|
||||
.h_full(),
|
||||
)
|
||||
.child(tab(
|
||||
ElementId::Name("history-tab".into()),
|
||||
active_tab != GitPanelTab::Changes,
|
||||
|
|
@ -6515,7 +6522,7 @@ impl GitPanel {
|
|||
)
|
||||
.separator()
|
||||
.action("Open Diff", menu::Confirm.boxed_clone())
|
||||
.action("Open Diff (File)", menu::SecondaryConfirm.boxed_clone())
|
||||
.action("Open File Diff", menu::SecondaryConfirm.boxed_clone())
|
||||
.action("View File", ViewFile.boxed_clone())
|
||||
.when(!is_created, |context_menu| {
|
||||
context_menu
|
||||
|
|
|
|||
|
|
@ -2,10 +2,6 @@ use anyhow::anyhow;
|
|||
use commit_modal::CommitModal;
|
||||
use editor::{Editor, actions::DiffClipboardWithSelectionData};
|
||||
|
||||
use ui::{
|
||||
Color, Headline, HeadlineSize, Icon, IconName, IconSize, IntoElement, ParentElement, Render,
|
||||
Styled, StyledExt, div, h_flex, rems, v_flex,
|
||||
};
|
||||
use workspace::{Toast, notifications::NotificationId};
|
||||
|
||||
mod blame_ui;
|
||||
|
|
@ -23,7 +19,7 @@ use menu::{Cancel, Confirm};
|
|||
use project::git_store::Repository;
|
||||
use project_diff::ProjectDiff;
|
||||
use time::OffsetDateTime;
|
||||
use ui::prelude::*;
|
||||
use ui::{ButtonLike, ContextMenu, ElevationIndex, PopoverMenuHandle, TintColor, prelude::*};
|
||||
use workspace::{
|
||||
ModalView, OpenMode, Workspace,
|
||||
notifications::{DetachAndPromptErr, NotifyTaskExt},
|
||||
|
|
@ -766,6 +762,7 @@ fn render_remote_button(
|
|||
keybinding_target: Option<FocusHandle>,
|
||||
show_fetch_button: bool,
|
||||
in_progress_operation: Option<RemoteOperationKind>,
|
||||
menu_handle: PopoverMenuHandle<ContextMenu>,
|
||||
) -> Option<impl IntoElement> {
|
||||
let id = id.into();
|
||||
let upstream = branch.upstream.as_ref();
|
||||
|
|
@ -778,6 +775,7 @@ fn render_remote_button(
|
|||
keybinding_target,
|
||||
id,
|
||||
in_progress_operation,
|
||||
menu_handle,
|
||||
)),
|
||||
(0, 0) => None,
|
||||
(ahead, 0) => Some(remote_button::render_push_button(
|
||||
|
|
@ -785,6 +783,7 @@ fn render_remote_button(
|
|||
id,
|
||||
ahead,
|
||||
in_progress_operation,
|
||||
menu_handle,
|
||||
)),
|
||||
(ahead, behind) => Some(remote_button::render_pull_button(
|
||||
keybinding_target,
|
||||
|
|
@ -792,6 +791,7 @@ fn render_remote_button(
|
|||
ahead,
|
||||
behind,
|
||||
in_progress_operation,
|
||||
menu_handle,
|
||||
)),
|
||||
},
|
||||
Some(Upstream {
|
||||
|
|
@ -801,11 +801,13 @@ fn render_remote_button(
|
|||
keybinding_target,
|
||||
id,
|
||||
in_progress_operation,
|
||||
menu_handle,
|
||||
)),
|
||||
None => Some(remote_button::render_publish_button(
|
||||
keybinding_target,
|
||||
id,
|
||||
in_progress_operation,
|
||||
menu_handle,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
|
@ -813,12 +815,16 @@ fn render_remote_button(
|
|||
mod remote_button {
|
||||
use crate::git_panel::RemoteOperationKind;
|
||||
use gpui::{Action, Anchor, AnyView, ClickEvent, FocusHandle};
|
||||
use ui::{CommonAnimationExt, ContextMenu, PopoverMenu, SplitButton, Tooltip, prelude::*};
|
||||
use ui::{
|
||||
ButtonLike, CommonAnimationExt, ContextMenu, ElevationIndex, PopoverMenu,
|
||||
PopoverMenuHandle, SplitButton, Tooltip, prelude::*,
|
||||
};
|
||||
|
||||
pub fn render_fetch_button(
|
||||
keybinding_target: Option<FocusHandle>,
|
||||
id: SharedString,
|
||||
in_progress_operation: Option<RemoteOperationKind>,
|
||||
menu_handle: PopoverMenuHandle<ContextMenu>,
|
||||
) -> SplitButton {
|
||||
split_button(
|
||||
id,
|
||||
|
|
@ -828,6 +834,7 @@ mod remote_button {
|
|||
Some(IconName::ArrowCircle),
|
||||
keybinding_target.clone(),
|
||||
in_progress_operation,
|
||||
menu_handle,
|
||||
move |_, window, cx| {
|
||||
window.dispatch_action(Box::new(git::Fetch), cx);
|
||||
},
|
||||
|
|
@ -848,6 +855,7 @@ mod remote_button {
|
|||
id: SharedString,
|
||||
ahead: u32,
|
||||
in_progress_operation: Option<RemoteOperationKind>,
|
||||
menu_handle: PopoverMenuHandle<ContextMenu>,
|
||||
) -> SplitButton {
|
||||
split_button(
|
||||
id,
|
||||
|
|
@ -857,6 +865,7 @@ mod remote_button {
|
|||
None,
|
||||
keybinding_target.clone(),
|
||||
in_progress_operation,
|
||||
menu_handle,
|
||||
move |_, window, cx| {
|
||||
window.dispatch_action(Box::new(git::Push), cx);
|
||||
},
|
||||
|
|
@ -878,6 +887,7 @@ mod remote_button {
|
|||
ahead: u32,
|
||||
behind: u32,
|
||||
in_progress_operation: Option<RemoteOperationKind>,
|
||||
menu_handle: PopoverMenuHandle<ContextMenu>,
|
||||
) -> SplitButton {
|
||||
split_button(
|
||||
id,
|
||||
|
|
@ -887,6 +897,7 @@ mod remote_button {
|
|||
None,
|
||||
keybinding_target.clone(),
|
||||
in_progress_operation,
|
||||
menu_handle,
|
||||
move |_, window, cx| {
|
||||
window.dispatch_action(Box::new(git::Pull), cx);
|
||||
},
|
||||
|
|
@ -906,6 +917,7 @@ mod remote_button {
|
|||
keybinding_target: Option<FocusHandle>,
|
||||
id: SharedString,
|
||||
in_progress_operation: Option<RemoteOperationKind>,
|
||||
menu_handle: PopoverMenuHandle<ContextMenu>,
|
||||
) -> SplitButton {
|
||||
split_button(
|
||||
id,
|
||||
|
|
@ -915,6 +927,7 @@ mod remote_button {
|
|||
Some(IconName::ExpandUp),
|
||||
keybinding_target.clone(),
|
||||
in_progress_operation,
|
||||
menu_handle,
|
||||
move |_, window, cx| {
|
||||
window.dispatch_action(Box::new(git::Push), cx);
|
||||
},
|
||||
|
|
@ -934,6 +947,7 @@ mod remote_button {
|
|||
keybinding_target: Option<FocusHandle>,
|
||||
id: SharedString,
|
||||
in_progress_operation: Option<RemoteOperationKind>,
|
||||
menu_handle: PopoverMenuHandle<ContextMenu>,
|
||||
) -> SplitButton {
|
||||
split_button(
|
||||
id,
|
||||
|
|
@ -943,6 +957,7 @@ mod remote_button {
|
|||
Some(IconName::ExpandUp),
|
||||
keybinding_target.clone(),
|
||||
in_progress_operation,
|
||||
menu_handle,
|
||||
move |_, window, cx| {
|
||||
window.dispatch_action(Box::new(git::Push), cx);
|
||||
},
|
||||
|
|
@ -986,18 +1001,16 @@ mod remote_button {
|
|||
fn render_git_action_menu(
|
||||
id: impl Into<ElementId>,
|
||||
keybinding_target: Option<FocusHandle>,
|
||||
menu_handle: PopoverMenuHandle<ContextMenu>,
|
||||
) -> impl IntoElement {
|
||||
let menu_open = menu_handle.is_deployed();
|
||||
|
||||
PopoverMenu::new(id.into())
|
||||
.trigger(
|
||||
ui::ButtonLike::new_rounded_right("split-button-right")
|
||||
.layer(ui::ElevationIndex::ModalSurface)
|
||||
.size(ui::ButtonSize::None)
|
||||
.child(
|
||||
div()
|
||||
.px_1()
|
||||
.child(Icon::new(IconName::ChevronDown).size(IconSize::XSmall)),
|
||||
),
|
||||
)
|
||||
.trigger(crate::render_split_button_chevron_trigger(
|
||||
"split-button-right",
|
||||
menu_open,
|
||||
))
|
||||
.with_handle(menu_handle)
|
||||
.menu(move |window, cx| {
|
||||
Some(ContextMenu::build(window, cx, |context_menu, _, _| {
|
||||
context_menu
|
||||
|
|
@ -1015,6 +1028,10 @@ mod remote_button {
|
|||
}))
|
||||
})
|
||||
.anchor(Anchor::TopRight)
|
||||
.offset(gpui::Point {
|
||||
x: px(0.),
|
||||
y: px(2.),
|
||||
})
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
|
|
@ -1026,6 +1043,7 @@ mod remote_button {
|
|||
left_icon: Option<IconName>,
|
||||
keybinding_target: Option<FocusHandle>,
|
||||
in_progress_operation: Option<RemoteOperationKind>,
|
||||
menu_handle: PopoverMenuHandle<ContextMenu>,
|
||||
left_on_click: impl Fn(&ClickEvent, &mut Window, &mut App) + 'static,
|
||||
tooltip: impl Fn(&mut Window, &mut App) -> AnyView + 'static,
|
||||
) -> SplitButton {
|
||||
|
|
@ -1033,7 +1051,6 @@ mod remote_button {
|
|||
h_flex()
|
||||
.ml_neg_px()
|
||||
.h(rems(0.875))
|
||||
.items_center()
|
||||
.overflow_hidden()
|
||||
.px_0p5()
|
||||
.child(
|
||||
|
|
@ -1046,58 +1063,57 @@ mod remote_button {
|
|||
let should_render_counts = left_icon.is_none() && (ahead_count > 0 || behind_count > 0);
|
||||
let is_in_progress = in_progress_operation.is_some();
|
||||
|
||||
let left = ui::ButtonLike::new_rounded_left(ElementId::Name(
|
||||
format!("split-button-left-{}", id).into(),
|
||||
))
|
||||
.layer(ui::ElevationIndex::ModalSurface)
|
||||
.size(ui::ButtonSize::Compact)
|
||||
.disabled(is_in_progress)
|
||||
.when(should_render_counts, |this| {
|
||||
this.child(
|
||||
h_flex()
|
||||
.ml_neg_0p5()
|
||||
.when(behind_count > 0, |this| {
|
||||
this.child(Icon::new(IconName::ArrowDown).size(IconSize::XSmall))
|
||||
.child(count(behind_count))
|
||||
})
|
||||
.when(ahead_count > 0, |this| {
|
||||
this.child(Icon::new(IconName::ArrowUp).size(IconSize::XSmall))
|
||||
.child(count(ahead_count))
|
||||
}),
|
||||
)
|
||||
})
|
||||
.when_some(left_icon, |this, left_icon| {
|
||||
this.map(|this| {
|
||||
if is_in_progress {
|
||||
this.child(
|
||||
Icon::new(IconName::LoadCircle)
|
||||
.size(IconSize::XSmall)
|
||||
.color(Color::Disabled)
|
||||
.with_rotate_animation(2),
|
||||
)
|
||||
} else {
|
||||
this.child(Icon::new(left_icon).size(IconSize::XSmall))
|
||||
}
|
||||
let left = ButtonLike::new_rounded_left(format!("split-button-left-{}", id))
|
||||
.layer(ElevationIndex::ModalSurface)
|
||||
.size(ButtonSize::Compact)
|
||||
.disabled(is_in_progress)
|
||||
.when(should_render_counts, |this| {
|
||||
this.child(
|
||||
h_flex()
|
||||
.ml_neg_0p5()
|
||||
.when(behind_count > 0, |this| {
|
||||
this.child(Icon::new(IconName::ArrowDown).size(IconSize::XSmall))
|
||||
.child(count(behind_count))
|
||||
})
|
||||
.when(ahead_count > 0, |this| {
|
||||
this.child(Icon::new(IconName::ArrowUp).size(IconSize::XSmall))
|
||||
.child(count(ahead_count))
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
.child(
|
||||
Label::new(left_label)
|
||||
.size(LabelSize::Small)
|
||||
.when(is_in_progress, |this| this.color(Color::Disabled))
|
||||
.mr_0p5(),
|
||||
)
|
||||
.on_click(left_on_click)
|
||||
.tooltip(move |window, cx| {
|
||||
if let Some(operation) = in_progress_operation {
|
||||
Tooltip::simple(in_progress_tooltip(operation), cx)
|
||||
} else {
|
||||
tooltip(window, cx)
|
||||
}
|
||||
});
|
||||
.when_some(left_icon, |this, left_icon| {
|
||||
this.map(|this| {
|
||||
if is_in_progress {
|
||||
this.child(
|
||||
Icon::new(IconName::LoadCircle)
|
||||
.size(IconSize::XSmall)
|
||||
.color(Color::Disabled)
|
||||
.with_rotate_animation(2),
|
||||
)
|
||||
} else {
|
||||
this.child(Icon::new(left_icon).size(IconSize::XSmall))
|
||||
}
|
||||
})
|
||||
})
|
||||
.child(
|
||||
Label::new(left_label)
|
||||
.size(LabelSize::Small)
|
||||
.when(is_in_progress, |this| this.color(Color::Disabled))
|
||||
.mr_0p5(),
|
||||
)
|
||||
.on_click(left_on_click)
|
||||
.tooltip(move |window, cx| {
|
||||
if let Some(operation) = in_progress_operation {
|
||||
Tooltip::simple(in_progress_tooltip(operation), cx)
|
||||
} else {
|
||||
tooltip(window, cx)
|
||||
}
|
||||
});
|
||||
|
||||
let right = render_git_action_menu(
|
||||
ElementId::Name(format!("split-button-right-{}", id).into()),
|
||||
format!("split-button-right-{}", id),
|
||||
keybinding_target,
|
||||
menu_handle,
|
||||
)
|
||||
.into_any_element();
|
||||
|
||||
|
|
@ -1105,6 +1121,25 @@ mod remote_button {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn render_split_button_chevron_trigger(
|
||||
id: impl Into<ElementId>,
|
||||
menu_open: bool,
|
||||
) -> ButtonLike {
|
||||
let chevron_button_size = rems_from_px(20.);
|
||||
let chevron_icon = if menu_open {
|
||||
IconName::ChevronUp
|
||||
} else {
|
||||
IconName::ChevronDown
|
||||
};
|
||||
|
||||
ButtonLike::new_rounded_right(id)
|
||||
.layer(ElevationIndex::ModalSurface)
|
||||
.selected_style(ButtonStyle::Tinted(TintColor::Accent))
|
||||
.width(chevron_button_size)
|
||||
.height(chevron_button_size.into())
|
||||
.child(Icon::new(chevron_icon).size(IconSize::XSmall))
|
||||
}
|
||||
|
||||
/// A visual representation of a file's Git status.
|
||||
#[derive(IntoElement, RegisterComponent)]
|
||||
pub struct GitStatusIcon {
|
||||
|
|
|
|||
|
|
@ -40,7 +40,6 @@ use std::sync::Arc;
|
|||
use theme::ActiveTheme;
|
||||
use ui::{
|
||||
CommonAnimationExt as _, DiffStat, Divider, KeyBinding, PopoverMenu, Tooltip, prelude::*,
|
||||
vertical_divider,
|
||||
};
|
||||
use util::{ResultExt as _, rel_path::RelPath};
|
||||
use workspace::{
|
||||
|
|
@ -1739,16 +1738,59 @@ impl Render for ProjectDiffToolbar {
|
|||
let button_states = project_diff.read(cx).button_states(cx);
|
||||
let review_count = project_diff.read(cx).total_review_comment_count();
|
||||
|
||||
h_group_xl()
|
||||
let (additions, deletions) = project_diff.read(cx).calculate_changed_lines(cx);
|
||||
let is_multibuffer_empty = project_diff.read(cx).multibuffer.read(cx).is_empty();
|
||||
|
||||
h_flex()
|
||||
.my_neg_1()
|
||||
.py_1()
|
||||
.items_center()
|
||||
.gap_1p5()
|
||||
.flex_wrap()
|
||||
.justify_between()
|
||||
.when(!is_multibuffer_empty, |this| {
|
||||
this.child(DiffStat::new(
|
||||
"project-diff-stat",
|
||||
additions as usize,
|
||||
deletions as usize,
|
||||
))
|
||||
.child(Divider::vertical().ml_1())
|
||||
})
|
||||
// n.b. the only reason these arrows are here is because we don't
|
||||
// support "undo" for staging so we need a way to go back.
|
||||
.child(
|
||||
h_group_sm()
|
||||
.when(button_states.selection, |el| {
|
||||
el.child(
|
||||
.child(
|
||||
IconButton::new("up", IconName::ArrowUp)
|
||||
.icon_size(IconSize::Small)
|
||||
.disabled(!button_states.prev_next)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Go to Previous Hunk",
|
||||
&GoToPreviousHunk,
|
||||
&focus_handle,
|
||||
))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&GoToPreviousHunk, window, cx)
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
IconButton::new("down", IconName::ArrowDown)
|
||||
.icon_size(IconSize::Small)
|
||||
.disabled(!button_states.prev_next)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Go to Next Hunk",
|
||||
&GoToHunk,
|
||||
&focus_handle,
|
||||
))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&GoToHunk, window, cx)
|
||||
})),
|
||||
),
|
||||
)
|
||||
.child(Divider::vertical())
|
||||
.child(
|
||||
h_group_sm()
|
||||
.when(button_states.selection, |this| {
|
||||
this.child(
|
||||
Button::new("stage", "Toggle Staged")
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Toggle Staged",
|
||||
|
|
@ -1761,127 +1803,83 @@ impl Render for ProjectDiffToolbar {
|
|||
})),
|
||||
)
|
||||
})
|
||||
.when(!button_states.selection, |el| {
|
||||
el.child(
|
||||
.when(!button_states.selection, |this| {
|
||||
this.child(
|
||||
Button::new("stage", "Stage")
|
||||
.disabled(!button_states.stage)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Stage and go to next hunk",
|
||||
"Stage and Go to Next Hunk",
|
||||
&StageAndNext,
|
||||
&focus_handle,
|
||||
))
|
||||
.disabled(
|
||||
!button_states.prev_next
|
||||
&& !button_states.stage_all
|
||||
&& !button_states.unstage_all,
|
||||
)
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&StageAndNext, window, cx)
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
Button::new("unstage", "Unstage")
|
||||
.disabled(!button_states.unstage)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Unstage and go to next hunk",
|
||||
"Unstage and Go to Next Hunk",
|
||||
&UnstageAndNext,
|
||||
&focus_handle,
|
||||
))
|
||||
.disabled(
|
||||
!button_states.prev_next
|
||||
&& !button_states.stage_all
|
||||
&& !button_states.unstage_all,
|
||||
)
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&UnstageAndNext, window, cx)
|
||||
})),
|
||||
)
|
||||
}),
|
||||
)
|
||||
// n.b. the only reason these arrows are here is because we don't
|
||||
// support "undo" for staging so we need a way to go back.
|
||||
.child(
|
||||
h_group_sm()
|
||||
.child(
|
||||
IconButton::new("up", IconName::ArrowUp)
|
||||
.shape(ui::IconButtonShape::Square)
|
||||
.child(Divider::vertical())
|
||||
.when(
|
||||
button_states.unstage_all && !button_states.stage_all,
|
||||
|this| {
|
||||
this.child(
|
||||
Button::new("unstage-all", "Unstage All")
|
||||
.width(rems_from_px(80.))
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Go to previous hunk",
|
||||
&GoToPreviousHunk,
|
||||
"Unstage All Changes",
|
||||
&UnstageAll,
|
||||
&focus_handle,
|
||||
))
|
||||
.disabled(!button_states.prev_next)
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&GoToPreviousHunk, window, cx)
|
||||
})),
|
||||
.on_click(
|
||||
cx.listener(|this, _, window, cx| this.unstage_all(window, cx)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
IconButton::new("down", IconName::ArrowDown)
|
||||
.shape(ui::IconButtonShape::Square)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Go to next hunk",
|
||||
&GoToHunk,
|
||||
&focus_handle,
|
||||
))
|
||||
.disabled(!button_states.prev_next)
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&GoToHunk, window, cx)
|
||||
})),
|
||||
),
|
||||
},
|
||||
)
|
||||
.child(vertical_divider())
|
||||
.child(
|
||||
h_group_sm()
|
||||
.when(
|
||||
button_states.unstage_all && !button_states.stage_all,
|
||||
|el| {
|
||||
el.child(
|
||||
Button::new("unstage-all", "Unstage All")
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Unstage all changes",
|
||||
&UnstageAll,
|
||||
&focus_handle,
|
||||
))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.unstage_all(window, cx)
|
||||
})),
|
||||
)
|
||||
},
|
||||
)
|
||||
.when(
|
||||
!button_states.unstage_all || button_states.stage_all,
|
||||
|el| {
|
||||
el.child(
|
||||
// todo make it so that changing to say "Unstaged"
|
||||
// doesn't change the position.
|
||||
div().child(
|
||||
Button::new("stage-all", "Stage All")
|
||||
.disabled(!button_states.stage_all)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Stage all changes",
|
||||
&StageAll,
|
||||
&focus_handle,
|
||||
))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.stage_all(window, cx)
|
||||
})),
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
.child(
|
||||
Button::new("commit", "Commit")
|
||||
.when(
|
||||
!button_states.unstage_all || button_states.stage_all,
|
||||
|this| {
|
||||
this.child(
|
||||
Button::new("stage-all", "Stage All")
|
||||
.width(rems_from_px(80.))
|
||||
.disabled(!button_states.stage_all)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Commit",
|
||||
&Commit,
|
||||
"Stage All Changes",
|
||||
&StageAll,
|
||||
&focus_handle,
|
||||
))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&Commit, window, cx);
|
||||
})),
|
||||
),
|
||||
.on_click(
|
||||
cx.listener(|this, _, window, cx| this.stage_all(window, cx)),
|
||||
),
|
||||
)
|
||||
},
|
||||
)
|
||||
.child(Divider::vertical())
|
||||
.child(
|
||||
Button::new("commit", "Commit")
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Commit",
|
||||
&Commit,
|
||||
&focus_handle,
|
||||
))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&Commit, window, cx);
|
||||
})),
|
||||
)
|
||||
// "Send Review to Agent" button (only shown when there are review comments)
|
||||
.when(review_count > 0, |el| {
|
||||
el.child(vertical_divider()).child(
|
||||
el.child(Divider::vertical()).child(
|
||||
render_send_review_to_agent_button(review_count, &focus_handle).on_click(
|
||||
cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&SendReviewToAgent, window, cx)
|
||||
|
|
@ -1985,13 +1983,20 @@ impl Render for BranchDiffToolbar {
|
|||
|
||||
let show_review_button = !is_multibuffer_empty && is_ai_enabled;
|
||||
|
||||
h_group_xl()
|
||||
h_flex()
|
||||
.my_neg_1()
|
||||
.py_1()
|
||||
.items_center()
|
||||
.gap_1p5()
|
||||
.flex_wrap()
|
||||
.justify_end()
|
||||
.gap_2()
|
||||
.justify_between()
|
||||
.when(!is_multibuffer_empty, |this| {
|
||||
this.child(DiffStat::new(
|
||||
"branch-diff-stat",
|
||||
additions as usize,
|
||||
deletions as usize,
|
||||
))
|
||||
})
|
||||
.child(Divider::vertical().ml_1())
|
||||
.child(
|
||||
PopoverMenu::new("branch-diff-base-branch-picker")
|
||||
.menu(move |window, cx| {
|
||||
|
|
@ -2013,6 +2018,7 @@ impl Render for BranchDiffToolbar {
|
|||
.ok();
|
||||
},
|
||||
);
|
||||
|
||||
Some(branch_picker::select_popover(
|
||||
workspace.clone(),
|
||||
repository.clone(),
|
||||
|
|
@ -2023,23 +2029,14 @@ impl Render for BranchDiffToolbar {
|
|||
))
|
||||
})
|
||||
.trigger_with_tooltip(
|
||||
Button::new("branch-diff-base-branch", base_ref_label)
|
||||
.color(Color::Muted)
|
||||
.end_icon(
|
||||
Icon::new(IconName::ChevronDown)
|
||||
.size(IconSize::XSmall)
|
||||
.color(Color::Muted),
|
||||
),
|
||||
Tooltip::text("Select base branch"),
|
||||
Button::new("branch-diff-base-branch", base_ref_label).end_icon(
|
||||
Icon::new(IconName::ChevronDown)
|
||||
.size(IconSize::XSmall)
|
||||
.color(Color::Muted),
|
||||
),
|
||||
Tooltip::text("Select Base Branch"),
|
||||
),
|
||||
)
|
||||
.when(!is_multibuffer_empty, |this| {
|
||||
this.child(DiffStat::new(
|
||||
"branch-diff-stat",
|
||||
additions as usize,
|
||||
deletions as usize,
|
||||
))
|
||||
})
|
||||
.when(show_review_button, |this| {
|
||||
let focus_handle = focus_handle.clone();
|
||||
this.child(Divider::vertical()).child(
|
||||
|
|
@ -2049,7 +2046,6 @@ impl Render for BranchDiffToolbar {
|
|||
.size(IconSize::Small)
|
||||
.color(Color::Muted),
|
||||
)
|
||||
.key_binding(KeyBinding::for_action_in(&ReviewDiff, &focus_handle, cx))
|
||||
.tooltip(move |_, cx| {
|
||||
Tooltip::with_meta_in(
|
||||
"Review Diff",
|
||||
|
|
@ -2065,7 +2061,7 @@ impl Render for BranchDiffToolbar {
|
|||
)
|
||||
})
|
||||
.when(review_count > 0, |this| {
|
||||
this.child(vertical_divider()).child(
|
||||
this.child(Divider::vertical()).child(
|
||||
render_send_review_to_agent_button(review_count, &focus_handle).on_click(
|
||||
cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&SendReviewToAgent, window, cx)
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
use crate::{git_panel::GitStatusEntry, git_status_icon};
|
||||
use crate::{git_panel::GitStatusEntry, git_panel_settings::GitPanelSettings, git_status_icon};
|
||||
use anyhow::{Context as _, Result};
|
||||
use buffer_diff::DiffHunkSecondaryStatus;
|
||||
use editor::{
|
||||
Direction, Editor, EditorEvent, EditorSettings, SplittableEditor, ToggleSplitDiff,
|
||||
DiffStyleControls, Direction, Editor, EditorEvent, EditorSettings, SplittableEditor,
|
||||
ToggleSplitDiff,
|
||||
actions::{GoToHunk, GoToPreviousHunk},
|
||||
file_status_label_color,
|
||||
};
|
||||
use fs::Fs;
|
||||
use git::{
|
||||
Commit, Restore, StageAndNext, StageFile, ToggleStaged, UnstageAndNext, UnstageFile,
|
||||
repository::RepoPath, status::StageStatus,
|
||||
};
|
||||
use gpui::{
|
||||
Action, AnyElement, App, AppContext as _, Context, Entity, EventEmitter, FocusHandle,
|
||||
Focusable, IntoElement, Render, Subscription, Task, WeakEntity, Window,
|
||||
Action, AnyElement, App, AppContext as _, Context, Empty, Entity, EventEmitter, FocusHandle,
|
||||
Focusable, HighlightStyle, IntoElement, Render, Subscription, Task, WeakEntity, Window,
|
||||
};
|
||||
use language::{Anchor, Buffer, HighlightedText, OffsetRangeExt as _, Point};
|
||||
use multi_buffer::{MultiBuffer, PathKey, excerpt_context_lines};
|
||||
|
|
@ -20,16 +21,13 @@ use project::{
|
|||
Project,
|
||||
git_store::{Repository, RepositoryId},
|
||||
};
|
||||
use settings::{DiffViewStyle, Settings, SettingsStore, update_settings_file};
|
||||
use settings::{Settings, SettingsStore, StatusStyle};
|
||||
use std::{
|
||||
any::{Any, TypeId},
|
||||
ops::Range,
|
||||
sync::Arc,
|
||||
};
|
||||
use ui::{
|
||||
Color, DiffStat, Divider, Icon, IconButton, IconButtonShape, IconName, Label, LabelCommon as _,
|
||||
SharedString, Tooltip, prelude::*, vertical_divider,
|
||||
};
|
||||
use ui::{DiffStat, Divider, Tooltip, prelude::*};
|
||||
use util::paths::{PathExt as _, PathStyle};
|
||||
use workspace::{
|
||||
Item, ItemHandle, ItemNavHistory, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView,
|
||||
|
|
@ -479,16 +477,31 @@ impl Item for SoloDiffView {
|
|||
}
|
||||
|
||||
fn breadcrumbs(&self, cx: &App) -> Option<(Vec<HighlightedText>, Option<gpui::Font>)> {
|
||||
let text: SharedString = self
|
||||
.repo_path
|
||||
.as_ref()
|
||||
.display(PathStyle::local())
|
||||
.into_owned()
|
||||
.into();
|
||||
|
||||
// When the git panel is set to convey status via label color rather
|
||||
// than an icon, tint the whole path like multibuffer headers do.
|
||||
let mut highlights = Vec::new();
|
||||
if GitPanelSettings::get_global(cx).status_style == StatusStyle::LabelColor
|
||||
&& let Some(status) = self
|
||||
.repository
|
||||
.read(cx)
|
||||
.status_for_path(&self.repo_path)
|
||||
.map(|entry| entry.status)
|
||||
{
|
||||
highlights.push((
|
||||
0..text.len(),
|
||||
HighlightStyle::color(file_status_label_color(Some(status)).color(cx)),
|
||||
));
|
||||
}
|
||||
|
||||
Some((
|
||||
vec![HighlightedText {
|
||||
text: self
|
||||
.repo_path
|
||||
.as_ref()
|
||||
.display(PathStyle::local())
|
||||
.into_owned()
|
||||
.into(),
|
||||
highlights: Vec::new(),
|
||||
}],
|
||||
vec![HighlightedText { text, highlights }],
|
||||
Some(
|
||||
theme_settings::ThemeSettings::get_global(cx)
|
||||
.buffer_font
|
||||
|
|
@ -548,43 +561,6 @@ impl SoloDiffStyleToolbar {
|
|||
self.solo_diff.as_ref()?.upgrade()
|
||||
}
|
||||
|
||||
fn set_diff_view_style(
|
||||
&mut self,
|
||||
diff_view_style: DiffViewStyle,
|
||||
window: &mut Window,
|
||||
cx: &mut Context<Self>,
|
||||
) {
|
||||
let Some(solo_diff) = self.solo_diff() else {
|
||||
return;
|
||||
};
|
||||
let workspace = solo_diff.read(cx).workspace.clone();
|
||||
|
||||
update_settings_file(<dyn Fs>::global(cx), cx, move |settings, _| {
|
||||
settings.editor.diff_view_style = Some(diff_view_style);
|
||||
});
|
||||
|
||||
if let Some(workspace) = workspace.upgrade() {
|
||||
let splittable_editors = {
|
||||
workspace
|
||||
.read(cx)
|
||||
.items(cx)
|
||||
.filter_map(|item| item.act_as_type(TypeId::of::<SplittableEditor>(), cx))
|
||||
.filter_map(|item| item.downcast::<SplittableEditor>().ok())
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
for editor in splittable_editors {
|
||||
editor.update(cx, |editor, cx| {
|
||||
if editor.diff_view_style() != diff_view_style {
|
||||
editor.toggle_split(&ToggleSplitDiff, window, cx);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn toggle_showing_full_file(&mut self, cx: &mut Context<Self>) {
|
||||
if let Some(solo_diff) = self.solo_diff() {
|
||||
solo_diff.update(cx, |solo_diff, cx| {
|
||||
|
|
@ -617,64 +593,49 @@ impl ToolbarItemView for SoloDiffStyleToolbar {
|
|||
impl Render for SoloDiffStyleToolbar {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let Some(solo_diff) = self.solo_diff() else {
|
||||
return div();
|
||||
return Empty.into_any_element();
|
||||
};
|
||||
let (editor_entity, showing_full_file) = {
|
||||
|
||||
let (editor_entity, showing_full_file, status) = {
|
||||
let solo_diff = solo_diff.read(cx);
|
||||
(solo_diff.editor.clone(), solo_diff.showing_full_file)
|
||||
(
|
||||
solo_diff.editor.clone(),
|
||||
solo_diff.showing_full_file,
|
||||
solo_diff
|
||||
.repository
|
||||
.read(cx)
|
||||
.status_for_path(&solo_diff.repo_path)
|
||||
.map(|entry| entry.status),
|
||||
)
|
||||
};
|
||||
let editor = editor_entity.read(cx);
|
||||
let diff_view_style = editor.diff_view_style();
|
||||
let is_split_set = diff_view_style == DiffViewStyle::Split;
|
||||
let split_icon = if is_split_set && !editor.is_split() {
|
||||
IconName::DiffSplitAuto
|
||||
|
||||
let show_status_icon =
|
||||
GitPanelSettings::get_global(cx).status_style != StatusStyle::LabelColor;
|
||||
|
||||
let (expand_icon, expand_tooltip) = if showing_full_file {
|
||||
(IconName::ChevronDownUp, "Show Changes Only")
|
||||
} else {
|
||||
IconName::DiffSplit
|
||||
(IconName::ChevronUpDown, "Show Full File")
|
||||
};
|
||||
|
||||
h_flex()
|
||||
.h_8()
|
||||
.items_center()
|
||||
.pl_0p5()
|
||||
.gap_1()
|
||||
.child(
|
||||
IconButton::new(
|
||||
"solo-diff-toggle-excerpts",
|
||||
if showing_full_file {
|
||||
IconName::ChevronDownUp
|
||||
} else {
|
||||
IconName::ChevronUpDown
|
||||
},
|
||||
)
|
||||
.icon_size(IconSize::Small)
|
||||
.tooltip(Tooltip::text(if showing_full_file {
|
||||
"Show Changes Only"
|
||||
} else {
|
||||
"Show Full File"
|
||||
}))
|
||||
.on_click(cx.listener(|this, _, _, cx| {
|
||||
this.toggle_showing_full_file(cx);
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
IconButton::new("solo-diff-unified", IconName::DiffUnified)
|
||||
IconButton::new("solo-diff-toggle-excerpts", expand_icon)
|
||||
.icon_size(IconSize::Small)
|
||||
.toggle_state(diff_view_style == DiffViewStyle::Unified)
|
||||
.tooltip(Tooltip::text("Unified"))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.set_diff_view_style(DiffViewStyle::Unified, window, cx);
|
||||
.tooltip(Tooltip::text(expand_tooltip))
|
||||
.on_click(cx.listener(|this, _, _, cx| {
|
||||
this.toggle_showing_full_file(cx);
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
IconButton::new("solo-diff-split", split_icon)
|
||||
.icon_size(IconSize::Small)
|
||||
.toggle_state(diff_view_style == DiffViewStyle::Split)
|
||||
.tooltip(Tooltip::text("Split"))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.set_diff_view_style(DiffViewStyle::Split, window, cx);
|
||||
})),
|
||||
.child(DiffStyleControls::new(editor_entity))
|
||||
.child(Divider::vertical().mr_1())
|
||||
.when_some(
|
||||
show_status_icon.then_some(status).flatten(),
|
||||
|this, status| this.child(git_status_icon(status)),
|
||||
)
|
||||
.child(vertical_divider())
|
||||
.child(div().w_1())
|
||||
.into_any_element()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -745,8 +706,9 @@ struct SoloDiffButtonStates {
|
|||
impl Render for SoloDiffGitToolbar {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let Some(solo_diff) = self.solo_diff() else {
|
||||
return div();
|
||||
return gpui::Empty.into_any_element();
|
||||
};
|
||||
|
||||
let focus_handle = solo_diff.focus_handle(cx);
|
||||
let solo_diff = solo_diff.read(cx);
|
||||
let button_states = solo_diff.button_states(cx);
|
||||
|
|
@ -754,32 +716,59 @@ impl Render for SoloDiffGitToolbar {
|
|||
.repository
|
||||
.read(cx)
|
||||
.status_for_path(&solo_diff.repo_path);
|
||||
let status = status_entry.as_ref().map(|entry| entry.status);
|
||||
let diff_stat = status_entry.and_then(|entry| entry.diff_stat);
|
||||
|
||||
h_group_xl()
|
||||
h_flex()
|
||||
.my_neg_1()
|
||||
.py_1()
|
||||
.items_center()
|
||||
.gap_1p5()
|
||||
.flex_wrap()
|
||||
.justify_between()
|
||||
.children(status.map(|status| git_status_icon(status).into_any_element()))
|
||||
.children(diff_stat.map(|stat| {
|
||||
DiffStat::new("solo-diff-stat", stat.added as usize, stat.deleted as usize)
|
||||
.into_any_element()
|
||||
}))
|
||||
.child(Divider::vertical().ml_1())
|
||||
.child(
|
||||
h_group_sm()
|
||||
.child(
|
||||
IconButton::new("up", IconName::ArrowUp)
|
||||
.icon_size(IconSize::Small)
|
||||
.disabled(!button_states.prev_next)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Go to Previous Hunk",
|
||||
&GoToPreviousHunk,
|
||||
&focus_handle,
|
||||
))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&GoToPreviousHunk, window, cx)
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
IconButton::new("down", IconName::ArrowDown)
|
||||
.icon_size(IconSize::Small)
|
||||
.disabled(!button_states.prev_next)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Go to Next Hunk",
|
||||
&GoToHunk,
|
||||
&focus_handle,
|
||||
))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&GoToHunk, window, cx)
|
||||
})),
|
||||
),
|
||||
)
|
||||
.child(Divider::vertical())
|
||||
.child(
|
||||
h_group_sm()
|
||||
.when(button_states.selection, |el| {
|
||||
el.child(
|
||||
Button::new("stage", "Toggle Staged")
|
||||
.disabled(!button_states.stage && !button_states.unstage)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Toggle Staged",
|
||||
&ToggleStaged,
|
||||
&focus_handle,
|
||||
))
|
||||
.disabled(!button_states.stage && !button_states.unstage)
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&ToggleStaged, window, cx)
|
||||
})),
|
||||
|
|
@ -788,24 +777,24 @@ impl Render for SoloDiffGitToolbar {
|
|||
.when(!button_states.selection, |el| {
|
||||
el.child(
|
||||
Button::new("stage", "Stage")
|
||||
.disabled(!button_states.stage)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Stage and go to next hunk",
|
||||
"Stage and Go to Next Hunk",
|
||||
&StageAndNext,
|
||||
&focus_handle,
|
||||
))
|
||||
.disabled(!button_states.stage)
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&StageAndNext, window, cx)
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
Button::new("unstage", "Unstage")
|
||||
.disabled(!button_states.unstage)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Unstage and go to next hunk",
|
||||
"Unstage and Go to Next Hunk",
|
||||
&UnstageAndNext,
|
||||
&focus_handle,
|
||||
))
|
||||
.disabled(!button_states.unstage)
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&UnstageAndNext, window, cx)
|
||||
})),
|
||||
|
|
@ -824,72 +813,40 @@ impl Render for SoloDiffGitToolbar {
|
|||
})),
|
||||
),
|
||||
)
|
||||
.child(Divider::vertical())
|
||||
.child(h_group_sm().child(if button_states.stage_file {
|
||||
Button::new("stage-file", "Stage All")
|
||||
.width(rems_from_px(80.))
|
||||
.disabled(!button_states.stage_file)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Stage All",
|
||||
&StageFile,
|
||||
&focus_handle,
|
||||
))
|
||||
.on_click(cx.listener(|this, _, window, cx| this.stage_file(window, cx)))
|
||||
} else {
|
||||
Button::new("unstage-file", "Unstage All")
|
||||
.width(rems_from_px(80.))
|
||||
.disabled(!button_states.unstage_file)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Unstage All",
|
||||
&UnstageFile,
|
||||
&focus_handle,
|
||||
))
|
||||
.on_click(cx.listener(|this, _, window, cx| this.unstage_file(window, cx)))
|
||||
}))
|
||||
.child(Divider::vertical())
|
||||
.child(
|
||||
h_group_sm()
|
||||
.child(
|
||||
IconButton::new("up", IconName::ArrowUp)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Go to previous hunk",
|
||||
&GoToPreviousHunk,
|
||||
&focus_handle,
|
||||
))
|
||||
.disabled(!button_states.prev_next)
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&GoToPreviousHunk, window, cx)
|
||||
})),
|
||||
)
|
||||
.child(
|
||||
IconButton::new("down", IconName::ArrowDown)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Go to next hunk",
|
||||
&GoToHunk,
|
||||
&focus_handle,
|
||||
))
|
||||
.disabled(!button_states.prev_next)
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&GoToHunk, window, cx)
|
||||
})),
|
||||
),
|
||||
)
|
||||
.child(vertical_divider())
|
||||
.child(
|
||||
h_group_sm()
|
||||
.child(if button_states.stage_file {
|
||||
Button::new("stage-file", "Stage File")
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Stage file",
|
||||
&StageFile,
|
||||
&focus_handle,
|
||||
))
|
||||
.disabled(!button_states.stage_file)
|
||||
.on_click(
|
||||
cx.listener(|this, _, window, cx| this.stage_file(window, cx)),
|
||||
)
|
||||
} else {
|
||||
Button::new("unstage-file", "Unstage File")
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Unstage file",
|
||||
&UnstageFile,
|
||||
&focus_handle,
|
||||
))
|
||||
.disabled(!button_states.unstage_file)
|
||||
.on_click(
|
||||
cx.listener(|this, _, window, cx| this.unstage_file(window, cx)),
|
||||
)
|
||||
})
|
||||
.child(
|
||||
Button::new("commit", "Commit")
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Commit",
|
||||
&Commit,
|
||||
&focus_handle,
|
||||
))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&Commit, window, cx);
|
||||
})),
|
||||
),
|
||||
Button::new("commit", "Commit")
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Commit",
|
||||
&Commit,
|
||||
&focus_handle,
|
||||
))
|
||||
.on_click(cx.listener(|this, _, window, cx| {
|
||||
this.dispatch_action(&Commit, window, cx);
|
||||
})),
|
||||
)
|
||||
.into_any_element()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -145,7 +145,7 @@ impl<D: PickerDelegate> Picker<D> {
|
|||
),
|
||||
)
|
||||
.when(preview_visible, |this| {
|
||||
this.child(Divider::vertical().h_4().mx_1())
|
||||
this.child(Divider::vertical().mx_1())
|
||||
.child(
|
||||
IconButton::new("picker-preview-right", IconName::DiffSplit)
|
||||
.icon_size(IconSize::Small)
|
||||
|
|
|
|||
|
|
@ -14,15 +14,15 @@ use crate::{
|
|||
use any_vec::AnyVec;
|
||||
use collections::HashMap;
|
||||
use editor::{
|
||||
Editor, EditorSettings, MultiBufferOffset, SplittableEditor, ToggleSplitDiff,
|
||||
DiffStyleControls, Editor, EditorSettings, MultiBufferOffset, SplittableEditor,
|
||||
actions::{Backtab, FoldAll, Tab, ToggleFoldAll, UnfoldAll},
|
||||
scroll::Autoscroll,
|
||||
};
|
||||
use futures::channel::oneshot;
|
||||
use gpui::{
|
||||
Action as _, App, ClickEvent, Context, Entity, EventEmitter, Focusable,
|
||||
InteractiveElement as _, IntoElement, KeyContext, ParentElement as _, Render, ScrollHandle,
|
||||
Styled, Subscription, Task, TaskExt, WeakEntity, Window, div,
|
||||
App, ClickEvent, Context, Entity, EventEmitter, Focusable, InteractiveElement as _,
|
||||
IntoElement, KeyContext, ParentElement as _, Render, ScrollHandle, Styled, Subscription, Task,
|
||||
TaskExt, WeakEntity, Window, div,
|
||||
};
|
||||
use language::{Language, LanguageRegistry};
|
||||
use project::{
|
||||
|
|
@ -30,17 +30,11 @@ use project::{
|
|||
search_history::{SearchHistory, SearchHistoryCursor},
|
||||
};
|
||||
|
||||
use fs::Fs;
|
||||
use settings::{DiffViewStyle, SeedQuerySetting, Settings, update_settings_file};
|
||||
use settings::{SeedQuerySetting, Settings};
|
||||
use std::{any::TypeId, sync::Arc};
|
||||
use zed_actions::{
|
||||
OpenSettingsAt, outline::ToggleOutline, workspace::CopyPath, workspace::CopyRelativePath,
|
||||
};
|
||||
use zed_actions::{outline::ToggleOutline, workspace::CopyPath, workspace::CopyRelativePath};
|
||||
|
||||
use ui::{
|
||||
BASE_REM_SIZE_IN_PX, IconButtonShape, PlatformStyle, TextSize, Tooltip, prelude::*,
|
||||
render_modifiers, utils::SearchInputWidth,
|
||||
};
|
||||
use ui::{BASE_REM_SIZE_IN_PX, IconButtonShape, Tooltip, prelude::*, utils::SearchInputWidth};
|
||||
use util::{ResultExt, paths::PathMatcher};
|
||||
use workspace::{
|
||||
ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView, Workspace,
|
||||
|
|
@ -109,127 +103,11 @@ impl Render for BufferSearchBar {
|
|||
let focus_handle = self.focus_handle(cx);
|
||||
|
||||
let has_splittable_editor = self.splittable_editor.is_some();
|
||||
let split_buttons = if has_splittable_editor {
|
||||
self.splittable_editor
|
||||
.as_ref()
|
||||
.and_then(|weak| weak.upgrade())
|
||||
.map(|splittable_editor| {
|
||||
let editor_ref = splittable_editor.read(cx);
|
||||
let diff_view_style = editor_ref.diff_view_style();
|
||||
|
||||
let is_split_set = diff_view_style == DiffViewStyle::Split;
|
||||
let is_split_active = editor_ref.is_split();
|
||||
let min_columns =
|
||||
EditorSettings::get_global(cx).minimum_split_diff_width as u32;
|
||||
|
||||
let split_icon = if is_split_set && !is_split_active {
|
||||
IconName::DiffSplitAuto
|
||||
} else {
|
||||
IconName::DiffSplit
|
||||
};
|
||||
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.child(
|
||||
IconButton::new("diff-unified", IconName::DiffUnified)
|
||||
.icon_size(IconSize::Small)
|
||||
.toggle_state(diff_view_style == DiffViewStyle::Unified)
|
||||
.tooltip(Tooltip::text("Unified"))
|
||||
.on_click({
|
||||
let splittable_editor = splittable_editor.downgrade();
|
||||
move |_, window, cx| {
|
||||
update_settings_file(
|
||||
<dyn Fs>::global(cx),
|
||||
cx,
|
||||
|settings, _| {
|
||||
settings.editor.diff_view_style =
|
||||
Some(DiffViewStyle::Unified);
|
||||
},
|
||||
);
|
||||
if diff_view_style == DiffViewStyle::Split {
|
||||
splittable_editor
|
||||
.update(cx, |editor, cx| {
|
||||
editor.toggle_split(
|
||||
&ToggleSplitDiff,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
IconButton::new("diff-split", split_icon)
|
||||
.toggle_state(diff_view_style == DiffViewStyle::Split)
|
||||
.icon_size(IconSize::Small)
|
||||
.tooltip(Tooltip::element(move |_, cx| {
|
||||
let message = if is_split_set && !is_split_active {
|
||||
format!("Split when wider than {} columns", min_columns)
|
||||
.into()
|
||||
} else {
|
||||
SharedString::from("Split")
|
||||
};
|
||||
|
||||
v_flex()
|
||||
.child(message)
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_0p5()
|
||||
.text_ui_sm(cx)
|
||||
.text_color(Color::Muted.color(cx))
|
||||
.children(render_modifiers(
|
||||
&gpui::Modifiers::secondary_key(),
|
||||
PlatformStyle::platform(),
|
||||
None,
|
||||
Some(TextSize::Small.rems(cx).into()),
|
||||
false,
|
||||
))
|
||||
.child("click to change min width"),
|
||||
)
|
||||
.into_any()
|
||||
}))
|
||||
.on_click({
|
||||
let splittable_editor = splittable_editor.downgrade();
|
||||
move |_, window, cx| {
|
||||
if window.modifiers().secondary() {
|
||||
window.dispatch_action(
|
||||
OpenSettingsAt {
|
||||
path: "minimum_split_diff_width".to_string(),
|
||||
target: None,
|
||||
}
|
||||
.boxed_clone(),
|
||||
cx,
|
||||
);
|
||||
} else {
|
||||
update_settings_file(
|
||||
<dyn Fs>::global(cx),
|
||||
cx,
|
||||
|settings, _| {
|
||||
settings.editor.diff_view_style =
|
||||
Some(DiffViewStyle::Split);
|
||||
},
|
||||
);
|
||||
if diff_view_style == DiffViewStyle::Unified {
|
||||
splittable_editor
|
||||
.update(cx, |editor, cx| {
|
||||
editor.toggle_split(
|
||||
&ToggleSplitDiff,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
})
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
}),
|
||||
)
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let split_buttons = self
|
||||
.splittable_editor
|
||||
.as_ref()
|
||||
.and_then(|weak| weak.upgrade())
|
||||
.map(DiffStyleControls::new);
|
||||
|
||||
let collapse_expand_button = if self.needs_expand_collapse_option(cx) {
|
||||
let query_editor_focus = self.query_editor.focus_handle(cx);
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
use gpui::{
|
||||
AnyElement, App, BoxShadow, IntoElement, ParentElement, RenderOnce, Styled, Window, div, hsla,
|
||||
prelude::FluentBuilder, px, relative,
|
||||
AnyElement, App, BoxShadow, ParentElement, RenderOnce, Styled, Window, div, hsla, prelude::*,
|
||||
px,
|
||||
};
|
||||
|
||||
use theme::ActiveTheme;
|
||||
|
||||
use crate::{ElevationIndex, prelude::*};
|
||||
use crate::{Divider, ElevationIndex, prelude::*};
|
||||
|
||||
use super::ButtonLike;
|
||||
|
||||
|
|
@ -80,12 +81,13 @@ impl RenderOnce for SplitButton {
|
|||
SplitButtonKind::ButtonLike(button) => button.into_any_element(),
|
||||
SplitButtonKind::IconButton(icon) => icon.into_any_element(),
|
||||
}))
|
||||
.child(
|
||||
div()
|
||||
.h(relative(0.8))
|
||||
.w_px()
|
||||
.bg(cx.theme().colors().border.opacity(0.5)),
|
||||
)
|
||||
.child(Divider::vertical().map(|s| {
|
||||
if self.style == SplitButtonStyle::Filled {
|
||||
s.h_full().color(crate::DividerColor::Border)
|
||||
} else {
|
||||
s.h_4()
|
||||
}
|
||||
}))
|
||||
.child(self.right)
|
||||
.when(self.style == SplitButtonStyle::Filled, |this| {
|
||||
this.bg(ElevationIndex::Surface.on_elevation_bg(cx))
|
||||
|
|
|
|||
|
|
@ -2,26 +2,6 @@ use gpui::{Hsla, IntoElement, PathBuilder, Refineable as _, StyleRefinement, can
|
|||
|
||||
use crate::prelude::*;
|
||||
|
||||
pub fn divider() -> Divider {
|
||||
Divider {
|
||||
line_style: DividerStyle::Solid,
|
||||
direction: DividerDirection::Horizontal,
|
||||
color: DividerColor::default(),
|
||||
style: StyleRefinement::default(),
|
||||
inset: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vertical_divider() -> Divider {
|
||||
Divider {
|
||||
line_style: DividerStyle::Solid,
|
||||
direction: DividerDirection::Vertical,
|
||||
color: DividerColor::default(),
|
||||
style: StyleRefinement::default(),
|
||||
inset: false,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
enum DividerStyle {
|
||||
Solid,
|
||||
|
|
@ -166,7 +146,7 @@ impl RenderOnce for Divider {
|
|||
DividerDirection::Vertical => div()
|
||||
.min_w_0()
|
||||
.w_px()
|
||||
.h_full()
|
||||
.h_4()
|
||||
.when(self.inset, |this| this.my_1p5()),
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue