Skip to content

Commit cfa7838

Browse files
authored
Merge pull request #16 from aiekick/explorebykeys
Explorebykeys
2 parents 30ddac8 + 4d12d2c commit cfa7838

File tree

8 files changed

+140
-57
lines changed

8 files changed

+140
-57
lines changed

3rdparty/imgui

Submodule imgui updated 47 files

CustomImGuiFileDialogConfig.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,15 @@
44

55
//#define USE_IMGUI_TABLES
66

7+
#define USE_EXPLORATION_BY_KEYS
78
#include <GLFW/glfw3.h>
9+
// Up key for explore to the top
810
#define IGFD_KEY_UP GLFW_KEY_UP
11+
// Down key for explore to the bottom
912
#define IGFD_KEY_DOWN GLFW_KEY_DOWN
13+
// Enter key for open directory
1014
#define IGFD_KEY_ENTER GLFW_KEY_ENTER
15+
// BackSpace for comming back to the last directory
1116
#define IGFD_KEY_BACKSPACE GLFW_KEY_BACKSPACE
1217

1318
// widget

ImGuiFileDialog/ImGuiFileDialog.cpp

Lines changed: 81 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ namespace igfd
341341
//////////////////////////////////////////////////////////////////////////////////////////////////
342342
///// CUSTOM SELECTABLE (Flashing Support) ///////////////////////////////////////////////////////
343343
//////////////////////////////////////////////////////////////////////////////////////////////////
344-
344+
#ifdef USE_EXPLORATION_BY_KEYS
345345
bool ImGuiFileDialog::FlashableSelectable(const char* label, bool selected,
346346
ImGuiSelectableFlags flags, bool vFlashing, const ImVec2& size_arg)
347347
{
@@ -466,6 +466,7 @@ namespace igfd
466466
IMGUI_TEST_ENGINE_ITEM_INFO(id, label, window->DC.ItemFlags);
467467
return pressed;
468468
}
469+
#endif
469470

470471
//////////////////////////////////////////////////////////////////////////////////////////////////
471472
///// STANDARD DIALOG ////////////////////////////////////////////////////////////////////////////
@@ -882,8 +883,8 @@ namespace igfd
882883
#endif
883884
#endif
884885
size_t countRows = m_FilteredFileList.size();
885-
ImGuiListClipper clipper(countRows, ImGui::GetFrameHeight());
886-
for(int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
886+
ImGuiListClipper clipper(countRows, ImGui::GetTextLineHeightWithSpacing());
887+
for(int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++)
887888
{
888889
const FileInfoStruct& infos = m_FilteredFileList[i];
889890

@@ -915,12 +916,16 @@ namespace igfd
915916
#ifdef USE_IMGUI_TABLES
916917
selectableFlags |= ImGuiSelectableFlags_SpanAllColumns;
917918
#endif
919+
bool _selectablePressed = false;
920+
#ifdef USE_EXPLORATION_BY_KEYS
918921
LocateByInputKey();
919-
bool _selectablePressed = false;
920-
bool flashed = BeginFlashItem(i);
921-
_selectablePressed = FlashableSelectable(str.c_str(), selected, selectableFlags, flashed);
922+
bool flashed = BeginFlashItem(i);
923+
_selectablePressed = FlashableSelectable(str.c_str(), selected, selectableFlags, flashed);
922924
if (flashed)
923925
EndFlashItem();
926+
#else
927+
_selectablePressed = ImGui::Selectable(str.c_str(), selected, selectableFlags);
928+
#endif
924929
if (_selectablePressed)
925930
{
926931
if (infos.type == 'd')
@@ -968,9 +973,9 @@ namespace igfd
968973
}
969974
ImGui::EndTable();
970975
#endif
971-
976+
#ifdef USE_EXPLORATION_BY_KEYS
972977
ExploreWithkeys(); // outside of file list loop
973-
978+
#endif
974979
// changement de repertoire
975980
if (pathClick)
976981
{
@@ -1665,9 +1670,10 @@ namespace igfd
16651670
}
16661671
free(files);
16671672
}
1673+
1674+
SortFields(m_SortingField);
1675+
ApplyFilteringOnFileList();
16681676
}
1669-
SortFields(m_SortingField);
1670-
ApplyFilteringOnFileList();
16711677
}
16721678

16731679
void ImGuiFileDialog::SetCurrentDir(const std::string& vPath)
@@ -1939,57 +1945,75 @@ namespace igfd
19391945
////////////////////////////////////////////////////////////////////////////////////////////////
19401946

