mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-24 17:28:40 +00:00
Remove dock from workspace
This commit is contained in:
parent
2d7cfb8c7c
commit
1919a826f9
18 changed files with 92 additions and 1461 deletions
|
@ -62,9 +62,5 @@
|
|||
"ctrl-f": "project_panel::ExpandSelectedEntry",
|
||||
"ctrl-shift-c": "project_panel::CopyPath"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Dock",
|
||||
"bindings": {}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -443,32 +443,6 @@
|
|||
"cmd-enter": "project_search::SearchInNew"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Workspace",
|
||||
"bindings": {
|
||||
"shift-escape": "dock::FocusDock"
|
||||
}
|
||||
},
|
||||
{
|
||||
"bindings": {
|
||||
"cmd-shift-k cmd-shift-right": "dock::AnchorDockRight",
|
||||
"cmd-shift-k cmd-shift-down": "dock::AnchorDockBottom",
|
||||
"cmd-shift-k cmd-shift-up": "dock::ExpandDock"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Pane",
|
||||
"bindings": {
|
||||
"cmd-escape": "dock::AddTabToDock"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Pane && docked",
|
||||
"bindings": {
|
||||
"shift-escape": "dock::HideDock",
|
||||
"cmd-escape": "dock::RemoveTabFromDock"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "ProjectPanel",
|
||||
"bindings": {
|
||||
|
|
|
@ -66,14 +66,7 @@
|
|||
"cmd-shift-a": "command_palette::Toggle",
|
||||
"cmd-alt-o": "project_symbols::Toggle",
|
||||
"cmd-1": "workspace::ToggleLeftSidebar",
|
||||
"cmd-6": "diagnostics::Deploy",
|
||||
"alt-f12": "dock::FocusDock"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Dock",
|
||||
"bindings": {
|
||||
"alt-f12": "dock::HideDock"
|
||||
"cmd-6": "diagnostics::Deploy"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -45,18 +45,11 @@
|
|||
{
|
||||
"context": "Workspace",
|
||||
"bindings": {
|
||||
"ctrl-`": "dock::FocusDock",
|
||||
"cmd-k cmd-b": "workspace::ToggleLeftSidebar",
|
||||
"cmd-t": "file_finder::Toggle",
|
||||
"shift-cmd-r": "project_symbols::Toggle",
|
||||
// Currently busted: https://github.com/zed-industries/feedback/issues/898
|
||||
"ctrl-0": "project_panel::ToggleFocus"
|
||||
}
|
||||
},
|
||||
{
|
||||
"context": "Dock",
|
||||
"bindings": {
|
||||
"ctrl-`": "dock::HideDock"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -83,9 +83,5 @@
|
|||
{
|
||||
"context": "ProjectPanel",
|
||||
"bindings": {}
|
||||
},
|
||||
{
|
||||
"context": "Dock",
|
||||
"bindings": {}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -59,16 +59,6 @@
|
|||
// 4. Save when idle for a certain amount of time:
|
||||
// "autosave": { "after_delay": {"milliseconds": 500} },
|
||||
"autosave": "off",
|
||||
// Where to place the dock by default. This setting can take three
|
||||
// values:
|
||||
//
|
||||
// 1. Position the dock attached to the bottom of the workspace
|
||||
// "default_dock_anchor": "bottom"
|
||||
// 2. Position the dock to the right of the workspace like a side panel
|
||||
// "default_dock_anchor": "right"
|
||||
// 3. Position the dock full screen over the entire workspace"
|
||||
// "default_dock_anchor": "expanded"
|
||||
"default_dock_anchor": "bottom",
|
||||
// Whether or not to remove any trailing whitespace from lines of a buffer
|
||||
// before saving it.
|
||||
"remove_trailing_whitespace_on_save": true,
|
||||
|
|
|
@ -195,7 +195,6 @@ impl TestServer {
|
|||
fs: fs.clone(),
|
||||
build_window_options: |_, _, _| Default::default(),
|
||||
initialize_workspace: |_, _, _| unimplemented!(),
|
||||
dock_default_item_factory: |_, _| None,
|
||||
background_actions: || &[],
|
||||
});
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ mod keymap_file;
|
|||
pub mod settings_file;
|
||||
pub mod watched_json;
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use anyhow::Result;
|
||||
use gpui::{
|
||||
font_cache::{FamilyId, FontCache},
|
||||
fonts, AssetSource,
|
||||
|
@ -15,10 +15,6 @@ use schemars::{
|
|||
};
|
||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use sqlez::{
|
||||
bindable::{Bind, Column, StaticColumnCount},
|
||||
statement::Statement,
|
||||
};
|
||||
use std::{
|
||||
borrow::Cow, collections::HashMap, num::NonZeroU32, ops::Range, path::Path, str, sync::Arc,
|
||||
};
|
||||
|
@ -48,7 +44,6 @@ pub struct Settings {
|
|||
pub show_call_status_icon: bool,
|
||||
pub vim_mode: bool,
|
||||
pub autosave: Autosave,
|
||||
pub default_dock_anchor: DockAnchor,
|
||||
pub editor_defaults: EditorSettings,
|
||||
pub editor_overrides: EditorSettings,
|
||||
pub git: GitSettings,
|
||||
|
@ -340,43 +335,6 @@ impl TerminalSettings {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Default, Copy, Clone, Hash, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum DockAnchor {
|
||||
#[default]
|
||||
Bottom,
|
||||
Right,
|
||||
Expanded,
|
||||
}
|
||||
|
||||
impl StaticColumnCount for DockAnchor {}
|
||||
impl Bind for DockAnchor {
|
||||
fn bind(&self, statement: &Statement, start_index: i32) -> anyhow::Result<i32> {
|
||||
match self {
|
||||
DockAnchor::Bottom => "Bottom",
|
||||
DockAnchor::Right => "Right",
|
||||
DockAnchor::Expanded => "Expanded",
|
||||
}
|
||||
.bind(statement, start_index)
|
||||
}
|
||||
}
|
||||
|
||||
impl Column for DockAnchor {
|
||||
fn column(statement: &mut Statement, start_index: i32) -> anyhow::Result<(Self, i32)> {
|
||||
String::column(statement, start_index).and_then(|(anchor_text, next_index)| {
|
||||
Ok((
|
||||
match anchor_text.as_ref() {
|
||||
"Bottom" => DockAnchor::Bottom,
|
||||
"Right" => DockAnchor::Right,
|
||||
"Expanded" => DockAnchor::Expanded,
|
||||
_ => bail!("Stored dock anchor is incorrect"),
|
||||
},
|
||||
next_index,
|
||||
))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
|
||||
pub struct SettingsFileContent {
|
||||
#[serde(default)]
|
||||
|
@ -403,8 +361,6 @@ pub struct SettingsFileContent {
|
|||
pub vim_mode: Option<bool>,
|
||||
#[serde(default)]
|
||||
pub autosave: Option<Autosave>,
|
||||
#[serde(default)]
|
||||
pub default_dock_anchor: Option<DockAnchor>,
|
||||
#[serde(flatten)]
|
||||
pub editor: EditorSettings,
|
||||
#[serde(default)]
|
||||
|
@ -501,7 +457,6 @@ impl Settings {
|
|||
show_call_status_icon: defaults.show_call_status_icon.unwrap(),
|
||||
vim_mode: defaults.vim_mode.unwrap(),
|
||||
autosave: defaults.autosave.unwrap(),
|
||||
default_dock_anchor: defaults.default_dock_anchor.unwrap(),
|
||||
editor_defaults: EditorSettings {
|
||||
tab_size: required(defaults.editor.tab_size),
|
||||
hard_tabs: required(defaults.editor.hard_tabs),
|
||||
|
@ -596,7 +551,6 @@ impl Settings {
|
|||
);
|
||||
merge(&mut self.vim_mode, data.vim_mode);
|
||||
merge(&mut self.autosave, data.autosave);
|
||||
merge(&mut self.default_dock_anchor, data.default_dock_anchor);
|
||||
merge(&mut self.base_keymap, data.base_keymap);
|
||||
merge(&mut self.features.copilot, data.features.copilot);
|
||||
|
||||
|
@ -796,7 +750,6 @@ impl Settings {
|
|||
show_call_status_icon: true,
|
||||
vim_mode: false,
|
||||
autosave: Autosave::Off,
|
||||
default_dock_anchor: DockAnchor::Bottom,
|
||||
editor_defaults: EditorSettings {
|
||||
tab_size: Some(4.try_into().unwrap()),
|
||||
hard_tabs: Some(false),
|
||||
|
|
|
@ -8,7 +8,6 @@ use gpui::{
|
|||
use settings::Settings;
|
||||
use std::any::TypeId;
|
||||
use workspace::{
|
||||
dock::{Dock, FocusDock},
|
||||
item::ItemHandle,
|
||||
NewTerminal, StatusItemView, Workspace,
|
||||
};
|
||||
|
@ -85,8 +84,8 @@ impl View for TerminalButton {
|
|||
} else {
|
||||
if !active {
|
||||
if let Some(workspace) = this.workspace.upgrade(cx) {
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
Dock::focus_dock(workspace, &Default::default(), cx)
|
||||
workspace.update(cx, |_workspace, _cx| {
|
||||
todo!()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -95,7 +94,7 @@ impl View for TerminalButton {
|
|||
.with_tooltip::<Self>(
|
||||
0,
|
||||
"Show Terminal".into(),
|
||||
Some(Box::new(FocusDock)),
|
||||
None, // TODO! We need a new action here.
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
),
|
||||
|
|
|
@ -73,7 +73,6 @@ pub struct Workspace {
|
|||
pub joining_project_avatar: ImageStyle,
|
||||
pub joining_project_message: ContainedText,
|
||||
pub external_location_message: ContainedText,
|
||||
pub dock: Dock,
|
||||
pub drop_target_overlay_color: Color,
|
||||
}
|
||||
|
||||
|
@ -296,15 +295,6 @@ pub struct Toolbar {
|
|||
pub nav_button: Interactive<IconButton>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Default)]
|
||||
pub struct Dock {
|
||||
pub initial_size_right: f32,
|
||||
pub initial_size_bottom: f32,
|
||||
pub wash_color: Color,
|
||||
pub panel: ContainerStyle,
|
||||
pub maximized: ContainerStyle,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Default)]
|
||||
pub struct Notifications {
|
||||
#[serde(flatten)]
|
||||
|
|
|
@ -1,816 +0,0 @@
|
|||
mod toggle_dock_button;
|
||||
|
||||
use collections::HashMap;
|
||||
use gpui::{
|
||||
actions,
|
||||
elements::{ChildView, Empty, MouseEventHandler, ParentElement, Side, Stack},
|
||||
geometry::vector::Vector2F,
|
||||
platform::{CursorStyle, MouseButton},
|
||||
AnyElement, AppContext, Border, Element, SizeConstraint, ViewContext, ViewHandle,
|
||||
};
|
||||
use settings::{DockAnchor, Settings};
|
||||
use theme::Theme;
|
||||
|
||||
use crate::{sidebar::SidebarSide, BackgroundActions, ItemHandle, Pane, Workspace};
|
||||
pub use toggle_dock_button::ToggleDockButton;
|
||||
|
||||
actions!(
|
||||
dock,
|
||||
[
|
||||
FocusDock,
|
||||
HideDock,
|
||||
AnchorDockRight,
|
||||
AnchorDockBottom,
|
||||
ExpandDock,
|
||||
AddTabToDock,
|
||||
RemoveTabFromDock,
|
||||
]
|
||||
);
|
||||
|
||||
pub fn init(cx: &mut AppContext) {
|
||||
cx.add_action(Dock::focus_dock);
|
||||
cx.add_action(Dock::hide_dock);
|
||||
cx.add_action(
|
||||
|workspace: &mut Workspace, _: &AnchorDockRight, cx: &mut ViewContext<Workspace>| {
|
||||
Dock::move_dock(workspace, DockAnchor::Right, true, cx);
|
||||
},
|
||||
);
|
||||
cx.add_action(
|
||||
|workspace: &mut Workspace, _: &AnchorDockBottom, cx: &mut ViewContext<Workspace>| {
|
||||
Dock::move_dock(workspace, DockAnchor::Bottom, true, cx)
|
||||
},
|
||||
);
|
||||
cx.add_action(
|
||||
|workspace: &mut Workspace, _: &ExpandDock, cx: &mut ViewContext<Workspace>| {
|
||||
Dock::move_dock(workspace, DockAnchor::Expanded, true, cx)
|
||||
},
|
||||
);
|
||||
cx.add_action(
|
||||
|workspace: &mut Workspace, _: &AddTabToDock, cx: &mut ViewContext<Workspace>| {
|
||||
if let Some(active_item) = workspace.active_item(cx) {
|
||||
let item_id = active_item.id();
|
||||
|
||||
let from = workspace.active_pane();
|
||||
let to = workspace.dock_pane();
|
||||
if from.id() == to.id() {
|
||||
return;
|
||||
}
|
||||
|
||||
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>| {
|
||||
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(),
|
||||
to.clone(),
|
||||
item_id,
|
||||
destination_index,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum DockPosition {
|
||||
Shown(DockAnchor),
|
||||
Hidden(DockAnchor),
|
||||
}
|
||||
|
||||
impl Default for DockPosition {
|
||||
fn default() -> Self {
|
||||
DockPosition::Hidden(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn icon_for_dock_anchor(anchor: DockAnchor) -> &'static str {
|
||||
match anchor {
|
||||
DockAnchor::Right => "icons/dock_right_12.svg",
|
||||
DockAnchor::Bottom => "icons/dock_bottom_12.svg",
|
||||
DockAnchor::Expanded => "icons/dock_modal_12.svg",
|
||||
}
|
||||
}
|
||||
|
||||
impl DockPosition {
|
||||
pub fn is_visible(&self) -> bool {
|
||||
match self {
|
||||
DockPosition::Shown(_) => true,
|
||||
DockPosition::Hidden(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn anchor(&self) -> DockAnchor {
|
||||
match self {
|
||||
DockPosition::Shown(anchor) | DockPosition::Hidden(anchor) => *anchor,
|
||||
}
|
||||
}
|
||||
|
||||
fn hide(self) -> Self {
|
||||
match self {
|
||||
DockPosition::Shown(anchor) => DockPosition::Hidden(anchor),
|
||||
DockPosition::Hidden(_) => self,
|
||||
}
|
||||
}
|
||||
|
||||
fn show(self) -> Self {
|
||||
match self {
|
||||
DockPosition::Hidden(anchor) => DockPosition::Shown(anchor),
|
||||
DockPosition::Shown(_) => self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type DockDefaultItemFactory =
|
||||
fn(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) -> Option<Box<dyn ItemHandle>>;
|
||||
|
||||
pub struct Dock {
|
||||
position: DockPosition,
|
||||
panel_sizes: HashMap<DockAnchor, f32>,
|
||||
pane: ViewHandle<Pane>,
|
||||
default_item_factory: DockDefaultItemFactory,
|
||||
}
|
||||
|
||||
impl Dock {
|
||||
pub fn new(
|
||||
default_item_factory: DockDefaultItemFactory,
|
||||
background_actions: BackgroundActions,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) -> Self {
|
||||
let position = DockPosition::Hidden(cx.global::<Settings>().default_dock_anchor);
|
||||
let workspace = cx.weak_handle();
|
||||
let pane =
|
||||
cx.add_view(|cx| Pane::new(workspace, Some(position.anchor()), background_actions, cx));
|
||||
pane.update(cx, |pane, cx| {
|
||||
pane.set_active(false, cx);
|
||||
});
|
||||
cx.subscribe(&pane, Workspace::handle_pane_event).detach();
|
||||
|
||||
Self {
|
||||
pane,
|
||||
panel_sizes: Default::default(),
|
||||
position,
|
||||
default_item_factory,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pane(&self) -> &ViewHandle<Pane> {
|
||||
&self.pane
|
||||
}
|
||||
|
||||
pub fn visible_pane(&self) -> Option<&ViewHandle<Pane>> {
|
||||
self.position.is_visible().then(|| self.pane())
|
||||
}
|
||||
|
||||
pub fn is_anchored_at(&self, anchor: DockAnchor) -> bool {
|
||||
self.position.is_visible() && self.position.anchor() == anchor
|
||||
}
|
||||
|
||||
pub(crate) fn set_dock_position(
|
||||
workspace: &mut Workspace,
|
||||
new_position: DockPosition,
|
||||
focus: bool,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) {
|
||||
workspace.dock.position = new_position;
|
||||
// Tell the pane about the new anchor position
|
||||
workspace.dock.pane.update(cx, |pane, cx| {
|
||||
pane.set_docked(Some(new_position.anchor()), cx)
|
||||
});
|
||||
|
||||
if workspace.dock.position.is_visible() {
|
||||
// Close the right sidebar if the dock is on the right side and the right sidebar is open
|
||||
if workspace.dock.position.anchor() == DockAnchor::Right {
|
||||
if workspace.right_sidebar().read(cx).is_open() {
|
||||
workspace.toggle_sidebar(SidebarSide::Right, cx);
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the pane has at least one item or construct a default item to put in it
|
||||
let pane = workspace.dock.pane.clone();
|
||||
if pane.read(cx).items().next().is_none() {
|
||||
if let Some(item_to_add) = (workspace.dock.default_item_factory)(workspace, cx) {
|
||||
Pane::add_item(workspace, &pane, item_to_add, focus, focus, None, cx);
|
||||
} else {
|
||||
workspace.dock.position = workspace.dock.position.hide();
|
||||
}
|
||||
} else {
|
||||
if focus {
|
||||
cx.focus(&pane);
|
||||
}
|
||||
}
|
||||
} else if let Some(last_active_center_pane) = workspace
|
||||
.last_active_center_pane
|
||||
.as_ref()
|
||||
.and_then(|pane| pane.upgrade(cx))
|
||||
{
|
||||
if focus {
|
||||
cx.focus(&last_active_center_pane);
|
||||
}
|
||||
}
|
||||
cx.emit(crate::Event::DockAnchorChanged);
|
||||
workspace.serialize_workspace(cx);
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn hide(workspace: &mut Workspace, cx: &mut ViewContext<Workspace>) {
|
||||
Self::set_dock_position(workspace, workspace.dock.position.hide(), true, cx);
|
||||
}
|
||||
|
||||
pub fn show(workspace: &mut Workspace, focus: bool, cx: &mut ViewContext<Workspace>) {
|
||||
Self::set_dock_position(workspace, workspace.dock.position.show(), focus, cx);
|
||||
}
|
||||
|
||||
pub fn hide_on_sidebar_shown(
|
||||
workspace: &mut Workspace,
|
||||
sidebar_side: SidebarSide,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) {
|
||||
if (sidebar_side == SidebarSide::Right && workspace.dock.is_anchored_at(DockAnchor::Right))
|
||||
|| workspace.dock.is_anchored_at(DockAnchor::Expanded)
|
||||
{
|
||||
Self::hide(workspace, cx);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn focus_dock(workspace: &mut Workspace, _: &FocusDock, cx: &mut ViewContext<Workspace>) {
|
||||
Self::set_dock_position(workspace, workspace.dock.position.show(), true, cx);
|
||||
}
|
||||
|
||||
pub fn hide_dock(workspace: &mut Workspace, _: &HideDock, cx: &mut ViewContext<Workspace>) {
|
||||
Self::set_dock_position(workspace, workspace.dock.position.hide(), true, cx);
|
||||
}
|
||||
|
||||
pub fn move_dock(
|
||||
workspace: &mut Workspace,
|
||||
new_anchor: DockAnchor,
|
||||
focus: bool,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) {
|
||||
Self::set_dock_position(workspace, DockPosition::Shown(new_anchor), focus, cx);
|
||||
}
|
||||
|
||||
pub fn render(
|
||||
&self,
|
||||
theme: &Theme,
|
||||
anchor: DockAnchor,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) -> Option<AnyElement<Workspace>> {
|
||||
let style = &theme.workspace.dock;
|
||||
|
||||
self.position
|
||||
.is_visible()
|
||||
.then(|| self.position.anchor())
|
||||
.filter(|current_anchor| *current_anchor == anchor)
|
||||
.map(|anchor| match anchor {
|
||||
DockAnchor::Bottom | DockAnchor::Right => {
|
||||
let mut panel_style = style.panel.clone();
|
||||
let (resize_side, initial_size) = if anchor == DockAnchor::Bottom {
|
||||
panel_style.border = Border {
|
||||
top: true,
|
||||
bottom: false,
|
||||
left: false,
|
||||
right: false,
|
||||
..panel_style.border
|
||||
};
|
||||
|
||||
(Side::Top, style.initial_size_bottom)
|
||||
} else {
|
||||
panel_style.border = Border {
|
||||
top: false,
|
||||
bottom: false,
|
||||
left: true,
|
||||
right: false,
|
||||
..panel_style.border
|
||||
};
|
||||
(Side::Left, style.initial_size_right)
|
||||
};
|
||||
|
||||
enum DockResizeHandle {}
|
||||
|
||||
let resizable = ChildView::new(&self.pane, cx)
|
||||
.contained()
|
||||
.with_style(panel_style)
|
||||
.with_resize_handle::<DockResizeHandle>(
|
||||
resize_side as usize,
|
||||
resize_side,
|
||||
4.,
|
||||
self.panel_sizes
|
||||
.get(&anchor)
|
||||
.copied()
|
||||
.unwrap_or(initial_size),
|
||||
cx,
|
||||
);
|
||||
|
||||
let size = resizable.current_size();
|
||||
cx.defer(move |workspace, _| {
|
||||
workspace.dock.panel_sizes.insert(anchor, size);
|
||||
});
|
||||
|
||||
if anchor == DockAnchor::Right {
|
||||
resizable.constrained().dynamically(|constraint, _, cx| {
|
||||
SizeConstraint::new(
|
||||
Vector2F::new(20., constraint.min.y()),
|
||||
Vector2F::new(cx.window_size().x() * 0.8, constraint.max.y()),
|
||||
)
|
||||
})
|
||||
} else {
|
||||
resizable.constrained().dynamically(|constraint, _, cx| {
|
||||
SizeConstraint::new(
|
||||
Vector2F::new(constraint.min.x(), 50.),
|
||||
Vector2F::new(constraint.max.x(), cx.window_size().y() * 0.8),
|
||||
)
|
||||
})
|
||||
}
|
||||
.into_any()
|
||||
}
|
||||
DockAnchor::Expanded => {
|
||||
enum ExpandedDockWash {}
|
||||
enum ExpandedDockPane {}
|
||||
Stack::new()
|
||||
.with_child(
|
||||
// Render wash under the dock which when clicked hides it
|
||||
MouseEventHandler::<ExpandedDockWash, _>::new(0, cx, |_, _| {
|
||||
Empty::new()
|
||||
.contained()
|
||||
.with_background_color(style.wash_color)
|
||||
})
|
||||
.capture_all()
|
||||
.on_down(MouseButton::Left, |_, workspace, cx| {
|
||||
Dock::hide_dock(workspace, &Default::default(), cx)
|
||||
})
|
||||
.with_cursor_style(CursorStyle::Arrow),
|
||||
)
|
||||
.with_child(
|
||||
MouseEventHandler::<ExpandedDockPane, _>::new(0, cx, |_state, cx| {
|
||||
ChildView::new(&self.pane, cx)
|
||||
})
|
||||
// Make sure all events directly under the dock pane
|
||||
// are captured
|
||||
.capture_all()
|
||||
.contained()
|
||||
.with_style(style.maximized),
|
||||
)
|
||||
.into_any()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn position(&self) -> DockPosition {
|
||||
self.position
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
path::PathBuf,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use gpui::{AppContext, BorrowWindowContext, TestAppContext, ViewContext, WindowContext};
|
||||
use project::{FakeFs, Project};
|
||||
use settings::Settings;
|
||||
use theme::ThemeRegistry;
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
dock,
|
||||
item::{self, test::TestItem},
|
||||
persistence::model::{
|
||||
SerializedItem, SerializedPane, SerializedPaneGroup, SerializedWorkspace,
|
||||
},
|
||||
register_deserializable_item,
|
||||
sidebar::Sidebar,
|
||||
AppState, ItemHandle, Workspace,
|
||||
};
|
||||
|
||||
pub fn default_item_factory(
|
||||
_workspace: &mut Workspace,
|
||||
cx: &mut ViewContext<Workspace>,
|
||||
) -> Option<Box<dyn ItemHandle>> {
|
||||
Some(Box::new(cx.add_view(|_| TestItem::new())))
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_dock_workspace_infinite_loop(cx: &mut TestAppContext) {
|
||||
cx.foreground().forbid_parking();
|
||||
Settings::test_async(cx);
|
||||
|
||||
cx.update(|cx| {
|
||||
register_deserializable_item::<item::test::TestItem>(cx);
|
||||
});
|
||||
|
||||
let serialized_workspace = SerializedWorkspace {
|
||||
id: 0,
|
||||
location: Vec::<PathBuf>::new().into(),
|
||||
dock_position: dock::DockPosition::Shown(DockAnchor::Expanded),
|
||||
center_group: SerializedPaneGroup::Pane(SerializedPane {
|
||||
active: false,
|
||||
children: vec![],
|
||||
}),
|
||||
dock_pane: SerializedPane {
|
||||
active: true,
|
||||
children: vec![SerializedItem {
|
||||
active: true,
|
||||
item_id: 0,
|
||||
kind: "TestItem".into(),
|
||||
}],
|
||||
},
|
||||
left_sidebar_open: false,
|
||||
bounds: Default::default(),
|
||||
display: Default::default(),
|
||||
};
|
||||
|
||||
let fs = FakeFs::new(cx.background());
|
||||
let project = Project::test(fs, [], cx).await;
|
||||
|
||||
let (_, _workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(
|
||||
Some(serialized_workspace),
|
||||
0,
|
||||
project.clone(),
|
||||
Arc::new(AppState {
|
||||
languages: project.read(cx).languages().clone(),
|
||||
themes: ThemeRegistry::new((), cx.font_cache().clone()),
|
||||
client: project.read(cx).client(),
|
||||
user_store: project.read(cx).user_store(),
|
||||
fs: project.read(cx).fs().clone(),
|
||||
build_window_options: |_, _, _| Default::default(),
|
||||
initialize_workspace: |_, _, _| {},
|
||||
dock_default_item_factory: default_item_factory,
|
||||
background_actions: || &[],
|
||||
}),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
||||
cx.foreground().run_until_parked();
|
||||
//Should terminate
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_dock_hides_when_pane_empty(cx: &mut TestAppContext) {
|
||||
let mut cx = DockTestContext::new(cx).await;
|
||||
|
||||
// Closing the last item in the dock hides the dock
|
||||
cx.move_dock(DockAnchor::Right);
|
||||
let old_items = cx.dock_items();
|
||||
assert!(!old_items.is_empty());
|
||||
cx.close_dock_items().await;
|
||||
cx.assert_dock_position(DockPosition::Hidden(DockAnchor::Right));
|
||||
|
||||
// Reopening the dock adds a new item
|
||||
cx.move_dock(DockAnchor::Right);
|
||||
let new_items = cx.dock_items();
|
||||
assert!(!new_items.is_empty());
|
||||
assert!(new_items
|
||||
.into_iter()
|
||||
.all(|new_item| !old_items.contains(&new_item)));
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_dock_panel_collisions(cx: &mut TestAppContext) {
|
||||
let mut cx = DockTestContext::new(cx).await;
|
||||
|
||||
// Dock closes when expanded for either panel
|
||||
cx.move_dock(DockAnchor::Expanded);
|
||||
cx.open_sidebar(SidebarSide::Left);
|
||||
cx.assert_dock_position(DockPosition::Hidden(DockAnchor::Expanded));
|
||||
cx.close_sidebar(SidebarSide::Left);
|
||||
cx.move_dock(DockAnchor::Expanded);
|
||||
cx.open_sidebar(SidebarSide::Right);
|
||||
cx.assert_dock_position(DockPosition::Hidden(DockAnchor::Expanded));
|
||||
|
||||
// Dock closes in the right position if the right sidebar is opened
|
||||
cx.move_dock(DockAnchor::Right);
|
||||
cx.open_sidebar(SidebarSide::Left);
|
||||
cx.assert_dock_position(DockPosition::Shown(DockAnchor::Right));
|
||||
cx.open_sidebar(SidebarSide::Right);
|
||||
cx.assert_dock_position(DockPosition::Hidden(DockAnchor::Right));
|
||||
cx.close_sidebar(SidebarSide::Right);
|
||||
|
||||
// Dock in bottom position ignores sidebars
|
||||
cx.move_dock(DockAnchor::Bottom);
|
||||
cx.open_sidebar(SidebarSide::Left);
|
||||
cx.open_sidebar(SidebarSide::Right);
|
||||
cx.assert_dock_position(DockPosition::Shown(DockAnchor::Bottom));
|
||||
|
||||
// Opening the dock in the right position closes the right sidebar
|
||||
cx.move_dock(DockAnchor::Right);
|
||||
cx.assert_sidebar_closed(SidebarSide::Right);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_focusing_panes_shows_and_hides_dock(cx: &mut TestAppContext) {
|
||||
let mut cx = DockTestContext::new(cx).await;
|
||||
|
||||
// Focusing an item not in the dock when expanded hides the dock
|
||||
let center_item = cx.add_item_to_center_pane();
|
||||
cx.move_dock(DockAnchor::Expanded);
|
||||
let dock_item = cx
|
||||
.dock_items()
|
||||
.get(0)
|
||||
.cloned()
|
||||
.expect("Dock should have an item at this point");
|
||||
center_item.update(&mut cx, |_, cx| cx.focus_self());
|
||||
cx.assert_dock_position(DockPosition::Hidden(DockAnchor::Expanded));
|
||||
|
||||
// Focusing an item not in the dock when not expanded, leaves the dock open but inactive
|
||||
cx.move_dock(DockAnchor::Right);
|
||||
center_item.update(&mut cx, |_, cx| cx.focus_self());
|
||||
cx.assert_dock_position(DockPosition::Shown(DockAnchor::Right));
|
||||
cx.assert_dock_pane_inactive();
|
||||
cx.assert_workspace_pane_active();
|
||||
|
||||
// Focusing an item in the dock activates it's pane
|
||||
dock_item.update(&mut cx, |_, cx| cx.focus_self());
|
||||
cx.assert_dock_position(DockPosition::Shown(DockAnchor::Right));
|
||||
cx.assert_dock_pane_active();
|
||||
cx.assert_workspace_pane_inactive();
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_toggle_dock_focus(cx: &mut TestAppContext) {
|
||||
let mut cx = DockTestContext::new(cx).await;
|
||||
|
||||
cx.move_dock(DockAnchor::Right);
|
||||
cx.assert_dock_pane_active();
|
||||
cx.hide_dock();
|
||||
cx.move_dock(DockAnchor::Right);
|
||||
cx.assert_dock_pane_active();
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_activate_next_and_prev_pane(cx: &mut TestAppContext) {
|
||||
let mut cx = DockTestContext::new(cx).await;
|
||||
|
||||
cx.move_dock(DockAnchor::Right);
|
||||
cx.assert_dock_pane_active();
|
||||
|
||||
cx.update_workspace(|workspace, cx| workspace.activate_next_pane(cx));
|
||||
cx.assert_dock_pane_active();
|
||||
|
||||
cx.update_workspace(|workspace, cx| workspace.activate_previous_pane(cx));
|
||||
cx.assert_dock_pane_active();
|
||||
}
|
||||
|
||||
struct DockTestContext<'a> {
|
||||
pub cx: &'a mut TestAppContext,
|
||||
pub window_id: usize,
|
||||
pub workspace: ViewHandle<Workspace>,
|
||||
}
|
||||
|
||||
impl<'a> DockTestContext<'a> {
|
||||
pub async fn new(cx: &'a mut TestAppContext) -> DockTestContext<'a> {
|
||||
Settings::test_async(cx);
|
||||
let fs = FakeFs::new(cx.background());
|
||||
|
||||
cx.update(|cx| init(cx));
|
||||
let project = Project::test(fs, [], cx).await;
|
||||
let (window_id, workspace) = cx.add_window(|cx| {
|
||||
Workspace::new(
|
||||
None,
|
||||
0,
|
||||
project.clone(),
|
||||
Arc::new(AppState {
|
||||
languages: project.read(cx).languages().clone(),
|
||||
themes: ThemeRegistry::new((), cx.font_cache().clone()),
|
||||
client: project.read(cx).client(),
|
||||
user_store: project.read(cx).user_store(),
|
||||
fs: project.read(cx).fs().clone(),
|
||||
build_window_options: |_, _, _| Default::default(),
|
||||
initialize_workspace: |_, _, _| {},
|
||||
dock_default_item_factory: default_item_factory,
|
||||
background_actions: || &[],
|
||||
}),
|
||||
cx,
|
||||
)
|
||||
});
|
||||
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
let left_panel = cx.add_view(|_| TestItem::new());
|
||||
workspace.left_sidebar().update(cx, |sidebar, cx| {
|
||||
sidebar.add_item(
|
||||
"icons/folder_tree_16.svg",
|
||||
"Left Test Panel".to_string(),
|
||||
left_panel.clone(),
|
||||
cx,
|
||||
);
|
||||
});
|
||||
|
||||
let right_panel = cx.add_view(|_| TestItem::new());
|
||||
workspace.right_sidebar().update(cx, |sidebar, cx| {
|
||||
sidebar.add_item(
|
||||
"icons/folder_tree_16.svg",
|
||||
"Right Test Panel".to_string(),
|
||||
right_panel.clone(),
|
||||
cx,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
Self {
|
||||
cx,
|
||||
window_id,
|
||||
workspace,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn workspace<F, T>(&self, read: F) -> T
|
||||
where
|
||||
F: FnOnce(&Workspace, &ViewContext<Workspace>) -> T,
|
||||
{
|
||||
self.workspace.read_with(self.cx, read)
|
||||
}
|
||||
|
||||
pub fn update_workspace<F, T>(&mut self, update: F) -> T
|
||||
where
|
||||
F: FnOnce(&mut Workspace, &mut ViewContext<Workspace>) -> T,
|
||||
{
|
||||
self.workspace.update(self.cx, update)
|
||||
}
|
||||
|
||||
pub fn sidebar<F, T>(&self, sidebar_side: SidebarSide, read: F) -> T
|
||||
where
|
||||
F: FnOnce(&Sidebar, &AppContext) -> T,
|
||||
{
|
||||
self.workspace(|workspace, cx| {
|
||||
let sidebar = match sidebar_side {
|
||||
SidebarSide::Left => workspace.left_sidebar(),
|
||||
SidebarSide::Right => workspace.right_sidebar(),
|
||||
}
|
||||
.read(cx);
|
||||
|
||||
read(sidebar, cx)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn center_pane_handle(&self) -> ViewHandle<Pane> {
|
||||
self.workspace(|workspace, cx| {
|
||||
workspace
|
||||
.last_active_center_pane
|
||||
.clone()
|
||||
.and_then(|pane| pane.upgrade(cx))
|
||||
.unwrap_or_else(|| workspace.center.panes()[0].clone())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn add_item_to_center_pane(&mut self) -> ViewHandle<TestItem> {
|
||||
self.update_workspace(|workspace, cx| {
|
||||
let item = cx.add_view(|_| TestItem::new());
|
||||
let pane = workspace
|
||||
.last_active_center_pane
|
||||
.clone()
|
||||
.and_then(|pane| pane.upgrade(cx))
|
||||
.unwrap_or_else(|| workspace.center.panes()[0].clone());
|
||||
Pane::add_item(
|
||||
workspace,
|
||||
&pane,
|
||||
Box::new(item.clone()),
|
||||
true,
|
||||
true,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
item
|
||||
})
|
||||
}
|
||||
|
||||
pub fn dock_pane<F, T>(&self, read: F) -> T
|
||||
where
|
||||
F: FnOnce(&Pane, &AppContext) -> T,
|
||||
{
|
||||
self.workspace(|workspace, cx| {
|
||||
let dock_pane = workspace.dock_pane().read(cx);
|
||||
read(dock_pane, cx)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn move_dock(&mut self, anchor: DockAnchor) {
|
||||
self.update_workspace(|workspace, cx| Dock::move_dock(workspace, anchor, true, cx));
|
||||
}
|
||||
|
||||
pub fn hide_dock(&mut self) {
|
||||
self.cx.dispatch_action(self.window_id, HideDock);
|
||||
}
|
||||
|
||||
pub fn open_sidebar(&mut self, sidebar_side: SidebarSide) {
|
||||
if !self.sidebar(sidebar_side, |sidebar, _| sidebar.is_open()) {
|
||||
self.update_workspace(|workspace, cx| workspace.toggle_sidebar(sidebar_side, cx));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close_sidebar(&mut self, sidebar_side: SidebarSide) {
|
||||
if self.sidebar(sidebar_side, |sidebar, _| sidebar.is_open()) {
|
||||
self.update_workspace(|workspace, cx| workspace.toggle_sidebar(sidebar_side, cx));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dock_items(&self) -> Vec<ViewHandle<TestItem>> {
|
||||
self.dock_pane(|pane, cx| {
|
||||
pane.items()
|
||||
.map(|item| {
|
||||
item.act_as::<TestItem>(cx)
|
||||
.expect("Dock Test Context uses TestItems in the dock")
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn close_dock_items(&mut self) {
|
||||
self.update_workspace(|workspace, cx| {
|
||||
Pane::close_items(workspace, workspace.dock_pane().clone(), cx, |_| true)
|
||||
})
|
||||
.await
|
||||
.expect("Could not close dock items")
|
||||
}
|
||||
|
||||
pub fn assert_dock_position(&self, expected_position: DockPosition) {
|
||||
self.workspace(|workspace, _| assert_eq!(workspace.dock.position, expected_position));
|
||||
}
|
||||
|
||||
pub fn assert_sidebar_closed(&self, sidebar_side: SidebarSide) {
|
||||
assert!(!self.sidebar(sidebar_side, |sidebar, _| sidebar.is_open()));
|
||||
}
|
||||
|
||||
pub fn assert_workspace_pane_active(&self) {
|
||||
assert!(self
|
||||
.center_pane_handle()
|
||||
.read_with(self.cx, |pane, _| pane.is_active()));
|
||||
}
|
||||
|
||||
pub fn assert_workspace_pane_inactive(&self) {
|
||||
assert!(!self
|
||||
.center_pane_handle()
|
||||
.read_with(self.cx, |pane, _| pane.is_active()));
|
||||
}
|
||||
|
||||
pub fn assert_dock_pane_active(&self) {
|
||||
assert!(self.dock_pane(|pane, _| pane.is_active()))
|
||||
}
|
||||
|
||||
pub fn assert_dock_pane_inactive(&self) {
|
||||
assert!(!self.dock_pane(|pane, _| pane.is_active()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Deref for DockTestContext<'a> {
|
||||
type Target = gpui::TestAppContext;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.cx
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> DerefMut for DockTestContext<'a> {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.cx
|
||||
}
|
||||
}
|
||||
|
||||
impl BorrowWindowContext for DockTestContext<'_> {
|
||||
fn read_with<T, F: FnOnce(&WindowContext) -> T>(&self, window_id: usize, f: F) -> T {
|
||||
BorrowWindowContext::read_with(self.cx, window_id, f)
|
||||
}
|
||||
|
||||
fn update<T, F: FnOnce(&mut WindowContext) -> T>(&mut self, window_id: usize, f: F) -> T {
|
||||
BorrowWindowContext::update(self.cx, window_id, f)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,126 +0,0 @@
|
|||
use super::{icon_for_dock_anchor, Dock, FocusDock, HideDock};
|
||||
use crate::{handle_dropped_item, StatusItemView, Workspace};
|
||||
use gpui::{
|
||||
elements::{Empty, MouseEventHandler, Svg},
|
||||
platform::CursorStyle,
|
||||
platform::MouseButton,
|
||||
AnyElement, Element, Entity, View, ViewContext, ViewHandle, WeakViewHandle,
|
||||
};
|
||||
use settings::Settings;
|
||||
|
||||
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::ViewContext<Self>) -> AnyElement<Self> {
|
||||
let workspace = self.workspace.upgrade(cx);
|
||||
|
||||
if workspace.is_none() {
|
||||
return Empty::new().into_any();
|
||||
}
|
||||
|
||||
let workspace = workspace.unwrap();
|
||||
let dock_position = workspace.read(cx).dock.position;
|
||||
let dock_pane = workspace.read(cx).dock_pane().clone();
|
||||
|
||||
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)
|
||||
}
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_up(MouseButton::Left, move |event, this, cx| {
|
||||
let drop_index = dock_pane.read(cx).items_len() + 1;
|
||||
handle_dropped_item(
|
||||
event,
|
||||
this.workspace.clone(),
|
||||
&dock_pane.downgrade(),
|
||||
drop_index,
|
||||
false,
|
||||
None,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
|
||||
if dock_position.is_visible() {
|
||||
button
|
||||
.on_click(MouseButton::Left, |_, this, cx| {
|
||||
if let Some(workspace) = this.workspace.upgrade(cx) {
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
Dock::hide_dock(workspace, &Default::default(), cx)
|
||||
})
|
||||
}
|
||||
})
|
||||
.with_tooltip::<Self>(
|
||||
0,
|
||||
"Hide Dock".into(),
|
||||
Some(Box::new(HideDock)),
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
)
|
||||
} else {
|
||||
button
|
||||
.on_click(MouseButton::Left, |_, this, cx| {
|
||||
if let Some(workspace) = this.workspace.upgrade(cx) {
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
Dock::focus_dock(workspace, &Default::default(), cx)
|
||||
})
|
||||
}
|
||||
})
|
||||
.with_tooltip::<Self>(
|
||||
0,
|
||||
"Focus Dock".into(),
|
||||
Some(Box::new(FocusDock)),
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
)
|
||||
}
|
||||
.into_any()
|
||||
}
|
||||
}
|
||||
|
||||
impl StatusItemView for ToggleDockButton {
|
||||
fn set_active_pane_item(
|
||||
&mut self,
|
||||
_active_pane_item: Option<&dyn crate::ItemHandle>,
|
||||
_cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
//Not applicable
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@ mod dragged_item_receiver;
|
|||
|
||||
use super::{ItemHandle, SplitDirection};
|
||||
use crate::{
|
||||
dock::{icon_for_dock_anchor, AnchorDockBottom, AnchorDockRight, Dock, ExpandDock},
|
||||
item::WeakItemHandle,
|
||||
toolbar::Toolbar,
|
||||
Item, NewFile, NewSearch, NewTerminal, Workspace,
|
||||
|
@ -29,7 +28,7 @@ use gpui::{
|
|||
};
|
||||
use project::{Project, ProjectEntryId, ProjectPath};
|
||||
use serde::Deserialize;
|
||||
use settings::{Autosave, DockAnchor, Settings};
|
||||
use settings::{Autosave, Settings};
|
||||
use std::{any::Any, cell::RefCell, cmp, mem, path::Path, rc::Rc};
|
||||
use theme::Theme;
|
||||
use util::ResultExt;
|
||||
|
@ -148,7 +147,6 @@ pub struct Pane {
|
|||
toolbar: ViewHandle<Toolbar>,
|
||||
tab_bar_context_menu: TabBarContextMenu,
|
||||
tab_context_menu: ViewHandle<ContextMenu>,
|
||||
docked: Option<DockAnchor>,
|
||||
_background_actions: BackgroundActions,
|
||||
workspace: WeakViewHandle<Workspace>,
|
||||
has_focus: bool,
|
||||
|
@ -204,7 +202,6 @@ pub enum ReorderBehavior {
|
|||
enum TabBarContextMenuKind {
|
||||
New,
|
||||
Split,
|
||||
Dock,
|
||||
}
|
||||
|
||||
struct TabBarContextMenu {
|
||||
|
@ -224,7 +221,6 @@ impl TabBarContextMenu {
|
|||
impl Pane {
|
||||
pub fn new(
|
||||
workspace: WeakViewHandle<Workspace>,
|
||||
docked: Option<DockAnchor>,
|
||||
background_actions: BackgroundActions,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Self {
|
||||
|
@ -256,7 +252,6 @@ impl Pane {
|
|||
handle: context_menu,
|
||||
},
|
||||
tab_context_menu: cx.add_view(|cx| ContextMenu::new(pane_view_id, cx)),
|
||||
docked,
|
||||
_background_actions: background_actions,
|
||||
workspace,
|
||||
has_focus: false,
|
||||
|
@ -280,11 +275,6 @@ impl Pane {
|
|||
self.has_focus
|
||||
}
|
||||
|
||||
pub fn set_docked(&mut self, docked: Option<DockAnchor>, cx: &mut ViewContext<Self>) {
|
||||
self.docked = docked;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
pub fn nav_history_for_item<T: Item>(&self, item: &ViewHandle<T>) -> ItemNavHistory {
|
||||
ItemNavHistory {
|
||||
history: self.nav_history.clone(),
|
||||
|
@ -1157,23 +1147,6 @@ impl Pane {
|
|||
self.tab_bar_context_menu.kind = TabBarContextMenuKind::Split;
|
||||
}
|
||||
|
||||
fn deploy_dock_menu(&mut self, cx: &mut ViewContext<Self>) {
|
||||
self.tab_bar_context_menu.handle.update(cx, |menu, cx| {
|
||||
menu.show(
|
||||
Default::default(),
|
||||
AnchorCorner::TopRight,
|
||||
vec![
|
||||
ContextMenuItem::action("Anchor Dock Right", AnchorDockRight),
|
||||
ContextMenuItem::action("Anchor Dock Bottom", AnchorDockBottom),
|
||||
ContextMenuItem::action("Expand Dock", ExpandDock),
|
||||
],
|
||||
cx,
|
||||
);
|
||||
});
|
||||
|
||||
self.tab_bar_context_menu.kind = TabBarContextMenuKind::Dock;
|
||||
}
|
||||
|
||||
fn deploy_new_menu(&mut self, cx: &mut ViewContext<Self>) {
|
||||
self.tab_bar_context_menu.handle.update(cx, |menu, cx| {
|
||||
menu.show(
|
||||
|
@ -1616,51 +1589,13 @@ impl Pane {
|
|||
self.tab_bar_context_menu
|
||||
.handle_if_kind(TabBarContextMenuKind::New),
|
||||
))
|
||||
.with_child(
|
||||
self.docked
|
||||
.map(|anchor| {
|
||||
// Add the dock menu button if this pane is a dock
|
||||
let dock_icon = icon_for_dock_anchor(anchor);
|
||||
|
||||
render_tab_bar_button(
|
||||
1,
|
||||
dock_icon,
|
||||
cx,
|
||||
|pane, cx| pane.deploy_dock_menu(cx),
|
||||
self.tab_bar_context_menu
|
||||
.handle_if_kind(TabBarContextMenuKind::Dock),
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
// Add the split menu if this pane is not a dock
|
||||
render_tab_bar_button(
|
||||
2,
|
||||
"icons/split_12.svg",
|
||||
cx,
|
||||
|pane, cx| pane.deploy_split_menu(cx),
|
||||
self.tab_bar_context_menu
|
||||
.handle_if_kind(TabBarContextMenuKind::Split),
|
||||
)
|
||||
}),
|
||||
)
|
||||
// Add the close dock button if this pane is a dock
|
||||
.with_children(self.docked.map(|_| {
|
||||
render_tab_bar_button(
|
||||
3,
|
||||
"icons/x_mark_8.svg",
|
||||
cx,
|
||||
|this, cx| {
|
||||
if let Some(workspace) = this.workspace.upgrade(cx) {
|
||||
cx.window_context().defer(move |cx| {
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
Dock::hide_dock(workspace, &Default::default(), cx)
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
None,
|
||||
)
|
||||
}))
|
||||
.with_child(render_tab_bar_button(
|
||||
2,
|
||||
"icons/split_12.svg",
|
||||
cx,
|
||||
|pane, cx| pane.deploy_split_menu(cx),
|
||||
self.tab_bar_context_menu.handle_if_kind(TabBarContextMenuKind::Split),
|
||||
))
|
||||
.contained()
|
||||
.with_style(theme.workspace.tab_bar.pane_button_container)
|
||||
.flex(1., false)
|
||||
|
@ -1737,11 +1672,7 @@ impl View for Pane {
|
|||
0,
|
||||
self.active_item_index + 1,
|
||||
false,
|
||||
if self.docked.is_some() {
|
||||
None
|
||||
} else {
|
||||
Some(100.)
|
||||
},
|
||||
Some(100.),
|
||||
cx,
|
||||
{
|
||||
let toolbar = self.toolbar.clone();
|
||||
|
@ -1843,9 +1774,6 @@ impl View for Pane {
|
|||
|
||||
fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
|
||||
Self::reset_to_default_keymap_context(keymap);
|
||||
if self.docked.is_some() {
|
||||
keymap.add_identifier("docked");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ use gpui::{platform::WindowBounds, Axis};
|
|||
use util::{unzip_option, ResultExt};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::dock::DockPosition;
|
||||
use crate::WorkspaceId;
|
||||
|
||||
use model::{
|
||||
|
@ -25,9 +24,9 @@ define_connection! {
|
|||
// workspaces(
|
||||
// workspace_id: usize, // Primary key for workspaces
|
||||
// workspace_location: Bincode<Vec<PathBuf>>,
|
||||
// dock_visible: bool,
|
||||
// dock_anchor: DockAnchor, // 'Bottom' / 'Right' / 'Expanded'
|
||||
// dock_pane: Option<usize>, // PaneId
|
||||
// dock_visible: bool, // Deprecated
|
||||
// dock_anchor: DockAnchor, // Deprecated
|
||||
// dock_pane: Option<usize>, // Deprecated
|
||||
// left_sidebar_open: boolean,
|
||||
// timestamp: String, // UTC YYYY-MM-DD HH:MM:SS
|
||||
// window_state: String, // WindowBounds Discriminant
|
||||
|
@ -71,10 +70,10 @@ define_connection! {
|
|||
CREATE TABLE workspaces(
|
||||
workspace_id INTEGER PRIMARY KEY,
|
||||
workspace_location BLOB UNIQUE,
|
||||
dock_visible INTEGER, // Boolean
|
||||
dock_anchor TEXT, // Enum: 'Bottom' / 'Right' / 'Expanded'
|
||||
dock_pane INTEGER, // NULL indicates that we don't have a dock pane yet
|
||||
left_sidebar_open INTEGER, //Boolean
|
||||
dock_visible INTEGER, // Deprecated. Preserving so users can downgrade Zed.
|
||||
dock_anchor TEXT, // Deprecated. Preserving so users can downgrade Zed.
|
||||
dock_pane INTEGER, // Deprecated. Preserving so users can downgrade Zed.
|
||||
left_sidebar_open INTEGER, // Boolean
|
||||
timestamp TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
FOREIGN KEY(dock_pane) REFERENCES panes(pane_id)
|
||||
) STRICT;
|
||||
|
@ -146,11 +145,10 @@ impl WorkspaceDb {
|
|||
|
||||
// Note that we re-assign the workspace_id here in case it's empty
|
||||
// and we've grabbed the most recent workspace
|
||||
let (workspace_id, workspace_location, left_sidebar_open, dock_position, bounds, display): (
|
||||
let (workspace_id, workspace_location, left_sidebar_open, bounds, display): (
|
||||
WorkspaceId,
|
||||
WorkspaceLocation,
|
||||
bool,
|
||||
DockPosition,
|
||||
Option<WindowBounds>,
|
||||
Option<Uuid>,
|
||||
) = self
|
||||
|
@ -159,8 +157,6 @@ impl WorkspaceDb {
|
|||
workspace_id,
|
||||
workspace_location,
|
||||
left_sidebar_open,
|
||||
dock_visible,
|
||||
dock_anchor,
|
||||
window_state,
|
||||
window_x,
|
||||
window_y,
|
||||
|
@ -178,15 +174,10 @@ impl WorkspaceDb {
|
|||
Some(SerializedWorkspace {
|
||||
id: workspace_id,
|
||||
location: workspace_location.clone(),
|
||||
dock_pane: self
|
||||
.get_dock_pane(workspace_id)
|
||||
.context("Getting dock pane")
|
||||
.log_err()?,
|
||||
center_group: self
|
||||
.get_center_pane_group(workspace_id)
|
||||
.context("Getting center group")
|
||||
.log_err()?,
|
||||
dock_position,
|
||||
left_sidebar_open,
|
||||
bounds,
|
||||
display,
|
||||
|
@ -200,7 +191,6 @@ impl WorkspaceDb {
|
|||
conn.with_savepoint("update_worktrees", || {
|
||||
// Clear out panes and pane_groups
|
||||
conn.exec_bound(sql!(
|
||||
UPDATE workspaces SET dock_pane = NULL WHERE workspace_id = ?1;
|
||||
DELETE FROM pane_groups WHERE workspace_id = ?1;
|
||||
DELETE FROM panes WHERE workspace_id = ?1;))?(workspace.id)
|
||||
.expect("Clearing old panes");
|
||||
|
@ -216,41 +206,24 @@ impl WorkspaceDb {
|
|||
workspace_id,
|
||||
workspace_location,
|
||||
left_sidebar_open,
|
||||
dock_visible,
|
||||
dock_anchor,
|
||||
timestamp
|
||||
)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, CURRENT_TIMESTAMP)
|
||||
VALUES (?1, ?2, ?3, CURRENT_TIMESTAMP)
|
||||
ON CONFLICT DO
|
||||
UPDATE SET
|
||||
workspace_location = ?2,
|
||||
left_sidebar_open = ?3,
|
||||
dock_visible = ?4,
|
||||
dock_anchor = ?5,
|
||||
timestamp = CURRENT_TIMESTAMP
|
||||
))?((
|
||||
workspace.id,
|
||||
&workspace.location,
|
||||
workspace.left_sidebar_open,
|
||||
workspace.dock_position,
|
||||
))
|
||||
.context("Updating workspace")?;
|
||||
|
||||
// Save center pane group and dock pane
|
||||
// Save center pane group
|
||||
Self::save_pane_group(conn, workspace.id, &workspace.center_group, None)
|
||||
.context("save pane group in save workspace")?;
|
||||
|
||||
let dock_id = Self::save_pane(conn, workspace.id, &workspace.dock_pane, None, true)
|
||||
.context("save pane in save workspace")?;
|
||||
|
||||
// Complete workspace initialization
|
||||
conn.exec_bound(sql!(
|
||||
UPDATE workspaces
|
||||
SET dock_pane = ?
|
||||
WHERE workspace_id = ?
|
||||
))?((dock_id, workspace.id))
|
||||
.context("Finishing initialization with dock pane")?;
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.log_err();
|
||||
|
@ -402,32 +375,17 @@ impl WorkspaceDb {
|
|||
Ok(())
|
||||
}
|
||||
SerializedPaneGroup::Pane(pane) => {
|
||||
Self::save_pane(conn, workspace_id, &pane, parent, false)?;
|
||||
Self::save_pane(conn, workspace_id, &pane, parent)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_dock_pane(&self, workspace_id: WorkspaceId) -> Result<SerializedPane> {
|
||||
let (pane_id, active) = self.select_row_bound(sql!(
|
||||
SELECT pane_id, active
|
||||
FROM panes
|
||||
WHERE pane_id = (SELECT dock_pane FROM workspaces WHERE workspace_id = ?)
|
||||
))?(workspace_id)?
|
||||
.context("No dock pane for workspace")?;
|
||||
|
||||
Ok(SerializedPane::new(
|
||||
self.get_items(pane_id).context("Reading items")?,
|
||||
active,
|
||||
))
|
||||
}
|
||||
|
||||
fn save_pane(
|
||||
conn: &Connection,
|
||||
workspace_id: WorkspaceId,
|
||||
pane: &SerializedPane,
|
||||
parent: Option<(GroupId, usize)>, // None indicates BOTH dock pane AND center_pane
|
||||
dock: bool,
|
||||
parent: Option<(GroupId, usize)>,
|
||||
) -> Result<PaneId> {
|
||||
let pane_id = conn.select_row_bound::<_, i64>(sql!(
|
||||
INSERT INTO panes(workspace_id, active)
|
||||
|
@ -436,13 +394,11 @@ impl WorkspaceDb {
|
|||
))?((workspace_id, pane.active))?
|
||||
.ok_or_else(|| anyhow!("Could not retrieve inserted pane_id"))?;
|
||||
|
||||
if !dock {
|
||||
let (parent_id, order) = unzip_option(parent);
|
||||
conn.exec_bound(sql!(
|
||||
INSERT INTO center_panes(pane_id, parent_group_id, position)
|
||||
VALUES (?, ?, ?)
|
||||
))?((pane_id, parent_id, order))?;
|
||||
}
|
||||
let (parent_id, order) = unzip_option(parent);
|
||||
conn.exec_bound(sql!(
|
||||
INSERT INTO center_panes(pane_id, parent_group_id, position)
|
||||
VALUES (?, ?, ?)
|
||||
))?((pane_id, parent_id, order))?;
|
||||
|
||||
Self::save_items(conn, workspace_id, pane_id, &pane.children).context("Saving items")?;
|
||||
|
||||
|
@ -498,10 +454,8 @@ impl WorkspaceDb {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use db::open_test_db;
|
||||
use settings::DockAnchor;
|
||||
|
||||
use super::*;
|
||||
|
||||
|
@ -578,20 +532,16 @@ mod tests {
|
|||
let mut workspace_1 = SerializedWorkspace {
|
||||
id: 1,
|
||||
location: (["/tmp", "/tmp2"]).into(),
|
||||
dock_position: crate::dock::DockPosition::Shown(DockAnchor::Bottom),
|
||||
center_group: Default::default(),
|
||||
dock_pane: Default::default(),
|
||||
left_sidebar_open: true,
|
||||
bounds: Default::default(),
|
||||
display: Default::default(),
|
||||
};
|
||||
|
||||
let mut workspace_2 = SerializedWorkspace {
|
||||
let mut _workspace_2 = SerializedWorkspace {
|
||||
id: 2,
|
||||
location: (["/tmp"]).into(),
|
||||
dock_position: crate::dock::DockPosition::Hidden(DockAnchor::Expanded),
|
||||
center_group: Default::default(),
|
||||
dock_pane: Default::default(),
|
||||
left_sidebar_open: false,
|
||||
bounds: Default::default(),
|
||||
display: Default::default(),
|
||||
|
@ -606,7 +556,7 @@ mod tests {
|
|||
})
|
||||
.await;
|
||||
|
||||
db.save_workspace(workspace_2.clone()).await;
|
||||
db.save_workspace(_workspace_2.clone()).await;
|
||||
|
||||
db.write(|conn| {
|
||||
conn.exec_bound(sql!(INSERT INTO test_table(text, workspace_id) VALUES (?, ?)))
|
||||
|
@ -619,26 +569,27 @@ mod tests {
|
|||
db.save_workspace(workspace_1.clone()).await;
|
||||
db.save_workspace(workspace_1).await;
|
||||
|
||||
workspace_2.dock_pane.children.push(SerializedItem {
|
||||
kind: Arc::from("Test"),
|
||||
item_id: 10,
|
||||
active: true,
|
||||
});
|
||||
db.save_workspace(workspace_2).await;
|
||||
todo!();
|
||||
// workspace_2.dock_pane.children.push(SerializedItem {
|
||||
// kind: Arc::from("Test"),
|
||||
// item_id: 10,
|
||||
// active: true,
|
||||
// });
|
||||
// db.save_workspace(workspace_2).await;
|
||||
|
||||
let test_text_2 = db
|
||||
.select_row_bound::<_, String>(sql!(SELECT text FROM test_table WHERE workspace_id = ?))
|
||||
.unwrap()(2)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert_eq!(test_text_2, "test-text-2");
|
||||
// let test_text_2 = db
|
||||
// .select_row_bound::<_, String>(sql!(SELECT text FROM test_table WHERE workspace_id = ?))
|
||||
// .unwrap()(2)
|
||||
// .unwrap()
|
||||
// .unwrap();
|
||||
// assert_eq!(test_text_2, "test-text-2");
|
||||
|
||||
let test_text_1 = db
|
||||
.select_row_bound::<_, String>(sql!(SELECT text FROM test_table WHERE workspace_id = ?))
|
||||
.unwrap()(1)
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
assert_eq!(test_text_1, "test-text-1");
|
||||
// let test_text_1 = db
|
||||
// .select_row_bound::<_, String>(sql!(SELECT text FROM test_table WHERE workspace_id = ?))
|
||||
// .unwrap()(1)
|
||||
// .unwrap()
|
||||
// .unwrap();
|
||||
// assert_eq!(test_text_1, "test-text-1");
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
@ -647,16 +598,6 @@ mod tests {
|
|||
|
||||
let db = WorkspaceDb(open_test_db("test_full_workspace_serialization").await);
|
||||
|
||||
let dock_pane = crate::persistence::model::SerializedPane {
|
||||
children: vec![
|
||||
SerializedItem::new("Terminal", 1, false),
|
||||
SerializedItem::new("Terminal", 2, false),
|
||||
SerializedItem::new("Terminal", 3, true),
|
||||
SerializedItem::new("Terminal", 4, false),
|
||||
],
|
||||
active: false,
|
||||
};
|
||||
|
||||
// -----------------
|
||||
// | 1,2 | 5,6 |
|
||||
// | - - - | |
|
||||
|
@ -697,9 +638,7 @@ mod tests {
|
|||
let workspace = SerializedWorkspace {
|
||||
id: 5,
|
||||
location: (["/tmp", "/tmp2"]).into(),
|
||||
dock_position: DockPosition::Shown(DockAnchor::Bottom),
|
||||
center_group,
|
||||
dock_pane,
|
||||
left_sidebar_open: true,
|
||||
bounds: Default::default(),
|
||||
display: Default::default(),
|
||||
|
@ -727,9 +666,7 @@ mod tests {
|
|||
let workspace_1 = SerializedWorkspace {
|
||||
id: 1,
|
||||
location: (["/tmp", "/tmp2"]).into(),
|
||||
dock_position: crate::dock::DockPosition::Shown(DockAnchor::Bottom),
|
||||
center_group: Default::default(),
|
||||
dock_pane: Default::default(),
|
||||
left_sidebar_open: true,
|
||||
bounds: Default::default(),
|
||||
display: Default::default(),
|
||||
|
@ -738,9 +675,7 @@ mod tests {
|
|||
let mut workspace_2 = SerializedWorkspace {
|
||||
id: 2,
|
||||
location: (["/tmp"]).into(),
|
||||
dock_position: crate::dock::DockPosition::Hidden(DockAnchor::Expanded),
|
||||
center_group: Default::default(),
|
||||
dock_pane: Default::default(),
|
||||
left_sidebar_open: false,
|
||||
bounds: Default::default(),
|
||||
display: Default::default(),
|
||||
|
@ -776,9 +711,7 @@ mod tests {
|
|||
let mut workspace_3 = SerializedWorkspace {
|
||||
id: 3,
|
||||
location: (&["/tmp", "/tmp2"]).into(),
|
||||
dock_position: DockPosition::Shown(DockAnchor::Right),
|
||||
center_group: Default::default(),
|
||||
dock_pane: Default::default(),
|
||||
left_sidebar_open: false,
|
||||
bounds: Default::default(),
|
||||
display: Default::default(),
|
||||
|
@ -801,52 +734,23 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
use crate::dock::DockPosition;
|
||||
use crate::persistence::model::SerializedWorkspace;
|
||||
use crate::persistence::model::{SerializedItem, SerializedPane, SerializedPaneGroup};
|
||||
|
||||
fn default_workspace<P: AsRef<Path>>(
|
||||
workspace_id: &[P],
|
||||
dock_pane: SerializedPane,
|
||||
center_group: &SerializedPaneGroup,
|
||||
) -> SerializedWorkspace {
|
||||
SerializedWorkspace {
|
||||
id: 4,
|
||||
location: workspace_id.into(),
|
||||
dock_position: crate::dock::DockPosition::Hidden(DockAnchor::Right),
|
||||
center_group: center_group.clone(),
|
||||
dock_pane,
|
||||
left_sidebar_open: true,
|
||||
bounds: Default::default(),
|
||||
display: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_basic_dock_pane() {
|
||||
env_logger::try_init().ok();
|
||||
|
||||
let db = WorkspaceDb(open_test_db("basic_dock_pane").await);
|
||||
|
||||
let dock_pane = crate::persistence::model::SerializedPane::new(
|
||||
vec![
|
||||
SerializedItem::new("Terminal", 1, false),
|
||||
SerializedItem::new("Terminal", 4, false),
|
||||
SerializedItem::new("Terminal", 2, false),
|
||||
SerializedItem::new("Terminal", 3, true),
|
||||
],
|
||||
false,
|
||||
);
|
||||
|
||||
let workspace = default_workspace(&["/tmp"], dock_pane, &Default::default());
|
||||
|
||||
db.save_workspace(workspace.clone()).await;
|
||||
|
||||
let new_workspace = db.workspace_for_roots(&["/tmp"]).unwrap();
|
||||
|
||||
assert_eq!(workspace.dock_pane, new_workspace.dock_pane);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_simple_split() {
|
||||
env_logger::try_init().ok();
|
||||
|
@ -890,7 +794,7 @@ mod tests {
|
|||
],
|
||||
};
|
||||
|
||||
let workspace = default_workspace(&["/tmp"], Default::default(), ¢er_pane);
|
||||
let workspace = default_workspace(&["/tmp"], ¢er_pane);
|
||||
|
||||
db.save_workspace(workspace.clone()).await;
|
||||
|
||||
|
@ -939,7 +843,7 @@ mod tests {
|
|||
|
||||
let id = &["/tmp"];
|
||||
|
||||
let mut workspace = default_workspace(id, Default::default(), ¢er_pane);
|
||||
let mut workspace = default_workspace(id, ¢er_pane);
|
||||
|
||||
db.save_workspace(workspace.clone()).await;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
dock::DockPosition, ItemDeserializers, Member, Pane, PaneAxis, Workspace, WorkspaceId,
|
||||
ItemDeserializers, Member, Pane, PaneAxis, Workspace, WorkspaceId,
|
||||
};
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use async_recursion::async_recursion;
|
||||
|
@ -11,7 +11,6 @@ use gpui::{
|
|||
platform::WindowBounds, AsyncAppContext, Axis, ModelHandle, Task, ViewHandle, WeakViewHandle,
|
||||
};
|
||||
use project::Project;
|
||||
use settings::DockAnchor;
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
|
@ -62,9 +61,7 @@ impl Column for WorkspaceLocation {
|
|||
pub struct SerializedWorkspace {
|
||||
pub id: WorkspaceId,
|
||||
pub location: WorkspaceLocation,
|
||||
pub dock_position: DockPosition,
|
||||
pub center_group: SerializedPaneGroup,
|
||||
pub dock_pane: SerializedPane,
|
||||
pub left_sidebar_open: bool,
|
||||
pub bounds: Option<WindowBounds>,
|
||||
pub display: Option<Uuid>,
|
||||
|
@ -278,64 +275,39 @@ impl Column for SerializedItem {
|
|||
}
|
||||
}
|
||||
|
||||
impl StaticColumnCount for DockPosition {
|
||||
fn column_count() -> usize {
|
||||
2
|
||||
}
|
||||
}
|
||||
impl Bind for DockPosition {
|
||||
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
|
||||
let next_index = statement.bind(self.is_visible(), start_index)?;
|
||||
statement.bind(self.anchor(), next_index)
|
||||
}
|
||||
}
|
||||
|
||||
impl Column for DockPosition {
|
||||
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
|
||||
let (visible, next_index) = bool::column(statement, start_index)?;
|
||||
let (dock_anchor, next_index) = DockAnchor::column(statement, next_index)?;
|
||||
let position = if visible {
|
||||
DockPosition::Shown(dock_anchor)
|
||||
} else {
|
||||
DockPosition::Hidden(dock_anchor)
|
||||
};
|
||||
Ok((position, next_index))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use db::sqlez::connection::Connection;
|
||||
use settings::DockAnchor;
|
||||
|
||||
use super::WorkspaceLocation;
|
||||
// use super::WorkspaceLocation;
|
||||
|
||||
#[test]
|
||||
fn test_workspace_round_trips() {
|
||||
let db = Connection::open_memory(Some("workspace_id_round_trips"));
|
||||
let _db = Connection::open_memory(Some("workspace_id_round_trips"));
|
||||
|
||||
db.exec(indoc::indoc! {"
|
||||
CREATE TABLE workspace_id_test(
|
||||
workspace_id INTEGER,
|
||||
dock_anchor TEXT
|
||||
);"})
|
||||
.unwrap()()
|
||||
.unwrap();
|
||||
todo!();
|
||||
// db.exec(indoc::indoc! {"
|
||||
// CREATE TABLE workspace_id_test(
|
||||
// workspace_id INTEGER,
|
||||
// dock_anchor TEXT
|
||||
// );"})
|
||||
// .unwrap()()
|
||||
// .unwrap();
|
||||
|
||||
let workspace_id: WorkspaceLocation = WorkspaceLocation::from(&["\test2", "\test1"]);
|
||||
// let workspace_id: WorkspaceLocation = WorkspaceLocation::from(&["\test2", "\test1"]);
|
||||
|
||||
db.exec_bound("INSERT INTO workspace_id_test(workspace_id, dock_anchor) VALUES (?,?)")
|
||||
.unwrap()((&workspace_id, DockAnchor::Bottom))
|
||||
.unwrap();
|
||||
// db.exec_bound("INSERT INTO workspace_id_test(workspace_id, dock_anchor) VALUES (?,?)")
|
||||
// .unwrap()((&workspace_id, DockAnchor::Bottom))
|
||||
// .unwrap();
|
||||
|
||||
assert_eq!(
|
||||
db.select_row("SELECT workspace_id, dock_anchor FROM workspace_id_test LIMIT 1")
|
||||
.unwrap()()
|
||||
.unwrap(),
|
||||
Some((
|
||||
WorkspaceLocation::from(&["\test1", "\test2"]),
|
||||
DockAnchor::Bottom
|
||||
))
|
||||
);
|
||||
// assert_eq!(
|
||||
// db.select_row("SELECT workspace_id, dock_anchor FROM workspace_id_test LIMIT 1")
|
||||
// .unwrap()()
|
||||
// .unwrap(),
|
||||
// Some((
|
||||
// WorkspaceLocation::from(&["\test1", "\test2"]),
|
||||
// DockAnchor::Bottom
|
||||
// ))
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
///
|
||||
/// This may cause issues when you're trying to write tests that use workspace focus to add items at
|
||||
/// specific locations.
|
||||
pub mod dock;
|
||||
pub mod item;
|
||||
pub mod notifications;
|
||||
pub mod pane;
|
||||
|
@ -22,7 +21,6 @@ use client::{
|
|||
Client, TypedEnvelope, UserStore,
|
||||
};
|
||||
use collections::{hash_map, HashMap, HashSet};
|
||||
use dock::{Dock, DockDefaultItemFactory, ToggleDockButton};
|
||||
use drag_and_drop::DragAndDrop;
|
||||
use futures::{
|
||||
channel::{mpsc, oneshot},
|
||||
|
@ -63,7 +61,6 @@ use crate::{
|
|||
persistence::model::{SerializedPane, SerializedPaneGroup, SerializedWorkspace},
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use log::warn;
|
||||
use notifications::{NotificationHandle, NotifyResultExt};
|
||||
pub use pane::*;
|
||||
pub use pane_group::*;
|
||||
|
@ -75,7 +72,7 @@ pub use persistence::{
|
|||
use postage::prelude::Stream;
|
||||
use project::{Project, ProjectEntryId, ProjectPath, Worktree, WorktreeId};
|
||||
use serde::Deserialize;
|
||||
use settings::{Autosave, DockAnchor, Settings};
|
||||
use settings::{Autosave, Settings};
|
||||
use shared_screen::SharedScreen;
|
||||
use sidebar::{Sidebar, SidebarButtons, SidebarSide, ToggleSidebarItem};
|
||||
use status_bar::StatusBar;
|
||||
|
@ -185,7 +182,6 @@ impl_actions!(workspace, [ActivatePane]);
|
|||
|
||||
pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
|
||||
pane::init(cx);
|
||||
dock::init(cx);
|
||||
notifications::init(cx);
|
||||
|
||||
cx.add_global_action({
|
||||
|
@ -362,7 +358,6 @@ pub struct AppState {
|
|||
pub build_window_options:
|
||||
fn(Option<WindowBounds>, Option<uuid::Uuid>, &dyn Platform) -> WindowOptions<'static>,
|
||||
pub initialize_workspace: fn(&mut Workspace, &Arc<AppState>, &mut ViewContext<Workspace>),
|
||||
pub dock_default_item_factory: DockDefaultItemFactory,
|
||||
pub background_actions: BackgroundActions,
|
||||
}
|
||||
|
||||
|
@ -386,7 +381,6 @@ impl AppState {
|
|||
user_store,
|
||||
initialize_workspace: |_, _, _| {},
|
||||
build_window_options: |_, _, _| Default::default(),
|
||||
dock_default_item_factory: |_, _| None,
|
||||
background_actions: || &[],
|
||||
})
|
||||
}
|
||||
|
@ -439,7 +433,6 @@ impl DelayedDebouncedEditAction {
|
|||
}
|
||||
|
||||
pub enum Event {
|
||||
DockAnchorChanged,
|
||||
PaneAdded(ViewHandle<Pane>),
|
||||
ContactRequestedJoin(u64),
|
||||
}
|
||||
|
@ -457,7 +450,6 @@ pub struct Workspace {
|
|||
last_active_center_pane: Option<WeakViewHandle<Pane>>,
|
||||
status_bar: ViewHandle<StatusBar>,
|
||||
titlebar_item: Option<AnyViewHandle>,
|
||||
dock: Dock,
|
||||
notifications: Vec<(TypeId, usize, Box<dyn NotificationHandle>)>,
|
||||
project: ModelHandle<Project>,
|
||||
leader_state: LeaderState,
|
||||
|
@ -535,16 +527,10 @@ impl Workspace {
|
|||
let weak_handle = cx.weak_handle();
|
||||
|
||||
let center_pane = cx
|
||||
.add_view(|cx| Pane::new(weak_handle.clone(), None, app_state.background_actions, cx));
|
||||
.add_view(|cx| Pane::new(weak_handle.clone(), app_state.background_actions, cx));
|
||||
cx.subscribe(¢er_pane, Self::handle_pane_event).detach();
|
||||
cx.focus(¢er_pane);
|
||||
cx.emit(Event::PaneAdded(center_pane.clone()));
|
||||
let dock = Dock::new(
|
||||
app_state.dock_default_item_factory,
|
||||
app_state.background_actions,
|
||||
cx,
|
||||
);
|
||||
let dock_pane = dock.pane().clone();
|
||||
|
||||
let mut current_user = app_state.user_store.read(cx).watch_current_user();
|
||||
let mut connection_status = app_state.client.status();
|
||||
|
@ -559,7 +545,6 @@ impl Workspace {
|
|||
}
|
||||
anyhow::Ok(())
|
||||
});
|
||||
let handle = cx.handle();
|
||||
|
||||
// All leader updates are enqueued and then processed in a single task, so
|
||||
// that each asynchronous operation can be run in order.
|
||||
|
@ -581,14 +566,12 @@ impl Workspace {
|
|||
let right_sidebar = cx.add_view(|_| Sidebar::new(SidebarSide::Right));
|
||||
let left_sidebar_buttons =
|
||||
cx.add_view(|cx| SidebarButtons::new(left_sidebar.clone(), weak_handle.clone(), cx));
|
||||
let toggle_dock = cx.add_view(|cx| ToggleDockButton::new(handle, cx));
|
||||
let right_sidebar_buttons =
|
||||
cx.add_view(|cx| SidebarButtons::new(right_sidebar.clone(), weak_handle.clone(), cx));
|
||||
let status_bar = cx.add_view(|cx| {
|
||||
let mut status_bar = StatusBar::new(¢er_pane.clone(), cx);
|
||||
status_bar.add_left_item(left_sidebar_buttons, cx);
|
||||
status_bar.add_right_item(right_sidebar_buttons, cx);
|
||||
status_bar.add_right_item(toggle_dock, cx);
|
||||
status_bar
|
||||
});
|
||||
|
||||
|
@ -630,11 +613,7 @@ impl Workspace {
|
|||
modal: None,
|
||||
weak_self: weak_handle.clone(),
|
||||
center: PaneGroup::new(center_pane.clone()),
|
||||
dock,
|
||||
// When removing an item, the last element remaining in this array
|
||||
// is used to find where focus should fallback to. As such, the order
|
||||
// of these two variables is important.
|
||||
panes: vec![dock_pane.clone(), center_pane.clone()],
|
||||
panes: vec![center_pane.clone()],
|
||||
panes_by_item: Default::default(),
|
||||
active_pane: center_pane.clone(),
|
||||
last_active_center_pane: Some(center_pane.downgrade()),
|
||||
|
@ -664,10 +643,6 @@ impl Workspace {
|
|||
cx.defer(move |_, cx| {
|
||||
Self::load_from_serialized_workspace(weak_handle, serialized_workspace, cx)
|
||||
});
|
||||
} else if project.read(cx).is_local() {
|
||||
if cx.global::<Settings>().default_dock_anchor != DockAnchor::Expanded {
|
||||
Dock::show(&mut this, false, cx);
|
||||
}
|
||||
}
|
||||
|
||||
this
|
||||
|
@ -1336,16 +1311,11 @@ impl Workspace {
|
|||
SidebarSide::Left => &mut self.left_sidebar,
|
||||
SidebarSide::Right => &mut self.right_sidebar,
|
||||
};
|
||||
let open = sidebar.update(cx, |sidebar, cx| {
|
||||
sidebar.update(cx, |sidebar, cx| {
|
||||
let open = !sidebar.is_open();
|
||||
sidebar.set_open(open, cx);
|
||||
open
|
||||
});
|
||||
|
||||
if open {
|
||||
Dock::hide_on_sidebar_shown(self, sidebar_side, cx);
|
||||
}
|
||||
|
||||
self.serialize_workspace(cx);
|
||||
|
||||
cx.focus_self();
|
||||
|
@ -1369,8 +1339,6 @@ impl Workspace {
|
|||
});
|
||||
|
||||
if let Some(active_item) = active_item {
|
||||
Dock::hide_on_sidebar_shown(self, action.sidebar_side, cx);
|
||||
|
||||
if active_item.is_focused(cx) {
|
||||
cx.focus_self();
|
||||
} else {
|
||||
|
@ -1401,8 +1369,6 @@ impl Workspace {
|
|||
sidebar.active_item().cloned()
|
||||
});
|
||||
if let Some(active_item) = active_item {
|
||||
Dock::hide_on_sidebar_shown(self, sidebar_side, cx);
|
||||
|
||||
if active_item.is_focused(cx) {
|
||||
cx.focus_self();
|
||||
} else {
|
||||
|
@ -1424,7 +1390,6 @@ impl Workspace {
|
|||
let pane = cx.add_view(|cx| {
|
||||
Pane::new(
|
||||
self.weak_handle(),
|
||||
None,
|
||||
self.app_state.background_actions,
|
||||
cx,
|
||||
)
|
||||
|
@ -1466,16 +1431,12 @@ impl Workspace {
|
|||
cx: &mut ViewContext<Self>,
|
||||
) -> Task<Result<Box<dyn ItemHandle>, anyhow::Error>> {
|
||||
let pane = pane.unwrap_or_else(|| {
|
||||
if !self.dock_active() {
|
||||
self.active_pane().downgrade()
|
||||
} else {
|
||||
self.last_active_center_pane.clone().unwrap_or_else(|| {
|
||||
self.panes
|
||||
.first()
|
||||
.expect("There must be an active pane")
|
||||
.downgrade()
|
||||
})
|
||||
}
|
||||
self.last_active_center_pane.clone().unwrap_or_else(|| {
|
||||
self.panes
|
||||
.first()
|
||||
.expect("There must be an active pane")
|
||||
.downgrade()
|
||||
})
|
||||
});
|
||||
|
||||
let task = self.load_path(path.into(), cx);
|
||||
|
@ -1599,15 +1560,7 @@ impl Workspace {
|
|||
status_bar.set_active_pane(&self.active_pane, cx);
|
||||
});
|
||||
self.active_item_path_changed(cx);
|
||||
|
||||
if &pane == self.dock_pane() {
|
||||
Dock::show(self, true, cx);
|
||||
} else {
|
||||
self.last_active_center_pane = Some(pane.downgrade());
|
||||
if self.dock.is_anchored_at(DockAnchor::Expanded) {
|
||||
Dock::hide(self, cx);
|
||||
}
|
||||
}
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
|
@ -1630,13 +1583,11 @@ impl Workspace {
|
|||
event: &pane::Event,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
let is_dock = &pane == self.dock.pane();
|
||||
match event {
|
||||
pane::Event::Split(direction) if !is_dock => {
|
||||
pane::Event::Split(direction) => {
|
||||
self.split_pane(pane, *direction, cx);
|
||||
}
|
||||
pane::Event::Remove if !is_dock => self.remove_pane(pane, cx),
|
||||
pane::Event::Remove if is_dock => Dock::hide(self, cx),
|
||||
pane::Event::Remove => self.remove_pane(pane, cx),
|
||||
pane::Event::ActivateItem { local } => {
|
||||
if *local {
|
||||
self.unfollow(&pane, cx);
|
||||
|
@ -1662,7 +1613,6 @@ impl Workspace {
|
|||
pane::Event::Focus => {
|
||||
self.handle_pane_focused(pane.clone(), cx);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.serialize_workspace(cx);
|
||||
|
@ -1674,11 +1624,6 @@ impl Workspace {
|
|||
direction: SplitDirection,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Option<ViewHandle<Pane>> {
|
||||
if &pane == self.dock_pane() {
|
||||
warn!("Can't split dock pane.");
|
||||
return None;
|
||||
}
|
||||
|
||||
let item = pane.read(cx).active_item()?;
|
||||
let maybe_pane_handle = if let Some(clone) = item.clone_on_split(self.database_id(), cx) {
|
||||
let new_pane = self.add_pane(cx);
|
||||
|
@ -1702,10 +1647,6 @@ impl Workspace {
|
|||
) {
|
||||
let Some(pane_to_split) = pane_to_split.upgrade(cx) else { return; };
|
||||
let Some(from) = from.upgrade(cx) else { return; };
|
||||
if &pane_to_split == self.dock_pane() {
|
||||
warn!("Can't split dock pane.");
|
||||
return;
|
||||
}
|
||||
|
||||
let new_pane = self.add_pane(cx);
|
||||
Pane::move_item(self, from.clone(), new_pane.clone(), item_id_to_move, 0, cx);
|
||||
|
@ -1723,11 +1664,6 @@ impl Workspace {
|
|||
cx: &mut ViewContext<Self>,
|
||||
) -> Option<Task<Result<()>>> {
|
||||
let pane_to_split = pane_to_split.upgrade(cx)?;
|
||||
if &pane_to_split == self.dock_pane() {
|
||||
warn!("Can't split dock pane.");
|
||||
return None;
|
||||
}
|
||||
|
||||
let new_pane = self.add_pane(cx);
|
||||
self.center
|
||||
.split(&pane_to_split, &new_pane, split_direction)
|
||||
|
@ -1764,14 +1700,6 @@ impl Workspace {
|
|||
&self.active_pane
|
||||
}
|
||||
|
||||
pub fn dock_pane(&self) -> &ViewHandle<Pane> {
|
||||
self.dock.pane()
|
||||
}
|
||||
|
||||
fn dock_active(&self) -> bool {
|
||||
&self.active_pane == self.dock.pane()
|
||||
}
|
||||
|
||||
fn project_remote_id_changed(&mut self, remote_id: Option<u64>, cx: &mut ViewContext<Self>) {
|
||||
if let Some(remote_id) = remote_id {
|
||||
self.remote_entity_subscription = Some(
|
||||
|
@ -2518,14 +2446,11 @@ impl Workspace {
|
|||
// - with_local_workspace() relies on this to not have other stuff open
|
||||
// when you open your log
|
||||
if !location.paths().is_empty() {
|
||||
let dock_pane = serialize_pane_handle(self.dock.pane(), cx);
|
||||
let center_group = build_serialized_pane_group(&self.center.root, cx);
|
||||
|
||||
let serialized_workspace = SerializedWorkspace {
|
||||
id: self.database_id,
|
||||
location,
|
||||
dock_position: self.dock.position(),
|
||||
dock_pane,
|
||||
center_group,
|
||||
left_sidebar_open: self.left_sidebar.read(cx).is_open(),
|
||||
bounds: Default::default(),
|
||||
|
@ -2545,26 +2470,14 @@ impl Workspace {
|
|||
cx: &mut AppContext,
|
||||
) {
|
||||
cx.spawn(|mut cx| async move {
|
||||
let (project, dock_pane_handle, old_center_pane) =
|
||||
let (project, old_center_pane) =
|
||||
workspace.read_with(&cx, |workspace, _| {
|
||||
(
|
||||
workspace.project().clone(),
|
||||
workspace.dock_pane().downgrade(),
|
||||
workspace.last_active_center_pane.clone(),
|
||||
)
|
||||
})?;
|
||||
|
||||
serialized_workspace
|
||||
.dock_pane
|
||||
.deserialize_to(
|
||||
&project,
|
||||
&dock_pane_handle,
|
||||
serialized_workspace.id,
|
||||
&workspace,
|
||||
&mut cx,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Traverse the splits tree and add to things
|
||||
let center_group = serialized_workspace
|
||||
.center_group
|
||||
|
@ -2602,18 +2515,6 @@ impl Workspace {
|
|||
workspace.toggle_sidebar(SidebarSide::Left, cx);
|
||||
}
|
||||
|
||||
// Note that without after_window, the focus_self() and
|
||||
// the focus the dock generates start generating alternating
|
||||
// focus due to the deferred execution each triggering each other
|
||||
cx.after_window_update(move |workspace, cx| {
|
||||
Dock::set_dock_position(
|
||||
workspace,
|
||||
serialized_workspace.dock_position,
|
||||
true,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
|
||||
cx.notify();
|
||||
})?;
|
||||
|
||||
|
@ -2634,7 +2535,6 @@ impl Workspace {
|
|||
fs: project.read(cx).fs().clone(),
|
||||
build_window_options: |_, _, _| Default::default(),
|
||||
initialize_workspace: |_, _, _| {},
|
||||
dock_default_item_factory: |_, _| None,
|
||||
background_actions: || &[],
|
||||
});
|
||||
Self::new(None, 0, project, app_state, cx)
|
||||
|
@ -2729,15 +2629,9 @@ impl View for Workspace {
|
|||
))
|
||||
.flex(1., true),
|
||||
)
|
||||
.with_children(self.dock.render(
|
||||
&theme,
|
||||
DockAnchor::Bottom,
|
||||
cx,
|
||||
)),
|
||||
)
|
||||
.flex(1., true),
|
||||
)
|
||||
.with_children(self.dock.render(&theme, DockAnchor::Right, cx))
|
||||
.with_children(
|
||||
if self.right_sidebar.read(cx).active_item().is_some() {
|
||||
Some(
|
||||
|
@ -2760,11 +2654,6 @@ impl View for Workspace {
|
|||
})
|
||||
.with_child(Overlay::new(
|
||||
Stack::new()
|
||||
.with_children(self.dock.render(
|
||||
&theme,
|
||||
DockAnchor::Expanded,
|
||||
cx,
|
||||
))
|
||||
.with_children(self.modal.as_ref().map(|modal| {
|
||||
ChildView::new(modal, cx)
|
||||
.contained()
|
||||
|
|
|
@ -52,7 +52,7 @@ use staff_mode::StaffMode;
|
|||
use theme::ThemeRegistry;
|
||||
use util::{channel::RELEASE_CHANNEL, paths, ResultExt, TryFutureExt};
|
||||
use workspace::{
|
||||
dock::FocusDock, item::ItemHandle, notifications::NotifyResultExt, AppState, OpenSettings,
|
||||
item::ItemHandle, notifications::NotifyResultExt, AppState, OpenSettings,
|
||||
Workspace,
|
||||
};
|
||||
use zed::{self, build_window_options, initialize_workspace, languages, menus};
|
||||
|
@ -205,7 +205,6 @@ fn main() {
|
|||
fs,
|
||||
build_window_options,
|
||||
initialize_workspace,
|
||||
dock_default_item_factory,
|
||||
background_actions,
|
||||
});
|
||||
cx.set_global(Arc::downgrade(&app_state));
|
||||
|
@ -776,7 +775,6 @@ pub fn background_actions() -> &'static [(&'static str, &'static dyn Action)] {
|
|||
&[
|
||||
("Go to file", &file_finder::Toggle),
|
||||
("Open command palette", &command_palette::Toggle),
|
||||
("Focus the dock", &FocusDock),
|
||||
("Open recent projects", &recent_projects::OpenRecent),
|
||||
("Change your settings", &OpenSettings),
|
||||
]
|
||||
|
|
|
@ -306,7 +306,6 @@ pub fn initialize_workspace(
|
|||
.detach();
|
||||
|
||||
cx.emit(workspace::Event::PaneAdded(workspace.active_pane().clone()));
|
||||
cx.emit(workspace::Event::PaneAdded(workspace.dock_pane().clone()));
|
||||
|
||||
let collab_titlebar_item =
|
||||
cx.add_view(|cx| CollabTitlebarItem::new(workspace, &workspace_handle, cx));
|
||||
|
|
Loading…
Reference in a new issue