Skip to content

Commit

Permalink
feat: Support percentage of auto in layout (#784)
Browse files Browse the repository at this point in the history
  • Loading branch information
marc2332 authored Aug 4, 2024
1 parent 741ef65 commit f5c638b
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 21 deletions.
25 changes: 12 additions & 13 deletions crates/components/src/accordion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ use freya_elements::{
events::MouseEvent,
};
use freya_hooks::{
use_animation_with_dependencies,
use_animation,
use_applied_theme,
use_node,
use_platform,
AccordionTheme,
AccordionThemeWith,
AnimNum,
Ease,
Function,
};
use winit::window::CursorIcon;

Expand Down Expand Up @@ -43,10 +44,13 @@ pub struct AccordionProps {
pub fn Accordion(props: AccordionProps) -> Element {
let theme = use_applied_theme!(&props.theme, accordion);
let mut open = use_signal(|| false);
let (node_ref, size) = use_node();

let animation = use_animation_with_dependencies(&size.area.height(), move |ctx, height| {
ctx.with(AnimNum::new(0., height).time(200))
let animation = use_animation(move |ctx| {
ctx.with(
AnimNum::new(0., 100.)
.time(300)
.function(Function::Expo)
.ease(Ease::Out),
)
});
let mut status = use_signal(AccordionStatus::default);
let platform = use_platform();
Expand Down Expand Up @@ -101,13 +105,8 @@ pub fn Accordion(props: AccordionProps) -> Element {
rect {
overflow: "clip",
width: "100%",
height: "{animation_value}",
rect {
reference: node_ref,
height: "auto",
width: "100%",
{&props.children}
}
height: "{animation_value}a",
{&props.children}
}
}
)
Expand Down
7 changes: 7 additions & 0 deletions crates/state/src/values/size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ impl Parse for Size {
.parse::<f32>()
.map_err(|_| ParseError)?,
)))
} else if value.contains('a') {
Ok(Size::InnerPercentage(Length::new(
value
.replace('a', "")
.parse::<f32>()
.map_err(|_| ParseError)?,
)))
} else {
Ok(Size::Pixels(Length::new(
value.parse::<f32>().map_err(|_| ParseError)?,
Expand Down
23 changes: 19 additions & 4 deletions crates/torin/src/geometry.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use crate::prelude::{
Alignment,
DirectionMode,
Gaps,
use crate::{
node::Node,
prelude::{
Alignment,
DirectionMode,
Gaps,
Size,
},
};

#[derive(PartialEq)]
Expand Down Expand Up @@ -42,6 +46,8 @@ pub trait AreaModel {
siblings_len: usize,
child_position: usize,
);

fn adjust_size(&mut self, node: &Node);
}

impl AreaModel for Area {
Expand Down Expand Up @@ -162,6 +168,15 @@ impl AreaModel for Area {
},
}
}

fn adjust_size(&mut self, node: &Node) {
if let Size::InnerPercentage(p) = node.width {
self.size.width *= p.get() / 100.;
}
if let Size::InnerPercentage(p) = node.height {
self.size.height *= p.get() / 100.;
}
}
}

pub fn get_align_axis(
Expand Down
5 changes: 4 additions & 1 deletion crates/torin/src/measure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ pub fn measure_inner_nodes<Key: NodeKey>(
let inner_area = *mode.inner_area();

// Final measurement
let (child_revalidated, child_areas) = measure_node(
let (child_revalidated, mut child_areas) = measure_node(
child_id,
&child_data,
layout,
Expand All @@ -424,6 +424,9 @@ pub fn measure_inner_nodes<Key: NodeKey>(
Phase::Final,
);

// Adjust the size of the area if needed
child_areas.area.adjust_size(&child_data);

// Stack the child into its parent
mode.stack_into_node(
parent_node,
Expand Down
5 changes: 4 additions & 1 deletion crates/torin/src/torin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ impl<Key: NodeKey> Torin<Key> {
available_area.move_with_offsets(&root_parent.offset_x, &root_parent.offset_y);
}

let (root_revalidated, root_layout_node) = measure_node(
let (root_revalidated, mut root_layout_node) = measure_node(
root_id,
&root,
self,
Expand All @@ -287,6 +287,9 @@ impl<Key: NodeKey> Torin<Key> {
Phase::Final,
);

// Adjust the size of the area if needed
root_layout_node.area.adjust_size(&root);

// Cache the root Node results if it was modified
if root_revalidated {
if let Some(measurer) = measurer {
Expand Down
13 changes: 11 additions & 2 deletions crates/torin/src/values/size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub enum Size {
Percentage(Length),
Pixels(Length),
RootPercentage(Length),
InnerPercentage(Length),
DynamicCalculations(Box<Vec<DynamicCalculation>>),
}

Expand All @@ -27,7 +28,14 @@ impl Default for Size {

impl Size {
pub fn inner_sized(&self) -> bool {
matches!(self, Self::Inner | Self::FillMinimum)
matches!(
self,
Self::Inner | Self::FillMinimum | Self::InnerPercentage(_)
)
}

pub fn inner_percentage_sized(&self) -> bool {
matches!(self, Self::InnerPercentage(_))
}

pub fn pretty(&self) -> String {
Expand All @@ -46,6 +54,7 @@ impl Size {
Size::Fill => "fill".to_string(),
Size::FillMinimum => "fill-min".to_string(),
Size::RootPercentage(p) => format!("{}% of root", p.get()),
Size::InnerPercentage(p) => format!("{}% of auto", p.get()),
}
}

Expand Down Expand Up @@ -135,7 +144,7 @@ impl Size {

pub fn most_fitting_size<'a>(&self, size: &'a f32, available_size: &'a f32) -> &'a f32 {
match self {
Self::Inner => available_size,
Self::Inner | Self::InnerPercentage(_) => available_size,
_ => size,
}
}
Expand Down
59 changes: 59 additions & 0 deletions crates/torin/tests/size.rs
Original file line number Diff line number Diff line change
Expand Up @@ -718,3 +718,62 @@ pub fn content_fit_fill_min() {
Rect::new(Point2D::new(0.0, 600.0), Size2D::new(100.0, 300.0)),
);
}

#[test]
pub fn inner_percentage() {
let (mut layout, mut measurer) = test_utils();

let mut mocked_dom = TestingDOM::default();
mocked_dom.add(
0,
None,
vec![1, 2],
Node::from_size_and_direction(
Size::Inner,
Size::InnerPercentage(Length::new(50.0)),
DirectionMode::Vertical,
),
);
mocked_dom.add(
1,
Some(0),
vec![],
Node::from_size_and_direction(
Size::Inner,
Size::Percentage(Length::new(30.0)),
DirectionMode::Vertical,
),
);
mocked_dom.add(
2,
Some(0),
vec![],
Node::from_size_and_direction(
Size::Pixels(Length::new(100.0)),
Size::Pixels(Length::new(100.0)),
DirectionMode::Vertical,
),
);

layout.measure(
0,
Rect::new(Point2D::new(0.0, 0.0), Size2D::new(1000.0, 1000.0)),
&mut measurer,
&mut mocked_dom,
);

assert_eq!(
layout.get(0).unwrap().visible_area(),
Rect::new(Point2D::new(0.0, 0.0), Size2D::new(100.0, 200.0)),
);

assert_eq!(
layout.get(1).unwrap().visible_area(),
Rect::new(Point2D::new(0.0, 0.0), Size2D::new(0.0, 300.0)),
);

assert_eq!(
layout.get(2).unwrap().visible_area(),
Rect::new(Point2D::new(0.0, 300.0), Size2D::new(100.0, 100.0)),
);
}

0 comments on commit f5c638b

Please sign in to comment.