mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-07 21:37:49 +03:00
Add a Flexible
element that works like in Flutter
This commit is contained in:
parent
ec36d818c0
commit
a0dd41cdf6
@ -32,8 +32,46 @@ impl Flex {
|
||||
Self::new(Axis::Vertical)
|
||||
}
|
||||
|
||||
fn child_flex<'b>(child: &ElementBox) -> Option<f32> {
|
||||
child.metadata::<FlexParentData>().map(|data| data.flex)
|
||||
fn layout_flex_children(
|
||||
&mut self,
|
||||
expanded: bool,
|
||||
constraint: SizeConstraint,
|
||||
remaining_space: &mut f32,
|
||||
remaining_flex: &mut f32,
|
||||
cross_axis_max: &mut f32,
|
||||
cx: &mut LayoutContext,
|
||||
) {
|
||||
let cross_axis = self.axis.invert();
|
||||
for child in &mut self.children {
|
||||
if let Some(metadata) = child.metadata::<FlexParentData>() {
|
||||
if metadata.expanded != expanded {
|
||||
continue;
|
||||
}
|
||||
|
||||
let flex = metadata.flex;
|
||||
let child_max = if *remaining_flex == 0.0 {
|
||||
*remaining_space
|
||||
} else {
|
||||
let space_per_flex = *remaining_space / *remaining_flex;
|
||||
space_per_flex * flex
|
||||
};
|
||||
let child_min = if expanded { child_max } else { 0. };
|
||||
let child_constraint = match self.axis {
|
||||
Axis::Horizontal => SizeConstraint::new(
|
||||
vec2f(child_min, constraint.min.y()),
|
||||
vec2f(child_max, constraint.max.y()),
|
||||
),
|
||||
Axis::Vertical => SizeConstraint::new(
|
||||
vec2f(constraint.min.x(), child_min),
|
||||
vec2f(constraint.max.x(), child_max),
|
||||
),
|
||||
};
|
||||
let child_size = child.layout(child_constraint, cx);
|
||||
*remaining_space -= child_size.along(self.axis);
|
||||
*remaining_flex -= flex;
|
||||
*cross_axis_max = cross_axis_max.max(child_size.along(cross_axis));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -58,8 +96,8 @@ impl Element for Flex {
|
||||
let cross_axis = self.axis.invert();
|
||||
let mut cross_axis_max: f32 = 0.0;
|
||||
for child in &mut self.children {
|
||||
if let Some(flex) = Self::child_flex(&child) {
|
||||
total_flex += flex;
|
||||
if let Some(metadata) = child.metadata::<FlexParentData>() {
|
||||
total_flex += metadata.flex;
|
||||
} else {
|
||||
let child_constraint = match self.axis {
|
||||
Axis::Horizontal => SizeConstraint::new(
|
||||
@ -84,30 +122,22 @@ impl Element for Flex {
|
||||
|
||||
let mut remaining_space = constraint.max_along(self.axis) - fixed_space;
|
||||
let mut remaining_flex = total_flex;
|
||||
for child in &mut self.children {
|
||||
if let Some(flex) = Self::child_flex(&child) {
|
||||
let child_max = if remaining_flex == 0.0 {
|
||||
remaining_space
|
||||
} else {
|
||||
let space_per_flex = remaining_space / remaining_flex;
|
||||
space_per_flex * flex
|
||||
};
|
||||
let child_constraint = match self.axis {
|
||||
Axis::Horizontal => SizeConstraint::new(
|
||||
vec2f(0.0, constraint.min.y()),
|
||||
vec2f(child_max, constraint.max.y()),
|
||||
),
|
||||
Axis::Vertical => SizeConstraint::new(
|
||||
vec2f(constraint.min.x(), 0.0),
|
||||
vec2f(constraint.max.x(), child_max),
|
||||
),
|
||||
};
|
||||
let child_size = child.layout(child_constraint, cx);
|
||||
remaining_space -= child_size.along(self.axis);
|
||||
remaining_flex -= flex;
|
||||
cross_axis_max = cross_axis_max.max(child_size.along(cross_axis));
|
||||
}
|
||||
}
|
||||
self.layout_flex_children(
|
||||
false,
|
||||
constraint,
|
||||
&mut remaining_space,
|
||||
&mut remaining_flex,
|
||||
&mut cross_axis_max,
|
||||
cx,
|
||||
);
|
||||
self.layout_flex_children(
|
||||
true,
|
||||
constraint,
|
||||
&mut remaining_space,
|
||||
&mut remaining_flex,
|
||||
&mut cross_axis_max,
|
||||
cx,
|
||||
);
|
||||
|
||||
match self.axis {
|
||||
Axis::Horizontal => vec2f(constraint.max.x() - remaining_space, cross_axis_max),
|
||||
@ -181,6 +211,7 @@ impl Element for Flex {
|
||||
|
||||
struct FlexParentData {
|
||||
flex: f32,
|
||||
expanded: bool,
|
||||
}
|
||||
|
||||
pub struct Expanded {
|
||||
@ -191,7 +222,10 @@ pub struct Expanded {
|
||||
impl Expanded {
|
||||
pub fn new(flex: f32, child: ElementBox) -> Self {
|
||||
Expanded {
|
||||
metadata: FlexParentData { flex },
|
||||
metadata: FlexParentData {
|
||||
flex,
|
||||
expanded: true,
|
||||
},
|
||||
child,
|
||||
}
|
||||
}
|
||||
@ -249,3 +283,73 @@ impl Element for Expanded {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Flexible {
|
||||
metadata: FlexParentData,
|
||||
child: ElementBox,
|
||||
}
|
||||
|
||||
impl Flexible {
|
||||
pub fn new(flex: f32, child: ElementBox) -> Self {
|
||||
Flexible {
|
||||
metadata: FlexParentData {
|
||||
flex,
|
||||
expanded: false,
|
||||
},
|
||||
child,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Element for Flexible {
|
||||
type LayoutState = ();
|
||||
type PaintState = ();
|
||||
|
||||
fn layout(
|
||||
&mut self,
|
||||
constraint: SizeConstraint,
|
||||
cx: &mut LayoutContext,
|
||||
) -> (Vector2F, Self::LayoutState) {
|
||||
let size = self.child.layout(constraint, cx);
|
||||
(size, ())
|
||||
}
|
||||
|
||||
fn paint(
|
||||
&mut self,
|
||||
bounds: RectF,
|
||||
visible_bounds: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
cx: &mut PaintContext,
|
||||
) -> Self::PaintState {
|
||||
self.child.paint(bounds.origin(), visible_bounds, cx)
|
||||
}
|
||||
|
||||
fn dispatch_event(
|
||||
&mut self,
|
||||
event: &Event,
|
||||
_: RectF,
|
||||
_: &mut Self::LayoutState,
|
||||
_: &mut Self::PaintState,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
self.child.dispatch_event(event, cx)
|
||||
}
|
||||
|
||||
fn metadata(&self) -> Option<&dyn Any> {
|
||||
Some(&self.metadata)
|
||||
}
|
||||
|
||||
fn debug(
|
||||
&self,
|
||||
_: RectF,
|
||||
_: &Self::LayoutState,
|
||||
_: &Self::PaintState,
|
||||
cx: &DebugContext,
|
||||
) -> Value {
|
||||
json!({
|
||||
"type": "Flexible",
|
||||
"flex": self.metadata.flex,
|
||||
"child": self.child.debug(cx)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -964,13 +964,13 @@ impl View for Workspace {
|
||||
if let Some(element) =
|
||||
self.left_sidebar.render_active_item(&settings, cx)
|
||||
{
|
||||
content.add_child(element);
|
||||
content.add_child(Flexible::new(0.8, element).boxed());
|
||||
}
|
||||
content.add_child(Expanded::new(1.0, self.center.render()).boxed());
|
||||
if let Some(element) =
|
||||
self.right_sidebar.render_active_item(&settings, cx)
|
||||
{
|
||||
content.add_child(element);
|
||||
content.add_child(Flexible::new(0.8, element).boxed());
|
||||
}
|
||||
content.add_child(self.right_sidebar.render(&settings, cx));
|
||||
content.boxed()
|
||||
|
@ -191,7 +191,7 @@ impl Pane {
|
||||
let border = &theme.workspace.tab.container.border;
|
||||
|
||||
row.add_child(
|
||||
Expanded::new(
|
||||
Flexible::new(
|
||||
1.0,
|
||||
MouseEventHandler::new::<Tab, _, _, _>(item.id(), cx, |mouse_state, cx| {
|
||||
let title = item.title(cx);
|
||||
|
@ -113,9 +113,13 @@ impl Sidebar {
|
||||
container.add_child(self.render_resize_handle(settings, cx));
|
||||
}
|
||||
container.add_child(
|
||||
ConstrainedBox::new(ChildView::new(active_item.id()).boxed())
|
||||
.with_width(*self.width.borrow())
|
||||
.boxed(),
|
||||
Flexible::new(
|
||||
1.,
|
||||
ConstrainedBox::new(ChildView::new(active_item.id()).boxed())
|
||||
.with_max_width(*self.width.borrow())
|
||||
.boxed(),
|
||||
)
|
||||
.boxed(),
|
||||
);
|
||||
if matches!(self.side, Side::Left) {
|
||||
container.add_child(self.render_resize_handle(settings, cx));
|
||||
|
Loading…
Reference in New Issue
Block a user