Detailed changes
@@ -219,7 +219,7 @@ impl ChatPanel {
Empty::new().boxed()
};
- Flexible::new(1., true, messages).boxed()
+ FlexItem::new(messages).flex(1., true).boxed()
}
fn render_message(&self, message: &ChannelMessage, cx: &AppContext) -> ElementBox {
@@ -212,7 +212,7 @@ impl ContactsPanel {
}));
}
})
- .flexible(1., true)
+ .flex(1., true)
.boxed()
})
.constrained()
@@ -78,7 +78,11 @@ impl View for FileFinder {
.with_style(settings.theme.selector.input_editor.container)
.boxed(),
)
- .with_child(Flexible::new(1.0, false, self.render_matches(cx)).boxed())
+ .with_child(
+ FlexItem::new(self.render_matches(cx))
+ .flex(1., false)
+ .boxed(),
+ )
.boxed(),
)
.with_style(settings.theme.selector.container)
@@ -166,23 +170,19 @@ impl FileFinder {
// .boxed(),
// )
.with_child(
- Flexible::new(
- 1.0,
- false,
- Flex::column()
- .with_child(
- Label::new(file_name.to_string(), style.label.clone())
- .with_highlights(file_name_positions)
- .boxed(),
- )
- .with_child(
- Label::new(full_path, style.label.clone())
- .with_highlights(full_path_positions)
- .boxed(),
- )
- .boxed(),
- )
- .boxed(),
+ Flex::column()
+ .with_child(
+ Label::new(file_name.to_string(), style.label.clone())
+ .with_highlights(file_name_positions)
+ .boxed(),
+ )
+ .with_child(
+ Label::new(full_path, style.label.clone())
+ .with_highlights(full_path_positions)
+ .boxed(),
+ )
+ .flex(1., false)
+ .boxed(),
)
.boxed(),
)
@@ -139,11 +139,18 @@ pub trait Element {
Expanded::new(self.boxed())
}
- fn flexible(self, flex: f32, expanded: bool) -> Flexible
+ fn flex(self, flex: f32, expanded: bool) -> FlexItem
where
Self: 'static + Sized,
{
- Flexible::new(flex, expanded, self.boxed())
+ FlexItem::new(self.boxed()).flex(flex, expanded)
+ }
+
+ fn flex_float(self) -> FlexItem
+ where
+ Self: 'static + Sized,
+ {
+ FlexItem::new(self.boxed()).float()
}
}
@@ -34,7 +34,7 @@ impl Flex {
fn layout_flex_children(
&mut self,
- expanded: bool,
+ layout_expanded: bool,
constraint: SizeConstraint,
remaining_space: &mut f32,
remaining_flex: &mut f32,
@@ -44,32 +44,33 @@ impl Flex {
let cross_axis = self.axis.invert();
for child in &mut self.children {
if let Some(metadata) = child.metadata::<FlexParentData>() {
- if metadata.expanded != expanded {
- continue;
- }
+ if let Some((flex, expanded)) = metadata.flex {
+ if expanded != layout_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));
+ 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));
+ }
}
}
}
@@ -82,7 +83,7 @@ impl Extend<ElementBox> for Flex {
}
impl Element for Flex {
- type LayoutState = bool;
+ type LayoutState = f32;
type PaintState = ();
fn layout(
@@ -96,8 +97,11 @@ 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(metadata) = child.metadata::<FlexParentData>() {
- *total_flex.get_or_insert(0.) += metadata.flex;
+ if let Some(flex) = child
+ .metadata::<FlexParentData>()
+ .and_then(|metadata| metadata.flex.map(|(flex, _)| flex))
+ {
+ *total_flex.get_or_insert(0.) += flex;
} else {
let child_constraint = match self.axis {
Axis::Horizontal => SizeConstraint::new(
@@ -115,12 +119,12 @@ impl Element for Flex {
}
}
+ let mut remaining_space = constraint.max_along(self.axis) - fixed_space;
let mut size = if let Some(mut remaining_flex) = total_flex {
- if constraint.max_along(self.axis).is_infinite() {
+ if remaining_space.is_infinite() {
panic!("flex contains flexible children but has an infinite constraint along the flex axis");
}
- let mut remaining_space = constraint.max_along(self.axis) - fixed_space;
self.layout_flex_children(
false,
constraint,
@@ -156,38 +160,47 @@ impl Element for Flex {
size.set_y(size.y().max(constraint.min.y()));
}
- let mut overflowing = false;
if size.x() > constraint.max.x() {
size.set_x(constraint.max.x());
- overflowing = true;
}
if size.y() > constraint.max.y() {
size.set_y(constraint.max.y());
- overflowing = true;
}
- (size, overflowing)
+ (size, remaining_space)
}
fn paint(
&mut self,
bounds: RectF,
visible_bounds: RectF,
- overflowing: &mut Self::LayoutState,
+ remaining_space: &mut Self::LayoutState,
cx: &mut PaintContext,
) -> Self::PaintState {
- if *overflowing {
+ let overflowing = *remaining_space < 0.;
+ if overflowing {
cx.scene.push_layer(Some(bounds));
}
let mut child_origin = bounds.origin();
for child in &mut self.children {
+ if *remaining_space > 0. {
+ if let Some(metadata) = child.metadata::<FlexParentData>() {
+ if metadata.float {
+ match self.axis {
+ Axis::Horizontal => child_origin += vec2f(*remaining_space, 0.0),
+ Axis::Vertical => child_origin += vec2f(0.0, *remaining_space),
+ }
+ *remaining_space = 0.;
+ }
+ }
+ }
child.paint(child_origin, visible_bounds, cx);
match self.axis {
Axis::Horizontal => child_origin += vec2f(child.size().x(), 0.0),
Axis::Vertical => child_origin += vec2f(0.0, child.size().y()),
}
}
- if *overflowing {
+ if overflowing {
cx.scene.pop_layer();
}
}
@@ -224,25 +237,38 @@ impl Element for Flex {
}
struct FlexParentData {
- flex: f32,
- expanded: bool,
+ flex: Option<(f32, bool)>,
+ float: bool,
}
-pub struct Flexible {
+pub struct FlexItem {
metadata: FlexParentData,
child: ElementBox,
}
-impl Flexible {
- pub fn new(flex: f32, expanded: bool, child: ElementBox) -> Self {
- Flexible {
- metadata: FlexParentData { flex, expanded },
+impl FlexItem {
+ pub fn new(child: ElementBox) -> Self {
+ FlexItem {
+ metadata: FlexParentData {
+ flex: None,
+ float: false,
+ },
child,
}
}
+
+ pub fn flex(mut self, flex: f32, expanded: bool) -> Self {
+ self.metadata.flex = Some((flex, expanded));
+ self
+ }
+
+ pub fn float(mut self) -> Self {
+ self.metadata.float = true;
+ self
+ }
}
-impl Element for Flexible {
+impl Element for FlexItem {
type LayoutState = ();
type PaintState = ();
@@ -77,7 +77,11 @@ impl View for OutlineView {
.with_style(settings.theme.selector.input_editor.container)
.boxed(),
)
- .with_child(Flexible::new(1.0, false, self.render_matches(cx)).boxed())
+ .with_child(
+ FlexItem::new(self.render_matches(cx))
+ .flex(1.0, false)
+ .boxed(),
+ )
.contained()
.with_style(settings.theme.selector.container)
.constrained()
@@ -76,7 +76,11 @@ impl View for ProjectSymbolsView {
.with_style(settings.theme.selector.input_editor.container)
.boxed(),
)
- .with_child(Flexible::new(1.0, false, self.render_matches(cx)).boxed())
+ .with_child(
+ FlexItem::new(self.render_matches(cx))
+ .flex(1., false)
+ .boxed(),
+ )
.contained()
.with_style(settings.theme.selector.container)
.constrained()
@@ -82,11 +82,7 @@ impl View for BufferSearchBar {
Flex::row()
.with_child(
Flex::row()
- .with_child(
- ChildView::new(&self.query_editor)
- .flexible(1., true)
- .boxed(),
- )
+ .with_child(ChildView::new(&self.query_editor).flex(1., true).boxed())
.with_children(self.active_editor.as_ref().and_then(|editor| {
let matches = self.editors_with_matches.get(&editor.downgrade())?;
let message = if let Some(match_ix) = self.active_match_index {
@@ -164,12 +164,10 @@ impl View for ProjectSearchView {
.aligned()
.contained()
.with_background_color(theme.editor.background)
- .flexible(1., true)
+ .flex(1., true)
.boxed()
} else {
- ChildView::new(&self.results_editor)
- .flexible(1., true)
- .boxed()
+ ChildView::new(&self.results_editor).flex(1., true).boxed()
}
}
@@ -691,11 +689,7 @@ impl View for ProjectSearchBar {
Flex::row()
.with_child(
Flex::row()
- .with_child(
- ChildView::new(&search.query_editor)
- .flexible(1., true)
- .boxed(),
- )
+ .with_child(ChildView::new(&search.query_editor).flex(1., true).boxed())
.with_children(search.active_match_index.map(|match_ix| {
Label::new(
format!(
@@ -310,7 +310,11 @@ impl View for ThemeSelector {
.with_style(theme.selector.input_editor.container)
.boxed(),
)
- .with_child(Flexible::new(1.0, false, self.render_matches(cx)).boxed())
+ .with_child(
+ FlexItem::new(self.render_matches(cx))
+ .flex(1., false)
+ .boxed(),
+ )
.boxed(),
)
.with_style(theme.selector.container)
@@ -612,7 +612,7 @@ impl Pane {
Empty::new()
.contained()
.with_border(theme.workspace.tab.container.border)
- .flexible(0., true)
+ .flex(0., true)
.named("filler"),
);
@@ -641,7 +641,7 @@ impl View for Pane {
Flex::column()
.with_child(self.render_tabs(cx))
.with_child(ChildView::new(&self.toolbar).boxed())
- .with_child(ChildView::new(active_item).flexible(1., true).boxed())
+ .with_child(ChildView::new(active_item).flex(1., true).boxed())
.boxed()
} else {
Empty::new().boxed()
@@ -248,7 +248,7 @@ impl PaneAxis {
member = Container::new(member).with_border(border).boxed();
}
- Flexible::new(1.0, true, member).boxed()
+ FlexItem::new(member).flex(1.0, true).boxed()
}))
.boxed()
}
@@ -138,7 +138,7 @@ impl Sidebar {
let width = self.width.clone();
move |size, _| *width.borrow_mut() = size.x()
})
- .flexible(1., false)
+ .flex(1., false)
.boxed(),
);
if matches!(self.side, Side::Left) {
@@ -47,12 +47,12 @@ impl View for StatusBar {
.with_margin_right(theme.item_spacing)
.boxed()
}))
- .with_child(Empty::new().flexible(1., true).boxed())
.with_children(self.right_items.iter().map(|i| {
ChildView::new(i.as_ref())
.aligned()
.contained()
.with_margin_left(theme.item_spacing)
+ .flex_float()
.boxed()
}))
.contained()
@@ -46,12 +46,12 @@ impl View for Toolbar {
.with_margin_right(theme.item_spacing)
.boxed()
}))
- .with_child(Empty::new().flexible(1., true).boxed())
.with_children(self.right_items.iter().map(|i| {
ChildView::new(i.as_ref())
.aligned()
.contained()
.with_margin_left(theme.item_spacing)
+ .flex_float()
.boxed()
}))
.contained()
@@ -1946,36 +1946,35 @@ impl View for Workspace {
if let Some(element) =
self.left_sidebar.render_active_item(&theme, cx)
{
- content.add_child(Flexible::new(0.8, false, element).boxed());
+ content
+ .add_child(FlexItem::new(element).flex(0.8, false).boxed());
}
content.add_child(
Flex::column()
.with_child(
- Flexible::new(
- 1.,
- true,
- self.center.render(
- &theme,
- &self.follower_states_by_leader,
- self.project.read(cx).collaborators(),
- ),
- )
+ FlexItem::new(self.center.render(
+ &theme,
+ &self.follower_states_by_leader,
+ self.project.read(cx).collaborators(),
+ ))
+ .flex(1., true)
.boxed(),
)
.with_child(ChildView::new(&self.status_bar).boxed())
- .flexible(1., true)
+ .flex(1., true)
.boxed(),
);
if let Some(element) =
self.right_sidebar.render_active_item(&theme, cx)
{
- content.add_child(Flexible::new(0.8, false, element).boxed());
+ content
+ .add_child(FlexItem::new(element).flex(0.8, false).boxed());
}
content.add_child(self.right_sidebar.render(&theme, cx));
content.boxed()
})
.with_children(self.modal.as_ref().map(|m| ChildView::new(m).boxed()))
- .flexible(1.0, true)
+ .flex(1.0, true)
.boxed(),
)
.contained()