Procházet zdrojové kódy

Review gui_file_dialog with proposed improvements

Proposed improvements in: https://github.com/raysan5/raylib/issues/1101
raysan5 před 5 roky
rodič
revize
7f4794c31d

+ 10 - 10
examples/custom_file_dialog/custom_file_dialog.c

@@ -35,17 +35,17 @@ int main()
     //---------------------------------------------------------------------------------------
     int screenWidth = 800;
     int screenHeight = 560;
-    
+
     InitWindow(screenWidth, screenHeight, "raygui - custom modal dialog");
     SetExitKey(0);
 
     // Custom file dialog
-    GuiFileDialogState fileDialogState = InitGuiFileDialog();
+    GuiFileDialogState fileDialogState = InitGuiFileDialog(420, 310, GetWorkingDirectory(), false);
 
     bool exitWindow = false;
 
     char fileNameToLoad[512] = { 0 };
-    
+
     Texture texture = { 0 };
 
     SetTargetFPS(60);
@@ -57,7 +57,7 @@ int main()
         // Update
         //----------------------------------------------------------------------------------
         exitWindow = WindowShouldClose();
-        
+
         if (fileDialogState.SelectFilePressed)
         {
             // Load image file (if supported extension)
@@ -67,7 +67,7 @@ int main()
                 UnloadTexture(texture);
                 texture = LoadTexture(fileNameToLoad);
             }
-            
+
             fileDialogState.SelectFilePressed = false;
         }
         //----------------------------------------------------------------------------------
@@ -77,20 +77,20 @@ int main()
         BeginDrawing();
 
             ClearBackground(GetColor(GuiGetStyle(DEFAULT, BACKGROUND_COLOR)));
-            
+
             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);
- 
+
             DrawText(fileNameToLoad, 208, GetScreenHeight() - 20, 10, GRAY);
- 
+
             // raygui: controls drawing
             //----------------------------------------------------------------------------------
             if (fileDialogState.fileDialogActive) GuiLock();
 
             if (GuiButton((Rectangle){ 20, 20, 140, 30 }, GuiIconText(RICON_FILE_OPEN, "Open Image"))) fileDialogState.fileDialogActive = true;
-            
+
             GuiUnlock();
-            
+
             // GUI: Dialog Window
             //--------------------------------------------------------------------------------
             GuiFileDialog(&fileDialogState);

+ 231 - 130
examples/custom_file_dialog/gui_file_dialog.h

@@ -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:
 *       #define GUI_FILE_DIALOG_IMPLEMENTATION
@@ -16,13 +16,24 @@
 *       - DirectoryExists()
 *       - 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 project is proprietary and confidential unless the owner allows
-*   usage in any other form by expresely written permission.
+*   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.
 *
 **********************************************************************************************/
 
@@ -37,21 +48,23 @@
 
 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
@@ -59,10 +72,10 @@ typedef struct {
     int dirFilesCount;
 
     char filterExt[256];
-    
+
     char dirPathTextCopy[256];
     char fileNameTextCopy[256];
-    
+
     int prevFilesListActive;
 
 } GuiFileDialogState;
