Begin porting the PaneAxis element
This commit is contained in:
parent
c7e19c0bcd
commit
25df11dd26
8 changed files with 564 additions and 407 deletions
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}),
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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 {
|
|||
// })
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue