Created
September 13, 2022 19:09
-
-
Save nicofretti/f2fb18dfbe28c029df64219f676b3ea0 to your computer and use it in GitHub Desktop.
Fix missing file list
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************************************* | |
* | |
* FileDialog v1.2 - Modal file dialog to open/save files | |
* | |
* MODULE USAGE: | |
* #define GUI_FILE_DIALOG_IMPLEMENTATION | |
* #include "gui_file_dialog.h" | |
* | |
* INIT: GuiFileDialogState state = InitGuiFileDialog(); | |
* DRAW: GuiFileDialog(&state); | |
* | |
* NOTE: This module depends on some raylib file system functions: | |
* - LoadDirectoryFiles() | |
* - UnloadDirectoryFiles() | |
* - GetWorkingDirectory() | |
* - DirectoryExists() | |
* - FileExists() | |
* | |
* LICENSE: zlib/libpng | |
* | |
* Copyright (c) 2019-2022 Ramon Santamaria (@raysan5) | |
* | |
* This software is provided "as-is", without any express or implied warranty. In no event | |
* will the authors be held liable for any damages arising from the use of this software. | |
* | |
* Permission is granted to anyone to use this software for any purpose, including commercial | |
* applications, and to alter it and redistribute it freely, subject to the following restrictions: | |
* | |
* 1. The origin of this software must not be misrepresented; you must not claim that you | |
* wrote the original software. If you use this software in a product, an acknowledgment | |
* in the product documentation would be appreciated but is not required. | |
* | |
* 2. Altered source versions must be plainly marked as such, and must not be misrepresented | |
* as being the original software. | |
* | |
* 3. This notice may not be removed or altered from any source distribution. | |
* | |
********************************************************************************************* | |
* Edited solutions for the following issues: | |
* - Filter system not working | |
* - File list didn't display correctly | |
* - Solution for c++ compatibility | |
* | |
* Example usage: | |
* | |
* InitGuiFileDialog(550, 500, "path", false,".extension"); | |
* | |
* Now is available to set the filter directly in the constructor | |
* | |
* Author: nicof | |
**********************************************************************************************/ | |
#include "raylib.h" | |
// WARNING: raygui implementation is expected to be defined before including this header | |
#undef RAYGUI_IMPLEMENTATION | |
#include "raygui.h" | |
#ifndef GUI_FILE_DIALOG_H | |
#define GUI_FILE_DIALOG_H | |
typedef struct { | |
Vector2 position; | |
Vector2 size; | |
bool fileDialogActive; | |
bool dirPathEditMode; | |
char dirPathText[256]; | |
int filesListScrollIndex; | |
bool filesListEditMode; | |
int filesListActive; | |
bool fileNameEditMode; | |
char fileNameText[256]; | |
bool SelectFilePressed; | |
bool CancelFilePressed; | |
int fileTypeActive; | |
int itemFocused; | |
// Custom state variables (depend on development software) | |
// NOTE: This variables should be added manually if required | |
FilePathList dirFiles; | |
char filterExt[256]; | |
char dirPathTextCopy[256]; | |
char fileNameTextCopy[256]; | |
// Edited - nicof: Save only the file name to be displayed on the file name text box | |
char realFileName[256]; | |
int prevFilesListActive; | |
bool saveFileMode; | |
std::shared_ptr<spdlog::logger> logger; | |
} GuiFileDialogState; | |
#ifdef __cplusplus | |
extern "C" { // Prevents name mangling of functions | |
#endif | |
//---------------------------------------------------------------------------------- | |
// Defines and Macros | |
//---------------------------------------------------------------------------------- | |
//... | |
//---------------------------------------------------------------------------------- | |
// Types and Structures Definition | |
//---------------------------------------------------------------------------------- | |
// ... | |
//---------------------------------------------------------------------------------- | |
// Global Variables Definition | |
//---------------------------------------------------------------------------------- | |
//... | |
//---------------------------------------------------------------------------------- | |
// Module Functions Declaration | |
//---------------------------------------------------------------------------------- | |
GuiFileDialogState InitGuiFileDialog(int width, int height, const char *initPath, bool active, std::shared_ptr<spdlog::logger> logger); | |
void GuiFileDialog(GuiFileDialogState *state); | |
#ifdef __cplusplus | |
} | |
#endif | |
#endif // GUI_FILE_DIALOG_H | |
/*********************************************************************************** | |
* | |
* GUI_FILE_DIALOG IMPLEMENTATION | |
* | |
************************************************************************************/ | |
#if defined(GUI_FILE_DIALOG_IMPLEMENTATION) | |
#include "raygui.h" | |
#include <cstring> // Required for: strcpy() | |
//---------------------------------------------------------------------------------- | |
// Defines and Macros | |
//---------------------------------------------------------------------------------- | |
#define MAX_DIRECTORY_FILES 1024 | |
#define MAX_DIR_PATH_LENGTH 1024 | |
//---------------------------------------------------------------------------------- | |
// Types and Structures Definition | |
//---------------------------------------------------------------------------------- | |
#if defined(USE_CUSTOM_LISTVIEW_FILEINFO) | |
// Detailed file info type | |
typedef struct FileInfo { | |
const char *name; | |
int size; | |
int modTime; | |
int type; | |
int icon; | |
} FileInfo; | |
#else | |
// Filename only | |
typedef char *FileInfo; | |
#endif | |
//---------------------------------------------------------------------------------- | |
// Global Variables Definition | |
//---------------------------------------------------------------------------------- | |
FileInfo *dirFilesIcon = NULL; | |
//---------------------------------------------------------------------------------- | |
// Internal Module Functions Definition | |
//---------------------------------------------------------------------------------- | |
// Read files in new path | |
static void ReloadDirectoryFiles(GuiFileDialogState *state); | |
#if defined(USE_CUSTOM_LISTVIEW_FILEINFO) | |
// List View control for files info with extended parameters | |
static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *focus, int *scrollIndex, int active); | |
#endif | |
//---------------------------------------------------------------------------------- | |
// Module Functions Definition | |
//---------------------------------------------------------------------------------- | |
GuiFileDialogState InitGuiFileDialog(int width, int height, const char *initPath, bool active, const char *fileExt) | |
{ | |
GuiFileDialogState state = { 0 }; | |
// Default dialog size is 440x310 | |
state.size.x = width == -1 ? 440 : width; | |
state.size.y = height == -1 ? 310 : height; | |
state.position = (Vector2){ GetScreenWidth()/2 - state.size.x/2, GetScreenHeight()/2 - state.size.y/2 }; | |
state.fileDialogActive = active; | |
state.dirPathEditMode = false; | |
state.filesListActive = -1; | |
state.prevFilesListActive = state.filesListActive; | |
state.filesListScrollIndex = 0; | |
state.fileNameEditMode = false; | |
state.SelectFilePressed = false; | |
state.CancelFilePressed = false; | |
state.fileTypeActive = 0; | |
strcpy(state.fileNameText, "\0"); | |
// Custom variables initialization | |
if (initPath && DirectoryExists(initPath)) | |
{ | |
strcpy(state.dirPathText, initPath); | |
} | |
else if (initPath && FileExists(initPath)) | |
{ | |
strcpy(state.dirPathText, GetDirectoryPath(initPath)); | |
strcpy(state.fileNameText, GetFileName(initPath)); | |
} | |
else strcpy(state.dirPathText, GetWorkingDirectory()); | |
strcpy(state.dirPathTextCopy, state.dirPathText); | |
strcpy(state.fileNameTextCopy, state.fileNameText); | |
strcpy(state.filterExt, fileExt); | |
state.dirFiles.count = 0; | |
return state; | |
} | |
// Update and draw file dialog | |
void GuiFileDialog(GuiFileDialogState *state) | |
{ | |
if (state->fileDialogActive) | |
{ | |
const int winWidth = state->size.x; | |
const int winHeight = state->size.y; | |
// Load dirFilesIcon and state->dirFiles lazily on windows open | |
// NOTE: they are automatically unloaded at fileDialog closing | |
//------------------------------------------------------------------------------------ | |
if (dirFilesIcon == NULL) | |
{ | |
dirFilesIcon = (FileInfo *)RL_CALLOC(MAX_DIRECTORY_FILES, sizeof(FileInfo)); // Max files to read | |
for (int i = 0; i < MAX_DIRECTORY_FILES; i++) dirFilesIcon[i] = (char *)RL_CALLOC(MAX_DIR_PATH_LENGTH, 1); // Max file name length | |
} | |
if (state->dirFiles.paths == NULL) | |
{ | |
state->dirFiles = LoadDirectoryFilesEx(state->dirPathText, state->filterExt, false); | |
for(int f = 0; f < state->dirFiles.count; f++) | |
{ | |
if (strcmp(state->fileNameText, state->dirFiles.paths[f]) == 0) | |
{ | |
if (state->filesListActive != f) state->filesListScrollIndex = state->filesListActive = f; // Make it active and visible only on first call | |
break; | |
} | |
} | |
} | |
//------------------------------------------------------------------------------------ | |
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), Fade(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)), 0.85f)); | |
state->fileDialogActive = !GuiWindowBox((Rectangle){ state->position.x + 0, state->position.y + 0, winWidth, winHeight }, "#198# Select File Dialog"); | |
// Button back | |
if (GuiButton((Rectangle){ state->position.x + winWidth - 50, state->position.y + 35, 40, 25 }, "< ..")) // || IsKeyReleased(KEY_DPAD_Y)) | |
{ | |
// Move dir path one level up | |
strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText)); | |
// Reload directory files (frees previous list) | |
ReloadDirectoryFiles(state); | |
state->filesListActive = -1; | |
strcpy(state->fileNameText, "\0"); | |
strcpy(state->fileNameTextCopy, state->fileNameText); | |
} | |
if (GuiTextBox((Rectangle){ state->position.x + 10, state->position.y + 35, winWidth - 65, 25 }, state->dirPathText, 256, state->dirPathEditMode)) | |
{ | |
if (state->dirPathEditMode) | |
{ | |
// Verify if a valid path has been introduced | |
if (DirectoryExists(state->dirPathText)) | |
{ | |
// Reload directory files (frees previous list) | |
ReloadDirectoryFiles(state); | |
strcpy(state->dirPathTextCopy, state->dirPathText); | |
} | |
else strcpy(state->dirPathText, state->dirPathTextCopy); | |
} | |
state->dirPathEditMode = !state->dirPathEditMode; | |
} | |
int prevTextAlignment = GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT); | |
int prevElementsHeight = GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT); | |
GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, TEXT_ALIGN_LEFT); | |
GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 24); | |
// TODO: ListViewElements should be aligned left | |
# if defined(USE_CUSTOM_LISTVIEW_FILEINFO) | |
FileInfo fileInfo; | |
state->filesListActive = GuiListViewFiles((Rectangle){ state->position.x + 10, state->position.y + 70, winWidth - 20, winHeight - 135 }, fileInfo, state->dirFiles.count, &state->itemFocused, &state->filesListScrollIndex, state->filesListActive); | |
# else | |
// Edited: nicof - Fix filenames errors | |
const char** names = | |
static_cast<const char **>(malloc(sizeof(char *) * state->dirFiles.count)); | |
for(int i =0; i<state->dirFiles.count; i++) | |
{ | |
names[i] = GetFileName(state->dirFiles.paths[i]); | |
} | |
//state->filesListActive = GuiListViewEx((Rectangle){ state->position.x + 10, state->position.y + 70, winWidth - 20, winHeight - 135 }, (const char**)dirFilesIcon, state->dirFiles.count, &state->itemFocused, &state->filesListScrollIndex, state->filesListActive); | |
state->filesListActive = GuiListViewEx((Rectangle){ state->position.x + 10, state->position.y + 70, winWidth - 20, winHeight - 135 }, | |
names, state->dirFiles.count, &state->itemFocused, &state->filesListScrollIndex, state->filesListActive); | |
# endif | |
GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, prevTextAlignment); | |
GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, prevElementsHeight); | |
if ((state->filesListActive >= 0) && (state->filesListActive != state->prevFilesListActive)) | |
//&& (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_DPAD_A))) | |
{ | |
strcpy(state->fileNameText, state->dirFiles.paths[state->filesListActive]); | |
if (DirectoryExists(TextFormat("%s/%s", state->dirPathText, state->fileNameText))) | |
{ | |
if (TextIsEqual(state->fileNameText, "..")) strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText)); | |
else strcpy(state->dirPathText, TextFormat("%s/%s", strcmp(state->dirPathText, "/")==0 ? "" : state->dirPathText, state->fileNameText)); | |
strcpy(state->dirPathTextCopy, state->dirPathText); | |
// Reload directory files (frees previous list) | |
ReloadDirectoryFiles(state); | |
strcpy(state->dirPathTextCopy, state->dirPathText); | |
state->filesListActive = -1; | |
strcpy(state->fileNameText, "\0"); | |
strcpy(state->fileNameTextCopy, state->fileNameText); | |
} | |
state->prevFilesListActive = state->filesListActive; | |
} | |
GuiLabel((Rectangle){ state->position.x + 10, state->position.y + winHeight - 60, 68, 25 }, "File name:"); | |
// Edited: nicof - Replace filename in the textbox | |
strcpy(state->realFileName,GetFileName(state->fileNameText)); | |
//if (GuiTextBox((Rectangle){ state->position.x + 75, state->position.y + winHeight - 60, winWidth - 200, 25 }, state->fileNameText, 128, state->fileNameEditMode)) | |
if (GuiTextBox((Rectangle){ state->position.x + 75, state->position.y + winHeight - 60, winWidth - 200, 25 }, state->realFileName, 128, state->fileNameEditMode)) | |
{ | |
if (*state->fileNameText) | |
{ | |
// Verify if a valid filename has been introduced | |
if (FileExists(TextFormat("%s/%s", state->dirPathText, state->fileNameText))) | |
{ | |
// Select filename from list view | |
for (int i = 0; i < state->dirFiles.count; i++) | |
{ | |
if (TextIsEqual(state->fileNameText, state->dirFiles.paths[i])) | |
{ | |
state->filesListActive = i; | |
strcpy(state->fileNameTextCopy, state->fileNameText); | |
break; | |
} | |
} | |
} | |
else if (!state->saveFileMode) | |
{ | |
strcpy(state->fileNameText, state->fileNameTextCopy); | |
} | |
} | |
state->fileNameEditMode = !state->fileNameEditMode; | |
} | |
state->fileTypeActive = GuiComboBox((Rectangle){ state->position.x + 75, state->position.y + winHeight - 30, winWidth - 200, 25 }, state->filterExt, state->fileTypeActive); | |
GuiLabel((Rectangle){ state->position.x + 10, state->position.y + winHeight - 30, 68, 25 }, "File filter:"); | |
state->SelectFilePressed = GuiButton((Rectangle){ state->position.x + winWidth - 120, state->position.y + winHeight - 60, 110, | |
#ifdef PLATFORM_DESKTOP | |
25 | |
#else | |
25 + 30 | |
#endif | |
}, "Select");// || IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_DPAD_A); | |
if (state->SelectFilePressed) state->fileDialogActive = false; | |
#ifdef PLATFORM_DESKTOP | |
if (GuiButton((Rectangle){ state->position.x + winWidth - 120, state->position.y + winHeight - 30, 110, 25 }, "Quit")) state->fileDialogActive = false; | |
#endif | |
// File dialog has been closed! | |
if (!state->fileDialogActive) | |
{ | |
// Free dirFiles memory | |
for (int i = 0; i < MAX_DIRECTORY_FILES; i++) | |
{ | |
RL_FREE(dirFilesIcon[i]); | |
} | |
UnloadDirectoryFiles(state->dirFiles); | |
state->dirFiles.count = 0; | |
state->dirFiles.capacity = 0; | |
state->dirFiles.paths = NULL; | |
RL_FREE(dirFilesIcon); | |
dirFilesIcon = NULL; | |
} | |
} | |
} | |
// Compare two files from a directory | |
static inline int FileCompare(const char *d1, const char *d2, const char *dir) | |
{ | |
const bool b1 = DirectoryExists(TextFormat("%s/%s", dir, d1)); | |
const bool b2 = DirectoryExists(TextFormat("%s/%s", dir, d2)); | |
if (b1 && !b2) return -1; | |
if (!b1 && b2) return 1; | |
if (!FileExists(TextFormat("%s/%s", dir, d1))) return 1; | |
if (!FileExists(TextFormat("%s/%s", dir, d2))) return -1; | |
return strcmp(d1, d2); | |
} | |
// Read files in new path | |
static void ReloadDirectoryFiles(GuiFileDialogState *state) | |
{ | |
UnloadDirectoryFiles(state->dirFiles); | |
state->dirFiles = LoadDirectoryFilesEx(state->dirPathText, state->filterExt, false); | |
state->itemFocused = 0; | |
} | |
#if defined(USE_CUSTOM_LISTVIEW_FILEINFO) | |
// List View control for files info with extended parameters | |
static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *focus, int *scrollIndex, int active) | |
{ | |
GuiState state = guiState; | |
int itemFocused = (focus == NULL)? -1 : *focus; | |
int itemSelected = active; | |
// Check if we need a scroll bar | |
bool useScrollBar = false; | |
if ((GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING))*count > bounds.height) useScrollBar = true; | |
// Define base item rectangle [0] | |
Rectangle itemBounds = { 0 }; | |
itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING); | |
itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH); | |
itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) - GuiGetStyle(DEFAULT, BORDER_WIDTH); | |
itemBounds.height = GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT); | |
if (useScrollBar) itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH); | |
// Get items on the list | |
int visibleItems = bounds.height/(GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING)); | |
if (visibleItems > count) visibleItems = count; | |
int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex; | |
if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0; | |
int endIndex = startIndex + visibleItems; | |
// Update control | |
//-------------------------------------------------------------------- | |
if ((state != GUI_STATE_DISABLED) && !guiLocked) | |
{ | |
Vector2 mousePoint = GetMousePosition(); | |
// Check mouse inside list view | |
if (CheckCollisionPointRec(mousePoint, bounds)) | |
{ | |
state = GUI_STATE_FOCUSED; | |
// Check focused and selected item | |
for (int i = 0; i < visibleItems; i++) | |
{ | |
if (CheckCollisionPointRec(mousePoint, itemBounds)) | |
{ | |
itemFocused = startIndex + i; | |
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) itemSelected = startIndex + i; | |
break; | |
} | |
// Update item rectangle y position for next item | |
itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING)); | |
} | |
if (useScrollBar) | |
{ | |
int wheelMove = GetMouseWheelMove(); | |
startIndex -= wheelMove; | |
if (startIndex < 0) startIndex = 0; | |
else if (startIndex > (count - visibleItems)) startIndex = count - visibleItems; | |
endIndex = startIndex + visibleItems; | |
if (endIndex > count) endIndex = count; | |
} | |
} | |
else itemFocused = -1; | |
// Reset item rectangle y to [0] | |
itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH); | |
} | |
//-------------------------------------------------------------------- | |
// Draw control | |
//-------------------------------------------------------------------- | |
DrawRectangleRec(bounds, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background | |
DrawRectangleLinesEx(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), guiAlpha)); | |
// TODO: Draw list view header with file sections: icon+name | size | type | modTime | |
// Draw visible items | |
for (int i = 0; i < visibleItems; i++) | |
{ | |
if (state == GUI_STATE_DISABLED) | |
{ | |
if ((startIndex + i) == itemSelected) | |
{ | |
DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)), guiAlpha)); | |
DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_DISABLED)), guiAlpha)); | |
} | |
// TODO: Draw full file info line: icon+name | size | type | modTime | |
GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED)), guiAlpha)); | |
} | |
else | |
{ | |
if ((startIndex + i) == itemSelected) | |
{ | |
// Draw item selected | |
DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)), guiAlpha)); | |
DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_PRESSED)), guiAlpha)); | |
GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_PRESSED)), guiAlpha)); | |
} | |
else if ((startIndex + i) == itemFocused) | |
{ | |
// Draw item focused | |
DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)), guiAlpha)); | |
DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_COLOR_FOCUSED)), guiAlpha)); | |
GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED)), guiAlpha)); | |
} | |
else | |
{ | |
// Draw item normal | |
GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_NORMAL)), guiAlpha)); | |
} | |
} | |
// Update item rectangle y position for next item | |
itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING)); | |
} | |
if (useScrollBar) | |
{ | |
Rectangle scrollBarBounds = { | |
bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), | |
bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH), | |
bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH) | |
}; | |
// Calculate percentage of visible items and apply same percentage to scrollbar | |
float percentVisible = (float)(endIndex - startIndex)/count; | |
float sliderSize = bounds.height*percentVisible; | |
int prevSliderSize = GuiGetStyle(SCROLLBAR, SLIDER_WIDTH); // Save default slider size | |
int prevScrollSpeed = GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed | |
GuiSetStyle(SCROLLBAR, SLIDER_WIDTH, sliderSize); // Change slider size | |
GuiSetStyle(SCROLLBAR, SCROLL_SPEED, count - visibleItems); // Change scroll speed | |
startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems); | |
GuiSetStyle(SCROLLBAR, SCROLL_SPEED, prevScrollSpeed); // Reset scroll speed to default | |
GuiSetStyle(SCROLLBAR, SLIDER_WIDTH, prevSliderSize); // Reset slider size to default | |
} | |
//-------------------------------------------------------------------- | |
if (focus != NULL) *focus = itemFocused; | |
if (scrollIndex != NULL) *scrollIndex = startIndex; | |
return itemSelected; | |
} | |
#endif // USE_CUSTOM_LISTVIEW_FILEINFO | |
#endif // GUI_FILE_DIALOG_IMPLEMENTATION |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment