switch to element defined span lens + better size fn
This commit is contained in:
@@ -7,11 +7,12 @@ pub struct Aligned {
|
||||
|
||||
impl Widget for Aligned {
|
||||
fn draw(&mut self, painter: &mut Painter) {
|
||||
let region = UiRegion::from_ui_size_align(painter.size(&self.inner), self.align);
|
||||
let region =
|
||||
UiRegion::from_ui_size_align(painter.size(&self.inner).to_uivec2(), self.align);
|
||||
painter.widget_within(&self.inner, region);
|
||||
}
|
||||
|
||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> UiVec2 {
|
||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> Size {
|
||||
ctx.size(&self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ impl Widget for Offset {
|
||||
painter.widget_within(&self.inner, region);
|
||||
}
|
||||
|
||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> UiVec2 {
|
||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> Size {
|
||||
ctx.size(&self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,22 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
pub struct Padded {
|
||||
pub struct Pad {
|
||||
pub padding: Padding,
|
||||
pub inner: WidgetId,
|
||||
}
|
||||
|
||||
impl Widget for Padded {
|
||||
impl Widget for Pad {
|
||||
fn draw(&mut self, painter: &mut Painter) {
|
||||
painter.widget_within(&self.inner, self.padding.region());
|
||||
}
|
||||
|
||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> UiVec2 {
|
||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> Size {
|
||||
let mut size = ctx.size(&self.inner);
|
||||
// TODO: this is currently a hack
|
||||
// the correct solution is that the position is not linear
|
||||
// becauase if you have 0.5 rel + 100 abs, it's linear
|
||||
// until you fill up parent rel (in abs units) and then 1.0 rel (piecewise linear)
|
||||
// so I guess yet another detection system is needed
|
||||
// to determine when abs translated to rel + rel > 1.0
|
||||
// hopefully find a way to get working on gpu so no cpu changing needed
|
||||
// eg by sending size to calculate above and then doing... something?
|
||||
if size.rel.x != 1.0 {
|
||||
size.abs.x += self.padding.left + self.padding.right;
|
||||
if size.x.rest == 0.0 {
|
||||
size.x.abs += self.padding.left + self.padding.right;
|
||||
}
|
||||
if size.rel.y != 1.0 {
|
||||
size.abs.y += self.padding.top + self.padding.bottom;
|
||||
if size.y.rest == 0.0 {
|
||||
size.y.abs += self.padding.top + self.padding.bottom;
|
||||
}
|
||||
size
|
||||
}
|
||||
|
||||
@@ -2,7 +2,8 @@ use crate::prelude::*;
|
||||
|
||||
pub struct Sized {
|
||||
pub inner: WidgetId,
|
||||
pub size: Vec2,
|
||||
pub x: Option<Len>,
|
||||
pub y: Option<Len>,
|
||||
}
|
||||
|
||||
impl Widget for Sized {
|
||||
@@ -10,7 +11,10 @@ impl Widget for Sized {
|
||||
painter.widget(&self.inner);
|
||||
}
|
||||
|
||||
fn desired_size(&mut self, _: &mut SizeCtx) -> UiVec2 {
|
||||
UiVec2::abs(self.size)
|
||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> Size {
|
||||
Size {
|
||||
x: self.x.unwrap_or_else(|| ctx.size(&self.inner).x),
|
||||
y: self.y.unwrap_or_else(|| ctx.size(&self.inner).y),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,26 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
pub struct Span {
|
||||
pub children: Vec<(WidgetId, SpanLen)>,
|
||||
pub children: Vec<WidgetId>,
|
||||
pub dir: Dir,
|
||||
pub spacing: f32,
|
||||
}
|
||||
|
||||
impl Widget for Span {
|
||||
fn draw(&mut self, painter: &mut Painter) {
|
||||
let total = self.setup(&mut painter.size_ctx());
|
||||
let total = self.len_sum(&mut painter.size_ctx());
|
||||
let mut start = UiScalar::rel_min();
|
||||
for (child, length) in &self.children {
|
||||
for child in &self.children {
|
||||
let mut child_region = UiRegion::full();
|
||||
let mut axis = child_region.axis_mut(self.dir.axis);
|
||||
axis.top_left.set(start);
|
||||
match *length {
|
||||
SpanLen::Fixed(offset) => {
|
||||
start.abs += offset;
|
||||
}
|
||||
SpanLen::Ratio(ratio) => {
|
||||
let offset = UiScalar::new(total.rel, total.abs);
|
||||
let rel_end = UiScalar::from_anchor(ratio / total.ratio);
|
||||
start = rel_end.within(start, (UiScalar::rel_max() + start) - offset);
|
||||
}
|
||||
SpanLen::Relative(rel) => {
|
||||
start.rel += rel;
|
||||
}
|
||||
SpanLen::Sized(size) => {
|
||||
let size_axis = size.axis(self.dir.axis);
|
||||
start.abs += size_axis.abs;
|
||||
start.rel += size_axis.rel;
|
||||
}
|
||||
let len = painter.size(child).axis(self.dir.axis);
|
||||
start.abs += len.abs;
|
||||
start.rel += len.rel;
|
||||
if len.rest > 0.0 {
|
||||
let offset = UiScalar::new(total.rel, total.abs);
|
||||
let rel_end = UiScalar::from_anchor(len.rest / total.rest);
|
||||
start = rel_end.within(start, (UiScalar::rel_max() + start) - offset);
|
||||
}
|
||||
axis.bot_right.set(start);
|
||||
if self.dir.sign == Sign::Neg {
|
||||
@@ -41,33 +31,29 @@ impl Widget for Span {
|
||||
}
|
||||
}
|
||||
|
||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> UiVec2 {
|
||||
let total = self.setup(ctx);
|
||||
let axis = self.dir.axis;
|
||||
let dir_len = if total.ratio != 0.0 {
|
||||
UiScalar::rel_max()
|
||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> Size {
|
||||
let mut sums = self.len_sum(ctx);
|
||||
let dir_len = if sums.rest == 0.0 && sums.rel == 0.0 {
|
||||
sums.abs += self.spacing * self.children.len().saturating_sub(1) as f32;
|
||||
sums
|
||||
} else {
|
||||
UiScalar::new(
|
||||
total.rel,
|
||||
total.abs + self.spacing * self.children.len().saturating_sub(1) as f32,
|
||||
)
|
||||
Len::default()
|
||||
};
|
||||
let mut max_ortho = UiScalar::ZERO;
|
||||
for (child, _) in &self.children {
|
||||
let size = ctx.size(child);
|
||||
max_ortho = max_ortho.max(size.axis(!self.dir.axis));
|
||||
let mut max_ortho = Len::ZERO;
|
||||
for child in &self.children {
|
||||
let len = ctx.size(child).axis(!self.dir.axis);
|
||||
// TODO: rel shouldn't do this, but no easy way before actually calculating pixels
|
||||
if len.rel > 0.0 || len.rest > 0.0 {
|
||||
max_ortho.rest = 1.0;
|
||||
max_ortho.abs = 0.0;
|
||||
break;
|
||||
}
|
||||
max_ortho.abs = max_ortho.abs.max(len.abs);
|
||||
}
|
||||
UiVec2::from_axis(axis, dir_len, max_ortho)
|
||||
Size::from_axis(self.dir.axis, dir_len, max_ortho)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SpanLenSums {
|
||||
pub abs: f32,
|
||||
pub ratio: f32,
|
||||
pub rel: f32,
|
||||
}
|
||||
|
||||
impl Span {
|
||||
pub fn empty(dir: Dir) -> Self {
|
||||
Self {
|
||||
@@ -82,61 +68,10 @@ impl Span {
|
||||
self
|
||||
}
|
||||
|
||||
fn setup(&mut self, ctx: &mut SizeCtx) -> SpanLenSums {
|
||||
self.children
|
||||
.iter_mut()
|
||||
.fold(SpanLenSums::default(), |mut s, (id, l)| {
|
||||
match l {
|
||||
SpanLen::Fixed(v) => s.abs += *v,
|
||||
SpanLen::Ratio(v) => s.ratio += *v,
|
||||
SpanLen::Relative(v) => s.rel += *v,
|
||||
SpanLen::Sized(v) => {
|
||||
let size = ctx.size(id);
|
||||
let len = size.axis(self.dir.axis);
|
||||
*v = size;
|
||||
s.abs += len.abs;
|
||||
s.rel += len.rel;
|
||||
}
|
||||
}
|
||||
s
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum SpanLen {
|
||||
/// exact (non dynamic) size
|
||||
Fixed(f32),
|
||||
/// relative to remaining free space and other ratios
|
||||
/// eg. 1 and 2 would take up 1/3 and 2/3 of the remaining space (after others)
|
||||
Ratio(f32),
|
||||
/// relative to the total space (of the entire span)
|
||||
/// eg. 0.5 means 1/2 of the total space
|
||||
Relative(f32),
|
||||
/// size determined by the child widget itself
|
||||
/// the value is not used externally, I just don't wanna make a duplicate enum
|
||||
/// there are util functions instead so
|
||||
Sized(UiVec2),
|
||||
}
|
||||
|
||||
pub fn fixed<N: UiNum>(x: N) -> SpanLen {
|
||||
SpanLen::Fixed(x.to_f32())
|
||||
}
|
||||
|
||||
pub fn ratio<N: UiNum>(x: N) -> SpanLen {
|
||||
SpanLen::Ratio(x.to_f32())
|
||||
}
|
||||
|
||||
pub fn relative<N: UiNum>(x: N) -> SpanLen {
|
||||
SpanLen::Relative(x.to_f32())
|
||||
}
|
||||
|
||||
pub fn sized() -> SpanLen {
|
||||
SpanLen::Sized(UiVec2::default())
|
||||
}
|
||||
|
||||
impl<N: UiNum> From<N> for SpanLen {
|
||||
fn from(value: N) -> Self {
|
||||
Self::Ratio(value.to_f32())
|
||||
fn len_sum(&mut self, ctx: &mut SizeCtx) -> Len {
|
||||
self.children.iter_mut().fold(Len::ZERO, |mut s, id| {
|
||||
s += ctx.size(id).axis(self.dir.axis);
|
||||
s
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,9 +24,9 @@ impl Widget for Stack {
|
||||
}
|
||||
}
|
||||
|
||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> UiVec2 {
|
||||
fn desired_size(&mut self, ctx: &mut SizeCtx) -> Size {
|
||||
match self.size {
|
||||
StackSize::Full => UiVec2::MAX_SIZE,
|
||||
StackSize::Default => Size::default(),
|
||||
StackSize::Child(i) => ctx.size(&self.children[i]),
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ impl Widget for Stack {
|
||||
#[derive(Default, Debug)]
|
||||
pub enum StackSize {
|
||||
#[default]
|
||||
Full,
|
||||
Default,
|
||||
Child(usize),
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user