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}