From aaeeadbbd75a3984e404c2d545fcf7e8abaa72f0 Mon Sep 17 00:00:00 2001 From: Pearce Keesling Date: Wed, 8 May 2024 22:07:49 -0700 Subject: [PATCH] Additional flex view options (#285) Wired up some more existing masonry flex properties so they can be set on the flex view. I was messing around with a dummy example to try out the v0.1 and noticed I couldn't easily center something because flex was only exposing direction not alignment/cross-alignment. It looked like all the logic already exists in masonry so it was just a matter of wiring it up. This is my first contribution so sorry if I missed some steps. Sidenote: I didn't see any examples of testing that a view updates the underlying element so I am guessing that is still tbd. If someone has a suggestion for a good way to do that I am happy to try it out. I'm also not sure what the etiquette is on adding/editing examples so I just included the example I was using to verify it worked but no stress if you want to remove it. --- crates/xilem_masonry/examples/flex.rs | 30 +++++++++++++++++++++ crates/xilem_masonry/src/view/flex.rs | 39 +++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 crates/xilem_masonry/examples/flex.rs diff --git a/crates/xilem_masonry/examples/flex.rs b/crates/xilem_masonry/examples/flex.rs new file mode 100644 index 00000000..c6ce956a --- /dev/null +++ b/crates/xilem_masonry/examples/flex.rs @@ -0,0 +1,30 @@ +// Copyright 2024 the Xilem Authors +// SPDX-License-Identifier: Apache-2.0 + +use masonry::widget::{CrossAxisAlignment, MainAxisAlignment}; +use winit::error::EventLoopError; +use xilem::{ + view::{button, flex, label}, + MasonryView, Xilem, +}; + +fn app_logic(data: &mut i32) -> impl MasonryView { + flex(( + button("-", |data| { + *data -= 1; + }), + label(format!("count: {}", data)), + button("+", |data| { + *data += 1; + }), + )) + .direction(xilem::Axis::Horizontal) + .cross_axis_alignment(CrossAxisAlignment::Center) + .main_axis_alignment(MainAxisAlignment::Center) +} + +fn main() -> Result<(), EventLoopError> { + let app = Xilem::new(0, app_logic); + app.run_windowed("Centered Flex".into())?; + Ok(()) +} diff --git a/crates/xilem_masonry/src/view/flex.rs b/crates/xilem_masonry/src/view/flex.rs index bcc1bb46..58dbb72a 100644 --- a/crates/xilem_masonry/src/view/flex.rs +++ b/crates/xilem_masonry/src/view/flex.rs @@ -4,7 +4,7 @@ use std::marker::PhantomData; use masonry::{ - widget::{self, Axis, WidgetMut}, + widget::{self, Axis, CrossAxisAlignment, MainAxisAlignment, WidgetMut}, Widget, WidgetPod, }; @@ -16,12 +16,18 @@ pub fn flex(sequence: VT) -> Flex { phantom: PhantomData, sequence, axis: Axis::Vertical, + cross_axis_alignment: CrossAxisAlignment::Center, + main_axis_alignment: MainAxisAlignment::Start, + fill_major_axis: false, } } pub struct Flex { sequence: VT, axis: Axis, + cross_axis_alignment: CrossAxisAlignment, + main_axis_alignment: MainAxisAlignment, + fill_major_axis: bool, phantom: PhantomData Marker>, } @@ -30,6 +36,20 @@ impl Flex { self.axis = axis; self } + pub fn cross_axis_alignment(mut self, axis: CrossAxisAlignment) -> Self { + self.cross_axis_alignment = axis; + self + } + + pub fn main_axis_alignment(mut self, axis: MainAxisAlignment) -> Self { + self.main_axis_alignment = axis; + self + } + + pub fn must_fill_major_axis(mut self, fill_major_axis: bool) -> Self { + self.fill_major_axis = fill_major_axis; + self + } } impl MasonryView for Flex @@ -47,7 +67,10 @@ where let mut scratch = Vec::new(); let mut splice = VecSplice::new(&mut elements, &mut scratch); let seq_state = self.sequence.build(cx, &mut splice); - let mut view = widget::Flex::for_axis(self.axis); + let mut view = widget::Flex::for_axis(self.axis) + .cross_axis_alignment(self.cross_axis_alignment) + .must_fill_main_axis(self.fill_major_axis) + .main_axis_alignment(self.main_axis_alignment); debug_assert!( scratch.is_empty(), // TODO: Not at all confident about this, but linear_layout makes this assumption @@ -81,6 +104,18 @@ where element.set_direction(self.axis); cx.mark_changed(); } + if prev.cross_axis_alignment != self.cross_axis_alignment { + element.set_cross_axis_alignment(self.cross_axis_alignment); + cx.mark_changed(); + } + if prev.main_axis_alignment != self.main_axis_alignment { + element.set_main_axis_alignment(self.main_axis_alignment); + cx.mark_changed(); + } + if prev.fill_major_axis != self.fill_major_axis { + element.set_must_fill_main_axis(self.fill_major_axis); + cx.mark_changed(); + } let mut splice = FlexSplice { ix: 0, element }; self.sequence .rebuild(view_state, cx, &prev.sequence, &mut splice);