Begin porting the PaneAxis element

This commit is contained in:
Mikayla 2023-12-07 17:16:19 -08:00
parent c7e19c0bcd
commit 25df11dd26
No known key found for this signature in database
8 changed files with 564 additions and 407 deletions

View file

@ -57,8 +57,12 @@ where
T: 'static,
E: 'static + Debug,
{
#[track_caller]
pub fn detach_and_log_err(self, cx: &mut AppContext) {
cx.foreground_executor().spawn(self.log_err()).detach();
let location = core::panic::Location::caller();
cx.foreground_executor()
.spawn(self.log_tracked_err(*location))
.detach();
}
}

View file

@ -8,6 +8,54 @@ use std::{
ops::{Add, Div, Mul, MulAssign, Sub},
};
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Axis {
Vertical,
Horizontal,
}
impl Axis {
pub fn invert(&self) -> Self {
match self {
Axis::Vertical => Axis::Horizontal,
Axis::Horizontal => Axis::Vertical,
}
}
}
impl sqlez::bindable::StaticColumnCount for Axis {}
impl sqlez::bindable::Bind for Axis {
fn bind(
&self,
statement: &sqlez::statement::Statement,
start_index: i32,
) -> anyhow::Result<i32> {
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.
@ -94,6 +142,19 @@ impl<T: Clone + Debug + Default> Point<T> {
y: f(self.y.clone()),
}
}
pub fn apply_along(&self, axis: Axis, f: impl FnOnce(T) -> T) -> Point<T> {
match axis {
Axis::Horizontal => Point {
x: f(self.x.clone()),
y: self.y.clone(),
},
Axis::Vertical => Point {
x: self.x.clone(),
y: f(self.y.clone()),
},
}
}
}
impl Point<Pixels> {
@ -373,6 +434,32 @@ impl Size<Pixels> {
}
}
impl<T> Size<T>
where
T: Clone + Default + Debug,
{
pub fn along(&self, axis: Axis) -> T {
match axis {
Axis::Horizontal => self.width.clone(),
Axis::Vertical => self.height.clone(),
}
}
/// Returns the value of this size along the given axis.
pub fn apply_along(&self, axis: Axis, f: impl FnOnce(T) -> T) -> Self {
match axis {
Axis::Horizontal => Size {
width: f(self.width.clone()),
height: self.height.clone(),
},
Axis::Vertical => Size {
width: self.width.clone(),
height: f(self.height.clone()),
},
}
}
}
impl<T> Size<T>
where
T: PartialOrd + Clone + Default + Debug,

View file

@ -477,3 +477,12 @@ impl From<Pixels> for AvailableSpace {
AvailableSpace::Definite(pixels)
}
}
impl From<Size<Pixels>> for Size<AvailableSpace> {
fn from(size: Size<Pixels>) -> Self {
Size {
width: AvailableSpace::Definite(size.width),
height: AvailableSpace::Definite(size.height),
}
}
}

View file

