-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfile-browser.cpp
More file actions
155 lines (138 loc) · 5.32 KB
/
file-browser.cpp
File metadata and controls
155 lines (138 loc) · 5.32 KB
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <algorithm>
#include <engine/imgui-objects/file-browser.hpp>
#include <imgui.h>
#include <iostream>
namespace Engine {
void FileBrowser::Initialize() {
// can be used to set directory using top bar like vscode does with a button
// in the area
}
void FileBrowser::UpdateOnWindowResize(FileBrowserState &state, int w, int h) {
state.mainWindowWidth = w;
state.mainWindowHeight = h;
state.mainwindowresize = true;
// 40% width, 60% height
state.filebrowserWidth = 0.4f * static_cast<float>(w);
state.filebrowserHeight = 0.6f * static_cast<float>(h);
}
bool FileBrowser::SetRootDirectory(FileBrowserState &state,
const std::string &path) {
try {
fs::path p(path);
if (path.empty() || !fs::exists(p) || !fs::is_directory(p))
return false;
state.root_directory = fs::canonical(p).string();
state.has_root = true;
state.selected_path.clear();
return true;
} catch (const fs::filesystem_error &e) {
std::cerr << "SetRootDirectory error: " << e.what() << std::endl;
return false;
}
}
void FileBrowser::OpenFile(const std::string &path) {
std::cout << "OpenFile: " << path << std::endl;
// Opening file logic
}
void FileBrowser::RenderDirectoryNode(FileBrowserState &state,
const fs::path &dirPath, int depth) {
// Collect entries (dirs first, then files)
std::vector<fs::directory_entry> entries;
try {
for (const auto &entry : fs::directory_iterator(dirPath)) {
entries.push_back(entry);
}
} catch (const fs::filesystem_error &e) {
ImGui::TextDisabled(" <error: %s>", e.what());
return;
}
std::sort(entries.begin(), entries.end(),
[](const fs::directory_entry &a, const fs::directory_entry &b) {
bool ad = a.is_directory();
bool bd = b.is_directory();
if (ad != bd)
return ad > bd; // dirs first
return a.path().filename().string() <
b.path().filename().string();
});
for (auto &entry : entries) {
const fs::path &p = entry.path();
std::string name = p.filename().string();
bool isDir = entry.is_directory();
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_SpanAvailWidth;
if (!isDir)
flags |=
ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen;
if (state.selected_path == p.string())
flags |= ImGuiTreeNodeFlags_Selected;
bool open = false;
if (isDir) {
open = ImGui::TreeNodeEx((name + "##" + p.string()).c_str(), flags);
} else {
ImGui::TreeNodeEx((name + "##" + p.string()).c_str(), flags);
}
if (ImGui::IsItemClicked()) {
state.selected_path = p.string();
if (!isDir) {
OpenFile(p.string());
}
}
if (open && isDir) {
// Limit depth if desired (optional)
if (depth < 64) {
RenderDirectoryNode(state, p, depth + 1);
} else {
ImGui::TextDisabled(" <max depth reached>");
}
ImGui::TreePop();
}
}
}
void FileBrowser::Render(FileBrowserState &state) {
if (state.mainwindowresize) {
ImGui::SetNextWindowSize(
ImVec2(state.filebrowserWidth, state.filebrowserHeight),
ImGuiCond_Always);
state.mainwindowresize = false;
} else {
ImGui::SetNextWindowSize(
ImVec2(state.filebrowserWidth, state.filebrowserHeight),
ImGuiCond_FirstUseEver);
ImGui::SetNextWindowPos(ImVec2(0, 20), ImGuiCond_FirstUseEver);
}
ImGui::SetNextWindowSizeConstraints(ImVec2(120, 120),
ImVec2(FLT_MAX, FLT_MAX));
if (ImGui::Begin("File Browser", nullptr, ImGuiWindowFlags_NoCollapse)) {
if (!state.has_root) {
ImGui::TextWrapped(
"No root directory set.\nUse File > Open Root... in the top "
"bar to pick one.");
} else {
ImGui::TextWrapped("Root: %s", state.root_directory.c_str());
if (!state.selected_path.empty()) {
ImGui::TextWrapped("Selected: %s", state.selected_path.c_str());
}
ImGui::Separator();
// Draw tree starting at root
fs::path root(state.root_directory);
// root is first node
ImGuiTreeNodeFlags rootFlags = ImGuiTreeNodeFlags_SpanAvailWidth;
if (state.selected_path == state.root_directory)
rootFlags |= ImGuiTreeNodeFlags_Selected;
std::string rootLabel =
(root.filename().string().empty() ? root.string()
: root.filename().string()) +
std::string("##") + state.root_directory;
bool rootOpen = ImGui::TreeNodeEx(rootLabel.c_str(), rootFlags);
if (ImGui::IsItemClicked()) {
state.selected_path = state.root_directory;
}
if (rootOpen) {
RenderDirectoryNode(state, root, 0);
ImGui::TreePop();
}
}
}
ImGui::End();
}
} // namespace Engine