1use crate::{Axis, WorkspaceId};
2use anyhow::{Context, Result};
3use db2::sqlez::{
4 bindable::{Bind, Column, StaticColumnCount},
5 statement::Statement,
6};
7use gpui2::WindowBounds;
8use std::{
9 path::{Path, PathBuf},
10 sync::Arc,
11};
12use uuid::Uuid;
13
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct WorkspaceLocation(Arc<Vec<PathBuf>>);
16
17impl WorkspaceLocation {
18 pub fn paths(&self) -> Arc<Vec<PathBuf>> {
19 self.0.clone()
20 }
21}
22
23impl<P: AsRef<Path>, T: IntoIterator<Item = P>> From<T> for WorkspaceLocation {
24 fn from(iterator: T) -> Self {
25 let mut roots = iterator
26 .into_iter()
27 .map(|p| p.as_ref().to_path_buf())
28 .collect::<Vec<_>>();
29 roots.sort();
30 Self(Arc::new(roots))
31 }
32}
33
34impl StaticColumnCount for WorkspaceLocation {}
35impl Bind for &WorkspaceLocation {
36 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
37 bincode::serialize(&self.0)
38 .expect("Bincode serialization of paths should not fail")
39 .bind(statement, start_index)
40 }
41}
42
43impl Column for WorkspaceLocation {
44 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
45 let blob = statement.column_blob(start_index)?;
46 Ok((
47 WorkspaceLocation(bincode::deserialize(blob).context("Bincode failed")?),
48 start_index + 1,
49 ))
50 }
51}
52
53#[derive(PartialEq, Clone)]
54pub struct SerializedWorkspace {
55 pub id: WorkspaceId,
56 pub location: WorkspaceLocation,
57 pub center_group: SerializedPaneGroup,
58 pub bounds: Option<WindowBounds>,
59 pub display: Option<Uuid>,
60 pub docks: DockStructure,
61}
62
63#[derive(Debug, PartialEq, Clone, Default)]
64pub struct DockStructure {
65 pub(crate) left: DockData,
66 pub(crate) right: DockData,
67 pub(crate) bottom: DockData,
68}
69
70impl Column for DockStructure {
71 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
72 let (left, next_index) = DockData::column(statement, start_index)?;
73 let (right, next_index) = DockData::column(statement, next_index)?;
74 let (bottom, next_index) = DockData::column(statement, next_index)?;
75 Ok((
76 DockStructure {
77 left,
78 right,
79 bottom,
80 },
81 next_index,
82 ))
83 }
84}
85
86impl Bind for DockStructure {
87 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
88 let next_index = statement.bind(&self.left, start_index)?;
89 let next_index = statement.bind(&self.right, next_index)?;
90 statement.bind(&self.bottom, next_index)
91 }
92}
93
94#[derive(Debug, PartialEq, Clone, Default)]
95pub struct DockData {
96 pub(crate) visible: bool,
97 pub(crate) active_panel: Option<String>,
98 pub(crate) zoom: bool,
99}
100
101impl Column for DockData {
102 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
103 let (visible, next_index) = Option::<bool>::column(statement, start_index)?;
104 let (active_panel, next_index) = Option::<String>::column(statement, next_index)?;
105 let (zoom, next_index) = Option::<bool>::column(statement, next_index)?;
106 Ok((
107 DockData {
108 visible: visible.unwrap_or(false),
109 active_panel,
110 zoom: zoom.unwrap_or(false),
111 },
112 next_index,
113 ))
114 }
115}
116
117impl Bind for DockData {
118 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
119 let next_index = statement.bind(&self.visible, start_index)?;
120 let next_index = statement.bind(&self.active_panel, next_index)?;
121 statement.bind(&self.zoom, next_index)
122 }
123}
124
125#[derive(PartialEq, Clone)]
126pub enum SerializedPaneGroup {
127 Group {
128 axis: Axis,
129 flexes: Option<Vec<f32>>,
130 children: Vec<SerializedPaneGroup>,
131 },
132 Pane(SerializedPane),
133}
134
135#[cfg(test)]
136impl Default for SerializedPaneGroup {
137 fn default() -> Self {
138 Self::Pane(SerializedPane {
139 children: vec![SerializedItem::default()],
140 active: false,
141 })
142 }
143}
144
145// impl SerializedPaneGroup {
146// #[async_recursion(?Send)]
147// pub(crate) async fn deserialize(
148// self,
149// project: &Model<Project>,
150// workspace_id: WorkspaceId,
151// workspace: WeakView<Workspace>,
152// cx: &mut AsyncAppContext,
153// ) -> Option<(Member, Option<View<Pane>>, Vec<Option<Box<dyn ItemHandle>>>)> {
154// match self {
155// SerializedPaneGroup::Group {
156// axis,
157// children,
158// flexes,
159// } => {
160// let mut current_active_pane = None;
161// let mut members = Vec::new();
162// let mut items = Vec::new();
163// for child in children {
164// if let Some((new_member, active_pane, new_items)) = child
165// .deserialize(project, workspace_id, workspace, cx)
166// .await
167// {
168// members.push(new_member);
169// items.extend(new_items);
170// current_active_pane = current_active_pane.or(active_pane);
171// }
172// }
173
174// if members.is_empty() {
175// return None;
176// }
177
178// if members.len() == 1 {
179// return Some((members.remove(0), current_active_pane, items));
180// }
181
182// Some((
183// Member::Axis(PaneAxis::load(axis, members, flexes)),
184// current_active_pane,
185// items,
186// ))
187// }
188// SerializedPaneGroup::Pane(serialized_pane) => {
189// let pane = workspace
190// .update(cx, |workspace, cx| workspace.add_pane(cx).downgrade())
191// .log_err()?;
192// let active = serialized_pane.active;
193// let new_items = serialized_pane
194// .deserialize_to(project, &pane, workspace_id, workspace, cx)
195// .await
196// .log_err()?;
197
198// // todo!();
199// // if pane.update(cx, |pane, _| pane.items_len() != 0).log_err()? {
200// // let pane = pane.upgrade()?;
201// // Some((Member::Pane(pane.clone()), active.then(|| pane), new_items))
202// // } else {
203// // let pane = pane.upgrade()?;
204// // workspace
205// // .update(cx, |workspace, cx| workspace.force_remove_pane(&pane, cx))
206// // .log_err()?;
207// // None
208// // }
209// None
210// }
211// }
212// }
213// }
214
215#[derive(Debug, PartialEq, Eq, Default, Clone)]
216pub struct SerializedPane {
217 pub(crate) active: bool,
218 pub(crate) children: Vec<SerializedItem>,
219}
220
221impl SerializedPane {
222 pub fn new(children: Vec<SerializedItem>, active: bool) -> Self {
223 SerializedPane { children, active }
224 }
225
226 // pub async fn deserialize_to(
227 // &self,
228 // _project: &Model<Project>,
229 // _pane: &WeakView<Pane>,
230 // _workspace_id: WorkspaceId,
231 // _workspace: WindowHandle<Workspace>,
232 // _cx: &mut AsyncAppContext,
233 // ) -> Result<Vec<Option<Box<dyn ItemHandle>>>> {
234 // anyhow::bail!("todo!()")
235 // // todo!()
236 // // let mut items = Vec::new();
237 // // let mut active_item_index = None;
238 // // for (index, item) in self.children.iter().enumerate() {
239 // // let project = project.clone();
240 // // let item_handle = pane
241 // // .update(cx, |_, cx| {
242 // // if let Some(deserializer) = cx.global::<ItemDeserializers>().get(&item.kind) {
243 // // deserializer(project, workspace, workspace_id, item.item_id, cx)
244 // // } else {
245 // // Task::ready(Err(anyhow::anyhow!(
246 // // "Deserializer does not exist for item kind: {}",
247 // // item.kind
248 // // )))
249 // // }
250 // // })?
251 // // .await
252 // // .log_err();
253
254 // // items.push(item_handle.clone());
255
256 // // if let Some(item_handle) = item_handle {
257 // // pane.update(cx, |pane, cx| {
258 // // pane.add_item(item_handle.clone(), true, true, None, cx);
259 // // })?;
260 // // }
261
262 // // if item.active {
263 // // active_item_index = Some(index);
264 // // }
265 // // }
266
267 // // if let Some(active_item_index) = active_item_index {
268 // // pane.update(cx, |pane, cx| {
269 // // pane.activate_item(active_item_index, false, false, cx);
270 // // })?;
271 // // }
272
273 // // anyhow::Ok(items)
274 // }
275}
276
277pub type GroupId = i64;
278pub type PaneId = i64;
279pub type ItemId = usize;
280
281#[derive(Debug, PartialEq, Eq, Clone)]
282pub struct SerializedItem {
283 pub kind: Arc<str>,
284 pub item_id: ItemId,
285 pub active: bool,
286}
287
288// impl SerializedItem {
289// pub fn new(kind: impl AsRef<str>, item_id: ItemId, active: bool) -> Self {
290// Self {
291// kind: Arc::from(kind.as_ref()),
292// item_id,
293// active,
294// }
295// }
296// }
297
298#[cfg(test)]
299impl Default for SerializedItem {
300 fn default() -> Self {
301 SerializedItem {
302 kind: Arc::from("Terminal"),
303 item_id: 100000,
304 active: false,
305 }
306 }
307}
308
309impl StaticColumnCount for SerializedItem {
310 fn column_count() -> usize {
311 3
312 }
313}
314impl Bind for &SerializedItem {
315 fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
316 let next_index = statement.bind(&self.kind, start_index)?;
317 let next_index = statement.bind(&self.item_id, next_index)?;
318 statement.bind(&self.active, next_index)
319 }
320}
321
322impl Column for SerializedItem {
323 fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
324 let (kind, next_index) = Arc::<str>::column(statement, start_index)?;
325 let (item_id, next_index) = ItemId::column(statement, next_index)?;
326 let (active, next_index) = bool::column(statement, next_index)?;
327 Ok((
328 SerializedItem {
329 kind,
330 item_id,
331 active,
332 },
333 next_index,
334 ))
335 }
336}