diff --git a/examples/layout.rs b/examples/layout.rs new file mode 100644 index 0000000000000000000000000000000000000000..41e335a54a0255ba8db2998b4a4468d87c91f3a9 --- /dev/null +++ b/examples/layout.rs @@ -0,0 +1,143 @@ +use bevy::prelude::*; +use kayak_ui::prelude::{widgets::*, *}; + +fn startup( + mut commands: Commands, + mut font_mapping: ResMut<FontMapping>, + asset_server: Res<AssetServer>, +) { + font_mapping.set_default(asset_server.load("roboto.kayak_font")); + + // Camera 2D forces a clear pass in bevy. + // We do this because our scene is not rendering anything else. + commands.spawn(Camera2dBundle::default()); + + let mut widget_context = KayakRootContext::new(); + widget_context.add_plugin(KayakWidgetsContextPlugin); + let parent_id = None; + + rsx! { + <KayakAppBundle> + <WindowBundle + window={KWindow { + title: "Layout example".into(), + draggable: true, + initial_position: Vec2::new(10.0, 10.0), + size: Vec2::new(512.0, 512.0), + ..KWindow::default() + }} + > + <ElementBundle + styles={KStyle{ + layout_type: LayoutType::Grid.into(), + grid_rows: vec![Units::Stretch(1.0), Units::Stretch(2.0), Units::Stretch(5.0)].into(), + grid_cols: vec![Units::Stretch(1.0), Units::Stretch(1.0)].into(), + ..default() + }} + > + <BackgroundBundle + styles={KStyle{ + background_color: Color::rgb(0.4, 0.9, 0.4).into(), + color: Color::rgb(0.0, 0.0, 0.0).into(), + padding: Edge::all(Units::Pixels(5.0)).into(), + border_radius: Corner::all(10.0).into(), + row_index: 0.into(), + col_index: 0.into(), + col_span: 2.into(), + layout_type: LayoutType::Row.into(), + col_between: Units::Pixels(5.0).into(), + ..default() + }} + > + <TextWidgetBundle + text={TextProps { + content: "A".into(), + ..default() + }} + /> + <TextWidgetBundle + text={TextProps { + content: "B".into(), + ..default() + }} + /> + <TextWidgetBundle + text={TextProps { + content: "C".into(), + ..default() + }} + /> + <TextWidgetBundle + text={TextProps { + content: "D".into(), + ..default() + }} + /> + <TextWidgetBundle + text={TextProps { + content: "E".into(), + ..default() + }} + /> + + </BackgroundBundle> + <TextWidgetBundle + text={TextProps { + content: "R1 C0".into(), + ..default() + }} + styles={KStyle{ + row_index: 1.into(), + col_index: 0.into(), + ..default() + }} + /> + <TextWidgetBundle + text={TextProps { + content: "R1 C1".into(), + ..default() + }} + styles={KStyle{ + row_index: 1.into(), + col_index: 1.into(), + ..default() + }} + /> + <TextWidgetBundle + text={TextProps { + content: "R2 C0".into(), + ..default() + }} + styles={KStyle{ + row_index: 2.into(), + col_index: 0.into(), + ..default() + }} + /> + <TextWidgetBundle + text={TextProps { + content: "R2 C1".into(), + ..default() + }} + styles={KStyle{ + row_index: 2.into(), + col_index: 1.into(), + ..default() + }} + /> + </ElementBundle> + </WindowBundle> + </KayakAppBundle> + } + + commands.spawn(UICameraBundle::new(widget_context)); +} + +fn main() { + App::new() + .add_plugins(DefaultPlugins) + .add_plugin(KayakContextPlugin) + .add_plugin(KayakWidgets) + .add_startup_system(startup) + .run() +} diff --git a/src/node.rs b/src/node.rs index 9c655a2613d988c6712df13a0f1fa37c8ebc1f8f..b307207fa7cff0b66674aed8b3d568aa8986726e 100644 --- a/src/node.rs +++ b/src/node.rs @@ -379,27 +379,69 @@ impl<'a> morphorm::Node<'a> for WrappedIndex { Some(morphorm::Units::Auto) } - fn grid_rows(&self, _store: &'_ Self::Data) -> Option<Vec<morphorm::Units>> { + fn grid_rows(&self, store: &'_ Self::Data) -> Option<Vec<morphorm::Units>> { + if let Ok(node) = store.get(self.0) { + return match &node.resolved_styles.grid_rows { + StyleProp::Default => Some(vec![]), + StyleProp::Value(prop) => Some(prop.iter().map(|&x| x.into()).collect()), + _ => Some(vec![]), + }; + } Some(vec![]) } - fn grid_cols(&self, _store: &'_ Self::Data) -> Option<Vec<morphorm::Units>> { + fn grid_cols(&self, store: &'_ Self::Data) -> Option<Vec<morphorm::Units>> { + if let Ok(node) = store.get(self.0) { + return match &node.resolved_styles.grid_cols { + StyleProp::Default => Some(vec![]), + StyleProp::Value(prop) => Some(prop.iter().map(|&x| x.into()).collect()), + _ => Some(vec![]), + }; + } Some(vec![]) } - fn row_index(&self, _store: &'_ Self::Data) -> Option<usize> { + fn row_index(&self, store: &'_ Self::Data) -> Option<usize> { + if let Ok(node) = store.get(self.0) { + return match node.resolved_styles.row_index { + StyleProp::Default => Some(0), + StyleProp::Value(prop) => Some(prop), + _ => Some(0), + }; + } Some(0) } - fn col_index(&self, _store: &'_ Self::Data) -> Option<usize> { + fn col_index(&self, store: &'_ Self::Data) -> Option<usize> { + if let Ok(node) = store.get(self.0) { + return match node.resolved_styles.col_index { + StyleProp::Default => Some(0), + StyleProp::Value(prop) => Some(prop), + _ => Some(0), + }; + } Some(0) } - fn row_span(&self, _store: &'_ Self::Data) -> Option<usize> { + fn row_span(&self, store: &'_ Self::Data) -> Option<usize> { + if let Ok(node) = store.get(self.0) { + return match node.resolved_styles.row_span { + StyleProp::Default => Some(1), + StyleProp::Value(prop) => Some(prop), + _ => Some(1), + }; + } Some(1) } - fn col_span(&self, _store: &'_ Self::Data) -> Option<usize> { + fn col_span(&self, store: &'_ Self::Data) -> Option<usize> { + if let Ok(node) = store.get(self.0) { + return match node.resolved_styles.col_span { + StyleProp::Default => Some(1), + StyleProp::Value(prop) => Some(prop), + _ => Some(1), + }; + } Some(1) } diff --git a/src/styles/style.rs b/src/styles/style.rs index 70b7f8f17344d4dd1e606ca5530f1cc5c4095bbe..5dba8472a8c1905b4f4637750b0708b0cce3f199 100644 --- a/src/styles/style.rs +++ b/src/styles/style.rs @@ -374,6 +374,30 @@ define_styles! { pub width: StyleProp<Units>, /// The z-index relative to it's parent. pub z_index: StyleProp<i32>, + /// The list of rows when using the grid layout + /// + /// This is specified in the parent widget and the children have to specify their `row_index`. + pub grid_rows: StyleProp<Vec<Units>>, + /// The list of columns when using the grid layout + /// + /// This is specified in the parent widget and the children have to specify their `col_index`. + pub grid_cols: StyleProp<Vec<Units>>, + /// The row index of this widget when using the grid layout + /// + /// This references the `grid_rows` property of the parent widget. + pub row_index: StyleProp<usize>, + /// The column index of this widget when using the grid layout + /// + /// This references the `grid_cols` property of the parent widget. + pub col_index: StyleProp<usize>, + /// The number rows that this widget spans when using the grid layout + /// + /// Specified in the child widget. + pub row_span: StyleProp<usize>, + /// The number columns that this widget spans when using the grid layout + /// + /// Specified in the child widget. + pub col_span: StyleProp<usize>, } } @@ -416,6 +440,12 @@ impl KStyle { top: StyleProp::Default, width: StyleProp::Default, z_index: StyleProp::Default, + grid_rows: StyleProp::Default, + grid_cols: StyleProp::Default, + row_index: StyleProp::Default, + col_index: StyleProp::Default, + row_span: StyleProp::Default, + col_span: StyleProp::Default, } } }