cosmic/widget/segmented_button/
vertical.rs
1use 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 fn variant_appearance(
40 theme: &crate::Theme,
41 style: &crate::theme::SegmentedButton,
42 ) -> super::Appearance {
43 theme.vertical(style)
44 }
45
46 #[allow(clippy::cast_precision_loss)]
47 fn variant_bounds<'b>(
48 &'b self,
49 state: &'b LocalState,
50 mut bounds: Rectangle,
51 ) -> Box<dyn Iterator<Item = ItemBounds> + 'b> {
52 let spacing = f32::from(self.spacing);
53
54 Box::new(
55 self.model
56 .order
57 .iter()
58 .copied()
59 .enumerate()
60 .flat_map(move |(nth, key)| {
61 let mut divider = None;
62 if self.model.divider_above(key).unwrap_or(false) && nth > 0 {
63 let mut divider_bounds = bounds;
64 divider_bounds.height = 1.0;
65 divider_bounds.x += f32::from(self.button_padding[0]);
66 divider_bounds.width -= f32::from(self.button_padding[0]);
67 divider_bounds.width -= f32::from(self.button_padding[2]);
68 divider = Some(ItemBounds::Divider(divider_bounds, false));
69
70 bounds.y += divider_bounds.height + spacing;
71 }
72
73 let mut layout_bounds = bounds;
74
75 let layout_size = state.internal_layout[nth].0;
76
77 layout_bounds.height = layout_size.height;
78
79 bounds.y += layout_bounds.height + spacing;
80
81 std::iter::once(ItemBounds::Button(key, layout_bounds)).chain(divider)
82 }),
83 )
84 }
85
86 #[allow(clippy::cast_precision_loss)]
87 #[allow(clippy::cast_possible_truncation)]
88 #[allow(clippy::cast_sign_loss)]
89 fn variant_layout(
90 &self,
91 state: &mut LocalState,
92 renderer: &crate::Renderer,
93 limits: &layout::Limits,
94 ) -> Size {
95 state.internal_layout.clear();
96 state.buttons_visible = self.model.order.len();
97 let limits = limits.width(self.width);
98
99 let (width, item_height) = self.max_button_dimensions(state, renderer);
100
101 for (size, actual) in &mut state.internal_layout {
102 size.width = width;
103 actual.width = item_height;
104 }
105
106 let spacing = f32::from(self.spacing);
107 let mut height = 0.0;
108 for (nth, key) in self.model.order.iter().copied().enumerate() {
109 if nth > 0 {
110 height += spacing;
111 if self.model.divider_above(key).unwrap_or(false) {
112 height += 1.0 + spacing;
113 }
114 }
115 height += item_height;
116 }
117
118 limits.height(Length::Fixed(height)).resolve(
119 self.width,
120 self.height,
121 Size::new(width, height),
122 )
123 }
124}