cadmus_core/view/navigation/providers/
directory.rs1use crate::context::Context;
2use crate::device::CURRENT_DEVICE;
3use crate::font::Fonts;
4use crate::geom::Point;
5use crate::unit::scale_by_dpi;
6use crate::view::home::directories_bar::DirectoriesBar;
7use crate::view::navigation::stack_navigation_bar::NavigationProvider;
8use crate::view::{View, SMALL_BAR_HEIGHT, THICKNESS_MEDIUM};
9use std::collections::BTreeSet;
10use std::path::{Path, PathBuf};
11
12#[derive(Debug, Clone, Copy, Default)]
13pub struct DirectoryNavigationProvider;
14
15impl DirectoryNavigationProvider {
16 #[inline]
17 fn guess_bar_size(dirs: &BTreeSet<PathBuf>) -> usize {
18 (dirs.iter().map(|dir| dir.as_os_str().len()).sum::<usize>() / 300).clamp(1, 4)
19 }
20}
21
22impl NavigationProvider for DirectoryNavigationProvider {
23 type LevelKey = PathBuf;
24 type LevelData = BTreeSet<PathBuf>;
25 type Bar = DirectoriesBar;
26
27 fn selected_leaf_key(&self, selected: &Self::LevelKey) -> Self::LevelKey {
28 selected.clone()
29 }
30
31 fn leaf_for_bar_traversal(
46 &self,
47 selected: &Self::LevelKey,
48 context: &Context,
49 ) -> Self::LevelKey {
50 let (_, dirs) = context.library.list(selected, None, true);
51 if dirs.is_empty() && *selected != context.library.home {
52 selected
53 .parent()
54 .map(|p| p.to_path_buf())
55 .unwrap_or_else(|| selected.clone())
56 } else {
57 selected.clone()
58 }
59 }
60
61 fn parent(&self, current: &Self::LevelKey) -> Option<Self::LevelKey> {
62 current.parent().map(|p| p.to_path_buf())
63 }
64
65 fn is_ancestor(&self, ancestor: &Self::LevelKey, descendant: &Self::LevelKey) -> bool {
66 descendant.starts_with(ancestor)
67 }
68
69 fn is_root(&self, key: &Self::LevelKey, context: &Context) -> bool {
70 *key == context.library.home
71 }
72
73 fn fetch_level_data(&self, key: &Self::LevelKey, context: &mut Context) -> Self::LevelData {
74 let (_, dirs) = context.library.list(key, None, true);
75 dirs
76 }
77
78 fn estimate_line_count(&self, _key: &Self::LevelKey, data: &Self::LevelData) -> usize {
79 Self::guess_bar_size(data)
80 }
81
82 fn create_bar(&self, rect: crate::geom::Rectangle, key: &Self::LevelKey) -> Self::Bar {
83 DirectoriesBar::new(rect, key)
84 }
85
86 fn bar_key(&self, bar: &Self::Bar) -> Self::LevelKey {
87 bar.path.clone()
88 }
89
90 fn update_bar(
91 &self,
92 bar: &mut Self::Bar,
93 data: &Self::LevelData,
94 selected: &Self::LevelKey,
95 fonts: &mut Fonts,
96 ) {
97 bar.update_content(data, Path::new(selected), fonts);
98 }
99
100 fn update_bar_selection(&self, bar: &mut Self::Bar, selected: &Self::LevelKey) {
101 bar.update_selected(Path::new(selected));
102 }
103
104 fn resize_bar_by(&self, bar: &mut Self::Bar, delta_y: i32, fonts: &mut Fonts) -> i32 {
105 let rectangle = *bar.rect();
106 let dpi = CURRENT_DEVICE.dpi;
107 let thickness = scale_by_dpi(THICKNESS_MEDIUM, dpi) as i32;
108 let min_height = scale_by_dpi(SMALL_BAR_HEIGHT, dpi) as i32 - thickness;
109
110 let y_max = (rectangle.max.y + delta_y).max(rectangle.min.y + min_height);
111 let resized = y_max - rectangle.max.y;
112
113 bar.rect_mut().max.y = y_max;
114
115 let dirs = bar.dirs();
116 let path = bar.path.clone();
117 bar.update_content(&dirs, path.as_path(), fonts);
118
119 resized
120 }
121
122 fn shift_bar(&self, bar: &mut Self::Bar, delta: Point) {
123 bar.shift(delta);
124 }
125}