//DEBUG MACRO #ifdef DEBUG #define log_debugc(str, ...) do { if (debug) fprintf(stdout, "[DEBUG] (%s:%d): " (str) "\n", __FILE__, __LINE__, ##__VA_ARGS__); } while (0) #define log_debugcpp(str) do { \ if (debug) std::cout << "[DEBUG]" << "(" << __FILE__ << ":" << __LINE__ << "): " << str << std::endl; \ } while (0) #define log_wdebugcpp(str) do { \ if (debug) std::wcout << "[DEBUG]" << "(" << __FILE__ << ":" << __LINE__ << "): " << str << std::endl; \ } while (0) #define log_directory(str) if(debugVerbosity & DEBUG_DIRECTORY) log_debugcpp((str)) #define log_volume(str) if(debugVerbosity & DEBUG_VOLUME) log_debugcpp((str)) #define log_extension(str) if(debugVerbosity & DEBUG_EXTENSION) log_debugcpp((str)) #else #define log_debugc(str, ...) #define log_debugcpp(str) #define log_wdebugcpp(str) #define log_directory(str) #define log_volume(str) #define log_extension(str) #endif //PATH MACRO #define MAX_LISTDIR_PATH_LENGTH (MAX_PATH - 3) #define MAX_ERRORSTR_LEN 512 //HISTORY HANDLING MACRO #define MIN_HISTORY_POS (history->historyTraversalPos <= 0) #define MAX_HISTORY_POS (history->historyTraversalPos >= history->historyDepth) #include #include #include #include #include #pragma once namespace fp { typedef struct { long long size; //TODO yel spacsio NELLA MEMoria WCHAR name[MAX_LISTDIR_PATH_LENGTH]; char nameUTF8[MAX_LISTDIR_PATH_LENGTH * 4]; SYSTEMTIME createTime; SYSTEMTIME lastAccessTime; SYSTEMTIME lastWriteTime; bool isFile; bool isHidden; } directoriesInfo; struct History { std::vector previousPaths; std::vector previousPathsUTF8; //warnings e 1 cosa //int historyDepth = -1; //TODO Limitar historial //const int maxHistoryDepth = 10000; //int currentStart = 0; int historyDepth; int historyTraversalPos; bool isAdditionTime; // wchar* operator[](int idx){ // if (idx > previousPaths.size()) // int newPos = idx + currentStart; // if (newPos < 0) return previousPaths[maxHistoryDepth - (newPos % maxHistoryDepth)]; // else return previousPaths[newPos % maxHistoryDepth]; // } // void push_back(wchar* path){ // if (previousPaths.size() < maxHistoryDepth) previousPaths.push_back(path); // else { // previousPaths[currentStart++] = path; // } // } History(){ historyTraversalPos = historyDepth = -1; isAdditionTime = true; } }; enum HistoryMovement { HISTORY_FORWARD = 1, HISTORY_BACKWARD = 0 }; enum ListDirectoryError { DIRECTORY_ERROR_PATH_TOO_LONG = -1, DIRECTORY_ERROR_ACCESSING_CONTENT = -2 }; enum AgnosticDirError { AGDIR_ERROR_ACCESS_DENIED = 1 }; namespace ErrorMessages { char addrBarError[] = "Failed to open folder: invalid path"; char tableElementError[] = "Failed to open folder: access restricted to non-admin users"; char accessDeniedError[] = "Failed to open folder: access denied"; char listDirectoryError[] = "Failed to open folder: unknown error"; char moveUpError[] = "Failed to move up: reached volume root?"; }; namespace Label { wchar_t saveFileLabel[] = L"Save file: "; wchar_t loadFileLabel[] = L"Select a file: "; wchar_t selectDirectoryLabel[] = L"Select a directory: "; }; enum ListFlags { LIST_DIRECTORY = (1<<0), LIST_VOLUME = (1<<1) }; enum WindowFlags { FP_FULLSCREEN = (1<<0), FP_MODAL = (1<<1), FP_FILE_LOAD = (1<<2), FP_FILE_SAVE = (1<<3), FP_DIRECTORY_SELECT = (1<<4) }; enum ExitFlags { EXIT_CONTINUE = (1<<0), EXIT_SELECTED = (1<<1), EXIT_CLOSED = (1<<2), EXIT_ERROR = (1<<3) }; //VARS #ifdef DEBUG bool debug = true; #else bool debug = false; #endif // Window open bool bool windowOpen = true; bool windowConfigured = false; //Flags used to determine: // window format //int windowFlags = 0; // if it's time to load new data int listFlags = LIST_DIRECTORY | LIST_VOLUME; //Array used to display current error char error[MAX_ERRORSTR_LEN]; //wchar_t errorUTF8[MAX_ERRORSTR_LEN * 4]; bool showError = false; //Stores found volumes //TODO onPresentPaths might not be the best name std::vector onPresentPaths; std::vector onPresentPathsUTF8; int numVolumes; //currentPath is the one used to retrieve data, then copied to addrBarVal for display. //addrBarVal is also used as a bacukp in case new currentPath is invalid //chosenFile stores absolute file path to return //TODO: hay historial. Coalescer en una sola? //cursed C momento: necesario ptr en otra var para mandar a wchar_t** de firma wchar_t currentPath[MAX_PATH]; //wchar_t* currentPathPtr = ¤tPath[0]; wchar_t addrBarVal[MAX_LISTDIR_PATH_LENGTH]; char addrBarValUTF8[MAX_LISTDIR_PATH_LENGTH * 4]; //wchar_t* addrBarValPtr = &addrBarVal[0]; wchar_t chosenPath[MAX_PATH]; char chosenPathUTF8[MAX_PATH * 4]; //Stores entires found within a given directory //static int currentItemIdx = -1; std::vector directoryContents; int numFiles = 0; //Going one level up needs to be hardcoded like this due to function inputMove needing a wchar_t** //c pervirtio con unicode std::wstring s(L"←→↑↓"); wchar_t moveUp[] = L".."; bool isListVolumesAdequate = true; bool isListDirectoriesAdequate = true; //RenderTime vars for filtering bool showHidden = false; bool filterByExtension = false; std::vector extensions; History* history; // int debugVerbosity = 0; // enum enumDebugVerbosity { // DEBUG_DIRECTORY = (1<<0), // DEBUG_VOLUME = (1<<1), // DEBUG_EXTENSION = (1<<2) // }; // debugVerbosity = DEBUG_DIRECTORY | DEBUG_EXTENSION; // debugVerbosity &= ~DEBUG_DIRECTORY; // if (debugVerbosity & (DEBUG_DIRECTORY | DEBUG_EXTENSION)); //TODO UNICORDEO /* FILE PICKER MOMENTO */ /* DIRECTORIES */ bool retrieveCurrentDirectory(wchar_t* currentPath){ if(GetCurrentDirectory(MAX_PATH, currentPath)) return true; return false; } bool moveDirectory(wchar_t* currentPath){ log_debugcpp(currentPath); if(SetCurrentDirectory(currentPath)) return true; return false; } int listDirectory(std::wstring path, std::vector *directoryContents){ HANDLE hFind = INVALID_HANDLE_VALUE; WIN32_FIND_DATA ffd; LARGE_INTEGER filesize; int numFiles = 0; if (path.length() > (MAX_LISTDIR_PATH_LENGTH)) return DIRECTORY_ERROR_PATH_TOO_LONG; path = path + L"\\*"; hFind = FindFirstFile(path.c_str(), &ffd); if (INVALID_HANDLE_VALUE == hFind) return DIRECTORY_ERROR_ACCESSING_CONTENT; do { if(!wcscmp(ffd.cFileName, L".") || !wcscmp(ffd.cFileName, L"..")) continue; log_debugcpp("BUCLE listDirectory iteracion " + std::to_string(numFiles)); directoriesInfo* itemInfo; if (directoryContents->size() <= numFiles){ itemInfo = new directoriesInfo(); directoryContents->push_back(itemInfo); } else { itemInfo = directoryContents->at(numFiles); } log_debugcpp("MEMORY ASSIGNES iteration " + std::to_string(numFiles)); //A registrar info, fiera itemInfo->isFile = (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? true : false; itemInfo->isHidden = (ffd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? true : false; //Tamaño filesize.QuadPart = ((ffd.nFileSizeHigh * (MAXDWORD+1)) + ffd.nFileSizeLow); itemInfo->size = filesize.QuadPart; //Fechitssss FileTimeToSystemTime(&ffd.ftCreationTime, &itemInfo->createTime); FileTimeToSystemTime(&ffd.ftLastAccessTime, &itemInfo->lastAccessTime); FileTimeToSystemTime(&ffd.ftLastWriteTime, &itemInfo->lastWriteTime); //Nombre de la cosita uint64_t idx = 0; do { itemInfo->name[idx] = ffd.cFileName[idx]; itemInfo->nameUTF8[idx] = ffd.cFileName[idx]; idx++; } while (ffd.cFileName[idx]); itemInfo->name[idx] = '\0'; itemInfo->nameUTF8[idx] = '\0'; log_debugcpp("INFORMACION ALMACENADA iteracion " + std::to_string(numFiles)); numFiles++; } while (FindNextFile(hFind, &ffd) != 0); FindClose(hFind); return numFiles; } long getLastSystemError(){ DWORD winLastError = GetLastError(); switch(winLastError){ case ERROR_ACCESS_DENIED: return AGDIR_ERROR_ACCESS_DENIED; break; default: return winLastError; break; } } /* VOLUMES */ //new wchar_t*[Wchar_TCount * sizeof(WWCHAR_T) /*idea, si quisiera que empezase en punto X del string coger el param opcional y crear un puntero a la posicion X del array para empezar desde ahi int explodePaths(TWCHAR_T* volumePaths, int volumePathLength, int volumePathBufferSize, wchar_t separator, std::vector *dest, , int startingFrom = 0); if (nextOcurrence == NULL) return 0; */ int explodePaths(wchar_t* volumePaths, int volumePathsBufferSize, wchar_t separator, std::vector *dest, std::vector *destUTF8, int depth = 1){ //Por alguna razón, esto que dice acabar con 2 NULL acaba con 3; de locos. //https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumepathnamesforvolumenamew wchar_t* nextOcurrence = wcschr(volumePaths, separator); wchar_t* itemPath; char* itemPathUTF8; itemPath = (wchar_t*)calloc(2, volumePathsBufferSize); itemPathUTF8 = (char*)calloc(4, volumePathsBufferSize); int pathLengthIdx = 0; for (; volumePaths[pathLengthIdx] != nextOcurrence[0]; pathLengthIdx++) { log_debugcpp(volumePaths[0] << " ENTERS " << std::to_string(pathLengthIdx)); itemPath[pathLengthIdx] = volumePaths[pathLengthIdx]; } itemPath[pathLengthIdx + 1] = '\0'; dest->push_back(itemPath); WideCharToMultiByte(CP_UTF8, NULL, itemPath, -1, itemPathUTF8, 4 * volumePathsBufferSize, NULL, NULL); destUTF8->push_back(itemPathUTF8); log_wdebugcpp(dest->at(dest->size() - 1) << L" EXPLODEPATH"); log_debugcpp(dest->at(destUTF8->size() - 1) << " EXPLODEPATH"); if (nextOcurrence[0] == nextOcurrence[1]) return depth; depth++; return explodePaths(nextOcurrence + sizeof(wchar_t), (volumePathsBufferSize - pathLengthIdx), separator, dest, destUTF8, depth); } int listVolumes(std::vector *onPresentPaths, std::vector *onPresentPathsUTF8){ HANDLE hFind = INVALID_HANDLE_VALUE; const wchar_t separator = '\0'; int numVolumes = 0; //Volume name wchar_t volumeName[MAX_PATH]; int volumeNameSize = sizeof volumeName / sizeof volumeName[0]; //Paths int volumePathsBufferSize = (MAX_PATH + 1) * sizeof(wchar_t); unsigned long volumePathLength; wchar_t volumePaths[volumePathsBufferSize]; std::fill(volumePaths, volumePaths + volumePathsBufferSize, '\0'); hFind = FindFirstVolume(volumeName, volumeNameSize); if (INVALID_HANDLE_VALUE == hFind) return -2; do { if(GetVolumePathNamesForVolumeName(volumeName, volumePaths, volumePathsBufferSize, &volumePathLength)){ if (volumePathLength == 1) { log_debugcpp("Skill Issue"); continue; } log_debugcpp(volumeName); //DEBUG: pathSchecker // if (debug && volumePaths[0] == 'E') { // std::cout << volumePathLength << std::endl; // /*exit(1);*/ // for (int i = 0; i < volumePathsBufferSize; i++){ // std::cout << std::to_string(i) + ": "; // std::cout << volumePaths[i]; // std::cout << " | "; // } // std::cout << std::endl << "I IA" << std::endl; // exit(1); // } if (debug) { if(numVolumes += explodePaths(volumePaths, volumePathsBufferSize, separator, onPresentPaths, onPresentPathsUTF8)){ for (int i = 0; i < onPresentPaths->size(); i++){ log_debugcpp(onPresentPaths->at(i)); } } } //std::cout << volumePaths << std::endl; log_debugcpp(std::to_string(volumePathLength) + "<- VOLUME PATH LENGTH"); log_debugcpp("THE END"); } else { log_debugcpp("no volumes found"); } //TODO benchimarqui std::fill(volumePaths, volumePaths + volumePathsBufferSize, '\0'); } while (FindNextVolume(hFind, volumeName, volumeNameSize) != 0); log_debugcpp(std::to_string(onPresentPaths->size()) + " JUST BEFORE MAIN"); FindVolumeClose(hFind); return numVolumes; } /* DISPLAY */ bool compareLastWchar(std::vector *lastCharCandidates, wchar_t* string){ bool matchingExtension = false; for (int i = 0; i < lastCharCandidates->size(); i++){ log_wdebugcpp(lastCharCandidates->at(i) + L" <- FILTERING EXTENSION"); if(wcslen(string) < lastCharCandidates->at(i).length()) continue; wchar_t* potentialExtension = &string[wcslen(string) - lastCharCandidates->at(i).length()]; log_wdebugcpp(potentialExtension << L" LEN " + std::to_wstring(wcslen(potentialExtension)) + L" <- VS -> " + lastCharCandidates->at(i) + L" LEN " + std::to_wstring(lastCharCandidates->at(i).length())); //+ strlen(potentialExtension) + std::to_string(lastCharCandidates->at(i).length()) if(!wcscmp(potentialExtension, lastCharCandidates->at(i).c_str())) { log_debugcpp("VALID EXTENSION"); matchingExtension = true; } } return matchingExtension; } //TODO huh // int handleFolderAccessResult(int listFlags, wchar_t* nextPath, bool* error, wchar_t* errorDest, \ // const wchar_t* errorContent, History* history, wchar_t* currentPath = NULL, wchar_t* addrBarVal = NULL){ // *error = false; // if(!moveDirectory(nextPath)) { // *error = true; // if(currentPath && addrBarVal) { // wcscpy(errorDest, errorContent); // wcscpy(addrBarVal, currentPath); // } // return listFlags; // } // if(currentPath && addrBarVal) { // wcscpy(currentPath, addrBarVal); // history->isAdditionTime = true; // } // return (listFlags |= LIST_DIRECTORY); // } //TODO huh, vale, no pasa por listdirectory por la flag, pero esto se podria hacer mejor manteniendo el no tirar de disco tb? int handleFolderAccessResult(int listFlags, wchar_t* nextPath, bool* error, char* errorDest, \ const char* errorContent, History* history, wchar_t* currentPath , wchar_t* addrBarVal){ *error = false; if(!moveDirectory(nextPath)) { *error = true; strcpy(errorDest, errorContent); wcscpy(addrBarVal, currentPath); return listFlags; } //wcscpy(currentPath, addrBarVal); history->isAdditionTime = true; return (listFlags |= LIST_DIRECTORY); } int handleFolderAccessResult(int listFlags, wchar_t* nextPath, bool* error, char* errorDest, \ const char* errorContent, History* history, bool isAdditionTime){ *error = false; if(!moveDirectory(nextPath)) { *error = true; strcpy(errorDest, errorContent); return listFlags; } if (isAdditionTime) history->isAdditionTime = true; return (listFlags |= LIST_DIRECTORY); } /* HISTORIAL */ void addPathToHistory(History *history, wchar_t* pathToAdd){ wchar_t* path; char* pathUTF8; if (history->historyTraversalPos + 1 >= history->previousPaths.size()){ path = (wchar_t*)calloc(2, MAX_PATH); history->previousPaths.push_back(path); pathUTF8 = (char*)calloc(4, MAX_PATH); WideCharToMultiByte(CP_UTF8, NULL, path, -1, pathUTF8, 4 * MAX_PATH, NULL, NULL); history->previousPathsUTF8.push_back(pathUTF8); } else { path = history->previousPaths.at(history->historyTraversalPos + 1); pathUTF8 = history->previousPathsUTF8.at(history->historyTraversalPos + 1); } wcsncpy(path, pathToAdd, MAX_PATH); history->historyTraversalPos++; history->historyDepth = history->historyTraversalPos; history->isAdditionTime = false; } wchar_t* moveThroughHistory(History *history, HistoryMovement movement) { int sign = (movement == HISTORY_BACKWARD ? -1 : 1); switch(movement){ case HISTORY_BACKWARD: if(MIN_HISTORY_POS) return history->previousPaths.at(history->historyTraversalPos); break; case HISTORY_FORWARD: if(MAX_HISTORY_POS) return history->previousPaths.at(history->historyDepth); break; default: return history->previousPaths.at(history->historyDepth); } history->historyTraversalPos += sign; return history->previousPaths.at(history->historyTraversalPos); } /* RENDERING */ int windowRendering(wchar_t*, bool*, int); int renderFilePicker(wchar_t* userPath, bool* windowOpen, int windowFlags = 0) { //TODO filesystem watcher //TODO let user handle memory management //TODO use local val to create actual windowFlags when expanding functionality if (!windowConfigured) { listFlags = LIST_DIRECTORY | LIST_VOLUME; history = new History(); if (windowFlags & FP_FULLSCREEN){ ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f)); ImGui::SetNextWindowSize(ImGui::GetIO().DisplaySize); windowFlags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize; } else { ImGui::SetNextWindowPos(ImVec2(50.0f, 50.0f)); ImGui::SetNextWindowSize(ImVec2(500.0f, 500.0f)); windowFlags = ImGuiWindowFlags_None; //const ImGuiViewport* viewport = ImGui::GetMainViewport(); } windowConfigured = true; } else windowFlags = 0; return windowRendering(userPath, windowOpen, windowFlags); } int exitWindow(wchar_t* userPath, bool* windowOpen, int exitFlag){ if(exitFlag & EXIT_SELECTED) { if (chosenPath[0] == '\0') return EXIT_CONTINUE; wcscpy(userPath, chosenPath); *windowOpen = false; } //Memory cleanup windowConfigured = false; for (int i = 0; i < history->previousPaths.size(); i++){ free(history->previousPaths.at(i)); } for (int i = 0; i < onPresentPaths.size(); i++){ free(onPresentPaths.at(i)); } onPresentPaths.resize(0); std::vector previousPaths; delete history; return exitFlag; } int windowRendering(wchar_t* userPath, bool* windowOpen, int windowFlags = 0){ ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGui::Begin("File picker", windowOpen, windowFlags); ImGui::PopStyleVar(1); //log_debugcpp(*windowOpen); //Listar UNA VEZ volumenes if (listFlags & LIST_VOLUME) { listFlags &= ~LIST_VOLUME; numVolumes = listVolumes(&onPresentPaths, &onPresentPathsUTF8); log_debugcpp(std::to_string(numVolumes) + "<- depth MAIN size() ->" + std::to_string(onPresentPaths.size())); } //Listar UNA VEZ directorios //ImGui::Text("%s PRE DIRECTORY TREATMENTO", currentPath); if (listFlags & LIST_DIRECTORY) { listFlags &= ~LIST_DIRECTORY; chosenPath[0] = '\0'; log_debugcpp("ADECUADO LISTAR DIRECTORIOS"); if(!retrieveCurrentDirectory(currentPath)) { log_debugcpp("NO HABIA DIRECTORIO GetCurrentPath()"); exit(EXIT_FAILURE); } // //TODO Expand extension filter numFiles = listDirectory(std::wstring(currentPath), &directoryContents); //std::cout << numFiles; if (numFiles < 0) { long directoryErrorCode; log_debugcpp("FALLO LA FUNCION, VALOR NEGATIVO " + std::to_string(numFiles)); if (numFiles == DIRECTORY_ERROR_ACCESSING_CONTENT) directoryErrorCode = getLastSystemError(); showError = true; switch(directoryErrorCode) { case AGDIR_ERROR_ACCESS_DENIED: strcpy(error, ErrorMessages::accessDeniedError); wcscpy(addrBarVal, history->previousPaths.at(history->historyTraversalPos)); wcscpy(currentPath, history->previousPaths.at(history->historyTraversalPos)); numFiles = listDirectory(history->previousPaths.at(history->historyTraversalPos), &directoryContents); break; default: strcpy(error, ErrorMessages::listDirectoryError); wcscpy(currentPath, addrBarVal); numFiles = listDirectory(std::wstring(currentPath), &directoryContents); break; } history->isAdditionTime = false; } else { showError = false; wcscpy(addrBarVal, currentPath); if(history->isAdditionTime) addPathToHistory(history, addrBarVal); } } /* It's renderin' time */ if(showError) ImGui::Text(error); ImGui::Text("Select a file:"); //BACK ImGui::BeginDisabled(MIN_HISTORY_POS); if(ImGui::Button("Back")) { wchar_t* interfaceMovementButtonsPath = moveThroughHistory(history, HISTORY_BACKWARD); listFlags = handleFolderAccessResult(listFlags, interfaceMovementButtonsPath, &showError, error, ErrorMessages::moveUpError, history, false); } ImGui::EndDisabled(); //FORWARD ImGui::SameLine(); ImGui::BeginDisabled(MAX_HISTORY_POS); if(ImGui::Button("Forward")) { wchar_t* interfaceMovementButtonsPath = moveThroughHistory(history, HISTORY_FORWARD); listFlags = handleFolderAccessResult(listFlags, interfaceMovementButtonsPath, &showError, error, ErrorMessages::moveUpError, history, false); } ImGui::EndDisabled(); //MOVE UP ImGui::SameLine(); if(ImGui::Button("Move Up")) { listFlags = handleFolderAccessResult(listFlags, moveUp, &showError, error, ErrorMessages::moveUpError, history, true); } ImGui::SameLine(); //BARRA DE DIRECCIONES ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - (ImGui::CalcTextSize("Enter").x + ImGui::GetStyle().ItemSpacing.x * 2) ); WideCharToMultiByte(CP_UTF8, NULL, addrBarVal, -1, addrBarValUTF8, 4 * MAX_PATH, NULL, NULL); if(ImGui::InputText("##addrbar", addrBarValUTF8, IM_ARRAYSIZE(addrBarValUTF8), ImGuiInputTextFlags_EnterReturnsTrue )){ log_debugcpp(currentPath <<" ADDRBAR INTENTO"); MultiByteToWideChar(CP_UTF8, NULL, addrBarValUTF8, -1, addrBarVal, 2 * MAX_PATH); listFlags = handleFolderAccessResult(listFlags, addrBarVal, &showError, error, ErrorMessages::addrBarError, history, currentPath, addrBarVal); } ImGui::PopItemWidth(); ImGui::SameLine(); if(ImGui::Button("Enter")){ log_debugcpp(currentPath <<" ADDRBAR INTENTO"); listFlags = handleFolderAccessResult(listFlags, addrBarVal, &showError, error, ErrorMessages::addrBarError, history, currentPath, addrBarVal); } //ImGui::Text("%s TEMPADDRBAR", currentPath); //LA GRAN TABLACIÓN: ACTOR EN LAS SOMBRAS static ImGuiTableFlags splitterTableFlags = ImGuiTableFlags_Resizable | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV; if (ImGui::BeginTable("##splitterTable", 2, splitterTableFlags, ImVec2(-FLT_MIN, 0.8f * ImGui::GetTextLineHeightWithSpacing()))){ ImGui::TableNextRow(); ImGui::TableNextColumn(); //VOLUMENES static ImGuiTableFlags volumesFlags = ImGuiTableFlags_RowBg | ImGuiTableFlags_ScrollY ; if (ImGui::BeginTable("##volumesTable", 1, volumesFlags, ImVec2(-FLT_MIN, 20 * ImGui::GetTextLineHeightWithSpacing()))){ ImGui::TableSetupColumn("Volumes", ImGuiTableColumnFlags_NoHide); //ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 12.0f); //ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 18.0f); ImGui::TableHeadersRow(); ImGui::TableNextRow(); if (numVolumes > 0) { for (int i = 0; i < onPresentPaths.size(); i++) { ImGui::TableNextColumn(); // ImGui::PushID(i); ImGui::PushStyleColor(ImGuiCol_Button, (ImVec4)ImColor::HSV(i / 7.0f, 0.6f, 0.6f)); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, (ImVec4)ImColor::HSV(i / 7.0f, 0.7f, 0.7f)); ImGui::PushStyleColor(ImGuiCol_ButtonActive, (ImVec4)ImColor::HSV(i / 7.0f, 0.8f, 0.8f)); if(ImGui::Button(onPresentPathsUTF8.at(i))){ listFlags = handleFolderAccessResult(listFlags, onPresentPaths.at(i), &showError, error, ErrorMessages::moveUpError, history, true); } ImGui::PopStyleColor(3); if (i != onPresentPaths.size() - 1) ImGui::TableNextRow(); // ImGui::PopID(); } } ImGui::EndTable(); } ImGui::TableNextColumn(); //DRAW DIRECTORIOS ENCONTRADOS static ImGuiTableFlags directoriesFlags = ImGuiTableFlags_RowBg | ImGuiTableFlags_Resizable |ImGuiTableFlags_ScrollY ; if (ImGui::BeginTable("##directoriesTable", 3, directoriesFlags, ImVec2(-FLT_MIN, 20 * ImGui::GetTextLineHeightWithSpacing()))){ ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_NoHide); ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_NoHide); ImGui::TableSetupColumn("Size", ImGuiTableColumnFlags_NoHide); //ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 12.0f); //ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthFixed, TEXT_BASE_WIDTH * 18.0f); ImGui::TableHeadersRow(); int idx = 0; for (; idx < numFiles; idx++) { if(directoryContents.at(idx)->isHidden && !showHidden) continue; if(filterByExtension && !directoryContents.at(idx)->isFile) { //TODO Expand extensions filter extensions.clear(); extensions.push_back(L"exe"); if (!compareLastWchar(&extensions, directoryContents.at(idx)->name)) continue; } ImGui::TableNextRow(); ImGui::TableNextColumn(); //NAME bool isSelected = false; WideCharToMultiByte(CP_UTF8, NULL, addrBarVal, -1, addrBarValUTF8, 4 * MAX_PATH, NULL, NULL); if (ImGui::Selectable(directoryContents.at(idx)->nameUTF8, &isSelected)){ if(!directoryContents.at(idx)->isFile) { wcscpy(chosenPath, addrBarVal); wcscat(chosenPath, L"\\"); wcscat(chosenPath, directoryContents.at(idx)->name); log_wdebugcpp(chosenPath << L" selected"); } else { wcscat(addrBarVal, L"\\"); wcscat(addrBarVal, directoryContents.at(idx)->name); log_debugcpp("directo selected"); listFlags = handleFolderAccessResult(listFlags, addrBarVal, &showError, error, ErrorMessages::tableElementError, history, currentPath, addrBarVal); } //currentItemIdx = -1; } ImGui::TableNextColumn(); //TYPE if (directoryContents.at(idx)->isFile) ImGui::Text("Folder"); else ImGui::Text("File"); ImGui::TableNextColumn(); //SIZE if (!directoryContents.at(idx)->isFile) ImGui::Text("%lld bytes", directoryContents.at(idx)->size); else ImGui::Text(""); //ImGui::SetItemDefaultFocus(); } //DISPLAYING ALTERNATIVE INFO if (!idx) { ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::Text("Folder is empty"); } ImGui::EndTable(); } ImGui::EndTable(); } //ImGui::TreePop(); //BOTTOM ROW ImGui::Checkbox("Show hidden", &showHidden); ImGui::SameLine(); ImGui::Checkbox("Filter by .exe", &filterByExtension); ImGui::SameLine(); ImGui::SameLine(); ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - (ImGui::CalcTextSize("Select").x + ImGui::GetStyle().ItemSpacing.x * 2) ); ImGui::BeginDisabled(); WideCharToMultiByte(CP_UTF8, NULL, chosenPath, -1, chosenPathUTF8, 4 * MAX_PATH, NULL, NULL); ImGui::InputText("##chosenbar", chosenPathUTF8, IM_ARRAYSIZE(chosenPathUTF8), ImGuiInputTextFlags_EnterReturnsTrue ); ImGui::EndDisabled(); ImGui::SameLine(); if(ImGui::Button("Select")) { log_wdebugcpp(chosenPath << " TRIED TO RETURN"); ImGui::End(); return exitWindow(userPath, windowOpen, ExitFlags::EXIT_SELECTED); } //listFlags = handleFolderAccessResult(listFlags, addrBarVal, &showError, error, ErrorMessages::addrBarError, history, currentPath, addrBarVal); ImGui::End(); if(windowOpen) return EXIT_CONTINUE; else return exitWindow(userPath, windowOpen, ExitFlags::EXIT_CLOSED); } }