mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
WIP
This commit is contained in:
parent
6d10328796
commit
6f6096238d
@ -17,13 +17,7 @@ use gpui::{
|
||||
use length::{Length, Rems};
|
||||
use log::warn;
|
||||
use optional_struct::*;
|
||||
use std::{
|
||||
any::Any,
|
||||
borrow::Cow,
|
||||
f32,
|
||||
ops::{Add, Range},
|
||||
sync::Arc,
|
||||
};
|
||||
use std::{any::Any, borrow::Cow, f32, ops::Range, sync::Arc};
|
||||
|
||||
pub struct Node<V: View> {
|
||||
style: NodeStyle,
|
||||
@ -285,19 +279,8 @@ impl<V: View> Node<V> {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn margins(
|
||||
mut self,
|
||||
top_bottom: impl Into<TopBottom>,
|
||||
left_right: impl Into<LeftRight>,
|
||||
) -> Self {
|
||||
let top_bottom = top_bottom.into();
|
||||
let left_right = left_right.into();
|
||||
self.style.margins = Edges {
|
||||
top: top_bottom.top,
|
||||
bottom: top_bottom.bottom,
|
||||
left: left_right.left,
|
||||
right: left_right.right,
|
||||
};
|
||||
pub fn margins(mut self, margins: impl Into<Edges<Length>>) -> Self {
|
||||
self.style.margins = margins.into();
|
||||
self
|
||||
}
|
||||
|
||||
@ -321,14 +304,10 @@ impl<V: View> Node<V> {
|
||||
self
|
||||
}
|
||||
|
||||
fn id_as_string(&self) -> String {
|
||||
fn id_string(&self) -> String {
|
||||
self.id.as_deref().unwrap_or("<anonymous>").to_string()
|
||||
}
|
||||
|
||||
fn log(&self, s: &str) {
|
||||
eprintln!("{}: {}", self.id_as_string(), s);
|
||||
}
|
||||
|
||||
fn layout_xy(
|
||||
&mut self,
|
||||
primary_axis: Axis2d,
|
||||
@ -337,8 +316,6 @@ impl<V: View> Node<V> {
|
||||
view: &mut V,
|
||||
cx: &mut LayoutContext<V>,
|
||||
) -> NodeLayout {
|
||||
self.log(&format!("{:?}", constraint));
|
||||
|
||||
let cross_axis = primary_axis.rotate();
|
||||
let total_flex = self.style.flex();
|
||||
let mut layout = NodeLayout {
|
||||
@ -350,149 +327,95 @@ impl<V: View> Node<V> {
|
||||
let fixed_padding_size = layout.padding.size();
|
||||
let fixed_margin_size = layout.margins.size();
|
||||
let borders_size = layout.borders.size();
|
||||
let padded_constraint = constraint - fixed_margin_size - borders_size - fixed_padding_size;
|
||||
let mut child_constraint = SizeConstraint::default();
|
||||
let fixed_constraint = constraint - fixed_margin_size - borders_size - fixed_padding_size;
|
||||
|
||||
dbg!(self.id_as_string());
|
||||
// Determine the child constraints in each dimension based on the styled size
|
||||
let mut child_constraint = SizeConstraint::default();
|
||||
for axis in [Axis2d::X, Axis2d::Y] {
|
||||
let length = self.style.size.get(axis);
|
||||
dbg!(axis, length);
|
||||
|
||||
match length {
|
||||
let content_length = match length {
|
||||
Length::Hug => {
|
||||
// Tell the children not to expand
|
||||
0.
|
||||
}
|
||||
Length::Fixed(fixed_length) => {
|
||||
// If the length is fixed, we calculate flexible padding and margins
|
||||
// before laying out the children.
|
||||
let fixed_length = fixed_length.to_pixels(rem_pixels);
|
||||
let mut remaining_flex = total_flex.get(axis);
|
||||
let mut remaining_length =
|
||||
(padded_constraint.max.get(axis) - fixed_length).max(0.);
|
||||
|
||||
// Here we avoid the padding exceeding the fixed length by giving
|
||||
// the padding calculation its own remaining_flex and remaining_length.
|
||||
let mut padding_flex = self.style.padding.flex().get(axis);
|
||||
let mut padding_length =
|
||||
((padding_flex / remaining_flex) * remaining_length).min(fixed_length);
|
||||
layout.padding.compute_flex_edges(
|
||||
&self.style.padding,
|
||||
axis,
|
||||
&mut padding_flex,
|
||||
&mut padding_length,
|
||||
rem_pixels,
|
||||
);
|
||||
remaining_flex -= padding_flex;
|
||||
remaining_length -= padding_length;
|
||||
layout.margins.compute_flex_edges(
|
||||
&self.style.margins,
|
||||
axis,
|
||||
&mut remaining_flex,
|
||||
&mut remaining_length,
|
||||
rem_pixels,
|
||||
);
|
||||
|
||||
dbg!(remaining_flex, remaining_length);
|
||||
|
||||
child_constraint.max.set(axis, remaining_length);
|
||||
if axis == cross_axis {
|
||||
child_constraint.min.set(axis, remaining_length);
|
||||
}
|
||||
// Tell the children to expand up to the fixed length minus the padding.
|
||||
fixed_length.to_pixels(rem_pixels) - fixed_padding_size.get(axis)
|
||||
}
|
||||
Length::Auto { .. } => {
|
||||
// If the length is flex, we calculate the content's share first.
|
||||
// We then layout the children and determine the flexible padding
|
||||
// and margins in a second phase.
|
||||
let mut remaining_flex = total_flex.get(axis);
|
||||
let mut remaining_length = dbg!(padded_constraint.max.get(axis));
|
||||
let content_length =
|
||||
length.flex_pixels(rem_pixels, &mut remaining_flex, &mut remaining_length);
|
||||
dbg!(content_length);
|
||||
child_constraint.max.set(axis, content_length);
|
||||
if axis == cross_axis {
|
||||
child_constraint.min.set(axis, content_length);
|
||||
}
|
||||
// Tell the children to expand to fill their share of the flex space in this node.
|
||||
length.flex_pixels(
|
||||
rem_pixels,
|
||||
&mut total_flex.get(axis),
|
||||
&mut fixed_constraint.max.get(axis),
|
||||
)
|
||||
}
|
||||
Length::Hug => {
|
||||
// If hug, leave the child constraint in its default zero state.
|
||||
// This will tell children to be as small as possible along this dimension,
|
||||
// and we calculate the flexible padding and margins in a second phase.
|
||||
};
|
||||
child_constraint.max.set(axis, content_length);
|
||||
if axis == cross_axis {
|
||||
child_constraint.min.set(axis, content_length);
|
||||
}
|
||||
}
|
||||
|
||||
// Lay out inflexible children. Total up flex of flexible children for
|
||||
// use in a second pass.
|
||||
let mut remaining_length = child_constraint.max.get(primary_axis);
|
||||
let mut remaining_flex = 0.;
|
||||
let mut total_length = 0.;
|
||||
let mut cross_axis_max: f32 = 0.;
|
||||
|
||||
for child in &mut self.children {
|
||||
if let Some(child_flex) = child
|
||||
.metadata::<NodeStyle>()
|
||||
.map(|style| style.flex().get(primary_axis))
|
||||
{
|
||||
if child_flex > 0. {
|
||||
remaining_flex += child_flex;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
let child_size = child.layout(child_constraint, view, cx);
|
||||
let child_length = child_size.get(primary_axis);
|
||||
remaining_length -= child_length;
|
||||
total_length += child_length;
|
||||
cross_axis_max = cross_axis_max.max(child_size.get(cross_axis));
|
||||
}
|
||||
|
||||
// Distribute the remaining length among the flexible children.
|
||||
for child in &mut self.children {
|
||||
if let Some(child_flex) = child
|
||||
.metadata::<NodeStyle>()
|
||||
.map(|style| style.flex().get(primary_axis))
|
||||
{
|
||||
if child_flex > 0. {
|
||||
let max_child_length = (child_flex / remaining_flex) * remaining_length;
|
||||
child_constraint.max.set(primary_axis, max_child_length);
|
||||
|
||||
let child_size = child.layout(child_constraint, view, cx);
|
||||
let child_length = child_size.get(primary_axis);
|
||||
total_length += child_length;
|
||||
remaining_length -= child_length;
|
||||
remaining_flex -= child_flex;
|
||||
cross_axis_max = cross_axis_max.max(child_size.get(cross_axis));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let content_size = {
|
||||
dbg!(self.id_as_string(), "lay out children");
|
||||
// Layout fixed children using the child constraint determined above.
|
||||
let mut remaining_child_length = dbg!(child_constraint.max).get(primary_axis);
|
||||
let mut remaining_child_flex = 0.;
|
||||
let mut total_child_length = 0.;
|
||||
let mut cross_axis_max: f32 = 0.;
|
||||
child_constraint.min.set(primary_axis, 0.);
|
||||
child_constraint.max.set(primary_axis, 0.);
|
||||
|
||||
for child in &mut self.children {
|
||||
// Don't lay out children that are flexible along the primary for this first pass,
|
||||
// but total up their flex for use in the second pass.
|
||||
if let Some(child_flex) = child
|
||||
.metadata::<NodeStyle>()
|
||||
.map(|style| style.flex().get(primary_axis))
|
||||
{
|
||||
if child_flex > 0. {
|
||||
remaining_child_flex += child_flex;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// The child is fixed along the primary axis, so perform layout.
|
||||
let child_size = child.layout(child_constraint, view, cx);
|
||||
let child_length = child_size.get(primary_axis);
|
||||
remaining_child_length -= child_length;
|
||||
total_child_length += child_length;
|
||||
cross_axis_max = cross_axis_max.max(child_size.get(cross_axis));
|
||||
}
|
||||
|
||||
// Now divide the remaining length among the flexible children.
|
||||
let id = self.id_as_string();
|
||||
for child in &mut self.children {
|
||||
if let Some(child_flex) = child
|
||||
.metadata::<NodeStyle>()
|
||||
.map(|style| style.flex().get(primary_axis))
|
||||
{
|
||||
if child_flex > 0. {
|
||||
eprintln!("{}: child is flexible", id);
|
||||
|
||||
let max_child_length =
|
||||
(child_flex / remaining_child_flex) * remaining_child_length;
|
||||
child_constraint.max.set(primary_axis, max_child_length);
|
||||
|
||||
let child_size = child.layout(child_constraint, view, cx);
|
||||
let child_length = child_size.get(primary_axis);
|
||||
total_child_length += child_length;
|
||||
remaining_child_length -= child_length;
|
||||
remaining_child_flex -= child_flex;
|
||||
cross_axis_max = cross_axis_max.max(child_size.get(cross_axis));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match primary_axis {
|
||||
Axis2d::X => vec2f(total_child_length, cross_axis_max),
|
||||
Axis2d::Y => vec2f(cross_axis_max, total_child_length),
|
||||
}
|
||||
let content_size = match primary_axis {
|
||||
Axis2d::X => vec2f(total_length, cross_axis_max),
|
||||
Axis2d::Y => vec2f(cross_axis_max, total_length),
|
||||
};
|
||||
|
||||
// Now distribute remaining space to flexible padding and margins.
|
||||
dbg!(self.id_as_string());
|
||||
// Distribute remaining space to flexible padding and margins.
|
||||
for axis in [Axis2d::X, Axis2d::Y] {
|
||||
dbg!(axis);
|
||||
let length = self.style.size.get(axis);
|
||||
|
||||
// Finish with flexible margins and padding now that children are laid out.
|
||||
match length {
|
||||
Length::Hug => {
|
||||
// Now that we know the size of our children, we can distribute
|
||||
// space to flexible padding and margins.
|
||||
let mut remaining_flex = total_flex.get(axis);
|
||||
let mut remaining_length =
|
||||
padded_constraint.min.get(axis) - content_size.get(axis);
|
||||
fixed_constraint.min.get(axis) - content_size.get(axis);
|
||||
|
||||
layout.padding.compute_flex_edges(
|
||||
&self.style.padding,
|
||||
axis,
|
||||
@ -515,26 +438,43 @@ impl<V: View> Node<V> {
|
||||
+ layout.margins.size().get(axis),
|
||||
);
|
||||
}
|
||||
Length::Fixed(fixed) => {
|
||||
// For a fixed length, we've already computed margins and padding
|
||||
// before laying out children. Padding and border are included in the
|
||||
// fixed length, so we just add the margins to determine the size.
|
||||
layout.size.set(
|
||||
Length::Fixed(fixed_length) => {
|
||||
let fixed_length = fixed_length.to_pixels(rem_pixels);
|
||||
|
||||
// With a fixed length, we can only distribute the space in the fixed-length container
|
||||
// not consumed by the content.
|
||||
let mut padding_flex = self.style.padding.flex().get(axis);
|
||||
let mut max_padding_length = (fixed_length - content_size.get(axis)).max(0.);
|
||||
layout.padding.compute_flex_edges(
|
||||
&self.style.padding,
|
||||
axis,
|
||||
fixed.to_pixels(rem_pixels) + layout.margins.size().get(axis),
|
||||
)
|
||||
&mut padding_flex,
|
||||
&mut max_padding_length,
|
||||
rem_pixels,
|
||||
);
|
||||
|
||||
// Similarly, distribute the available space for margins so we preserve the fixed length
|
||||
// of the container.
|
||||
let mut margin_flex = self.style.margins.flex().get(axis);
|
||||
let mut max_margin_length = constraint.max.get(axis) - fixed_length;
|
||||
layout.margins.compute_flex_edges(
|
||||
&self.style.padding,
|
||||
axis,
|
||||
&mut margin_flex,
|
||||
&mut max_margin_length,
|
||||
rem_pixels,
|
||||
);
|
||||
|
||||
layout
|
||||
.size
|
||||
.set(axis, fixed_length + layout.margins.size().get(axis))
|
||||
}
|
||||
Length::Auto { .. } => {
|
||||
let mut remaining_flex = total_flex.get(axis);
|
||||
let mut remaining_length = padded_constraint.max.get(axis);
|
||||
|
||||
dbg!(remaining_flex, remaining_length);
|
||||
|
||||
let mut remaining_length = fixed_constraint.max.get(axis);
|
||||
let flex_length =
|
||||
length.flex_pixels(rem_pixels, &mut remaining_flex, &mut remaining_length);
|
||||
|
||||
dbg!(flex_length, remaining_flex, remaining_length);
|
||||
|
||||
layout.padding.compute_flex_edges(
|
||||
&self.style.padding,
|
||||
axis,
|
||||
@ -543,8 +483,6 @@ impl<V: View> Node<V> {
|
||||
rem_pixels,
|
||||
);
|
||||
|
||||
dbg!(remaining_flex, remaining_length);
|
||||
|
||||
layout.margins.compute_flex_edges(
|
||||
&self.style.margins,
|
||||
axis,
|
||||
@ -553,8 +491,6 @@ impl<V: View> Node<V> {
|
||||
rem_pixels,
|
||||
);
|
||||
|
||||
dbg!(remaining_flex, remaining_length);
|
||||
|
||||
layout.size.set(
|
||||
axis,
|
||||
flex_length
|
||||
@ -566,8 +502,6 @@ impl<V: View> Node<V> {
|
||||
}
|
||||
}
|
||||
|
||||
self.log(&format!("{:?}", layout));
|
||||
|
||||
layout
|
||||
}
|
||||
}
|
||||
@ -845,6 +779,55 @@ impl Edges<Rems> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<L> From<L> for Edges<Length>
|
||||
where
|
||||
L: Into<Length>,
|
||||
{
|
||||
fn from(uniform: L) -> Self {
|
||||
let uniform = uniform.into();
|
||||
Edges {
|
||||
top: uniform,
|
||||
bottom: uniform,
|
||||
left: uniform,
|
||||
right: uniform,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Vertical, Horizontal> From<(Vertical, Horizontal)> for Edges<Length>
|
||||
where
|
||||
Vertical: Into<Length>,
|
||||
Horizontal: Into<Length>,
|
||||
{
|
||||
fn from((vertical, horizontal): (Vertical, Horizontal)) -> Self {
|
||||
let vertical = vertical.into();
|
||||
let horizontal = horizontal.into();
|
||||
Edges {
|
||||
top: vertical,
|
||||
bottom: vertical,
|
||||
left: horizontal,
|
||||
right: horizontal,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Top, Bottom, Left, Right> From<(Top, Bottom, Left, Right)> for Edges<Length>
|
||||
where
|
||||
Top: Into<Length>,
|
||||
Bottom: Into<Length>,
|
||||
Left: Into<Length>,
|
||||
Right: Into<Length>,
|
||||
{
|
||||
fn from((top, bottom, left, right): (Top, Bottom, Left, Right)) -> Self {
|
||||
Edges {
|
||||
top: top.into(),
|
||||
bottom: bottom.into(),
|
||||
left: left.into(),
|
||||
right: right.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
struct CornerRadii {
|
||||
top_left: f32,
|
||||
@ -1440,18 +1423,6 @@ pub struct TextLayout {
|
||||
line_height: f32,
|
||||
}
|
||||
|
||||
fn optional_add<T>(a: Option<T>, b: Option<T>) -> Option<T::Output>
|
||||
where
|
||||
T: Add<Output = T>,
|
||||
{
|
||||
match (a, b) {
|
||||
(Some(a), Some(b)) => Some(a + b),
|
||||
(Some(a), None) => Some(a),
|
||||
(None, Some(b)) => Some(b),
|
||||
(None, None) => None,
|
||||
}
|
||||
}
|
||||
|
||||
trait Vector2FExt {
|
||||
fn infinity() -> Self;
|
||||
fn get(self, axis: Axis2d) -> f32;
|
||||
|
@ -14,27 +14,20 @@ pub struct Playground<V: View>(PhantomData<V>);
|
||||
|
||||
impl<V: View> Playground<V> {
|
||||
pub fn render(&mut self, _: &mut V, _: &mut gpui::ViewContext<V>) -> AnyElement<V> {
|
||||
column()
|
||||
.id("red column")
|
||||
row()
|
||||
.id("green row")
|
||||
.width(auto())
|
||||
.height(auto())
|
||||
.fill(Color::red())
|
||||
.child(
|
||||
row()
|
||||
.id("green row")
|
||||
.width(auto())
|
||||
.height(rems(20.))
|
||||
.margins(rems(0.), auto())
|
||||
.fill(Color::green())
|
||||
.child(
|
||||
row()
|
||||
.id("blue row")
|
||||
.width(rems(20.))
|
||||
.height(auto())
|
||||
.fill(Color::blue()),
|
||||
),
|
||||
)
|
||||
.into_any()
|
||||
.height(rems(20.))
|
||||
.fill(Color::green())
|
||||
// .child(
|
||||
// row()
|
||||
// .id("blue box")
|
||||
// .width(rems(20.))
|
||||
// .height(auto())
|
||||
// .margin_left(auto())
|
||||
// .fill(Color::blue()),
|
||||
// )
|
||||
// .into_any()
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,7 +155,7 @@ impl<V: View, D: DialogDelegate<V>> Dialog<V, D> {
|
||||
pub fn render(&mut self, _: &mut V, _: &mut gpui::ViewContext<V>) -> AnyElement<V> {
|
||||
column()
|
||||
.child(text(self.title.clone()).text_size(lg()))
|
||||
.child(text(self.description.clone()).margins(m4(), auto()))
|
||||
.child(text(self.description.clone()).margins((m4(), auto())))
|
||||
.child(row().children(self.buttons.drain(..).map(|button| (button)())))
|
||||
.into_any()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user