1use apply::Apply;
9use iced::clipboard::dnd::DndAction;
10use iced::clipboard::mime::AllowedMimeTypes;
11use iced::{Background, Length};
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> {
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
138impl<'a, Message: Clone + 'static> From<NavBar<'a, Message>>
139 for Container<'a, Message, crate::Theme, crate::Renderer>
140{
141 fn from(this: NavBar<'a, Message>) -> Self {
142 let theme = crate::theme::active();
143 let space_s = theme.cosmic().space_s();
144 let space_xxs = theme.cosmic().space_xxs();
145
146 this.segmented_button
147 .button_height(32)
148 .button_padding([space_s, space_xxs, space_s, space_xxs])
149 .button_spacing(space_xxs)
150 .spacing(space_xxs)
151 .style(crate::theme::SegmentedButton::NavBar)
152 .apply(container)
153 .padding(space_xxs)
154 .apply(scrollable)
155 .class(crate::style::iced::Scrollable::Minimal)
156 .height(Length::Fill)
157 .apply(container)
158 .height(Length::Fill)
159 .class(theme::Container::custom(nav_bar_style))
160 }
161}
162
163impl<'a, Message: Clone + 'static> From<NavBar<'a, Message>> for crate::Element<'a, Message> {
164 fn from(this: NavBar<'a, Message>) -> Self {
165 Container::from(this).into()
166 }
167}
168
169#[must_use]
170pub fn nav_bar_style(theme: &Theme) -> iced_widget::container::Style {
171 let cosmic = &theme.cosmic();
172 iced_widget::container::Style {
173 icon_color: Some(cosmic.on_bg_color().into()),
174 text_color: Some(cosmic.on_bg_color().into()),
175 background: Some(Background::Color(cosmic.primary.base.into())),
176 border: Border {
177 width: 0.0,
178 color: Color::TRANSPARENT,
179 radius: cosmic.corner_radii.radius_s.into(),
180 },
181 shadow: Shadow::default(),
182 snap: true,
183 }
184}