@ -184,6 +184,11 @@ pub trait TryFutureExt {
fn log_err(self) -> LogErrorFuture<Self>
where
Self: Sized;
fn log_tracked_err(self, location: core::panic::Location<'static>) -> LogErrorFuture<Self>
where
Self: Sized;
fn warn_on_err(self) -> LogErrorFuture<Self>
where
Self: Sized;
@ -197,18 +202,29 @@ where
F: Future<Output = Result<T, E>>,
E: std::fmt::Debug,
{
#[track_caller]
fn log_err(self) -> LogErrorFuture<Self>
where
Self: Sized,
{
LogErrorFuture(self, log::Level::Error)
let location = Location::caller();
LogErrorFuture(self, log::Level::Error, *location)
}
fn log_tracked_err(self, location: core::panic::Location<'static>) -> LogErrorFuture<Self>
where
Self: Sized,
{
LogErrorFuture(self, log::Level::Error, location)
}
#[track_caller]
fn warn_on_err(self) -> LogErrorFuture<Self>
where
Self: Sized,
{
LogErrorFuture(self, log::Level::Warn)
let location = Location::caller();
LogErrorFuture(self, log::Level::Warn, *location)
}
fn unwrap(self) -> UnwrapFuture<Self>
@ -219,7 +235,7 @@ where
}
}
pub struct LogErrorFuture<F>(F, log::Level);
pub struct LogErrorFuture<F>(F, log::Level, core::panic::Location<'static>);
impl<F, T, E> Future for LogErrorFuture<F>
where
@ -230,12 +246,19 @@ where
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
let level = self.1;
let location = self.2;
let inner = unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0) };
match inner.poll(cx) {
Poll::Ready(output) => Poll::Ready(match output {
Ok(output) => Some(output),
Err(error) => {
log::log!(level, "{:?}", error);
log::log!(
level,
"{}:{}: {:?}",
location.file(),
location.line(),
error
);
None
}
}),

View file

@ -1,6 +1,6 @@
use crate::{status_bar::StatusItemView, Axis, Workspace};
use crate::{status_bar::StatusItemView, Workspace};
use gpui::{
div, px, Action, AnchorCorner, AnyView, AppContext, Div, Entity, EntityId, EventEmitter,
div, px, Action, AnchorCorner, AnyView, AppContext, Axis, Div, Entity, EntityId, EventEmitter,
FocusHandle, FocusableView, IntoElement, ParentElement, Render, SharedString, Styled,
Subscription, View, ViewContext, VisualContext, WeakView, WindowContext,
};

View file

@ -1,13 +1,9 @@
use crate::{AppState, FollowerState, Pane, Workspace};
use anyhow::{anyhow, bail, Result};
use crate::{pane_group::element::pane_axis, AppState, FollowerState, Pane, Workspace};
use anyhow::{anyhow, Result};
use call::{ActiveCall, ParticipantLocation};
use collections::HashMap;
use db::sqlez::{
bindable::{Bind, Column, StaticColumnCount},
statement::Statement,
};
use gpui::{
point, size, AnyWeakView, Bounds, Div, Entity as _, IntoElement, Model, Pixels, Point, View,
point, size, AnyWeakView, Axis, Bounds, Entity as _, IntoElement, Model, Pixels, Point, View,
ViewContext,
};
use parking_lot::Mutex;
@ -20,38 +16,6 @@ const HANDLE_HITBOX_SIZE: f32 = 4.0;
const HORIZONTAL_MIN_SIZE: f32 = 80.;
const VERTICAL_MIN_SIZE: f32 = 100.;
#[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,
@ -632,16 +596,10 @@ impl PaneAxis {
zoomed: Option<&AnyWeakView>,
app_state: &Arc<AppState>,
cx: &mut ViewContext<Workspace>,
) -> Div {
) -> gpui::AnyElement {
debug_assert!(self.members.len() == self.flexes.lock().len());
div()
.flex()
.flex_auto()
.map(|s| match self.axis {
Axis::Vertical => s.flex_col(),
Axis::Horizontal => s.flex_row(),
})
pane_axis(self.axis, basis, self.flexes.clone())
.children(self.members.iter().enumerate().map(|(ix, member)| {
match member {
Member::Axis(axis) => axis
@ -658,6 +616,7 @@ impl PaneAxis {
Member::Pane(pane) => pane.clone().into_any_element(),
}
}))
.into_any_element()
// let mut pane_axis = PaneAxisElement::new(
// self.axis,
@ -767,7 +726,84 @@ impl SplitDirection {
}
}
// mod element {
mod element {
use std::sync::Arc;
use gpui::{relative, AnyElement, Axis, Element, IntoElement, ParentElement, Style};
use parking_lot::Mutex;
use smallvec::SmallVec;
pub fn pane_axis(axis: Axis, basis: usize, flexes: Arc<Mutex<Vec<f32>>>) -> PaneAxisElement {
PaneAxisElement {
axis,
basis,
flexes,
children: SmallVec::new(),
}
}
pub struct PaneAxisElement {
axis: Axis,
basis: usize,
flexes: Arc<Mutex<Vec<f32>>>,
children: SmallVec<[AnyElement; 2]>,
}
impl IntoElement for PaneAxisElement {
type Element = Self;
fn element_id(&self) -> Option<ui::prelude::ElementId> {
Some("pane axis".into())
}
fn into_element(self) -> Self::Element {
self
}
}
impl Element for PaneAxisElement {
type State = ();
fn layout(
&mut self,
state: Option<Self::State>,
cx: &mut ui::prelude::WindowContext,
) -> (gpui::LayoutId, Self::State) {
let mut style = Style::default();
style.size.width = relative(1.).into();
style.size.height = relative(1.).into();
let layout_id = cx.request_layout(&style, None);
(layout_id, ())
}
fn paint(
self,
bounds: gpui::Bounds<ui::prelude::Pixels>,
state: &mut Self::State,
cx: &mut ui::prelude::WindowContext,
) {
let flexes = self.flexes.lock().clone();
debug_assert!(flexes.len() == self.children.len());
let origin = bounds.origin;
let size = bounds.size;
let len = self.children.len();
let child_size = size.apply_along(self.axis, |val| val / len as f32);
for (ix, child) in self.children.into_iter().enumerate() {
let origin =
origin.apply_along(self.axis, |val| val + child_size.along(self.axis) * ix);
child.draw(origin, child_size.into(), cx);
}
}
}
impl ParentElement for PaneAxisElement {
fn children_mut(&mut self) -> &mut smallvec::SmallVec<[AnyElement; 2]> {
&mut self.children
}
}
// // use std::{cell::RefCell, iter::from_fn, ops::Range, rc::Rc};
// // use gpui::{
@ -1166,4 +1202,4 @@ impl SplitDirection {
// })
// }
// }
// }
}

View file

@ -6,12 +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::WindowBounds;
use gpui::{Axis, WindowBounds};
use util::{unzip_option, ResultExt};
use uuid::Uuid;
use crate::{Axis, WorkspaceId};
use crate::WorkspaceId;
use model::{
GroupId, PaneId, SerializedItem, SerializedPane, SerializedPaneGroup, SerializedWorkspace,
@ -403,7 +403,7 @@ impl WorkspaceDb {
.map(|(group_id, axis, pane_id, active, flexes)| {
if let Some((group_id, axis)) = group_id.zip(axis) {
let flexes = flexes
.map(|flexes| serde_json::from_str::<Vec<f32>>(&flexes))
.map(|flexes: String| serde_json::from_str::<Vec<f32>>(&flexes))
.transpose()?;
Ok(SerializedPaneGroup::Group {

View file

@ -1,13 +1,11 @@
use crate::{
item::ItemHandle, Axis, ItemDeserializers, Member, Pane, PaneAxis, Workspace, WorkspaceId,
};
use crate::{item::ItemHandle, ItemDeserializers, Member, Pane, PaneAxis, Workspace, WorkspaceId};
use anyhow::{Context, Result};
use async_recursion::async_recursion;
use db::sqlez::{
bindable::{Bind, Column, StaticColumnCount},
statement::Statement,
};
use gpui::{AsyncWindowContext, Model, Task, View, WeakView, WindowBounds};
use gpui::{AsyncWindowContext, Axis, Model, Task, View, WeakView, WindowBounds};
use project::Project;
use std::{
path::{Path, PathBuf},