Tabs n splits (#3340)

Adds back:

- [x] Tab clicking
- [x] Splits ~
- [x] Workspace deserialization

Also adds a new `FocusableView` API to GPUI

Release Notes:

- N/A
This commit is contained in:
Mikayla Maki 2023-11-15 23:52:43 -08:00 committed by GitHub
commit c8f83e2d4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 455 additions and 510 deletions

View File

@ -204,6 +204,9 @@ core-graphics = { git = "https://github.com/servo/core-foundation-rs", rev = "07
[profile.dev]
split-debuginfo = "unpacked"
[profile.dev.package.taffy]
opt-level = 3
[profile.release]
debug = true
lto = "thin"

View File

@ -220,7 +220,6 @@ impl TestServer {
languages: Arc::new(language_registry),
fs: fs.clone(),
build_window_options: |_, _, _| Default::default(),
initialize_workspace: |_, _, _, _| gpui::Task::ready(Ok(())),
node_runtime: FakeNodeRuntime::new(),
});

View File

@ -153,17 +153,20 @@ actions!(
// channel_id: ChannelId,
// }
// const COLLABORATION_PANEL_KEY: &'static str = "CollaborationPanel";
const COLLABORATION_PANEL_KEY: &'static str = "CollaborationPanel";
use std::sync::Arc;
use db::kvp::KEY_VALUE_STORE;
use gpui::{
actions, div, AppContext, AsyncWindowContext, Div, EventEmitter, FocusHandle, Focusable,
InteractiveComponent, ParentComponent, Render, Task, View, ViewContext, VisualContext,
WeakView,
actions, div, serde_json, AppContext, AsyncWindowContext, Div, EventEmitter, FocusHandle,
Focusable, FocusableView, InteractiveComponent, ParentComponent, Render, View, ViewContext,
VisualContext, WeakView,
};
use project::Fs;
use serde_derive::{Deserialize, Serialize};
use settings::Settings;
use util::ResultExt;
use workspace::{
dock::{DockPosition, Panel, PanelEvent},
Workspace,
@ -317,11 +320,11 @@ pub struct CollabPanel {
// Channel(ChannelId),
// }
// #[derive(Serialize, Deserialize)]
// struct SerializedCollabPanel {
// width: Option<f32>,
// collapsed_channels: Option<Vec<ChannelId>>,
// }
#[derive(Serialize, Deserialize)]
struct SerializedCollabPanel {
width: Option<f32>,
collapsed_channels: Option<Vec<u64>>,
}
// #[derive(Debug)]
// pub enum Event {
@ -660,43 +663,34 @@ impl CollabPanel {
})
}
pub fn load(
pub async fn load(
workspace: WeakView<Workspace>,
cx: AsyncWindowContext,
) -> Task<anyhow::Result<View<Self>>> {
cx.spawn(|mut cx| async move {
// todo!()
// let serialized_panel = if let Some(panel) = cx
// .background()
// .spawn(async move { KEY_VALUE_STORE.read_kvp(COLLABORATION_PANEL_KEY) })
// .await
// .log_err()
// .flatten()
// {
// match serde_json::from_str::<SerializedCollabPanel>(&panel) {
// Ok(panel) => Some(panel),
// Err(err) => {
// log::error!("Failed to deserialize collaboration panel: {}", err);
// None
// }
// }
// } else {
// None
// };
mut cx: AsyncWindowContext,
) -> anyhow::Result<View<Self>> {
let serialized_panel = cx
.background_executor()
.spawn(async move { KEY_VALUE_STORE.read_kvp(COLLABORATION_PANEL_KEY) })
.await
.map_err(|_| anyhow::anyhow!("Failed to read collaboration panel from key value store"))
.log_err()
.flatten()
.map(|panel| serde_json::from_str::<SerializedCollabPanel>(&panel))
.transpose()
.log_err()
.flatten();
workspace.update(&mut cx, |workspace, cx| {
let panel = CollabPanel::new(workspace, cx);
// if let Some(serialized_panel) = serialized_panel {
// panel.update(cx, |panel, cx| {
// panel.width = serialized_panel.width;
// panel.collapsed_channels = serialized_panel
// .collapsed_channels
// .unwrap_or_else(|| Vec::new());
// cx.notify();
// });
// }
panel
})
workspace.update(&mut cx, |workspace, cx| {
let panel = CollabPanel::new(workspace, cx);
if let Some(serialized_panel) = serialized_panel {
panel.update(cx, |panel, cx| {
panel.width = serialized_panel.width;
// panel.collapsed_channels = serialized_panel
// .collapsed_channels
// .unwrap_or_else(|| Vec::new());
cx.notify();
});
}
panel
})
}
@ -3454,11 +3448,13 @@ impl Panel for CollabPanel {
self.focus_handle.contains_focused(cx)
}
fn persistent_name(&self) -> &'static str {
"Collaboration Panel"
fn persistent_name() -> &'static str {
"CollabPanel"
}
}
fn focus_handle(&self, _cx: &ui::prelude::WindowContext) -> gpui::FocusHandle {
impl FocusableView for CollabPanel {
fn focus_handle(&self, _cx: &AppContext) -> gpui::FocusHandle {
self.focus_handle.clone()
}
}

View File

@ -41,8 +41,8 @@ use git::diff_hunk_to_display;
use gpui::{
action, actions, div, point, prelude::*, px, relative, rems, size, uniform_list, AnyElement,
AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Component, Context,
EventEmitter, FocusHandle, FontFeatures, FontStyle, FontWeight, HighlightStyle, Hsla,
InputHandler, KeyContext, Model, MouseButton, ParentComponent, Pixels, Render, Styled,
EventEmitter, FocusHandle, FocusableView, FontFeatures, FontStyle, FontWeight, HighlightStyle,
Hsla, InputHandler, KeyContext, Model, MouseButton, ParentComponent, Pixels, Render, Styled,
Subscription, Task, TextStyle, UniformListScrollHandle, View, ViewContext, VisualContext,
WeakView, WindowContext,
};
@ -9367,6 +9367,12 @@ pub struct EditorReleased(pub WeakView<Editor>);
//
impl EventEmitter<Event> for Editor {}
impl FocusableView for Editor {
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
self.focus_handle.clone()
}
}
impl Render for Editor {
type Element = EditorElement;

View File

@ -527,10 +527,6 @@ fn deserialize_anchor(buffer: &MultiBufferSnapshot, anchor: proto::EditorAnchor)
}
impl Item for Editor {
fn focus_handle(&self) -> FocusHandle {
self.focus_handle.clone()
}
fn navigate(&mut self, data: Box<dyn std::any::Any>, cx: &mut ViewContext<Self>) -> bool {
todo!();
// if let Ok(data) = data.downcast::<NavigationData>() {

View File

@ -68,7 +68,7 @@ pub trait Action: std::fmt::Debug + 'static {
// Types become actions by satisfying a list of trait bounds.
impl<A> Action for A
where
A: for<'a> Deserialize<'a> + PartialEq + Clone + Default + std::fmt::Debug + 'static,
A: for<'a> Deserialize<'a> + PartialEq + Default + Clone + std::fmt::Debug + 'static,
{
fn qualified_name() -> SharedString {
let name = type_name::<A>();

View File

@ -1,7 +1,7 @@
use crate::{
AnyView, AnyWindowHandle, AppCell, AppContext, BackgroundExecutor, Context, ForegroundExecutor,
Model, ModelContext, Render, Result, Task, View, ViewContext, VisualContext, WindowContext,
WindowHandle,
AnyView, AnyWindowHandle, AppCell, AppContext, BackgroundExecutor, Context, FocusableView,
ForegroundExecutor, Model, ModelContext, Render, Result, Task, View, ViewContext,
VisualContext, WindowContext, WindowHandle,
};
use anyhow::{anyhow, Context as _};
use derive_more::{Deref, DerefMut};
@ -307,4 +307,13 @@ impl VisualContext for AsyncWindowContext {
self.window
.update(self, |_, cx| cx.replace_root_view(build_view))
}
fn focus_view<V>(&mut self, view: &View<V>) -> Self::Result<()>
where
V: FocusableView,
{
self.window.update(self, |_, cx| {
view.read(cx).focus_handle(cx).clone().focus(cx);
})
}
}

View File

@ -68,6 +68,7 @@ impl EntityMap {
}
/// Move an entity to the stack.
#[track_caller]
pub fn lease<'a, T>(&mut self, model: &'a Model<T>) -> Lease<'a, T> {
self.assert_valid_context(model);
let entity = Some(

View File

@ -562,6 +562,14 @@ impl<'a> VisualContext for VisualTestContext<'a> {
.update(self.cx, |_, cx| cx.replace_root_view(build_view))
.unwrap()
}
fn focus_view<V: crate::FocusableView>(&mut self, view: &View<V>) -> Self::Result<()> {
self.window
.update(self.cx, |_, cx| {
view.read(cx).focus_handle(cx).clone().focus(cx)
})
.unwrap()
}
}
impl AnyWindowHandle {

View File

@ -135,6 +135,10 @@ pub trait VisualContext: Context {
) -> Self::Result<View<V>>
where
V: Render;
fn focus_view<V>(&mut self, view: &View<V>) -> Self::Result<()>
where
V: FocusableView;
}
pub trait Entity<T>: Sealed {

View File

@ -1,7 +1,8 @@
use crate::{
private::Sealed, AnyBox, AnyElement, AnyModel, AnyWeakModel, AppContext, AvailableSpace,
BorrowWindow, Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, LayoutId,
Model, Pixels, Point, Size, ViewContext, VisualContext, WeakModel, WindowContext,
BorrowWindow, Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, FocusHandle,
FocusableView, LayoutId, Model, Pixels, Point, Size, ViewContext, VisualContext, WeakModel,
WindowContext,
};
use anyhow::{Context, Result};
use std::{
@ -73,6 +74,13 @@ impl<V: 'static> View<V> {
component: Some(component),
}
}
pub fn focus_handle(&self, cx: &AppContext) -> FocusHandle
where
V: FocusableView,
{
self.read(cx).focus_handle(cx)
}
}
impl<V> Clone for View<V> {

View File

@ -185,6 +185,10 @@ impl Drop for FocusHandle {
}
}
pub trait FocusableView: Render {
fn focus_handle(&self, cx: &AppContext) -> FocusHandle;
}
// Holds the state for a specific window.
pub struct Window {
pub(crate) handle: AnyWindowHandle,
@ -1546,6 +1550,12 @@ impl VisualContext for WindowContext<'_> {
self.window.root_view = Some(view.clone().into());
view
}
fn focus_view<V: crate::FocusableView>(&mut self, view: &View<V>) -> Self::Result<()> {
self.update_view(view, |view, cx| {
view.focus_handle(cx).clone().focus(cx);
})
}
}
impl<'a> std::ops::Deref for WindowContext<'a> {
@ -2219,9 +2229,7 @@ impl<'a, V: 'static> ViewContext<'a, V> {
.set_input_handler(Box::new(input_handler));
}
}
}
impl<V> ViewContext<'_, V> {
pub fn emit<Evt>(&mut self, event: Evt)
where
Evt: 'static,
@ -2234,6 +2242,13 @@ impl<V> ViewContext<'_, V> {
event: Box::new(event),
});
}
pub fn focus_self(&mut self)
where
V: FocusableView,
{
self.defer(|view, cx| view.focus_handle(cx).focus(cx))
}
}
impl<V> Context for ViewContext<'_, V> {
@ -2309,6 +2324,10 @@ impl<V: 'static> VisualContext for ViewContext<'_, V> {
{
self.window_cx.replace_root_view(build_view)
}
fn focus_view<W: FocusableView>(&mut self, view: &View<W>) -> Self::Result<()> {
self.window_cx.focus_view(view)
}
}
impl<'a, V> std::ops::Deref for ViewContext<'a, V> {

View File

@ -9,10 +9,10 @@ use file_associations::FileAssociations;
use anyhow::{anyhow, Result};
use gpui::{
actions, div, px, uniform_list, Action, AppContext, AssetSource, AsyncWindowContext,
ClipboardItem, Component, Div, EventEmitter, FocusHandle, Focusable, InteractiveComponent,
Model, MouseButton, ParentComponent, Pixels, Point, PromptLevel, Render, Stateful,
StatefulInteractiveComponent, Styled, Task, UniformListScrollHandle, View, ViewContext,
VisualContext as _, WeakView, WindowContext,
ClipboardItem, Component, Div, EventEmitter, FocusHandle, Focusable, FocusableView,
InteractiveComponent, Model, MouseButton, ParentComponent, Pixels, Point, PromptLevel, Render,
Stateful, StatefulInteractiveComponent, Styled, Task, UniformListScrollHandle, View,
ViewContext, VisualContext as _, WeakView, WindowContext,
};
use menu::{Confirm, SelectNext, SelectPrev};
use project::{
@ -32,7 +32,7 @@ use std::{
use theme::ActiveTheme as _;
use ui::{h_stack, v_stack, IconElement, Label};
use unicase::UniCase;
use util::{maybe, TryFutureExt};
use util::{maybe, ResultExt, TryFutureExt};
use workspace::{
dock::{DockPosition, PanelEvent},
Workspace,
@ -310,32 +310,31 @@ impl ProjectPanel {
project_panel
}
pub fn load(
pub async fn load(
workspace: WeakView<Workspace>,
cx: AsyncWindowContext,
) -> Task<Result<View<Self>>> {
cx.spawn(|mut cx| async move {
// let serialized_panel = if let Some(panel) = cx
// .background_executor()
// .spawn(async move { KEY_VALUE_STORE.read_kvp(PROJECT_PANEL_KEY) })
// .await
// .log_err()
// .flatten()
// {
// Some(serde_json::from_str::<SerializedProjectPanel>(&panel)?)
// } else {
// None
// };
workspace.update(&mut cx, |workspace, cx| {
let panel = ProjectPanel::new(workspace, cx);
// if let Some(serialized_panel) = serialized_panel {
// panel.update(cx, |panel, cx| {
// panel.width = serialized_panel.width;
// cx.notify();
// });
// }
panel
})
mut cx: AsyncWindowContext,
) -> Result<View<Self>> {
let serialized_panel = cx
.background_executor()
.spawn(async move { KEY_VALUE_STORE.read_kvp(PROJECT_PANEL_KEY) })
.await
.map_err(|e| anyhow!("Failed to load project panel: {}", e))
.log_err()
.flatten()
.map(|panel| serde_json::from_str::<SerializedProjectPanel>(&panel))
.transpose()
.log_err()
.flatten();
workspace.update(&mut cx, |workspace, cx| {
let panel = ProjectPanel::new(workspace, cx);
if let Some(serialized_panel) = serialized_panel {
panel.update(cx, |panel, cx| {
panel.width = serialized_panel.width;
cx.notify();
});
}
panel
})
}
@ -1531,25 +1530,19 @@ impl workspace::dock::Panel for ProjectPanel {
Box::new(ToggleFocus)
}
// fn should_change_position_on_event(event: &Self::Event) -> bool {
// matches!(event, Event::DockPositionChanged)
// }
fn has_focus(&self, _: &WindowContext) -> bool {
self.has_focus
}
fn persistent_name(&self) -> &'static str {
fn persistent_name() -> &'static str {
"Project Panel"
}
}
fn focus_handle(&self, _cx: &WindowContext) -> FocusHandle {
impl FocusableView for ProjectPanel {
fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
self.focus_handle.clone()
}
// fn is_focus_event(event: &Self::Event) -> bool {
// matches!(event, Event::Focus)
// }
}
impl ClipboardEntry {

View File

@ -9,7 +9,7 @@ use schemars::{
};
use serde::Deserialize;
use serde_json::Value;
use util::asset_str;
use util::{asset_str, ResultExt};
#[derive(Debug, Deserialize, Default, Clone, JsonSchema)]
#[serde(transparent)]
@ -86,9 +86,7 @@ impl KeymapFile {
"invalid binding value for keystroke {keystroke}, context {context:?}"
)
})
// todo!()
.ok()
// .log_err()
.log_err()
.map(|action| KeyBinding::load(&keystroke, action, context.as_deref()))
})
.collect::<Result<Vec<_>>>()?;

View File

@ -1,8 +1,8 @@
use crate::{status_bar::StatusItemView, Axis, Workspace};
use gpui::{
div, px, Action, AnyView, AppContext, Component, Div, Entity, EntityId, EventEmitter,
FocusHandle, ParentComponent, Render, Styled, Subscription, View, ViewContext, WeakView,
WindowContext,
FocusHandle, FocusableView, ParentComponent, Render, Styled, Subscription, View, ViewContext,
WeakView, WindowContext,
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
@ -18,8 +18,8 @@ pub enum PanelEvent {
Focus,
}
pub trait Panel: Render + EventEmitter<PanelEvent> {
fn persistent_name(&self) -> &'static str;
pub trait Panel: FocusableView + EventEmitter<PanelEvent> {
fn persistent_name() -> &'static str;
fn position(&self, cx: &WindowContext) -> DockPosition;
fn position_is_valid(&self, position: DockPosition) -> bool;
fn set_position(&mut self, position: DockPosition, cx: &mut ViewContext<Self>);
@ -36,12 +36,11 @@ pub trait Panel: Render + EventEmitter<PanelEvent> {
fn set_zoomed(&mut self, _zoomed: bool, _cx: &mut ViewContext<Self>) {}
fn set_active(&mut self, _active: bool, _cx: &mut ViewContext<Self>) {}
fn has_focus(&self, cx: &WindowContext) -> bool;
fn focus_handle(&self, cx: &WindowContext) -> FocusHandle;
}
pub trait PanelHandle: Send + Sync {
fn id(&self) -> EntityId;
fn persistent_name(&self, cx: &WindowContext) -> &'static str;
fn persistent_name(&self) -> &'static str;
fn position(&self, cx: &WindowContext) -> DockPosition;
fn position_is_valid(&self, position: DockPosition, cx: &WindowContext) -> bool;
fn set_position(&self, position: DockPosition, cx: &mut WindowContext);
@ -54,7 +53,7 @@ pub trait PanelHandle: Send + Sync {
fn toggle_action(&self, cx: &WindowContext) -> Box<dyn Action>;
fn icon_label(&self, cx: &WindowContext) -> Option<String>;
fn has_focus(&self, cx: &WindowContext) -> bool;
fn focus_handle(&self, cx: &WindowContext) -> FocusHandle;
fn focus_handle(&self, cx: &AppContext) -> FocusHandle;
fn to_any(&self) -> AnyView;
}
@ -66,8 +65,8 @@ where
self.entity_id()
}
fn persistent_name(&self, cx: &WindowContext) -> &'static str {
self.read(cx).persistent_name()
fn persistent_name(&self) -> &'static str {
T::persistent_name()
}
fn position(&self, cx: &WindowContext) -> DockPosition {
@ -122,7 +121,7 @@ where
self.clone().into()
}
fn focus_handle(&self, cx: &WindowContext) -> FocusHandle {
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
self.read(cx).focus_handle(cx).clone()
}
}
@ -140,6 +139,14 @@ pub struct Dock {
active_panel_index: usize,
}
impl FocusableView for Dock {
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
self.panel_entries[self.active_panel_index]
.panel
.focus_handle(cx)
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, JsonSchema, PartialEq)]
#[serde(rename_all = "lowercase")]
pub enum DockPosition {
@ -221,12 +228,14 @@ impl Dock {
.position(|entry| entry.panel.to_any().downcast::<T>().is_ok())
}
pub fn panel_index_for_ui_name(&self, _ui_name: &str, _cx: &AppContext) -> Option<usize> {
todo!()
// self.panel_entries.iter().position(|entry| {
// let panel = entry.panel.as_any();
// cx.view_ui_name(panel.window(), panel.id()) == Some(ui_name)
// })
pub fn panel_index_for_persistent_name(
&self,
ui_name: &str,
_cx: &AppContext,
) -> Option<usize> {
self.panel_entries
.iter()
.position(|entry| entry.panel.persistent_name() == ui_name)
}
pub fn active_panel_index(&self) -> usize {
@ -654,11 +663,11 @@ impl Render for PanelButtons {
.enumerate()
.filter_map(|(i, panel)| {
let icon = panel.panel.icon(cx)?;
let name = panel.panel.persistent_name(cx);
let name = panel.panel.persistent_name();
let action = panel.panel.toggle_action(cx);
let action2 = action.boxed_clone();
let mut button = IconButton::new(panel.panel.persistent_name(cx), icon)
let mut button = IconButton::new(panel.panel.persistent_name(), icon)
.when(i == active_index, |el| el.state(InteractionState::Active))
.on_click(move |this, cx| cx.dispatch_action(action.boxed_clone()))
.tooltip(move |_, cx| Tooltip::for_action(name, &*action2, cx));
@ -717,7 +726,7 @@ pub mod test {
}
impl Panel for TestPanel {
fn persistent_name(&self) -> &'static str {
fn persistent_name() -> &'static str {
"TestPanel"
}
@ -765,8 +774,10 @@ pub mod test {
fn has_focus(&self, _cx: &WindowContext) -> bool {
self.has_focus
}
}
fn focus_handle(&self, cx: &WindowContext) -> FocusHandle {
impl FocusableView for TestPanel {
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
unimplemented!()
}
}

View File

@ -12,8 +12,9 @@ use client2::{
Client,
};
use gpui::{
AnyElement, AnyView, AppContext, Entity, EntityId, EventEmitter, FocusHandle, HighlightStyle,
Model, Pixels, Point, Render, SharedString, Task, View, ViewContext, WeakView, WindowContext,
AnyElement, AnyView, AppContext, Entity, EntityId, EventEmitter, FocusHandle, FocusableView,
HighlightStyle, Model, Pixels, Point, SharedString, Task, View, ViewContext, WeakView,
WindowContext,
};
use project2::{Project, ProjectEntryId, ProjectPath};
use schemars::JsonSchema;
@ -91,8 +92,7 @@ pub struct BreadcrumbText {
pub highlights: Option<Vec<(Range<usize>, HighlightStyle)>>,
}
pub trait Item: Render + EventEmitter<ItemEvent> {
fn focus_handle(&self) -> FocusHandle;
pub trait Item: FocusableView + EventEmitter<ItemEvent> {
fn deactivated(&mut self, _: &mut ViewContext<Self>) {}
fn workspace_deactivated(&mut self, _: &mut ViewContext<Self>) {}
fn navigate(&mut self, _: Box<dyn Any>, _: &mut ViewContext<Self>) -> bool {
@ -286,7 +286,7 @@ impl dyn ItemHandle {
impl<T: Item> ItemHandle for View<T> {
fn focus_handle(&self, cx: &WindowContext) -> FocusHandle {
self.read(cx).focus_handle()
self.focus_handle(cx)
}
fn subscribe_to_item_events(

View File

@ -8,8 +8,8 @@ use anyhow::Result;
use collections::{HashMap, HashSet, VecDeque};
use gpui::{
actions, prelude::*, register_action, AppContext, AsyncWindowContext, Component, Div, EntityId,
EventEmitter, FocusHandle, Focusable, Model, PromptLevel, Render, Task, View, ViewContext,
VisualContext, WeakView, WindowContext,
EventEmitter, FocusHandle, Focusable, FocusableView, Model, PromptLevel, Render, Task, View,
ViewContext, VisualContext, WeakView, WindowContext,
};
use parking_lot::Mutex;
use project2::{Project, ProjectEntryId, ProjectPath};
@ -125,10 +125,6 @@ pub fn init(cx: &mut AppContext) {
// cx.add_async_action(Pane::close_items_to_the_left);
// cx.add_async_action(Pane::close_items_to_the_right);
// cx.add_async_action(Pane::close_all_items);
// cx.add_action(|pane: &mut Pane, _: &SplitLeft, cx| pane.split(SplitDirection::Left, cx));
// cx.add_action(|pane: &mut Pane, _: &SplitUp, cx| pane.split(SplitDirection::Up, cx));
// cx.add_action(|pane: &mut Pane, _: &SplitRight, cx| pane.split(SplitDirection::Right, cx));
// cx.add_action(|pane: &mut Pane, _: &SplitDown, cx| pane.split(SplitDirection::Down, cx));
}
pub enum Event {
@ -1195,9 +1191,9 @@ impl Pane {
}
}
// pub fn split(&mut self, direction: SplitDirection, cx: &mut ViewContext<Self>) {
// cx.emit(Event::Split(direction));
// }
pub fn split(&mut self, direction: SplitDirection, cx: &mut ViewContext<Self>) {
cx.emit(Event::Split(direction));
}
// fn deploy_split_menu(&mut self, cx: &mut ViewContext<Self>) {
// self.tab_bar_context_menu.handle.update(cx, |menu, cx| {
@ -1398,6 +1394,7 @@ impl Pane {
.when_some(item.tab_tooltip_text(cx), |div, text| {
div.tooltip(move |_, cx| cx.build_view(|cx| Tooltip::new(text.clone())).into())
})
.on_click(move |v: &mut Self, e, cx| v.activate_item(ix, true, true, cx))
// .on_drag(move |pane, cx| pane.render_tab(ix, item.boxed_clone(), detail, cx))
// .drag_over::<DraggedTab>(|d| d.bg(cx.theme().colors().element_drop_target))
// .on_drop(|_view, state: View<DraggedTab>, cx| {
@ -1430,32 +1427,22 @@ impl Pane {
.items_center()
.gap_1()
.text_color(text_color)
.children(if item.has_conflict(cx) {
Some(
IconElement::new(Icon::ExclamationTriangle)
.size(ui::IconSize::Small)
.color(TextColor::Warning),
)
} else if item.is_dirty(cx) {
Some(
IconElement::new(Icon::ExclamationTriangle)
.size(ui::IconSize::Small)
.color(TextColor::Info),
)
} else {
None
})
.children(if !close_right {
Some(close_icon())
} else {
None
})
.children(
item.has_conflict(cx)
.then(|| {
IconElement::new(Icon::ExclamationTriangle)
.size(ui::IconSize::Small)
.color(TextColor::Warning)
})
.or(item.is_dirty(cx).then(|| {
IconElement::new(Icon::ExclamationTriangle)
.size(ui::IconSize::Small)
.color(TextColor::Info)
})),
)
.children((!close_right).then(|| close_icon()))
.child(label)
.children(if close_right {
Some(close_icon())
} else {
None
}),
.children(close_right.then(|| close_icon())),
)
}
@ -1912,9 +1899,11 @@ impl Pane {
}
}
// impl Entity for Pane {
// type Event = Event;
// }
impl FocusableView for Pane {
fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
self.focus_handle.clone()
}
}
impl Render for Pane {
type Element = Focusable<Self, Div<Self>>;
@ -1923,6 +1912,10 @@ impl Render for Pane {
v_stack()
.key_context("Pane")
.track_focus(&self.focus_handle)
.on_action(|pane: &mut Pane, _: &SplitLeft, cx| pane.split(SplitDirection::Left, cx))
.on_action(|pane: &mut Pane, _: &SplitUp, cx| pane.split(SplitDirection::Up, cx))
.on_action(|pane: &mut Pane, _: &SplitRight, cx| pane.split(SplitDirection::Right, cx))
.on_action(|pane: &mut Pane, _: &SplitDown, cx| pane.split(SplitDirection::Down, cx))
.size_full()
.on_action(|pane: &mut Self, action, cx| {
pane.close_active_item(action, cx)

View File

@ -148,6 +148,10 @@ impl PaneGroup {
self.root.collect_panes(&mut panes);
panes
}
pub(crate) fn first_pane(&self) -> View<Pane> {
self.root.first_pane()
}
}
#[derive(Clone, PartialEq)]
@ -181,6 +185,13 @@ impl Member {
}
}
fn first_pane(&self) -> View<Pane> {
match self {
Member::Axis(axis) => axis.members[0].first_pane(),
Member::Pane(pane) => pane.clone(),
}
}
pub fn render(
&self,
project: &Model<Project>,
@ -551,7 +562,32 @@ impl PaneAxis {
) -> AnyElement<Workspace> {
debug_assert!(self.members.len() == self.flexes.lock().len());
todo!()
div()
.flex()
.flex_auto()
.map(|s| match self.axis {
Axis::Vertical => s.flex_col(),
Axis::Horizontal => s.flex_row(),
})
.children(self.members.iter().enumerate().map(|(ix, member)| {
match member {
Member::Axis(axis) => axis
.render(
project,
basis,
follower_states,
active_call,
active_pane,
zoomed,
app_state,
cx,
)
.render(),
Member::Pane(pane) => pane.clone().render(),
}
}))
.render()
// let mut pane_axis = PaneAxisElement::new(
// self.axis,
// basis,

View File

@ -68,41 +68,6 @@ impl StatusBar {
}
}
// todo!()
// impl View for StatusBar {
// fn ui_name() -> &'static str {
// "StatusBar"
// }
// fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
// let theme = &theme::current(cx).workspace.status_bar;
// StatusBarElement {
// left: Flex::row()
// .with_children(self.left_items.iter().map(|i| {
// ChildView::new(i.as_any(), cx)
// .aligned()
// .contained()
// .with_margin_right(theme.item_spacing)
// }))
// .into_any(),
// right: Flex::row()
// .with_children(self.right_items.iter().rev().map(|i| {
// ChildView::new(i.as_any(), cx)
// .aligned()
// .contained()
// .with_margin_left(theme.item_spacing)
// }))
// .into_any(),
// }
// .contained()
// .with_style(theme.container)
// .constrained()
// .with_height(theme.height)
// .into_any()
// }
// }
impl StatusBar {
pub fn new(active_pane: &View<Pane>, cx: &mut ViewContext<Self>) -> Self {
let mut this = Self {
@ -222,80 +187,3 @@ impl From<&dyn StatusItemViewHandle> for AnyView {
val.to_any().clone()
}
}
// todo!()
// struct StatusBarElement {
// left: AnyElement<StatusBar>,
// right: AnyElement<StatusBar>,
// }
// todo!()
// impl Element<StatusBar> for StatusBarElement {
// type LayoutState = ();
// type PaintState = ();
// fn layout(
// &mut self,
// mut constraint: SizeConstraint,
// view: &mut StatusBar,
// cx: &mut ViewContext<StatusBar>,
// ) -> (Vector2F, Self::LayoutState) {
// let max_width = constraint.max.x();
// constraint.min = vec2f(0., constraint.min.y());
// let right_size = self.right.layout(constraint, view, cx);
// let constraint = SizeConstraint::new(
// vec2f(0., constraint.min.y()),
// vec2f(max_width - right_size.x(), constraint.max.y()),
// );
// self.left.layout(constraint, view, cx);
// (vec2f(max_width, right_size.y()), ())
// }
// fn paint(
// &mut self,
// bounds: RectF,
// visible_bounds: RectF,
// _: &mut Self::LayoutState,
// view: &mut StatusBar,
// cx: &mut ViewContext<StatusBar>,
// ) -> Self::PaintState {
// let origin_y = bounds.upper_right().y();
// let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
// let left_origin = vec2f(bounds.lower_left().x(), origin_y);
// self.left.paint(left_origin, visible_bounds, view, cx);
// let right_origin = vec2f(bounds.upper_right().x() - self.right.size().x(), origin_y);
// self.right.paint(right_origin, visible_bounds, view, cx);
// }
// fn rect_for_text_range(
// &self,
// _: Range<usize>,
// _: RectF,
// _: RectF,
// _: &Self::LayoutState,
// _: &Self::PaintState,
// _: &StatusBar,
// _: &ViewContext<StatusBar>,
// ) -> Option<RectF> {
// None
// }
// fn debug(
// &self,
// bounds: RectF,
// _: &Self::LayoutState,
// _: &Self::PaintState,
// _: &StatusBar,
// _: &ViewContext<StatusBar>,
// ) -> serde_json::Value {
// json!({
// "type": "StatusBarElement",
// "bounds": bounds.to_json()
// })
// }
// }

View File

@ -37,9 +37,10 @@ use futures::{
};
use gpui::{
actions, div, point, prelude::*, size, Action, AnyModel, AnyView, AnyWeakView, AppContext,
AsyncAppContext, AsyncWindowContext, Bounds, Div, Entity, EntityId, EventEmitter, GlobalPixels,
KeyContext, Model, ModelContext, ParentComponent, Point, Render, Size, Styled, Subscription,
Task, View, ViewContext, WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions,
AsyncAppContext, AsyncWindowContext, Bounds, Div, Entity, EntityId, EventEmitter, FocusHandle,
FocusableView, GlobalPixels, KeyContext, Model, ModelContext, ParentComponent, Point, Render,
Size, Styled, Subscription, Task, View, ViewContext, WeakView, WindowBounds, WindowContext,
WindowHandle, WindowOptions,
};
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
use itertools::Itertools;
@ -319,12 +320,6 @@ pub struct AppState {
pub fs: Arc<dyn fs2::Fs>,
pub build_window_options:
fn(Option<WindowBounds>, Option<Uuid>, &mut AppContext) -> WindowOptions,
pub initialize_workspace: fn(
WeakView<Workspace>,
bool,
Arc<AppState>,
AsyncWindowContext,
) -> Task<anyhow::Result<()>>,
pub node_runtime: Arc<dyn NodeRuntime>,
}
@ -370,7 +365,6 @@ impl AppState {
user_store,
workspace_store,
node_runtime: FakeNodeRuntime::new(),
initialize_workspace: |_, _, _, _| Task::ready(Ok(())),
build_window_options: |_, _, _| Default::default(),
})
}
@ -682,7 +676,7 @@ impl Workspace {
fn new_local(
abs_paths: Vec<PathBuf>,
app_state: Arc<AppState>,
_requesting_window: Option<WindowHandle<Workspace>>,
requesting_window: Option<WindowHandle<Workspace>>,
cx: &mut AppContext,
) -> Task<
anyhow::Result<(
@ -700,7 +694,8 @@ impl Workspace {
);
cx.spawn(|mut cx| async move {
let serialized_workspace: Option<SerializedWorkspace> = None; //persistence::DB.workspace_for_roots(&abs_paths.as_slice());
let serialized_workspace: Option<SerializedWorkspace> =
persistence::DB.workspace_for_roots(&abs_paths.as_slice());
let paths_to_open = Arc::new(abs_paths);
@ -729,15 +724,14 @@ impl Workspace {
DB.next_id().await.unwrap_or(0)
};
// todo!()
let window = /*if let Some(window) = requesting_window {
let window = if let Some(window) = requesting_window {
cx.update_window(window.into(), |old_workspace, cx| {
cx.replace_root_view(|cx| {
Workspace::new(workspace_id, project_handle.clone(), app_state.clone(), cx)
});
});
})?;
window
} else */ {
} else {
let window_bounds_override = window_bounds_env_override(&cx);
let (bounds, display) = if let Some(bounds) = window_bounds_override {
(Some(bounds), None)
@ -751,12 +745,13 @@ impl Workspace {
// Stored bounds are relative to the containing display.
// So convert back to global coordinates if that screen still exists
if let WindowBounds::Fixed(mut window_bounds) = bounds {
let screen =
cx.update(|cx|
cx.displays()
.into_iter()
.find(|display| display.uuid().ok() == Some(serialized_display))
).ok()??;
let screen = cx
.update(|cx| {
cx.displays().into_iter().find(|display| {
display.uuid().ok() == Some(serialized_display)
})
})
.ok()??;
let screen_bounds = screen.bounds();
window_bounds.origin.x += screen_bounds.origin.x;
window_bounds.origin.y += screen_bounds.origin.y;
@ -785,17 +780,17 @@ impl Workspace {
};
// todo!() Ask how to do this
let weak_view = window.update(&mut cx, |_, cx| cx.view().downgrade())?;
let async_cx = window.update(&mut cx, |_, cx| cx.to_async())?;
// let weak_view = window.update(&mut cx, |_, cx| cx.view().downgrade())?;
// let async_cx = window.update(&mut cx, |_, cx| cx.to_async())?;
(app_state.initialize_workspace)(
weak_view,
serialized_workspace.is_some(),
app_state.clone(),
async_cx,
)
.await
.log_err();
// (app_state.initialize_workspace)(
// weak_view,
// serialized_workspace.is_some(),
// app_state.clone(),
// async_cx,
// )
// .await
// .log_err();
window
.update(&mut cx, |_, cx| cx.activate_window())
@ -804,12 +799,7 @@ impl Workspace {
notify_if_database_failed(window, &mut cx);
let opened_items = window
.update(&mut cx, |_workspace, cx| {
open_items(
serialized_workspace,
project_paths,
app_state,
cx,
)
open_items(serialized_workspace, project_paths, app_state, cx)
})?
.await
.unwrap_or_default();
@ -2970,13 +2960,15 @@ impl Workspace {
cx.notify();
}
// fn schedule_serialize(&mut self, cx: &mut ViewContext<Self>) {
// self._schedule_serialize = Some(cx.spawn(|this, cx| async move {
// cx.background().timer(Duration::from_millis(100)).await;
// this.read_with(&cx, |this, cx| this.serialize_workspace(cx))
// .ok();
// }));
// }
fn schedule_serialize(&mut self, cx: &mut ViewContext<Self>) {
self._schedule_serialize = Some(cx.spawn(|this, mut cx| async move {
cx.background_executor()
.timer(Duration::from_millis(100))
.await;
this.update(&mut cx, |this, cx| this.serialize_workspace(cx))
.log_err();
}));
}
fn serialize_workspace(&self, cx: &mut ViewContext<Self>) {
fn serialize_pane_handle(pane_handle: &View<Pane>, cx: &WindowContext) -> SerializedPane {
@ -3032,7 +3024,7 @@ impl Workspace {
let left_visible = left_dock.is_open();
let left_active_panel = left_dock
.visible_panel()
.and_then(|panel| Some(panel.persistent_name(cx).to_string()));
.and_then(|panel| Some(panel.persistent_name().to_string()));
let left_dock_zoom = left_dock
.visible_panel()
.map(|panel| panel.is_zoomed(cx))
@ -3042,7 +3034,7 @@ impl Workspace {
let right_visible = right_dock.is_open();
let right_active_panel = right_dock
.visible_panel()
.and_then(|panel| Some(panel.persistent_name(cx).to_string()));
.and_then(|panel| Some(panel.persistent_name().to_string()));
let right_dock_zoom = right_dock
.visible_panel()
.map(|panel| panel.is_zoomed(cx))
@ -3052,7 +3044,7 @@ impl Workspace {
let bottom_visible = bottom_dock.is_open();
let bottom_active_panel = bottom_dock
.visible_panel()
.and_then(|panel| Some(panel.persistent_name(cx).to_string()));
.and_then(|panel| Some(panel.persistent_name().to_string()));
let bottom_dock_zoom = bottom_dock
.visible_panel()
.map(|panel| panel.is_zoomed(cx))
@ -3158,45 +3150,34 @@ impl Workspace {
// Swap workspace center group
workspace.center = PaneGroup::with_root(center_group);
// Change the focus to the workspace first so that we retrigger focus in on the pane.
// todo!()
// cx.focus_self();
// if let Some(active_pane) = active_pane {
// cx.focus(&active_pane);
// } else {
// cx.focus(workspace.panes.last().unwrap());
// }
} else {
// todo!()
// let old_center_handle = old_center_pane.and_then(|weak| weak.upgrade());
// if let Some(old_center_handle) = old_center_handle {
// cx.focus(&old_center_handle)
// } else {
// cx.focus_self()
// }
workspace.last_active_center_pane = active_pane.as_ref().map(|p| p.downgrade());
if let Some(active_pane) = active_pane {
workspace.active_pane = active_pane;
cx.focus_self();
} else {
workspace.active_pane = workspace.center.first_pane().clone();
}
}
let docks = serialized_workspace.docks;
workspace.left_dock.update(cx, |dock, cx| {
dock.set_open(docks.left.visible, cx);
if let Some(active_panel) = docks.left.active_panel {
if let Some(ix) = dock.panel_index_for_ui_name(&active_panel, cx) {
if let Some(ix) = dock.panel_index_for_persistent_name(&active_panel, cx) {
dock.activate_panel(ix, cx);
}
}
dock.active_panel()
.map(|panel| panel.set_zoomed(docks.left.zoom, cx));
if docks.left.visible && docks.left.zoom {
// todo!()
// cx.focus_self()
cx.focus_self()
}
});
// TODO: I think the bug is that setting zoom or active undoes the bottom zoom or something
workspace.right_dock.update(cx, |dock, cx| {
dock.set_open(docks.right.visible, cx);
if let Some(active_panel) = docks.right.active_panel {
if let Some(ix) = dock.panel_index_for_ui_name(&active_panel, cx) {
if let Some(ix) = dock.panel_index_for_persistent_name(&active_panel, cx) {
dock.activate_panel(ix, cx);
}
}
@ -3204,14 +3185,13 @@ impl Workspace {
.map(|panel| panel.set_zoomed(docks.right.zoom, cx));
if docks.right.visible && docks.right.zoom {
// todo!()
// cx.focus_self()
cx.focus_self()
}
});
workspace.bottom_dock.update(cx, |dock, cx| {
dock.set_open(docks.bottom.visible, cx);
if let Some(active_panel) = docks.bottom.active_panel {
if let Some(ix) = dock.panel_index_for_ui_name(&active_panel, cx) {
if let Some(ix) = dock.panel_index_for_persistent_name(&active_panel, cx) {
dock.activate_panel(ix, cx);
}
}
@ -3220,8 +3200,7 @@ impl Workspace {
.map(|panel| panel.set_zoomed(docks.bottom.zoom, cx));
if docks.bottom.visible && docks.bottom.zoom {
// todo!()
// cx.focus_self()
cx.focus_self()
}
});
@ -3283,7 +3262,6 @@ impl Workspace {
// },
// );
.on_action(|this, e: &ToggleLeftDock, cx| {
println!("TOGGLING DOCK");
this.toggle_dock(DockPosition::Left, cx);
})
// cx.add_action(|workspace: &mut Workspace, _: &ToggleRightDock, cx| {
@ -3347,7 +3325,6 @@ impl Workspace {
user_store,
fs: project.read(cx).fs().clone(),
build_window_options: |_, _, _| Default::default(),
initialize_workspace: |_, _, _, _| Task::ready(Ok(())),
node_runtime: FakeNodeRuntime::new(),
});
let workspace = Self::new(0, project, app_state, cx);
@ -3626,6 +3603,12 @@ fn notify_if_database_failed(workspace: WindowHandle<Workspace>, cx: &mut AsyncA
impl EventEmitter<Event> for Workspace {}
impl FocusableView for Workspace {
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
self.active_pane.focus_handle(cx)
}
}
impl Render for Workspace {
type Element = Div<Self>;

View File

@ -50,8 +50,8 @@ use util::{
use uuid::Uuid;
use workspace::{AppState, WorkspaceStore};
use zed2::{
build_window_options, ensure_only_instance, handle_cli_connection, init_zed_actions,
initialize_workspace, languages, Assets, IsOnlyInstance, OpenListener, OpenRequest,
build_window_options, ensure_only_instance, handle_cli_connection, initialize_workspace,
languages, Assets, IsOnlyInstance, OpenListener, OpenRequest,
};
mod open_listener;
@ -176,7 +176,6 @@ fn main() {
user_store,
fs,
build_window_options,
initialize_workspace,
// background_actions: todo!("ask Mikayla"),
workspace_store,
node_runtime,
@ -213,7 +212,7 @@ fn main() {
// zed::init(&app_state, cx);
// cx.set_menus(menus::menus());
init_zed_actions(app_state.clone(), cx);
initialize_workspace(app_state.clone(), cx);
if stdout_is_a_pty() {
cx.activate(true);

View File

@ -10,13 +10,13 @@ pub use assets::*;
use collections::VecDeque;
use editor::{Editor, MultiBuffer};
use gpui::{
actions, point, px, AppContext, AsyncWindowContext, Context, PromptLevel, Task,
TitlebarOptions, ViewContext, VisualContext, WeakView, WindowBounds, WindowKind, WindowOptions,
actions, point, px, AppContext, Context, PromptLevel, TitlebarOptions, ViewContext,
VisualContext, WindowBounds, WindowKind, WindowOptions,
};
pub use only_instance::*;
pub use open_listener::*;
use anyhow::{anyhow, Context as _, Result};
use anyhow::{anyhow, Context as _};
use project_panel::ProjectPanel;
use settings::{initial_local_settings_content, Settings};
use std::{borrow::Cow, ops::Deref, sync::Arc};
@ -86,8 +86,147 @@ pub fn build_window_options(
}
}
pub fn init_zed_actions(app_state: Arc<AppState>, cx: &mut AppContext) {
cx.observe_new_views(move |workspace: &mut Workspace, _cx| {
pub fn initialize_workspace(app_state: Arc<AppState>, cx: &mut AppContext) {
cx.observe_new_views(move |workspace: &mut Workspace, cx| {
let workspace_handle = cx.view().clone();
cx.subscribe(&workspace_handle, {
move |workspace, _, event, cx| {
if let workspace::Event::PaneAdded(pane) = event {
pane.update(cx, |pane, cx| {
pane.toolbar().update(cx, |toolbar, cx| {
// todo!()
// let breadcrumbs = cx.add_view(|_| Breadcrumbs::new(workspace));
// toolbar.add_item(breadcrumbs, cx);
// let buffer_search_bar = cx.add_view(BufferSearchBar::new);
// toolbar.add_item(buffer_search_bar.clone(), cx);
// let quick_action_bar = cx.add_view(|_| {
// QuickActionBar::new(buffer_search_bar, workspace)
// });
// toolbar.add_item(quick_action_bar, cx);
// let diagnostic_editor_controls =
// cx.add_view(|_| diagnostics2::ToolbarControls::new());
// toolbar.add_item(diagnostic_editor_controls, cx);
// let project_search_bar = cx.add_view(|_| ProjectSearchBar::new());
// toolbar.add_item(project_search_bar, cx);
// let submit_feedback_button =
// cx.add_view(|_| SubmitFeedbackButton::new());
// toolbar.add_item(submit_feedback_button, cx);
// let feedback_info_text = cx.add_view(|_| FeedbackInfoText::new());
// toolbar.add_item(feedback_info_text, cx);
// let lsp_log_item =
// cx.add_view(|_| language_tools::LspLogToolbarItemView::new());
// toolbar.add_item(lsp_log_item, cx);
// let syntax_tree_item = cx
// .add_view(|_| language_tools::SyntaxTreeToolbarItemView::new());
// toolbar.add_item(syntax_tree_item, cx);
})
});
}
}
})
.detach();
// cx.emit(workspace2::Event::PaneAdded(
// workspace.active_pane().clone(),
// ));
// let collab_titlebar_item =
// cx.add_view(|cx| CollabTitlebarItem::new(workspace, &workspace_handle, cx));
// workspace.set_titlebar_item(collab_titlebar_item.into_any(), cx);
// let copilot =
// cx.add_view(|cx| copilot_button::CopilotButton::new(app_state.fs.clone(), cx));
// let diagnostic_summary =
// cx.add_view(|cx| diagnostics::items::DiagnosticIndicator::new(workspace, cx));
// let activity_indicator = activity_indicator::ActivityIndicator::new(
// workspace,
// app_state.languages.clone(),
// cx,
// );
// let active_buffer_language =
// cx.add_view(|_| language_selector::ActiveBufferLanguage::new(workspace));
// let vim_mode_indicator = cx.add_view(|cx| vim::ModeIndicator::new(cx));
// let feedback_button = cx.add_view(|_| {
// feedback::deploy_feedback_button::DeployFeedbackButton::new(workspace)
// });
// let cursor_position = cx.add_view(|_| editor::items::CursorPosition::new());
workspace.status_bar().update(cx, |status_bar, cx| {
// status_bar.add_left_item(diagnostic_summary, cx);
// status_bar.add_left_item(activity_indicator, cx);
// status_bar.add_right_item(feedback_button, cx);
// status_bar.add_right_item(copilot, cx);
// status_bar.add_right_item(active_buffer_language, cx);
// status_bar.add_right_item(vim_mode_indicator, cx);
// status_bar.add_right_item(cursor_position, cx);
});
// auto_update::notify_of_any_new_update(cx.weak_handle(), cx);
// vim::observe_keystrokes(cx);
// cx.on_window_should_close(|workspace, cx| {
// if let Some(task) = workspace.close(&Default::default(), cx) {
// task.detach_and_log_err(cx);
// }
// false
// });
cx.spawn(|workspace_handle, mut cx| async move {
let project_panel = ProjectPanel::load(workspace_handle.clone(), cx.clone());
// let terminal_panel = TerminalPanel::load(workspace_handle.clone(), cx.clone());
// let assistant_panel = AssistantPanel::load(workspace_handle.clone(), cx.clone());
let channels_panel =
collab_ui::collab_panel::CollabPanel::load(workspace_handle.clone(), cx.clone());
// let chat_panel =
// collab_ui::chat_panel::ChatPanel::load(workspace_handle.clone(), cx.clone());
// let notification_panel = collab_ui::notification_panel::NotificationPanel::load(
// workspace_handle.clone(),
// cx.clone(),
// );
let (
project_panel,
// terminal_panel,
// assistant_panel,
channels_panel,
// chat_panel,
// notification_panel,
) = futures::try_join!(
project_panel,
// terminal_panel,
// assistant_panel,
channels_panel,
// chat_panel,
// notification_panel,
)?;
workspace_handle.update(&mut cx, |workspace, cx| {
let project_panel_position = project_panel.position(cx);
workspace.add_panel(project_panel, cx);
// workspace.add_panel(terminal_panel, cx);
// workspace.add_panel(assistant_panel, cx);
workspace.add_panel(channels_panel, cx);
// workspace.add_panel(chat_panel, cx);
// workspace.add_panel(notification_panel, cx);
// if !was_deserialized
// && workspace
// .project()
// .read(cx)
// .visible_worktrees(cx)
// .any(|tree| {
// tree.read(cx)
// .root_entry()
// .map_or(false, |entry| entry.is_dir())
// })
// {
// workspace.toggle_dock(project_panel_position, cx);
// }
// cx.focus_self();
})
})
.detach();
workspace
.register_action(about)
.register_action(|_, _: &Hide, cx| {
@ -291,150 +430,6 @@ pub fn init_zed_actions(app_state: Arc<AppState>, cx: &mut AppContext) {
.detach();
}
pub fn initialize_workspace(
workspace_handle: WeakView<Workspace>,
was_deserialized: bool,
app_state: Arc<AppState>,
cx: AsyncWindowContext,
) -> Task<Result<()>> {
cx.spawn(|mut cx| async move {
workspace_handle.update(&mut cx, |workspace, cx| {
let workspace_handle = cx.view().clone();
cx.subscribe(&workspace_handle, {
move |workspace, _, event, cx| {
if let workspace::Event::PaneAdded(pane) = event {
pane.update(cx, |pane, cx| {
pane.toolbar().update(cx, |toolbar, cx| {
// todo!()
// let breadcrumbs = cx.add_view(|_| Breadcrumbs::new(workspace));
// toolbar.add_item(breadcrumbs, cx);
// let buffer_search_bar = cx.add_view(BufferSearchBar::new);
// toolbar.add_item(buffer_search_bar.clone(), cx);
// let quick_action_bar = cx.add_view(|_| {
// QuickActionBar::new(buffer_search_bar, workspace)
// });
// toolbar.add_item(quick_action_bar, cx);
// let diagnostic_editor_controls =
// cx.add_view(|_| diagnostics2::ToolbarControls::new());
// toolbar.add_item(diagnostic_editor_controls, cx);
// let project_search_bar = cx.add_view(|_| ProjectSearchBar::new());
// toolbar.add_item(project_search_bar, cx);
// let submit_feedback_button =
// cx.add_view(|_| SubmitFeedbackButton::new());
// toolbar.add_item(submit_feedback_button, cx);
// let feedback_info_text = cx.add_view(|_| FeedbackInfoText::new());
// toolbar.add_item(feedback_info_text, cx);
// let lsp_log_item =
// cx.add_view(|_| language_tools::LspLogToolbarItemView::new());
// toolbar.add_item(lsp_log_item, cx);
// let syntax_tree_item = cx
// .add_view(|_| language_tools::SyntaxTreeToolbarItemView::new());
// toolbar.add_item(syntax_tree_item, cx);
})
});
}
}
})
.detach();
// cx.emit(workspace2::Event::PaneAdded(
// workspace.active_pane().clone(),
// ));
// let copilot =
// cx.add_view(|cx| copilot_button::CopilotButton::new(app_state.fs.clone(), cx));
// let diagnostic_summary =
// cx.add_view(|cx| diagnostics::items::DiagnosticIndicator::new(workspace, cx));
// let activity_indicator = activity_indicator::ActivityIndicator::new(
// workspace,
// app_state.languages.clone(),
// cx,
// );
// let active_buffer_language =
// cx.add_view(|_| language_selector::ActiveBufferLanguage::new(workspace));
// let vim_mode_indicator = cx.add_view(|cx| vim::ModeIndicator::new(cx));
// let feedback_button = cx.add_view(|_| {
// feedback::deploy_feedback_button::DeployFeedbackButton::new(workspace)
// });
// let cursor_position = cx.add_view(|_| editor::items::CursorPosition::new());
workspace.status_bar().update(cx, |status_bar, cx| {
// status_bar.add_left_item(diagnostic_summary, cx);
// status_bar.add_left_item(activity_indicator, cx);
// status_bar.add_right_item(feedback_button, cx);
// status_bar.add_right_item(copilot, cx);
// status_bar.add_right_item(active_buffer_language, cx);
// status_bar.add_right_item(vim_mode_indicator, cx);
// status_bar.add_right_item(cursor_position, cx);
});
// auto_update::notify_of_any_new_update(cx.weak_handle(), cx);
// vim::observe_keystrokes(cx);
// cx.on_window_should_close(|workspace, cx| {
// if let Some(task) = workspace.close(&Default::default(), cx) {
// task.detach_and_log_err(cx);
// }
// false
// });
})?;
let project_panel = ProjectPanel::load(workspace_handle.clone(), cx.clone());
// let terminal_panel = TerminalPanel::load(workspace_handle.clone(), cx.clone());
// let assistant_panel = AssistantPanel::load(workspace_handle.clone(), cx.clone());
let channels_panel =
collab_ui::collab_panel::CollabPanel::load(workspace_handle.clone(), cx.clone());
// let chat_panel =
// collab_ui::chat_panel::ChatPanel::load(workspace_handle.clone(), cx.clone());
// let notification_panel = collab_ui::notification_panel::NotificationPanel::load(
// workspace_handle.clone(),
// cx.clone(),
// );
let (
project_panel,
// terminal_panel,
// assistant_panel,
channels_panel,
// chat_panel,
// notification_panel,
) = futures::try_join!(
project_panel,
// terminal_panel,
// assistant_panel,
channels_panel,
// chat_panel,
// notification_panel,/
)?;
workspace_handle.update(&mut cx, |workspace, cx| {
let project_panel_position = project_panel.position(cx);
workspace.add_panel(project_panel, cx);
// workspace.add_panel(terminal_panel, cx);
// workspace.add_panel(assistant_panel, cx);
workspace.add_panel(channels_panel, cx);
// workspace.add_panel(chat_panel, cx);
// workspace.add_panel(notification_panel, cx);
// if !was_deserialized
// && workspace
// .project()
// .read(cx)
// .visible_worktrees(cx)
// .any(|tree| {
// tree.read(cx)
// .root_entry()
// .map_or(false, |entry| entry.is_dir())
// })
// {
workspace.toggle_dock(project_panel_position, cx);
// }
// cx.focus_self();
})?;
Ok(())
})
}
fn about(_: &mut Workspace, _: &About, cx: &mut gpui::ViewContext<Workspace>) {
let app_name = cx.global::<ReleaseChannel>().display_name();
let version = env!("CARGO_PKG_VERSION");