WIP: Make the item module compile again

This commit is contained in:
Antonio Scandurra 2023-10-31 13:51:42 +01:00
parent e8eea52d0f
commit 14a6199b4b
6 changed files with 478 additions and 521 deletions

View file

@ -14,7 +14,7 @@ pub use test_context::*;
use crate::{
current_platform, image_cache::ImageCache, Action, AnyBox, AnyView, AnyWindowHandle,
AppMetadata, AssetSource, ClipboardItem, Context, DispatchPhase, DisplayId, Executor,
AppMetadata, AssetSource, ClipboardItem, Context, DispatchPhase, DisplayId, Entity, Executor,
FocusEvent, FocusHandle, FocusId, KeyBinding, Keymap, LayoutId, MainThread, MainThreadOnly,
Pixels, Platform, Point, Render, SharedString, SubscriberSet, Subscription, SvgRenderer, Task,
TextStyle, TextStyleRefinement, TextSystem, View, ViewContext, Window, WindowContext,
@ -694,13 +694,17 @@ impl AppContext {
self.globals_by_type.insert(global_type, lease.global);
}
pub fn observe_release<E: 'static>(
pub fn observe_release<E, T>(
&mut self,
handle: &Model<E>,
mut on_release: impl FnMut(&mut E, &mut AppContext) + Send + 'static,
) -> Subscription {
handle: &E,
mut on_release: impl FnMut(&mut T, &mut AppContext) + Send + 'static,
) -> Subscription
where
E: Entity<T>,
T: 'static,
{
self.release_listeners.insert(
handle.entity_id,
handle.entity_id(),
Box::new(move |entity, cx| {
let entity = entity.downcast_mut().expect("invalid entity type");
on_release(entity, cx)

View file

@ -314,7 +314,7 @@ impl AnyView {
.map_err(|_| self)
}
pub(crate) fn entity_type(&self) -> TypeId {
pub fn entity_type(&self) -> TypeId {
self.0.entity_type()
}

View file

@ -1,88 +1,80 @@
// use crate::{
// pane, persistence::model::ItemId, searchable::SearchableItemHandle, FollowableItemBuilders,
// ItemNavHistory, Pane, ToolbarItemLocation, ViewId, Workspace, WorkspaceId,
// };
// use crate::{AutosaveSetting, DelayedDebouncedEditAction, WorkspaceSettings};
use crate::{
pane::{self, Pane},
persistence::model::ItemId,
searchable::SearchableItemHandle,
workspace_settings::{AutosaveSetting, WorkspaceSettings},
DelayedDebouncedEditAction, FollowableItemBuilders, ItemNavHistory, ToolbarItemLocation,
ViewId, Workspace, WorkspaceId,
};
use anyhow::Result;
use client2::{
proto::{self, PeerId},
Client,
};
use gpui2::{
AnyElement, AnyView, AppContext, EventEmitter, HighlightStyle, Model, Pixels, Point, Render,
SharedString, Task, View, ViewContext, WeakView, WindowContext,
};
use parking_lot::Mutex;
use project2::{Project, ProjectEntryId, ProjectPath};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use settings2::Settings;
use smallvec::SmallVec;
use std::{
any::{Any, TypeId},
ops::Range,
path::PathBuf,
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
time::Duration,
};
use theme2::Theme;
// use client2::{
// proto::{self, PeerId},
// Client,
// };
// use gpui2::geometry::vector::Vector2F;
// use gpui2::AnyWindowHandle;
// use gpui2::{
// fonts::HighlightStyle, AnyElement, AnyViewHandle, AppContext, Model, Task, View,
// ViewContext, View, WeakViewHandle, WindowContext,
// };
// use project2::{Project, ProjectEntryId, ProjectPath};
// use schemars::JsonSchema;
// use serde_derive::{Deserialize, Serialize};
// use settings2::Setting;
// use smallvec::SmallVec;
// use std::{
// any::{Any, TypeId},
// borrow::Cow,
// cell::RefCell,
// fmt,
// ops::Range,
// path::PathBuf,
// rc::Rc,
// sync::{
// atomic::{AtomicBool, Ordering},
// Arc,
// },
// time::Duration,
// };
// use theme2::Theme;
// #[derive(Deserialize)]
// pub struct ItemSettings {
// pub git_status: bool,
// pub close_position: ClosePosition,
// }
#[derive(Deserialize)]
pub struct ItemSettings {
pub git_status: bool,
pub close_position: ClosePosition,
}
// #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
// #[serde(rename_all = "lowercase")]
// pub enum ClosePosition {
// Left,
// #[default]
// Right,
// }
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "lowercase")]
pub enum ClosePosition {
Left,
#[default]
Right,
}
// impl ClosePosition {
// pub fn right(&self) -> bool {
// match self {
// ClosePosition::Left => false,
// ClosePosition::Right => true,
// }
// }
// }
impl ClosePosition {
pub fn right(&self) -> bool {
match self {
ClosePosition::Left => false,
ClosePosition::Right => true,
}
}
}
// #[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
// pub struct ItemSettingsContent {
// git_status: Option<bool>,
// close_position: Option<ClosePosition>,
// }
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
pub struct ItemSettingsContent {
git_status: Option<bool>,
close_position: Option<ClosePosition>,
}
// impl Setting for ItemSettings {
// const KEY: Option<&'static str> = Some("tabs");
impl Settings for ItemSettings {
const KEY: Option<&'static str> = Some("tabs");
// type FileContent = ItemSettingsContent;
type FileContent = ItemSettingsContent;
// fn load(
// default_value: &Self::FileContent,
// user_values: &[&Self::FileContent],
// _: &gpui2::AppContext,
// ) -> anyhow::Result<Self> {
// Self::load_via_json_merge(default_value, user_values)
// }
// }
fn load(
default_value: &Self::FileContent,
user_values: &[&Self::FileContent],
_: &mut AppContext,
) -> Result<Self> {
Self::load_via_json_merge(default_value, user_values)
}
}
#[derive(Eq, PartialEq, Hash, Debug)]
pub enum ItemEvent {
@ -165,18 +157,18 @@ pub trait Item: Render + EventEmitter + Send {
false
}
// fn act_as_type<'a>(
// &'a self,
// type_id: TypeId,
// self_handle: &'a View<Self>,
// _: &'a AppContext,
// ) -> Option<&AnyViewHandle> {
// if TypeId::of::<Self>() == type_id {
// Some(self_handle)
// } else {
// None
// }
// }
fn act_as_type<'a>(
&'a self,
type_id: TypeId,
self_handle: &'a View<Self>,
_: &'a AppContext,
) -> Option<AnyView> {
if TypeId::of::<Self>() == type_id {
Some(self_handle.clone().into_any())
} else {
None
}
}
fn as_searchable(&self, _: &View<Self>) -> Option<Box<dyn SearchableItemHandle>> {
None
@ -215,35 +207,6 @@ pub trait Item: Render + EventEmitter + Send {
}
}
use std::{
any::Any,
cell::RefCell,
ops::Range,
path::PathBuf,
rc::Rc,
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
time::Duration,
};
use gpui2::{
AnyElement, AnyView, AnyWindowHandle, AppContext, EventEmitter, HighlightStyle, Model, Pixels,
Point, Render, SharedString, Task, View, ViewContext, WeakView, WindowContext,
};
use project2::{Project, ProjectEntryId, ProjectPath};
use smallvec::SmallVec;
use crate::{
pane::{self, Pane},
persistence::model::ItemId,
searchable::SearchableItemHandle,
workspace_settings::{AutosaveSetting, WorkspaceSettings},
DelayedDebouncedEditAction, FollowableItemBuilders, ItemNavHistory, ToolbarItemLocation,
ViewId, Workspace, WorkspaceId,
};
pub trait ItemHandle: 'static + Send {
fn subscribe_to_item_events(
&self,
@ -275,7 +238,6 @@ pub trait ItemHandle: 'static + Send {
fn workspace_deactivated(&self, cx: &mut WindowContext);
fn navigate(&self, data: Box<dyn Any>, cx: &mut WindowContext) -> bool;
fn id(&self) -> usize;
fn window(&self) -> AnyWindowHandle;
fn to_any(&self) -> AnyView;
fn is_dirty(&self, cx: &AppContext) -> bool;
fn has_conflict(&self, cx: &AppContext) -> bool;
@ -288,12 +250,12 @@ pub trait ItemHandle: 'static + Send {
cx: &mut WindowContext,
) -> Task<Result<()>>;
fn reload(&self, project: Model<Project>, cx: &mut WindowContext) -> Task<Result<()>>;
// fn act_as_type<'a>(&'a self, type_id: TypeId, cx: &'a AppContext) -> Option<&'a AnyViewHandle>; todo!()
fn act_as_type(&self, type_id: TypeId, cx: &AppContext) -> Option<AnyView>;
fn to_followable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn FollowableItemHandle>>;
fn on_release(
&self,
cx: &mut AppContext,
callback: Box<dyn FnOnce(&mut AppContext)>,
callback: Box<dyn FnOnce(&mut AppContext) + Send>,
) -> gpui2::Subscription;
fn to_searchable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>>;
fn breadcrumb_location(&self, cx: &AppContext) -> ToolbarItemLocation;
@ -303,23 +265,21 @@ pub trait ItemHandle: 'static + Send {
fn pixel_position_of_cursor(&self, cx: &AppContext) -> Option<Point<Pixels>>;
}
pub trait WeakItemHandle: Send {
pub trait WeakItemHandle: Send + Sync {
fn id(&self) -> usize;
fn window(&self) -> AnyWindowHandle;
fn upgrade(&self) -> Option<Box<dyn ItemHandle>>;
}
// todo!()
// impl dyn ItemHandle {
// pub fn downcast<T: View>(&self) -> Option<View<T>> {
// self.as_any().clone().downcast()
// }
impl dyn ItemHandle {
pub fn downcast<V: 'static>(&self) -> Option<View<V>> {
self.to_any().downcast().ok()
}
// pub fn act_as<T: View>(&self, cx: &AppContext) -> Option<View<T>> {
// self.act_as_type(TypeId::of::<T>(), cx)
// .and_then(|t| t.clone().downcast())
// }
// }
pub fn act_as<V: 'static>(&self, cx: &AppContext) -> Option<View<V>> {
self.act_as_type(TypeId::of::<V>(), cx)
.and_then(|t| t.downcast().ok())
}
}
impl<T: Item> ItemHandle for View<T> {
fn subscribe_to_item_events(
@ -438,8 +398,8 @@ impl<T: Item> ItemHandle for View<T> {
.is_none()
{
let mut pending_autosave = DelayedDebouncedEditAction::new();
let pending_update = Rc::new(RefCell::new(None));
let pending_update_scheduled = Rc::new(AtomicBool::new(false));
let pending_update = Arc::new(Mutex::new(None));
let pending_update_scheduled = Arc::new(AtomicBool::new(false));
let mut event_subscription =
Some(cx.subscribe(self, move |workspace, item, event, cx| {
@ -462,33 +422,31 @@ impl<T: Item> ItemHandle for View<T> {
workspace.unfollow(&pane, cx);
}
if item.add_event_to_update_proto(
event,
&mut *pending_update.borrow_mut(),
cx,
) && !pending_update_scheduled.load(Ordering::SeqCst)
if item.add_event_to_update_proto(event, &mut *pending_update.lock(), cx)
&& !pending_update_scheduled.load(Ordering::SeqCst)
{
pending_update_scheduled.store(true, Ordering::SeqCst);
cx.after_window_update({
let pending_update = pending_update.clone();
let pending_update_scheduled = pending_update_scheduled.clone();
move |this, cx| {
pending_update_scheduled.store(false, Ordering::SeqCst);
this.update_followers(
is_project_item,
proto::update_followers::Variant::UpdateView(
proto::UpdateView {
id: item
.remote_id(&this.app_state.client, cx)
.map(|id| id.to_proto()),
variant: pending_update.borrow_mut().take(),
leader_id,
},
),
cx,
);
}
});
todo!("replace with on_next_frame?");
// cx.after_window_update({
// let pending_update = pending_update.clone();
// let pending_update_scheduled = pending_update_scheduled.clone();
// move |this, cx| {
// pending_update_scheduled.store(false, Ordering::SeqCst);
// this.update_followers(
// is_project_item,
// proto::update_followers::Variant::UpdateView(
// proto::UpdateView {
// id: item
// .remote_id(&this.app_state.client, cx)
// .map(|id| id.to_proto()),
// variant: pending_update.borrow_mut().take(),
// leader_id,
// },
// ),
// cx,
// );
// }
// });
}
}
@ -525,15 +483,16 @@ impl<T: Item> ItemHandle for View<T> {
}
}));
cx.observe_focus(self, move |workspace, item, focused, cx| {
if !focused
&& WorkspaceSettings::get_global(cx).autosave == AutosaveSetting::OnFocusChange
{
Pane::autosave_item(&item, workspace.project.clone(), cx)
.detach_and_log_err(cx);
}
})
.detach();
todo!("observe focus");
// cx.observe_focus(self, move |workspace, item, focused, cx| {
// if !focused
// && WorkspaceSettings::get_global(cx).autosave == AutosaveSetting::OnFocusChange
// {
// Pane::autosave_item(&item, workspace.project.clone(), cx)
// .detach_and_log_err(cx);
// }
// })
// .detach();
let item_id = self.id();
cx.observe_release(self, move |workspace, _, _| {
@ -564,11 +523,6 @@ impl<T: Item> ItemHandle for View<T> {
self.id()
}
fn window(&self) -> AnyWindowHandle {
todo!()
// AnyViewHandle::window(self)
}
fn to_any(&self) -> AnyView {
self.clone().into_any()
}
@ -602,16 +556,15 @@ impl<T: Item> ItemHandle for View<T> {
self.update(cx, |item, cx| item.reload(project, cx))
}
// todo!()
// fn act_as_type<'a>(&'a self, type_id: TypeId, cx: &'a AppContext) -> Option<&'a AnyViewHandle> {
// self.read(cx).act_as_type(type_id, self, cx)
// }
fn act_as_type<'a>(&'a self, type_id: TypeId, cx: &'a AppContext) -> Option<AnyView> {
self.read(cx).act_as_type(type_id, self, cx)
}
fn to_followable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn FollowableItemHandle>> {
if cx.has_global::<FollowableItemBuilders>() {
let builders = cx.global::<FollowableItemBuilders>();
let item = self.as_any();
Some(builders.get(&item.view_type())?.1(item))
let item = self.to_any();
Some(builders.get(&item.entity_type())?.1(&item))
} else {
None
}
@ -620,7 +573,7 @@ impl<T: Item> ItemHandle for View<T> {
fn on_release(
&self,
cx: &mut AppContext,
callback: Box<dyn FnOnce(&mut AppContext)>,
callback: Box<dyn FnOnce(&mut AppContext) + Send>,
) -> gpui2::Subscription {
cx.observe_release(self, move |_, cx| callback(cx))
}
@ -673,10 +626,6 @@ impl<T: Item> WeakItemHandle for WeakView<T> {
self.id()
}
fn window(&self) -> AnyWindowHandle {
self.window()
}
fn upgrade(&self) -> Option<Box<dyn ItemHandle>> {
self.upgrade().map(|v| Box::new(v) as Box<dyn ItemHandle>)
}

View file

@ -2,10 +2,15 @@
use crate::{
item::{Item, ItemHandle, WeakItemHandle},
toolbar::Toolbar,
SplitDirection, Workspace,
};
use anyhow::Result;
use collections::{HashMap, VecDeque};
use gpui2::{EventEmitter, Model, View, ViewContext, WeakView};
use gpui2::{
AppContext, EventEmitter, Model, Task, View, ViewContext, VisualContext, WeakView,
WindowContext,
};
use parking_lot::Mutex;
use project2::{Project, ProjectEntryId, ProjectPath};
use serde::Deserialize;
@ -68,6 +73,7 @@ pub enum SaveIntent {
// pub save_intent: Option<SaveIntent>,
// }
// todo!()
// actions!(
// pane,
// [
@ -90,8 +96,9 @@ pub enum SaveIntent {
// impl_actions!(pane, [ActivateItem, CloseActiveItem, CloseAllItems]);
// const MAX_NAVIGATION_HISTORY_LEN: usize = 1024;
const MAX_NAVIGATION_HISTORY_LEN: usize = 1024;
// todo!()
// pub fn init(cx: &mut AppContext) {
// cx.add_action(Pane::toggle_zoom);
// cx.add_action(|pane: &mut Pane, action: &ActivateItem, cx| {
@ -330,7 +337,7 @@ impl Pane {
pane: handle.clone(),
next_timestamp,
}))),
// toolbar: cx.add_view(|_| Toolbar::new()),
toolbar: cx.build_view(|_| Toolbar::new()),
// tab_bar_context_menu: TabBarContextMenu {
// kind: TabBarContextMenuKind::New,
// handle: context_menu,
@ -447,33 +454,33 @@ impl Pane {
}
}
// pub fn nav_history(&self) -> &NavHistory {
// &self.nav_history
// }
pub fn nav_history(&self) -> &NavHistory {
&self.nav_history
}
// pub fn nav_history_mut(&mut self) -> &mut NavHistory {
// &mut self.nav_history
// }
pub fn nav_history_mut(&mut self) -> &mut NavHistory {
&mut self.nav_history
}
// pub fn disable_history(&mut self) {
// self.nav_history.disable();
// }
pub fn disable_history(&mut self) {
self.nav_history.disable();
}
// pub fn enable_history(&mut self) {
// self.nav_history.enable();
// }
pub fn enable_history(&mut self) {
self.nav_history.enable();
}
// pub fn can_navigate_backward(&self) -> bool {
// !self.nav_history.0.borrow().backward_stack.is_empty()
// }
pub fn can_navigate_backward(&self) -> bool {
!self.nav_history.0.lock().backward_stack.is_empty()
}
// pub fn can_navigate_forward(&self) -> bool {
// !self.nav_history.0.borrow().forward_stack.is_empty()
// }
pub fn can_navigate_forward(&self) -> bool {
!self.nav_history.0.lock().forward_stack.is_empty()
}
// fn history_updated(&mut self, cx: &mut ViewContext<Self>) {
// self.toolbar.update(cx, |_, cx| cx.notify());
// }
fn history_updated(&mut self, cx: &mut ViewContext<Self>) {
self.toolbar.update(cx, |_, cx| cx.notify());
}
pub(crate) fn open_item(
&mut self,
@ -736,115 +743,115 @@ impl Pane {
// ))
// }
// pub fn close_item_by_id(
// &mut self,
// item_id_to_close: usize,
// save_intent: SaveIntent,
// cx: &mut ViewContext<Self>,
// ) -> Task<Result<()>> {
// self.close_items(cx, save_intent, move |view_id| view_id == item_id_to_close)
pub fn close_item_by_id(
&mut self,
item_id_to_close: usize,
save_intent: SaveIntent,
cx: &mut ViewContext<Self>,
) -> Task<Result<()>> {
self.close_items(cx, save_intent, move |view_id| view_id == item_id_to_close)
}
// pub fn close_inactive_items(
// &mut self,
// _: &CloseInactiveItems,
// cx: &mut ViewContext<Self>,
// ) -> Option<Task<Result<()>>> {
// if self.items.is_empty() {
// return None;
// }
// pub fn close_inactive_items(
// &mut self,
// _: &CloseInactiveItems,
// cx: &mut ViewContext<Self>,
// ) -> Option<Task<Result<()>>> {
// if self.items.is_empty() {
// return None;
// }
// let active_item_id = self.items[self.active_item_index].id();
// Some(self.close_items(cx, SaveIntent::Close, move |item_id| {
// item_id != active_item_id
// }))
// }
// let active_item_id = self.items[self.active_item_index].id();
// Some(self.close_items(cx, SaveIntent::Close, move |item_id| {
// item_id != active_item_id
// }))
// pub fn close_clean_items(
// &mut self,
// _: &CloseCleanItems,
// cx: &mut ViewContext<Self>,
// ) -> Option<Task<Result<()>>> {
// let item_ids: Vec<_> = self
// .items()
// .filter(|item| !item.is_dirty(cx))
// .map(|item| item.id())
// .collect();
// Some(self.close_items(cx, SaveIntent::Close, move |item_id| {
// item_ids.contains(&item_id)
// }))
// }
// pub fn close_items_to_the_left(
// &mut self,
// _: &CloseItemsToTheLeft,
// cx: &mut ViewContext<Self>,
// ) -> Option<Task<Result<()>>> {
// if self.items.is_empty() {
// return None;
// }
// let active_item_id = self.items[self.active_item_index].id();
// Some(self.close_items_to_the_left_by_id(active_item_id, cx))
// }
// pub fn close_items_to_the_left_by_id(
// &mut self,
// item_id: usize,
// cx: &mut ViewContext<Self>,
// ) -> Task<Result<()>> {
// let item_ids: Vec<_> = self
// .items()
// .take_while(|item| item.id() != item_id)
// .map(|item| item.id())
// .collect();
// self.close_items(cx, SaveIntent::Close, move |item_id| {
// item_ids.contains(&item_id)
// })
// }
// pub fn close_items_to_the_right(
// &mut self,
// _: &CloseItemsToTheRight,
// cx: &mut ViewContext<Self>,
// ) -> Option<Task<Result<()>>> {
// if self.items.is_empty() {
// return None;
// }
// let active_item_id = self.items[self.active_item_index].id();
// Some(self.close_items_to_the_right_by_id(active_item_id, cx))
// }
// pub fn close_items_to_the_right_by_id(
// &mut self,
// item_id: usize,
// cx: &mut ViewContext<Self>,
// ) -> Task<Result<()>> {
// let item_ids: Vec<_> = self
// .items()
// .rev()
// .take_while(|item| item.id() != item_id)
// .map(|item| item.id())
// .collect();
// self.close_items(cx, SaveIntent::Close, move |item_id| {
// item_ids.contains(&item_id)
// })
// }
// pub fn close_all_items(
// &mut self,
// action: &CloseAllItems,
// cx: &mut ViewContext<Self>,
// ) -> Option<Task<Result<()>>> {
// if self.items.is_empty() {
// return None;
// }
// pub fn close_clean_items(
// &mut self,
// _: &CloseCleanItems,
// cx: &mut ViewContext<Self>,
// ) -> Option<Task<Result<()>>> {
// let item_ids: Vec<_> = self
// .items()
// .filter(|item| !item.is_dirty(cx))
// .map(|item| item.id())
// .collect();
// Some(self.close_items(cx, SaveIntent::Close, move |item_id| {
// item_ids.contains(&item_id)
// }))
// }
// pub fn close_items_to_the_left(
// &mut self,
// _: &CloseItemsToTheLeft,
// cx: &mut ViewContext<Self>,
// ) -> Option<Task<Result<()>>> {
// if self.items.is_empty() {
// return None;
// }
// let active_item_id = self.items[self.active_item_index].id();
// Some(self.close_items_to_the_left_by_id(active_item_id, cx))
// }
// pub fn close_items_to_the_left_by_id(
// &mut self,
// item_id: usize,
// cx: &mut ViewContext<Self>,
// ) -> Task<Result<()>> {
// let item_ids: Vec<_> = self
// .items()
// .take_while(|item| item.id() != item_id)
// .map(|item| item.id())
// .collect();
// self.close_items(cx, SaveIntent::Close, move |item_id| {
// item_ids.contains(&item_id)
// })
// }
// pub fn close_items_to_the_right(
// &mut self,
// _: &CloseItemsToTheRight,
// cx: &mut ViewContext<Self>,
// ) -> Option<Task<Result<()>>> {
// if self.items.is_empty() {
// return None;
// }
// let active_item_id = self.items[self.active_item_index].id();
// Some(self.close_items_to_the_right_by_id(active_item_id, cx))
// }
// pub fn close_items_to_the_right_by_id(
// &mut self,
// item_id: usize,
// cx: &mut ViewContext<Self>,
// ) -> Task<Result<()>> {
// let item_ids: Vec<_> = self
// .items()
// .rev()
// .take_while(|item| item.id() != item_id)
// .map(|item| item.id())
// .collect();
// self.close_items(cx, SaveIntent::Close, move |item_id| {
// item_ids.contains(&item_id)
// })
// }
// pub fn close_all_items(
// &mut self,
// action: &CloseAllItems,
// cx: &mut ViewContext<Self>,
// ) -> Option<Task<Result<()>>> {
// if self.items.is_empty() {
// return None;
// }
// Some(
// self.close_items(cx, action.save_intent.unwrap_or(SaveIntent::Close), |_| {
// true
// }),
// )
// }
// Some(
// self.close_items(cx, action.save_intent.unwrap_or(SaveIntent::Close), |_| {
// true
// }),
// )
// }
// pub(super) fn file_names_for_prompt(
// items: &mut dyn Iterator<Item = &Box<dyn ItemHandle>>,
@ -1156,28 +1163,29 @@ impl Pane {
// Ok(true)
// }
// fn can_autosave_item(item: &dyn ItemHandle, cx: &AppContext) -> bool {
// let is_deleted = item.project_entry_ids(cx).is_empty();
// item.is_dirty(cx) && !item.has_conflict(cx) && item.can_save(cx) && !is_deleted
// }
fn can_autosave_item(item: &dyn ItemHandle, cx: &AppContext) -> bool {
let is_deleted = item.project_entry_ids(cx).is_empty();
item.is_dirty(cx) && !item.has_conflict(cx) && item.can_save(cx) && !is_deleted
}
// pub fn autosave_item(
// item: &dyn ItemHandle,
// project: Model<Project>,
// cx: &mut WindowContext,
// ) -> Task<Result<()>> {
// if Self::can_autosave_item(item, cx) {
// item.save(project, cx)
// } else {
// Task::ready(Ok(()))
// }
// }
pub fn autosave_item(
item: &dyn ItemHandle,
project: Model<Project>,
cx: &mut WindowContext,
) -> Task<Result<()>> {
if Self::can_autosave_item(item, cx) {
item.save(project, cx)
} else {
Task::ready(Ok(()))
}
}
// pub fn focus_active_item(&mut self, cx: &mut ViewContext<Self>) {
// if let Some(active_item) = self.active_item() {
// cx.focus(active_item.as_any());
// }
// }
pub fn focus_active_item(&mut self, cx: &mut ViewContext<Self>) {
todo!();
// if let Some(active_item) = self.active_item() {
// cx.focus(active_item.as_any());
// }
}
// pub fn split(&mut self, direction: SplitDirection, cx: &mut ViewContext<Self>) {
// cx.emit(Event::Split(direction));
@ -1979,7 +1987,7 @@ impl NavHistory {
cx: &AppContext,
mut f: impl FnMut(&NavigationEntry, (ProjectPath, Option<PathBuf>)),
) {
let borrowed_history = self.0.borrow();
let borrowed_history = self.0.lock();
borrowed_history
.forward_stack
.iter()
@ -1990,7 +1998,7 @@ impl NavHistory {
borrowed_history.paths_by_item.get(&entry.item.id())
{
f(entry, project_and_abs_path.clone());
} else if let Some(item) = entry.item.upgrade(cx) {
} else if let Some(item) = entry.item.upgrade() {
if let Some(path) = item.project_path(cx) {
f(entry, (path, None));
}
@ -1999,23 +2007,23 @@ impl NavHistory {
}
pub fn set_mode(&mut self, mode: NavigationMode) {
self.0.borrow_mut().mode = mode;
self.0.lock().mode = mode;
}
pub fn mode(&self) -> NavigationMode {
self.0.borrow().mode
self.0.lock().mode
}
pub fn disable(&mut self) {
self.0.borrow_mut().mode = NavigationMode::Disabled;
self.0.lock().mode = NavigationMode::Disabled;
}
pub fn enable(&mut self) {
self.0.borrow_mut().mode = NavigationMode::Normal;
self.0.lock().mode = NavigationMode::Normal;
}
pub fn pop(&mut self, mode: NavigationMode, cx: &mut WindowContext) -> Option<NavigationEntry> {
let mut state = self.0.borrow_mut();
let mut state = self.0.lock();
let entry = match mode {
NavigationMode::Normal | NavigationMode::Disabled | NavigationMode::ClosingItem => {
return None
@ -2034,10 +2042,10 @@ impl NavHistory {
pub fn push<D: 'static + Any>(
&mut self,
data: Option<D>,
item: Rc<dyn WeakItemHandle>,
item: Arc<dyn WeakItemHandle>,
cx: &mut WindowContext,
) {
let state = &mut *self.0.borrow_mut();
let state = &mut *self.0.lock();
match state.mode {
NavigationMode::Disabled => {}
NavigationMode::Normal | NavigationMode::ReopeningClosedItem => {
@ -2086,7 +2094,7 @@ impl NavHistory {
}
pub fn remove_item(&mut self, item_id: usize) {
let mut state = self.0.borrow_mut();
let mut state = self.0.lock();
state.paths_by_item.remove(&item_id);
state
.backward_stack
@ -2100,19 +2108,19 @@ impl NavHistory {
}
pub fn path_for_item(&self, item_id: usize) -> Option<(ProjectPath, Option<PathBuf>)> {
self.0.borrow().paths_by_item.get(&item_id).cloned()
self.0.lock().paths_by_item.get(&item_id).cloned()
}
}
// impl NavHistoryState {
// pub fn did_update(&self, cx: &mut WindowContext) {
// if let Some(pane) = self.pane.upgrade(cx) {
// cx.defer(move |cx| {
// pane.update(cx, |pane, cx| pane.history_updated(cx));
// });
// }
// }
// }
impl NavHistoryState {
pub fn did_update(&self, cx: &mut WindowContext) {
if let Some(pane) = self.pane.upgrade() {
cx.defer(move |cx| {
pane.update(cx, |pane, cx| pane.history_updated(cx));
});
}
}
}
// pub struct PaneBackdrop<V> {
// child_view: usize,

View file

@ -1,7 +1,7 @@
use crate::ItemHandle;
use gpui2::{AppContext, EventEmitter, View, ViewContext, WindowContext};
use gpui2::{AnyView, AppContext, EventEmitter, Render, View, ViewContext, WindowContext};
pub trait ToolbarItemView: EventEmitter + Sized {
pub trait ToolbarItemView: Render + EventEmitter {
fn set_active_pane_item(
&mut self,
active_pane_item: Option<&dyn crate::ItemHandle>,
@ -22,14 +22,14 @@ pub trait ToolbarItemView: EventEmitter + Sized {
/// Number of times toolbar's height will be repeated to get the effective height.
/// Useful when multiple rows one under each other are needed.
/// The rows have the same width and act as a whole when reacting to resizes and similar events.
fn row_count(&self, _cx: &ViewContext<Self>) -> usize {
fn row_count(&self, _cx: &WindowContext) -> usize {
1
}
}
trait ToolbarItemViewHandle {
trait ToolbarItemViewHandle: Send {
fn id(&self) -> usize;
// fn as_any(&self) -> &AnyViewHandle; todo!()
fn to_any(&self) -> AnyView;
fn set_active_pane_item(
&self,
active_pane_item: Option<&dyn ItemHandle>,
@ -249,7 +249,7 @@ impl Toolbar {
pub fn item_of_type<T: ToolbarItemView>(&self) -> Option<View<T>> {
self.items
.iter()
.find_map(|(item, _)| item.as_any().clone().downcast())
.find_map(|(item, _)| item.to_any().downcast().ok())
}
pub fn hidden(&self) -> bool {
@ -262,10 +262,9 @@ impl<T: ToolbarItemView> ToolbarItemViewHandle for View<T> {
self.id()
}
// todo!()
// fn as_any(&self) -> &AnyViewHandle {
// self
// }
fn to_any(&self) -> AnyView {
self.clone().into_any()
}
fn set_active_pane_item(
&self,
@ -285,7 +284,7 @@ impl<T: ToolbarItemView> ToolbarItemViewHandle for View<T> {
}
fn row_count(&self, cx: &WindowContext) -> usize {
self.read_with(cx, |this, cx| this.row_count(cx))
self.read(cx).row_count(cx)
}
}

View file

@ -36,6 +36,10 @@ use std::{
pub use toolbar::{ToolbarItemLocation, ToolbarItemView};
use util::ResultExt;
use crate::persistence::model::{
DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup,
};
// lazy_static! {
// static ref ZED_WINDOW_SIZE: Option<Vector2F> = env::var("ZED_WINDOW_SIZE")
// .ok()
@ -514,9 +518,9 @@ pub struct Workspace {
// zoomed: Option<AnyWeakViewHandle>,
// zoomed_position: Option<DockPosition>,
// center: PaneGroup,
// left_dock: View<Dock>,
// bottom_dock: View<Dock>,
// right_dock: View<Dock>,
left_dock: View<Dock>,
bottom_dock: View<Dock>,
right_dock: View<Dock>,
panes: Vec<View<Pane>>,
panes_by_item: HashMap<usize, WeakView<Pane>>,
// active_pane: View<Pane>,
@ -526,8 +530,8 @@ pub struct Workspace {
// titlebar_item: Option<AnyViewHandle>,
// notifications: Vec<(TypeId, usize, Box<dyn NotificationHandle>)>,
project: Model<Project>,
// follower_states: HashMap<View<Pane>, FollowerState>,
// last_leaders_by_pane: HashMap<WeakView<Pane>, PeerId>,
follower_states: HashMap<View<Pane>, FollowerState>,
last_leaders_by_pane: HashMap<WeakView<Pane>, PeerId>,
// window_edited: bool,
// active_call: Option<(ModelHandle<ActiveCall>, Vec<Subscription>)>,
// leader_updates_tx: mpsc::UnboundedSender<(PeerId, proto::UpdateFollowers)>,
@ -2613,37 +2617,33 @@ impl Workspace {
// self.start_following(leader_id, cx)
// }
// pub fn unfollow(
// &mut self,
// pane: &View<Pane>,
// cx: &mut ViewContext<Self>,
// ) -> Option<PeerId> {
// let state = self.follower_states.remove(pane)?;
// let leader_id = state.leader_id;
// for (_, item) in state.items_by_leader_view_id {
// item.set_leader_peer_id(None, cx);
// }
pub fn unfollow(&mut self, pane: &View<Pane>, cx: &mut ViewContext<Self>) -> Option<PeerId> {
let state = self.follower_states.remove(pane)?;
let leader_id = state.leader_id;
for (_, item) in state.items_by_leader_view_id {
item.set_leader_peer_id(None, cx);
}
// if self
// .follower_states
// .values()
// .all(|state| state.leader_id != state.leader_id)
// {
// let project_id = self.project.read(cx).remote_id();
// let room_id = self.active_call()?.read(cx).room()?.read(cx).id();
// self.app_state
// .client
// .send(proto::Unfollow {
// room_id,
// project_id,
// leader_id: Some(leader_id),
// })
// .log_err();
// }
if self
.follower_states
.values()
.all(|state| state.leader_id != state.leader_id)
{
let project_id = self.project.read(cx).remote_id();
let room_id = self.active_call()?.read(cx).room()?.read(cx).id();
self.app_state
.client
.send(proto::Unfollow {
room_id,
project_id,
leader_id: Some(leader_id),
})
.log_err();
}
// cx.notify();
// Some(leader_id)
// }
cx.notify();
Some(leader_id)
}
// pub fn is_being_followed(&self, peer_id: PeerId) -> bool {
// self.follower_states
@ -3210,137 +3210,134 @@ impl Workspace {
// }));
// }
// fn serialize_workspace(&self, cx: &ViewContext<Self>) {
// fn serialize_pane_handle(
// pane_handle: &View<Pane>,
// cx: &AppContext,
// ) -> SerializedPane {
// let (items, active) = {
// let pane = pane_handle.read(cx);
// let active_item_id = pane.active_item().map(|item| item.id());
// (
// pane.items()
// .filter_map(|item_handle| {
// Some(SerializedItem {
// kind: Arc::from(item_handle.serialized_item_kind()?),
// item_id: item_handle.id(),
// active: Some(item_handle.id()) == active_item_id,
// })
// })
// .collect::<Vec<_>>(),
// pane.has_focus(),
// )
// };
fn serialize_workspace(&self, cx: &ViewContext<Self>) {
fn serialize_pane_handle(pane_handle: &View<Pane>, cx: &AppContext) -> SerializedPane {
let (items, active) = {
let pane = pane_handle.read(cx);
let active_item_id = pane.active_item().map(|item| item.id());
(
pane.items()
.filter_map(|item_handle| {
Some(SerializedItem {
kind: Arc::from(item_handle.serialized_item_kind()?),
item_id: item_handle.id(),
active: Some(item_handle.id()) == active_item_id,
})
})
.collect::<Vec<_>>(),
pane.has_focus(),
)
};
// SerializedPane::new(items, active)
// }
SerializedPane::new(items, active)
}
// fn build_serialized_pane_group(
// pane_group: &Member,
// cx: &AppContext,
// ) -> SerializedPaneGroup {
// match pane_group {
// Member::Axis(PaneAxis {
// axis,
// members,
// flexes,
// bounding_boxes: _,
// }) => SerializedPaneGroup::Group {
// axis: *axis,
// children: members
// .iter()
// .map(|member| build_serialized_pane_group(member, cx))
// .collect::<Vec<_>>(),
// flexes: Some(flexes.borrow().clone()),
// },
// Member::Pane(pane_handle) => {
// SerializedPaneGroup::Pane(serialize_pane_handle(&pane_handle, cx))
// }
// }
// }
fn build_serialized_pane_group(
pane_group: &Member,
cx: &AppContext,
) -> SerializedPaneGroup {
match pane_group {
Member::Axis(PaneAxis {
axis,
members,
flexes,
bounding_boxes: _,
}) => SerializedPaneGroup::Group {
axis: *axis,
children: members
.iter()
.map(|member| build_serialized_pane_group(member, cx))
.collect::<Vec<_>>(),
flexes: Some(flexes.borrow().clone()),
},
Member::Pane(pane_handle) => {
SerializedPaneGroup::Pane(serialize_pane_handle(&pane_handle, cx))
}
}
}
// fn build_serialized_docks(this: &Workspace, cx: &ViewContext<Workspace>) -> DockStructure {
// let left_dock = this.left_dock.read(cx);
// let left_visible = left_dock.is_open();
// let left_active_panel = left_dock.visible_panel().and_then(|panel| {
// Some(
// cx.view_ui_name(panel.as_any().window(), panel.id())?
// .to_string(),
// )
// });
// let left_dock_zoom = left_dock
// .visible_panel()
// .map(|panel| panel.is_zoomed(cx))
// .unwrap_or(false);
fn build_serialized_docks(this: &Workspace, cx: &ViewContext<Workspace>) -> DockStructure {
let left_dock = this.left_dock.read(cx);
let left_visible = left_dock.is_open();
let left_active_panel = left_dock.visible_panel().and_then(|panel| {
Some(
cx.view_ui_name(panel.as_any().window(), panel.id())?
.to_string(),
)
});
let left_dock_zoom = left_dock
.visible_panel()
.map(|panel| panel.is_zoomed(cx))
.unwrap_or(false);
// let right_dock = this.right_dock.read(cx);
// let right_visible = right_dock.is_open();
// let right_active_panel = right_dock.visible_panel().and_then(|panel| {
// Some(
// cx.view_ui_name(panel.as_any().window(), panel.id())?
// .to_string(),
// )
// });
// let right_dock_zoom = right_dock
// .visible_panel()
// .map(|panel| panel.is_zoomed(cx))
// .unwrap_or(false);
let right_dock = this.right_dock.read(cx);
let right_visible = right_dock.is_open();
let right_active_panel = right_dock.visible_panel().and_then(|panel| {
Some(
cx.view_ui_name(panel.as_any().window(), panel.id())?
.to_string(),
)
});
let right_dock_zoom = right_dock
.visible_panel()
.map(|panel| panel.is_zoomed(cx))
.unwrap_or(false);
// let bottom_dock = this.bottom_dock.read(cx);
// let bottom_visible = bottom_dock.is_open();
// let bottom_active_panel = bottom_dock.visible_panel().and_then(|panel| {
// Some(
// cx.view_ui_name(panel.as_any().window(), panel.id())?
// .to_string(),
// )
// });
// let bottom_dock_zoom = bottom_dock
// .visible_panel()
// .map(|panel| panel.is_zoomed(cx))
// .unwrap_or(false);
let bottom_dock = this.bottom_dock.read(cx);
let bottom_visible = bottom_dock.is_open();
let bottom_active_panel = bottom_dock.visible_panel().and_then(|panel| {
Some(
cx.view_ui_name(panel.as_any().window(), panel.id())?
.to_string(),
)
});
let bottom_dock_zoom = bottom_dock
.visible_panel()
.map(|panel| panel.is_zoomed(cx))
.unwrap_or(false);
// DockStructure {
// left: DockData {
// visible: left_visible,
// active_panel: left_active_panel,
// zoom: left_dock_zoom,
// },
// right: DockData {
// visible: right_visible,
// active_panel: right_active_panel,
// zoom: right_dock_zoom,
// },
// bottom: DockData {
// visible: bottom_visible,
// active_panel: bottom_active_panel,
// zoom: bottom_dock_zoom,
// },
// }
// }
DockStructure {
left: DockData {
visible: left_visible,
active_panel: left_active_panel,
zoom: left_dock_zoom,
},
right: DockData {
visible: right_visible,
active_panel: right_active_panel,
zoom: right_dock_zoom,
},
bottom: DockData {
visible: bottom_visible,
active_panel: bottom_active_panel,
zoom: bottom_dock_zoom,
},
}
}
// if let Some(location) = self.location(cx) {
// // Load bearing special case:
// // - with_local_workspace() relies on this to not have other stuff open
// // when you open your log
// if !location.paths().is_empty() {
// let center_group = build_serialized_pane_group(&self.center.root, cx);
// let docks = build_serialized_docks(self, cx);
if let Some(location) = self.location(cx) {
// Load bearing special case:
// - with_local_workspace() relies on this to not have other stuff open
// when you open your log
if !location.paths().is_empty() {
let center_group = build_serialized_pane_group(&self.center.root, cx);
let docks = build_serialized_docks(self, cx);
// let serialized_workspace = SerializedWorkspace {
// id: self.database_id,
// location,
// center_group,
// bounds: Default::default(),
// display: Default::default(),
// docks,
// };
let serialized_workspace = SerializedWorkspace {
id: self.database_id,
location,
center_group,
bounds: Default::default(),
display: Default::default(),
docks,
};
// cx.background()
// .spawn(persistence::DB.save_workspace(serialized_workspace))
// .detach();
// }
// }
// }
cx.background()
.spawn(persistence::DB.save_workspace(serialized_workspace))
.detach();
}
}
}
// pub(crate) fn load_workspace(
// workspace: WeakView<Workspace>,