@@ -3,7 +3,7 @@ use crate::{
LayoutContext, PaintContext, SizeConstraint,
};
use json::ToJson;
-use pathfinder_geometry::vector::{vec2f, Vector2F};
+use pathfinder_geometry::vector::Vector2F;
use serde_json::json;
pub struct Align {
@@ -19,8 +19,13 @@ impl Align {
}
}
- pub fn top_center(mut self) -> Self {
- self.alignment = vec2f(0.0, -1.0);
+ pub fn top(mut self) -> Self {
+ self.alignment.set_y(-1.0);
+ self
+ }
+
+ pub fn right(mut self) -> Self {
+ self.alignment.set_x(1.0);
self
}
}
@@ -23,6 +23,11 @@ impl ConstrainedBox {
}
}
+ pub fn with_min_width(mut self, min_width: f32) -> Self {
+ self.constraint.min.set_x(min_width);
+ self
+ }
+
pub fn with_max_width(mut self, max_width: f32) -> Self {
self.constraint.max.set_x(max_width);
self
@@ -33,6 +38,12 @@ impl ConstrainedBox {
self
}
+ pub fn with_width(mut self, width: f32) -> Self {
+ self.constraint.min.set_x(width);
+ self.constraint.max.set_x(width);
+ self
+ }
+
pub fn with_height(mut self, height: f32) -> Self {
self.constraint.min.set_y(height);
self.constraint.max.set_y(height);
@@ -51,6 +62,7 @@ impl Element for ConstrainedBox {
) -> (Vector2F, Self::LayoutState) {
constraint.min = constraint.min.max(self.constraint.min);
constraint.max = constraint.max.min(self.constraint.max);
+ constraint.max = constraint.max.max(constraint.min);
let size = self.child.layout(constraint, ctx);
(size, ())
}
@@ -43,6 +43,18 @@ impl Container {
self
}
+ pub fn with_horizontal_padding(mut self, padding: f32) -> Self {
+ self.padding.left = padding;
+ self.padding.right = padding;
+ self
+ }
+
+ pub fn with_vertical_padding(mut self, padding: f32) -> Self {
+ self.padding.top = padding;
+ self.padding.bottom = padding;
+ self
+ }
+
pub fn with_uniform_padding(mut self, padding: f32) -> Self {
self.padding = Padding {
top: padding,
@@ -1,4 +1,4 @@
-use std::any::Any;
+use std::{any::Any, f32::INFINITY};
use crate::{
json::{self, ToJson, Value},
@@ -88,9 +88,13 @@ 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 {
- let space_per_flex = remaining_space / remaining_flex;
if let Some(flex) = Self::child_flex(&child) {
- let child_max = space_per_flex * 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_constraint = match self.axis {
Axis::Horizontal => SizeConstraint::new(
vec2f(0.0, constraint.min.y()),
@@ -192,33 +192,28 @@ impl Pane {
let padding = 6.;
let mut container = Container::new(
- Align::new(
- Flex::row()
- .with_child(
+ Stack::new()
+ .with_child(
+ Align::new(
Label::new(title, settings.ui_font_family, settings.ui_font_size)
.boxed(),
)
- .with_child(
- Container::new(
- LineBox::new(
- settings.ui_font_family,
- settings.ui_font_size,
- ConstrainedBox::new(Self::render_modified_icon(
- item.is_dirty(app),
- ))
- .with_max_width(12.)
- .boxed(),
- )
+ .boxed(),
+ )
+ .with_child(
+ LineBox::new(
+ settings.ui_font_family,
+ settings.ui_font_size,
+ Align::new(Self::render_modified_icon(item.is_dirty(app)))
+ .right()
.boxed(),
- )
- .with_margin_left(20.)
- .boxed(),
)
.boxed(),
- )
- .boxed(),
+ )
+ .boxed(),
)
- .with_uniform_padding(padding)
+ .with_vertical_padding(padding)
+ .with_horizontal_padding(10.)
.with_border(border);
if ix == self.active_item {
@@ -240,6 +235,7 @@ impl Pane {
})
.boxed(),
)
+ .with_min_width(80.0)
.with_max_width(264.0)
.boxed(),
)
@@ -247,9 +243,29 @@ impl Pane {
);
}
+ // Ensure there's always a minimum amount of space after the last tab,
+ // so that the tab's border doesn't abut the window's border.
+ row.add_child(
+ ConstrainedBox::new(
+ Container::new(
+ LineBox::new(
+ settings.ui_font_family,
+ settings.ui_font_size,
+ Empty::new().boxed(),
+ )
+ .boxed(),
+ )
+ .with_uniform_padding(6.0)
+ .with_border(Border::bottom(1.0, border_color))
+ .boxed(),
+ )
+ .with_min_width(20.)
+ .named("fixed-filler"),
+ );
+
row.add_child(
Expanded::new(
- 1.0,
+ 0.0,
Container::new(
LineBox::new(
settings.ui_font_family,
@@ -269,23 +285,24 @@ impl Pane {
}
fn render_modified_icon(is_modified: bool) -> ElementBox {
- Canvas::new(move |bounds, ctx| {
- if is_modified {
- let padding = if bounds.height() < bounds.width() {
- vec2f(bounds.width() - bounds.height(), 0.0)
- } else {
- vec2f(0.0, bounds.height() - bounds.width())
- };
- let square = RectF::new(bounds.origin() + padding / 2., bounds.size() - padding);
- ctx.scene.push_quad(Quad {
- bounds: square,
- background: Some(ColorF::new(0.639, 0.839, 1.0, 1.0).to_u8()),
- border: Default::default(),
- corner_radius: square.width() / 2.,
- });
- }
- })
- .boxed()
+ let diameter = 8.;
+ ConstrainedBox::new(
+ Canvas::new(move |bounds, ctx| {
+ if is_modified {
+ let square = RectF::new(bounds.origin(), vec2f(diameter, diameter));
+ ctx.scene.push_quad(Quad {
+ bounds: square,
+ background: Some(ColorF::new(0.639, 0.839, 1.0, 1.0).to_u8()),
+ border: Default::default(),
+ corner_radius: diameter / 2.,
+ });
+ }
+ })
+ .boxed(),
+ )
+ .with_width(diameter)
+ .with_height(diameter)
+ .named("tab-right-icon")
}
}