cosmic/widget/segmented_button/
vertical.rs1use super::model::{Model, Selectable};
7use super::style::StyleSheet;
8use super::widget::{ItemBounds, LocalState, SegmentedButton, SegmentedVariant};
9
10use iced::{Length, Rectangle, Size};
11use iced_core::layout;
12
13pub struct Vertical;
15
16pub type VerticalSegmentedButton<'a, SelectionMode, Message> =
18 SegmentedButton<'a, Vertical, SelectionMode, Message>;
19
20pub fn vertical<SelectionMode, Message>(
24 model: &Model<SelectionMode>,
25) -> SegmentedButton<Vertical, SelectionMode, Message>
26where
27 Model<SelectionMode>: Selectable,
28 SelectionMode: Default,
29{
30 SegmentedButton::new(model)
31}
32
33impl<SelectionMode, Message> SegmentedVariant
34 for SegmentedButton<'_, Vertical, SelectionMode, Message>
35where
36 Model<SelectionMode>: Selectable,
37 SelectionMode: Default,
38{
39 const VERTICAL: bool = true;
40
41 fn variant_appearance(
42 theme: &crate::Theme,
43 style: &crate::theme::SegmentedButton,
44 ) -> super::Appearance {
45 theme.vertical(style)
46 }
47
48 #[allow(clippy::cast_precision_loss)]
49 fn variant_bounds<'b>(
50 &'b self,
51 state: &'b LocalState,
52 mut bounds: Rectangle,
53 ) -> Box<dyn Iterator<Item = ItemBounds> + 'b> {
54 let spacing = f32::from(self.spacing);
55
56 Box::new(
57 self.model
58 .order
59 .iter()
60 .copied()
61 .enumerate()
62 .flat_map(move |(nth, key)| {
63 let mut divider = None;
64 if self.model.divider_above(key).unwrap_or(false) && nth > 0 {
65 let mut divider_bounds = bounds;
66 divider_bounds.height = 1.0;
67 divider_bounds.x += f32::from(self.button_padding[0]);
68 divider_bounds.width -= f32::from(self.button_padding[0]);
69 divider_bounds.width -= f32::from(self.button_padding[2]);
70 divider = Some(ItemBounds::Divider(divider_bounds, false));
71
72 bounds.y += divider_bounds.height + spacing;
73 }
74
75 let mut layout_bounds = bounds;
76
77 let layout_size = state.internal_layout[nth].0;
78
79 layout_bounds.height = layout_size.height;
80
81 bounds.y += layout_bounds.height + spacing;
82
83 std::iter::once(ItemBounds::Button(key, layout_bounds)).chain(divider)
84 }),
85 )
86 }
87
88 #[allow(clippy::cast_precision_loss)]
89 #[allow(clippy::cast_possible_truncation)]
90 #[allow(clippy::cast_sign_loss)]
91 fn variant_layout(
92 &self,
93 state: &mut LocalState,
94 renderer: &crate::Renderer,
95 limits: &layout::Limits,
96 ) -> Size {
97 state.internal_layout.clear();
98 state.buttons_visible = self.model.order.len();
99 let limits = limits.width(self.width);
100
101 let (width, item_height) = self.max_button_dimensions(state, renderer);
102
103 for (size, actual) in &mut state.internal_layout {
104 size.width = width;
105 actual.width = item_height;
106 }
107
108 let spacing = f32::from(self.spacing);
109 let mut height = 0.0;
110 for (nth, key) in self.model.order.iter().copied().enumerate() {
111 if nth > 0 {
112 height += spacing;
113 if self.model.divider_above(key).unwrap_or(false) {
114 height += 1.0 + spacing;
115 }
116 }
117 height += item_height;
118 }
119
120 limits.height(Length::Fixed(height)).resolve(
121 self.width,
122 self.height,
123 Size::new(width, height),
124 )
125 }
126}