cosmic/widget/
dialog.rs
1use crate::{
2 Element,
3 iced::{Length, Pixels},
4 style, theme, widget,
5};
6use std::borrow::Cow;
7
8pub fn dialog<'a, Message>() -> Dialog<'a, Message> {
9 Dialog::new()
10}
11
12pub struct Dialog<'a, Message> {
13 title: Option<Cow<'a, str>>,
14 icon: Option<Element<'a, Message>>,
15 body: Option<Cow<'a, str>>,
16 controls: Vec<Element<'a, Message>>,
17 primary_action: Option<Element<'a, Message>>,
18 secondary_action: Option<Element<'a, Message>>,
19 tertiary_action: Option<Element<'a, Message>>,
20 width: Option<Length>,
21 height: Option<Length>,
22 max_width: Option<Pixels>,
23 max_height: Option<Pixels>,
24}
25
26impl<Message> Default for Dialog<'_, Message> {
27 fn default() -> Self {
28 Self::new()
29 }
30}
31
32impl<'a, Message> Dialog<'a, Message> {
33 pub fn new() -> Self {
34 Self {
35 title: None,
36 icon: None,
37 body: None,
38 controls: Vec::new(),
39 primary_action: None,
40 secondary_action: None,
41 tertiary_action: None,
42 width: None,
43 height: None,
44 max_width: None,
45 max_height: None,
46 }
47 }
48
49 pub fn title(mut self, title: impl Into<Cow<'a, str>>) -> Self {
50 self.title = Some(title.into());
51 self
52 }
53
54 pub fn icon(mut self, icon: impl Into<Element<'a, Message>>) -> Self {
55 self.icon = Some(icon.into());
56 self
57 }
58
59 pub fn body(mut self, body: impl Into<Cow<'a, str>>) -> Self {
60 self.body = Some(body.into());
61 self
62 }
63
64 pub fn control(mut self, control: impl Into<Element<'a, Message>>) -> Self {
65 self.controls.push(control.into());
66 self
67 }
68
69 pub fn primary_action(mut self, button: impl Into<Element<'a, Message>>) -> Self {
70 self.primary_action = Some(button.into());
71 self
72 }
73
74 pub fn secondary_action(mut self, button: impl Into<Element<'a, Message>>) -> Self {
75 self.secondary_action = Some(button.into());
76 self
77 }
78
79 pub fn tertiary_action(mut self, button: impl Into<Element<'a, Message>>) -> Self {
80 self.tertiary_action = Some(button.into());
81 self
82 }
83
84 pub fn width(mut self, width: impl Into<Length>) -> Self {
85 self.width = Some(width.into());
86 self
87 }
88
89 pub fn height(mut self, height: impl Into<Length>) -> Self {
90 self.height = Some(height.into());
91 self
92 }
93
94 pub fn max_height(mut self, max_height: impl Into<Pixels>) -> Self {
95 self.max_height = Some(max_height.into());
96 self
97 }
98
99 pub fn max_width(mut self, max_width: impl Into<Pixels>) -> Self {
100 self.max_width = Some(max_width.into());
101 self
102 }
103}
104
105impl<'a, Message: Clone + 'static> From<Dialog<'a, Message>> for Element<'a, Message> {
106 fn from(dialog: Dialog<'a, Message>) -> Self {
107 let cosmic_theme::Spacing {
108 space_l,
109 space_m,
110 space_s,
111 space_xxs,
112 ..
113 } = theme::THEME.lock().unwrap().cosmic().spacing;
114
115 let mut content_col = widget::column::with_capacity(3 + dialog.controls.len() * 2);
116
117 let mut should_space = false;
118
119 if let Some(title) = dialog.title {
120 content_col = content_col.push(widget::text::title3(title));
121 should_space = true;
122 }
123 if let Some(body) = dialog.body {
124 if should_space {
125 content_col = content_col
126 .push(widget::vertical_space().height(Length::Fixed(space_xxs.into())));
127 }
128 content_col = content_col.push(widget::text::body(body));
129 should_space = true;
130 }
131 for control in dialog.controls {
132 if should_space {
133 content_col = content_col
134 .push(widget::vertical_space().height(Length::Fixed(space_s.into())));
135 }
136 content_col = content_col.push(control);
137 should_space = true;
138 }
139
140 let mut content_row = widget::row::with_capacity(2).spacing(space_s);
141 if let Some(icon) = dialog.icon {
142 content_row = content_row.push(icon);
143 }
144 content_row = content_row.push(content_col);
145
146 let mut button_row = widget::row::with_capacity(4).spacing(space_xxs);
147 if let Some(button) = dialog.tertiary_action {
148 button_row = button_row.push(button);
149 }
150 button_row = button_row.push(widget::horizontal_space());
151 if let Some(button) = dialog.secondary_action {
152 button_row = button_row.push(button);
153 }
154 if let Some(button) = dialog.primary_action {
155 button_row = button_row.push(button);
156 }
157
158 let mut container = widget::container(
159 widget::column::with_children(vec![content_row.into(), button_row.into()])
160 .spacing(space_l),
161 )
162 .class(style::Container::Dialog)
163 .padding(space_m)
164 .width(dialog.width.unwrap_or(Length::Fixed(570.0)));
165
166 if let Some(height) = dialog.height {
167 container = container.height(height);
168 }
169
170 if let Some(max_width) = dialog.max_width {
171 container = container.max_width(max_width);
172 }
173
174 if let Some(max_height) = dialog.max_height {
175 container = container.max_height(max_height);
176 }
177
178 Element::from(container)
179 }
180}