mirror of
https://github.com/slint-ui/slint.git
synced 2025-09-28 12:54:45 +00:00
Draft of the layouting runtime code
This commit is contained in:
parent
c966f6e546
commit
88e904d228
2 changed files with 90 additions and 0 deletions
89
sixtyfps_runtime/corelib/layout.rs
Normal file
89
sixtyfps_runtime/corelib/layout.rs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
type Coord = f32;
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct LayoutData {
|
||||||
|
// inputs
|
||||||
|
min: Coord,
|
||||||
|
max: Coord,
|
||||||
|
pref: Coord,
|
||||||
|
stretch: f32,
|
||||||
|
|
||||||
|
// outputs
|
||||||
|
pos: Coord,
|
||||||
|
size: Coord,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Layout the items within a specified size
|
||||||
|
///
|
||||||
|
/// This is quite a simple implementation for now
|
||||||
|
pub fn layout_items(data: &mut [LayoutData], start_pos: Coord, size: Coord) {
|
||||||
|
let (min, _max, perf, mut s) = data.iter().fold((0., 0., 0., 0.), |(min, max, pref, s), it| {
|
||||||
|
(min + it.min, max + it.max, pref + it.pref, s + it.stretch)
|
||||||
|
});
|
||||||
|
if size >= perf {
|
||||||
|
// bigger than the prefered size
|
||||||
|
|
||||||
|
// distribute each item its prefered size
|
||||||
|
let mut pos = start_pos;
|
||||||
|
for it in data.iter_mut() {
|
||||||
|
it.size = it.pref;
|
||||||
|
it.pos = pos;
|
||||||
|
pos += it.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate the space according to the stretch. Until all space is distributed, or all item
|
||||||
|
// have reached their maximum size
|
||||||
|
let mut extra_space = size - perf;
|
||||||
|
while s > 0. && extra_space > 0. {
|
||||||
|
let extra_per_stretch = extra_space / s;
|
||||||
|
s = 0.;
|
||||||
|
let mut pos = start_pos;
|
||||||
|
for it in data.iter_mut() {
|
||||||
|
let give = (extra_per_stretch * it.stretch).min(it.max - it.size);
|
||||||
|
it.size += give;
|
||||||
|
extra_space -= give;
|
||||||
|
if give > 0. {
|
||||||
|
s += it.stretch;
|
||||||
|
}
|
||||||
|
it.pos = pos;
|
||||||
|
pos += it.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
/*if size < min*/
|
||||||
|
{
|
||||||
|
// We have less than the minimum size
|
||||||
|
// distribute the difference proportional to the size (TODO: and stretch)
|
||||||
|
let ratio = size / min;
|
||||||
|
let mut pos = start_pos;
|
||||||
|
for it in data {
|
||||||
|
it.size = it.min * ratio;
|
||||||
|
it.pos = pos;
|
||||||
|
pos += it.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_layout_items() {
|
||||||
|
let my_items = &mut [
|
||||||
|
LayoutData { min: 100., max: 200., pref: 100., stretch: 1., ..Default::default() },
|
||||||
|
LayoutData { min: 50., max: 300., pref: 100., stretch: 1., ..Default::default() },
|
||||||
|
LayoutData { min: 50., max: 150., pref: 100., stretch: 1., ..Default::default() },
|
||||||
|
];
|
||||||
|
|
||||||
|
layout_items(my_items, 100., 650.);
|
||||||
|
assert_eq!(my_items[0].size, 200.);
|
||||||
|
assert_eq!(my_items[1].size, 300.);
|
||||||
|
assert_eq!(my_items[2].size, 150.);
|
||||||
|
|
||||||
|
layout_items(my_items, 100., 200.);
|
||||||
|
assert_eq!(my_items[0].size, 100.);
|
||||||
|
assert_eq!(my_items[1].size, 50.);
|
||||||
|
assert_eq!(my_items[2].size, 50.);
|
||||||
|
|
||||||
|
layout_items(my_items, 100., 300.);
|
||||||
|
assert_eq!(my_items[0].size, 100.);
|
||||||
|
assert_eq!(my_items[1].size, 100.);
|
||||||
|
assert_eq!(my_items[2].size, 100.);
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ use core::ptr::NonNull;
|
||||||
use kurbo::BezPath;
|
use kurbo::BezPath;
|
||||||
|
|
||||||
pub mod graphics;
|
pub mod graphics;
|
||||||
|
pub mod layout;
|
||||||
|
|
||||||
pub mod abi {
|
pub mod abi {
|
||||||
pub mod datastructures;
|
pub mod datastructures;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue