Detailed changes
@@ -9,11 +9,13 @@ use crate::{
GlobalPixels, GlyphId, InputEvent, LineLayout, Pixels, Point, RenderGlyphParams,
RenderImageParams, RenderSvgParams, Result, Scene, SharedString, Size,
};
-use anyhow::anyhow;
+use anyhow::{anyhow, bail};
use async_task::Runnable;
use futures::channel::oneshot;
use seahash::SeaHasher;
use serde::{Deserialize, Serialize};
+use sqlez::bindable::{Bind, Column, StaticColumnCount};
+use sqlez::statement::Statement;
use std::borrow::Cow;
use std::hash::{Hash, Hasher};
use std::time::Duration;
@@ -368,6 +370,65 @@ pub enum WindowBounds {
Fixed(Bounds<GlobalPixels>),
}
+impl StaticColumnCount for WindowBounds {
+ fn column_count() -> usize {
+ 5
+ }
+}
+
+impl Bind for WindowBounds {
+ fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
+ let (region, next_index) = match self {
+ WindowBounds::Fullscreen => {
+ let next_index = statement.bind(&"Fullscreen", start_index)?;
+ (None, next_index)
+ }
+ WindowBounds::Maximized => {
+ let next_index = statement.bind(&"Maximized", start_index)?;
+ (None, next_index)
+ }
+ WindowBounds::Fixed(region) => {
+ let next_index = statement.bind(&"Fixed", start_index)?;
+ (Some(*region), next_index)
+ }
+ };
+
+ todo!()
+ // statement.bind(
+ // ®ion.map(|region| {
+ // (
+ // region.min_x(),
+ // region.min_y(),
+ // region.width(),
+ // region.height(),
+ // )
+ // }),
+ // next_index,
+ // )
+ }
+}
+
+impl Column for WindowBounds {
+ fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
+ let (window_state, next_index) = String::column(statement, start_index)?;
+ let bounds = match window_state.as_str() {
+ "Fullscreen" => WindowBounds::Fullscreen,
+ "Maximized" => WindowBounds::Maximized,
+ "Fixed" => {
+ // let ((x, y, width, height), _) = Column::column(statement, next_index)?;
+ // WindowBounds::Fixed(RectF::new(
+ // Vector2F::new(x, y),
+ // Vector2F::new(width, height),
+ // ))
+ todo!()
+ }
+ _ => bail!("Window State did not have a valid string"),
+ };
+
+ Ok((bounds, next_index + 4))
+ }
+}
+
#[derive(Copy, Clone, Debug)]
pub enum WindowAppearance {
Light,
@@ -253,9 +253,9 @@ pub trait ItemHandle: 'static + Send {
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,
+ &mut self,
cx: &mut AppContext,
- callback: Box<dyn FnOnce(&mut AppContext) + Send>,
+ callback: Box<dyn FnMut(&mut AppContext) + Send>,
) -> gpui2::Subscription;
fn to_searchable_item_handle(&self, cx: &AppContext) -> Option<Box<dyn SearchableItemHandle>>;
fn breadcrumb_location(&self, cx: &AppContext) -> ToolbarItemLocation;
@@ -571,9 +571,9 @@ impl<T: Item> ItemHandle for View<T> {
}
fn on_release(
- &self,
+ &mut self,
cx: &mut AppContext,
- callback: Box<dyn FnOnce(&mut AppContext) + Send>,
+ mut callback: Box<dyn FnMut(&mut AppContext) + Send>,
) -> gpui2::Subscription {
cx.observe_release(self, move |_, cx| callback(cx))
}
@@ -1,7 +1,11 @@
use crate::{AppState, FollowerState, Pane, Workspace};
-use anyhow::{anyhow, Result};
+use anyhow::{anyhow, bail, Result};
use call2::ActiveCall;
use collections::HashMap;
+use db2::sqlez::{
+ bindable::{Bind, Column, StaticColumnCount},
+ statement::Statement,
+};
use gpui2::{point, size, AnyElement, AnyView, Bounds, Model, Pixels, Point, View, ViewContext};
use parking_lot::Mutex;
use project2::Project;
@@ -13,12 +17,38 @@ const HANDLE_HITBOX_SIZE: f32 = 4.0;
const HORIZONTAL_MIN_SIZE: f32 = 80.;
const VERTICAL_MIN_SIZE: f32 = 100.;
-#[derive(Copy, Clone, PartialEq, Eq)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Axis {
Vertical,
Horizontal,
}
+impl StaticColumnCount for Axis {}
+impl Bind for Axis {
+ fn bind(&self, statement: &Statement, start_index: i32) -> anyhow::Result<i32> {
+ match self {
+ Axis::Horizontal => "Horizontal",
+ Axis::Vertical => "Vertical",
+ }
+ .bind(statement, start_index)
+ }
+}
+
+impl Column for Axis {
+ fn column(statement: &mut Statement, start_index: i32) -> anyhow::Result<(Self, i32)> {
+ String::column(statement, start_index).and_then(|(axis_text, next_index)| {
+ Ok((
+ match axis_text.as_str() {
+ "Horizontal" => Axis::Horizontal,
+ "Vertical" => Axis::Vertical,
+ _ => bail!("Stored serialized item kind is incorrect"),
+ },
+ next_index,
+ ))
+ })
+ }
+}
+
#[derive(Clone, PartialEq)]
pub struct PaneGroup {
pub(crate) root: Member,
@@ -7,7 +7,7 @@ use db2::sqlez::{
bindable::{Bind, Column, StaticColumnCount},
statement::Statement,
};
-use gpui2::{AsyncAppContext, AsyncWindowContext, Model, Task, View, WeakView, WindowBounds};
+use gpui2::{AsyncWindowContext, Model, Task, View, WeakView, WindowBounds};
use project2::Project;
use std::{
path::{Path, PathBuf},
@@ -232,7 +232,7 @@ impl SerializedPane {
pane: &WeakView<Pane>,
workspace_id: WorkspaceId,
workspace: &WeakView<Workspace>,
- cx: &mut AsyncAppContext,
+ cx: &mut AsyncWindowContext,
) -> Result<Vec<Option<Box<dyn ItemHandle>>>> {
let mut items = Vec::new();
let mut active_item_index = None;
@@ -491,7 +491,7 @@ impl DelayedDebouncedEditAction {
self.cancel_channel = Some(sender);
let previous_task = self.task.take();
- self.task = Some(cx.spawn(|workspace, mut cx| async move {
+ self.task = Some(cx.spawn(move |workspace, mut cx| async move {
let mut timer = cx.executor().timer(delay).fuse();
if let Some(previous_task) = previous_task {
previous_task.await;
@@ -765,47 +765,47 @@ impl Workspace {
// }
// }
- // fn new_local(
- // abs_paths: Vec<PathBuf>,
- // app_state: Arc<AppState>,
- // requesting_window: Option<WindowHandle<Workspace>>,
- // cx: &mut AppContext,
- // ) -> Task<(
- // WeakView<Workspace>,
- // Vec<Option<Result<Box<dyn ItemHandle>, anyhow::Error>>>,
- // )> {
- // let project_handle = Project::local(
- // app_state.client.clone(),
- // app_state.node_runtime.clone(),
- // app_state.user_store.clone(),
- // app_state.languages.clone(),
- // app_state.fs.clone(),
- // cx,
- // );
-
- // cx.spawn(|mut cx| async move {
- // let serialized_workspace = persistence::DB.workspace_for_roots(&abs_paths.as_slice());
-
- // let paths_to_open = Arc::new(abs_paths);
-
- // // Get project paths for all of the abs_paths
- // let mut worktree_roots: HashSet<Arc<Path>> = Default::default();
- // let mut project_paths: Vec<(PathBuf, Option<ProjectPath>)> =
- // Vec::with_capacity(paths_to_open.len());
- // for path in paths_to_open.iter().cloned() {
- // if let Some((worktree, project_entry)) = cx
- // .update(|cx| {
- // Workspace::project_path_for_path(project_handle.clone(), &path, true, cx)
- // })
- // .await
- // .log_err()
- // {
- // worktree_roots.insert(worktree.read_with(&mut cx, |tree, _| tree.abs_path()));
- // project_paths.push((path, Some(project_entry)));
- // } else {
- // project_paths.push((path, None));
- // }
+ // fn new_local(
+ // abs_paths: Vec<PathBuf>,
+ // app_state: Arc<AppState>,
+ // requesting_window: Option<WindowHandle<Workspace>>,
+ // cx: &mut AppContext,
+ // ) -> Task<(
+ // WeakView<Workspace>,
+ // Vec<Option<Result<Box<dyn ItemHandle>, anyhow::Error>>>,
+ // )> {
+ // let project_handle = Project::local(
+ // app_state.client.clone(),
+ // app_state.node_runtime.clone(),
+ // app_state.user_store.clone(),
+ // app_state.languages.clone(),
+ // app_state.fs.clone(),
+ // cx,
+ // );
+
+ // cx.spawn(|mut cx| async move {
+ // let serialized_workspace = persistence::DB.workspace_for_roots(&abs_paths.as_slice());
+
+ // let paths_to_open = Arc::new(abs_paths);
+
+ // // Get project paths for all of the abs_paths
+ // let mut worktree_roots: HashSet<Arc<Path>> = Default::default();
+ // let mut project_paths: Vec<(PathBuf, Option<ProjectPath>)> =
+ // Vec::with_capacity(paths_to_open.len());
+ // for path in paths_to_open.iter().cloned() {
+ // if let Some((worktree, project_entry)) = cx
+ // .update(|cx| {
+ // Workspace::project_path_for_path(project_handle.clone(), &path, true, cx)
+ // })
+ // .await
+ // .log_err()
+ // {
+ // worktree_roots.insert(worktree.read_with(&mut cx, |tree, _| tree.abs_path()));
+ // project_paths.push((path, Some(project_entry)));
+ // } else {
+ // project_paths.push((path, None));
// }
+ // }
// let workspace_id = if let Some(serialized_workspace) = serialized_workspace.as_ref() {
// serialized_workspace.id
@@ -1470,13 +1470,13 @@ impl Workspace {
visible: bool,
cx: &mut ViewContext<Self>,
) -> Task<Vec<Option<Result<Box<dyn ItemHandle>, anyhow::Error>>>> {
- log::info!("open paths {:?}", abs_paths);
+ log::info!("open paths {abs_paths:?}");
let fs = self.app_state.fs.clone();
// Sort the paths to ensure we add worktrees for parents before their children.
abs_paths.sort_unstable();
- cx.spawn(|this, mut cx| async move {
+ cx.spawn(move |this, mut cx| async move {
let mut tasks = Vec::with_capacity(abs_paths.len());
for abs_path in &abs_paths {
let project_path = match this
@@ -1495,45 +1495,41 @@ impl Workspace {
};
let this = this.clone();
- let task = cx.spawn(|mut cx| {
- let fs = fs.clone();
- let abs_path = abs_path.clone();
- async move {
- let (worktree, project_path) = project_path?;
- if fs.is_file(&abs_path).await {
- Some(
- this.update(&mut cx, |this, cx| {
- this.open_path(project_path, None, true, cx)
- })
- .log_err()?
- .await,
- )
- } else {
- this.update(&mut cx, |workspace, cx| {
- let worktree = worktree.read(cx);
- let worktree_abs_path = worktree.abs_path();
- let entry_id = if abs_path == worktree_abs_path.as_ref() {
- worktree.root_entry()
- } else {
- abs_path
- .strip_prefix(worktree_abs_path.as_ref())
- .ok()
- .and_then(|relative_path| {
- worktree.entry_for_path(relative_path)
- })
- }
- .map(|entry| entry.id);
- if let Some(entry_id) = entry_id {
- workspace.project.update(cx, |_, cx| {
- cx.emit(project2::Event::ActiveEntryChanged(Some(
- entry_id,
- )));
- })
- }
+ let abs_path = abs_path.clone();
+ let fs = fs.clone();
+ let task = cx.spawn(move |mut cx| async move {
+ let (worktree, project_path) = project_path?;
+ if fs.is_file(&abs_path).await {
+ Some(
+ this.update(&mut cx, |this, cx| {
+ this.open_path(project_path, None, true, cx)
})
- .log_err()?;
- None
- }
+ .log_err()?
+ .await,
+ )
+ } else {
+ this.update(&mut cx, |workspace, cx| {
+ let worktree = worktree.read(cx);
+ let worktree_abs_path = worktree.abs_path();
+ let entry_id = if abs_path == worktree_abs_path.as_ref() {
+ worktree.root_entry()
+ } else {
+ abs_path
+ .strip_prefix(worktree_abs_path.as_ref())
+ .ok()
+ .and_then(|relative_path| {
+ worktree.entry_for_path(relative_path)
+ })
+ }
+ .map(|entry| entry.id);
+ if let Some(entry_id) = entry_id {
+ workspace.project.update(cx, |_, cx| {
+ cx.emit(project2::Event::ActiveEntryChanged(Some(entry_id)));
+ })
+ }
+ })
+ .log_err()?;
+ None
}
});
tasks.push(task);
@@ -1572,7 +1568,7 @@ impl Workspace {
let entry = project.update(cx, |project, cx| {
project.find_or_create_local_worktree(abs_path, visible, cx)
});
- cx.spawn(|cx| async move {
+ cx.spawn(|mut cx| async move {
let (worktree, path) = entry.await?;
let worktree_id = worktree.update(&mut cx, |t, _| t.id())?;
Ok((
@@ -2043,7 +2039,7 @@ impl Workspace {
});
let task = self.load_path(path.into(), cx);
- cx.spawn(|_, mut cx| async move {
+ cx.spawn(move |_, mut cx| async move {
let (project_entry_id, build_item) = task.await?;
pane.update(&mut cx, |pane, cx| {
pane.open_item(project_entry_id, focus_item, cx, build_item)
@@ -3220,7 +3216,7 @@ impl Workspace {
// }));
// }
- fn serialize_workspace(&self, cx: &ViewContext<Self>) {
+ fn serialize_workspace(&self, cx: &mut ViewContext<Self>) {
fn serialize_pane_handle(pane_handle: &View<Pane>, cx: &AppContext) -> SerializedPane {
let (items, active) = {
let pane = pane_handle.read(cx);
@@ -3266,7 +3262,10 @@ impl Workspace {
}
}
- fn build_serialized_docks(this: &Workspace, cx: &ViewContext<Workspace>) -> DockStructure {
+ fn build_serialized_docks(
+ this: &Workspace,
+ cx: &mut 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| {
@@ -4313,9 +4312,9 @@ pub fn open_paths(
> {
let app_state = app_state.clone();
let abs_paths = abs_paths.to_vec();
- cx.spawn(|mut cx| async move {
+ cx.spawn(move |mut cx| async move {
// Open paths in existing workspace if possible
- let existing = activate_workspace_for_project(&mut cx, |project, cx| {
+ let existing = activate_workspace_for_project(&mut cx, move |project, cx| {
project.contains_paths(&abs_paths, cx)
})
.await;
@@ -4330,12 +4329,12 @@ pub fn open_paths(
// ))
todo!()
} else {
- todo!()
// Ok(cx
// .update(|cx| {
// Workspace::new_local(abs_paths, app_state.clone(), requesting_window, cx)
// })
// .await)
+ todo!()
}
})
}