Onyx-Engine/src/editor/Windows/FileBrowser.cpp

188 lines
6.3 KiB
C++
Raw Normal View History

// File: src/FileBrowser.cpp
2025-05-21 16:49:17 +00:00
#include "FileBrowser.h"
#include <filesystem>
namespace OX
{
FileBrowser::FileBrowser() = default;
2025-05-21 16:49:17 +00:00
FileBrowser::~FileBrowser() = default;
void FileBrowser::SetFilter(const std::string &f) { _filter = f; }
void FileBrowser::SetFileSelectedCallback(FileSelectedCallback cb) { _onFileSelected = std::move(cb); }
void FileBrowser::Draw(const char *title)
{
ImGui::Begin(title);
// --- toolbar now contains back button, inline path, filter & view toggle all on one row ---
DrawToolbar();
2025-05-21 16:49:17 +00:00
// main content
auto root = AssetManager::GetFileTree();
std::function<std::shared_ptr<ResourceTreeNode>(std::shared_ptr<ResourceTreeNode>, const std::string &)> find =
[&](auto node, const std::string &path)-> std::shared_ptr<ResourceTreeNode>
{
if (node->path == path) return node;
for (auto &c: node->children) {
if (c->isDirectory) {
if (auto f = find(c, path)) return f;
}
}
return nullptr;
};
auto node = find(root, _currentPath);
if (!node) {
ImGui::TextColored(ImGui::GetStyle().Colors[ImGuiCol_TextDisabled],
"Path not found: %s", _currentPath.c_str());
} else if (_gridMode) {
DrawGridView(node);
} else {
DrawListView(node);
}
2025-05-21 16:49:17 +00:00
ImGui::End();
}
// ——— Combined toolbar & inline path ———
void FileBrowser::DrawToolbar()
{
// back button
if (_currentPath != "res://") {
if (ImGui::Button("Back")) {
auto pos = _currentPath.find_last_of('/');
_currentPath = (pos != std::string::npos && pos > 6)
? _currentPath.substr(0, pos)
: "res://";
}
}
ImGui::SameLine();
2025-05-21 16:49:17 +00:00
// inline, non-interactive path text
ImGui::Text("%s", _currentPath.c_str());
ImGui::SameLine();
// filter input takes all remaining space
float avail = ImGui::GetContentRegionAvail().x;
ImGui::PushItemWidth(avail * 0.5f);
//ImGui::InputTextWithHint("##filter", "Filter files...", _filter.c_str(), ImGuiInputTextFlags_AutoSelectAll);
ImGui::PopItemWidth();
ImGui::SameLine();
// grid/list toggle
if (_gridMode) {
if (ImGui::Button("List View")) _gridMode = false;
} else {
if (ImGui::Button("Grid View")) _gridMode = true;
}
ImGui::Separator();
}
// ——— Polished grid view ———
void FileBrowser::DrawGridView(const std::shared_ptr<ResourceTreeNode> &node)
{
const float cellW = _cfg.thumbnailSize + _cfg.padding * 2;
ImVec2 avail = ImGui::GetContentRegionAvail();
int cols = std::max(1, int(avail.x / cellW));
ImGui::BeginChild("GridRegion", ImVec2(0, 0), false, ImGuiWindowFlags_AlwaysUseWindowPadding);
ImGui::Columns(cols, nullptr, false);
for (auto &c: node->children) {
if (!_filter.empty() && !PassesFilter(c->name)) continue;
if (!c) return;
ImGui::PushID(c->path.c_str());
ImGui::BeginGroup();
// invisible button as hit target
ImVec2 btnSize(cellW, _cfg.thumbnailSize + _cfg.labelHeight + _cfg.padding);
ImGui::InvisibleButton("cell", btnSize);
bool hovered = ImGui::IsItemHovered();
bool clicked = ImGui::IsItemClicked();
// background rect
ImVec2 mn = ImGui::GetItemRectMin();
ImVec2 mx = ImGui::GetItemRectMax();
ImU32 bg = hovered ? _cfg.highlightColor : _cfg.bgColor;
ImGui::GetWindowDrawList()
->AddRectFilled(mn, mx, bg, 4.0f);
// thumbnail or icon
ImGui::SetCursorScreenPos({mn.x + _cfg.padding, mn.y + _cfg.padding});
if (c->isDirectory) {
ImGui::Image(GetIconTexture(*c),
{_cfg.thumbnailSize, _cfg.thumbnailSize});
} else {
auto asset = AssetManager::Get(c->path);
if (asset && asset->GetTypeName() == "texture2D") {
auto tex = std::static_pointer_cast<Texture2D>(asset);
ImGui::Image((ImTextureID) (intptr_t) tex->GetID(),
{_cfg.thumbnailSize, _cfg.thumbnailSize},
{0, 1}, {1, 0});
} else {
ImGui::Dummy({_cfg.thumbnailSize, _cfg.thumbnailSize});
2025-05-21 16:49:17 +00:00
}
}
// label
ImGui::SetCursorScreenPos({mn.x + _cfg.padding, mx.y - _cfg.labelHeight});
ImGui::PushTextWrapPos(mx.x);
ImGui::TextUnformatted(c->name.c_str());
ImGui::PopTextWrapPos();
// click handling
if (clicked) {
if (c->isDirectory) {
_currentPath = c->path;
} else if (_onFileSelected) {
_onFileSelected(c->path);
}
}
ImGui::EndGroup();
2025-05-21 16:49:17 +00:00
ImGui::NextColumn();
ImGui::PopID();
2025-05-21 16:49:17 +00:00
}
ImGui::Columns(1);
ImGui::EndChild();
}
// ——— Simple list view ———
void FileBrowser::DrawListView(const std::shared_ptr<ResourceTreeNode> &node)
{
ImGui::BeginChild("ListRegion", ImVec2(0, 0), false);
for (auto &c: node->children) {
if (!_filter.empty() && !PassesFilter(c->name)) continue;
if (ImGui::Selectable(c->name.c_str(), false, ImGuiSelectableFlags_AllowDoubleClick)) {
if (ImGui::IsMouseDoubleClicked(0)) {
if (c->isDirectory) {
_currentPath = c->path;
} else if (_onFileSelected) {
_onFileSelected(c->path);
}
}
}
}
ImGui::EndChild();
}
2025-05-21 16:49:17 +00:00
bool FileBrowser::PassesFilter(const std::string &name) const
{
return _filter.empty() ||
(name.find(_filter) != std::string::npos);
}
2025-05-21 16:49:17 +00:00
ImTextureID FileBrowser::GetIconTexture(const ResourceTreeNode &node)
{
return 0;
2025-05-21 16:49:17 +00:00
}
} // namespace OX