From 7cd04247b80dfedf83b5d9efd04c1bc5ce3047e2 Mon Sep 17 00:00:00 2001 From: griffi-gh Date: Tue, 28 Nov 2023 10:31:38 +0100 Subject: [PATCH] fix stuff --- kubi-ui/examples/test.rs | 54 +++++++++++++- kubi-ui/src/element/builtin/container.rs | 93 +++++++++++++++++------- 2 files changed, 117 insertions(+), 30 deletions(-) diff --git a/kubi-ui/examples/test.rs b/kubi-ui/examples/test.rs index eada74f..4895626 100644 --- a/kubi-ui/examples/test.rs +++ b/kubi-ui/examples/test.rs @@ -1,5 +1,5 @@ use std::time::Instant; -use glam::{Vec2, IVec2, UVec2}; +use glam::{Vec2, IVec2, UVec2, vec4}; use glium::{backend::glutin::SimpleWindowBuilder, Surface}; use winit::{ event::{Event, WindowEvent}, @@ -7,7 +7,7 @@ use winit::{ }; use kubi_ui::{ KubiUi, - backend::glium::GliumUiRenderer, element::{progress_bar::ProgressBar, container::{Container, Sides}, UiElement}, UiSize + backend::glium::GliumUiRenderer, element::{progress_bar::ProgressBar, container::{Container, Sides, Alignment}, UiElement, rect::Rect}, UiSize, UiDirection }; fn main() { @@ -37,6 +37,7 @@ fn main() { kui.add(Container { gap: 5., padding: Sides::all(5.), + align: (Alignment::Center, Alignment::Center), elements: vec![ Box::new(ProgressBar { value: 0.5, @@ -46,6 +47,55 @@ fn main() { value: instant.elapsed().as_secs_f32().sin().powi(2), ..Default::default() }), + Box::new(Container { + size: (UiSize::Percentage(1.), UiSize::Auto), + align: (Alignment::Center, Alignment::End), + padding: Sides::all(5.), + gap: 10., + elements: vec![ + Box::new(Rect { + size: (UiSize::Percentage(0.5), UiSize::Pixels(30.)), + color: Some(vec4(0.75, 0., 0., 1.)) + }), + Box::new(Rect { + size: (UiSize::Percentage(instant.elapsed().as_secs_f32().cos().powi(2) / 2. + 0.5), UiSize::Pixels(30.)), + color: Some(vec4(0., 0.75, 0., 1.)) + }), + ], + ..Default::default() + }), + Box::new(Container { + gap: 5., + padding: Sides::all(5.), + background: Some(vec4(0., 0., 0., 0.5)), + direction: UiDirection::Horizontal, + elements: { + let mut x: Vec> = vec![]; + for i in 0..10 { + x.push(Box::new(Rect { + size: (UiSize::Pixels(50.), UiSize::Pixels(50.)), + color: if i == 1 { + Some(vec4(0.75, 0.75, 0.75, 0.75)) + } else { + Some(vec4(0.5, 0.5, 0.5, 0.75)) + } + })); + } + x + }, + ..Default::default() + }), + Box::new(Container { + background: Some(vec4(1., 0., 0., 1.)), + padding: Sides::horizontal_vertical(30., 5.), + elements: vec![ + Box::new(Rect { + size: (UiSize::Pixels(50.), UiSize::Pixels(50.)), + color: Some(vec4(1., 1., 1., 0.75)) + }) + ], + ..Default::default() + }) ], ..Default::default() }, resolution); diff --git a/kubi-ui/src/element/builtin/container.rs b/kubi-ui/src/element/builtin/container.rs index 88335de..fe57116 100644 --- a/kubi-ui/src/element/builtin/container.rs +++ b/kubi-ui/src/element/builtin/container.rs @@ -9,6 +9,7 @@ use crate::{ element::UiElement }; +#[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum Alignment { Begin, Center, @@ -51,8 +52,9 @@ impl Sides { } pub struct Container { - pub min_size: (UiSize, UiSize), - pub max_size: (UiSize, UiSize), + // pub min_size: (UiSize, UiSize), + // pub max_size: (UiSize, UiSize), + pub size: (UiSize, UiSize), pub direction: UiDirection, //pub reverse: bool, pub gap: f32, @@ -67,13 +69,15 @@ pub struct Container { impl Default for Container { fn default() -> Self { Self { - min_size: (UiSize::Auto, UiSize::Auto), - max_size: (UiSize::Auto, UiSize::Auto), + // min_size: (UiSize::Auto, UiSize::Auto), + // max_size: (UiSize::Auto, UiSize::Auto), + size: (UiSize::Auto, UiSize::Auto), direction: UiDirection::Vertical, //reverse: false, gap: 0., padding: Sides::all(0.), - align: (Alignment::Center, Alignment::Begin), + ///Primary/secondary axis + align: (Alignment::Begin, Alignment::Begin), background: Default::default(), borders: Default::default(), clip: Default::default(), @@ -83,7 +87,7 @@ impl Default for Container { } impl Container { - pub fn measure_max_size(&self, layout: &LayoutInfo) -> Vec2 { + pub fn measure_max_inner_size(&self, layout: &LayoutInfo) -> Vec2 { layout.max_size - vec2( self.padding.left + self.padding.right, self.padding.top + self.padding.bottom, @@ -94,27 +98,43 @@ impl Container { impl UiElement for Container { fn measure(&self, state: &StateRepo, layout: &LayoutInfo) -> Response { let mut size = Vec2::ZERO; - let mut leftover_gap = Vec2::ZERO; - for element in &self.elements { - let measure = element.measure(state, &LayoutInfo { - position: layout.position + size, - max_size: self.measure_max_size(layout), // - size TODO - direction: self.direction, - }); - match self.direction { - UiDirection::Horizontal => { - size.x += measure.desired_size.x + self.gap; - size.y = size.y.max(measure.desired_size.y); - leftover_gap.x = self.gap; - }, - UiDirection::Vertical => { - size.x = size.x.max(measure.desired_size.x); - size.y += measure.desired_size.y + self.gap; - leftover_gap.y = self.gap; + if matches!(self.size.0, UiSize::Auto) || matches!(self.size.1, UiSize::Auto) { + let mut leftover_gap = Vec2::ZERO; + for element in &self.elements { + let measure = element.measure(state, &LayoutInfo { + position: layout.position + size, + max_size: self.measure_max_inner_size(layout), // - size TODO + direction: self.direction, + }); + match self.direction { + UiDirection::Horizontal => { + size.x += measure.desired_size.x + self.gap; + size.y = size.y.max(measure.desired_size.y); + leftover_gap.x = self.gap; + }, + UiDirection::Vertical => { + size.x = size.x.max(measure.desired_size.x); + size.y += measure.desired_size.y + self.gap; + leftover_gap.y = self.gap; + } } } + size -= leftover_gap; + size += vec2( + self.padding.left + self.padding.right, + self.padding.top + self.padding.bottom, + ); + } + match self.size.0 { + UiSize::Auto => (), + UiSize::Percentage(percentage) => size.x = layout.max_size.x * percentage, + UiSize::Pixels(pixels) => size.x = pixels, + } + match self.size.1 { + UiSize::Auto => (), + UiSize::Percentage(percentage) => size.y = layout.max_size.y * percentage, + UiSize::Pixels(pixels) => size.y = pixels, } - size -= leftover_gap; Response { desired_size: size } } @@ -157,17 +177,34 @@ impl UiElement for Container { for element in &self.elements { //(passing max size from layout rather than actual bounds for the sake of consistency with measure() above) - let layout = LayoutInfo { + let mut el_layout = LayoutInfo { position, - max_size: self.measure_max_size(layout), + max_size: self.measure_max_inner_size(layout), direction: self.direction, }; //measure - let el_measure = element.measure(state, &layout); + let el_measure = element.measure(state, &el_layout); + + //align (on sec. axis) + match (self.align.1, self.direction) { + (Alignment::Begin, _) => (), + (Alignment::Center, UiDirection::Horizontal) => { + el_layout.position.y += (measure.desired_size.y - self.padding.bottom - self.padding.top - el_measure.desired_size.y) / 2.; + }, + (Alignment::Center, UiDirection::Vertical) => { + el_layout.position.x += (measure.desired_size.x - self.padding.left - self.padding.right - el_measure.desired_size.x) / 2.; + }, + (Alignment::End, UiDirection::Horizontal) => { + el_layout.position.y += measure.desired_size.y - el_measure.desired_size.y - self.padding.bottom; + }, + (Alignment::End, UiDirection::Vertical) => { + el_layout.position.x += measure.desired_size.x - el_measure.desired_size.x - self.padding.right; + } + } //process - element.process(&el_measure, state, &layout, draw); + element.process(&el_measure, state, &el_layout, draw); //layout match self.direction {