Detailed changes
@@ -2,13 +2,14 @@ use std::{any::Any, rc::Rc};
use crate::{
adapter::Adapter,
- style::{DefinedLength, Display, ElementStyle, Fill, Length, Overflow, Position},
+ style::{Display, ElementStyle, Fill, Overflow, Position},
};
use anyhow::Result;
use derive_more::{Deref, DerefMut};
use gpui::{
- scene::MouseClick, EngineLayout, LayoutContext as LegacyLayoutContext,
- PaintContext as LegacyPaintContext,
+ geometry::{DefinedLength, Length},
+ scene::MouseClick,
+ EngineLayout, LayoutContext as LegacyLayoutContext, PaintContext as LegacyPaintContext,
};
use playground_macros::tailwind_lengths;
pub use taffy::tree::NodeId;
@@ -3,13 +3,12 @@ use components::button;
use element::Element;
use frame::frame;
use gpui::{
- geometry::{rect::RectF, vector::vec2f},
+ geometry::{percent, rect::RectF, vector::vec2f},
platform::WindowOptions,
};
use log::LevelFilter;
use simplelog::SimpleLogger;
-use style::percent;
use themes::{rose_pine, ThemeColors};
use view::view;
@@ -1,4 +1,5 @@
use crate::color::Hsla;
+use gpui::geometry::{DefinedLength, Edges, Length, Point, Size};
pub use taffy::style::{
AlignContent, AlignItems, AlignSelf, Display, FlexDirection, FlexWrap, JustifyContent,
Overflow, Position,
@@ -143,180 +144,6 @@ impl Default for ElementStyle {
}
}
-#[derive(Clone)]
-pub struct Point<T> {
- pub x: T,
- pub y: T,
-}
-
-impl<T> Into<taffy::geometry::Point<T>> for Point<T> {
- fn into(self) -> taffy::geometry::Point<T> {
- taffy::geometry::Point {
- x: self.x,
- y: self.y,
- }
- }
-}
-
-#[derive(Clone)]
-pub struct Size<T> {
- pub width: T,
- pub height: T,
-}
-
-impl Size<DefinedLength> {
- pub const fn zero() -> Self {
- Self {
- width: DefinedLength::Pixels(0.),
- height: DefinedLength::Pixels(0.),
- }
- }
-
- pub fn to_taffy(&self, rem_size: f32) -> taffy::geometry::Size<taffy::style::LengthPercentage> {
- taffy::geometry::Size {
- width: self.width.to_taffy(rem_size),
- height: self.height.to_taffy(rem_size),
- }
- }
-}
-
-impl Size<Length> {
- pub const fn auto() -> Self {
- Self {
- width: Length::Auto,
- height: Length::Auto,
- }
- }
-
- pub fn to_taffy<T: From<taffy::prelude::LengthPercentageAuto>>(
- &self,
- rem_size: f32,
- ) -> taffy::geometry::Size<T> {
- taffy::geometry::Size {
- width: self.width.to_taffy(rem_size).into(),
- height: self.height.to_taffy(rem_size).into(),
- }
- }
-}
-
-#[derive(Clone)]
-pub struct Edges<T> {
- pub top: T,
- pub right: T,
- pub bottom: T,
- pub left: T,
-}
-
-impl Edges<DefinedLength> {
- pub const fn zero() -> Self {
- Self {
- top: DefinedLength::Pixels(0.0),
- right: DefinedLength::Pixels(0.0),
- bottom: DefinedLength::Pixels(0.0),
- left: DefinedLength::Pixels(0.0),
- }
- }
-
- pub fn to_taffy(&self, rem_size: f32) -> taffy::geometry::Rect<taffy::style::LengthPercentage> {
- taffy::geometry::Rect {
- top: self.top.to_taffy(rem_size),
- right: self.right.to_taffy(rem_size),
- bottom: self.bottom.to_taffy(rem_size),
- left: self.left.to_taffy(rem_size),
- }
- }
-}
-
-impl Edges<Length> {
- pub const fn auto() -> Self {
- Self {
- top: Length::Auto,
- right: Length::Auto,
- bottom: Length::Auto,
- left: Length::Auto,
- }
- }
-
- pub const fn zero() -> Self {
- Self {
- top: Length::Defined(DefinedLength::Pixels(0.0)),
- right: Length::Defined(DefinedLength::Pixels(0.0)),
- bottom: Length::Defined(DefinedLength::Pixels(0.0)),
- left: Length::Defined(DefinedLength::Pixels(0.0)),
- }
- }
-
- pub fn to_taffy(
- &self,
- rem_size: f32,
- ) -> taffy::geometry::Rect<taffy::style::LengthPercentageAuto> {
- taffy::geometry::Rect {
- top: self.top.to_taffy(rem_size),
- right: self.right.to_taffy(rem_size),
- bottom: self.bottom.to_taffy(rem_size),
- left: self.left.to_taffy(rem_size),
- }
- }
-}
-
-/// A non-auto length that can be defined in pixels, rems, or percent of parent.
-#[derive(Clone, Copy)]
-pub enum DefinedLength {
- Pixels(f32),
- Rems(f32),
- Percent(f32), // 0. - 100.
-}
-
-impl DefinedLength {
- fn to_taffy(&self, rem_size: f32) -> taffy::style::LengthPercentage {
- match self {
- DefinedLength::Pixels(pixels) => taffy::style::LengthPercentage::Length(*pixels),
- DefinedLength::Rems(rems) => taffy::style::LengthPercentage::Length(rems * rem_size),
- DefinedLength::Percent(percent) => {
- taffy::style::LengthPercentage::Percent(*percent / 100.)
- }
- }
- }
-}
-
-/// A length that can be defined in pixels, rems, percent of parent, or auto.
-#[derive(Clone, Copy)]
-pub enum Length {
- Defined(DefinedLength),
- Auto,
-}
-
-pub fn auto() -> Length {
- Length::Auto
-}
-
-pub fn percent(percent: f32) -> DefinedLength {
- DefinedLength::Percent(percent)
-}
-
-pub fn rems(rems: f32) -> DefinedLength {
- DefinedLength::Rems(rems)
-}
-
-pub fn pixels(pixels: f32) -> DefinedLength {
- DefinedLength::Pixels(pixels)
-}
-
-impl Length {
- fn to_taffy(&self, rem_size: f32) -> taffy::prelude::LengthPercentageAuto {
- match self {
- Length::Defined(length) => length.to_taffy(rem_size).into(),
- Length::Auto => taffy::prelude::LengthPercentageAuto::Auto,
- }
- }
-}
-
-impl From<DefinedLength> for Length {
- fn from(value: DefinedLength) -> Self {
- Length::Defined(value)
- }
-}
-
#[derive(Clone)]
pub enum Fill {
Color(Hsla),
@@ -1,6 +1,6 @@
use crate::{
elements::AnyRootElement,
- geometry::rect::RectF,
+ geometry::{rect::RectF, Size},
json::ToJson,
keymap_matcher::{Binding, KeymapContext, Keystroke, MatchResult},
platform::{
@@ -33,7 +33,10 @@ use std::{
mem,
ops::{Deref, DerefMut, Range, Sub},
};
-use taffy::Taffy;
+use taffy::{
+ tree::{Measurable, MeasureFunc},
+ Taffy,
+};
use util::ResultExt;
use uuid::Uuid;
@@ -1253,6 +1256,15 @@ impl LayoutEngine {
.new_with_children(style, &children.into_iter().collect::<Vec<_>>())?)
}
+ pub fn add_measured_node<F>(&mut self, style: LayoutStyle, measure: F) -> Result<LayoutNodeId>
+ where
+ F: Fn(MeasureParams) -> Size<f32> + Sync + Send + 'static,
+ {
+ Ok(self
+ .0
+ .new_leaf_with_measure(style, MeasureFunc::Boxed(Box::new(MeasureFn(measure))))?)
+ }
+
pub fn compute_layout(&mut self, root: LayoutNodeId, available_space: Vector2F) -> Result<()> {
self.0.compute_layout(
root,
@@ -1269,11 +1281,54 @@ impl LayoutEngine {
}
}
+pub struct MeasureFn<F>(F);
+
+impl<F: Send + Sync> Measurable for MeasureFn<F>
+where
+ F: Fn(MeasureParams) -> Size<f32>,
+{
+ fn measure(
+ &self,
+ known_dimensions: taffy::prelude::Size<Option<f32>>,
+ available_space: taffy::prelude::Size<taffy::style::AvailableSpace>,
+ ) -> taffy::prelude::Size<f32> {
+ (self.0)(MeasureParams {
+ known_dimensions: known_dimensions.into(),
+ available_space: available_space.into(),
+ })
+ .into()
+ }
+}
+
pub struct EngineLayout {
pub bounds: RectF,
pub order: u32,
}
+pub struct MeasureParams {
+ pub known_dimensions: Size<Option<f32>>,
+ pub available_space: Size<AvailableSpace>,
+}
+
+pub enum AvailableSpace {
+ /// The amount of space available is the specified number of pixels
+ Pixels(f32),
+ /// The amount of space available is indefinite and the node should be laid out under a min-content constraint
+ MinContent,
+ /// The amount of space available is indefinite and the node should be laid out under a max-content constraint
+ MaxContent,
+}
+
+impl From<taffy::prelude::AvailableSpace> for AvailableSpace {
+ fn from(value: taffy::prelude::AvailableSpace) -> Self {
+ match value {
+ taffy::prelude::AvailableSpace::Definite(pixels) => Self::Pixels(pixels),
+ taffy::prelude::AvailableSpace::MinContent => Self::MinContent,
+ taffy::prelude::AvailableSpace::MaxContent => Self::MaxContent,
+ }
+ }
+}
+
impl From<&taffy::tree::Layout> for EngineLayout {
fn from(value: &taffy::tree::Layout) -> Self {
Self {
@@ -131,3 +131,201 @@ impl ToJson for RectF {
json!({"origin": self.origin().to_json(), "size": self.size().to_json()})
}
}
+
+#[derive(Clone)]
+pub struct Point<T> {
+ pub x: T,
+ pub y: T,
+}
+
+impl<T> Into<taffy::geometry::Point<T>> for Point<T> {
+ fn into(self) -> taffy::geometry::Point<T> {
+ taffy::geometry::Point {
+ x: self.x,
+ y: self.y,
+ }
+ }
+}
+
+#[derive(Clone)]
+pub struct Size<T> {
+ pub width: T,
+ pub height: T,
+}
+
+impl<S, T> From<taffy::geometry::Size<S>> for Size<T>
+where
+ S: Into<T>,
+{
+ fn from(value: taffy::geometry::Size<S>) -> Self {
+ Self {
+ width: value.width.into(),
+ height: value.height.into(),
+ }
+ }
+}
+
+impl<S, T> Into<taffy::geometry::Size<S>> for Size<T>
+where
+ T: Into<S>,
+{
+ fn into(self) -> taffy::geometry::Size<S> {
+ taffy::geometry::Size {
+ width: self.width.into(),
+ height: self.height.into(),
+ }
+ }
+}
+
+impl Size<DefinedLength> {
+ pub const fn zero() -> Self {
+ Self {
+ width: DefinedLength::Pixels(0.),
+ height: DefinedLength::Pixels(0.),
+ }
+ }
+
+ pub fn to_taffy(&self, rem_size: f32) -> taffy::geometry::Size<taffy::style::LengthPercentage> {
+ taffy::geometry::Size {
+ width: self.width.to_taffy(rem_size),
+ height: self.height.to_taffy(rem_size),
+ }
+ }
+}
+
+impl Size<Length> {
+ pub const fn auto() -> Self {
+ Self {
+ width: Length::Auto,
+ height: Length::Auto,
+ }
+ }
+
+ pub fn to_taffy<T: From<taffy::prelude::LengthPercentageAuto>>(
+ &self,
+ rem_size: f32,
+ ) -> taffy::geometry::Size<T> {
+ taffy::geometry::Size {
+ width: self.width.to_taffy(rem_size).into(),
+ height: self.height.to_taffy(rem_size).into(),
+ }
+ }
+}
+
+#[derive(Clone)]
+pub struct Edges<T> {
+ pub top: T,
+ pub right: T,
+ pub bottom: T,
+ pub left: T,
+}
+
+impl Edges<DefinedLength> {
+ pub const fn zero() -> Self {
+ Self {
+ top: DefinedLength::Pixels(0.0),
+ right: DefinedLength::Pixels(0.0),
+ bottom: DefinedLength::Pixels(0.0),
+ left: DefinedLength::Pixels(0.0),
+ }
+ }
+
+ pub fn to_taffy(&self, rem_size: f32) -> taffy::geometry::Rect<taffy::style::LengthPercentage> {
+ taffy::geometry::Rect {
+ top: self.top.to_taffy(rem_size),
+ right: self.right.to_taffy(rem_size),
+ bottom: self.bottom.to_taffy(rem_size),
+ left: self.left.to_taffy(rem_size),
+ }
+ }
+}
+
+impl Edges<Length> {
+ pub const fn auto() -> Self {
+ Self {
+ top: Length::Auto,
+ right: Length::Auto,
+ bottom: Length::Auto,
+ left: Length::Auto,
+ }
+ }
+
+ pub const fn zero() -> Self {
+ Self {
+ top: Length::Defined(DefinedLength::Pixels(0.0)),
+ right: Length::Defined(DefinedLength::Pixels(0.0)),
+ bottom: Length::Defined(DefinedLength::Pixels(0.0)),
+ left: Length::Defined(DefinedLength::Pixels(0.0)),
+ }
+ }
+
+ pub fn to_taffy(
+ &self,
+ rem_size: f32,
+ ) -> taffy::geometry::Rect<taffy::style::LengthPercentageAuto> {
+ taffy::geometry::Rect {
+ top: self.top.to_taffy(rem_size),
+ right: self.right.to_taffy(rem_size),
+ bottom: self.bottom.to_taffy(rem_size),
+ left: self.left.to_taffy(rem_size),
+ }
+ }
+}
+
+/// A non-auto length that can be defined in pixels, rems, or percent of parent.
+#[derive(Clone, Copy)]
+pub enum DefinedLength {
+ Pixels(f32),
+ Rems(f32),
+ Percent(f32), // 0. - 100.
+}
+
+impl DefinedLength {
+ fn to_taffy(&self, rem_size: f32) -> taffy::style::LengthPercentage {
+ match self {
+ DefinedLength::Pixels(pixels) => taffy::style::LengthPercentage::Length(*pixels),
+ DefinedLength::Rems(rems) => taffy::style::LengthPercentage::Length(rems * rem_size),
+ DefinedLength::Percent(percent) => {
+ taffy::style::LengthPercentage::Percent(*percent / 100.)
+ }
+ }
+ }
+}
+
+/// A length that can be defined in pixels, rems, percent of parent, or auto.
+#[derive(Clone, Copy)]
+pub enum Length {
+ Defined(DefinedLength),
+ Auto,
+}
+
+pub fn auto() -> Length {
+ Length::Auto
+}
+
+pub fn percent(percent: f32) -> DefinedLength {
+ DefinedLength::Percent(percent)
+}
+
+pub fn rems(rems: f32) -> DefinedLength {
+ DefinedLength::Rems(rems)
+}
+
+pub fn pixels(pixels: f32) -> DefinedLength {
+ DefinedLength::Pixels(pixels)
+}
+
+impl Length {
+ pub fn to_taffy(&self, rem_size: f32) -> taffy::prelude::LengthPercentageAuto {
+ match self {
+ Length::Defined(length) => length.to_taffy(rem_size).into(),
+ Length::Auto => taffy::prelude::LengthPercentageAuto::Auto,
+ }
+ }
+}
+
+impl From<DefinedLength> for Length {
+ fn from(value: DefinedLength) -> Self {
+ Length::Defined(value)
+ }
+}