diff --git a/kubi-ui/examples/test.rs b/kubi-ui/examples/test.rs index 2a4b7a3..be02dd7 100644 --- a/kubi-ui/examples/test.rs +++ b/kubi-ui/examples/test.rs @@ -39,12 +39,23 @@ fn main() { kui.add(Container { gap: 5., padding: Sides::all(5.), - align: (Alignment::Center, Alignment::Center), + align: (Alignment::Begin, Alignment::Center), + size: (UiSize::Percentage(1.), UiSize::Percentage(1.)), elements: vec![ Box::new(ProgressBar { value: 0.5, ..Default::default() }), + ], + ..Default::default() + }, resolution); + + kui.add(Container { + gap: 5., + padding: Sides::all(5.), + align: (Alignment::End, Alignment::Center), + size: (UiSize::Percentage(1.), UiSize::Percentage(1.)), + elements: vec![ Box::new(ProgressBar { value: z, ..Default::default() diff --git a/kubi-ui/src/element/builtin/container.rs b/kubi-ui/src/element/builtin/container.rs index fe57116..f9b084c 100644 --- a/kubi-ui/src/element/builtin/container.rs +++ b/kubi-ui/src/element/builtin/container.rs @@ -4,7 +4,7 @@ use crate::{ UiSize, LayoutInfo, draw::UiDrawCommand, - measure::Response, + measure::{Response, Hints}, state::StateRepo, element::UiElement }; @@ -88,6 +88,7 @@ impl Default for Container { impl Container { pub fn measure_max_inner_size(&self, layout: &LayoutInfo) -> Vec2 { + //TODO take explicit size into account layout.max_size - vec2( self.padding.left + self.padding.right, self.padding.top + self.padding.bottom, @@ -98,33 +99,36 @@ impl Container { impl UiElement for Container { fn measure(&self, state: &StateRepo, layout: &LayoutInfo) -> Response { let mut size = Vec2::ZERO; - 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; - } + //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.size.x + self.gap; + size.y = size.y.max(measure.size.y); + leftover_gap.x = self.gap; + }, + UiDirection::Vertical => { + size.x = size.x.max(measure.size.x); + size.y += measure.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, - ); } + size -= leftover_gap; + + let inner_content_size = Some(size); + + 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, @@ -135,7 +139,15 @@ impl UiElement for Container { UiSize::Percentage(percentage) => size.y = layout.max_size.y * percentage, UiSize::Pixels(pixels) => size.y = pixels, } - Response { desired_size: size } + + Response { + size, + hints: Hints { + inner_content_size, + ..Default::default() + }, + user_data: None + } } fn process(&self, measure: &Response, state: &mut StateRepo, layout: &LayoutInfo, draw: &mut Vec) { @@ -145,7 +157,7 @@ impl UiElement for Container { if let Some(color) = self.background { draw.push(UiDrawCommand::Rectangle { position, - size: measure.desired_size, + size: measure.size, color }); } @@ -154,25 +166,21 @@ impl UiElement for Container { position += vec2(self.padding.left, self.padding.top); //alignment - //TODO: REQUIRES MAX MEASURE SIZES! - // match self.align.0 { - // Alignment::Begin => (), - // Alignment::Center => { - // position.x += (layout.max_size.x - measure.desired_size.x) / 2.; - // }, - // Alignment::End => { - // position.x += layout.max_size.x - measure.desired_size.x; - // } - // } - // match self.align.1 { - // Alignment::Begin => (), - // Alignment::Center => { - // position.y += (layout.max_size.y - measure.desired_size.y) / 2.; - // }, - // Alignment::End => { - // position.y += layout.max_size.y - measure.desired_size.y; - // } - // } + match (self.align.0, self.direction) { + (Alignment::Begin, _) => (), + (Alignment::Center, UiDirection::Horizontal) => { + position.x += (measure.size.x - measure.hints.inner_content_size.unwrap().x) / 2.; + }, + (Alignment::Center, UiDirection::Vertical) => { + position.y += (measure.size.y - measure.hints.inner_content_size.unwrap().y) / 2.; + }, + (Alignment::End, UiDirection::Horizontal) => { + position.x += measure.size.x - measure.hints.inner_content_size.unwrap().x - self.padding.right - self.padding.left; + }, + (Alignment::End, UiDirection::Vertical) => { + position.y += measure.size.y - measure.hints.inner_content_size.unwrap().y - self.padding.bottom - self.padding.top; + } + } for element in &self.elements { //(passing max size from layout rather than actual bounds for the sake of consistency with measure() above) @@ -190,16 +198,16 @@ impl UiElement for Container { 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.; + el_layout.position.y += (measure.size.y - self.padding.bottom - self.padding.top - el_measure.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.; + el_layout.position.x += (measure.size.x - self.padding.left - self.padding.right - el_measure.size.x) / 2.; }, (Alignment::End, UiDirection::Horizontal) => { - el_layout.position.y += measure.desired_size.y - el_measure.desired_size.y - self.padding.bottom; + el_layout.position.y += measure.size.y - el_measure.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; + el_layout.position.x += measure.size.x - el_measure.size.x - self.padding.right; } } @@ -209,10 +217,10 @@ impl UiElement for Container { //layout match self.direction { UiDirection::Horizontal => { - position.x += el_measure.desired_size.x + self.gap; + position.x += el_measure.size.x + self.gap; }, UiDirection::Vertical => { - position.y += el_measure.desired_size.y + self.gap; + position.y += el_measure.size.y + self.gap; } } } diff --git a/kubi-ui/src/element/builtin/progress_bar.rs b/kubi-ui/src/element/builtin/progress_bar.rs index 3d54f95..977df55 100644 --- a/kubi-ui/src/element/builtin/progress_bar.rs +++ b/kubi-ui/src/element/builtin/progress_bar.rs @@ -33,7 +33,7 @@ impl UiElement for ProgressBar { fn measure(&self, _: &StateRepo, layout: &LayoutInfo) -> Response { Response { - desired_size: vec2( + size: vec2( match self.size.0 { UiSize::Auto => layout.max_size.x.max(300.), UiSize::Percentage(p) => layout.max_size.x * p, @@ -44,7 +44,9 @@ impl UiElement for ProgressBar { UiSize::Percentage(p) => layout.max_size.y * p, UiSize::Pixels(p) => p, } - ) + ), + hints: Default::default(), + user_data: None, } } @@ -53,14 +55,14 @@ impl UiElement for ProgressBar { if value < 1. { draw.push(UiDrawCommand::Rectangle { position: layout.position, - size: measure.desired_size, + size: measure.size, color: self.color_background }); } if value > 0. { draw.push(UiDrawCommand::Rectangle { position: layout.position, - size: measure.desired_size * vec2(value, 1.0), + size: measure.size * vec2(value, 1.0), color: self.color_foreground }); } diff --git a/kubi-ui/src/element/builtin/rect.rs b/kubi-ui/src/element/builtin/rect.rs index 9838a24..692dd06 100644 --- a/kubi-ui/src/element/builtin/rect.rs +++ b/kubi-ui/src/element/builtin/rect.rs @@ -25,7 +25,7 @@ impl Default for Rect { impl UiElement for Rect { fn measure(&self, _state: &StateRepo, layout: &LayoutInfo) -> Response { Response { - desired_size: vec2( + size: vec2( match self.size.0 { UiSize::Auto => layout.max_size.x, UiSize::Percentage(percentage) => layout.max_size.x * percentage, @@ -36,7 +36,9 @@ impl UiElement for Rect { UiSize::Percentage(percentage) => layout.max_size.y * percentage, UiSize::Pixels(pixels) => pixels, }, - ) + ), + hints: Default::default(), + user_data: None } } @@ -44,7 +46,7 @@ impl UiElement for Rect { if let Some(color) = self.color { draw.push(UiDrawCommand::Rectangle { position: layout.position, - size: measure.desired_size, + size: measure.size, color, }); } diff --git a/kubi-ui/src/element/builtin/spacer.rs b/kubi-ui/src/element/builtin/spacer.rs index 92c4d61..fe1fb86 100644 --- a/kubi-ui/src/element/builtin/spacer.rs +++ b/kubi-ui/src/element/builtin/spacer.rs @@ -19,10 +19,12 @@ impl Default for Spacer { impl UiElement for Spacer { fn measure(&self, state: &StateRepo, layout: &LayoutInfo) -> Response { Response { - desired_size: match layout.direction { + size: match layout.direction { UiDirection::Horizontal => vec2(self.0, 0.), UiDirection::Vertical => vec2(0., self.0), - } + }, + hints: Default::default(), + user_data: None } } diff --git a/kubi-ui/src/measure.rs b/kubi-ui/src/measure.rs index 7be6e64..9a83832 100644 --- a/kubi-ui/src/measure.rs +++ b/kubi-ui/src/measure.rs @@ -1,5 +1,15 @@ use glam::Vec2; -pub struct Response { - pub desired_size: Vec2 +#[derive(Default)] +#[non_exhaustive] +pub struct Hints { + pub inner_content_size: Option, + pub inner_content_size_cache: Option>, +} + +#[derive(Default)] +pub struct Response { + pub size: Vec2, + pub hints: Hints, + pub user_data: Option>, }