Added some more layout documentation.
This commit is contained in:
parent
5b2d5bd0d9
commit
5377b7e8eb
|
@ -549,8 +549,8 @@ fn center_viewport(msg: impl UiNode) -> impl UiNode {
|
|||
// the large images can take a moment to decode in debug builds, but the size
|
||||
// is already known after read, so the "loading.." message ends-up off-screen
|
||||
// because it is centered on the image.
|
||||
layout::x = zero_ui::scroll::SCROLL.horizontal_offset().map(|&fct| Length::Relative(fct) - 1.vw() * fct);
|
||||
layout::y = zero_ui::scroll::SCROLL.vertical_offset().map(|&fct| Length::Relative(fct) - 1.vh() * fct);
|
||||
layout::x = zero_ui::scroll::SCROLL.horizontal_offset().map(|&fct| Length::Factor(fct) - 1.vw() * fct);
|
||||
layout::y = zero_ui::scroll::SCROLL.vertical_offset().map(|&fct| Length::Factor(fct) - 1.vh() * fct);
|
||||
widget::can_auto_hide = false;
|
||||
layout::max_size = (1.vw(), 1.vh());
|
||||
child_align = Align::CENTER;
|
||||
|
|
|
@ -242,13 +242,13 @@ impl_from_and_into_var! {
|
|||
GradientRadius::farthest_corner(radii)
|
||||
}
|
||||
|
||||
/// Conversion to [`Length::Relative`] and to radius.
|
||||
/// Conversion to [`Length::Factor`] and to radius.
|
||||
fn from(percent: FactorPercent) -> GradientRadius {
|
||||
Length::Relative(percent.into()).into()
|
||||
Length::Factor(percent.into()).into()
|
||||
}
|
||||
/// Conversion to [`Length::Relative`] and to radius.
|
||||
/// Conversion to [`Length::Factor`] and to radius.
|
||||
fn from(norm: Factor) -> GradientRadius {
|
||||
Length::Relative(norm).into()
|
||||
Length::Factor(norm).into()
|
||||
}
|
||||
/// Conversion to [`Length::DipF32`] and to radius.
|
||||
fn from(f: f32) -> GradientRadius {
|
||||
|
@ -539,12 +539,12 @@ impl_from_and_into_var! {
|
|||
GradientStop::ColorHint(color_hint)
|
||||
}
|
||||
|
||||
/// Conversion to [`Length::Relative`] color hint.
|
||||
/// Conversion to [`Length::Factor`] color hint.
|
||||
fn from(color_hint: FactorPercent) -> GradientStop {
|
||||
GradientStop::ColorHint(color_hint.into())
|
||||
}
|
||||
|
||||
/// Conversion to [`Length::Relative`] color hint.
|
||||
/// Conversion to [`Length::Factor`] color hint.
|
||||
fn from(color_hint: Factor) -> GradientStop {
|
||||
GradientStop::ColorHint(color_hint.into())
|
||||
}
|
||||
|
@ -738,11 +738,11 @@ impl GradientStops {
|
|||
middle: vec![
|
||||
GradientStop::Color(ColorStop {
|
||||
color,
|
||||
offset: Length::Relative(Factor(0.5 - tran)),
|
||||
offset: Length::Factor(Factor(0.5 - tran)),
|
||||
}),
|
||||
GradientStop::Color(ColorStop {
|
||||
color: end.color,
|
||||
offset: Length::Relative(Factor(0.5 + tran)),
|
||||
offset: Length::Factor(Factor(0.5 + tran)),
|
||||
}),
|
||||
],
|
||||
end,
|
||||
|
@ -784,7 +784,7 @@ impl GradientStops {
|
|||
|
||||
let end = ColorStop {
|
||||
color: colors[last].into(),
|
||||
offset: Length::Relative(Factor(1.0)),
|
||||
offset: Length::Factor(Factor(1.0)),
|
||||
};
|
||||
middle.push(
|
||||
ColorStop {
|
||||
|
|
|
@ -25,8 +25,6 @@ use crate::context::LAYOUT;
|
|||
#[derive(Clone, serde::Serialize, serde::Deserialize)]
|
||||
pub enum Length {
|
||||
/// The default (initial) value.
|
||||
///
|
||||
/// This is usually `0.px()`, unless the property redefines it.
|
||||
Default,
|
||||
/// The exact length in device independent units.
|
||||
Dip(Dip),
|
||||
|
@ -35,7 +33,7 @@ pub enum Length {
|
|||
/// The exact length in font points.
|
||||
Pt(f32),
|
||||
/// Relative to the fill length.
|
||||
Relative(Factor),
|
||||
Factor(Factor),
|
||||
/// Relative to the leftover fill length.
|
||||
Leftover(Factor),
|
||||
/// Relative to the font-size of the widget.
|
||||
|
@ -83,7 +81,7 @@ impl<L: Into<Length>> ops::Add<L> for Length {
|
|||
(Dip(a), Dip(b)) => Dip(a + b),
|
||||
(Px(a), Px(b)) => Px(a + b),
|
||||
(Pt(a), Pt(b)) => Pt(a + b),
|
||||
(Relative(a), Relative(b)) => Relative(a + b),
|
||||
(Factor(a), Factor(b)) => Factor(a + b),
|
||||
(Leftover(a), Leftover(b)) => Leftover(a + b),
|
||||
(Em(a), Em(b)) => Em(a + b),
|
||||
(RootEm(a), RootEm(b)) => RootEm(a + b),
|
||||
|
@ -123,7 +121,7 @@ impl<L: Into<Length>> ops::Sub<L> for Length {
|
|||
(Dip(a), Dip(b)) => Dip(a - b),
|
||||
(Px(a), Px(b)) => Px(a - b),
|
||||
(Pt(a), Pt(b)) => Pt(a - b),
|
||||
(Relative(a), Relative(b)) => Relative(a - b),
|
||||
(Factor(a), Factor(b)) => Factor(a - b),
|
||||
(Leftover(a), Leftover(b)) => Leftover(a - b),
|
||||
(Em(a), Em(b)) => Em(a - b),
|
||||
(RootEm(a), RootEm(b)) => RootEm(a - b),
|
||||
|
@ -164,7 +162,7 @@ impl<F: Into<Factor>> ops::Mul<F> for Length {
|
|||
Dip(e) => DipF32(e.to_f32() * rhs.0),
|
||||
Px(e) => PxF32(e.0 as f32 * rhs.0),
|
||||
Pt(e) => Pt(e * rhs.0),
|
||||
Relative(r) => Relative(r * rhs),
|
||||
Factor(r) => Factor(r * rhs),
|
||||
Leftover(r) => Leftover(r * rhs),
|
||||
Em(e) => Em(e * rhs),
|
||||
RootEm(e) => RootEm(e * rhs),
|
||||
|
@ -200,7 +198,7 @@ impl<F: Into<Factor>> ops::Div<F> for Length {
|
|||
Dip(e) => DipF32(e.to_f32() / rhs.0),
|
||||
Px(e) => PxF32(e.0 as f32 / rhs.0),
|
||||
Pt(e) => Pt(e / rhs.0),
|
||||
Relative(r) => Relative(r / rhs),
|
||||
Factor(r) => Factor(r / rhs),
|
||||
Leftover(r) => Leftover(r / rhs),
|
||||
Em(e) => Em(e / rhs),
|
||||
RootEm(e) => RootEm(e / rhs),
|
||||
|
@ -235,7 +233,7 @@ impl Transitionable for Length {
|
|||
(Dip(a), Dip(b)) => Dip(a.lerp(b, step)),
|
||||
(Px(a), Px(b)) => Px(a.lerp(b, step)),
|
||||
(Pt(a), Pt(b)) => Pt(a.lerp(b, step)),
|
||||
(Relative(a), Relative(b)) => Relative(a.lerp(b, step)),
|
||||
(Factor(a), Factor(b)) => Factor(a.lerp(b, step)),
|
||||
(Leftover(a), Leftover(b)) => Leftover(a.lerp(b, step)),
|
||||
(Em(a), Em(b)) => Em(a.lerp(b, step)),
|
||||
(RootEm(a), RootEm(b)) => RootEm(a.lerp(b, step)),
|
||||
|
@ -262,7 +260,7 @@ impl ops::Neg for Length {
|
|||
Length::Dip(e) => Length::Dip(-e),
|
||||
Length::Px(e) => Length::Px(-e),
|
||||
Length::Pt(e) => Length::Pt(-e),
|
||||
Length::Relative(e) => Length::Relative(-e),
|
||||
Length::Factor(e) => Length::Factor(-e),
|
||||
Length::Leftover(e) => Length::Leftover(-e),
|
||||
Length::Em(e) => Length::Em(-e),
|
||||
Length::RootEm(e) => Length::RootEm(-e),
|
||||
|
@ -294,7 +292,7 @@ impl PartialEq for Length {
|
|||
|
||||
(DipF32(a), DipF32(b)) | (PxF32(a), PxF32(b)) => about_eq(*a, *b, EQ_EPSILON_100),
|
||||
|
||||
(Relative(a), Relative(b)) | (Em(a), Em(b)) | (RootEm(a), RootEm(b)) | (Leftover(a), Leftover(b)) => a == b,
|
||||
(Factor(a), Factor(b)) | (Em(a), Em(b)) | (RootEm(a), RootEm(b)) | (Leftover(a), Leftover(b)) => a == b,
|
||||
|
||||
(ViewportWidth(a), ViewportWidth(b))
|
||||
| (ViewportHeight(a), ViewportHeight(b))
|
||||
|
@ -319,7 +317,7 @@ impl fmt::Debug for Length {
|
|||
Dip(e) => f.debug_tuple("Length::Dip").field(e).finish(),
|
||||
Px(e) => f.debug_tuple("Length::Px").field(e).finish(),
|
||||
Pt(e) => f.debug_tuple("Length::Pt").field(e).finish(),
|
||||
Relative(e) => f.debug_tuple("Length::Relative").field(e).finish(),
|
||||
Factor(e) => f.debug_tuple("Length::Factor").field(e).finish(),
|
||||
Leftover(e) => f.debug_tuple("Length::Leftover").field(e).finish(),
|
||||
Em(e) => f.debug_tuple("Length::Em").field(e).finish(),
|
||||
RootEm(e) => f.debug_tuple("Length::RootEm").field(e).finish(),
|
||||
|
@ -337,7 +335,7 @@ impl fmt::Debug for Length {
|
|||
Dip(e) => write!(f, "{}.dip()", e.to_f32()),
|
||||
Px(e) => write!(f, "{}.px()", e.0),
|
||||
Pt(e) => write!(f, "{e}.pt()"),
|
||||
Relative(e) => write!(f, "{}.pct()", e.0 * 100.0),
|
||||
Factor(e) => write!(f, "{}.pct()", e.0 * 100.0),
|
||||
Leftover(e) => write!(f, "{}.lft()", e.0),
|
||||
Em(e) => write!(f, "{}.em()", e.0),
|
||||
RootEm(e) => write!(f, "{}.rem()", e.0),
|
||||
|
@ -360,7 +358,7 @@ impl fmt::Display for Length {
|
|||
Dip(l) => write!(f, "{l}"),
|
||||
Px(l) => write!(f, "{l}"),
|
||||
Pt(l) => write!(f, "{l}pt"),
|
||||
Relative(n) => write!(f, "{:.*}%", f.precision().unwrap_or(0), n.0 * 100.0),
|
||||
Factor(n) => write!(f, "{:.*}%", f.precision().unwrap_or(0), n.0 * 100.0),
|
||||
Leftover(l) => write!(f, "{l}lft"),
|
||||
Em(e) => write!(f, "{e}em"),
|
||||
RootEm(re) => write!(f, "{re}rem"),
|
||||
|
@ -375,14 +373,14 @@ impl fmt::Display for Length {
|
|||
}
|
||||
}
|
||||
impl_from_and_into_var! {
|
||||
/// Conversion to [`Length::Relative`]
|
||||
/// Conversion to [`Length::Factor`]
|
||||
fn from(percent: FactorPercent) -> Length {
|
||||
Length::Relative(percent.into())
|
||||
Length::Factor(percent.into())
|
||||
}
|
||||
|
||||
/// Conversion to [`Length::Relative`]
|
||||
/// Conversion to [`Length::Factor`]
|
||||
fn from(norm: Factor) -> Length {
|
||||
Length::Relative(norm)
|
||||
Length::Factor(norm)
|
||||
}
|
||||
|
||||
/// Conversion to [`Length::DipF32`]
|
||||
|
@ -413,12 +411,12 @@ impl Length {
|
|||
|
||||
/// Length that fills the available space.
|
||||
pub const fn fill() -> Length {
|
||||
Length::Relative(Factor(1.0))
|
||||
Length::Factor(Factor(1.0))
|
||||
}
|
||||
|
||||
/// Length that fills 50% of the available space.
|
||||
pub const fn half() -> Length {
|
||||
Length::Relative(Factor(0.5))
|
||||
Length::Factor(Factor(0.5))
|
||||
}
|
||||
|
||||
/// Returns a length that resolves to the maximum layout length between `self` and `other`.
|
||||
|
@ -429,7 +427,7 @@ impl Length {
|
|||
(Dip(a), Dip(b)) => Dip(a.max(b)),
|
||||
(Px(a), Px(b)) => Px(a.max(b)),
|
||||
(Pt(a), Pt(b)) => Pt(a.max(b)),
|
||||
(Relative(a), Relative(b)) => Relative(a.max(b)),
|
||||
(Factor(a), Factor(b)) => Factor(a.max(b)),
|
||||
(Leftover(a), Leftover(b)) => Leftover(a.max(b)),
|
||||
(Em(a), Em(b)) => Em(a.max(b)),
|
||||
(RootEm(a), RootEm(b)) => RootEm(a.max(b)),
|
||||
|
@ -453,7 +451,7 @@ impl Length {
|
|||
(Dip(a), Dip(b)) => Dip(a.min(b)),
|
||||
(Px(a), Px(b)) => Px(a.min(b)),
|
||||
(Pt(a), Pt(b)) => Pt(a.min(b)),
|
||||
(Relative(a), Relative(b)) => Relative(a.min(b)),
|
||||
(Factor(a), Factor(b)) => Factor(a.min(b)),
|
||||
(Leftover(a), Leftover(b)) => Leftover(a.min(b)),
|
||||
(Em(a), Em(b)) => Em(a.min(b)),
|
||||
(RootEm(a), RootEm(b)) => RootEm(a.min(b)),
|
||||
|
@ -482,7 +480,7 @@ impl Length {
|
|||
Dip(e) => Dip(e.abs()),
|
||||
Px(e) => Px(e.abs()),
|
||||
Pt(e) => Pt(e.abs()),
|
||||
Relative(r) => Relative(r.abs()),
|
||||
Factor(r) => Factor(r.abs()),
|
||||
Leftover(r) => Leftover(r.abs()),
|
||||
Em(e) => Em(e.abs()),
|
||||
RootEm(r) => RootEm(r.abs()),
|
||||
|
@ -508,7 +506,7 @@ impl Length {
|
|||
Dip(l) => Some(*l == self::Dip::new(0)),
|
||||
Px(l) => Some(*l == self::Px(0)),
|
||||
Pt(l) => Some(l.abs() < EQ_EPSILON),
|
||||
Relative(f) => Some(f.0.abs() < EQ_EPSILON),
|
||||
Factor(f) => Some(f.0.abs() < EQ_EPSILON),
|
||||
Leftover(f) => Some(f.0.abs() < EQ_EPSILON),
|
||||
Em(f) => Some(f.0.abs() < EQ_EPSILON),
|
||||
RootEm(f) => Some(f.0.abs() < EQ_EPSILON),
|
||||
|
@ -596,7 +594,7 @@ impl super::Layout1d for Length {
|
|||
Dip(l) => l.to_px(LAYOUT.scale_factor()),
|
||||
Px(l) => *l,
|
||||
Pt(l) => Self::pt_to_px(*l, LAYOUT.scale_factor()),
|
||||
Relative(f) => LAYOUT.constraints_for(axis).fill() * f.0,
|
||||
Factor(f) => LAYOUT.constraints_for(axis).fill() * f.0,
|
||||
Leftover(f) => {
|
||||
if let Some(l) = LAYOUT.leftover_for(axis) {
|
||||
l
|
||||
|
@ -624,7 +622,7 @@ impl super::Layout1d for Length {
|
|||
Dip(l) => l.to_f32() * LAYOUT.scale_factor().0,
|
||||
Px(l) => l.0 as f32,
|
||||
Pt(l) => Self::pt_to_px_f32(*l, LAYOUT.scale_factor()),
|
||||
Relative(f) => LAYOUT.constraints_for(axis).fill().0 as f32 * f.0,
|
||||
Factor(f) => LAYOUT.constraints_for(axis).fill().0 as f32 * f.0,
|
||||
Leftover(f) => {
|
||||
if let Some(l) = LAYOUT.leftover_for(axis) {
|
||||
l.0 as f32
|
||||
|
@ -652,7 +650,7 @@ impl super::Layout1d for Length {
|
|||
Dip(_) => LayoutMask::SCALE_FACTOR,
|
||||
Px(_) => LayoutMask::empty(),
|
||||
Pt(_) => LayoutMask::SCALE_FACTOR,
|
||||
Relative(_) => LayoutMask::CONSTRAINTS,
|
||||
Factor(_) => LayoutMask::CONSTRAINTS,
|
||||
Leftover(_) => LayoutMask::LEFTOVER,
|
||||
Em(_) => LayoutMask::FONT_SIZE,
|
||||
RootEm(_) => LayoutMask::ROOT_FONT_SIZE,
|
||||
|
@ -884,6 +882,22 @@ pub trait LengthUnits {
|
|||
/// Returns [`Length::Pt`].
|
||||
fn pt(self) -> Length;
|
||||
|
||||
/// Factor of the fill length.
|
||||
///
|
||||
/// This is the same as [`FactorUnits::fct`], but produces a [`Length`] directly. This might be needed
|
||||
/// in places that don't automatically convert [`Factor`] to [`Length`].
|
||||
///
|
||||
/// Returns [`Length::Factor`].
|
||||
fn fct_l(self) -> Length;
|
||||
|
||||
/// Percentage of the fill length.
|
||||
///
|
||||
/// This is the same as [`FactorUnits::pct`], but produces a [`Length`] directly. This might be needed
|
||||
/// in places that don't automatically convert [`FactorPercent`] to [`Length`].
|
||||
///
|
||||
/// Returns [`Length::Factor`].
|
||||
fn pct_l(self) -> Length;
|
||||
|
||||
/// Factor of the font-size of the widget.
|
||||
///
|
||||
/// Returns [`Length::Em`].
|
||||
|
@ -965,6 +979,14 @@ impl LengthUnits for f32 {
|
|||
Length::Pt(self)
|
||||
}
|
||||
|
||||
fn fct_l(self) -> Length {
|
||||
Length::Factor(self.fct())
|
||||
}
|
||||
|
||||
fn pct_l(self) -> Length {
|
||||
Length::Factor(self.pct().fct())
|
||||
}
|
||||
|
||||
fn em(self) -> Length {
|
||||
Length::Em(self.into())
|
||||
}
|
||||
|
@ -1030,6 +1052,14 @@ impl LengthUnits for i32 {
|
|||
Length::Pt(self as f32)
|
||||
}
|
||||
|
||||
fn fct_l(self) -> Length {
|
||||
Length::Factor(self.fct())
|
||||
}
|
||||
|
||||
fn pct_l(self) -> Length {
|
||||
Length::Factor(self.pct().fct())
|
||||
}
|
||||
|
||||
fn em(self) -> Length {
|
||||
Length::Em(self.fct())
|
||||
}
|
||||
|
|
|
@ -147,12 +147,12 @@ impl_from_and_into_var! {
|
|||
Vector::splat(length)
|
||||
}
|
||||
|
||||
/// Conversion to [`Length::Relative`] then to vector.
|
||||
/// Conversion to [`Length::Factor`] then to vector.
|
||||
fn from(percent: FactorPercent) -> Vector {
|
||||
Length::from(percent).into()
|
||||
}
|
||||
|
||||
/// Conversion to [`Length::Relative`] then to vector.
|
||||
/// Conversion to [`Length::Factor`] then to vector.
|
||||
fn from(norm: Factor) -> Vector {
|
||||
Length::from(norm).into()
|
||||
}
|
||||
|
|
|
@ -1477,7 +1477,7 @@ impl GridLayout {
|
|||
}
|
||||
}
|
||||
|
||||
// individual factors under `1.0` behave like `Length::Relative`.
|
||||
// individual factors under `1.0` behave like `Length::Factor`.
|
||||
if total_factor < Factor(1.0) {
|
||||
total_factor = Factor(1.0);
|
||||
}
|
||||
|
@ -1606,7 +1606,7 @@ impl GridLayout {
|
|||
}
|
||||
}
|
||||
|
||||
// individual factors under `1.0` behave like `Length::Relative`.
|
||||
// individual factors under `1.0` behave like `Length::Factor`.
|
||||
if total_factor < Factor(1.0) {
|
||||
total_factor = Factor(1.0);
|
||||
}
|
||||
|
|
|
@ -990,7 +990,7 @@ pub enum WidgetLength {
|
|||
#[default]
|
||||
Default,
|
||||
/// The [`Length::Leftover`] value. Evaluates to the [`LayoutMetrics::leftover`] value when measured, if
|
||||
/// a leftover value is not provided evaluates like a [`Length::Relative`].
|
||||
/// a leftover value is not provided evaluates like a [`Length::Factor`].
|
||||
///
|
||||
/// The *leftover* length needs to be computed by the parent panel, as it depends on the length of the sibling widgets,
|
||||
/// not just the panel constraints. Panels that support this, compute the value for each widget and measure/layout each using
|
||||
|
|
|
@ -146,8 +146,8 @@ pub fn is_collapsed(child: impl UiNode, state: impl IntoVar<bool>) -> impl UiNod
|
|||
/// Container! {
|
||||
/// zero_ui::core::widget_base::can_auto_hide = false;
|
||||
///
|
||||
/// x = zero_ui::widgets::scroll::SCROLL_HORIZONTAL_OFFSET_VAR.map(|&fct| Length::Relative(fct) - 1.vw() * fct);
|
||||
/// y = zero_ui::widgets::scroll::SCROLL_VERTICAL_OFFSET_VAR.map(|&fct| Length::Relative(fct) - 1.vh() * fct);
|
||||
/// x = zero_ui::widgets::scroll::SCROLL_HORIZONTAL_OFFSET_VAR.map(|&fct| Length::Factor(fct) - 1.vw() * fct);
|
||||
/// y = zero_ui::widgets::scroll::SCROLL_VERTICAL_OFFSET_VAR.map(|&fct| Length::Factor(fct) - 1.vh() * fct);
|
||||
/// max_size = (1.vw(), 1.vh());
|
||||
/// content_align = Align::CENTER;
|
||||
///
|
||||
|
|
|
@ -1,10 +1,98 @@
|
|||
//! Layout service, units and other types.
|
||||
//!
|
||||
//! # Measure & Layout
|
||||
//! A widget final size and position is influenced by the widget and all ancestor widgets, the properties
|
||||
//! and nodes that influence the size and position can be grouped into [widget intrinsics](#widget-intrinsics),
|
||||
//! [widget properties](#widget-properties), [layout properties](#layout-properties) and [transform properties](#transform-properties).
|
||||
//!
|
||||
//! TODO !!:
|
||||
//! Internally this is split into two passes [`UiNode::layout`] and [`UiNode::render`], transform properties are only applied
|
||||
//! during render and only influence the size and position of the widget and descendants, the other properties are true layout
|
||||
//! and influence the size and position of the parent widget and siblings too.
|
||||
//!
|
||||
//! # Exact Size & Units
|
||||
//! [`UiNode::Layout`]: crate::widget::node::UiNode::layout
|
||||
//! [`UiNode::render`]: crate::widget::node::UiNode::render
|
||||
//!
|
||||
//! ## Widget Intrinsics
|
||||
//!
|
||||
//! Each widget defines a size preference, the default widget has no minimum nor maximum size, it fills available space and collapses
|
||||
//! to zero when aligned, most widgets override this and have a minimum size preference.
|
||||
//! The `Text!` prefers a size that fits the entire text without introducing wrap line breaks,
|
||||
//! the `Stack!` widget prefers a size that fits all its children positioned in a given direction.
|
||||
//!
|
||||
//! ### Widget Properties
|
||||
//!
|
||||
//! Widget size can be influenced by properties widget specific properties, the `Text!` widget is affected by the font properties
|
||||
//! for example, as different fonts have different sizes. The `Stack!` widget is affected by the `direction` property that changes
|
||||
//! position of children widgets and so changes the size that best fits the children.
|
||||
//!
|
||||
//! ## Layout Properties
|
||||
//!
|
||||
//! Widget size and position can be more directly configured using the standalone layout properties defined in this module,
|
||||
//! as an example the [`min_size`](fn@min_size) property influences the widget size and the [`align`](fn@align) property
|
||||
//! influences the widget position, the [`margin`](fn@margin) property potentially influences both size and position.
|
||||
//!
|
||||
//! ```
|
||||
//! use zero_ui::prelude::*;
|
||||
//! # let _scope = APP.defaults();
|
||||
//!
|
||||
//! # let _ =
|
||||
//! Window! {
|
||||
//! child = Wgt! {
|
||||
//! layout::min_size = 40;
|
||||
//! layout::align = layout::Align::CENTER;
|
||||
//! widget::background_color = colors::AZURE;
|
||||
//! };
|
||||
//! }
|
||||
//! # ;
|
||||
//! ```
|
||||
//!
|
||||
//! ## Transform Properties
|
||||
//!
|
||||
//! Widget size and position can be affected during render only, the standalone [`transform`](fn@transform) property
|
||||
//! and derived properties like [`scale`](fn@scale) change the final size and position of the widget by transforming
|
||||
//! the final layout size and position, this affects only the widget and descendants, widget interactions like clicks
|
||||
//! will *see* the widget at its final transformed bounds, but the parent widget will size itself and position other
|
||||
//! children using the layout size and position.
|
||||
//!
|
||||
//! ```
|
||||
//! use zero_ui::prelude::*;
|
||||
//! # let _scope = APP.defaults();
|
||||
//!
|
||||
//! # let _ =
|
||||
//! Stack! {
|
||||
//! layout::align = layout::Align::CENTER;
|
||||
//! direction = StackDirection::left_to_right();
|
||||
//! children = ui_vec![
|
||||
//! Wgt! {
|
||||
//! layout::size = (100, 200);
|
||||
//! widget::background_color = colors::RED;
|
||||
//! },
|
||||
//! Wgt! {
|
||||
//! layout::scale = 120.pct();
|
||||
//! layout::size = (100, 200);
|
||||
//! widget::z_index = widget::ZIndex::FRONT;
|
||||
//! widget::background_color = colors::GREEN;
|
||||
//! },
|
||||
//! Wgt! {
|
||||
//! layout::size = (100, 200);
|
||||
//! widget::background_color = colors::BLUE;
|
||||
//! },
|
||||
//! ];
|
||||
//! }
|
||||
//! # ;
|
||||
//! ```
|
||||
//!
|
||||
//! The example above declares a horizontal stack with 3 rectangles, the green rectangle is rendered
|
||||
//! slightly over the other rectangles because it is [`scale`](fn@scale) to 120% of the size, scale
|
||||
//! is a render transform only so the stack widget still positions the other rectangles as if the middle
|
||||
//! one was not scaled. Also note the [`widget::z_index`](fn@crate::widget::z_index) usage, the stack widget
|
||||
//! render each children in declaration order by default, this is overridden for the green rectangle so
|
||||
//! it is rendered last, over the blue rectangle too.
|
||||
//!
|
||||
//! # Layout Units
|
||||
//!
|
||||
//! Most layout properties receive inputs in [`Length`] or length composite types like [`Size`]. These
|
||||
//! types are layout in the widget context to compute their actual length, the example below demonstrates
|
||||
//! every [`LengthUnits`], [`FactorUnits`] and length expressions.
|
||||
//!
|
||||
//! ```
|
||||
//! use zero_ui::prelude::*;
|
||||
|
@ -33,8 +121,10 @@
|
|||
//! width!(100.dip()), // 100 device independent pixels
|
||||
//! width!(100.px()), // 100 device pixels
|
||||
//! width!(100.pct()), // 100% of the available width
|
||||
//! width!(100.pct_l()), // 100% of the available width
|
||||
//! width!(50.pct()), // 50% of the available width
|
||||
//! width!(1.fct()), // 1 times the available width
|
||||
//! width!(1.fct_l()), // 1 times the available width
|
||||
//! width!(0.5.fct()), // 0.5 times the available width
|
||||
//! width!(100.pt()), // 100 font points
|
||||
//! width!(8.em()), // 8 times the font size
|
||||
|
@ -51,7 +141,9 @@
|
|||
//! width!(50.vmin_pct()), // 50% of the viewport min(width, height)
|
||||
//! width!(0.5.vmax()), // 0.5 times the viewport max(width, height)
|
||||
//! width!(50.vmax_pct()), // 50% of the viewport max(width, height)
|
||||
//! width!(100.dip() + 50.pct()), // expression, 100dip + 50%.
|
||||
//! width!(1.lft()), //1 parcel of the leftover space.
|
||||
//! width!(Length::Default), // default value
|
||||
//! ];
|
||||
//! widget::border = 1, colors::RED.desaturate(50.pct());
|
||||
//! };
|
||||
|
@ -60,6 +152,100 @@
|
|||
//! # ;
|
||||
//! ```
|
||||
//!
|
||||
//! ## Length & Factor Units
|
||||
//!
|
||||
//! Length units are defined by [`LengthUnits`] that provides extension methods for `f32` and `i32` values.
|
||||
//!
|
||||
//! The most common unit is the *device independent pixel*, or DIP, this is a value that is multiplied by the system scale
|
||||
//! factor to compute the an exact pixel length, widgets sized in DIPs have a similar apparent size indented of the
|
||||
//! screen pixel density. This is the default unit, `f32` and `i32` convert to it so `width = 100;` is the same as `width = 100.dip();`.
|
||||
//!
|
||||
//! Length can be relative to the available space provided by the parent widget, `100.pct()` and `1.fct()` declare [`FactorPercent`]
|
||||
//! and [`Factor`] values that convert to [`Length::Factor`]. The [`FactorUnits`] provide the extension methods and
|
||||
//! is implemented for `f32` and `i32`. You can also use `100.pct_l()` and `1.fct_l()` to get a [`Length`] value directly in places
|
||||
//! that don't convert the factor types to length.
|
||||
//!
|
||||
//! There are multiple units related to font size, `24.pt()` defines a size in *font points*, one font point is `96/72 * scale_factor`
|
||||
//! device pixels. Size can be relative to the contextual font size, `2.em()` and `200.em_pct()` declare a length twice the computed
|
||||
//! contextual font size, `2.rem()` and `2.rem_pct()` declare a length twice the computed root font size (the `Window!` font size).
|
||||
//!
|
||||
//! Lengths can also be relative to the *viewport*. The viewport is the window content area size, or the parent `Scroll!` visible area size.
|
||||
//! Lengths `0.2.vw()` and `20.vw_pct()` are 20% of the viewport width, `0.2.vh()` and `20.vh_pct()` are 20% of the viewport height,
|
||||
//! `1.vmin()` is the minimum viewport length (`min(w, h)`), `1.vmax()` is the maximum viewport length.
|
||||
//!
|
||||
//! ### Length Expressions
|
||||
//!
|
||||
//! Different length units can be mixed into a length expression, `1.em() + 5.dip()` will create a [`Length::Expr`] value that on layout
|
||||
//! will compute the pixel length of both terms and then sum. Length expressions support the four basic arithmetic operations, negation,
|
||||
//! maximum and minimum and absolute.
|
||||
//!
|
||||
//! Some basic length expressions are pre-computed on the spot, `10.dip() + 10.dip()` declares a `Length::Dip(20)` value, but most
|
||||
//! expression declare an object that dynamically executes the expression after all terms are layout.
|
||||
//!
|
||||
//! ### Leftover Length
|
||||
//!
|
||||
//! The leftover length is a special value that represents the space leftover after non-leftover sibling widgets are layout. This
|
||||
//! must be implemented by a parent widget to fully work, the `Grid!` widget implements it, in widgets that don't implement it
|
||||
//! the unit behaves like a factor.
|
||||
//!
|
||||
//! ```
|
||||
//! use zero_ui::prelude::*;
|
||||
//! # let _scope = APP.defaults();
|
||||
//!
|
||||
//! # let _ =
|
||||
//! Window! {
|
||||
//! child = Grid! {
|
||||
//! columns = ui_vec![
|
||||
//! grid::Column!(1.lft()),
|
||||
//! grid::Column!(100.dip()),
|
||||
//! grid::Column!(2.lft()),
|
||||
//! ];
|
||||
//! rows = ui_vec![grid::Row!(100.pct())];
|
||||
//! cells = ui_vec![
|
||||
//! Wgt! {
|
||||
//! grid::cell::column = 0;
|
||||
//! widget::background_color = colors::RED;
|
||||
//! },
|
||||
//! Wgt! {
|
||||
//! grid::cell::column = 1;
|
||||
//! widget::background_color = colors::GREEN;
|
||||
//! },
|
||||
//! Wgt! {
|
||||
//! grid::cell::column = 2;
|
||||
//! widget::background_color = colors::BLUE;
|
||||
//! },
|
||||
//! ];
|
||||
//! }
|
||||
//! }
|
||||
//! # ;
|
||||
//! ```
|
||||
//!
|
||||
//! The example above declares a grid with 3 columns, on layout the grid computes the width of the middle column first (`100.dip()`),
|
||||
//! the leftover available width is divided between the other 2 columns proportional to the leftover value. Note that value range
|
||||
//! of leftover is normalized across all leftover siblings, in the example above changing the values to `2.lft()` and `4.lft()`
|
||||
//! will produce the column sizes.
|
||||
//!
|
||||
//! ### Default Length
|
||||
//!
|
||||
//! The [`Length::Default`] value represents the length that is used when no other length is set. It is a placeholder value
|
||||
//! that is filled in by the widget or property that is resolving the layout. The `grid::Column!()` has `Default` width, in
|
||||
//! grids this means *auto-size*, the column is sized to fit all cells. In the standalone [`width`](fn@width) property
|
||||
//! the default width means the fill width.
|
||||
//!
|
||||
//! # Layout Pass
|
||||
//!
|
||||
//! !!:
|
||||
//!
|
||||
//! ## Service
|
||||
//!
|
||||
//! ## Constraints & Align
|
||||
//!
|
||||
//! ## Outer & Inner Bounds
|
||||
//!
|
||||
//! ## Inline
|
||||
//!
|
||||
//! ## Border?
|
||||
//!
|
||||
//! # Full API
|
||||
//!
|
||||
//! See [`zero_ui_layout`], [`zero_ui_wgt_transform`] and [`zero_ui_wgt_size_offset`] for the full API.
|
||||
|
|
Loading…
Reference in New Issue