mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-28 15:44:20 +03:00
Merge pull request #2188 from zed-industries/dont-open-project-items-in-dock
Dont open project items in dock
This commit is contained in:
commit
efafd1d8d3
@ -450,15 +450,16 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Dock",
|
||||
"context": "Pane",
|
||||
"bindings": {
|
||||
"shift-escape": "dock::HideDock"
|
||||
"cmd-escape": "dock::AddTabToDock"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Pane",
|
||||
"context": "Dock",
|
||||
"bindings": {
|
||||
"cmd-escape": "dock::MoveActiveItemToDock"
|
||||
"shift-escape": "dock::HideDock",
|
||||
"cmd-escape": "dock::RemoveTabFromDock"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -5,7 +5,7 @@ mod keystroke;
|
||||
|
||||
use std::{any::TypeId, fmt::Debug};
|
||||
|
||||
use collections::HashMap;
|
||||
use collections::{BTreeMap, HashMap};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
use crate::Action;
|
||||
@ -60,13 +60,28 @@ impl KeymapMatcher {
|
||||
!self.pending_keystrokes.is_empty()
|
||||
}
|
||||
|
||||
/// Pushes a keystroke onto the matcher.
|
||||
/// The result of the new keystroke is returned:
|
||||
/// MatchResult::None =>
|
||||
/// No match is valid for this key given any pending keystrokes.
|
||||
/// MatchResult::Pending =>
|
||||
/// There exist bindings which are still waiting for more keys.
|
||||
/// MatchResult::Complete(matches) =>
|
||||
/// 1 or more bindings have recieved the necessary key presses.
|
||||
/// The order of the matched actions is by order in the keymap file first and
|
||||
/// position of the matching view second.
|
||||
pub fn push_keystroke(
|
||||
&mut self,
|
||||
keystroke: Keystroke,
|
||||
mut dispatch_path: Vec<(usize, KeymapContext)>,
|
||||
) -> MatchResult {
|
||||
let mut any_pending = false;
|
||||
let mut matched_bindings: Vec<(usize, Box<dyn Action>)> = Vec::new();
|
||||
// Collect matched bindings into an ordered list using the position in the matching binding first,
|
||||
// and then the order the binding matched in the view tree second.
|
||||
// The key is the reverse position of the binding in the bindings list so that later bindings
|
||||
// match before earlier ones in the user's config
|
||||
let mut matched_bindings: BTreeMap<usize, Vec<(usize, Box<dyn Action>)>> =
|
||||
Default::default();
|
||||
|
||||
let first_keystroke = self.pending_keystrokes.is_empty();
|
||||
self.pending_keystrokes.push(keystroke.clone());
|
||||
@ -75,29 +90,33 @@ impl KeymapMatcher {
|
||||
self.contexts
|
||||
.extend(dispatch_path.iter_mut().map(|e| std::mem::take(&mut e.1)));
|
||||
|
||||
for (i, (view_id, _)) in dispatch_path.into_iter().enumerate() {
|
||||
// Find the bindings which map the pending keystrokes and current context
|
||||
for (i, (view_id, _)) in dispatch_path.iter().enumerate() {
|
||||
// Don't require pending view entry if there are no pending keystrokes
|
||||
if !first_keystroke && !self.pending_views.contains_key(&view_id) {
|
||||
if !first_keystroke && !self.pending_views.contains_key(view_id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If there is a previous view context, invalidate that view if it
|
||||
// has changed
|
||||
if let Some(previous_view_context) = self.pending_views.remove(&view_id) {
|
||||
if let Some(previous_view_context) = self.pending_views.remove(view_id) {
|
||||
if previous_view_context != self.contexts[i] {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the bindings which map the pending keystrokes and current context
|
||||
for binding in self.keymap.bindings().iter().rev() {
|
||||
for (order, binding) in self.keymap.bindings().iter().rev().enumerate() {
|
||||
match binding.match_keys_and_context(&self.pending_keystrokes, &self.contexts[i..])
|
||||
{
|
||||
BindingMatchResult::Complete(action) => {
|
||||
matched_bindings.push((view_id, action))
|
||||
matched_bindings
|
||||
.entry(order)
|
||||
.or_default()
|
||||
.push((*view_id, action));
|
||||
}
|
||||
BindingMatchResult::Partial => {
|
||||
self.pending_views.insert(view_id, self.contexts[i].clone());
|
||||
self.pending_views
|
||||
.insert(*view_id, self.contexts[i].clone());
|
||||
any_pending = true;
|
||||
}
|
||||
_ => {}
|
||||
@ -110,7 +129,9 @@ impl KeymapMatcher {
|
||||
}
|
||||
|
||||
if !matched_bindings.is_empty() {
|
||||
MatchResult::Matches(matched_bindings)
|
||||
// Collect the sorted matched bindings into the final vec for ease of use
|
||||
// Matched bindings are in order by precedence
|
||||
MatchResult::Matches(matched_bindings.into_values().flatten().collect())
|
||||
} else if any_pending {
|
||||
MatchResult::Pending
|
||||
} else {
|
||||
|
@ -1,19 +1,20 @@
|
||||
mod toggle_dock_button;
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
use collections::HashMap;
|
||||
use gpui::{
|
||||
actions,
|
||||
elements::{ChildView, Container, Empty, MouseEventHandler, ParentElement, Side, Stack, Svg},
|
||||
elements::{ChildView, Container, Empty, MouseEventHandler, ParentElement, Side, Stack},
|
||||
geometry::vector::Vector2F,
|
||||
impl_internal_actions, Border, CursorStyle, Element, ElementBox, Entity, MouseButton,
|
||||
MutableAppContext, RenderContext, SizeConstraint, View, ViewContext, ViewHandle,
|
||||
WeakViewHandle,
|
||||
impl_internal_actions, Border, CursorStyle, Element, ElementBox, MouseButton,
|
||||
MutableAppContext, RenderContext, SizeConstraint, ViewContext, ViewHandle,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use settings::{DockAnchor, Settings};
|
||||
use theme::Theme;
|
||||
|
||||
use crate::{
|
||||
handle_dropped_item, sidebar::SidebarSide, ItemHandle, Pane, StatusItemView, Workspace,
|
||||
};
|
||||
use crate::{sidebar::SidebarSide, ItemHandle, Pane, Workspace};
|
||||
pub use toggle_dock_button::ToggleDockButton;
|
||||
|
||||
#[derive(PartialEq, Clone, Deserialize)]
|
||||
pub struct MoveDock(pub DockAnchor);
|
||||
@ -29,7 +30,8 @@ actions!(
|
||||
AnchorDockRight,
|
||||
AnchorDockBottom,
|
||||
ExpandDock,
|
||||
MoveActiveItemToDock,
|
||||
AddTabToDock,
|
||||
RemoveTabFromDock,
|
||||
]
|
||||
);
|
||||
impl_internal_actions!(dock, [MoveDock, AddDefaultItemToDock]);
|
||||
@ -54,7 +56,8 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||
},
|
||||
);
|
||||
cx.add_action(
|
||||
|workspace: &mut Workspace, _: &MoveActiveItemToDock, cx: &mut ViewContext<Workspace>| {
|
||||
|workspace: &mut Workspace, _: &AddTabToDock, cx: &mut ViewContext<Workspace>| {
|
||||
eprintln!("Add tab to dock");
|
||||
if let Some(active_item) = workspace.active_item(cx) {
|
||||
let item_id = active_item.id();
|
||||
|
||||
@ -66,6 +69,42 @@ pub fn init(cx: &mut MutableAppContext) {
|
||||
|
||||
let destination_index = to.read(cx).items_len() + 1;
|
||||
|
||||
Pane::move_item(
|
||||
workspace,
|
||||
from.clone(),
|
||||
to.clone(),
|
||||
item_id,
|
||||
destination_index,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
cx.add_action(
|
||||
|workspace: &mut Workspace, _: &RemoveTabFromDock, cx: &mut ViewContext<Workspace>| {
|
||||
eprintln!("Removing tab from dock");
|
||||
if let Some(active_item) = workspace.active_item(cx) {
|
||||
let item_id = active_item.id();
|
||||
|
||||
let from = workspace.dock_pane();
|
||||
let to = workspace
|
||||
.last_active_center_pane
|
||||
.as_ref()
|
||||
.and_then(|pane| pane.upgrade(cx))
|
||||
.unwrap_or_else(|| {
|
||||
workspace
|
||||
.panes
|
||||
.first()
|
||||
.expect("There must be a pane")
|
||||
.clone()
|
||||
});
|
||||
|
||||
if from.id() == to.id() {
|
||||
return;
|
||||
}
|
||||
|
||||
let destination_index = to.read(cx).items_len() + 1;
|
||||
|
||||
Pane::move_item(
|
||||
workspace,
|
||||
from.clone(),
|
||||
@ -376,108 +415,6 @@ impl Dock {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ToggleDockButton {
|
||||
workspace: WeakViewHandle<Workspace>,
|
||||
}
|
||||
|
||||
impl ToggleDockButton {
|
||||
pub fn new(workspace: ViewHandle<Workspace>, cx: &mut ViewContext<Self>) -> Self {
|
||||
// When dock moves, redraw so that the icon and toggle status matches.
|
||||
cx.subscribe(&workspace, |_, _, _, cx| cx.notify()).detach();
|
||||
|
||||
Self {
|
||||
workspace: workspace.downgrade(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Entity for ToggleDockButton {
|
||||
type Event = ();
|
||||
}
|
||||
|
||||
impl View for ToggleDockButton {
|
||||
fn ui_name() -> &'static str {
|
||||
"Dock Toggle"
|
||||
}
|
||||
|
||||
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox {
|
||||
let workspace = self.workspace.upgrade(cx);
|
||||
|
||||
if workspace.is_none() {
|
||||
return Empty::new().boxed();
|
||||
}
|
||||
|
||||
let workspace = workspace.unwrap();
|
||||
let dock_position = workspace.read(cx).dock.position;
|
||||
|
||||
let theme = cx.global::<Settings>().theme.clone();
|
||||
|
||||
let button = MouseEventHandler::<Self>::new(0, cx, {
|
||||
let theme = theme.clone();
|
||||
move |state, _| {
|
||||
let style = theme
|
||||
.workspace
|
||||
.status_bar
|
||||
.sidebar_buttons
|
||||
.item
|
||||
.style_for(state, dock_position.is_visible());
|
||||
|
||||
Svg::new(icon_for_dock_anchor(dock_position.anchor()))
|
||||
.with_color(style.icon_color)
|
||||
.constrained()
|
||||
.with_width(style.icon_size)
|
||||
.with_height(style.icon_size)
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
.boxed()
|
||||
}
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_up(MouseButton::Left, move |event, cx| {
|
||||
let dock_pane = workspace.read(cx.app).dock_pane();
|
||||
let drop_index = dock_pane.read(cx.app).items_len() + 1;
|
||||
handle_dropped_item(event, &dock_pane.downgrade(), drop_index, false, None, cx);
|
||||
});
|
||||
|
||||
if dock_position.is_visible() {
|
||||
button
|
||||
.on_click(MouseButton::Left, |_, cx| {
|
||||
cx.dispatch_action(HideDock);
|
||||
})
|
||||
.with_tooltip::<Self, _>(
|
||||
0,
|
||||
"Hide Dock".into(),
|
||||
Some(Box::new(HideDock)),
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
)
|
||||
} else {
|
||||
button
|
||||
.on_click(MouseButton::Left, |_, cx| {
|
||||
cx.dispatch_action(FocusDock);
|
||||
})
|
||||
.with_tooltip::<Self, _>(
|
||||
0,
|
||||
"Focus Dock".into(),
|
||||
Some(Box::new(FocusDock)),
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
)
|
||||
}
|
||||
.boxed()
|
||||
}
|
||||
}
|
||||
|
||||
impl StatusItemView for ToggleDockButton {
|
||||
fn set_active_pane_item(
|
||||
&mut self,
|
||||
_active_pane_item: Option<&dyn crate::ItemHandle>,
|
||||
_cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
//Not applicable
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{
|
||||
@ -485,7 +422,7 @@ mod tests {
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use gpui::{AppContext, TestAppContext, UpdateView, ViewContext};
|
||||
use gpui::{AppContext, TestAppContext, UpdateView, View, ViewContext};
|
||||
use project::{FakeFs, Project};
|
||||
use settings::Settings;
|
||||
|
||||
|
112
crates/workspace/src/dock/toggle_dock_button.rs
Normal file
112
crates/workspace/src/dock/toggle_dock_button.rs
Normal file
@ -0,0 +1,112 @@
|
||||
use gpui::{
|
||||
elements::{Empty, MouseEventHandler, Svg},
|
||||
CursorStyle, Element, ElementBox, Entity, MouseButton, View, ViewContext, ViewHandle,
|
||||
WeakViewHandle,
|
||||
};
|
||||
use settings::Settings;
|
||||
|
||||
use crate::{handle_dropped_item, StatusItemView, Workspace};
|
||||
|
||||
use super::{icon_for_dock_anchor, FocusDock, HideDock};
|
||||
|
||||
pub struct ToggleDockButton {
|
||||
workspace: WeakViewHandle<Workspace>,
|
||||
}
|
||||
|
||||
impl ToggleDockButton {
|
||||
pub fn new(workspace: ViewHandle<Workspace>, cx: &mut ViewContext<Self>) -> Self {
|
||||
// When dock moves, redraw so that the icon and toggle status matches.
|
||||
cx.subscribe(&workspace, |_, _, _, cx| cx.notify()).detach();
|
||||
|
||||
Self {
|
||||
workspace: workspace.downgrade(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Entity for ToggleDockButton {
|
||||
type Event = ();
|
||||
}
|
||||
|
||||
impl View for ToggleDockButton {
|
||||
fn ui_name() -> &'static str {
|
||||
"Dock Toggle"
|
||||
}
|
||||
|
||||
fn render(&mut self, cx: &mut gpui::RenderContext<'_, Self>) -> ElementBox {
|
||||
let workspace = self.workspace.upgrade(cx);
|
||||
|
||||
if workspace.is_none() {
|
||||
return Empty::new().boxed();
|
||||
}
|
||||
|
||||
let workspace = workspace.unwrap();
|
||||
let dock_position = workspace.read(cx).dock.position;
|
||||
|
||||
let theme = cx.global::<Settings>().theme.clone();
|
||||
|
||||
let button = MouseEventHandler::<Self>::new(0, cx, {
|
||||
let theme = theme.clone();
|
||||
move |state, _| {
|
||||
let style = theme
|
||||
.workspace
|
||||
.status_bar
|
||||
.sidebar_buttons
|
||||
.item
|
||||
.style_for(state, dock_position.is_visible());
|
||||
|
||||
Svg::new(icon_for_dock_anchor(dock_position.anchor()))
|
||||
.with_color(style.icon_color)
|
||||
.constrained()
|
||||
.with_width(style.icon_size)
|
||||
.with_height(style.icon_size)
|
||||
.contained()
|
||||
.with_style(style.container)
|
||||
.boxed()
|
||||
}
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_up(MouseButton::Left, move |event, cx| {
|
||||
let dock_pane = workspace.read(cx.app).dock_pane();
|
||||
let drop_index = dock_pane.read(cx.app).items_len() + 1;
|
||||
handle_dropped_item(event, &dock_pane.downgrade(), drop_index, false, None, cx);
|
||||
});
|
||||
|
||||
if dock_position.is_visible() {
|
||||
button
|
||||
.on_click(MouseButton::Left, |_, cx| {
|
||||
cx.dispatch_action(HideDock);
|
||||
})
|
||||
.with_tooltip::<Self, _>(
|
||||
0,
|
||||
"Hide Dock".into(),
|
||||
Some(Box::new(HideDock)),
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
)
|
||||
} else {
|
||||
button
|
||||
.on_click(MouseButton::Left, |_, cx| {
|
||||
cx.dispatch_action(FocusDock);
|
||||
})
|
||||
.with_tooltip::<Self, _>(
|
||||
0,
|
||||
"Focus Dock".into(),
|
||||
Some(Box::new(FocusDock)),
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
)
|
||||
}
|
||||
.boxed()
|
||||
}
|
||||
}
|
||||
|
||||
impl StatusItemView for ToggleDockButton {
|
||||
fn set_active_pane_item(
|
||||
&mut self,
|
||||
_active_pane_item: Option<&dyn crate::ItemHandle>,
|
||||
_cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
//Not applicable
|
||||
}
|
||||
}
|
@ -1432,7 +1432,7 @@ impl View for Pane {
|
||||
enum TabBarEventHandler {}
|
||||
stack.add_child(
|
||||
MouseEventHandler::<TabBarEventHandler>::new(0, cx, |_, _| {
|
||||
Flex::row()
|
||||
Empty::new()
|
||||
.contained()
|
||||
.with_style(theme.workspace.tab_bar.container)
|
||||
.boxed()
|
||||
|
Loading…
Reference in New Issue
Block a user