mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 03:14:56 +07:00
git: Add toolbar buttons for SplittableEditor (#48323)
Release Notes: - N/A
This commit is contained in:
parent
323680f6fe
commit
804caba60c
6 changed files with 123 additions and 61 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -7273,7 +7273,6 @@ dependencies = [
|
|||
"ctor",
|
||||
"db",
|
||||
"editor",
|
||||
"feature_flags",
|
||||
"futures 0.3.31",
|
||||
"fuzzy",
|
||||
"git",
|
||||
|
|
@ -14842,6 +14841,7 @@ dependencies = [
|
|||
"client",
|
||||
"collections",
|
||||
"editor",
|
||||
"feature_flags",
|
||||
"futures 0.3.31",
|
||||
"gpui",
|
||||
"itertools 0.14.0",
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ command_palette_hooks.workspace = true
|
|||
component.workspace = true
|
||||
db.workspace = true
|
||||
editor.workspace = true
|
||||
feature_flags.workspace = true
|
||||
futures.workspace = true
|
||||
fuzzy.workspace = true
|
||||
git.workspace = true
|
||||
|
|
|
|||
|
|
@ -8,13 +8,12 @@ use anyhow::{Context as _, Result, anyhow};
|
|||
use buffer_diff::{BufferDiff, DiffHunkSecondaryStatus};
|
||||
use collections::{HashMap, HashSet};
|
||||
use editor::{
|
||||
Addon, Editor, EditorEvent, SelectionEffects, SplitDiffFeatureFlag, SplittableEditor,
|
||||
ToggleSplitDiff,
|
||||
Addon, Editor, EditorEvent, SelectionEffects, SplittableEditor,
|
||||
actions::{GoToHunk, GoToPreviousHunk, SendReviewToAgent},
|
||||
multibuffer_context_lines,
|
||||
scroll::Autoscroll,
|
||||
};
|
||||
use feature_flags::FeatureFlagAppExt as _;
|
||||
|
||||
use git::{
|
||||
Commit, StageAll, StageAndNext, ToggleStaged, UnstageAll, UnstageAndNext,
|
||||
repository::{Branch, RepoPath, Upstream, UpstreamTracking, UpstreamTrackingStatus},
|
||||
|
|
@ -480,7 +479,6 @@ impl ProjectDiff {
|
|||
}
|
||||
|
||||
fn button_states(&self, cx: &App) -> ButtonStates {
|
||||
let is_split = self.editor.read(cx).is_split();
|
||||
let editor = self.editor.read(cx).rhs_editor().read(cx);
|
||||
let snapshot = self.multibuffer.read(cx).snapshot(cx);
|
||||
let prev_next = snapshot.diff_hunks().nth(1).is_some();
|
||||
|
|
@ -541,7 +539,6 @@ impl ProjectDiff {
|
|||
selection,
|
||||
stage_all,
|
||||
unstage_all,
|
||||
is_split,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -987,6 +984,8 @@ impl Item for ProjectDiff {
|
|||
Some(self_handle.clone().into())
|
||||
} else if type_id == TypeId::of::<Editor>() {
|
||||
Some(self.editor.read(cx).rhs_editor().clone().into())
|
||||
} else if type_id == TypeId::of::<SplittableEditor>() {
|
||||
Some(self.editor.clone().into())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -1293,7 +1292,6 @@ struct ButtonStates {
|
|||
selection: bool,
|
||||
stage_all: bool,
|
||||
unstage_all: bool,
|
||||
is_split: bool,
|
||||
}
|
||||
|
||||
impl Render for ProjectDiffToolbar {
|
||||
|
|
@ -1433,31 +1431,6 @@ impl Render for ProjectDiffToolbar {
|
|||
)
|
||||
},
|
||||
)
|
||||
.map(|this| {
|
||||
if !cx.has_flag::<SplitDiffFeatureFlag>() {
|
||||
return this;
|
||||
}
|
||||
this.child(
|
||||
Button::new(
|
||||
"toggle-split",
|
||||
if button_states.is_split {
|
||||
"Stacked View"
|
||||
} else {
|
||||
"Split View"
|
||||
},
|
||||
)
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
"Toggle Split View",
|
||||
&ToggleSplitDiff,
|
||||
&focus_handle,
|
||||
))
|
||||
.on_click(cx.listener(
|
||||
|this, _, window, cx| {
|
||||
this.dispatch_action(&ToggleSplitDiff, window, cx);
|
||||
},
|
||||
)),
|
||||
)
|
||||
})
|
||||
.child(
|
||||
Button::new("commit", "Commit")
|
||||
.tooltip(Tooltip::for_action_title_in(
|
||||
|
|
|
|||
|
|
@ -92,6 +92,8 @@ pub enum IconName {
|
|||
DebugStepOut,
|
||||
DebugStepOver,
|
||||
Diff,
|
||||
DiffSplit,
|
||||
DiffStacked,
|
||||
Disconnected,
|
||||
Download,
|
||||
EditorAtom,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ any_vec.workspace = true
|
|||
bitflags.workspace = true
|
||||
collections.workspace = true
|
||||
editor.workspace = true
|
||||
feature_flags.workspace = true
|
||||
futures.workspace = true
|
||||
gpui.workspace = true
|
||||
language.workspace = true
|
||||
|
|
|
|||
|
|
@ -13,14 +13,16 @@ use crate::{
|
|||
use any_vec::AnyVec;
|
||||
use collections::HashMap;
|
||||
use editor::{
|
||||
DisplayPoint, Editor, EditorSettings, MultiBufferOffset,
|
||||
DisplayPoint, Editor, EditorSettings, MultiBufferOffset, SplitDiffFeatureFlag,
|
||||
SplittableEditor, ToggleSplitDiff,
|
||||
actions::{Backtab, FoldAll, Tab, ToggleFoldAll, UnfoldAll},
|
||||
};
|
||||
use feature_flags::FeatureFlagAppExt as _;
|
||||
use futures::channel::oneshot;
|
||||
use gpui::{
|
||||
Action, App, ClickEvent, Context, Entity, EventEmitter, Focusable, InteractiveElement as _,
|
||||
IntoElement, KeyContext, ParentElement as _, Render, ScrollHandle, Styled, Subscription, Task,
|
||||
Window, actions, div,
|
||||
WeakEntity, Window, actions, div,
|
||||
};
|
||||
use language::{Language, LanguageRegistry};
|
||||
use project::{
|
||||
|
|
@ -132,6 +134,8 @@ pub struct BufferSearchBar {
|
|||
editor_needed_width: Pixels,
|
||||
regex_language: Option<Arc<Language>>,
|
||||
is_collapsed: bool,
|
||||
splittable_editor: Option<WeakEntity<SplittableEditor>>,
|
||||
_splittable_editor_subscription: Option<Subscription>,
|
||||
}
|
||||
|
||||
impl EventEmitter<Event> for BufferSearchBar {}
|
||||
|
|
@ -140,46 +144,94 @@ impl Render for BufferSearchBar {
|
|||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let focus_handle = self.focus_handle(cx);
|
||||
|
||||
let has_splittable_editor =
|
||||
self.splittable_editor.is_some() && cx.has_flag::<SplitDiffFeatureFlag>();
|
||||
let split_buttons = if has_splittable_editor {
|
||||
self.splittable_editor
|
||||
.as_ref()
|
||||
.and_then(|weak| weak.upgrade())
|
||||
.map(|splittable_editor| {
|
||||
let is_split = splittable_editor.read(cx).is_split();
|
||||
let focus_handle = splittable_editor.focus_handle(cx);
|
||||
h_flex()
|
||||
.gap_0p5()
|
||||
.child(
|
||||
IconButton::new("diff-stacked", IconName::DiffStacked)
|
||||
.shape(IconButtonShape::Square)
|
||||
.toggle_state(!is_split)
|
||||
.tooltip(|_, cx| {
|
||||
Tooltip::for_action("Stacked", &ToggleSplitDiff, cx)
|
||||
})
|
||||
.when(is_split, |button| {
|
||||
let focus_handle = focus_handle.clone();
|
||||
button.on_click(move |_, window, cx| {
|
||||
focus_handle.focus(window, cx);
|
||||
window.dispatch_action(ToggleSplitDiff.boxed_clone(), cx);
|
||||
})
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
IconButton::new("diff-split", IconName::DiffSplit)
|
||||
.shape(IconButtonShape::Square)
|
||||
.toggle_state(is_split)
|
||||
.tooltip(|_, cx| {
|
||||
Tooltip::for_action("Side by Side", &ToggleSplitDiff, cx)
|
||||
})
|
||||
.when(!is_split, |button| {
|
||||
button.on_click({
|
||||
let focus_handle = focus_handle.clone();
|
||||
move |_, window, cx| {
|
||||
focus_handle.focus(window, cx);
|
||||
window
|
||||
.dispatch_action(ToggleSplitDiff.boxed_clone(), cx);
|
||||
}
|
||||
})
|
||||
}),
|
||||
)
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let collapse_expand_button = if self.needs_expand_collapse_option(cx) {
|
||||
let query_editor_focus = self.query_editor.focus_handle(cx);
|
||||
|
||||
let (icon, label, tooltip_label) = if self.is_collapsed {
|
||||
(
|
||||
IconName::ChevronUpDown,
|
||||
"Expand All",
|
||||
"Expand All Search Results",
|
||||
)
|
||||
(IconName::ChevronUpDown, "Expand All", "Expand All Files")
|
||||
} else {
|
||||
(
|
||||
IconName::ChevronDownUp,
|
||||
"Collapse All",
|
||||
"Collapse All Search Results",
|
||||
"Collapse All Files",
|
||||
)
|
||||
};
|
||||
|
||||
if self.dismissed {
|
||||
let button = Button::new("multibuffer-collapse-expand-empty", label)
|
||||
if has_splittable_editor {
|
||||
return h_flex()
|
||||
.gap_1()
|
||||
.child(
|
||||
IconButton::new("multibuffer-collapse-expand-empty", icon)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(move |_, cx| {
|
||||
Tooltip::for_action_in(
|
||||
tooltip_label,
|
||||
&ToggleFoldAll,
|
||||
&query_editor_focus,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.on_click(|_event, window, cx| {
|
||||
window.dispatch_action(ToggleFoldAll.boxed_clone(), cx)
|
||||
}),
|
||||
)
|
||||
.children(split_buttons)
|
||||
.into_any_element();
|
||||
}
|
||||
|
||||
return Button::new("multibuffer-collapse-expand-empty", label)
|
||||
.icon_position(IconPosition::Start)
|
||||
.icon(icon)
|
||||
.tooltip(move |_, cx| {
|
||||
Tooltip::for_action_in(
|
||||
tooltip_label,
|
||||
&ToggleFoldAll,
|
||||
&query_editor_focus.clone(),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.on_click(|_event, window, cx| {
|
||||
window.dispatch_action(ToggleFoldAll.boxed_clone(), cx)
|
||||
})
|
||||
.into_any_element();
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
Some(
|
||||
IconButton::new("multibuffer-collapse-expand", icon)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(move |_, cx| {
|
||||
Tooltip::for_action_in(
|
||||
tooltip_label,
|
||||
|
|
@ -191,6 +243,28 @@ impl Render for BufferSearchBar {
|
|||
.on_click(|_event, window, cx| {
|
||||
window.dispatch_action(ToggleFoldAll.boxed_clone(), cx)
|
||||
})
|
||||
.into_any_element();
|
||||
}
|
||||
|
||||
Some(
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.child(
|
||||
IconButton::new("multibuffer-collapse-expand", icon)
|
||||
.shape(IconButtonShape::Square)
|
||||
.tooltip(move |_, cx| {
|
||||
Tooltip::for_action_in(
|
||||
tooltip_label,
|
||||
&ToggleFoldAll,
|
||||
&query_editor_focus,
|
||||
cx,
|
||||
)
|
||||
})
|
||||
.on_click(|_event, window, cx| {
|
||||
window.dispatch_action(ToggleFoldAll.boxed_clone(), cx)
|
||||
}),
|
||||
)
|
||||
.children(split_buttons)
|
||||
.into_any_element(),
|
||||
)
|
||||
} else {
|
||||
|
|
@ -558,9 +632,20 @@ impl ToolbarItemView for BufferSearchBar {
|
|||
cx.notify();
|
||||
self.active_searchable_item_subscriptions.take();
|
||||
self.active_searchable_item.take();
|
||||
self.splittable_editor = None;
|
||||
self._splittable_editor_subscription = None;
|
||||
|
||||
self.pending_search.take();
|
||||
|
||||
if let Some(splittable_editor) = item
|
||||
.and_then(|item| item.act_as_type(TypeId::of::<SplittableEditor>(), cx))
|
||||
.and_then(|entity| entity.downcast::<SplittableEditor>().ok())
|
||||
{
|
||||
self._splittable_editor_subscription =
|
||||
Some(cx.observe(&splittable_editor, |_, _, cx| cx.notify()));
|
||||
self.splittable_editor = Some(splittable_editor.downgrade());
|
||||
}
|
||||
|
||||
if let Some(searchable_item_handle) =
|
||||
item.and_then(|item| item.to_searchable_item_handle(cx))
|
||||
{
|
||||
|
|
@ -818,6 +903,8 @@ impl BufferSearchBar {
|
|||
editor_needed_width: px(0.),
|
||||
regex_language: None,
|
||||
is_collapsed: false,
|
||||
splittable_editor: None,
|
||||
_splittable_editor_subscription: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue