/****************************************************************************** * File - fileBrowser.cpp * Author - Joey Pollack * Date - 2021/11/04 (y/m/d) * Mod Date - 2021/11/04 (y/m/d) * Description - File browser dialog window. Can be used for opening * and saving files. ******************************************************************************/ #include "file_browser.h" #include #include #include #include #include #include #include #include "dearimgui/imgui.h" namespace lunarium { FileBrowser::FileBrowser() : mIsOpen(false), mSelectionMode(SelectionMode::FILES_ONLY), mWarnOnExisting(false), mpFolderIcon(nullptr), mResult(Result::CANCEL), mpNewFolderIcon(nullptr), mpUpFolderIcon(nullptr) { mPrompt = "Select an item"; memset(mDirNameBuffer, 0, mBufferSize); memset(mInputBuffer, 0, mBufferSize); mpFolderIcon = DataManager::mFolderIcon; mpNewFolderIcon = DataManager::mNewFolderIcon; mpUpFolderIcon = DataManager::mUpArrowIcon; } /// If the given path does not exist this will default to the /// current working directory bool FileBrowser::OpenInDirectory(std::filesystem::path path) { if (mIsOpen) return false; if (!std::filesystem::exists(path)) path = std::filesystem::current_path(); if (!std::filesystem::is_directory(path)) return false; mCurrentDirectory = path; mResult = Result::STILL_WAITING; // Get list of items in the current directory ReloadItems(); mIsOpen = true; return true; } bool FileBrowser::DoFrame() { if (!mIsOpen) return false; ImGui::SetNextWindowSize(ImVec2(600, 400), ImGuiCond_Appearing); if (!ImGui::Begin("File Browser", &mIsOpen, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoDocking)) { ImGui::End(); return false; } ImGui::TextUnformatted(mPrompt.c_str()); ImGui::Separator(); ImVec2 iconSize(mpNewFolderIcon->GetWidth(), mpNewFolderIcon->GetHeight()); if (ImGui::ImageButton((ImTextureID) mpNewFolderIcon->GetGLTextureID64(), iconSize)) { ImGui::OpenPopup("New Folder Name"); memset(mDirNameBuffer, 0, mBufferSize); } if (ImGui::BeginPopup("New Folder Name")) { if (ImGui::InputText("Folder Name", mDirNameBuffer, mBufferSize, ImGuiInputTextFlags_EnterReturnsTrue)) { std::filesystem::create_directory(mDirNameBuffer); ImGui::CloseCurrentPopup(); ReloadItems(); } ImGui::EndPopup(); } ImGui::SameLine(); iconSize = ImVec2(mpUpFolderIcon->GetWidth(), mpUpFolderIcon->GetHeight()); if (ImGui::ImageButton((ImTextureID) mpUpFolderIcon->GetGLTextureID64(), iconSize)) { mCurrentDirectory = mCurrentDirectory.parent_path(); ReloadItems(); } ImGui::SameLine(); ImGui::TextUnformatted(mCurrentDirectory.string().c_str()); DoListBox(); ImGui::Separator(); if (ImGui::InputText("selection", mInputBuffer, mBufferSize)) { mInputSelection = mCurrentDirectory / mInputBuffer; mpSelectedItem = &mInputSelection; } ImGui::Separator(); bool res = DoButtons(); ImGui::End(); return res; } void FileBrowser::AddExtensionFilter(std::string ext) { mExtensionsFilter.push_back(ext); } void FileBrowser::SetSelectionMode(SelectionMode mode) { mSelectionMode = mode; } void FileBrowser::WarnOnExistingFileSelection(bool warn) { mWarnOnExisting = warn; } void FileBrowser::SetPrompt(std::string prompt) { mPrompt = prompt; } /// returns nullptr if the dialog has not been opened yet const std::filesystem::path* FileBrowser::GetSelectedItem() const { return mpSelectedItem; } FileBrowser::Result FileBrowser::GetResult() const { return mResult; } bool FileBrowser::IsOpen() const { return mIsOpen; } void FileBrowser::Close() { mIsOpen = false; } void FileBrowser::ReloadItems() { mpSelectedItem = nullptr; mItemsInDir.clear(); for(auto const& dir_entry: std::filesystem::directory_iterator{mCurrentDirectory}) { mItemsInDir.push_back(dir_entry.path()); } // Sort by type and then by name std::sort(mItemsInDir.begin(), mItemsInDir.end(), [](std::filesystem::path& lhs, std::filesystem::path& rhs) { if (std::filesystem::is_directory(lhs) && std::filesystem::is_directory(rhs)) { return strcmp(lhs.filename().string().c_str(), rhs.filename().string().c_str()) < 0; } if (std::filesystem::is_directory(lhs) && !std::filesystem::is_directory(rhs)) { return true; } return false; }); } //////////////////////////////////////////////////////////// // RENDER HELPER METHODS //////////////////////////////////////////////////////////// void FileBrowser::DoListBox() { if (ImGui::BeginListBox("", ImVec2(ImGui::GetWindowWidth(), ImGui::GetWindowHeight() * .575f))) { for (int i = 0; i < mItemsInDir.size(); i++) { if (std::filesystem::is_directory(mItemsInDir[i])) { ImVec2 size(mpFolderIcon->GetWidth(), mpFolderIcon->GetHeight()); ImTextureID id = (ImTextureID) mpFolderIcon->GetGLTextureID64(); ImGui::Image(id, size); ImGui::SameLine(); } if (ImGui::Selectable(mItemsInDir[i].filename().string().c_str())) { if (std::filesystem::is_directory(mItemsInDir[i])) { mCurrentDirectory /= mItemsInDir[i]; ReloadItems(); if (mSelectionMode == SelectionMode::DIRECTORIES_ONLY || mSelectionMode == SelectionMode::ANY) { mpSelectedItem = &mCurrentDirectory; } } else { if (mSelectionMode == SelectionMode::FILES_ONLY || mSelectionMode == SelectionMode::ANY) { mpSelectedItem = &mItemsInDir[i]; } } } } ImGui::EndListBox(); } } bool FileBrowser::DoButtons() { ImGui::SetCursorPosX(ImGui::GetWindowSize().x - 100.0f); if (ImGui::Button("OK")) { if (std::filesystem::exists(*mpSelectedItem) && mWarnOnExisting) { ImGui::OpenPopup("Warn"); } else { mResult = Result::OK; mIsOpen = false; return false; } } if (ImGui::BeginPopup("Warn")) { ImGui::Text("This file already exists. Are you sure you want to overwrite it?"); if (ImGui::Button("Yes")) { mResult = Result::OK; mIsOpen = false; ImGui::EndPopup(); return false; } ImGui::SameLine(); if (ImGui::Button("No")) { ImGui::CloseCurrentPopup(); } ImGui::EndPopup(); } ImGui::SameLine(); if (ImGui::Button("Cancel")) { mResult = Result::CANCEL; mIsOpen = false; return false; } return true; } }