1use repose_core::prelude::*;
7use repose_core::{Modifier, PaddingValues, View, WindowSizeClass};
8
9use crate::{Box, Column, Row, Text, ViewExt};
10
11#[derive(Clone, Copy, Debug)]
12pub struct PaneScaffoldDirective {
13 pub max_horizontal_partitions: u32,
14 pub horizontal_part_spacing: Dp,
15 pub list_pane_width: Dp,
16 pub content_padding: PaddingValues,
17}
18
19impl Default for PaneScaffoldDirective {
20 fn default() -> Self {
21 Self {
22 max_horizontal_partitions: 1,
23 horizontal_part_spacing: Dp::ZERO,
24 list_pane_width: Dp::ZERO,
25 content_padding: PaddingValues::default(),
26 }
27 }
28}
29
30impl PaneScaffoldDirective {
31 pub fn from_window_size_class(class: WindowSizeClass) -> Self {
32 if class.is_at_least_medium_width() {
33 Self {
34 max_horizontal_partitions: 2,
35 horizontal_part_spacing: Dp::ZERO,
36 list_pane_width: Dp(360.0),
37 content_padding: PaddingValues::default(),
38 }
39 } else {
40 Self {
41 max_horizontal_partitions: 1,
42 horizontal_part_spacing: Dp::ZERO,
43 list_pane_width: Dp::ZERO,
44 content_padding: PaddingValues::default(),
45 }
46 }
47 }
48}
49
50#[derive(Clone, Copy, Debug, PartialEq, Eq)]
51pub enum ListDetailPaneValue {
52 List,
53 Detail,
54}
55
56pub fn ListDetailPaneScaffold<F1, F2>(
57 directive: PaneScaffoldDirective,
58 value: ListDetailPaneValue,
59 list: F1,
60 detail: F2,
61) -> View
62where
63 F1: Fn() -> View + 'static,
64 F2: Fn() -> View + 'static,
65{
66 if directive.max_horizontal_partitions >= 2 {
67 let spacing = directive.horizontal_part_spacing;
68 let list_mod = if directive.list_pane_width.0 > 0.0 {
69 Modifier::new()
70 .width(directive.list_pane_width)
71 .fill_max_height()
72 } else {
73 Modifier::new().flex_grow(1.0).fill_max_height()
74 };
75 Row(Modifier::new().fill_max_size().gap(spacing)).child((
76 Box(list_mod).child(list()),
77 Box(Modifier::new().flex_grow(1.0).fill_max_height()).child(detail()),
78 ))
79 } else {
80 match value {
81 ListDetailPaneValue::List => list(),
82 ListDetailPaneValue::Detail => detail(),
83 }
84 }
85}
86
87pub fn ScaffoldPane(directive: &PaneScaffoldDirective, content: View) -> View {
88 Box(Modifier::new()
89 .fill_max_size()
90 .padding_values(directive.content_padding))
91 .child(content)
92}
93
94pub fn TwoPaneTopBar(title: &str, leading: Option<View>, trailing: Option<View>) -> View {
95 let th = theme();
96 let leading = leading.unwrap_or_else(|| Box(Modifier::new().width(Dp::ZERO).height(Dp::ZERO)));
97 let trailing =
98 trailing.unwrap_or_else(|| Box(Modifier::new().width(Dp::ZERO).height(Dp::ZERO)));
99 Box(Modifier::new()
100 .fill_max_width()
101 .height(Dp(56.0))
102 .background(th.surface)
103 .padding_values(PaddingValues {
104 left: Dp(16.0),
105 right: Dp(16.0),
106 top: Dp::ZERO,
107 bottom: Dp::ZERO,
108 }))
109 .child((
110 leading,
111 Column(
112 Modifier::new()
113 .flex_grow(1.0)
114 .padding_values(PaddingValues {
115 left: Dp(16.0),
116 right: Dp(16.0),
117 top: Dp::ZERO,
118 bottom: Dp::ZERO,
119 }),
120 )
121 .child(Text(title)),
122 trailing,
123 ))
124}