19411947
static size_t locateFileByInputChar_lastFileIdx = 0;
1948+
static char locateFileByInputChar_lastChar = 0;
1949+
static int locateFileByInputChar_InputQueueCharactersSize = 0;
1950+
static bool locateFileByInputChar_lastFound = false;
1951+
1952+
bool ImGuiFileDialog::LocateItem_Loop(char vC)
1953+
{
1954+
bool found = false;
1955+
1956+
for (size_t i = locateFileByInputChar_lastFileIdx; i < m_FilteredFileList.size(); i++)
1957+
{
1958+
if (m_FilteredFileList[i].fileName_optimized[0] == vC || // lower case search
1959+
m_FilteredFileList[i].fileName[0] == vC) // maybe upper case search
1960+
{
1961+
float p = (float)((double)i / (double)m_FilteredFileList.size()) * ImGui::GetScrollMaxY();
1962+
ImGui::SetScrollY(p);
1963+
found = true;
1964+
locateFileByInputChar_lastFound = true;
1965+
locateFileByInputChar_lastFileIdx = i;
1966+
StartFlashItem(locateFileByInputChar_lastFileIdx);
1967+
1968+
auto infos = &m_FilteredFileList[locateFileByInputChar_lastFileIdx];
1969+
1970+
if (infos->type == 'd')
1971+
{
1972+
if (!dlg_filters) // directory chooser
1973+
{
1974+
SelectFileName(*infos);
1975+
}
1976+
}
1977+
else
1978+
{
1979+
SelectFileName(*infos);
1980+
}
19421981

1982+
found = true;
1983+
1984+
break;
1985+
}
1986+
}
1987+
1988+
return found;
1989+
}
1990+
1991+
#ifdef USE_EXPLORATION_BY_KEYS
19431992
void ImGuiFileDialog::LocateByInputKey()
19441993
{
19451994
ImGuiContext& g = *GImGui;
1946-
if (!g.ActiveId && !m_FileList.empty())
1995+
if (!g.ActiveId && !m_FilteredFileList.empty())
19471996
{
19481997
// point by char
1949-
static char locateFileByInputChar_lastChar = 0;
1950-
static int locateFileByInputChar_InputQueueCharactersSize = 0;
19511998
if (!ImGui::GetIO().InputQueueCharacters.empty())
19521999
{
19532000
char c = ImGui::GetIO().InputQueueCharacters.back();
1954-
if (locateFileByInputChar_InputQueueCharactersSize != ImGui::GetIO().InputQueueCharacters.size())
2001+
if (locateFileByInputChar_InputQueueCharactersSize !=
2002+
ImGui::GetIO().InputQueueCharacters.size())
19552003
{
19562004
if (c == locateFileByInputChar_lastChar) // next file starting with same char until
19572005
{
1958-
if (locateFileByInputChar_lastFileIdx < m_FileList.size() - 1)
2006+
if (locateFileByInputChar_lastFileIdx < m_FilteredFileList.size() - 1)
19592007
locateFileByInputChar_lastFileIdx++;
19602008
else
19612009
locateFileByInputChar_lastFileIdx = 0;
19622010
}
1963-
else // new char
1964-
{
1965-
locateFileByInputChar_lastFileIdx = 0;
1966-
}
19672011

1968-
static bool locateFileByInputChar_lastFound = false;
1969-
bool found = false;
1970-
for (size_t i = locateFileByInputChar_lastFileIdx; i < m_FileList.size(); i++)
2012+
if (!LocateItem_Loop(c))
19712013
{
1972-
if (m_FileList[i].fileName_optimized[0] == c || // lower case search
1973-
m_FileList[i].fileName[0] == c) // maybe upper case search
1974-
{
1975-
float p = (float)((double)i / (double)m_FileList.size()) * ImGui::GetScrollMaxY();
1976-
ImGui::SetScrollY(p);
1977-
found = true;
1978-
locateFileByInputChar_lastFound = true;
1979-
locateFileByInputChar_lastFileIdx = i;
1980-
StartFlashItem(locateFileByInputChar_lastFileIdx);
1981-
break;
1982-
}
1983-
1984-
if (c == locateFileByInputChar_lastChar &&
1985-
locateFileByInputChar_lastFound &&
1986-
!found &&
1987-
i == m_FileList.size() - 1) //last item and not found => new loop
1988-
{
1989-
locateFileByInputChar_lastFileIdx = 0; // cyclic next file starting with same char until
1990-
i = 0;
1991-
locateFileByInputChar_lastFound = false;
1992-
}
2014+
// not found, loop again from 0 this time
2015+
locateFileByInputChar_lastFileIdx = 0;
2016+
LocateItem_Loop(c);
19932017
}
19942018

19952019
locateFileByInputChar_lastChar = c;
@@ -2002,24 +2026,24 @@ namespace igfd
20022026
void ImGuiFileDialog::ExploreWithkeys()
20032027
{
20042028
ImGuiContext& g = *GImGui;
2005-
if (!g.ActiveId && !m_FileList.empty())
2029+
if (!g.ActiveId && !m_FilteredFileList.empty())
20062030
{
20072031
// explore
20082032
bool exploreByKey = false;
20092033
bool enterInDirectory = false;
20102034
bool exitDirectory = false;
2011-
if (ImGui::IsKeyReleased(IGFD_KEY_UP))
2035+
if (ImGui::IsKeyPressed(IGFD_KEY_UP))
20122036
{
20132037
exploreByKey = true;
20142038
if (locateFileByInputChar_lastFileIdx > 0)
20152039
{
20162040
locateFileByInputChar_lastFileIdx--;
20172041
}
20182042
}
2019-
else if (ImGui::IsKeyReleased(IGFD_KEY_DOWN))
2043+
else if (ImGui::IsKeyPressed(IGFD_KEY_DOWN))
20202044
{
20212045
exploreByKey = true;
2022-
if (locateFileByInputChar_lastFileIdx < m_FileList.size() - 1)
2046+
if (locateFileByInputChar_lastFileIdx < m_FilteredFileList.size() - 1)
20232047
{
20242048
locateFileByInputChar_lastFileIdx++;
20252049
}
@@ -2037,11 +2061,11 @@ namespace igfd
20372061

20382062
if (exploreByKey)
20392063
{
2040-
float p = (float)((double)locateFileByInputChar_lastFileIdx / (double)m_FileList.size()) * ImGui::GetScrollMaxY();
2064+
float p = (float)((double)locateFileByInputChar_lastFileIdx / (double)m_FilteredFileList.size()) * ImGui::GetScrollMaxY();
20412065
ImGui::SetScrollY(p);
20422066
StartFlashItem(locateFileByInputChar_lastFileIdx);
20432067

2044-
auto infos = &m_FileList[locateFileByInputChar_lastFileIdx];
2068+
auto infos = &m_FilteredFileList[locateFileByInputChar_lastFileIdx];
20452069

20462070
if (infos->type == 'd')
20472071
{
@@ -2079,7 +2103,7 @@ namespace igfd
20792103
{
20802104
// changement de repertoire
20812105
SetPath(m_CurrentPath);
2082-
if (locateFileByInputChar_lastFileIdx > m_FileList.size() - 1)
2106+
if (locateFileByInputChar_lastFileIdx > m_FilteredFileList.size() - 1)
20832107
{
20842108
locateFileByInputChar_lastFileIdx = 0;
20852109
}
@@ -2111,7 +2135,7 @@ namespace igfd
21112135
if (m_FlashedItem == vIdx &&
21122136
std::abs(m_FlashAlpha - 0.0f) > 0.00001f)
21132137
{
2114-
m_FlashAlpha -= m_FlashAlphaStep;
2138+
m_FlashAlpha -= m_FlashAlphaAttenInSecs * ImGui::GetIO().DeltaTime;
21152139
if (m_FlashAlpha < 0.0f) m_FlashAlpha = 0.0f;
21162140

21172141
ImVec4 hov = ImGui::GetStyleColorVec4(ImGuiCol_HeaderHovered);
@@ -2127,5 +2151,11 @@ namespace igfd
21272151
{
21282152
ImGui::PopStyleColor();
21292153
}
2154+
2155+
void ImGuiFileDialog::SetFlashingAttenuationInSeconds(float vAttenValue)
2156+
{
2157+
m_FlashAlphaAttenInSecs = 1.0f / max(vAttenValue,0.01f);
2158+
}
2159+
#endif
21302160
}
21312161

ImGuiFileDialog/ImGuiFileDialog.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,13 @@ namespace igfd
6464
size_t fileSize = 0; // for sorting operations
6565
std::string formatedFileSize;
6666
std::string fileModifDate;
67-
6867
};
6968

7069
// old FilterInfosStruct
7170
struct FileExtentionInfosStruct
7271
{
7372
std::string icon;
7473
ImVec4 color = ImVec4(0, 0, 0, 0);
75-
7674
FileExtentionInfosStruct() { color = ImVec4(0, 0, 0, 0); }
7775
FileExtentionInfosStruct(const ImVec4& vColor, const std::string& vIcon = std::string())
7876
{
@@ -109,7 +107,7 @@ namespace igfd
109107

110108
enum SortingFieldEnum
111109
{
112-
FIELD_NONE=0,
110+
FIELD_NONE = 0,
113111
FIELD_FILENAME,
114112
FIELD_SIZE,
115113
FIELD_DATE
@@ -134,7 +132,7 @@ namespace igfd
134132
private: // flash when select by char
135133
size_t m_FlashedItem = 0;
136134
float m_FlashAlpha = 0.0f;
137-
float m_FlashAlphaStep = 0.01f; // fps display dependant
135+
float m_FlashAlphaAttenInSecs = 1.0f; // fps display dependant
138136

139137
public:
140138
static char FileNameBuffer[MAX_FILE_DIALOG_NAME_BUFFER];
@@ -210,6 +208,7 @@ namespace igfd
210208
const std::string& vFilePathName, const int& vCountSelectionMax = 1,
211209
UserDatas vUserDatas = 0);
212210

211+
public: // core
213212
bool FileDialog(const std::string& vKey, ImGuiWindowFlags vFlags = ImGuiWindowFlags_NoCollapse,
214213
ImVec2 vMinSize = ImVec2(0, 0), ImVec2 vMaxSize = ImVec2(FLT_MAX, FLT_MAX));
215214
void CloseDialog(const std::string& vKey);
@@ -246,13 +245,18 @@ namespace igfd
246245
private:
247246
void ApplyFilteringOnFileList();
248247

248+
#ifdef USE_EXPLORATION_BY_KEYS
249249
private: // file localization by input chat // widget flashing
250250
void LocateByInputKey();
251+
bool LocateItem_Loop(char vC);
251252
void ExploreWithkeys();
252253
static bool FlashableSelectable(const char* label, bool selected = false, ImGuiSelectableFlags flags = 0,
253254
bool vFlashing = false, const ImVec2& size = ImVec2(0, 0));
254255
void StartFlashItem(size_t vIdx);
255256
bool BeginFlashItem(size_t vIdx);
256257
void EndFlashItem();
258+
public:
259+
void SetFlashingAttenuationInSeconds(float vAttenValue);
260+
#endif
257261
};
258262
}

ImGuiFileDialog/ImGuiFileDialogConfig.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,16 @@
44

55
//#define USE_IMGUI_TABLES
66

7-
//#include <GLFW/glfw3.h>
7+
//#define USE_EXPLORATION_BY_KEYS
8+
// this mapping by default is for GLFW but you can use another
9+
//#include <GLFW/glfw3.h>
10+
// Up key for explore to the top
811
//#define IGFD_KEY_UP GLFW_KEY_UP
12+
// Down key for explore to the bottom
913
//#define IGFD_KEY_DOWN GLFW_KEY_DOWN
14+
// Enter key for open directory
1015
//#define IGFD_KEY_ENTER GLFW_KEY_ENTER
16+
// BackSpace for comming back to the last directory
1117
//#define IGFD_KEY_BACKSPACE GLFW_KEY_BACKSPACE
1218

1319
// widget

README.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ An example of the File Dialog integrated within the ImGui Demo App
1818
- Support of Modal/Standard dialog type
1919
- Support both Mode : File Chooser or Directory Chooser
2020
- Support filter collection / Custom filter name
21+
- Support files Exploring with keys : Up / Down / Enter (open dir) / Backspace (come back)
22+
- Support files Exploring by input char (case insensitive)
2123

2224
Use the Namespace igfd (for avoid conflict with variables, struct and class names)
2325

@@ -186,6 +188,28 @@ You can have tables display like that.
186188
187189
![alt text](doc/imgui_tables_branch.gif)
188190
191+
## Exploring by keys
192+
193+
you can activate this feature by uncomment : "#define USE_EXPLORATION_BY_KEYS"
194+
in you custom config file (CustomImGuiFileDialogConfig.h in this example)
195+
196+
you can also uncomment the next lines for define your keys :
197+
198+
* IGFD_KEY_UP => Up key for explore to the top
199+
* IGFD_KEY_DOWN => Down key for explore to the bottom
200+
* IGFD_KEY_ENTER => Enter key for open directory
201+
* IGFD_KEY_BACKSPACE => BackSpace for comming back to the last directory
202+
203+
you can also explore a file list by use the current key char.
204+
205+
![alt text](doc/explore_ny_keys.gif)
206+
207+
as you see the current item is flashed (by default for 1 sec)
208+
you can define the flashing life time by yourself with the function
209+
```cpp
210+
igfd::ImGuiFileDialog::Instance()->SetFlashingAttenuationInSeconds(1.0f);
211+
```
212+
189213
## How to Integrate ImGuiFileDialog in your porject
190214

191215
### ImGuiFileDialog require :

doc/explore_ny_keys.gif

1.94 MB
Loading

0 commit comments

Comments
 (0)