model.rs

  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}