@@ -89,7 +102,7 @@ extern "C" {            // Prevents name mangling of functions
 //----------------------------------------------------------------------------------
 // Module Functions Declaration
 //----------------------------------------------------------------------------------
-GuiFileDialogState InitGuiFileDialog(void);
+GuiFileDialogState InitGuiFileDialog(int width, int height, const char *initPath, bool active);
 void GuiFileDialog(GuiFileDialogState *state);
 
 #ifdef __cplusplus
@@ -128,12 +141,15 @@ typedef struct FileInfo {
     int type;
     int icon;
 } FileInfo;
+#else
+// Filename only
+typedef char *FileInfo;
 #endif
 
 //----------------------------------------------------------------------------------
 // Global Variables Definition
 //----------------------------------------------------------------------------------
-char **dirFilesIcon = NULL;
+FileInfo *dirFilesIcon = NULL;
 
 //----------------------------------------------------------------------------------
 // Internal Module Functions Definition
@@ -143,25 +159,28 @@ static char **ReadDirectoryFiles(const char *dir, int *filesCount, char *filterE
 
 #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)
+static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *focus, int *scrollIndex, int active);
 #endif
 
 //----------------------------------------------------------------------------------
 // Module Functions Definition
 //----------------------------------------------------------------------------------
-GuiFileDialogState InitGuiFileDialog(void)
+GuiFileDialogState InitGuiFileDialog(int width, int height, const char *initPath, bool active)
 {
     GuiFileDialogState state = { 0 };
 
-    state.position = (Vector2){ GetScreenWidth()/2 - 480/2, GetScreenHeight()/2 - 305/2 };
-    
-    state.fileDialogActive = false;
+    // 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;
@@ -169,58 +188,91 @@ GuiFileDialogState InitGuiFileDialog(void)
 
     state.fileTypeActive = 0;
 
+    strcpy(state.fileNameText, "\0");
+
     // 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.fileNameTextCopy, state.fileNameText);
+
     strcpy(state.filterExt, "all");
 
     state.dirFilesCount = 0;
     state.dirFiles = NULL;      // NOTE: Loaded lazily on window active
-    
-    strcpy(state.fileNameText, "\0");
-    strcpy(state.fileNameTextCopy, state.fileNameText);
 
     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)
-{   
+{
     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 = (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
         }
-    
-        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));
-        state->fileDialogActive = !GuiWindowBox((Rectangle){ state->position.x + 0, state->position.y + 0, 480, 310 }, "#198#Select File Dialog");
-        
-        if (GuiButton((Rectangle){ state->position.x + 430, state->position.y + 35, 40, 25 }, "< .."))
+        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 + winWidth - 50, state->position.y + 35, 40, 25 }, "< .."))// || IsKeyReleased(KEY_DPAD_Y))
         {
             // Move dir path one level up
             strcpy(state->dirPathText, GetPrevDirectoryPath(state->dirPathText));
-            
+
             // RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles())
-            for (int i = 0; i < state->dirFilesCount; i++) RL_FREE(state->dirFiles[i]);
-            RL_FREE(state->dirFiles);
-            
-            // Read files in the new path
-            state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
-            
+            FD_RELOAD_DIRPATH(state);
+
             state->filesListActive = -1;
             strcpy(state->fileNameText, "\0");
             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)
             {
@@ -228,51 +280,48 @@ void GuiFileDialog(GuiFileDialogState *state)
                 if (DirectoryExists(state->dirPathText))
                 {
                     // RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles())
-                    for (int i = 0; i < state->dirFilesCount; i++) RL_FREE(state->dirFiles[i]);
-                    RL_FREE(state->dirFiles);
-                    
-                    // Read files in new path
-                    state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
-                    
+                    FD_RELOAD_DIRPATH(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, GUI_TEXT_ALIGN_LEFT);
         GuiSetStyle(LISTVIEW, LIST_ITEMS_HEIGHT, 24);
-        
+
         // 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, 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[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));
-                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);
-                
+
                 // RL_FREE previous dirFiles (reloaded by ReadDirectoryFiles())
-                for (int i = 0; i < state->dirFilesCount; i++) RL_FREE(state->dirFiles[i]);
-                RL_FREE(state->dirFiles);
-                
-                // Read files in new path
-                state->dirFiles = ReadDirectoryFiles(state->dirPathText, &state->dirFilesCount, state->filterExt);
-                
+                FD_RELOAD_DIRPATH(state);
+
                 strcpy(state->dirPathTextCopy, state->dirPathText);
-                
+
                 state->filesListActive = -1;
                 strcpy(state->fileNameText, "\0");
                 strcpy(state->fileNameTextCopy, state->fileNameText);
@@ -280,12 +329,12 @@ void GuiFileDialog(GuiFileDialogState *state)
 
             state->prevFilesListActive = state->filesListActive;
         }
-        
-        GuiLabel((Rectangle){ state->position.x + 10, state->position.y + 245, 68, 25 }, "File name:");
-        
-        if (GuiTextBox((Rectangle){ state->position.x + 75, state->position.y + 245, 275, 25 }, state->fileNameText, 128, state->fileNameEditMode)) 
+
+        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 + winHeight - 60, winWidth - 200, 25 }, state->fileNameText, 128, state->fileNameEditMode))
         {
-            if (state->fileNameText)
+            if (*state->fileNameText)
             {
                 // Verify if a valid filename has been introduced
                 if (FileExists(TextFormat("%s/%s", state->dirPathText, state->fileNameText)))
@@ -301,37 +350,45 @@ void GuiFileDialog(GuiFileDialogState *state)
                         }
                     }
                 }
