diff --git a/Cargo.lock b/Cargo.lock index 0cbd9c7b67..d4f4339d03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3066,7 +3066,6 @@ dependencies = [ "slotmap", "smallvec", "smol", - "sqlez", "sum_tree", "taffy", "thiserror", @@ -6847,7 +6846,6 @@ dependencies = [ "serde_json", "serde_json_lenient", "smallvec", - "sqlez", "toml 0.5.11", "tree-sitter", "tree-sitter-json 0.19.0", @@ -9440,6 +9438,7 @@ dependencies = [ "serde_json", "settings", "smallvec", + "sqlez", "terminal", "theme", "ui", diff --git a/crates/gpui/Cargo.toml b/crates/gpui/Cargo.toml index d654131a56..6ea3524fcc 100644 --- a/crates/gpui/Cargo.toml +++ b/crates/gpui/Cargo.toml @@ -18,7 +18,6 @@ collections = { path = "../collections" } gpui_macros = { path = "../gpui_macros" } util = { path = "../util" } sum_tree = { path = "../sum_tree" } -sqlez = { path = "../sqlez" } async-task = "4.7" backtrace = { version = "0.3", optional = true } ctor.workspace = true diff --git a/crates/gpui/src/geometry.rs b/crates/gpui/src/geometry.rs index 4d2137c257..d68ab89f6c 100644 --- a/crates/gpui/src/geometry.rs +++ b/crates/gpui/src/geometry.rs @@ -31,39 +31,6 @@ pub trait Along { fn apply_along(&self, axis: Axis, f: impl FnOnce(Self::Unit) -> Self::Unit) -> Self; } -impl sqlez::bindable::StaticColumnCount for Axis {} -impl sqlez::bindable::Bind for Axis { - fn bind( - &self, - statement: &sqlez::statement::Statement, - start_index: i32, - ) -> anyhow::Result { - match self { - Axis::Horizontal => "Horizontal", - Axis::Vertical => "Vertical", - } - .bind(statement, start_index) - } -} - -impl sqlez::bindable::Column for Axis { - fn column( - statement: &mut sqlez::statement::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, - _ => anyhow::bail!("Stored serialized item kind is incorrect"), - }, - next_index, - )) - }) - } -} - /// Describes a location in a 2D cartesian coordinate space. /// /// It holds two public fields, `x` and `y`, which represent the coordinates in the space. @@ -2296,18 +2263,6 @@ impl From for GlobalPixels { } } -impl sqlez::bindable::StaticColumnCount for GlobalPixels {} - -impl sqlez::bindable::Bind for GlobalPixels { - fn bind( - &self, - statement: &sqlez::statement::Statement, - start_index: i32, - ) -> anyhow::Result { - self.0.bind(statement, start_index) - } -} - /// Represents a length in rems, a unit based on the font-size of the window, which can be assigned with [WindowContext::set_rem_size]. /// /// Rems are used for defining lengths that are scalable and consistent across different UI elements. diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index e7ee5f9e29..0c4581904f 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -6,19 +6,17 @@ mod mac; mod test; use crate::{ - point, size, Action, AnyWindowHandle, BackgroundExecutor, Bounds, DevicePixels, Font, FontId, - FontMetrics, FontRun, ForegroundExecutor, GlobalPixels, GlyphId, InputEvent, Keymap, - LineLayout, Pixels, Point, RenderGlyphParams, RenderImageParams, RenderSvgParams, Result, - Scene, SharedString, Size, TaskLabel, + Action, AnyWindowHandle, BackgroundExecutor, Bounds, DevicePixels, Font, FontId, FontMetrics, + FontRun, ForegroundExecutor, GlobalPixels, GlyphId, InputEvent, Keymap, LineLayout, Pixels, + Point, RenderGlyphParams, RenderImageParams, RenderSvgParams, Result, Scene, SharedString, + Size, TaskLabel, }; -use anyhow::{anyhow, bail}; +use anyhow::anyhow; use async_task::Runnable; use futures::channel::oneshot; use parking::Unparker; 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; @@ -396,67 +394,6 @@ pub enum WindowBounds { Fixed(Bounds), } -impl StaticColumnCount for WindowBounds { - fn column_count() -> usize { - 5 - } -} - -impl Bind for WindowBounds { - fn bind(&self, statement: &Statement, start_index: i32) -> Result { - 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) - } - }; - - statement.bind( - ®ion.map(|region| { - ( - region.origin.x, - region.origin.y, - region.size.width, - region.size.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)?; - let x: f64 = x; - let y: f64 = y; - let width: f64 = width; - let height: f64 = height; - WindowBounds::Fixed(Bounds { - origin: point(x.into(), y.into()), - size: size(width.into(), height.into()), - }) - } - _ => bail!("Window State did not have a valid string"), - }; - - Ok((bounds, next_index + 4)) - } -} - #[derive(Copy, Clone, Debug)] pub enum WindowAppearance { Light, diff --git a/crates/settings/Cargo.toml b/crates/settings/Cargo.toml index f89b80902d..fe9dd35019 100644 --- a/crates/settings/Cargo.toml +++ b/crates/settings/Cargo.toml @@ -14,7 +14,6 @@ test-support = ["gpui/test-support", "fs/test-support"] [dependencies] collections = { path = "../collections" } gpui = { path = "../gpui" } -sqlez = { path = "../sqlez" } fs = { path = "../fs" } feature_flags = { path = "../feature_flags" } util = { path = "../util" } diff --git a/crates/workspace/Cargo.toml b/crates/workspace/Cargo.toml index d600a290db..9159fe2b3c 100644 --- a/crates/workspace/Cargo.toml +++ b/crates/workspace/Cargo.toml @@ -32,6 +32,7 @@ language = { path = "../language" } node_runtime = { path = "../node_runtime" } project = { path = "../project" } settings = { path = "../settings" } +sqlez = { path = "../sqlez" } terminal = { path = "../terminal" } theme = { path = "../theme" } util = { path = "../util" } diff --git a/crates/workspace/src/persistence.rs b/crates/workspace/src/persistence.rs index 5358ee3f4c..d03c7b3d0f 100644 --- a/crates/workspace/src/persistence.rs +++ b/crates/workspace/src/persistence.rs @@ -6,7 +6,12 @@ use std::path::Path; use anyhow::{anyhow, bail, Context, Result}; use db::{define_connection, query, sqlez::connection::Connection, sqlez_macros::sql}; -use gpui::{Axis, WindowBounds}; +use gpui::{point, size, Axis, Bounds, WindowBounds}; + +use sqlez::{ + bindable::{Bind, Column, StaticColumnCount}, + statement::Statement, +}; use util::{unzip_option, ResultExt}; use uuid::Uuid; @@ -20,6 +25,121 @@ use model::{ use self::model::DockStructure; +#[derive(Copy, Clone, Debug, PartialEq)] +pub(crate) struct SerializedAxis(pub(crate) gpui::Axis); +impl sqlez::bindable::StaticColumnCount for SerializedAxis {} +impl sqlez::bindable::Bind for SerializedAxis { + fn bind( + &self, + statement: &sqlez::statement::Statement, + start_index: i32, + ) -> anyhow::Result { + match self.0 { + gpui::Axis::Horizontal => "Horizontal", + gpui::Axis::Vertical => "Vertical", + } + .bind(statement, start_index) + } +} + +impl sqlez::bindable::Column for SerializedAxis { + fn column( + statement: &mut sqlez::statement::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" => Self(Axis::Horizontal), + "Vertical" => Self(Axis::Vertical), + _ => anyhow::bail!("Stored serialized item kind is incorrect"), + }, + next_index, + )) + }) + } +} + +#[derive(Clone, Debug, PartialEq)] +pub(crate) struct SerializedWindowsBounds(pub(crate) WindowBounds); + +impl StaticColumnCount for SerializedWindowsBounds { + fn column_count() -> usize { + 5 + } +} + +impl Bind for SerializedWindowsBounds { + fn bind(&self, statement: &Statement, start_index: i32) -> Result { + let (region, next_index) = match self.0 { + 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) + } + }; + + statement.bind( + ®ion.map(|region| { + ( + SerializedGlobalPixels(region.origin.x), + SerializedGlobalPixels(region.origin.y), + SerializedGlobalPixels(region.size.width), + SerializedGlobalPixels(region.size.height), + ) + }), + next_index, + ) + } +} + +impl Column for SerializedWindowsBounds { + 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" => SerializedWindowsBounds(WindowBounds::Fullscreen), + "Maximized" => SerializedWindowsBounds(WindowBounds::Maximized), + "Fixed" => { + let ((x, y, width, height), _) = Column::column(statement, next_index)?; + let x: f64 = x; + let y: f64 = y; + let width: f64 = width; + let height: f64 = height; + SerializedWindowsBounds(WindowBounds::Fixed(Bounds { + origin: point(x.into(), y.into()), + size: size(width.into(), height.into()), + })) + } + _ => bail!("Window State did not have a valid string"), + }; + + Ok((bounds, next_index + 4)) + } +} + +#[derive(Clone, Debug, PartialEq)] +struct SerializedGlobalPixels(gpui::GlobalPixels); +impl sqlez::bindable::StaticColumnCount for SerializedGlobalPixels {} + +impl sqlez::bindable::Bind for SerializedGlobalPixels { + fn bind( + &self, + statement: &sqlez::statement::Statement, + start_index: i32, + ) -> anyhow::Result { + let this: f64 = self.0.into(); + let this: f32 = this as _; + this.bind(statement, start_index) + } +} + define_connection! { // Current schema shape using pseudo-rust syntax: // @@ -181,7 +301,7 @@ impl WorkspaceDb { /// Returns a serialized workspace for the given worktree_roots. If the passed array /// is empty, the most recent workspace is returned instead. If no workspace for the /// passed roots is stored, returns none. - pub fn workspace_for_roots>( + pub(crate) fn workspace_for_roots>( &self, worktree_roots: &[P], ) -> Option { @@ -192,7 +312,7 @@ impl WorkspaceDb { let (workspace_id, workspace_location, bounds, display, docks): ( WorkspaceId, WorkspaceLocation, - Option, + Option, Option, DockStructure, ) = self @@ -230,7 +350,7 @@ impl WorkspaceDb { .get_center_pane_group(workspace_id) .context("Getting center group") .log_err()?, - bounds, + bounds: bounds.map(|bounds| bounds.0), display, docks, }) @@ -238,7 +358,7 @@ impl WorkspaceDb { /// Saves a workspace using the worktree roots. Will garbage collect any workspaces /// that used this workspace previously - pub async fn save_workspace(&self, workspace: SerializedWorkspace) { + pub(crate) async fn save_workspace(&self, workspace: SerializedWorkspace) { self.write(move |conn| { conn.with_savepoint("update_worktrees", || { // Clear out panes and pane_groups @@ -367,7 +487,7 @@ impl WorkspaceDb { type GroupKey = (Option, WorkspaceId); type GroupOrPane = ( Option, - Option, + Option, Option, Option, Option, @@ -536,7 +656,7 @@ impl WorkspaceDb { } query! { - pub async fn set_window_bounds(workspace_id: WorkspaceId, bounds: WindowBounds, display: Uuid) -> Result<()> { + pub(crate) async fn set_window_bounds(workspace_id: WorkspaceId, bounds: SerializedWindowsBounds, display: Uuid) -> Result<()> { UPDATE workspaces SET window_state = ?2, window_x = ?3, @@ -683,7 +803,7 @@ mod tests { fn group(axis: Axis, children: Vec) -> SerializedPaneGroup { SerializedPaneGroup::Group { - axis, + axis: SerializedAxis(axis), flexes: None, children, } diff --git a/crates/workspace/src/persistence/model.rs b/crates/workspace/src/persistence/model.rs index f204e5152c..c75ea2f52f 100644 --- a/crates/workspace/src/persistence/model.rs +++ b/crates/workspace/src/persistence/model.rs @@ -1,3 +1,4 @@ +use super::SerializedAxis; use crate::{item::ItemHandle, ItemDeserializers, Member, Pane, PaneAxis, Workspace, WorkspaceId}; use anyhow::{Context, Result}; use async_recursion::async_recursion; @@ -5,7 +6,7 @@ use db::sqlez::{ bindable::{Bind, Column, StaticColumnCount}, statement::Statement, }; -use gpui::{AsyncWindowContext, Axis, Model, Task, View, WeakView, WindowBounds}; +use gpui::{AsyncWindowContext, Model, Task, View, WeakView, WindowBounds}; use project::Project; use std::{ path::{Path, PathBuf}, @@ -54,13 +55,13 @@ impl Column for WorkspaceLocation { } #[derive(Debug, PartialEq, Clone)] -pub struct SerializedWorkspace { - pub id: WorkspaceId, - pub location: WorkspaceLocation, - pub center_group: SerializedPaneGroup, - pub bounds: Option, - pub display: Option, - pub docks: DockStructure, +pub(crate) struct SerializedWorkspace { + pub(crate) id: WorkspaceId, + pub(crate) location: WorkspaceLocation, + pub(crate) center_group: SerializedPaneGroup, + pub(crate) bounds: Option, + pub(crate) display: Option, + pub(crate) docks: DockStructure, } #[derive(Debug, PartialEq, Clone, Default)] @@ -126,9 +127,9 @@ impl Bind for DockData { } #[derive(Debug, PartialEq, Clone)] -pub enum SerializedPaneGroup { +pub(crate) enum SerializedPaneGroup { Group { - axis: Axis, + axis: SerializedAxis, flexes: Option>, children: Vec, }, @@ -183,7 +184,7 @@ impl SerializedPaneGroup { } Some(( - Member::Axis(PaneAxis::load(axis, members, flexes)), + Member::Axis(PaneAxis::load(axis.0, members, flexes)), current_active_pane, items, )) diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index f46a1806e1..474747c907 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -42,9 +42,9 @@ use node_runtime::NodeRuntime; use notifications::{simple_message_notification::MessageNotification, NotificationHandle}; pub use pane::*; pub use pane_group::*; -use persistence::DB; +use persistence::{model::SerializedWorkspace, SerializedWindowsBounds, DB}; pub use persistence::{ - model::{ItemId, SerializedWorkspace, WorkspaceLocation}, + model::{ItemId, WorkspaceLocation}, WorkspaceDb, DB as WORKSPACE_DB, }; use postage::stream::Stream; @@ -70,8 +70,9 @@ use util::ResultExt; use uuid::Uuid; pub use workspace_settings::{AutosaveSetting, WorkspaceSettings}; -use crate::persistence::model::{ - DockData, DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup, +use crate::persistence::{ + model::{DockData, DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup}, + SerializedAxis, }; lazy_static! { @@ -625,7 +626,11 @@ impl Workspace { if let Some(display_uuid) = display.uuid().log_err() { cx.background_executor() - .spawn(DB.set_window_bounds(workspace_id, bounds, display_uuid)) + .spawn(DB.set_window_bounds( + workspace_id, + SerializedWindowsBounds(bounds), + display_uuid, + )) .detach_and_log_err(cx); } } @@ -2989,7 +2994,7 @@ impl Workspace { flexes, bounding_boxes: _, }) => SerializedPaneGroup::Group { - axis: *axis, + axis: SerializedAxis(*axis), children: members .iter() .map(|member| build_serialized_pane_group(member, cx))