cosmic/app/
context_drawer.rs

1// Copyright 2024 System76 <info@system76.com>
2// SPDX-License-Identifier: MPL-2.0
3//
4use std::borrow::Cow;
5
6use crate::Element;
7
8pub struct ContextDrawer<'a, Message: Clone + 'static> {
9    pub title: Option<Cow<'a, str>>,
10    pub header_actions: Vec<Element<'a, Message>>,
11    pub header: Option<Element<'a, Message>>,
12    pub content: Element<'a, Message>,
13    pub footer: Option<Element<'a, Message>>,
14    pub on_close: Message,
15}
16
17#[cfg(feature = "about")]
18pub fn about<Message: Clone + 'static>(
19    about: &crate::widget::about::About,
20    on_url_press: impl Fn(String) -> Message,
21    on_close: Message,
22) -> ContextDrawer<'_, Message> {
23    context_drawer(crate::widget::about(about, on_url_press), on_close)
24}
25
26pub fn context_drawer<'a, Message: Clone + 'static>(
27    content: impl Into<Element<'a, Message>>,
28    on_close: Message,
29) -> ContextDrawer<'a, Message> {
30    ContextDrawer {
31        title: None,
32        content: content.into(),
33        header_actions: vec![],
34        footer: None,
35        on_close,
36        header: None,
37    }
38}
39
40impl<'a, Message: Clone + 'static> ContextDrawer<'a, Message> {
41    /// Set a context drawer header title
42    pub fn title(mut self, title: impl Into<Cow<'a, str>>) -> Self {
43        self.title = Some(title.into());
44        self
45    }
46    /// App-specific actions at the start of the context drawer header
47    pub fn header_actions(
48        mut self,
49        header_actions: impl IntoIterator<Item = Element<'a, Message>>,
50    ) -> Self {
51        self.header_actions = header_actions.into_iter().collect();
52        self
53    }
54    /// Non-scrolling elements placed below the context drawer title row
55    pub fn header(mut self, header: impl Into<Element<'a, Message>>) -> Self {
56        self.header = Some(header.into());
57        self
58    }
59
60    /// Elements placed below the context drawer scrollable
61    pub fn footer(mut self, footer: impl Into<Element<'a, Message>>) -> Self {
62        self.footer = Some(footer.into());
63        self
64    }
65
66    pub fn map<Out: Clone + 'static>(
67        mut self,
68        on_message: fn(Message) -> Out,
69    ) -> ContextDrawer<'a, Out> {
70        ContextDrawer {
71            title: self.title,
72            content: self.content.map(on_message),
73            header: self.header.map(|el| el.map(on_message)),
74            footer: self.footer.map(|el| el.map(on_message)),
75            on_close: on_message(self.on_close),
76            header_actions: self
77                .header_actions
78                .into_iter()
79                .map(|el| el.map(on_message))
80                .collect(),
81        }
82    }
83}