cosmic/widget/
nav_bar.rs
1use apply::Apply;
9use iced::{
10 Background, Length,
11 clipboard::{dnd::DndAction, mime::AllowedMimeTypes},
12};
13use iced_core::{Border, Color, Shadow};
14
15use crate::widget::{Container, Icon, container, menu, scrollable, segmented_button};
16use crate::{Theme, theme};
17
18use super::dnd_destination::DragId;
19
20pub type Id = segmented_button::Entity;
21pub type Model = segmented_button::SingleSelectModel;
22
23pub fn nav_bar<Message: Clone + 'static>(
27 model: &segmented_button::SingleSelectModel,
28 on_activate: fn(segmented_button::Entity) -> Message,
29) -> NavBar<Message> {
30 NavBar {
31 segmented_button: segmented_button::vertical(model).on_activate(on_activate),
32 }
33}
34
35pub fn nav_bar_dnd<Message, D: AllowedMimeTypes>(
38 model: &segmented_button::SingleSelectModel,
39 on_activate: fn(segmented_button::Entity) -> Message,
40 on_dnd_enter: impl Fn(segmented_button::Entity, Vec<String>) -> Message + 'static,
41 on_dnd_leave: impl Fn(segmented_button::Entity) -> Message + 'static,
42 on_dnd_drop: impl Fn(segmented_button::Entity, Option<D>, DndAction) -> Message + 'static,
43 id: DragId,
44) -> NavBar<Message>
45where
46 Message: Clone + 'static,
47{
48 NavBar {
49 segmented_button: segmented_button::vertical(model)
50 .on_activate(on_activate)
51 .on_dnd_enter(on_dnd_enter)
52 .on_dnd_leave(on_dnd_leave)
53 .on_dnd_drop(on_dnd_drop)
54 .drag_id(id),
55 }
56}
57
58#[must_use]
59pub struct NavBar<'a, Message> {
60 segmented_button:
61 segmented_button::VerticalSegmentedButton<'a, segmented_button::SingleSelect, Message>,
62}
63
64impl<'a, Message: Clone + 'static> NavBar<'a, Message> {
65 #[inline]
66 pub fn close_icon(mut self, close_icon: Icon) -> Self {
67 self.segmented_button = self.segmented_button.close_icon(close_icon);
68 self
69 }
70
71 #[inline]
72 pub fn context_menu(mut self, context_menu: Option<Vec<menu::Tree<'a, Message>>>) -> Self {
73 self.segmented_button = self.segmented_button.context_menu(context_menu);
74 self
75 }
76
77 #[inline]
78 pub fn drag_id(mut self, id: DragId) -> Self {
79 self.segmented_button = self.segmented_button.drag_id(id);
80 self
81 }
82
83 #[must_use]
85 #[inline]
86 pub fn into_container(self) -> Container<'a, Message, crate::Theme, crate::Renderer> {
87 Container::from(self)
88 }
89
90 pub fn on_close<T>(mut self, on_close: T) -> Self
92 where
93 T: Fn(Id) -> Message + 'static,
94 {
95 self.segmented_button = self.segmented_button.on_close(on_close);
96 self
97 }
98
99 pub fn on_context<T>(mut self, on_context: T) -> Self
101 where
102 T: Fn(Id) -> Message + 'static,
103 {
104 self.segmented_button = self.segmented_button.on_context(on_context);
105 self
106 }
107
108 pub fn on_middle_press<T>(mut self, on_middle_press: T) -> Self
110 where
111 T: Fn(Id) -> Message + 'static,
112 {
113 self.segmented_button = self.segmented_button.on_middle_press(on_middle_press);
114 self
115 }
116
117 pub fn on_dnd_drop<D: AllowedMimeTypes>(
119 mut self,
120 handler: impl Fn(Id, Option<D>, DndAction) -> Message + 'static,
121 ) -> Self {
122 self.segmented_button = self.segmented_button.on_dnd_drop(handler);
123 self
124 }
125
126 pub fn on_dnd_enter(mut self, handler: impl Fn(Id, Vec<String>) -> Message + 'static) -> Self {
128 self.segmented_button = self.segmented_button.on_dnd_enter(handler);
129 self
130 }
131
132 pub fn on_dnd_leave(mut self, handler: impl Fn(Id) -> Message + 'static) -> Self {
134 self.segmented_button = self.segmented_button.on_dnd_leave(handler);
135 self
136 }
137}
138
139impl<'a, Message: Clone + 'static> From<NavBar<'a, Message>>
140 for Container<'a, Message, crate::Theme, crate::Renderer>
141{
142 fn from(this: NavBar<'a, Message>) -> Self {
143 let theme = crate::theme::active();
144 let space_s = theme.cosmic().space_s();
145 let space_xxs = theme.cosmic().space_xxs();
146
147 this.segmented_button
148 .button_height(32)
149 .button_padding([space_s, space_xxs, space_s, space_xxs])
150 .button_spacing(space_xxs)
151 .spacing(space_xxs)
152 .style(crate::theme::SegmentedButton::TabBar)
153 .apply(container)
154 .padding(space_xxs)
155 .apply(scrollable)
156 .class(crate::style::iced::Scrollable::Minimal)
157 .height(Length::Fill)
158 .apply(container)
159 .height(Length::Fill)
160 .class(theme::Container::custom(nav_bar_style))
161 }
162}
163
164impl<'a, Message: Clone + 'static> From<NavBar<'a, Message>> for crate::Element<'a, Message> {
165 fn from(this: NavBar<'a, Message>) -> Self {
166 Container::from(this).into()
167 }
168}
169
170#[must_use]
171pub fn nav_bar_style(theme: &Theme) -> iced_widget::container::Style {
172 let cosmic = &theme.cosmic();
173 iced_widget::container::Style {
174 icon_color: Some(cosmic.on_bg_color().into()),
175 text_color: Some(cosmic.on_bg_color().into()),
176 background: Some(Background::Color(cosmic.primary.base.into())),
177 border: Border {
178 width: 0.0,
179 color: Color::TRANSPARENT,
180 radius: cosmic.corner_radii.radius_s.into(),
181 },
182 shadow: Shadow::default(),
183 }
184}