1use apply::Apply;
9use iced::clipboard::dnd::DndAction;
10use iced::clipboard::mime::AllowedMimeTypes;
11use iced::{Background, Length, window};
12use iced_core::{Border, Color, Shadow};
13
14use crate::widget::{Container, Icon, container, menu, scrollable, segmented_button};
15use crate::{Theme, theme};
16
17use super::dnd_destination::DragId;
18
19pub type Id = segmented_button::Entity;
20pub type Model = segmented_button::SingleSelectModel;
21
22pub fn nav_bar<Message: Clone + 'static>(
26 model: &segmented_button::SingleSelectModel,
27 on_activate: fn(segmented_button::Entity) -> Message,
28) -> NavBar<'_, Message> {
29 NavBar {
30 segmented_button: segmented_button::vertical(model).on_activate(on_activate),
31 }
32}
33
34pub fn nav_bar_dnd<Message, D: AllowedMimeTypes>(
37 model: &segmented_button::SingleSelectModel,
38 on_activate: fn(segmented_button::Entity) -> Message,
39 on_dnd_enter: impl Fn(segmented_button::Entity, Vec<String>) -> Message + 'static,
40 on_dnd_leave: impl Fn(segmented_button::Entity) -> Message + 'static,
41 on_dnd_drop: impl Fn(segmented_button::Entity, Option<D>, DndAction) -> Message + 'static,
42 id: DragId,
43) -> NavBar<'_, Message>
44where
45 Message: Clone + 'static,
46{
47 NavBar {
48 segmented_button: segmented_button::vertical(model)
49 .on_activate(on_activate)
50 .on_dnd_enter(on_dnd_enter)
51 .on_dnd_leave(on_dnd_leave)
52 .on_dnd_drop(on_dnd_drop)
53 .drag_id(id),
54 }
55}
56
57#[must_use]
58pub struct NavBar<'a, Message: Clone + 'static> {
59 segmented_button:
60 segmented_button::VerticalSegmentedButton<'a, segmented_button::SingleSelect, Message>,
61}
62
63impl<'a, Message: Clone + 'static> NavBar<'a, Message> {
64 #[inline]
65 pub fn close_icon(mut self, close_icon: Icon) -> Self {
66 self.segmented_button = self.segmented_button.close_icon(close_icon);
67 self
68 }
69
70 #[inline]
71 pub fn context_menu(mut self, context_menu: Option<Vec<menu::Tree<Message>>>) -> Self {
72 self.segmented_button = self.segmented_button.context_menu(context_menu);
73 self
74 }
75
76 #[inline]
77 pub fn drag_id(mut self, id: DragId) -> Self {
78 self.segmented_button = self.segmented_button.drag_id(id);
79 self
80 }
81
82 #[must_use]
84 #[inline]
85 pub fn into_container(self) -> Container<'a, Message, crate::Theme, crate::Renderer> {
86 Container::from(self)
87 }
88
89 pub fn on_close<T>(mut self, on_close: T) -> Self
91 where
92 T: Fn(Id) -> Message + 'static,
93 {
94 self.segmented_button = self.segmented_button.on_close(on_close);
95 self
96 }
97
98 pub fn on_context<T>(mut self, on_context: T) -> Self
100 where
101 T: Fn(Id) -> Message + 'static,
102 {
103 self.segmented_button = self.segmented_button.on_context(on_context);
104 self
105 }
106
107 pub fn on_middle_press<T>(mut self, on_middle_press: T) -> Self
109 where
110 T: Fn(Id) -> Message + 'static,
111 {
112 self.segmented_button = self.segmented_button.on_middle_press(on_middle_press);
113 self
114 }
115
116 pub fn on_dnd_drop<D: AllowedMimeTypes>(
118 mut self,
119 handler: impl Fn(Id, Option<D>, DndAction) -> Message + 'static,
120 ) -> Self {
121 self.segmented_button = self.segmented_button.on_dnd_drop(handler);
122 self
123 }
124
125 pub fn on_dnd_enter(mut self, handler: impl Fn(Id, Vec<String>) -> Message + 'static) -> Self {
127 self.segmented_button = self.segmented_button.on_dnd_enter(handler);
128 self
129 }
130
131 pub fn on_dnd_leave(mut self, handler: impl Fn(Id) -> Message + 'static) -> Self {
133 self.segmented_button = self.segmented_button.on_dnd_leave(handler);
134 self
135 }
136
137 #[cfg(wayland_platform)]
138 pub fn with_positioner(
139 mut self,
140 positioner: iced_runtime::platform_specific::wayland::popup::SctkPositioner,
141 ) -> Self {
142 self.segmented_button = self.segmented_button.with_positioner(positioner);
143 self
144 }
145
146 #[must_use]
147 pub fn window_id(mut self, id: window::Id) -> Self {
148 self.segmented_button = self.segmented_button.window_id(id);
149 self
150 }
151
152 #[must_use]
153 pub fn window_id_maybe(mut self, id: Option<window::Id>) -> Self {
154 self.segmented_button = self.segmented_button.window_id_maybe(id);
155
156 self
157 }
158
159 #[must_use]
160 pub fn on_surface_action(
161 mut self,
162 handler: impl Fn(crate::surface::Action) -> Message + Send + Sync + 'static,
163 ) -> Self {
164 self.segmented_button = self.segmented_button.on_surface_action(handler);
165 self
166 }
167}
168
169impl<'a, Message: Clone + 'static> From<NavBar<'a, Message>>
170 for Container<'a, Message, crate::Theme, crate::Renderer>
171{
172 fn from(this: NavBar<'a, Message>) -> Self {
173 let theme = crate::theme::active();
174 let space_s = theme.cosmic().space_s();
175 let space_xxs = theme.cosmic().space_xxs();
176
177 this.segmented_button
178 .button_height(32)
179 .button_padding([space_s, space_xxs, space_s, space_xxs])
180 .button_spacing(space_xxs)
181 .spacing(space_xxs)
182 .style(crate::theme::SegmentedButton::NavBar)
183 .apply(container)
184 .padding(space_xxs)
185 .apply(scrollable)
186 .class(crate::style::iced::Scrollable::Minimal)
187 .height(Length::Fill)
188 .apply(container)
189 .height(Length::Fill)
190 .class(theme::Container::custom(nav_bar_style))
191 }
192}
193
194impl<'a, Message: Clone + 'static> From<NavBar<'a, Message>> for crate::Element<'a, Message> {
195 fn from(this: NavBar<'a, Message>) -> Self {
196 Container::from(this).into()
197 }
198}
199
200#[must_use]
201pub fn nav_bar_style(theme: &Theme) -> iced_widget::container::Style {
202 let cosmic = &theme.cosmic();
203 iced_widget::container::Style {
204 icon_color: Some(cosmic.on_bg_color().into()),
205 text_color: Some(cosmic.on_bg_color().into()),
206 background: Some(Background::Color(
207 cosmic.primary(theme.transparent).base.into(),
208 )),
209 border: Border {
210 width: 0.0,
211 color: Color::TRANSPARENT,
212 radius: cosmic.corner_radii.radius_s.into(),
213 },
214 shadow: Shadow::default(),
215 snap: true,
216 }
217}