mirror of
https://github.com/raysan5/raygui.git
synced 2026-02-02 12:19:17 -05:00
Review gui_file_dialog with proposed improvements
Proposed improvements in: https://github.com/raysan5/raylib/issues/1101
This commit is contained in:
@ -35,17 +35,17 @@ int main()
|
|||||||
//---------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------
|
||||||
int screenWidth = 800;
|
int screenWidth = 800;
|
||||||
int screenHeight = 560;
|
int screenHeight = 560;
|
||||||
|
|
||||||
InitWindow(screenWidth, screenHeight, "raygui - custom modal dialog");
|
InitWindow(screenWidth, screenHeight, "raygui - custom modal dialog");
|
||||||
SetExitKey(0);
|
SetExitKey(0);
|
||||||
|
|
||||||
// Custom file dialog
|
// Custom file dialog
|
||||||
GuiFileDialogState fileDialogState = InitGuiFileDialog();
|
GuiFileDialogState fileDialogState = InitGuiFileDialog(420, 310, GetWorkingDirectory(), false);
|
||||||
|
|
||||||
bool exitWindow = false;
|
bool exitWindow = false;
|
||||||
|
|
||||||
char fileNameToLoad[512] = { 0 };
|
char fileNameToLoad[512] = { 0 };
|
||||||
|
|
||||||
Texture texture = { 0 };
|
Texture texture = { 0 };
|
||||||
|
|
||||||
SetTargetFPS(60);
|
SetTargetFPS(60);
|
||||||
@ -57,7 +57,7 @@ int main()
|
|||||||
// Update
|
// Update
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
exitWindow = WindowShouldClose();
|
exitWindow = WindowShouldClose();
|
||||||
|
|
||||||
if (fileDialogState.SelectFilePressed)
|
if (fileDialogState.SelectFilePressed)
|
||||||
{
|
{
|
||||||
// Load image file (if supported extension)
|
// Load image file (if supported extension)
|
||||||
@ -67,7 +67,7 @@ int main()
|
|||||||
UnloadTexture(texture);
|
UnloadTexture(texture);
|
||||||
texture = LoadTexture(fileNameToLoad);
|
texture = LoadTexture(fileNameToLoad);
|
||||||
}
|
}
|
||||||
|
|
||||||
fileDialogState.SelectFilePressed = false;
|
fileDialogState.SelectFilePressed = false;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
@ -77,20 +77,20 @@ int main()
|
|||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
|
|
||||||
ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
|
ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
|
||||||
|
|
||||||
DrawTexture(texture, GetScreenWidth()/2 - texture.width/2, GetScreenHeight()/2 - texture.height/2 - 5, WHITE);
|
DrawTexture(texture, GetScreenWidth()/2 - texture.width/2, GetScreenHeight()/2 - texture.height/2 - 5, WHITE);
|
||||||
DrawRectangleLines(GetScreenWidth()/2 - texture.width/2, GetScreenHeight()/2 - texture.height/2 - 5, texture.width, texture.height, BLACK);
|
DrawRectangleLines(GetScreenWidth()/2 - texture.width/2, GetScreenHeight()/2 - texture.height/2 - 5, texture.width, texture.height, BLACK);
|
||||||
|
|
||||||
DrawText(fileNameToLoad, 208, GetScreenHeight() - 20, 10, GRAY);
|
DrawText(fileNameToLoad, 208, GetScreenHeight() - 20, 10, GRAY);
|
||||||
|
|
||||||
// raygui: controls drawing
|
// raygui: controls drawing
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
if (fileDialogState.fileDialogActive) GuiLock();
|
if (fileDialogState.fileDialogActive) GuiLock();
|
||||||
|
|
||||||
if (GuiButton((Rectangle){ 20, 20, 140, 30 }, GuiIconText(RICON_FILE_OPEN, "Open Image"))) fileDialogState.fileDialogActive = true;
|
if (GuiButton((Rectangle){ 20, 20, 140, 30 }, GuiIconText(RICON_FILE_OPEN, "Open Image"))) fileDialogState.fileDialogActive = true;
|
||||||
|
|
||||||
GuiUnlock();
|
GuiUnlock();
|
||||||
|
|
||||||
// GUI: Dialog Window
|
// GUI: Dialog Window
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
GuiFileDialog(&fileDialogState);
|
GuiFileDialog(&fileDialogState);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
/*******************************************************************************************
|
/*******************************************************************************************
|
||||||
*
|
*
|
||||||
* FileDialog v1.0.0 - Modal file dialog to open/save files
|
* FileDialog v1.1 - Modal file dialog to open/save files
|
||||||
*
|
*
|
||||||
* MODULE USAGE:
|
* MODULE USAGE:
|
||||||
* #define GUI_FILE_DIALOG_IMPLEMENTATION
|
* #define GUI_FILE_DIALOG_IMPLEMENTATION
|
||||||
@ -16,13 +16,24 @@
|
|||||||
* - DirectoryExists()
|
* - DirectoryExists()
|
||||||
* - FileExists()
|
* - FileExists()
|
||||||
*
|
*
|
||||||
* LICENSE: Propietary License
|
* LICENSE: zlib/libpng
|
||||||
*
|
*
|
||||||
* Copyright (c) 2019 raylib technologies (@raylibtech). All Rights Reserved.
|
* Copyright (c) 2019-2020 Ramon Santamaria (@raysan5)
|
||||||
*
|
*
|
||||||
* Unauthorized copying of this file, via any medium is strictly prohibited
|
* This software is provided "as-is", without any express or implied warranty. In no event
|
||||||
* This project is proprietary and confidential unless the owner allows
|
* will the authors be held liable for any damages arising from the use of this software.
|
||||||
* usage in any other form by expresely written permission.
|
*
|
||||||
|
* 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.
|
||||||
*
|
*
|
||||||
**********************************************************************************************/
|
**********************************************************************************************/
|
||||||
|
|
||||||
@ -37,21 +48,23 @@
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Vector2 position;
|
Vector2 position;
|
||||||
|
Vector2 size;
|
||||||
|
|
||||||
bool fileDialogActive;
|
bool fileDialogActive;
|
||||||
|
|
||||||
bool dirPathEditMode;
|
bool dirPathEditMode;
|
||||||
char dirPathText[256];
|
char dirPathText[256];
|
||||||
|
|
||||||
int filesListScrollIndex;
|
int filesListScrollIndex;
|
||||||
bool filesListEditMode;
|
bool filesListEditMode;
|
||||||
int filesListActive;
|
int filesListActive;
|
||||||
|
|
||||||
bool fileNameEditMode;
|
bool fileNameEditMode;
|
||||||
char fileNameText[256];
|
char fileNameText[256];
|
||||||
bool SelectFilePressed;
|
bool SelectFilePressed;
|
||||||
bool CancelFilePressed;
|
bool CancelFilePressed;
|
||||||
int fileTypeActive;
|
int fileTypeActive;
|
||||||
|
int itemFocused;
|
||||||
|
|
||||||
// Custom state variables (depend on development software)
|
// Custom state variables (depend on development software)
|
||||||
// NOTE: This variables should be added manually if required
|
// NOTE: This variables should be added manually if required
|
||||||
@ -59,10 +72,10 @@ typedef struct {
|
|||||||
int dirFilesCount;
|
int dirFilesCount;
|
||||||
|
|
||||||
char filterExt[256];
|
char filterExt[256];
|
||||||
|
|
||||||
char dirPathTextCopy[256];
|
char dirPathTextCopy[256];
|
||||||
char fileNameTextCopy[256];
|
char fileNameTextCopy[256];
|
||||||
|
|
||||||
int prevFilesListActive;
|
int prevFilesListActive;
|
||||||
|
|
||||||
} GuiFileDialogState;
|
} GuiFileDialogState;
|
||||||
@ -89,7 +102,7 @@ extern "C" { // Prevents name mangling of functions
|
|||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Declaration
|
// Module Functions Declaration
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
GuiFileDialogState InitGuiFileDialog(void);
|
GuiFileDialogState InitGuiFileDialog(int width, int height, const char *initPath, bool active);
|
||||||
void GuiFileDialog(GuiFileDialogState *state);
|
void GuiFileDialog(GuiFileDialogState *state);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -128,12 +141,15 @@ typedef struct FileInfo {
|
|||||||
int type;
|
int type;
|
||||||
int icon;
|
int icon;
|
||||||
} FileInfo;
|
} FileInfo;
|
||||||
|
#else
|
||||||
|
// Filename only
|
||||||
|
typedef char *FileInfo;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Global Variables Definition
|
// Global Variables Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
char **dirFilesIcon = NULL;
|
FileInfo *dirFilesIcon = NULL;
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Internal Module Functions Definition
|
// Internal Module Functions Definition
|
||||||
@ -143,25 +159,28 @@ static char **ReadDirectoryFiles(const char *dir, int *filesCount, char *filterE
|
|||||||
|
|
||||||
#if defined(USE_CUSTOM_LISTVIEW_FILEINFO)
|
#if defined(USE_CUSTOM_LISTVIEW_FILEINFO)
|
||||||
// List View control for files info with extended parameters
|
// List View control for files info with extended parameters
|
||||||
static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *focus, int *scrollIndex, int active)
|
static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *focus, int *scrollIndex, int active);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
// Module Functions Definition
|
// Module Functions Definition
|
||||||
//----------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------
|
||||||
GuiFileDialogState InitGuiFileDialog(void)
|
GuiFileDialogState InitGuiFileDialog(int width, int height, const char *initPath, bool active)
|
||||||
{
|
{
|
||||||
GuiFileDialogState state = { 0 };
|
GuiFileDialogState state = { 0 };
|
||||||
|
|
||||||
state.position = (Vector2){ GetScreenWidth()/2 - 480/2, GetScreenHeight()/2 - 305/2 };
|
// Default dialog size is 440x310
|
||||||
|
state.size.x = width == -1 ? 440 : width;
|
||||||
state.fileDialogActive = false;
|
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.dirPathEditMode = false;
|
||||||
|
|
||||||
state.filesListActive = -1;
|
state.filesListActive = -1;
|
||||||
state.prevFilesListActive = state.filesListActive;
|
state.prevFilesListActive = state.filesListActive;
|
||||||
state.filesListScrollIndex = 0;
|
state.filesListScrollIndex = 0;
|
||||||
|
|
||||||
state.fileNameEditMode = false;
|
state.fileNameEditMode = false;
|
||||||
|
|
||||||
state.SelectFilePressed = false;
|
state.SelectFilePressed = false;
|
||||||
@ -169,58 +188,91 @@ GuiFileDialogState InitGuiFileDialog(void)
|
|||||||
|
|
||||||
state.fileTypeActive = 0;
|
state.fileTypeActive = 0;
|
||||||
|
|
||||||
|
strcpy(state.fileNameText, "\0");
|
||||||
|
|
||||||
// Custom variables initialization
|
// Custom variables initialization
|
||||||
strcpy(state.dirPathText, GetWorkingDirectory());
|
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.dirPathTextCopy, state.dirPathText);
|
||||||
|
strcpy(state.fileNameTextCopy, state.fileNameText);
|
||||||
|
|
||||||
strcpy(state.filterExt, "all");
|
strcpy(state.filterExt, "all");
|
||||||
|
|
||||||
state.dirFilesCount = 0;
|
state.dirFilesCount = 0;
|
||||||
state.dirFiles = NULL; // NOTE: Loaded lazily on window active
|
state.dirFiles = NULL; // NOTE: Loaded lazily on window active
|
||||||
|
|
||||||
strcpy(state.fileNameText, "\0");
|
|
||||||
strcpy(state.fileNameTextCopy, state.fileNameText);
|
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read files in new path
|
||||||
|
static void FD_RELOAD_DIRPATH(GuiFileDialogState *state)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < state->dirFilesCount; i++) RL_FREE(state->dirFiles[i]);
|
||||||
|
RL_FREE(state->dirFiles);
|
||||||
|
|
||||||
|
state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
|
||||||
|
state->itemFocused = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update and draw file dialog
|
||||||
void GuiFileDialog(GuiFileDialogState *state)
|
void GuiFileDialog(GuiFileDialogState *state)
|
||||||
{
|
{
|
||||||
if (state->fileDialogActive)
|
if (state->fileDialogActive)
|
||||||
{
|
{
|
||||||
|
const int winWidth = state->size.x;
|
||||||
|
const int winHeight = state->size.y;
|
||||||
|
|
||||||
// Load dirFilesIcon and state->dirFiles lazily on windows open
|
// Load dirFilesIcon and state->dirFiles lazily on windows open
|
||||||
// NOTE: they are automatically unloaded at fileDialog closing
|
// NOTE: they are automatically unloaded at fileDialog closing
|
||||||
//------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------
|
||||||
if (dirFilesIcon == NULL)
|
if (dirFilesIcon == NULL)
|
||||||
{
|
{
|
||||||
dirFilesIcon = (char **)RL_MALLOC(MAX_DIRECTORY_FILES*sizeof(char *)); // Max files to read
|
dirFilesIcon = (FileInfo *)RL_MALLOC(MAX_DIRECTORY_FILES*sizeof(FileInfo)); // Max files to read
|
||||||
for (int i = 0; i < MAX_DIRECTORY_FILES; i++) dirFilesIcon[i] = (char *)calloc(MAX_DIR_PATH_LENGTH, 1); // Max file name length
|
for (int i = 0; i < MAX_DIRECTORY_FILES; i++) dirFilesIcon[i] = (char *)calloc(MAX_DIR_PATH_LENGTH, 1); // Max file name length
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->dirFiles == NULL) state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
|
if (state->dirFiles == NULL)
|
||||||
|
{
|
||||||
|
state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
|
||||||
|
|
||||||
|
for(int f = 0; f < state->dirFilesCount; f++)
|
||||||
|
{
|
||||||
|
if (strcmp(state->fileNameText, state->dirFiles[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));
|
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, 480, 310 }, "#198#Select File Dialog");
|
state->fileDialogActive = !GuiWindowBox((Rectangle){ state->position.x + 0, state->position.y + 0, winWidth, winHeight }, "#198#LuaJIT | Select File Dialog");
|
||||||
|
|
||||||
if (GuiButton((Rectangle){ state->position.x + 430, state->position.y + 35, 40, 25 }, "< .."))
|
if (GuiButton((Rectangle){ state->position.x + winWidth - 50, state->position.y + 35, 40, 25 }, "< .."))// || IsKeyReleased(KEY_DPAD_Y))
|
||||||
{
|
{
|
||||||
// Move dir path one level up
|
// Move dir path one level up
|
||||||
strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText));
|
strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText));
|
||||||
|
|
||||||
// RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles())
|
// RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles())
|
||||||
for (int i = 0; i < state->dirFilesCount; i++) RL_FREE(state->dirFiles[i]);
|
FD_RELOAD_DIRPATH(state);
|
||||||
RL_FREE(state->dirFiles);
|
|
||||||
|
|
||||||
// Read files in the new path
|
|
||||||
state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
|
|
||||||
|
|
||||||
state->filesListActive = -1;
|
state->filesListActive = -1;
|
||||||
strcpy(state->fileNameText, "\0");
|
strcpy(state->fileNameText, "\0");
|
||||||
strcpy(state->fileNameTextCopy, state->fileNameText);
|
strcpy(state->fileNameTextCopy, state->fileNameText);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GuiTextBox((Rectangle){ state->position.x + 10, state->position.y + 35, 410, 25 }, state->dirPathText, 256, state->dirPathEditMode))
|
if (GuiTextBox((Rectangle){ state->position.x + 10, state->position.y + 35, winWidth - 65, 25 }, state->dirPathText, 256, state->dirPathEditMode))
|
||||||
{
|
{
|
||||||
if (state->dirPathEditMode)
|
if (state->dirPathEditMode)
|
||||||
{
|
{
|
||||||
@ -228,51 +280,48 @@ void GuiFileDialog(GuiFileDialogState *state)
|
|||||||
if (DirectoryExists(state->dirPathText))
|
if (DirectoryExists(state->dirPathText))
|
||||||
{
|
{
|
||||||
// RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles())
|
// RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles())
|
||||||
for (int i = 0; i < state->dirFilesCount; i++) RL_FREE(state->dirFiles[i]);
|
FD_RELOAD_DIRPATH(state);
|
||||||
RL_FREE(state->dirFiles);
|
|
||||||
|
|
||||||
// Read files in new path
|
|
||||||
state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
|
|
||||||
|
|
||||||
strcpy(state->dirPathTextCopy, state->dirPathText);
|
strcpy(state->dirPathTextCopy, state->dirPathText);
|
||||||
}
|
}
|
||||||
else strcpy(state->dirPathText, state->dirPathTextCopy);
|
else strcpy(state->dirPathText, state->dirPathTextCopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
state->dirPathEditMode = !state->dirPathEditMode;
|
state->dirPathEditMode = !state->dirPathEditMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
int prevTextAlignment = GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT);
|
int prevTextAlignment = GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT);
|
||||||
int prevElementsHeight = GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
|
int prevElementsHeight = GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
|
||||||
GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
|
GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, GUI_TEXT_ALIGN_LEFT);
|
||||||
GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 24);
|
GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 24);
|
||||||
|
|
||||||
// TODO: ListViewElements should be aligned left
|
// TODO: ListViewElements should be aligned left
|
||||||
state->filesListActive = GuiListViewEx((Rectangle){ state->position.x + 10, state->position.y + 70, 460, 164 }, (const char **)dirFilesIcon, state->dirFilesCount, NULL, &state->filesListScrollIndex, state->filesListActive);
|
# 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->dirFilesCount, &state->itemFocused, &state->filesListScrollIndex, state->filesListActive);
|
||||||
|
# else
|
||||||
|
state->filesListActive = GuiListViewEx((Rectangle){ state->position.x + 10, state->position.y + 70, winWidth - 20, winHeight - 135 }, (const char**)dirFilesIcon, state->dirFilesCount, &state->itemFocused, &state->filesListScrollIndex, state->filesListActive);
|
||||||
|
# endif
|
||||||
GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, prevTextAlignment);
|
GuiSetStyle(LISTVIEW, TEXT_ALIGNMENT, prevTextAlignment);
|
||||||
GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, prevElementsHeight);
|
GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, prevElementsHeight);
|
||||||
|
|
||||||
if ((state->filesListActive >= 0) && (state->filesListActive != state->prevFilesListActive))
|
if ((state->filesListActive >= 0) && (state->filesListActive != state->prevFilesListActive))
|
||||||
|
//&& (IsMouseButtonPressed(MOUSE_LEFT_BUTTON) || IsKeyPressed(KEY_ENTER) || IsKeyPressed(KEY_DPAD_A)))
|
||||||
{
|
{
|
||||||
strcpy(state->fileNameText, state->dirFiles[state->filesListActive]);
|
strcpy(state->fileNameText, state->dirFiles[state->filesListActive]);
|
||||||
|
|
||||||
if (DirectoryExists(TextFormat("%s\\%s", state->dirPathText, state->fileNameText)))
|
if (DirectoryExists(TextFormat("%s/%s", state->dirPathText, state->fileNameText)))
|
||||||
{
|
{
|
||||||
if (TextIsEqual(state->fileNameText, "..")) strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText));
|
if (TextIsEqual(state->fileNameText, "..")) strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText));
|
||||||
else strcpy(state->dirPathText, TextFormat("%s\\%s", state->dirPathText, state->fileNameText));
|
else strcpy(state->dirPathText, TextFormat("%s/%s", strcmp(state->dirPathText, "/")==0 ? "" : state->dirPathText, state->fileNameText));
|
||||||
|
|
||||||
strcpy(state->dirPathTextCopy, state->dirPathText);
|
strcpy(state->dirPathTextCopy, state->dirPathText);
|
||||||
|
|
||||||
// RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles())
|
// RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles())
|
||||||
for (int i = 0; i < state->dirFilesCount; i++) RL_FREE(state->dirFiles[i]);
|
FD_RELOAD_DIRPATH(state);
|
||||||
RL_FREE(state->dirFiles);
|
|
||||||
|
|
||||||
// Read files in new path
|
|
||||||
state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
|
|
||||||
|
|
||||||
strcpy(state->dirPathTextCopy, state->dirPathText);
|
strcpy(state->dirPathTextCopy, state->dirPathText);
|
||||||
|
|
||||||
state->filesListActive = -1;
|
state->filesListActive = -1;
|
||||||
strcpy(state->fileNameText, "\0");
|
strcpy(state->fileNameText, "\0");
|
||||||
strcpy(state->fileNameTextCopy, state->fileNameText);
|
strcpy(state->fileNameTextCopy, state->fileNameText);
|
||||||
@ -280,12 +329,12 @@ void GuiFileDialog(GuiFileDialogState *state)
|
|||||||
|
|
||||||
state->prevFilesListActive = state->filesListActive;
|
state->prevFilesListActive = state->filesListActive;
|
||||||
}
|
}
|
||||||
|
|
||||||
GuiLabel((Rectangle){ state->position.x + 10, state->position.y + 245, 68, 25 }, "File name:");
|
GuiLabel((Rectangle){ state->position.x + 10, state->position.y + winHeight - 60, 68, 25 }, "File name:");
|
||||||
|
|
||||||
if (GuiTextBox((Rectangle){ state->position.x + 75, state->position.y + 245, 275, 25 }, state->fileNameText, 128, state->fileNameEditMode))
|
if (GuiTextBox((Rectangle){ state->position.x + 75, state->position.y + winHeight - 60, winWidth - 200, 25 }, state->fileNameText, 128, state->fileNameEditMode))
|
||||||
{
|
{
|
||||||
if (state->fileNameText)
|
if (*state->fileNameText)
|
||||||
{
|
{
|
||||||
// Verify if a valid filename has been introduced
|
// Verify if a valid filename has been introduced
|
||||||
if (FileExists(TextFormat("%s/%s", state->dirPathText, state->fileNameText)))
|
if (FileExists(TextFormat("%s/%s", state->dirPathText, state->fileNameText)))
|
||||||
@ -301,37 +350,45 @@ void GuiFileDialog(GuiFileDialogState *state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strcpy(state->fileNameText, state->fileNameTextCopy);
|
strcpy(state->fileNameText, state->fileNameTextCopy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state->fileNameEditMode = !state->fileNameEditMode;
|
state->fileNameEditMode = !state->fileNameEditMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->fileTypeActive = GuiComboBox((Rectangle){ state->position.x + 75, state->position.y + 275, 275, 25 }, "All files", state->fileTypeActive);
|
state->fileTypeActive = GuiComboBox((Rectangle){ state->position.x + 75, state->position.y + winHeight - 30, winWidth - 200, 25 }, "All files", state->fileTypeActive);
|
||||||
GuiLabel((Rectangle){ state->position.x + 10, state->position.y + 275, 68, 25 }, "File filter:");
|
GuiLabel((Rectangle){ state->position.x + 10, state->position.y + winHeight - 30, 68, 25 }, "File filter:");
|
||||||
|
|
||||||
state->SelectFilePressed = GuiButton((Rectangle){ state->position.x + 360, state->position.y + 245, 110, 25 }, "Select");
|
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;
|
if (state->SelectFilePressed) state->fileDialogActive = false;
|
||||||
|
|
||||||
if (GuiButton((Rectangle){ state->position.x + 360, state->position.y + 275, 110, 25 }, "Cancel")) 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!
|
// File dialog has been closed!
|
||||||
if (!state->fileDialogActive)
|
if (!state->fileDialogActive)
|
||||||
{
|
{
|
||||||
// RL_FREE dirFiles memory
|
// RL_FREE dirFiles memory
|
||||||
for (int i = 0; i < state->dirFilesCount; i++)
|
for (int i = 0; i < state->dirFilesCount; i++)
|
||||||
{
|
{
|
||||||
RL_FREE(state->dirFiles[i]);
|
RL_FREE(state->dirFiles[i]);
|
||||||
RL_FREE(dirFilesIcon[i]);
|
RL_FREE(dirFilesIcon[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
RL_FREE(state->dirFiles);
|
RL_FREE(state->dirFiles);
|
||||||
RL_FREE(dirFilesIcon);
|
RL_FREE(dirFilesIcon);
|
||||||
|
|
||||||
dirFilesIcon = NULL;
|
dirFilesIcon = NULL;
|
||||||
state->dirFiles = NULL;
|
state->dirFiles = NULL;
|
||||||
}
|
}
|
||||||
@ -339,35 +396,81 @@ void GuiFileDialog(GuiFileDialogState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read all filenames from directory (supported file types)
|
// Read all filenames from directory (supported file types)
|
||||||
|
static inline int _file_comp(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);
|
||||||
|
}
|
||||||
static char **ReadDirectoryFiles(const char *dir, int *filesCount, char *filterExt)
|
static char **ReadDirectoryFiles(const char *dir, int *filesCount, char *filterExt)
|
||||||
{
|
{
|
||||||
int validFilesCount = 0;
|
int validFilesCount = 0;
|
||||||
char **validFiles = (char **)RL_MALLOC(MAX_DIRECTORY_FILES*sizeof(char *)); // Max files to read
|
char **validFiles = (char **)RL_MALLOC(MAX_DIRECTORY_FILES*sizeof(char *)); // Max files to read
|
||||||
for (int i = 0; i < MAX_DIRECTORY_FILES; i++) validFiles[i] = (char *)RL_MALLOC(MAX_DIR_PATH_LENGTH); // Max file name length
|
for (int i = 0; i < MAX_DIRECTORY_FILES; i++) validFiles[i] = (char *)RL_MALLOC(MAX_DIR_PATH_LENGTH); // Max file name length
|
||||||
|
|
||||||
int filterExtCount = 0;
|
int filterExtCount = 0;
|
||||||
const char **extensions = GuiTextSplit(filterExt, &filterExtCount, NULL);
|
const char **extensions = GuiTextSplit(filterExt, &filterExtCount, NULL);
|
||||||
bool filterExtensions = true;
|
bool filterExtensions = true;
|
||||||
|
|
||||||
int dirFilesCount = 0;
|
int dirFilesCount = 0;
|
||||||
char **files = GetDirectoryFiles(dir, &dirFilesCount);
|
char **files = GetDirectoryFiles(dir, &dirFilesCount);
|
||||||
|
|
||||||
|
// Sort files and directories: dir by name + files by name
|
||||||
|
// https://en.wikibooks.org/wiki/Algorithm_Implementation/Sorting/Quicksort#C
|
||||||
|
if (dirFilesCount > 1)
|
||||||
|
{
|
||||||
|
const int MAX = 64;
|
||||||
|
unsigned int left = 0, stack[MAX], pos = 0, seed = rand(), len = dirFilesCount;
|
||||||
|
|
||||||
|
for ( ; ; )
|
||||||
|
{
|
||||||
|
for (; left+1 < len; len++) /* sort left to len-1 */
|
||||||
|
{
|
||||||
|
if (pos == MAX) len = stack[pos = 0]; /* stack overflow, reset */
|
||||||
|
char *pivot = files[left+seed%(len-left)]; /* pick random pivot */
|
||||||
|
seed = seed*69069+1; /* next pseudorandom number */
|
||||||
|
stack[pos++] = len; /* sort right part later */
|
||||||
|
|
||||||
|
for (unsigned int right = left-1; ; ) /* inner loop: partitioning */
|
||||||
|
{
|
||||||
|
while (_file_comp(files[++right], pivot, dir) < 0);/* look for greater element */
|
||||||
|
while (_file_comp(pivot, files[--len], dir) < 0); /* look for smaller element */
|
||||||
|
if (right >= len) break; /* partition point found? */
|
||||||
|
char *temp = files[right];
|
||||||
|
files[right] = files[len]; /* the only swap */
|
||||||
|
files[len] = temp;
|
||||||
|
} /* partitioned, continue left part */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pos == 0) break; /* stack empty? */
|
||||||
|
left = len; /* left to right is sorted */
|
||||||
|
len = stack[--pos]; /* get next range to sort */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (TextIsEqual(extensions[0], "all")) filterExtensions = false;
|
if (TextIsEqual(extensions[0], "all")) filterExtensions = false;
|
||||||
|
|
||||||
for (int i = 0; (i < dirFilesCount) && (validFilesCount < MAX_DIRECTORY_FILES); i++)
|
for (int i = 0; (i < dirFilesCount) && (validFilesCount < MAX_DIRECTORY_FILES); i++)
|
||||||
{
|
{
|
||||||
if (TextIsEqual(files[i], ".")) continue;
|
if (TextIsEqual(files[i], ".")) continue;
|
||||||
|
|
||||||
if (!filterExtensions)
|
if (!filterExtensions)
|
||||||
{
|
{
|
||||||
strcpy(validFiles[validFilesCount], files[i]);
|
strncpy(validFiles[validFilesCount], files[i], MAX_DIR_PATH_LENGTH);
|
||||||
|
|
||||||
// Only filter files by extensions, directories should be available
|
// Only filter files by extensions, directories should be available
|
||||||
if (DirectoryExists(TextFormat("%s\\%s", dir, files[i]))) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 1, files[i]));
|
if (DirectoryExists(TextFormat("%s/%s", dir, files[i]))) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 1, files[i]));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO: Assign custom filetype icons depending on file extension (image, audio, text, video, models...)
|
// TODO: Assign custom filetype icons depending on file extension (image, audio, text, video, models...)
|
||||||
|
|
||||||
if (IsFileExtension(files[i], ".png")) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 12, files[i]));
|
if (IsFileExtension(files[i], ".png")) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 12, files[i]));
|
||||||
else strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 10, files[i]));
|
else strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 10, files[i]));
|
||||||
}
|
}
|
||||||
@ -386,17 +489,15 @@ static char **ReadDirectoryFiles(const char *dir, int *filesCount, char *filterE
|
|||||||
|
|
||||||
if (IsFileExtension(files[i], ".png")) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 12, files[i]));
|
if (IsFileExtension(files[i], ".png")) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 12, files[i]));
|
||||||
else strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 10, files[i]));
|
else strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 10, files[i]));
|
||||||
|
|
||||||
validFilesCount++;
|
validFilesCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Sort files and directories: dir by name + files by name
|
|
||||||
|
|
||||||
ClearDirectoryFiles();
|
ClearDirectoryFiles();
|
||||||
|
|
||||||
*filesCount = validFilesCount;
|
*filesCount = validFilesCount;
|
||||||
return validFiles;
|
return validFiles;
|
||||||
}
|
}
|
||||||
@ -408,23 +509,23 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
|
|||||||
GuiControlState state = guiState;
|
GuiControlState state = guiState;
|
||||||
int itemFocused = (focus == NULL)? -1 : *focus;
|
int itemFocused = (focus == NULL)? -1 : *focus;
|
||||||
int itemSelected = active;
|
int itemSelected = active;
|
||||||
|
|
||||||
// Check if we need a scroll bar
|
// Check if we need a scroll bar
|
||||||
bool useScrollBar = false;
|
bool useScrollBar = false;
|
||||||
if ((GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING))*count > bounds.height) useScrollBar = true;
|
if ((GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING))*count > bounds.height) useScrollBar = true;
|
||||||
|
|
||||||
// Define base item rectangle [0]
|
// Define base item rectangle [0]
|
||||||
Rectangle itemBounds = { 0 };
|
Rectangle itemBounds = { 0 };
|
||||||
itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING);
|
itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING);
|
||||||
itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
|
itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
|
||||||
itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) - GuiGetStyle(DEFAULT, BORDER_WIDTH);
|
itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) - GuiGetStyle(DEFAULT, BORDER_WIDTH);
|
||||||
itemBounds.height = GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT);
|
itemBounds.height = GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT);
|
||||||
if (useScrollBar) itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH);
|
if (useScrollBar) itemBounds.width -= GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH);
|
||||||
|
|
||||||
// Get items on the list
|
// Get items on the list
|
||||||
int visibleItems = bounds.height/(GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING));
|
int visibleItems = bounds.height/(GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING));
|
||||||
if (visibleItems > count) visibleItems = count;
|
if (visibleItems > count) visibleItems = count;
|
||||||
|
|
||||||
int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex;
|
int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex;
|
||||||
if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0;
|
if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0;
|
||||||
int endIndex = startIndex + visibleItems;
|
int endIndex = startIndex + visibleItems;
|
||||||
@ -434,12 +535,12 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
|
|||||||
if ((state != GUI_STATE_DISABLED) && !guiLocked)
|
if ((state != GUI_STATE_DISABLED) && !guiLocked)
|
||||||
{
|
{
|
||||||
Vector2 mousePoint = GetMousePosition();
|
Vector2 mousePoint = GetMousePosition();
|
||||||
|
|
||||||
// Check mouse inside list view
|
// Check mouse inside list view
|
||||||
if (CheckCollisionPointRec(mousePoint, bounds))
|
if (CheckCollisionPointRec(mousePoint, bounds))
|
||||||
{
|
{
|
||||||
state = GUI_STATE_FOCUSED;
|
state = GUI_STATE_FOCUSED;
|
||||||
|
|
||||||
// Check focused and selected item
|
// Check focused and selected item
|
||||||
for (int i = 0; i < visibleItems; i++)
|
for (int i = 0; i < visibleItems; i++)
|
||||||
{
|
{
|
||||||
@ -449,16 +550,16 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
|
|||||||
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) itemSelected = startIndex + i;
|
if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) itemSelected = startIndex + i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update item rectangle y position for next item
|
// Update item rectangle y position for next item
|
||||||
itemBounds.y += (GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING));
|
itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useScrollBar)
|
if (useScrollBar)
|
||||||
{
|
{
|
||||||
int wheelMove = GetMouseWheelMove();
|
int wheelMove = GetMouseWheelMove();
|
||||||
startIndex -= wheelMove;
|
startIndex -= wheelMove;
|
||||||
|
|
||||||
if (startIndex < 0) startIndex = 0;
|
if (startIndex < 0) startIndex = 0;
|
||||||
else if (startIndex > (count - visibleItems)) startIndex = count - visibleItems;
|
else if (startIndex > (count - visibleItems)) startIndex = count - visibleItems;
|
||||||
|
|
||||||
@ -467,19 +568,19 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else itemFocused = -1;
|
else itemFocused = -1;
|
||||||
|
|
||||||
// Reset item rectangle y to [0]
|
// Reset item rectangle y to [0]
|
||||||
itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
|
itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
// Draw control
|
// Draw control
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
DrawRectangleRec(bounds, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background
|
DrawRectangleRec(bounds, GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR))); // Draw background
|
||||||
DrawRectangleLinesEx(bounds, GuiGetStyle(DEFAULT, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER + state*3)), guiAlpha));
|
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
|
// TODO: Draw list view header with file sections: icon+name | size | type | modTime
|
||||||
|
|
||||||
// Draw visible items
|
// Draw visible items
|
||||||
for (int i = 0; i < visibleItems; i++)
|
for (int i = 0; i < visibleItems; i++)
|
||||||
{
|
{
|
||||||
@ -490,9 +591,9 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
|
|||||||
DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)), guiAlpha));
|
DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_DISABLED)), guiAlpha));
|
||||||
DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_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
|
// 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));
|
GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_DISABLED)), guiAlpha));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -502,7 +603,7 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
|
|||||||
// Draw item selected
|
// Draw item selected
|
||||||
DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)), guiAlpha));
|
DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_PRESSED)), guiAlpha));
|
||||||
DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_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));
|
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)
|
else if ((startIndex + i) == itemFocused)
|
||||||
@ -510,7 +611,7 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
|
|||||||
// Draw item focused
|
// Draw item focused
|
||||||
DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)), guiAlpha));
|
DrawRectangleRec(itemBounds, Fade(GetColor(GuiGetStyle(LISTVIEW, BASE_COLOR_FOCUSED)), guiAlpha));
|
||||||
DrawRectangleLinesEx(itemBounds, GuiGetStyle(LISTVIEW, BORDER_WIDTH), Fade(GetColor(GuiGetStyle(LISTVIEW, BORDER_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));
|
GuiDrawText(files[startIndex + i].name, GetTextBounds(DEFAULT, itemBounds), GuiGetStyle(LISTVIEW, TEXT_ALIGNMENT), Fade(GetColor(GuiGetStyle(LISTVIEW, TEXT_COLOR_FOCUSED)), guiAlpha));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -521,36 +622,36 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update item rectangle y position for next item
|
// Update item rectangle y position for next item
|
||||||
itemBounds.y += (GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT) + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING));
|
itemBounds.y += (GuiGetStyle(LISTVIEW, LIST_ITEMS_HEIGHT) + GuiGetStyle(LISTVIEW, LIST_ITEMS_PADDING));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (useScrollBar)
|
if (useScrollBar)
|
||||||
{
|
{
|
||||||
Rectangle scrollBarBounds = {
|
Rectangle scrollBarBounds = {
|
||||||
bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
|
bounds.x + bounds.width - GuiGetStyle(LISTVIEW, BORDER_WIDTH) - GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
|
||||||
bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
|
bounds.y + GuiGetStyle(LISTVIEW, BORDER_WIDTH), (float)GuiGetStyle(LISTVIEW, SCROLLBAR_WIDTH),
|
||||||
bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH)
|
bounds.height - 2*GuiGetStyle(DEFAULT, BORDER_WIDTH)
|
||||||
};
|
};
|
||||||
|
|
||||||
// Calculate percentage of visible items and apply same percentage to scrollbar
|
// Calculate percentage of visible items and apply same percentage to scrollbar
|
||||||
float percentVisible = (float)(endIndex - startIndex)/count;
|
float percentVisible = (float)(endIndex - startIndex)/count;
|
||||||
float sliderSize = bounds.height*percentVisible;
|
float sliderSize = bounds.height*percentVisible;
|
||||||
|
|
||||||
int prevSliderSize = GuiGetStyle(SCROLLBAR, SLIDER_SIZE); // Save default slider size
|
int prevSliderSize = GuiGetStyle(SCROLLBAR, SLIDER_WIDTH); // Save default slider size
|
||||||
int prevScrollSpeed = GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed
|
int prevScrollSpeed = GuiGetStyle(SCROLLBAR, SCROLL_SPEED); // Save default scroll speed
|
||||||
GuiSetStyle(SCROLLBAR, SLIDER_SIZE, sliderSize); // Change slider size
|
GuiSetStyle(SCROLLBAR, SLIDER_WIDTH, sliderSize); // Change slider size
|
||||||
GuiSetStyle(SCROLLBAR, SCROLL_SPEED, count - visibleItems); // Change scroll speed
|
GuiSetStyle(SCROLLBAR, SCROLL_SPEED, count - visibleItems); // Change scroll speed
|
||||||
|
|
||||||
startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems);
|
startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems);
|
||||||
|
|
||||||
GuiSetStyle(SCROLLBAR, SCROLL_SPEED, prevScrollSpeed); // Reset scroll speed to default
|
GuiSetStyle(SCROLLBAR, SCROLL_SPEED, prevScrollSpeed); // Reset scroll speed to default
|
||||||
GuiSetStyle(SCROLLBAR, SLIDER_SIZE, prevSliderSize); // Reset slider size to default
|
GuiSetStyle(SCROLLBAR, SLIDER_WIDTH, prevSliderSize); // Reset slider size to default
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------
|
//--------------------------------------------------------------------
|
||||||
|
|
||||||
if (focus != NULL) *focus = itemFocused;
|
if (focus != NULL) *focus = itemFocused;
|
||||||
if (scrollIndex != NULL) *scrollIndex = startIndex;
|
if (scrollIndex != NULL) *scrollIndex = startIndex;
|
||||||
|
|
||||||
return itemSelected;
|
return itemSelected;
|
||||||
}
|
}
|
||||||
#endif // USE_CUSTOM_LISTVIEW_FILEINFO
|
#endif // USE_CUSTOM_LISTVIEW_FILEINFO
|
||||||
|
|||||||
Reference in New Issue
Block a user