1use super::library_label::LibraryLabel;
2use crate::color::WHITE;
3use crate::context::Context;
4use crate::font::Fonts;
5use crate::framebuffer::{Framebuffer, UpdateMode};
6use crate::geom::{halves, CycleDir, Rectangle};
7use crate::view::filler::Filler;
8use crate::view::icon::Icon;
9use crate::view::page_label::PageLabel;
10use crate::view::{Bus, Event, Hub, Id, RenderData, RenderQueue, View, ID_FEEDER};
11
12pub struct BottomBar {
13 id: Id,
14 rect: Rectangle,
15 children: Vec<Box<dyn View>>,
16 is_prev_disabled: bool,
17 is_next_disabled: bool,
18}
19
20impl BottomBar {
21 pub fn new(
22 rect: Rectangle,
23 current_page: usize,
24 pages_count: usize,
25 name: &str,
26 count: usize,
27 filter: bool,
28 ) -> BottomBar {
29 let id = ID_FEEDER.next();
30 let mut children = Vec::new();
31 let side = rect.height() as i32;
32 let is_prev_disabled = pages_count < 2 || current_page == 0;
33 let is_next_disabled = pages_count < 2 || current_page == pages_count - 1;
34
35 let prev_rect = rect![rect.min, rect.min + side];
36
37 if is_prev_disabled {
38 let prev_filler = Filler::new(prev_rect, WHITE);
39 children.push(Box::new(prev_filler) as Box<dyn View>);
40 } else {
41 let prev_icon = Icon::new("arrow-left", prev_rect, Event::Page(CycleDir::Previous));
42 children.push(Box::new(prev_icon) as Box<dyn View>);
43 }
44
45 let (small_half_width, big_half_width) = halves(rect.width() as i32 - 2 * side);
46 let library_label = LibraryLabel::new(
47 rect![
48 rect.min.x + side,
49 rect.min.y,
50 rect.min.x + side + small_half_width,
51 rect.max.y
52 ],
53 name,
54 count,
55 filter,
56 );
57 children.push(Box::new(library_label) as Box<dyn View>);
58
59 let page_label = PageLabel::new(
60 rect![
61 rect.max.x - side - big_half_width,
62 rect.min.y,
63 rect.max.x - side,
64 rect.max.y
65 ],
66 current_page,
67 pages_count,
68 false,
69 );
70 children.push(Box::new(page_label) as Box<dyn View>);
71
72 let next_rect = rect![rect.max - side, rect.max];
73
74 if is_next_disabled {
75 let next_filler = Filler::new(next_rect, WHITE);
76 children.push(Box::new(next_filler) as Box<dyn View>);
77 } else {
78 let next_icon = Icon::new(
79 "arrow-right",
80 rect![rect.max - side, rect.max],
81 Event::Page(CycleDir::Next),
82 );
83 children.push(Box::new(next_icon) as Box<dyn View>);
84 }
85
86 BottomBar {
87 id,
88 rect,
89 children,
90 is_prev_disabled,
91 is_next_disabled,
92 }
93 }
94
95 pub fn update_library_label(
96 &mut self,
97 name: &str,
98 count: usize,
99 filter: bool,
100 rq: &mut RenderQueue,
101 ) {
102 let library_label = self.children[1]
103 .as_mut()
104 .downcast_mut::<LibraryLabel>()
105 .unwrap();
106 library_label.update(name, count, filter, rq);
107 }
108
109 pub fn update_page_label(
110 &mut self,
111 current_page: usize,
112 pages_count: usize,
113 rq: &mut RenderQueue,
114 ) {
115 let page_label = self.children[2]
116 .as_mut()
117 .downcast_mut::<PageLabel>()
118 .unwrap();
119 page_label.update(current_page, pages_count, rq);
120 }
121
122 pub fn update_icons(&mut self, current_page: usize, pages_count: usize, rq: &mut RenderQueue) {
123 let is_prev_disabled = pages_count < 2 || current_page == 0;
124
125 if self.is_prev_disabled != is_prev_disabled {
126 let index = 0;
127 let prev_rect = *self.child(index).rect();
128 if is_prev_disabled {
129 let prev_filler = Filler::new(prev_rect, WHITE);
130 self.children[index] = Box::new(prev_filler) as Box<dyn View>;
131 } else {
132 let prev_icon = Icon::new("arrow-left", prev_rect, Event::Page(CycleDir::Previous));
133 self.children[index] = Box::new(prev_icon) as Box<dyn View>;
134 }
135 self.is_prev_disabled = is_prev_disabled;
136 rq.add(RenderData::new(self.id, prev_rect, UpdateMode::Gui));
137 }
138
139 let is_next_disabled = pages_count < 2 || current_page == pages_count - 1;
140
141 if self.is_next_disabled != is_next_disabled {
142 let index = self.len() - 1;
143 let next_rect = *self.child(index).rect();
144 if is_next_disabled {
145 let next_filler = Filler::new(next_rect, WHITE);
146 self.children[index] = Box::new(next_filler) as Box<dyn View>;
147 } else {
148 let next_icon = Icon::new("arrow-right", next_rect, Event::Page(CycleDir::Next));
149 self.children[index] = Box::new(next_icon) as Box<dyn View>;
150 }
151 self.is_next_disabled = is_next_disabled;
152 rq.add(RenderData::new(self.id, next_rect, UpdateMode::Gui));
153 }
154 }
155}
156
157impl View for BottomBar {
158 #[cfg_attr(feature = "otel", tracing::instrument(skip(self, _evt, _hub, _bus, _rq, _context), fields(event = ?_evt), ret(level=tracing::Level::TRACE)))]
159 fn handle_event(
160 &mut self,
161 _evt: &Event,
162 _hub: &Hub,
163 _bus: &mut Bus,
164 _rq: &mut RenderQueue,
165 _context: &mut Context,
166 ) -> bool {
167 false
168 }
169
170 #[cfg_attr(feature = "otel", tracing::instrument(skip(self, _fb, _fonts, _rect), fields(rect = ?_rect)))]
171 fn render(&self, _fb: &mut dyn Framebuffer, _rect: Rectangle, _fonts: &mut Fonts) {}
172
173 fn resize(&mut self, rect: Rectangle, hub: &Hub, rq: &mut RenderQueue, context: &mut Context) {
174 let side = rect.height() as i32;
175 let prev_rect = rect![rect.min, rect.min + side];
176 self.children[0].resize(prev_rect, hub, rq, context);
177 let (small_half_width, big_half_width) = halves(rect.width() as i32 - 2 * side);
178 let library_label_rect = rect![
179 rect.min.x + side,
180 rect.min.y,
181 rect.min.x + side + small_half_width,
182 rect.max.y
183 ];
184 self.children[1].resize(library_label_rect, hub, rq, context);
185 let page_label_rect = rect![
186 rect.max.x - side - big_half_width,
187 rect.min.y,
188 rect.max.x - side,
189 rect.max.y
190 ];
191
192 self.children[2].resize(page_label_rect, hub, rq, context);
193 let next_rect = rect![rect.max - side, rect.max];
194 self.children[3].resize(next_rect, hub, rq, context);
195 self.rect = rect;
196 }
197
198 fn rect(&self) -> &Rectangle {
199 &self.rect
200 }
201
202 fn rect_mut(&mut self) -> &mut Rectangle {
203 &mut self.rect
204 }
205
206 fn children(&self) -> &Vec<Box<dyn View>> {
207 &self.children
208 }
209
210 fn children_mut(&mut self) -> &mut Vec<Box<dyn View>> {
211 &mut self.children
212 }
213
214 fn id(&self) -> Id {
215 self.id
216 }
217}