kas_core/layout/
mod.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6//! Layout utilities
7//!
8//! For documentation of layout resolution, see the [`Layout`] trait.
9//!
10//! Size units are physical (real) pixels. This applies to most of KAS.
11//!
12//! ## Data types
13//!
14//! [`SizeRules`] is the "heart" of widget layout, used to specify a widget's
15//! size requirements. It provides various methods to compute derived rules
16//! and [`SizeRules::solve_seq`], the "muscle" of the layout engine.
17//!
18//! [`AxisInfo`], [`Margins`] and [`Stretch`] are auxilliary data types.
19//!
20//! ## Solvers
21//!
22//! The [`RulesSolver`] and [`RulesSetter`] traits define interfaces for
23//! layout engines:
24//!
25//! -   [`SingleSolver`] and [`SingleSetter`] are trivial implementations for
26//!     single-child parents
27//! -   [`RowSolver`] and [`RowSetter`] set out a row or column of children.
28//!     These are parametrised over `S: RowStorage` allowing both efficient
29//!     operation on a small fixed number of children with [`FixedRowStorage`]
30//!     and operation on a over a `Vec` with [`DynRowStorage`].
31//! -   [`GridSolver`] and [`GridSetter`] set out children assigned to grid
32//!     cells with optional cell-spans. This is the most powerful and flexible
33//!     layout engine.
34//!
35//! [`RowPositionSolver`] may be used with widgets set out by [`RowSetter`]
36//! to quickly locate children from a `coord` or `rect`.
37//!
38//! [`Layout`]: crate::Layout
39
40mod align;
41mod grid_solver;
42mod row_solver;
43mod single_solver;
44mod size_rules;
45mod size_types;
46mod sizer;
47mod storage;
48
49use crate::dir::{Direction, Directional, Directions};
50
51pub use align::{Align, AlignHints, AlignPair};
52pub use grid_solver::{DefaultWithLen, GridCellInfo, GridDimensions, GridSetter, GridSolver};
53pub use row_solver::{RowPositionSolver, RowSetter, RowSolver};
54pub use single_solver::{SingleSetter, SingleSolver};
55pub use size_rules::SizeRules;
56pub use size_types::*;
57pub use sizer::{RulesSetter, RulesSolver, SolveCache, solve_size_rules};
58pub use storage::*;
59
60/// Information on which axis is being resized
61///
62/// Also conveys the size of the other axis, if fixed.
63#[derive(Copy, Clone, Debug)]
64pub struct AxisInfo {
65    vertical: bool,
66    has_fixed: bool,
67    other_axis: i32,
68}
69
70impl AxisInfo {
71    /// Construct with direction and an optional value for the other axis
72    ///
73    /// This method is *usually* not required by user code.
74    #[inline]
75    pub fn new(vertical: bool, fixed: Option<i32>) -> Self {
76        AxisInfo {
77            vertical,
78            has_fixed: fixed.is_some(),
79            other_axis: fixed.unwrap_or(0),
80        }
81    }
82
83    /// True if the current axis is vertical
84    #[inline]
85    pub fn is_vertical(self) -> bool {
86        self.vertical
87    }
88
89    /// True if the current axis is horizontal
90    #[inline]
91    pub fn is_horizontal(self) -> bool {
92        !self.vertical
93    }
94
95    /// Size of other axis, if fixed
96    #[inline]
97    pub fn other(&self) -> Option<i32> {
98        if self.has_fixed { Some(self.other_axis) } else { None }
99    }
100
101    /// Subtract `x` from size of other axis (if applicable)
102    #[inline]
103    pub fn sub_other(&mut self, x: i32) {
104        self.other_axis -= x;
105    }
106}
107
108impl Directional for AxisInfo {
109    type Flipped = Self;
110    type Reversed = Self;
111
112    fn flipped(mut self) -> Self::Flipped {
113        self.vertical = !self.vertical;
114        self.has_fixed = false;
115        self
116    }
117
118    #[inline]
119    fn reversed(self) -> Self::Reversed {
120        self
121    }
122
123    #[inline]
124    fn as_direction(self) -> Direction {
125        match self.vertical {
126            false => Direction::Right,
127            true => Direction::Down,
128        }
129    }
130}
131
132impl From<AxisInfo> for Directions {
133    fn from(axis: AxisInfo) -> Directions {
134        match axis.vertical {
135            false => Directions::LEFT | Directions::RIGHT,
136            true => Directions::UP | Directions::DOWN,
137        }
138    }
139}
140
141#[cfg(test)]
142#[test]
143fn size() {
144    assert_eq!(std::mem::size_of::<AxisInfo>(), 8);
145}