cosmic/widget/settings/
item.rs1use std::borrow::Cow;
5
6use crate::{
7 Element, Theme, theme,
8 widget::{FlexRow, Row, column, container, flex_row, row, text},
9};
10use derive_setters::Setters;
11use iced_core::{Length, text::Wrapping};
12use iced_widget::space;
13use taffy::AlignContent;
14
15#[must_use]
17#[allow(clippy::module_name_repetitions)]
18pub fn item<'a, Message: 'static>(
19 title: impl Into<Cow<'a, str>> + 'a,
20 widget: impl Into<Element<'a, Message>> + 'a,
21) -> Row<'a, Message, Theme> {
22 #[inline(never)]
23 fn inner<'a, Message: 'static>(
24 title: Cow<'a, str>,
25 widget: Element<'a, Message>,
26 ) -> Row<'a, Message, Theme> {
27 item_row(vec![
28 text(title).wrapping(Wrapping::Word).into(),
29 space::horizontal().into(),
30 widget,
31 ])
32 }
33
34 inner(title.into(), widget.into())
35}
36
37#[must_use]
39#[allow(clippy::module_name_repetitions)]
40pub fn item_row<Message>(children: Vec<Element<Message>>) -> Row<Message, Theme> {
41 row::with_children(children)
42 .spacing(theme::spacing().space_xs)
43 .align_y(iced::Alignment::Center)
44 .width(Length::Fill)
45}
46
47#[allow(clippy::module_name_repetitions)]
49pub fn flex_item<'a, Message: 'static>(
50 title: impl Into<Cow<'a, str>> + 'a,
51 widget: impl Into<Element<'a, Message>> + 'a,
52) -> FlexRow<'a, Message> {
53 #[inline(never)]
54 fn inner<'a, Message: 'static>(
55 title: Cow<'a, str>,
56 widget: Element<'a, Message>,
57 ) -> FlexRow<'a, Message> {
58 flex_item_row(vec![
59 text(title)
60 .wrapping(Wrapping::Word)
61 .width(Length::Fill)
62 .into(),
63 container(widget).width(Length::Shrink).into(),
64 ])
65 .width(Length::Fill)
66 }
67
68 inner(title.into(), widget.into())
69}
70
71#[allow(clippy::module_name_repetitions)]
73pub fn flex_item_row<Message>(children: Vec<Element<Message>>) -> FlexRow<Message> {
74 flex_row(children)
75 .spacing(theme::spacing().space_xs)
76 .min_item_width(200.0)
77 .justify_items(iced::Alignment::Center)
78 .justify_content(AlignContent::SpaceBetween)
79 .width(Length::Fill)
80}
81
82pub fn builder<'a, Message: 'static>(title: impl Into<Cow<'a, str>>) -> Item<'a, Message> {
84 Item {
85 title: title.into(),
86 description: None,
87 icon: None,
88 }
89}
90
91#[derive(Setters)]
93pub struct Item<'a, Message> {
94 title: Cow<'a, str>,
96
97 #[setters(strip_option, into)]
99 description: Option<Cow<'a, str>>,
100
101 #[setters(strip_option, into)]
103 icon: Option<Element<'a, Message>>,
104}
105
106impl<'a, Message: 'static> Item<'a, Message> {
107 pub fn control(self, widget: impl Into<Element<'a, Message>>) -> Row<'a, Message, Theme> {
109 item_row(self.control_(widget.into()))
110 }
111
112 pub fn flex_control(self, widget: impl Into<Element<'a, Message>>) -> FlexRow<'a, Message> {
114 flex_item_row(self.control_(widget.into()))
115 }
116
117 #[inline(never)]
118 fn control_(self, widget: Element<'a, Message>) -> Vec<Element<'a, Message>> {
119 let mut contents = Vec::with_capacity(4);
120
121 if let Some(icon) = self.icon {
122 contents.push(icon);
123 }
124
125 if let Some(description) = self.description {
126 let column = column::with_capacity(2)
127 .spacing(2)
128 .push(text::body(self.title).wrapping(Wrapping::Word))
129 .push(text::caption(description).wrapping(Wrapping::Word))
130 .width(Length::Fill);
131
132 contents.push(column.into());
133 } else {
134 contents.push(text(self.title).width(Length::Fill).into());
135 }
136
137 contents.push(widget);
138 contents
139 }
140
141 pub fn toggler(
142 self,
143 is_checked: bool,
144 message: impl Fn(bool) -> Message + 'static,
145 ) -> Row<'a, Message, Theme> {
146 self.control(
147 crate::widget::toggler(is_checked)
148 .width(Length::Shrink)
149 .on_toggle(message),
150 )
151 }
152}