use crate::{Axis, WorkspaceId}; use anyhow::{Context, Result}; use db2::sqlez::{ bindable::{Bind, Column, StaticColumnCount}, statement::Statement, }; use gpui2::WindowBounds; use std::{ path::{Path, PathBuf}, sync::Arc, }; use uuid::Uuid; #[derive(Debug, Clone, PartialEq, Eq)] pub struct WorkspaceLocation(Arc>); impl WorkspaceLocation { pub fn paths(&self) -> Arc> { self.0.clone() } } impl, T: IntoIterator> From for WorkspaceLocation { fn from(iterator: T) -> Self { let mut roots = iterator .into_iter() .map(|p| p.as_ref().to_path_buf()) .collect::>(); roots.sort(); Self(Arc::new(roots)) } } impl StaticColumnCount for WorkspaceLocation {} impl Bind for &WorkspaceLocation { fn bind(&self, statement: &Statement, start_index: i32) -> Result { bincode::serialize(&self.0) .expect("Bincode serialization of paths should not fail") .bind(statement, start_index) } } impl Column for WorkspaceLocation { fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> { let blob = statement.column_blob(start_index)?; Ok(( WorkspaceLocation(bincode::deserialize(blob).context("Bincode failed")?), start_index + 1, )) } } #[derive(PartialEq, Clone)] pub struct SerializedWorkspace { pub id: WorkspaceId, pub location: WorkspaceLocation, pub center_group: SerializedPaneGroup, pub bounds: Option, pub display: Option, pub docks: DockStructure, } #[derive(Debug, PartialEq, Clone, Default)] pub struct DockStructure { pub(crate) left: DockData, pub(crate) right: DockData, pub(crate) bottom: DockData, } impl Column for DockStructure { fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> { let (left, next_index) = DockData::column(statement, start_index)?; let (right, next_index) = DockData::column(statement, next_index)?; let (bottom, next_index) = DockData::column(statement, next_index)?; Ok(( DockStructure { left, right, bottom, }, next_index, )) } } impl Bind for DockStructure { fn bind(&self, statement: &Statement, start_index: i32) -> Result { let next_index = statement.bind(&self.left, start_index)?; let next_index = statement.bind(&self.right, next_index)?; statement.bind(&self.bottom, next_index) } } #[derive(Debug, PartialEq, Clone, Default)] pub struct DockData { pub(crate) visible: bool, pub(crate) active_panel: Option, pub(crate) zoom: bool, } impl Column for DockData { fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> { let (visible, next_index) = Option::::column(statement, start_index)?; let (active_panel, next_index) = Option::::column(statement, next_index)?; let (zoom, next_index) = Option::::column(statement, next_index)?; Ok(( DockData { visible: visible.unwrap_or(false), active_panel, zoom: zoom.unwrap_or(false), }, next_index, )) } } impl Bind for DockData { fn bind(&self, statement: &Statement, start_index: i32) -> Result { let next_index = statement.bind(&self.visible, start_index)?; let next_index = statement.bind(&self.active_panel, next_index)?; statement.bind(&self.zoom, next_index) } } #[derive(PartialEq, Clone)] pub enum SerializedPaneGroup { Group { axis: Axis, flexes: Option>, children: Vec, }, Pane(SerializedPane), } #[cfg(test)] impl Default for SerializedPaneGroup { fn default() -> Self { Self::Pane(SerializedPane { children: vec![SerializedItem::default()], active: false, }) } } // impl SerializedPaneGroup { // #[async_recursion(?Send)] // pub(crate) async fn deserialize( // self, // project: &Model, // workspace_id: WorkspaceId, // workspace: WeakView, // cx: &mut AsyncAppContext, // ) -> Option<(Member, Option>, Vec>>)> { // match self { // SerializedPaneGroup::Group { // axis, // children, // flexes, // } => { // let mut current_active_pane = None; // let mut members = Vec::new(); // let mut items = Vec::new(); // for child in children { // if let Some((new_member, active_pane, new_items)) = child // .deserialize(project, workspace_id, workspace, cx) // .await // { // members.push(new_member); // items.extend(new_items); // current_active_pane = current_active_pane.or(active_pane); // } // } // if members.is_empty() { // return None; // } // if members.len() == 1 { // return Some((members.remove(0), current_active_pane, items)); // } // Some(( // Member::Axis(PaneAxis::load(axis, members, flexes)), // current_active_pane, // items, // )) // } // SerializedPaneGroup::Pane(serialized_pane) => { // let pane = workspace // .update(cx, |workspace, cx| workspace.add_pane(cx).downgrade()) // .log_err()?; // let active = serialized_pane.active; // let new_items = serialized_pane // .deserialize_to(project, &pane, workspace_id, workspace, cx) // .await // .log_err()?; // // todo!(); // // if pane.update(cx, |pane, _| pane.items_len() != 0).log_err()? { // // let pane = pane.upgrade()?; // // Some((Member::Pane(pane.clone()), active.then(|| pane), new_items)) // // } else { // // let pane = pane.upgrade()?; // // workspace // // .update(cx, |workspace, cx| workspace.force_remove_pane(&pane, cx)) // // .log_err()?; // // None // // } // None // } // } // } // } #[derive(Debug, PartialEq, Eq, Default, Clone)] pub struct SerializedPane { pub(crate) active: bool, pub(crate) children: Vec, } impl SerializedPane { pub fn new(children: Vec, active: bool) -> Self { SerializedPane { children, active } } // pub async fn deserialize_to( // &self, // _project: &Model, // _pane: &WeakView, // _workspace_id: WorkspaceId, // _workspace: WindowHandle, // _cx: &mut AsyncAppContext, // ) -> Result>>> { // anyhow::bail!("todo!()") // // todo!() // // let mut items = Vec::new(); // // let mut active_item_index = None; // // for (index, item) in self.children.iter().enumerate() { // // let project = project.clone(); // // let item_handle = pane // // .update(cx, |_, cx| { // // if let Some(deserializer) = cx.global::().get(&item.kind) { // // deserializer(project, workspace, workspace_id, item.item_id, cx) // // } else { // // Task::ready(Err(anyhow::anyhow!( // // "Deserializer does not exist for item kind: {}", // // item.kind // // ))) // // } // // })? // // .await // // .log_err(); // // items.push(item_handle.clone()); // // if let Some(item_handle) = item_handle { // // pane.update(cx, |pane, cx| { // // pane.add_item(item_handle.clone(), true, true, None, cx); // // })?; // // } // // if item.active { // // active_item_index = Some(index); // // } // // } // // if let Some(active_item_index) = active_item_index { // // pane.update(cx, |pane, cx| { // // pane.activate_item(active_item_index, false, false, cx); // // })?; // // } // // anyhow::Ok(items) // } } pub type GroupId = i64; pub type PaneId = i64; pub type ItemId = usize; #[derive(Debug, PartialEq, Eq, Clone)] pub struct SerializedItem { pub kind: Arc, pub item_id: ItemId, pub active: bool, } // impl SerializedItem { // pub fn new(kind: impl AsRef, item_id: ItemId, active: bool) -> Self { // Self { // kind: Arc::from(kind.as_ref()), // item_id, // active, // } // } // } #[cfg(test)] impl Default for SerializedItem { fn default() -> Self { SerializedItem { kind: Arc::from("Terminal"), item_id: 100000, active: false, } } } impl StaticColumnCount for SerializedItem { fn column_count() -> usize { 3 } } impl Bind for &SerializedItem { fn bind(&self, statement: &Statement, start_index: i32) -> Result { let next_index = statement.bind(&self.kind, start_index)?; let next_index = statement.bind(&self.item_id, next_index)?; statement.bind(&self.active, next_index) } } impl Column for SerializedItem { fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> { let (kind, next_index) = Arc::::column(statement, start_index)?; let (item_id, next_index) = ItemId::column(statement, next_index)?; let (active, next_index) = bool::column(statement, next_index)?; Ok(( SerializedItem { kind, item_id, active, }, next_index, )) } }