Skip to main content

cosmic/widget/
dialog.rs

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