1use std::sync::Arc;
2
3use crate::builder::{ContainerCtx, LayoutBuilder};
4use crate::compiler::compile;
5use crate::error::PaneError;
6use crate::preset::PresetInfo;
7use crate::resolver::ResolvedLayout;
8use crate::tree::LayoutTree;
9
10pub struct Layout {
12 tree: LayoutTree,
13}
14
15impl std::fmt::Debug for Layout {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 f.debug_struct("Layout")
18 .field("panel_count", &self.tree.panel_count())
19 .finish()
20 }
21}
22
23impl Layout {
24 pub(crate) fn from_tree(tree: LayoutTree) -> Self {
26 Self { tree }
27 }
28
29 pub fn tree(&self) -> &LayoutTree {
31 &self.tree
32 }
33
34 pub fn window_size(&self) -> usize {
36 self.tree.window_size()
37 }
38
39 pub fn resolve(&self, width: f32, height: f32) -> Result<ResolvedLayout, PaneError> {
41 self.tree.resolve(width, height)
42 }
43
44 pub fn build_row(f: impl FnOnce(&mut ContainerCtx)) -> Result<Self, PaneError> {
48 let mut b = LayoutBuilder::new();
49 b.row(f)?;
50 b.build()
51 }
52
53 pub fn build_col(f: impl FnOnce(&mut ContainerCtx)) -> Result<Self, PaneError> {
55 let mut b = LayoutBuilder::new();
56 b.col(f)?;
57 b.build()
58 }
59
60 pub fn build_row_gap(gap: f32, f: impl FnOnce(&mut ContainerCtx)) -> Result<Self, PaneError> {
62 let mut b = LayoutBuilder::new();
63 b.row_gap(gap, f)?;
64 b.build()
65 }
66
67 pub fn build_col_gap(gap: f32, f: impl FnOnce(&mut ContainerCtx)) -> Result<Self, PaneError> {
69 let mut b = LayoutBuilder::new();
70 b.col_gap(gap, f)?;
71 b.build()
72 }
73
74 pub fn row(kinds: impl IntoIterator<Item = impl Into<Arc<str>>>) -> Result<Self, PaneError> {
76 let kinds: Vec<Arc<str>> = kinds.into_iter().map(Into::into).collect();
77 let mut b = LayoutBuilder::new();
78 b.row(|r| {
79 for kind in &kinds {
80 r.panel(Arc::clone(kind));
81 }
82 })?;
83 b.build()
84 }
85
86 pub fn col(kinds: impl IntoIterator<Item = impl Into<Arc<str>>>) -> Result<Self, PaneError> {
88 let kinds: Vec<Arc<str>> = kinds.into_iter().map(Into::into).collect();
89 let mut b = LayoutBuilder::new();
90 b.col(|r| {
91 for kind in &kinds {
92 r.panel(Arc::clone(kind));
93 }
94 })?;
95 b.build()
96 }
97
98 pub fn row_with(
100 panels: impl IntoIterator<Item = (impl Into<Arc<str>>, crate::panel::Constraints)>,
101 ) -> Result<Self, PaneError> {
102 let panels: Vec<_> = panels.into_iter().map(|(k, c)| (k.into(), c)).collect();
103 let mut b = LayoutBuilder::new();
104 b.row(|r| {
105 for (kind, constraints) in &panels {
106 r.panel_with(Arc::clone(kind), *constraints);
107 }
108 })?;
109 b.build()
110 }
111
112 pub fn col_with(
114 panels: impl IntoIterator<Item = (impl Into<Arc<str>>, crate::panel::Constraints)>,
115 ) -> Result<Self, PaneError> {
116 let panels: Vec<_> = panels.into_iter().map(|(k, c)| (k.into(), c)).collect();
117 let mut b = LayoutBuilder::new();
118 b.col(|c| {
119 for (kind, constraints) in &panels {
120 c.panel_with(Arc::clone(kind), *constraints);
121 }
122 })?;
123 b.build()
124 }
125
126 pub fn presets() -> &'static [PresetInfo] {
128 &crate::preset::catalog::PRESETS
129 }
130
131 pub fn master_stack(
135 kinds: impl IntoIterator<Item = impl Into<Arc<str>>>,
136 ) -> crate::preset::MasterStack {
137 crate::preset::MasterStack::new(kinds)
138 }
139
140 pub fn centered_master(
142 kinds: impl IntoIterator<Item = impl Into<Arc<str>>>,
143 ) -> crate::preset::CenteredMaster {
144 crate::preset::CenteredMaster::new(kinds)
145 }
146
147 pub fn monocle(kinds: impl IntoIterator<Item = impl Into<Arc<str>>>) -> crate::preset::Monocle {
149 crate::preset::Monocle::new(kinds)
150 }
151
152 pub fn scrollable(
154 kinds: impl IntoIterator<Item = impl Into<Arc<str>>>,
155 ) -> crate::preset::Scrollable {
156 crate::preset::Scrollable::new(kinds)
157 }
158
159 pub fn dwindle(kinds: impl IntoIterator<Item = impl Into<Arc<str>>>) -> crate::preset::Dwindle {
161 crate::preset::Dwindle::new(kinds)
162 }
163
164 pub fn spiral(kinds: impl IntoIterator<Item = impl Into<Arc<str>>>) -> crate::preset::Spiral {
166 crate::preset::Spiral::new(kinds)
167 }
168
169 pub fn columns(
171 count: usize,
172 kinds: impl IntoIterator<Item = impl Into<Arc<str>>>,
173 ) -> crate::preset::Columns {
174 crate::preset::Columns::new(count, kinds)
175 }
176
177 pub fn deck(kinds: impl IntoIterator<Item = impl Into<Arc<str>>>) -> crate::preset::Deck {
179 crate::preset::Deck::new(kinds)
180 }
181
182 pub fn tabbed(kinds: impl IntoIterator<Item = impl Into<Arc<str>>>) -> crate::preset::Tabbed {
184 crate::preset::Tabbed::new(kinds)
185 }
186
187 pub fn stacked(kinds: impl IntoIterator<Item = impl Into<Arc<str>>>) -> crate::preset::Stacked {
189 crate::preset::Stacked::new(kinds)
190 }
191
192 pub fn sidebar(
194 sidebar_kind: impl Into<Arc<str>>,
195 content_kind: impl Into<Arc<str>>,
196 ) -> crate::preset::Sidebar {
197 crate::preset::Sidebar::new(sidebar_kind, content_kind)
198 }
199
200 pub fn holy_grail(
202 header: impl Into<Arc<str>>,
203 footer: impl Into<Arc<str>>,
204 left: impl Into<Arc<str>>,
205 main: impl Into<Arc<str>>,
206 right: impl Into<Arc<str>>,
207 ) -> crate::preset::HolyGrail {
208 crate::preset::HolyGrail::new(header, footer, left, main, right)
209 }
210
211 pub fn dashboard(
213 cards: impl IntoIterator<Item = (impl Into<Arc<str>>, usize)>,
214 ) -> crate::preset::Dashboard {
215 crate::preset::Dashboard::new(cards)
216 }
217
218 pub fn split(first: impl Into<Arc<str>>, second: impl Into<Arc<str>>) -> crate::preset::Split {
220 crate::preset::Split::new(first, second)
221 }
222
223 pub fn grid(
225 cols: usize,
226 kinds: impl IntoIterator<Item = impl Into<Arc<str>>>,
227 ) -> crate::preset::Grid {
228 crate::preset::Grid::new(cols, kinds)
229 }
230}
231
232impl Layout {
233 #[cfg(feature = "toml")]
235 pub fn from_toml(input: &str) -> Result<Self, crate::toml_parse::TomlError> {
236 crate::toml_parse::parse(input)
237 }
238
239 #[cfg(feature = "toml")]
241 pub fn from_toml_file(
242 path: impl AsRef<std::path::Path>,
243 ) -> Result<Self, crate::toml_parse::TomlError> {
244 let input = std::fs::read_to_string(path)?;
245 crate::toml_parse::parse(&input)
246 }
247
248 pub fn compile(&self) -> Result<crate::compiler::CompileResult, PaneError> {
250 compile(&self.tree)
251 }
252}
253
254impl From<Layout> for LayoutTree {
255 fn from(layout: Layout) -> Self {
256 layout.tree
257 }
258}