-                else 
+                else
                 {
                     strcpy(state->fileNameText, state->fileNameTextCopy);
                 }
             }
-            
+
             state->fileNameEditMode = !state->fileNameEditMode;
         }
 
-        state->fileTypeActive = GuiComboBox((Rectangle){ state->position.x + 75, state->position.y + 275, 275, 25 }, "All files", state->fileTypeActive);
-        GuiLabel((Rectangle){ state->position.x + 10, state->position.y + 275, 68, 25 }, "File filter:");
-        
-        state->SelectFilePressed = GuiButton((Rectangle){ state->position.x + 360, state->position.y + 245, 110, 25 }, "Select");
-        
+        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 + 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;
-        
-        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!
         if (!state->fileDialogActive)
         {
             // 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(dirFilesIcon[i]);
             }
-            
+
             RL_FREE(state->dirFiles);
             RL_FREE(dirFilesIcon);
-            
+
             dirFilesIcon = NULL;
             state->dirFiles = NULL;
         }
@@ -339,35 +396,81 @@ void GuiFileDialog(GuiFileDialogState *state)
 }
 
 // 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)
 {
     int validFilesCount = 0;
     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
-    
+
     int filterExtCount = 0;
     const char **extensions = GuiTextSplit(filterExt, &filterExtCount, NULL);
     bool filterExtensions = true;
-    
+
     int dirFilesCount = 0;
     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;
 
     for (int i = 0; (i < dirFilesCount) && (validFilesCount < MAX_DIRECTORY_FILES); i++)
     {
         if (TextIsEqual(files[i], ".")) continue;
-        
+
         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
-            if (DirectoryExists(TextFormat("%s\\%s", dir, files[i]))) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 1, files[i]));
-            else 
+            if (DirectoryExists(TextFormat("%s/%s", dir, files[i]))) strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 1, files[i]));
+            else
             {
                 // 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]));
                 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]));
                     else strcpy(dirFilesIcon[validFilesCount], TextFormat("#%i#%s", 10, files[i]));
-                    
+
                     validFilesCount++;
                 }
             }
         }
     }
-    
-    // TODO: Sort files and directories: dir by name + files by name
 
     ClearDirectoryFiles();
-    
+
     *filesCount = validFilesCount;
     return validFiles;
 }
@@ -408,23 +509,23 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
     GuiControlState state = guiState;
     int itemFocused = (focus == NULL)? -1 : *focus;
     int itemSelected = active;
-    
+
     // Check if we need a scroll bar
     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]
     Rectangle itemBounds = { 0 };
-    itemBounds.x = bounds.x + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING);
-    itemBounds.y = bounds.y + GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) + GuiGetStyle(DEFAULT, BORDER_WIDTH);
-    itemBounds.width = bounds.width - 2*GuiGetStyle(LISTVIEW, ELEMENTS_PADDING) - GuiGetStyle(DEFAULT, BORDER_WIDTH);
-    itemBounds.height = GuiGetStyle(LISTVIEW, ELEMENTS_HEIGHT);
+    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, 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;
-    
+
     int startIndex = (scrollIndex == NULL)? 0 : *scrollIndex;
     if ((startIndex < 0) || (startIndex > (count - visibleItems))) startIndex = 0;
     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)
     {
         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++)
             {
@@ -449,16 +550,16 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
                     if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) itemSelected = startIndex + i;
                     break;
                 }
-                
+
                 // 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)
             {
                 int wheelMove = GetMouseWheelMove();
                 startIndex -= wheelMove;
-                    
+
                 if (startIndex < 0) startIndex = 0;
                 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;
-        
+
         // 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
     //--------------------------------------------------------------------
     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++)
     {
@@ -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));
                 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));
         }
         else
@@ -502,7 +603,7 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
                 // 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)
@@ -510,7 +611,7 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
                 // 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
@@ -521,36 +622,36 @@ static int GuiListViewFiles(Rectangle bounds, FileInfo *files, int count, int *f
         }
 
         // 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)
     {
-        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) 
+        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_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
-        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
 
         startIndex = GuiScrollBar(scrollBarBounds, startIndex, 0, count - visibleItems);
 
         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 (scrollIndex != NULL) *scrollIndex = startIndex;
-    
+
     return itemSelected;
 }
 #endif // USE_CUSTOM_LISTVIEW_FILEINFO