1use crate::color::{SEPARATOR_NORMAL, TEXT_BUMP_SMALL};
2use crate::context::Context;
3use crate::device::CURRENT_DEVICE;
4use crate::font::Fonts;
5use crate::framebuffer::Framebuffer;
6use crate::geom::Rectangle;
7use crate::gesture::GestureEvent;
8use crate::input::DeviceEvent;
9use crate::unit::scale_by_dpi;
10use crate::view::filler::Filler;
11use crate::view::icon::Icon;
12use crate::view::input_field::InputField;
13use crate::view::{Bus, Event, Hub, Id, RenderQueue, View, ViewId, ID_FEEDER, THICKNESS_MEDIUM};
14
15pub struct AddressBar {
16 id: Id,
17 pub rect: Rectangle,
18 children: Vec<Box<dyn View>>,
19}
20
21impl AddressBar {
22 pub fn new<S: AsRef<str>>(rect: Rectangle, text: S, context: &mut Context) -> AddressBar {
23 let id = ID_FEEDER.next();
24 let mut children = Vec::new();
25 let dpi = CURRENT_DEVICE.dpi;
26 let thickness = scale_by_dpi(THICKNESS_MEDIUM, dpi) as i32;
27 let side = rect.height() as i32;
28
29 let home_rect = rect![rect.min, rect.min + side];
30 let home_icon = Icon::new(
31 "home",
32 home_rect,
33 Event::SelectDirectory(context.library.home.clone()),
34 )
35 .background(TEXT_BUMP_SMALL[0]);
36
37 children.push(Box::new(home_icon) as Box<dyn View>);
38
39 let separator = Filler::new(
40 rect![
41 pt!(rect.min.x + side, rect.min.y),
42 pt!(rect.min.x + side + thickness, rect.max.y)
43 ],
44 SEPARATOR_NORMAL,
45 );
46
47 children.push(Box::new(separator) as Box<dyn View>);
48
49 let input_field = InputField::new(
50 rect![
51 pt!(rect.min.x + side + thickness, rect.min.y),
52 pt!(rect.max.x - side - thickness, rect.max.y)
53 ],
54 ViewId::AddressBarInput,
55 )
56 .border(false)
57 .text(text.as_ref(), context);
58
59 children.push(Box::new(input_field) as Box<dyn View>);
60
61 let separator = Filler::new(
62 rect![
63 pt!(rect.max.x - side - thickness, rect.min.y),
64 pt!(rect.max.x - side, rect.max.y)
65 ],
66 SEPARATOR_NORMAL,
67 );
68
69 children.push(Box::new(separator) as Box<dyn View>);
70
71 let close_icon = Icon::new(
72 "close",
73 rect![
74 pt!(rect.max.x - side, rect.min.y),
75 pt!(rect.max.x, rect.max.y)
76 ],
77 Event::Close(ViewId::AddressBar),
78 )
79 .background(TEXT_BUMP_SMALL[0]);
80
81 children.push(Box::new(close_icon) as Box<dyn View>);
82
83 AddressBar { id, rect, children }
84 }
85
86 pub fn set_text<S: AsRef<str>>(
87 &mut self,
88 text: S,
89 rq: &mut RenderQueue,
90 context: &mut Context,
91 ) {
92 if let Some(input_field) = self.children[2].downcast_mut::<InputField>() {
93 input_field.set_text(text.as_ref(), true, rq, context);
94 }
95 }
96}
97
98impl View for AddressBar {
99 #[cfg_attr(feature = "otel", tracing::instrument(skip(self, _hub, _bus, _rq, _context), fields(event = ?evt), ret(level=tracing::Level::TRACE)))]
100 fn handle_event(
101 &mut self,
102 evt: &Event,
103 _hub: &Hub,
104 _bus: &mut Bus,
105 _rq: &mut RenderQueue,
106 _context: &mut Context,
107 ) -> bool {
108 match *evt {
109 Event::Gesture(GestureEvent::Tap(center))
110 | Event::Gesture(GestureEvent::HoldFingerShort(center, ..))
111 if self.rect.includes(center) =>
112 {
113 true
114 }
115 Event::Gesture(GestureEvent::Swipe { start, .. }) if self.rect.includes(start) => true,
116 Event::Device(DeviceEvent::Finger { position, .. }) if self.rect.includes(position) => {
117 true
118 }
119 _ => false,
120 }
121 }
122
123 #[cfg_attr(feature = "otel", tracing::instrument(skip(self, _fb, _fonts, _rect), fields(rect = ?_rect)))]
124 fn render(&self, _fb: &mut dyn Framebuffer, _rect: Rectangle, _fonts: &mut Fonts) {}
125
126 fn resize(&mut self, rect: Rectangle, hub: &Hub, rq: &mut RenderQueue, context: &mut Context) {
127 let dpi = CURRENT_DEVICE.dpi;
128 let thickness = scale_by_dpi(THICKNESS_MEDIUM, dpi) as i32;
129 let side = rect.height() as i32;
130 self.children[0].resize(rect![rect.min, rect.min + side], hub, rq, context);
131 self.children[1].resize(
132 rect![
133 pt!(rect.min.x + side, rect.min.y),
134 pt!(rect.min.x + side + thickness, rect.max.y)
135 ],
136 hub,
137 rq,
138 context,
139 );
140 self.children[2].resize(
141 rect![
142 pt!(rect.min.x + side + thickness, rect.min.y),
143 pt!(rect.max.x - side - thickness, rect.max.y)
144 ],
145 hub,
146 rq,
147 context,
148 );
149 self.children[3].resize(
150 rect![
151 pt!(rect.max.x - side - thickness, rect.min.y),
152 pt!(rect.max.x - side, rect.max.y)
153 ],
154 hub,
155 rq,
156 context,
157 );
158 self.children[4].resize(
159 rect![
160 pt!(rect.max.x - side, rect.min.y),
161 pt!(rect.max.x, rect.max.y)
162 ],
163 hub,
164 rq,
165 context,
166 );
167 self.rect = rect;
168 }
169
170 fn rect(&self) -> &Rectangle {
171 &self.rect
172 }
173
174 fn rect_mut(&mut self) -> &mut Rectangle {
175 &mut self.rect
176 }
177
178 fn children(&self) -> &Vec<Box<dyn View>> {
179 &self.children
180 }
181
182 fn children_mut(&mut self) -> &mut Vec<Box<dyn View>> {
183 &mut self.children
184 }
185
186 fn id(&self) -> Id {
187 self.id
188 }
189}