mirror of https://github.com/linebender/xilem
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.
This commit is contained in:
parent
43bd4ef090
commit
aaeeadbbd7
|
@ -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<i32> {
|
||||||
|
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(())
|
||||||
|
}
|
|
@ -4,7 +4,7 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use masonry::{
|
use masonry::{
|
||||||
widget::{self, Axis, WidgetMut},
|
widget::{self, Axis, CrossAxisAlignment, MainAxisAlignment, WidgetMut},
|
||||||
Widget, WidgetPod,
|
Widget, WidgetPod,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -16,12 +16,18 @@ pub fn flex<VT, Marker>(sequence: VT) -> Flex<VT, Marker> {
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
sequence,
|
sequence,
|
||||||
axis: Axis::Vertical,
|
axis: Axis::Vertical,
|
||||||
|
cross_axis_alignment: CrossAxisAlignment::Center,
|
||||||
|
main_axis_alignment: MainAxisAlignment::Start,
|
||||||
|
fill_major_axis: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Flex<VT, Marker> {
|
pub struct Flex<VT, Marker> {
|
||||||
sequence: VT,
|
sequence: VT,
|
||||||
axis: Axis,
|
axis: Axis,
|
||||||
|
cross_axis_alignment: CrossAxisAlignment,
|
||||||
|
main_axis_alignment: MainAxisAlignment,
|
||||||
|
fill_major_axis: bool,
|
||||||
phantom: PhantomData<fn() -> Marker>,
|
phantom: PhantomData<fn() -> Marker>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +36,20 @@ impl<VT, Marker> Flex<VT, Marker> {
|
||||||
self.axis = axis;
|
self.axis = axis;
|
||||||
self
|
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<State, Action, Marker: 'static, Seq> MasonryView<State, Action> for Flex<Seq, Marker>
|
impl<State, Action, Marker: 'static, Seq> MasonryView<State, Action> for Flex<Seq, Marker>
|
||||||
|
@ -47,7 +67,10 @@ where
|
||||||
let mut scratch = Vec::new();
|
let mut scratch = Vec::new();
|
||||||
let mut splice = VecSplice::new(&mut elements, &mut scratch);
|
let mut splice = VecSplice::new(&mut elements, &mut scratch);
|
||||||
let seq_state = self.sequence.build(cx, &mut splice);
|
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!(
|
debug_assert!(
|
||||||
scratch.is_empty(),
|
scratch.is_empty(),
|
||||||
// TODO: Not at all confident about this, but linear_layout makes this assumption
|
// TODO: Not at all confident about this, but linear_layout makes this assumption
|
||||||
|
@ -81,6 +104,18 @@ where
|
||||||
element.set_direction(self.axis);
|
element.set_direction(self.axis);
|
||||||
cx.mark_changed();
|
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 };
|
let mut splice = FlexSplice { ix: 0, element };
|
||||||
self.sequence
|
self.sequence
|
||||||
.rebuild(view_state, cx, &prev.sequence, &mut splice);
|
.rebuild(view_state, cx, &prev.sequence, &mut splice);
|
||||||
|
|
Loading…
Reference in New Issue