123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625 |
- /*******************************************************************************************
- *
- * Window File Dialog v1.2 - Modal file dialog to open/save files
- *
- * MODULE USAGE:
- * #define GUI_WINDOW_FILE_DIALOG_IMPLEMENTATION
- * #include "gui_window_file_dialog.h"
- *
- * INIT: GuiWindowFileDialogState state = GuiInitWindowFileDialog();
- * DRAW: GuiWindowFileDialog(&state);
- *
- * NOTE: This module depends on some raylib file system functions:
- * - LoadDirectoryFiles()
- * - UnloadDirectoryFiles()
- * - GetWorkingDirectory()
- * - DirectoryExists()
- * - FileExists()
- *
- * LICENSE: zlib/libpng
- *
- * Copyright (c) 2019-2024 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.
- *
- **********************************************************************************************/
- #include "raylib.h"
- #ifndef GUI_WINDOW_FILE_DIALOG_H
- #define GUI_WINDOW_FILE_DIALOG_H
- // Gui file dialog context data
- typedef struct {
- // Window management variables
- bool windowActive;
- Rectangle windowBounds;
- Vector2 panOffset;
- bool dragMode;
- bool supportDrag;
- // UI variables
- bool dirPathEditMode;
- char dirPathText[1024];
- int filesListScrollIndex;
- bool filesListEditMode;
- int filesListActive;
- bool fileNameEditMode;
- char fileNameText[1024];
- bool SelectFilePressed;
- bool CancelFilePressed;
- int fileTypeActive;
- int itemFocused;
- // Custom state variables
- FilePathList dirFiles;
- char filterExt[256];
- char dirPathTextCopy[1024];
- char fileNameTextCopy[1024];
- int prevFilesListActive;
- bool saveFileMode;
- } GuiWindowFileDialogState;
- #ifdef __cplusplus
- extern "C" { // Prevents name mangling of functions
- #endif
- //----------------------------------------------------------------------------------
- // Defines and Macros
- //----------------------------------------------------------------------------------
- //...
- //----------------------------------------------------------------------------------
- // Types and Structures Definition
- //----------------------------------------------------------------------------------
- // ...
- //----------------------------------------------------------------------------------
- // Global Variables Definition
- //----------------------------------------------------------------------------------
- //...
- //----------------------------------------------------------------------------------
- // Module Functions Declaration
- //----------------------------------------------------------------------------------
- GuiWindowFileDialogState InitGuiWindowFileDialog(const char *initPath);
- void GuiWindowFileDialog(GuiWindowFileDialogState *state);
- #ifdef __cplusplus
- }
- #endif
- #endif // GUI_WINDOW_FILE_DIALOG_H
- /***********************************************************************************
- *
- * GUI_WINDOW_FILE_DIALOG IMPLEMENTATION
- *
- ************************************************************************************/
- #if defined(GUI_WINDOW_FILE_DIALOG_IMPLEMENTATION)
- #include "../../src/raygui.h"
- #include <string.h> // Required for: strcpy()
- //----------------------------------------------------------------------------------
- // Defines and Macros
- //----------------------------------------------------------------------------------
- #define MAX_DIRECTORY_FILES 2048
- #define MAX_ICON_PATH_LENGTH 512
- #ifdef _WIN32
- #define PATH_SEPERATOR "\\"
- #else
- #define PATH_SEPERATOR "/"
- #endif
- //----------------------------------------------------------------------------------
- // 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; // Files are just a path string
- #endif
- //----------------------------------------------------------------------------------
- // Global Variables Definition
- //----------------------------------------------------------------------------------
- FileInfo *dirFilesIcon = NULL; // Path string + icon (for fancy drawing)
- //----------------------------------------------------------------------------------
- // Internal Module Functions Definition
- //----------------------------------------------------------------------------------
- // Read files in new path
- static void ReloadDirectoryFiles(GuiWindowFileDialogState *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
- //----------------------------------------------------------------------------------
- GuiWindowFileDialogState InitGuiWindowFileDialog(const char *initPath)
- {
- GuiWindowFileDialogState state = { 0 };
- // Init window data
- state.windowBounds = (Rectangle){ GetScreenWidth()/2 - 440/2, GetScreenHeight()/2 - 310/2, 440, 310 };
- state.windowActive = false;
- state.supportDrag = true;
- state.dragMode = false;
- state.panOffset = (Vector2){ 0, 0 };
- // Init path data
- 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());
- // TODO: Why we keep a copy?
- strcpy(state.dirPathTextCopy, state.dirPathText);
- strcpy(state.fileNameTextCopy, state.fileNameText);
- state.filterExt[0] = '\0';
- //strcpy(state.filterExt, "all");
- state.dirFiles.count = 0;
- return state;
- }
- // Update and draw file dialog
- void GuiWindowFileDialog(GuiWindowFileDialogState *state)
- {
- if (state->windowActive)
- {
- // Update window dragging
- //----------------------------------------------------------------------------------------
- if (state->supportDrag)
- {
- Vector2 mousePosition = GetMousePosition();
- if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON))
- {
- // Window can be dragged from the top window bar
- if (CheckCollisionPointRec(mousePosition, (Rectangle){ state->windowBounds.x, state->windowBounds.y, (float)state->windowBounds.width, RAYGUI_WINDOWBOX_STATUSBAR_HEIGHT }))
- {
- state->dragMode = true;
- state->panOffset.x = mousePosition.x - state->windowBounds.x;
- state->panOffset.y = mousePosition.y - state->windowBounds.y;
- }
- }
- if (state->dragMode)
- {
- state->windowBounds.x = (mousePosition.x - state->panOffset.x);
- state->windowBounds.y = (mousePosition.y - state->panOffset.y);
- // Check screen limits to avoid moving out of screen
- if (state->windowBounds.x < 0) state->windowBounds.x = 0;
- else if (state->windowBounds.x > (GetScreenWidth() - state->windowBounds.width)) state->windowBounds.x = GetScreenWidth() - state->windowBounds.width;
- if (state->windowBounds.y < 0) state->windowBounds.y = 0;
- else if (state->windowBounds.y > (GetScreenHeight() - state->windowBounds.height)) state->windowBounds.y = GetScreenHeight() - state->windowBounds.height;
- if (IsMouseButtonReleased(MOUSE_LEFT_BUTTON)) state->dragMode = false;
- }
- }
- //----------------------------------------------------------------------------------------
- // 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_ICON_PATH_LENGTH, 1); // Max file name length
- }
- // Load current directory files
- if (state->dirFiles.paths == NULL) ReloadDirectoryFiles(state);
- //----------------------------------------------------------------------------------------
- // Draw window and controls
- //----------------------------------------------------------------------------------------
- state->windowActive = !GuiWindowBox(state->windowBounds, "#198# Select File Dialog");
- // Draw previous directory button + logic
- if (GuiButton((Rectangle){ state->windowBounds.x + state->windowBounds.width - 48, state->windowBounds.y + 24 + 12, 40, 24 }, "< .."))
- {
- // Move dir path one level up
- strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText));
- // Reload directory files (frees previous list)
- ReloadDirectoryFiles(state);
- state->filesListActive = -1;
- memset(state->fileNameText, 0, 1024);
- memset(state->fileNameTextCopy, 0, 1024);
- }
- // Draw current directory text box info + path editing logic
- if (GuiTextBox((Rectangle){ state->windowBounds.x + 8, state->windowBounds.y + 24 + 12, state->windowBounds.width - 48 - 16, 24 }, state->dirPathText, 1024, 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;
- }
- // List view elements are aligned left
- 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);
- # if defined(USE_CUSTOM_LISTVIEW_FILEINFO)
- state->filesListActive = GuiListViewFiles((Rectangle){ state->position.x + 8, state->position.y + 48 + 20, state->windowBounds.width - 16, state->windowBounds.height - 60 - 16 - 68 }, fileInfo, state->dirFiles.count, &state->itemFocused, &state->filesListScrollIndex, state->filesListActive);
- # else
- GuiListViewEx((Rectangle){ state->windowBounds.x + 8, state->windowBounds.y + 48 + 20, state->windowBounds.width - 16, state->windowBounds.height - 60 - 16 - 68 },
- (const char**)dirFilesIcon, state->dirFiles.count, &state->filesListScrollIndex, &state->filesListActive, &state->itemFocused);
- # endif
- GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, prevTextAlignment);
- GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, prevElementsHeight);
- // Check if a path has been selected, if it is a directory, move to that directory (and reload paths)
- if ((state->filesListActive >= 0) && (state->filesListActive != state->prevFilesListActive))
- //&& (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_DPAD_A)))
- {
- strcpy(state->fileNameText, GetFileName(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;
- }
- // Draw bottom controls
- //--------------------------------------------------------------------------------------
- GuiLabel((Rectangle){ state->windowBounds.x + 8, state->windowBounds.y + state->windowBounds.height - 68, 60, 24 }, "File name:");
- if (GuiTextBox((Rectangle){ state->windowBounds.x + 72, state->windowBounds.y + state->windowBounds.height - 68, state->windowBounds.width - 184, 24 }, state->fileNameText, 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 (unsigned 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;
- }
- GuiLabel((Rectangle){ state->windowBounds.x + 8, state->windowBounds.y + state->windowBounds.height - 24 - 12, 68, 24 }, "File filter:");
- GuiComboBox((Rectangle){ state->windowBounds.x + 72, state->windowBounds.y + state->windowBounds.height - 24 - 12, state->windowBounds.width - 184, 24 }, "All files", &state->fileTypeActive);
- state->SelectFilePressed = GuiButton((Rectangle){ state->windowBounds.x + state->windowBounds.width - 96 - 8, state->windowBounds.y + state->windowBounds.height - 68, 96, 24 }, "Select");
- if (GuiButton((Rectangle){ state->windowBounds.x + state->windowBounds.width - 96 - 8, state->windowBounds.y + state->windowBounds.height - 24 - 12, 96, 24 }, "Cancel")) state->windowActive = false;
- //--------------------------------------------------------------------------------------
- // Exit on file selected
- if (state->SelectFilePressed) state->windowActive = false;
- // File dialog has been closed, free all memory before exit
- if (!state->windowActive)
- {
- // Free dirFilesIcon memory
- for (int i = 0; i < MAX_DIRECTORY_FILES; i++) RL_FREE(dirFilesIcon[i]);
- RL_FREE(dirFilesIcon);
- dirFilesIcon = NULL;
- // Unload directory file paths
- UnloadDirectoryFiles(state->dirFiles);
- // Reset state variables
- state->dirFiles.count = 0;
- state->dirFiles.capacity = 0;
- state->dirFiles.paths = 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(GuiWindowFileDialogState *state)
- {
- UnloadDirectoryFiles(state->dirFiles);
- state->dirFiles = LoadDirectoryFilesEx(state->dirPathText, (state->filterExt[0] == '\0')? NULL : state->filterExt, false);
- state->itemFocused = 0;
- // Reset dirFilesIcon memory
- for (int i = 0; i < MAX_DIRECTORY_FILES; i++) memset(dirFilesIcon[i], 0, MAX_ICON_PATH_LENGTH);
- // Copy paths as icon + fileNames into dirFilesIcon
- for (unsigned int i = 0; i < state->dirFiles.count; i++)
- {
- if (IsPathFile(state->dirFiles.paths[i]))
- {
- // Path is a file, a file icon for convenience (for some recognized extensions)
- if (IsFileExtension(state->dirFiles.paths[i], ".png;.bmp;.tga;.gif;.jpg;.jpeg;.psd;.hdr;.qoi;.dds;.pkm;.ktx;.pvr;.astc"))
- {
- strcpy(dirFilesIcon[i], TextFormat("#12#%s", GetFileName(state->dirFiles.paths[i])));
- }
- else if (IsFileExtension(state->dirFiles.paths[i], ".wav;.mp3;.ogg;.flac;.xm;.mod;.it;.wma;.aiff"))
- {
- strcpy(dirFilesIcon[i], TextFormat("#11#%s", GetFileName(state->dirFiles.paths[i])));
- }
- else if (IsFileExtension(state->dirFiles.paths[i], ".txt;.info;.md;.nfo;.xml;.json;.c;.cpp;.cs;.lua;.py;.glsl;.vs;.fs"))
- {
- strcpy(dirFilesIcon[i], TextFormat("#10#%s", GetFileName(state->dirFiles.paths[i])));
- }
- else if (IsFileExtension(state->dirFiles.paths[i], ".exe;.bin;.raw;.msi"))
- {
- strcpy(dirFilesIcon[i], TextFormat("#200#%s", GetFileName(state->dirFiles.paths[i])));
- }
- else strcpy(dirFilesIcon[i], TextFormat("#218#%s", GetFileName(state->dirFiles.paths[i])));
- }
- else
- {
- // Path is a directory, add a directory icon
- strcpy(dirFilesIcon[i], TextFormat("#1#%s", GetFileName(state->dirFiles.paths[i])));
- }
- }
- }
- #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)
- {
- int result = 0;
- 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;
- *active = itemSelected;
- return result;
- }
- #endif // USE_CUSTOM_LISTVIEW_FILEINFO
- #endif // GUI_FILE_DIALOG_IMPLEMENTATION
|