cosmic/widget/segmented_button/model/
entity.rs

1// Copyright 2023 System76 <info@system76.com>
2// SPDX-License-Identifier: MPL-2.0
3
4use std::borrow::Cow;
5
6use slotmap::{SecondaryMap, SparseSecondaryMap};
7
8use crate::widget::Icon;
9
10use super::{Entity, Model, Selectable};
11
12/// A newly-inserted item which may have additional actions applied to it.
13pub struct EntityMut<'a, SelectionMode: Default> {
14    pub(super) id: Entity,
15    pub(super) model: &'a mut Model<SelectionMode>,
16}
17
18impl<SelectionMode: Default> EntityMut<'_, SelectionMode>
19where
20    Model<SelectionMode>: Selectable,
21{
22    /// Activates the newly-inserted item.
23    ///
24    /// ```ignore
25    /// model.insert().text("Item A").activate();
26    /// ```
27    #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)]
28    #[inline]
29    pub fn activate(self) -> Self {
30        self.model.activate(self.id);
31        self
32    }
33
34    /// Associates extra data with an external secondary map.
35    ///
36    /// The secondary map internally uses a `Vec`, so should only be used for data that
37    /// is commonly associated.
38    ///
39    /// ```ignore
40    /// let mut secondary_data = segmented_button::SecondaryMap::default();
41    /// model.insert().text("Item A").secondary(&mut secondary_data, String::new("custom data"));
42    /// ```
43    #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)]
44    #[inline]
45    pub fn secondary<Data>(self, map: &mut SecondaryMap<Entity, Data>, data: Data) -> Self {
46        map.insert(self.id, data);
47        self
48    }
49
50    /// Associates extra data with an external sparse secondary map.
51    ///
52    /// Sparse maps internally use a `HashMap`, for data that is sparsely associated.
53    ///
54    /// ```ignore
55    /// let mut secondary_data = segmented_button::SparseSecondaryMap::default();
56    /// model.insert().text("Item A").secondary(&mut secondary_data, String::new("custom data"));
57    /// ```
58    #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)]
59    #[inline]
60    pub fn secondary_sparse<Data>(
61        self,
62        map: &mut SparseSecondaryMap<Entity, Data>,
63        data: Data,
64    ) -> Self {
65        map.insert(self.id, data);
66        self
67    }
68
69    /// Shows a close button for this item.
70    #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)]
71    #[inline]
72    pub fn closable(self) -> Self {
73        self.model.closable_set(self.id, true);
74        self
75    }
76
77    /// Associates data with the item.
78    ///
79    /// There may only be one data component per Rust type.
80    ///
81    /// ```ignore
82    /// model.insert().text("Item A").data(String::from("custom string"));
83    /// ```
84    #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)]
85    #[inline]
86    pub fn data<Data: 'static>(self, data: Data) -> Self {
87        self.model.data_set(self.id, data);
88        self
89    }
90
91    #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)]
92    #[inline]
93    pub fn divider_above(self, divider_above: bool) -> Self {
94        self.model.divider_above_set(self.id, divider_above);
95        self
96    }
97
98    /// Define an icon for the item.
99    ///
100    /// ```ignore
101    /// model.insert().text("Item A").icon(IconSource::from("icon-a"));
102    /// ```
103    #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)]
104    #[inline]
105    pub fn icon(self, icon: impl Into<Icon>) -> Self {
106        self.model.icon_set(self.id, icon.into());
107        self
108    }
109
110    /// Returns the ID of the item that was inserted.
111    ///
112    /// ```ignore
113    /// let id = model.insert("Item A").id();
114    /// ```
115    #[must_use]
116    #[inline]
117    pub const fn id(self) -> Entity {
118        self.id
119    }
120
121    #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)]
122    #[inline]
123    pub fn indent(self, indent: u16) -> Self {
124        self.model.indent_set(self.id, indent);
125        self
126    }
127
128    /// Define the position of the item.
129    #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)]
130    #[inline]
131    pub fn position(self, position: u16) -> Self {
132        self.model.position_set(self.id, position);
133        self
134    }
135
136    /// Swap the position with another item in the model.
137    #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)]
138    #[inline]
139    pub fn position_swap(self, other: Entity) -> Self {
140        self.model.position_swap(self.id, other);
141        self
142    }
143
144    /// Defines the text for the item.
145    #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)]
146    pub fn text(self, text: impl Into<Cow<'static, str>>) -> Self {
147        self.model.text_set(self.id, text);
148        self
149    }
150
151    /// Calls a function with the ID without consuming the wrapper.
152    #[allow(clippy::must_use_candidate, clippy::return_self_not_must_use)]
153    pub fn with_id(self, func: impl FnOnce(Entity)) -> Self {
154        func(self.id);
155        self
156    }
157}