1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
extern crate imgui;
#[macro_use]
extern crate cfg_if;
use std::cmp::Ordering;
use std::path::*;
use std::{fs, io};
use imgui::*;
pub trait UiFileExplorer {
fn file_explorer<T, S>(&self, target: T, extensions: &[S]) -> io::Result<Option<PathBuf>>
where
T: AsRef<Path>,
S: AsRef<str>;
}
fn has_extension<P: AsRef<Path>, S: AsRef<str>>(path: P, extensions: &[S]) -> bool {
let path = path.as_ref();
if let Some(test_ext) = path.extension() {
if let Some(test_ext) = test_ext.to_str() {
extensions
.iter()
.any(|ext| test_ext.to_lowercase() == ext.as_ref().to_lowercase())
} else {
false
}
} else {
false
}
}
cfg_if! {
if #[cfg(unix)] {
pub const TOP_FOLDER: &str = "/";
} else {
pub const TOP_FOLDER: &str = "C:";
}
}
impl<'ui> UiFileExplorer for Ui<'ui> {
fn file_explorer<T, S>(&self, target: T, extensions: &[S]) -> io::Result<Option<PathBuf>>
where
T: AsRef<Path>,
S: AsRef<str>,
{
let ret = view_dirs(&self, target, extensions);
fn view_dirs<'a, T: AsRef<Path>, S: AsRef<str>>(
ui: &Ui<'a>,
target: T,
extensions: &[S],
) -> io::Result<Option<PathBuf>> {
let target = target.as_ref();
let mut files = Vec::new();
for direntry in fs::read_dir(target)? {
match direntry {
Ok(direntry) => {
let path = direntry.path();
if path.is_dir() || has_extension(&path, extensions) {
files.push(path);
}
}
Err(e) => eprintln!("Error on listing files: {:?}", e),
}
}
files.sort_by(|path1, path2| match (path1.is_dir(), path2.is_dir()) {
(true, true) => path1.cmp(path2),
(false, false) => path1.cmp(path2),
(true, false) => Ordering::Less,
(false, true) => Ordering::Greater,
});
let mut ret = Ok(None);
for i in files {
if i.is_dir() {
if let Some(dirname) = i.file_name() {
if let Some(dirname) = dirname.to_str() {
let im_dirname = ImString::new(dirname);
ui.tree_node(&im_dirname).build(|| {
ret = view_dirs(ui, &i, extensions);
});
} else {
eprintln!("Could not get str out of directory: {:?}", i);
}
} else {
eprintln!("Could not get dirname for path: {:?}", i);
}
} else {
if let Some(file_name) = i.file_name() {
if let Some(file_name) = file_name.to_str() {
ui.bullet_text(im_str!(""));
ui.same_line(0.0);
if ui.small_button(&ImString::new(file_name)) {
ret = Ok(Some(i.clone()));
}
} else {
eprintln!("Could not get str out of file: {:?}", i);
}
} else {
eprintln!("Could not get file_name for path: {:?}", i);
}
}
}
ret
}
ret
}
}