e8555c89 Andy McCall 1 month ago
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include " ImGuiFileDialog.h"
37
38
#ifdef __cplusplus
39
40
41
42
#include < cfloat>
43
#include < cstring>
44
#include < cstdarg>
45
#include < sstream>
46
#include < iomanip>
47
#include < ctime>
48
#include < memory>
49
#include < sys/stat.h>
50
#include < cstdio>
51
#include < cerrno>
52
53
54
static void RightAlignText ( const char * text , const char * maxWidthText )
55
{
56
auto maxWidth = ImGui:: CalcTextSize ( maxWidthText ) . x ;
57
auto actualWidth = ImGui:: CalcTextSize ( text ) . x ;
58
if ( auto spacing = maxWidth - actualWidth; spacing > 0.0f ) {
59
auto pos = ImGui:: GetCursorPosX ( ) ;
60
ImGui:: SetCursorPosX ( pos + spacing ) ;
61
}
62
ImGui:: TextUnformatted ( text ) ;
63
64
}
65
66
67
68
69
70
#ifdef USE_STD_FILESYSTEM
71
#include < filesystem>
72
#include < exception>
73
#endif
74
75
#ifdef __EMSCRIPTEN__
76
#include < emscripten.h>
77
#endif
78
79
#ifdef _MSC_VER
80
81
#define IGFD_DEBUG_BREAK \
82
if ( IsDebuggerPresent ( ) ) __debugbreak ( )
83
#else
84
#define IGFD_DEBUG_BREAK
85
#endif
86
87
#if defined (__WIN32__) || defined (WIN32) || defined (_WIN32) || defined (__WIN64__) || defined (WIN64) || defined (_WIN64) || defined (_MSC_VER)
88
#define _IGFD_WIN_
89
#define stat _stat
90
#define stricmp _stricmp
91
#include < cctype>
92
93
#ifdef USE_STD_FILESYSTEM
94
#include < windows.h>
95
#else
96
#include " dirent/dirent.h"
97
#endif
98
#define PATH_SEP ' \\ '
99
#ifndef PATH_MAX
100
#define PATH_MAX 260
101
#endif
102
#elif defined (__linux__) || defined (__FreeBSD__) || defined (__DragonFly__) || defined (__NetBSD__) || defined (__APPLE__) || defined (__EMSCRIPTEN__)
103
#define _IGFD_UNIX_
104
#define stricmp strcasecmp
105
#include < sys/types.h>
106
107
#ifndef USE_STD_FILESYSTEM
108
#include < dirent.h>
109
#endif
110
#define PATH_SEP ' /'
111
#endif
112
113
#include " imgui.h"
114
#include " imgui_internal.h"
115
116
117
#ifndef IM_TRUNC
118
#define IM_TRUNC IM_FLOOR
119
#endif
120
121
#include < cstdlib>
122
#include < algorithm>
123
#include < iostream>
124
125
126
127
128
129
#ifdef USE_THUMBNAILS
130
#ifndef DONT_DEFINE_AGAIN__STB_IMAGE_IMPLEMENTATION
131
#ifndef STB_IMAGE_IMPLEMENTATION
132
#define STB_IMAGE_IMPLEMENTATION
133
#endif
134
#endif
135
#include " stb/stb_image.h"
136
#ifndef DONT_DEFINE_AGAIN__STB_IMAGE_RESIZE_IMPLEMENTATION
137
#ifndef STB_IMAGE_RESIZE_IMPLEMENTATION
138
#define STB_IMAGE_RESIZE_IMPLEMENTATION
139
#endif
140
#endif
141
#include " stb/stb_image_resize.h"
142
#endif
143
144
145
#ifndef IS_FLOAT_DIFFERENT
146
#define IS_FLOAT_DIFFERENT ( a , b ) ( fabs ( ( a) - ( b) ) > FLT_EPSILON)
147
#endif
148
#ifndef IS_FLOAT_EQUAL
149
#define IS_FLOAT_EQUAL ( a , b ) ( fabs ( ( a) - ( b) ) < FLT_EPSILON)
150
#endif
151
152
153
154
155
156
157
158
159
160
161
#ifndef FILTER_COMBO_AUTO_SIZE
162
#define FILTER_COMBO_AUTO_SIZE 1
163
#endif
164
#ifndef FILTER_COMBO_MIN_WIDTH
165
#define FILTER_COMBO_MIN_WIDTH 150.0f
166
#endif
167
#ifndef IMGUI_BEGIN_COMBO
168
#define IMGUI_BEGIN_COMBO ImGui:: BeginCombo
169
#endif
170
171
172
173
174
175
#ifndef IMGUI_PATH_BUTTON
176
#define IMGUI_PATH_BUTTON ImGui:: Button
177
#endif
178
#ifndef IMGUI_BUTTON
179
#define IMGUI_BUTTON ImGui:: Button
180
#endif
181
182
183
184
#ifndef createDirButtonString
185
#define createDirButtonString " +"
186
#endif
187
#ifndef okButtonString
188
#define okButtonString " OK"
189
#endif
190
#ifndef okButtonWidth
191
#define okButtonWidth 0.0f
192
#endif
193
#ifndef cancelButtonString
194
#define cancelButtonString " Cancel"
195
#endif
196
#ifndef cancelButtonWidth
197
#define cancelButtonWidth 0.0f
198
#endif
199
#ifndef okCancelButtonAlignement
200
#define okCancelButtonAlignement 0.0f
201
#endif
202
#ifndef invertOkAndCancelButtons
203
204
#define invertOkAndCancelButtons 0
205
#endif
206
#ifndef resetButtonString
207
#define resetButtonString " R"
208
#endif
209
#ifndef drivesButtonString
210
#define drivesButtonString " Drives"
211
#endif
212
#ifndef editPathButtonString
213
#define editPathButtonString " E"
214
#endif
215
#ifndef searchString
216
#define searchString " Filter:"
217
#endif
218
#ifndef dirEntryString
219
#define dirEntryString " [Dir]"
220
#endif
221
#ifndef linkEntryString
222
#define linkEntryString " [Link]"
223
#endif
224
#ifndef fileEntryString
225
#define fileEntryString " [File]"
226
#endif
227
#ifndef fileNameString
228
#define fileNameString " File Name:"
229
#endif
230
#ifndef dirNameString
231
#define dirNameString " Directory Path:"
232
#endif
233
#ifndef buttonResetSearchString
234
#define buttonResetSearchString " Reset filter"
235
#endif
236
#ifndef buttonDriveString
237
#define buttonDriveString " Drives"
238
#endif
239
#ifndef buttonEditPathString
240
#define buttonEditPathString " Edit path\n You can also right click on path buttons"
241
#endif
242
#ifndef buttonResetPathString
243
#define buttonResetPathString " Reset to current directory"
244
#endif
245
#ifndef buttonCreateDirString
246
#define buttonCreateDirString " Create Directory"
247
#endif
248
#ifndef tableHeaderAscendingIcon
249
#define tableHeaderAscendingIcon " A|"
250
#endif
251
#ifndef tableHeaderDescendingIcon
252
#define tableHeaderDescendingIcon " D|"
253
#endif
254
#ifndef tableHeaderFileNameString
255
#define tableHeaderFileNameString " File name"
256
#endif
257
#ifndef tableHeaderFileTypeString
258
#define tableHeaderFileTypeString " Type"
259
#endif
260
#ifndef tableHeaderFileSizeString
261
#define tableHeaderFileSizeString " Size"
262
#endif
263
#ifndef tableHeaderFileDateString
264
#define tableHeaderFileDateString " Date"
265
#endif
266
#ifndef fileSizeBytes
267
#define fileSizeBytes " o"
268
#endif
269
#ifndef fileSizeKiloBytes
270
#define fileSizeKiloBytes " Ko"
271
#endif
272
#ifndef fileSizeMegaBytes
273
#define fileSizeMegaBytes " Mo"
274
#endif
275
#ifndef fileSizeGigaBytes
276
#define fileSizeGigaBytes " Go"
277
#endif
278
#ifndef OverWriteDialogTitleString
279
#define OverWriteDialogTitleString " The selected file already exists!"
280
#endif
281
#ifndef OverWriteDialogMessageString
282
#define OverWriteDialogMessageString " Are you sure you want to overwrite it?"
283
#endif
284
#ifndef OverWriteDialogConfirmButtonString
285
#define OverWriteDialogConfirmButtonString " Confirm"
286
#endif
287
#ifndef OverWriteDialogCancelButtonString
288
#define OverWriteDialogCancelButtonString " Cancel"
289
#endif
290
#ifndef DateTimeFormat
291
292
#define DateTimeFormat " %Y/%m/%d %H:%M"
293
#endif
294
295
296
297
#ifdef USE_THUMBNAILS
298
#ifndef tableHeaderFileThumbnailsString
299
#define tableHeaderFileThumbnailsString " Thumbnails"
300
#endif
301
#ifndef DisplayMode_FilesList_ButtonString
302
#define DisplayMode_FilesList_ButtonString " FL"
303
#endif
304
#ifndef DisplayMode_FilesList_ButtonHelp
305
#define DisplayMode_FilesList_ButtonHelp " File List"
306
#endif
307
#ifndef DisplayMode_ThumbailsList_ButtonString
308
#define DisplayMode_ThumbailsList_ButtonString " TL"
309
#endif
310
#ifndef DisplayMode_ThumbailsList_ButtonHelp
311
#define DisplayMode_ThumbailsList_ButtonHelp " Thumbnails List"
312
#endif
313
#ifndef DisplayMode_ThumbailsGrid_ButtonString
314
#define DisplayMode_ThumbailsGrid_ButtonString " TG"
315
#endif
316
#ifndef DisplayMode_ThumbailsGrid_ButtonHelp
317
#define DisplayMode_ThumbailsGrid_ButtonHelp " Thumbnails Grid"
318
#endif
319
#ifndef DisplayMode_ThumbailsList_ImageHeight
320
#define DisplayMode_ThumbailsList_ImageHeight 32.0f
321
#endif
322
#ifndef IMGUI_RADIO_BUTTON
323
inline bool inRadioButton ( const char * vLabel , bool vToggled ) {
324
bool pressed = false ;
325
if ( vToggled) {
326
ImVec4 bua = ImGui:: GetStyleColorVec4 ( ImGuiCol_ButtonActive ) ;
327
ImVec4 te = ImGui:: GetStyleColorVec4 ( ImGuiCol_Text ) ;
328
ImGui:: PushStyleColor ( ImGuiCol_Button, te ) ;
329
ImGui:: PushStyleColor ( ImGuiCol_ButtonActive, te ) ;
330
ImGui:: PushStyleColor ( ImGuiCol_ButtonHovered, te ) ;
331
ImGui:: PushStyleColor ( ImGuiCol_Text, bua ) ;
332
}
333
pressed = IMGUI_BUTTON ( vLabel ) ;
334
if ( vToggled) {
335
ImGui:: PopStyleColor ( 4 ) ;
336
}
337
return pressed;
338
}
339
#define IMGUI_RADIO_BUTTON inRadioButton
340
#endif
341
#endif
342
343
344
345
#ifdef USE_BOOKMARK
346
#ifndef defaultBookmarkPaneWith
347
#define defaultBookmarkPaneWith 150.0f
348
#endif
349
#ifndef bookmarksButtonString
350
#define bookmarksButtonString " Bookmark"
351
#endif
352
#ifndef bookmarksButtonHelpString
353
#define bookmarksButtonHelpString " Bookmark"
354
#endif
355
#ifndef addBookmarkButtonString
356
#define addBookmarkButtonString " +"
357
#endif
358
#ifndef removeBookmarkButtonString
359
#define removeBookmarkButtonString " -"
360
#endif
361
#ifndef IMGUI_TOGGLE_BUTTON
362
inline bool inToggleButton ( const char * vLabel , bool * vToggled ) {
363
bool pressed = false ;
364
365
if ( vToggled && * vToggled) {
366
ImVec4 bua = ImGui:: GetStyleColorVec4 ( ImGuiCol_ButtonActive ) ;
367
368
369
ImVec4 te = ImGui:: GetStyleColorVec4 ( ImGuiCol_Text ) ;
370
ImGui:: PushStyleColor ( ImGuiCol_Button, te ) ;
371
ImGui:: PushStyleColor ( ImGuiCol_ButtonActive, te ) ;
372
ImGui:: PushStyleColor ( ImGuiCol_ButtonHovered, te ) ;
373
ImGui:: PushStyleColor ( ImGuiCol_Text, bua ) ;
374
}
375
376
pressed = IMGUI_BUTTON ( vLabel ) ;
377
378
if ( vToggled && * vToggled) {
379
ImGui:: PopStyleColor ( 4 ) ;
380
}
381
382
if ( vToggled && pressed) * vToggled = ! * vToggled;
383
384
return pressed;
385
}
386
#define IMGUI_TOGGLE_BUTTON inToggleButton
387
#endif
388
#endif
389
390
391
392
393
394
395
396
class IGFDException : public std:: exception {
397
private :
398
std:: string m_Message ;
399
400
public :
401
IGFDException ( const std:: string& vMessage ) : m_Message ( vMessage ) {
402
}
403
const char * what ( ) {
404
return m_Message . c_str ( ) ;
405
}
406
} ;
407
408
409
410
411
412
#ifndef CUSTOM_FILESYSTEM_INCLUDE
413
#ifdef USE_STD_FILESYSTEM
414
415
static std:: filesystem:: path stringToPath ( const std:: string& str )
416
{
417
#ifdef _IGFD_WIN_
418
return std:: filesystem:: path ( IGFD:: Utils:: UTF8Decode ( str ) ) ;
419
#else
420
return std:: filesystem:: path ( str ) ;
421
#endif
422
}
423
424
static std:: string pathToString ( const std:: filesystem:: path& path )
425
{
426
#ifdef _IGFD_WIN_
427
return IGFD:: Utils:: UTF8Encode ( path. wstring ( ) ) ;
428
#else
429
return path. string ( ) ;
430
#endif
431
}
432
433
class FileSystemStd : public IGFD:: IFileSystem {
434
public :
435
bool IsDirectoryCanBeOpened ( const std:: string& vName ) override {
436
bool bExists = false ;
437
if ( ! vName. empty ( ) ) {
438
namespace fs = std:: filesystem;
439
auto pathName = stringToPath ( vName ) ;
440
try {
441
442
443
bExists = fs:: is_directory ( pathName ) ;
444
445
446
const auto dir_iter = fs:: directory_iterator ( pathName ) ;
447
( void ) dir_iter;
448
} catch ( const std:: exception& ) {
449
450
bExists = false ;
451
}
452
}
453
return bExists;
454
}
455
bool IsDirectoryExist ( const std:: string& vName ) override {
456
if ( ! vName. empty ( ) ) {
457
namespace fs = std:: filesystem;
458
return fs:: is_directory ( stringToPath ( vName ) ) ;
459
}
460
return false ;
461
}
462
bool IsFileExist ( const std:: string& vName ) override {
463
namespace fs = std:: filesystem;
464
return fs:: is_regular_file ( stringToPath ( vName ) ) ;
465
}
466
bool CreateDirectoryIfNotExist ( const std:: string& vName ) override {
467
if ( vName. empty ( ) ) return false ;
468
if ( IsDirectoryExist ( vName ) ) return false ;
469
470
#if defined (__EMSCRIPTEN__)
471
std:: string str = std:: string ( " FS.mkdir('" ) + vName + " ');" ;
472
emscripten_run_script ( str. c_str ( ) ) ;
473
bool res = true ;
474
#else
475
namespace fs = std:: filesystem;
476
bool res = fs:: create_directories ( stringToPath ( vName ) ) ;
477
#endif
478
if ( ! res) {
479
std:: cout << " Error creating directory " << vName << std:: endl;
480
}
481
return res;
482
}
483
std:: vector< std:: string> GetDrivesList ( ) override {
484
std:: vector< std:: string> res;
485
#ifdef _IGFD_WIN_
486
const DWORD mydrives = 2048 ;
487
char lpBuffer[ 2048 ] ;
488
#define mini ( a , b ) ( ( ( a) < ( b) ) ? ( a) : ( b) )
489
const DWORD countChars = mini ( GetLogicalDriveStringsA ( mydrives, lpBuffer ) , 2047 ) ;
490
#undef mini
491
if ( countChars > 0U && countChars < 2049U ) {
492
std:: string var = std:: string ( lpBuffer, ( size_t ) countChars ) ;
493
IGFD:: Utils:: ReplaceString ( var, " \\ " , " " ) ;
494
res = IGFD:: Utils:: SplitStringToVector ( var, ' \0 ' , false ) ;
495
}
496
#endif
497
return res;
498
}
499
500
IGFD:: Utils:: PathStruct ParsePathFileName ( const std:: string& vPathFileName ) override {
501
502
namespace fs = std:: filesystem;
503
IGFD:: Utils:: PathStruct res;
504
if ( vPathFileName. empty ( ) ) return res;
505
auto fsPath = stringToPath ( vPathFileName ) ;
506
if ( fs:: is_directory ( fsPath ) ) {
507
res. name = " " ;
508
res. path = pathToString ( fsPath ) ;
509
res. isOk = true ;
510
} else if ( fs:: is_regular_file ( fsPath ) ) {
511
res. name = pathToString ( fsPath. filename ( ) ) ;
512
res. path = pathToString ( fsPath. parent_path ( ) ) ;
513
res. isOk = true ;
514
}
515
return res;
516
}
517
518
std:: vector< IGFD:: FileInfos> ScanDirectory ( const std:: string& vPath ) override {
519
std:: vector< IGFD:: FileInfos> res;
520
try {
521
namespace fs = std:: filesystem;
522
auto fspath = stringToPath ( vPath ) ;
523
const auto dir_iter = fs:: directory_iterator ( fspath ) ;
524
IGFD:: FileType fstype = IGFD:: FileType ( IGFD:: FileType:: ContentType:: Directory, fs:: is_symlink ( fs:: status ( fspath ) ) ) ;
525
{
526
IGFD:: FileInfos file_two_dot;
527
file_two_dot. filePath = vPath;
528
file_two_dot. fileNameExt = " .." ;
529
file_two_dot. fileType = fstype;
530
res. push_back ( file_two_dot ) ;
531
}
532
for ( const auto & file : dir_iter) {
533
IGFD:: FileType fileType;
534
if ( file. is_symlink ( ) ) {
535
fileType. SetSymLink ( file. is_symlink ( ) ) ;
536
fileType. SetContent ( IGFD:: FileType:: ContentType:: LinkToUnknown ) ;
537
}
538
if ( file. is_directory ( ) ) {
539
fileType. SetContent ( IGFD:: FileType:: ContentType:: Directory ) ;
540
}
541
else if ( file. is_regular_file ( ) ) {
542
fileType. SetContent ( IGFD:: FileType:: ContentType:: File ) ;
543
}
544
if ( fileType. isValid ( ) ) {
545
auto fileNameExt = pathToString ( file. path ( ) . filename ( ) ) ;
546
{
547
IGFD:: FileInfos _file;
548
_file. filePath = vPath;
549
_file. fileNameExt = fileNameExt;
550
_file. fileType = fileType;
551
res. push_back ( _file ) ;
552
}
553
}
554
}
555
} catch ( const std:: exception& ex) {
556
printf ( " %s " , ex. what ( ) ) ;
557
}
558
return res;
559
}
560
bool IsDirectory ( const std:: string& vFilePathName ) override {
561
namespace fs = std:: filesystem;
562
return fs:: is_directory ( stringToPath ( vFilePathName ) ) ;
563
}
564
} ;
565
#define FILE_SYSTEM_OVERRIDE FileSystemStd
566
#else
567
class FileSystemDirent : public IGFD:: IFileSystem {
568
public :
569
bool IsDirectoryCanBeOpened ( const std:: string& vName ) override {
570
if ( ! vName. empty ( ) ) {
571
DIR* pDir = nullptr ;
572
573
574
pDir = opendir ( vName. c_str ( ) ) ;
575
if ( pDir != nullptr ) {
576
( void ) closedir ( pDir ) ;
577
return true ;
578
}
579
}
580
return false ;
581
}
582
bool IsDirectoryExist ( const std:: string& vName ) override {
583
bool bExists = false ;
584
if ( ! vName. empty ( ) ) {
585
DIR* pDir = nullptr ;
586
pDir = opendir ( vName. c_str ( ) ) ;
587
if ( pDir) {
588
bExists = true ;
589
closedir ( pDir ) ;
590
} else if ( ENOENT == errno) {
591
592
593
} else {
594
595
596
597
bExists = true ;
598
}
599
}
600
return bExists;
601
}
602
bool IsFileExist ( const std:: string& vName ) override {
603
std:: ifstream docFile ( vName, std:: ios:: in ) ;
604
if ( docFile. is_open ( ) ) {
605
docFile. close ( ) ;
606
return true ;
607
}
608
return false ;
609
}
610
bool CreateDirectoryIfNotExist ( const std:: string& vName ) override {
611
bool res = false ;
612
if ( ! vName. empty ( ) ) {
613
if ( ! IsDirectoryExist ( vName ) ) {
614
#ifdef _IGFD_WIN_
615
std:: wstring wname = IGFD:: Utils:: UTF8Decode ( vName) ;
616
if ( CreateDirectoryW ( wname. c_str ( ) , nullptr ) ) {
617
res = true ;
618
}
619
#elif defined (__EMSCRIPTEN__)
620
std:: string str = std:: string ( " FS.mkdir('" ) + vName + " ');" ;
621
emscripten_run_script ( str. c_str ( ) ) ;
622
res = true ;
623
#elif defined (_IGFD_UNIX_)
624
char buffer[ PATH_MAX] = { } ;
625
snprintf ( buffer, PATH_MAX, " mkdir -p \" %s \" " , vName. c_str ( ) ) ;
626
const int dir_err = std:: system ( buffer ) ;
627
if ( dir_err != - 1 ) {
628
res = true ;
629
}
630
#endif
631
if ( ! res) {
632
std:: cout << " Error creating directory " << vName << std:: endl;
633
}
634
}
635
}
636
637
return res;
638
}
639
640
std:: vector< std:: string> GetDrivesList ( ) override {
641
std:: vector< std:: string> res;
642
#ifdef _IGFD_WIN_
643
const DWORD mydrives = 2048 ;
644
char lpBuffer[ 2048 ] ;
645
#define mini ( a , b ) ( ( ( a) < ( b) ) ? ( a) : ( b) )
646
const DWORD countChars = mini ( GetLogicalDriveStringsA ( mydrives, lpBuffer ) , 2047 ) ;
647
#undef mini
648
if ( countChars > 0U && countChars < 2049U ) {
649
std:: string var = std:: string ( lpBuffer, ( size_t ) countChars ) ;
650
IGFD:: Utils:: ReplaceString ( var, " \\ " , " " ) ;
651
res = IGFD:: Utils:: SplitStringToVector ( var, ' \0 ' , false ) ;
652
}
653
#endif
654
return res;
655
}
656
657
IGFD:: Utils:: PathStruct ParsePathFileName ( const std:: string& vPathFileName ) override {
658
IGFD:: Utils:: PathStruct res;
659
if ( ! vPathFileName. empty ( ) ) {
660
std:: string pfn = vPathFileName;
661
std:: string separator ( 1u , PATH_SEP) ;
662
IGFD:: Utils:: ReplaceString ( pfn, " \\ " , separator ) ;
663
IGFD:: Utils:: ReplaceString ( pfn, " /" , separator ) ;
664
size_t lastSlash = pfn. find_last_of ( separator ) ;
665
if ( lastSlash != std:: string:: npos) {
666
res. name = pfn. substr ( lastSlash + 1 ) ;
667
res. path = pfn. substr ( 0 , lastSlash) ;
668
res. isOk = true ;
669
}
670
size_t lastPoint = pfn. find_last_of ( ' .' ) ;
671
if ( lastPoint != std:: string:: npos) {
672
if ( ! res. isOk ) {
673
res. name = pfn;
674
res. isOk = true ;
675
}
676
res. ext = pfn. substr ( lastPoint + 1 ) ;
677
IGFD:: Utils:: ReplaceString ( res. name , " ." + res. ext , " " ) ;
678
}
679
if ( ! res. isOk ) {
680
res. name = std:: move ( pfn ) ;
681
res. isOk = true ;
682
}
683
}
684
return res;
685
}
686
687
std:: vector< IGFD:: FileInfos> ScanDirectory ( const std:: string& vPath ) override {
688
std:: vector< IGFD:: FileInfos> res;
689
struct dirent* * files = nullptr ;
690
size_t n = scandir ( vPath. c_str ( ) , & files, nullptr ,
691
[ ] ( const struct dirent* * a, const struct dirent* * b) {
692
return strcoll ( ( * a) -> d_name , ( * b) -> d_name ) ;
693
} ) ;
694
if ( n && files) {
695
for ( size_t i = 0 ; i < n; + + i) {
696
struct dirent* ent = files[ i] ;
697
IGFD:: FileType fileType;
698
switch ( ent-> d_type ) {
699
case DT_DIR: fileType. SetContent ( IGFD:: FileType:: ContentType:: Directory ) ; break ;
700
case DT_REG: fileType. SetContent ( IGFD:: FileType:: ContentType:: File ) ; break ;
701
#if defined (_IGFD_UNIX_) || (DT_LNK != DT_UNKNOWN)
702
case DT_LNK:
703
#endif
704
case DT_UNKNOWN: {
705
struct stat sb = { } ;
706
#ifdef _IGFD_WIN_
707
auto filePath = vPath + ent-> d_name ;
708
#else
709
auto filePath = vPath + IGFD:: Utils:: GetPathSeparator ( ) + ent-> d_name ;
710
#endif
711
if ( ! stat ( filePath. c_str ( ) , & sb ) ) {
712
if ( sb. st_mode & S_IFLNK) {
713
fileType. SetSymLink ( true ) ;
714
715
fileType. SetContent ( IGFD:: FileType:: ContentType:: LinkToUnknown ) ;
716
}
717
if ( sb. st_mode & S_IFREG) {
718
fileType. SetContent ( IGFD:: FileType:: ContentType:: File ) ;
719
break ;
720
} else if ( sb. st_mode & S_IFDIR) {
721
fileType. SetContent ( IGFD:: FileType:: ContentType:: Directory ) ;
722
break ;
723
}
724
}
725
break ;
726
}
727
default : break ;
728
}
729
if ( fileType. isValid ( ) ) {
730
IGFD:: FileInfos _file;
731
_file. filePath = vPath;
732
_file. fileNameExt = ent-> d_name ;
733
_file. fileType = fileType;
734
res. push_back ( _file ) ;
735
}
736
}
737
for ( size_t i = 0 ; i < n; + + i) {
738
free ( files[ i] ) ;
739
}
740
free ( files ) ;
741
}
742
return res;
743
}
744
bool IsDirectory ( const std:: string& vFilePathName ) override {
745
DIR * pDir = opendir ( vFilePathName. c_str ( ) ) ;
746
if ( pDir) {
747
( void ) closedir ( pDir ) ;
748
return true ;
749
}
750
return false ;
751
}
752
} ;
753
#define FILE_SYSTEM_OVERRIDE FileSystemDirent
754
#endif
755
#else
756
#include CUSTOM_FILESYSTEM_INCLUDE
757
#endif
758
759
760
761
762
763
764
bool IGFD:: Utils:: ImSplitter ( bool split_vertically , float thickness , float * size1 , float * size2 , float min_size1 , float min_size2 , float splitter_long_axis_size ) {
765
using namespace ImGui;
766
ImGuiContext& g = * GImGui;
767
ImGuiWindow* window = g. CurrentWindow ;
768
ImGuiID id = window-> GetID ( " ##Splitter" ) ;
769
ImRect bb;
770
bb. Min = window-> DC . CursorPos + ( split_vertically ? ImVec2 ( * size1, 0.0f ) : ImVec2 ( 0.0f , * size1) ) ;
771
bb. Max = bb. Min + CalcItemSize ( split_vertically ? ImVec2 ( thickness, splitter_long_axis_size ) : ImVec2 ( splitter_long_axis_size, thickness ) , 0.0f , 0.0f ) ;
772
return SplitterBehavior ( bb, id, split_vertically ? ImGuiAxis_X : ImGuiAxis_Y, size1, size2, min_size1, min_size2, 1.0f ) ;
773
}
774
775
776
std:: string IGFD:: Utils:: UTF8Encode ( const std:: wstring& wstr ) {
777
std:: string res;
778
#ifdef _IGFD_WIN_
779
if ( ! wstr. empty ( ) ) {
780
int size_needed = WideCharToMultiByte ( CP_UTF8, 0 , & wstr[ 0 ] , ( int ) wstr. size ( ) , NULL , 0 , NULL , NULL ) ;
781
if ( size_needed) {
782
res = std:: string ( size_needed, 0 ) ;
783
WideCharToMultiByte ( CP_UTF8, 0 , & wstr[ 0 ] , ( int ) wstr. size ( ) , & res[ 0 ] , size_needed, NULL , NULL ) ;
784
}
785
}
786
#else
787
788
( void ) wstr;
789
#endif
790
return res;
791
}
792
793
794
std:: wstring IGFD:: Utils:: UTF8Decode ( const std:: string& str ) {
795
std:: wstring res;
796
#ifdef _IGFD_WIN_
797
if ( ! str. empty ( ) ) {
798
int size_needed = MultiByteToWideChar ( CP_UTF8, 0 , & str[ 0 ] , ( int ) str. size ( ) , NULL , 0 ) ;
799
if ( size_needed) {
800
res = std:: wstring ( size_needed, 0 ) ;
801
MultiByteToWideChar ( CP_UTF8, 0 , & str[ 0 ] , ( int ) str. size ( ) , & res[ 0 ] , size_needed ) ;
802
}
803
}
804
#else
805
806
( void ) str;
807
#endif
808
return res;
809
}
810
811
bool IGFD:: Utils:: ReplaceString ( std:: string& str , const :: std:: string& oldStr , const :: std:: string& newStr , const size_t & vMaxRecursion ) {
812
if ( ! str. empty ( ) && oldStr != newStr) {
813
bool res = false ;
814
size_t pos = 0 ;
815
bool found = false ;
816
size_t max_recursion = vMaxRecursion;
817
do {
818
pos = str. find ( oldStr, pos ) ;
819
if ( pos != std:: string:: npos) {
820
found = res = true ;
821
str. replace ( pos, oldStr. length ( ) , newStr ) ;
822
pos += newStr. length ( ) ;
823
} else if ( found && max_recursion > 0 ) {
824
found = false ;
825
pos = 0 ;
826
- - max_recursion;
827
}
828
} while ( pos != std:: string:: npos) ;
829
return res;
830
}
831
return false ;
832
}
833
834
std:: vector< std:: string> IGFD:: Utils:: SplitStringToVector ( const std:: string& vText , const char & vDelimiter , const bool & vPushEmpty ) {
835
std:: vector< std:: string> arr;
836
if ( ! vText. empty ( ) ) {
837
size_t start = 0 ;
838
size_t end = vText. find ( vDelimiter, start ) ;
839
while ( end != std:: string:: npos) {
840
auto token = vText. substr ( start, end - start ) ;
841
if ( ! token. empty ( ) || ( token. empty ( ) && vPushEmpty) ) {
842
arr. push_back ( token ) ;
843
}
844
start = end + 1 ;
845
end = vText. find ( vDelimiter, start ) ;
846
}
847
auto token = vText. substr ( start ) ;
848
if ( ! token. empty ( ) || ( token. empty ( ) && vPushEmpty) ) {
849
arr. push_back ( token ) ;
850
}
851
}
852
return arr;
853
}
854
855
void IGFD:: Utils:: AppendToBuffer ( char * vBuffer , size_t vBufferLen , const std:: string& vStr ) {
856
std:: string st = vStr;
857
size_t len = vBufferLen - 1u ;
858
size_t slen = strlen ( vBuffer ) ;
859
860
if ( ! st. empty ( ) && st != " \n " ) {
861
IGFD:: Utils:: ReplaceString ( st, " \n " , " " ) ;
862
IGFD:: Utils:: ReplaceString ( st, " \r " , " " ) ;
863
}
864
vBuffer[ slen] = ' \0 ' ;
865
std:: string str = std:: string ( vBuffer ) ;
866
867
str += vStr;
868
if ( len > str. size ( ) ) {
869
len = str. size ( ) ;
870
}
871
#ifdef _MSC_VER
872
strncpy_s ( vBuffer, vBufferLen, str. c_str ( ) , len) ;
873
#else
874
strncpy ( vBuffer, str. c_str ( ) , len ) ;
875
#endif
876
vBuffer[ len] = ' \0 ' ;
877
}
878
879
void IGFD:: Utils:: ResetBuffer ( char * vBuffer ) {
880
vBuffer[ 0 ] = ' \0 ' ;
881
}
882
883
void IGFD:: Utils:: SetBuffer ( char * vBuffer , size_t vBufferLen , const std:: string& vStr ) {
884
ResetBuffer ( vBuffer ) ;
885
AppendToBuffer ( vBuffer, vBufferLen, vStr ) ;
886
}
887
888
std:: string IGFD:: Utils:: LowerCaseString ( const std:: string& vString ) {
889
auto str = vString;
890
891
892
for ( char & c : str) {
893
c = ( char ) std:: tolower ( c ) ;
894
}
895
896
return str;
897
}
898
899
size_t IGFD:: Utils:: GetCharCountInString ( const std:: string& vString , const char & vChar ) {
900
size_t res = 0U ;
901
for ( const auto & c : vString) {
902
if ( c == vChar) {
903
+ + res;
904
}
905
}
906
return res;
907
}
908
909
size_t IGFD:: Utils:: GetLastCharPosWithMinCharCount ( const std:: string& vString , const char & vChar , const size_t & vMinCharCount ) {
910
if ( vMinCharCount) {
911
size_t last_dot_pos = vString. size ( ) + 1U ;
912
size_t count_dots = vMinCharCount;
913
while ( count_dots > 0U && last_dot_pos > 0U && last_dot_pos != std:: string:: npos) {
914
auto new_dot = vString. rfind ( vChar, last_dot_pos - 1U ) ;
915
if ( new_dot != std:: string:: npos) {
916
last_dot_pos = new_dot;
917
- - count_dots;
918
} else {
919
break ;
920
}
921
}
922
return last_dot_pos;
923
}
924
return std:: string:: npos;
925
}
926
927
std:: string IGFD:: Utils:: GetPathSeparator ( ) {
928
return std:: string ( 1U , PATH_SEP) ;
929
}
930
931
std:: string IGFD:: Utils:: RoundNumber ( double vvalue , int n ) {
932
std:: stringstream tmp;
933
tmp << std:: setprecision ( n ) << std:: fixed << vvalue;
934
return tmp. str ( ) ;
935
}
936
937
std:: pair< std:: string, std:: string> IGFD:: Utils:: FormatFileSize ( size_t vByteSize ) {
938
if ( vByteSize != 0 ) {
939
static double lo = 1024.0 ;
940
static double ko = 1024.0 * 1024.0 ;
941
static double mo = 1024.0 * 1024.0 * 1024.0 ;
942
943
auto v = ( double ) vByteSize;
944
945
if ( v < lo)
946
return { RoundNumber ( v, 0 ) , fileSizeBytes} ;
947
else if ( v < ko)
948
return { RoundNumber ( v / lo, 2 ) , fileSizeKiloBytes} ;
949
else if ( v < mo)
950
return { RoundNumber ( v / ko, 2 ) , fileSizeMegaBytes} ;
951
else
952
return { RoundNumber ( v / mo, 2 ) , fileSizeGigaBytes} ;
953
}
954
955
return { " 0" , fileSizeBytes} ;
956
}
957
958
959
960
961
962
IGFD:: FileStyle:: FileStyle ( ) : color ( 0 , 0 , 0 , 0 ) {
963
}
964
965
IGFD:: FileStyle:: FileStyle ( const FileStyle& vStyle ) {
966
color = vStyle. color ;
967
icon = vStyle. icon ;
968
font = vStyle. font ;
969
flags = vStyle. flags ;
970
}
971
972
IGFD:: FileStyle:: FileStyle ( const ImVec4& vColor , const std:: string& vIcon , ImFont* vFont ) : color ( vColor ) , icon ( vIcon ) , font ( vFont ) {
973
}
974
975
976
977
978
979
void IGFD:: SearchManager:: Clear ( ) {
980
searchTag. clear ( ) ;
981
IGFD:: Utils:: ResetBuffer ( searchBuffer ) ;
982
}
983
984
void IGFD:: SearchManager:: DrawSearchBar ( FileDialogInternal& vFileDialogInternal ) {
985
986
if ( IMGUI_BUTTON ( resetButtonString " ##BtnImGuiFileDialogSearchField" ) ) {
987
Clear ( ) ;
988
vFileDialogInternal. fileManager . ApplyFilteringOnFileList ( vFileDialogInternal ) ;
989
}
990
if ( ImGui:: IsItemHovered ( ) ) ImGui:: SetTooltip ( buttonResetSearchString ) ;
991
ImGui:: SameLine ( ) ;
992
ImGui:: Text ( searchString ) ;
993
ImGui:: SameLine ( ) ;
994
ImGui:: PushItemWidth ( ImGui:: GetContentRegionAvail ( ) . x ) ;
995
bool edited = ImGui:: InputText ( " ##InputImGuiFileDialogSearchField" , searchBuffer, MAX_FILE_DIALOG_NAME_BUFFER) ;
996
if ( ImGui:: GetItemID ( ) == ImGui:: GetActiveID ( ) ) searchInputIsActive = true ;
997
ImGui:: PopItemWidth ( ) ;
998
if ( edited) {
999
searchTag = searchBuffer;
1000
vFileDialogInternal. fileManager . ApplyFilteringOnFileList ( vFileDialogInternal ) ;
1001
}
1002
}
1003
1004
1005
1006
1007
1008
void IGFD:: FilterInfos:: setCollectionTitle ( const std:: string& vTitle ) {
1009
title = vTitle;
1010
}
1011
1012
void IGFD:: FilterInfos:: addFilter ( const std:: string& vFilter , const bool & vIsRegex ) {
1013
setCollectionTitle ( vFilter ) ;
1014
addCollectionFilter ( vFilter, vIsRegex ) ;
1015
}
1016
1017
void IGFD:: FilterInfos:: addCollectionFilter ( const std:: string& vFilter , const bool & vIsRegex ) {
1018
if ( ! vIsRegex) {
1019
if ( vFilter. find ( ' *' ) != std:: string:: npos) {
1020
const auto & regex_string = transformAsteriskBasedFilterToRegex ( vFilter ) ;
1021
addCollectionFilter ( regex_string, true ) ;
1022
return ;
1023
}
1024
filters. try_add ( vFilter ) ;
1025
filters_optimized. try_add ( Utils:: LowerCaseString ( vFilter ) ) ;
1026
auto _count_dots = Utils:: GetCharCountInString ( vFilter, ' .' ) ;
1027
if ( _count_dots > count_dots) {
1028
count_dots = _count_dots;
1029
}
1030
} else {
1031
try {
1032
auto rx = std:: regex ( vFilter ) ;
1033
filters. try_add ( vFilter ) ;
1034
filters_regex. emplace_back ( rx ) ;
1035
} catch ( std:: exception& ) {
1036
assert ( 0 ) ;
1037
}
1038
}
1039
}
1040
1041
void IGFD:: FilterInfos:: clear ( ) {
1042
title. clear ( ) ;
1043
filters. clear ( ) ;
1044
filters_optimized. clear ( ) ;
1045
filters_regex. clear ( ) ;
1046
}
1047
1048
bool IGFD:: FilterInfos:: empty ( ) const {
1049
return filters. empty ( ) || filters. begin ( ) -> empty ( ) ;
1050
}
1051
1052
const std:: string& IGFD:: FilterInfos:: getFirstFilter ( ) const {
1053
if ( ! filters. empty ( ) ) {
1054
return * filters. begin ( ) ;
1055
}
1056
return empty_string;
1057
}
1058
1059
bool IGFD:: FilterInfos:: exist ( const FileInfos& vFileInfos , bool vIsCaseInsensitive ) const {
1060
for ( const auto & filter : filters) {
1061
if ( vFileInfos. SearchForExt ( filter, vIsCaseInsensitive, count_dots ) ) {
1062
return true ;
1063
}
1064
}
1065
return false ;
1066
}
1067
1068
bool IGFD:: FilterInfos:: regexExist ( const std:: string& vFilter ) const {
1069
for ( auto regex : filters_regex) {
1070
if ( std:: regex_search ( vFilter, regex ) ) {
1071
return true ;
1072
}
1073
}
1074
return false ;
1075
}
1076
1077
std:: string IGFD:: FilterInfos:: transformAsteriskBasedFilterToRegex ( const std:: string& vFilter ) {
1078
std:: string res;
1079
if ( ! vFilter. empty ( ) && vFilter. find ( ' *' ) != std:: string:: npos) {
1080
res = " ((" ;
1081
for ( const auto & c : vFilter) {
1082
if ( c == ' .' ) {
1083
res += " [.]" ;
1084
} else if ( c == ' *' ) {
1085
res += " .*" ;
1086
} else {
1087
res += c;
1088
}
1089
}
1090
res += " $))" ;
1091
}
1092
return res;
1093
}
1094
1095
1096
1097
1098
1099
const IGFD:: FilterInfos& IGFD:: FilterManager:: GetSelectedFilter ( ) const {
1100
return m_SelectedFilter ;
1101
}
1102
1103
void IGFD:: FilterManager:: ParseFilters ( const char * vFilters ) {
1104
m_ParsedFilters . clear ( ) ;
1105
1106
if ( vFilters) {
1107
dLGFilters = vFilters;
1108
} else {
1109
dLGFilters. clear ( ) ;
1110
}
1111
1112
if ( ! dLGFilters. empty ( ) ) {
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
bool current_filter_found = false ;
1125
bool started = false ;
1126
bool regex_started = false ;
1127
bool parenthesis_started = false ;
1128
1129
std:: string word;
1130
std:: string filter_name;
1131
1132
char last_split_char = 0 ;
1133
for ( char c : dLGFilters) {
1134
if ( c == ' {' ) {
1135
if ( regex_started) {
1136
word += c;
1137
} else {
1138
started = true ;
1139
m_ParsedFilters . emplace_back ( ) ;
1140
m_ParsedFilters . back ( ) . setCollectionTitle ( filter_name ) ;
1141
filter_name. clear ( ) ;
1142
word. clear ( ) ;
1143
}
1144
last_split_char = c;
1145
} else if ( c == ' }' ) {
1146
if ( regex_started) {
1147
word += c;
1148
} else {
1149
if ( started) {
1150
if ( word. size ( ) > 1U && word[ 0 ] == ' .' ) {
1151
if ( m_ParsedFilters . empty ( ) ) {
1152
m_ParsedFilters . emplace_back ( ) ;
1153
}
1154
m_ParsedFilters . back ( ) . addCollectionFilter ( word, false ) ;
1155
}
1156
word. clear ( ) ;
1157
filter_name. clear ( ) ;
1158
started = false ;
1159
}
1160
}
1161
last_split_char = c;
1162
} else if ( c == ' (' ) {
1163
word += c;
1164
if ( last_split_char == ' (' ) {
1165
regex_started = true ;
1166
}
1167
parenthesis_started = true ;
1168
if ( ! started) {
1169
filter_name += c;
1170
}
1171
last_split_char = c;
1172
} else if ( c == ' )' ) {
1173
word += c;
1174
if ( last_split_char == ' )' ) {
1175
if ( regex_started) {
1176
if ( started) {
1177
m_ParsedFilters . back ( ) . addCollectionFilter ( word, true ) ;
1178
} else {
1179
m_ParsedFilters . emplace_back ( ) ;
1180
m_ParsedFilters . back ( ) . addFilter ( word, true ) ;
1181
}
1182
word. clear ( ) ;
1183
filter_name. clear ( ) ;
1184
regex_started = false ;
1185
} else {
1186
if ( ! started) {
1187
if ( ! m_ParsedFilters . empty ( ) ) {
1188
m_ParsedFilters . erase ( m_ParsedFilters . begin ( ) + m_ParsedFilters . size ( ) - 1U ) ;
1189
} else {
1190
m_ParsedFilters . clear ( ) ;
1191
}
1192
}
1193
word. clear ( ) ;
1194
filter_name. clear ( ) ;
1195
}
1196
}
1197
parenthesis_started = false ;
1198
if ( ! started) {
1199
filter_name += c;
1200
}
1201
last_split_char = c;
1202
} else if ( c == ' .' ) {
1203
word += c;
1204
if ( ! started) {
1205
filter_name += c;
1206
}
1207
last_split_char = c;
1208
} else if ( c == ' ,' ) {
1209
if ( regex_started) {
1210
regex_started = false ;
1211
word. clear ( ) ;
1212
filter_name. clear ( ) ;
1213
} else {
1214
if ( started) {
1215
if ( word. size ( ) > 1U && word[ 0 ] == ' .' ) {
1216
m_ParsedFilters . back ( ) . addCollectionFilter ( word, false ) ;
1217
word. clear ( ) ;
1218
filter_name. clear ( ) ;
1219
}
1220
} else {
1221
if ( word. size ( ) > 1U && word[ 0 ] == ' .' ) {
1222
m_ParsedFilters . emplace_back ( ) ;
1223
m_ParsedFilters . back ( ) . addFilter ( word, false ) ;
1224
word. clear ( ) ;
1225
filter_name. clear ( ) ;
1226
}
1227
if ( parenthesis_started) {
1228
filter_name += c;
1229
}
1230
}
1231
}
1232
} else {
1233
if ( c != ' ' ) {
1234
word += c;
1235
}
1236
if ( ! started) {
1237
filter_name += c;
1238
}
1239
}
1240
}
1241
1242
if ( started) {
1243
if ( ! m_ParsedFilters . empty ( ) ) {
1244
m_ParsedFilters . erase ( m_ParsedFilters . begin ( ) + m_ParsedFilters . size ( ) - 1U ) ;
1245
} else {
1246
m_ParsedFilters . clear ( ) ;
1247
}
1248
} else if ( word. size ( ) > 1U && word[ 0 ] == ' .' ) {
1249
m_ParsedFilters . emplace_back ( ) ;
1250
m_ParsedFilters . back ( ) . addFilter ( word, false ) ;
1251
word. clear ( ) ;
1252
}
1253
1254
for ( const auto & it : m_ParsedFilters ) {
1255
if ( it. title == m_SelectedFilter . title ) {
1256
m_SelectedFilter = it;
1257
current_filter_found = true ;
1258
break ;
1259
}
1260
}
1261
1262
if ( ! current_filter_found) {
1263
if ( ! m_ParsedFilters . empty ( ) ) {
1264
m_SelectedFilter = * m_ParsedFilters . begin ( ) ;
1265
}
1266
}
1267
}
1268
}
1269
1270
void IGFD:: FilterManager:: SetSelectedFilterWithExt ( const std:: string& vFilter ) {
1271
if ( ! m_ParsedFilters . empty ( ) ) {
1272
if ( ! vFilter. empty ( ) ) {
1273
for ( const auto & infos : m_ParsedFilters ) {
1274
for ( const auto & filter : infos. filters ) {
1275
if ( vFilter == filter) {
1276
m_SelectedFilter = infos;
1277
}
1278
}
1279
}
1280
}
1281
1282
if ( m_SelectedFilter . empty ( ) ) {
1283
m_SelectedFilter = * m_ParsedFilters . begin ( ) ;
1284
}
1285
}
1286
}
1287
1288
void IGFD:: FilterManager:: SetFileStyle ( const IGFD_FileStyleFlags& vFlags , const char * vCriteria , const FileStyle& vInfos ) {
1289
std:: string _criteria = ( vCriteria != nullptr ) ? std:: string ( vCriteria ) : " " ;
1290
m_FilesStyle [ vFlags] [ _criteria] = std:: make_shared < FileStyle> ( vInfos ) ;
1291
m_FilesStyle [ vFlags] [ _criteria] -> flags = vFlags;
1292
}
1293
1294
1295
1296
bool IGFD:: FilterManager:: m_FillFileStyle ( std:: shared_ptr< FileInfos> vFileInfos ) const {
1297
1298
1299
1300
if ( vFileInfos. use_count ( ) && ! m_FilesStyle . empty ( ) ) {
1301
for ( const auto & _flag : m_FilesStyle ) {
1302
for ( const auto & _file : _flag. second ) {
1303
if ( ( _flag. first & IGFD_FileStyleByTypeDir && _flag. first & IGFD_FileStyleByTypeLink && vFileInfos-> fileType . isDir ( ) && vFileInfos-> fileType . isSymLink ( ) ) ||
1304
( _flag. first & IGFD_FileStyleByTypeFile && _flag. first & IGFD_FileStyleByTypeLink && vFileInfos-> fileType . isFile ( ) && vFileInfos-> fileType . isSymLink ( ) ) ||
1305
( _flag. first & IGFD_FileStyleByTypeLink && vFileInfos-> fileType . isSymLink ( ) ) || ( _flag. first & IGFD_FileStyleByTypeDir && vFileInfos-> fileType . isDir ( ) ) ||
1306
( _flag. first & IGFD_FileStyleByTypeFile && vFileInfos-> fileType . isFile ( ) ) ) {
1307
if ( _file. first . empty ( ) ) {
1308
vFileInfos-> fileStyle = _file. second ;
1309
} else if ( _file. first . find ( " ((" ) != std:: string:: npos && std:: regex_search ( vFileInfos-> fileNameExt ,
1310
std:: regex ( _file. first ) ) ) {
1311
vFileInfos-> fileStyle = _file. second ;
1312
} else if ( _file. first == vFileInfos-> fileNameExt ) {
1313
vFileInfos-> fileStyle = _file. second ;
1314
}
1315
}
1316
1317
if ( _flag. first & IGFD_FileStyleByExtention) {
1318
if ( _file. first . find ( " ((" ) != std:: string:: npos && std:: regex_search ( vFileInfos-> fileExtLevels [ 0 ] , std:: regex ( _file. first ) ) ) {
1319
vFileInfos-> fileStyle = _file. second ;
1320
} else if ( vFileInfos-> SearchForExt ( _file. first , false ) ) {
1321
vFileInfos-> fileStyle = _file. second ;
1322
}
1323
}
1324
1325
if ( _flag. first & IGFD_FileStyleByFullName) {
1326
if ( _file. first . find ( " ((" ) != std:: string:: npos && std:: regex_search ( vFileInfos-> fileNameExt , std:: regex ( _file. first ) ) ) {
1327
vFileInfos-> fileStyle = _file. second ;
1328
} else if ( _file. first == vFileInfos-> fileNameExt ) {
1329
vFileInfos-> fileStyle = _file. second ;
1330
}
1331
}
1332
1333
if ( _flag. first & IGFD_FileStyleByContainedInFullName) {
1334
if ( _file. first . find ( " ((" ) != std:: string:: npos && std:: regex_search ( vFileInfos-> fileNameExt , std:: regex ( _file. first ) ) ) {
1335
vFileInfos-> fileStyle = _file. second ;
1336
} else if ( vFileInfos-> fileNameExt . find ( _file. first ) != std:: string:: npos) {
1337
vFileInfos-> fileStyle = _file. second ;
1338
}
1339
}
1340
1341
for ( auto & functor : m_FilesStyleFunctors ) {
1342
if ( functor) {
1343
FileStyle result;
1344
if ( functor ( * ( vFileInfos. get ( ) ) , result) ) {
1345
vFileInfos-> fileStyle = std:: make_shared < FileStyle> ( std:: move ( result ) ) ;
1346
}
1347
}
1348
}
1349
1350
if ( vFileInfos-> fileStyle . use_count ( ) ) {
1351
return true ;
1352
}
1353
}
1354
}
1355
}
1356
1357
return false ;
1358
}
1359
1360
void IGFD:: FilterManager:: SetFileStyle ( const IGFD_FileStyleFlags& vFlags , const char * vCriteria , const ImVec4& vColor , const std:: string& vIcon , ImFont* vFont ) {
1361
std:: string _criteria;
1362
if ( vCriteria) _criteria = std:: string ( vCriteria ) ;
1363
m_FilesStyle [ vFlags] [ _criteria] = std:: make_shared < FileStyle> ( vColor, vIcon, vFont ) ;
1364
m_FilesStyle [ vFlags] [ _criteria] -> flags = vFlags;
1365
}
1366
1367
void IGFD:: FilterManager:: SetFileStyle ( FileStyle:: FileStyleFunctor vFunctor ) {
1368
if ( vFunctor) {
1369
m_FilesStyleFunctors . push_back ( vFunctor ) ;
1370
}
1371
}
1372
1373
1374
bool IGFD:: FilterManager:: GetFileStyle ( const IGFD_FileStyleFlags& vFlags , const std:: string& vCriteria , ImVec4* vOutColor , std:: string* vOutIcon , ImFont* * vOutFont ) {
1375
if ( vOutColor) {
1376
if ( ! m_FilesStyle . empty ( ) ) {
1377
if ( m_FilesStyle . find ( vFlags ) != m_FilesStyle . end ( ) ) {
1378
if ( vFlags & IGFD_FileStyleByContainedInFullName) {
1379
1380
for ( const auto & _file : m_FilesStyle . at ( vFlags ) ) {
1381
if ( vCriteria. find ( _file. first ) != std:: string:: npos) {
1382
if ( _file. second . use_count ( ) ) {
1383
* vOutColor = _file. second -> color ;
1384
if ( vOutIcon) * vOutIcon = _file. second -> icon ;
1385
if ( vOutFont) * vOutFont = _file. second -> font ;
1386
return true ;
1387
}
1388
}
1389
}
1390
} else {
1391
if ( m_FilesStyle . at ( vFlags ) . find ( vCriteria ) != m_FilesStyle . at ( vFlags ) . end ( ) ) {
1392
* vOutColor = m_FilesStyle [ vFlags] [ vCriteria] -> color ;
1393
if ( vOutIcon) * vOutIcon = m_FilesStyle [ vFlags] [ vCriteria] -> icon ;
1394
if ( vOutFont) * vOutFont = m_FilesStyle [ vFlags] [ vCriteria] -> font ;
1395
return true ;
1396
}
1397
}
1398
} else {
1399
1400
for ( const auto & _flag : m_FilesStyle ) {
1401
if ( _flag. first & vFlags) {
1402
if ( _flag. first & IGFD_FileStyleByContainedInFullName) {
1403
1404
for ( const auto & _file : m_FilesStyle . at ( _flag. first ) ) {
1405
if ( vCriteria. find ( _file. first ) != std:: string:: npos) {
1406
if ( _file. second . use_count ( ) ) {
1407
* vOutColor = _file. second -> color ;
1408
if ( vOutIcon) * vOutIcon = _file. second -> icon ;
1409
if ( vOutFont) * vOutFont = _file. second -> font ;
1410
return true ;
1411
}
1412
}
1413
}
1414
} else {
1415
if ( m_FilesStyle . at ( _flag. first ) . find ( vCriteria ) != m_FilesStyle . at ( _flag. first ) . end ( ) ) {
1416
* vOutColor = m_FilesStyle [ _flag. first ] [ vCriteria] -> color ;
1417
if ( vOutIcon) * vOutIcon = m_FilesStyle [ _flag. first ] [ vCriteria] -> icon ;
1418
if ( vOutFont) * vOutFont = m_FilesStyle [ _flag. first ] [ vCriteria] -> font ;
1419
return true ;
1420
}
1421
}
1422
}
1423
}
1424
}
1425
}
1426
}
1427
return false ;
1428
}
1429
1430
void IGFD:: FilterManager:: ClearFilesStyle ( ) {
1431
m_FilesStyle . clear ( ) ;
1432
}
1433
1434
bool IGFD:: FilterManager:: IsCoveredByFilters ( const FileInfos& vFileInfos , bool vIsCaseInsensitive ) const {
1435
if ( ! dLGFilters. empty ( ) && ! m_SelectedFilter . empty ( ) ) {
1436
return ( m_SelectedFilter . exist ( vFileInfos, vIsCaseInsensitive ) || m_SelectedFilter . regexExist ( vFileInfos. fileNameExt ) ) ;
1437
}
1438
1439
return false ;
1440
}
1441
1442
float IGFD:: FilterManager:: GetFilterComboBoxWidth ( ) const {
1443
#if FILTER_COMBO_AUTO_SIZE
1444
const auto & combo_width = ImGui:: CalcTextSize ( m_SelectedFilter . title . c_str ( ) ) . x + ImGui:: GetFrameHeight ( ) + ImGui:: GetStyle ( ) . ItemInnerSpacing . x ;
1445
return ImMax ( combo_width, FILTER_COMBO_MIN_WIDTH) ;
1446
#else
1447
return FILTER_COMBO_MIN_WIDTH;
1448
#endif
1449
}
1450
1451
bool IGFD:: FilterManager:: DrawFilterComboBox ( FileDialogInternal& vFileDialogInternal ) {
1452
if ( ! dLGFilters. empty ( ) ) {
1453
ImGui:: SameLine ( ) ;
1454
bool needToApllyNewFilter = false ;
1455
ImGui:: PushItemWidth ( GetFilterComboBoxWidth ( ) ) ;
1456
if ( IMGUI_BEGIN_COMBO ( " ##Filters" , m_SelectedFilter . title . c_str ( ) , ImGuiComboFlags_None) ) {
1457
intptr_t i = 0 ;
1458
for ( const auto & filter : m_ParsedFilters ) {
1459
const bool item_selected = ( filter. title == m_SelectedFilter . title ) ;
1460
ImGui:: PushID ( ( void * ) ( intptr_t ) i+ + ) ;
1461
if ( ImGui:: Selectable ( filter. title . c_str ( ) , item_selected ) ) {
1462
m_SelectedFilter = filter;
1463
needToApllyNewFilter = true ;
1464
}
1465
ImGui:: PopID ( ) ;
1466
}
1467
ImGui:: EndCombo ( ) ;
1468
}
1469
ImGui:: PopItemWidth ( ) ;
1470
if ( needToApllyNewFilter) {
1471
vFileDialogInternal. fileManager . OpenCurrentPath ( vFileDialogInternal ) ;
1472
}
1473
return needToApllyNewFilter;
1474
}
1475
return false ;
1476
}
1477
1478
std:: string IGFD:: FilterManager:: ReplaceExtentionWithCurrentFilterIfNeeded ( const std:: string& vFileName , IGFD_ResultMode vFlag ) const {
1479
auto result = vFileName;
1480
if ( ! result. empty ( ) ) {
1481
const auto & current_filter = m_SelectedFilter . getFirstFilter ( ) ;
1482
if ( ! current_filter. empty ( ) ) {
1483
Utils:: ReplaceString ( result, " .." , " ." ) ;
1484
1485
1486
if ( current_filter. find ( " ((" ) != std:: string:: npos) {
1487
return result;
1488
}
1489
1490
1491
if ( current_filter. find ( " .*" ) != std:: string:: npos) {
1492
return result;
1493
}
1494
1495
switch ( vFlag) {
1496
case IGFD_ResultMode_KeepInputFile: {
1497
return vFileName;
1498
}
1499
case IGFD_ResultMode_OverwriteFileExt: {
1500
const auto & count_dots = Utils:: GetCharCountInString ( vFileName, ' .' ) ;
1501
const auto & min_dots = ImMin < size_t > ( count_dots, m_SelectedFilter . count_dots ) ;
1502
const auto & lp = Utils:: GetLastCharPosWithMinCharCount ( vFileName, ' .' , min_dots ) ;
1503
if ( lp != std:: string:: npos) {
1504
const auto & file_name_without_user_ext = vFileName. substr ( 0 , lp) ;
1505
result = file_name_without_user_ext + current_filter;
1506
} else {
1507
result = vFileName + current_filter;
1508
}
1509
break ;
1510
}
1511
case IGFD_ResultMode_AddIfNoFileExt: {
1512
const auto & count_dots = Utils:: GetCharCountInString ( vFileName, ' .' ) ;
1513
const auto & min_dots = ImMin < size_t > ( count_dots, m_SelectedFilter . count_dots ) ;
1514
const auto & lp = Utils:: GetLastCharPosWithMinCharCount ( vFileName, ' .' , min_dots ) ;
1515
if ( lp == std:: string:: npos ||
1516
lp == ( vFileName. size ( ) - 1U ) ) {
1517
const auto & file_name_without_user_ext = vFileName. substr ( 0 , lp) ;
1518
result = file_name_without_user_ext + current_filter;
1519
}
1520
break ;
1521
}
1522
}
1523
1524
Utils:: ReplaceString ( result, " .." , " ." ) ;
1525
}
1526
}
1527
return result;
1528
}
1529
1530
void IGFD:: FilterManager:: SetDefaultFilterIfNotDefined ( ) {
1531
if ( m_SelectedFilter . empty ( ) &&
1532
! m_ParsedFilters . empty ( ) ) {
1533
m_SelectedFilter = * m_ParsedFilters . begin ( ) ;
1534
}
1535
}
1536
1537
1538
1539
1540
1541
IGFD:: FileType:: FileType ( ) = default ;
1542
IGFD:: FileType:: FileType ( const ContentType& vContentType , const bool & vIsSymlink ) : m_Content ( vContentType) , m_Symlink ( vIsSymlink) {
1543
}
1544
void IGFD:: FileType:: SetContent ( const ContentType& vContentType ) {
1545
m_Content = vContentType;
1546
}
1547
void IGFD:: FileType:: SetSymLink ( const bool & vIsSymlink ) {
1548
m_Symlink = vIsSymlink;
1549
}
1550
bool IGFD:: FileType:: isValid ( ) const {
1551
return m_Content != ContentType:: Invalid;
1552
}
1553
bool IGFD:: FileType:: isDir ( ) const {
1554
return m_Content == ContentType:: Directory;
1555
}
1556
bool IGFD:: FileType:: isFile ( ) const {
1557
return m_Content == ContentType:: File;
1558
}
1559
bool IGFD:: FileType:: isLinkToUnknown ( ) const {
1560
return m_Content == ContentType:: LinkToUnknown;
1561
}
1562
bool IGFD:: FileType:: isSymLink ( ) const {
1563
return m_Symlink ;
1564
}
1565
1566
bool IGFD:: FileType:: operator== ( const FileType& rhs ) const {
1567
return m_Content == rhs. m_Content ;
1568
}
1569
bool IGFD:: FileType:: operator!= ( const FileType& rhs ) const {
1570
return m_Content != rhs. m_Content ;
1571
}
1572
bool IGFD:: FileType:: operator< ( const FileType& rhs ) const {
1573
return m_Content < rhs. m_Content ;
1574
}
1575
bool IGFD:: FileType:: operator> ( const FileType& rhs ) const {
1576
return m_Content > rhs. m_Content ;
1577
}
1578
1579
1580
1581
1582
1583
bool IGFD:: FileInfos:: SearchForTag ( const std:: string& vTag ) const {
1584
if ( ! vTag. empty ( ) ) {
1585
if ( fileNameExt_optimized == " .." ) return true ;
1586
return fileNameExt_optimized. find ( vTag ) != std:: string:: npos ||
1587
fileNameExt. find ( vTag ) != std:: string:: npos;
1588
}
1589
1590
1591
return true ;
1592
}
1593
1594
bool IGFD:: FileInfos:: SearchForExt ( const std:: string& vExt , const bool & vIsCaseInsensitive , const size_t & vMaxLevel ) const {
1595
if ( ! vExt. empty ( ) ) {
1596
const auto & ext_to_check = vIsCaseInsensitive ? Utils:: LowerCaseString ( vExt ) : vExt;
1597
const auto & ext_levels = vIsCaseInsensitive ? fileExtLevels_optimized : fileExtLevels;
1598
if ( vMaxLevel >= 1 && countExtDot >= vMaxLevel) {
1599
for ( const auto & ext : ext_levels) {
1600
if ( ! ext. empty ( ) && ext == ext_to_check) {
1601
return true ;
1602
}
1603
}
1604
} else {
1605
return ( fileExtLevels[ 0 ] == vExt) ;
1606
}
1607
}
1608
return false ;
1609
}
1610
1611
bool IGFD:: FileInfos:: SearchForExts ( const std:: string& vComaSepExts , const bool & vIsCaseInsensitive , const size_t & vMaxLevel ) const {
1612
if ( ! vComaSepExts. empty ( ) ) {
1613
const auto & arr = Utils:: SplitStringToVector ( vComaSepExts, ' ,' , false ) ;
1614
for ( const auto & a : arr) {
1615
if ( SearchForExt ( a, vIsCaseInsensitive, vMaxLevel ) ) {
1616
return true ;
1617
}
1618
}
1619
}
1620
return false ;
1621
}
1622
1623
bool IGFD:: FileInfos:: FinalizeFileTypeParsing ( const size_t & vMaxDotToExtract ) {
1624
if ( fileType. isFile ( ) || fileType. isLinkToUnknown ( ) ) {
1625
countExtDot = Utils:: GetCharCountInString ( fileNameExt, ' .' ) ;
1626
size_t lpt = 0U ;
1627
if ( countExtDot > 1U ) {
1628
size_t max_dot_to_extract = vMaxDotToExtract;
1629
if ( max_dot_to_extract > countExtDot) {
1630
max_dot_to_extract = countExtDot;
1631
}
1632
lpt = Utils:: GetLastCharPosWithMinCharCount ( fileNameExt, ' .' , max_dot_to_extract ) ;
1633
} else {
1634
lpt = fileNameExt. find_first_of ( ' .' ) ;
1635
}
1636
if ( lpt != std:: string:: npos) {
1637
size_t lvl = 0U ;
1638
fileNameLevels[ lvl] = fileNameExt. substr ( 0 , lpt) ;
1639
fileNameLevels[ lvl] = Utils:: LowerCaseString ( fileNameLevels[ lvl] ) ;
1640
fileExtLevels[ lvl] = fileNameExt. substr ( lpt ) ;
1641
fileExtLevels_optimized[ lvl] = Utils:: LowerCaseString ( fileExtLevels[ lvl] ) ;
1642
if ( countExtDot > 1U ) {
1643
auto count = countExtDot;
1644
while ( count > 0 && lpt != std:: string:: npos && lvl < fileExtLevels. size ( ) ) {
1645
+ + lpt, + + lvl;
1646
if ( fileNameExt. size ( ) > lpt) {
1647
lpt = fileNameExt. find_first_of ( ' .' , lpt) ;
1648
if ( lpt != std:: string:: npos) {
1649
fileNameLevels[ lvl] = fileNameExt. substr ( 0 , lpt) ;
1650
fileNameLevels[ lvl] = Utils:: LowerCaseString ( fileNameLevels[ lvl] ) ;
1651
fileExtLevels[ lvl] = fileNameExt. substr ( lpt ) ;
1652
fileExtLevels_optimized[ lvl] = Utils:: LowerCaseString ( fileExtLevels[ lvl] ) ;
1653
}
1654
}
1655
}
1656
}
1657
}
1658
return true ;
1659
}
1660
return false ;
1661
}
1662
1663
1664
1665
1666
1667
IGFD:: FileManager:: FileManager ( ) {
1668
fsRoot = IGFD:: Utils:: GetPathSeparator ( ) ;
1669
m_FileSystemName = typeid ( FILE_SYSTEM_OVERRIDE ) . name ( ) ;
1670
1671
m_FileSystemPtr = std:: unique_ptr < FILE_SYSTEM_OVERRIDE> ( new FILE_SYSTEM_OVERRIDE ( ) ) ;
1672
1673
}
1674
1675
void IGFD:: FileManager:: OpenCurrentPath ( const FileDialogInternal& vFileDialogInternal ) {
1676
showDrives = false ;
1677
ClearComposer ( ) ;
1678
ClearFileLists ( ) ;
1679
if ( dLGDirectoryMode) {
1680
SetDefaultFileName ( " ." ) ;
1681
} else {
1682
SetDefaultFileName ( dLGDefaultFileName ) ;
1683
}
1684
ScanDir ( vFileDialogInternal, GetCurrentPath ( ) ) ;
1685
}
1686
1687
void IGFD:: FileManager:: SortFields ( const FileDialogInternal& vFileDialogInternal ) {
1688
m_SortFields ( vFileDialogInternal, m_FileList , m_FilteredFileList ) ;
1689
}
1690
1691
void IGFD:: FileManager:: m_SortFields ( const FileDialogInternal& vFileDialogInternal , std:: vector< std:: shared_ptr< FileInfos> > & vFileInfosList , std:: vector< std:: shared_ptr< FileInfos> > & vFileInfosFilteredList ) {
1692
static constexpr const char * defaultHeaderString[ ] = {
1693
tableHeaderFileNameString,
1694
tableHeaderFileTypeString,
1695
tableHeaderFileSizeString,
1696
tableHeaderFileDateString,
1697
#ifdef USE_THUMBNAILS
1698
tableHeaderFileThumbnailsString,
1699
#endif
1700
} ;
1701
for ( int i = 0 ; i < SortingFieldEnum:: NUM_FIELDS; + + i) {
1702
header[ i] = defaultHeaderString[ i] ;
1703
}
1704
bool ascending = sortingDirection[ sortingField] ;
1705
#ifdef USE_CUSTOM_SORTING_ICON
1706
header[ sortingField] = ( ascending ? tableHeaderAscendingIcon : tableHeaderDescendingIcon)
1707
+ header[ sortingField] ;
1708
#endif
1709
1710
std:: stable_sort ( vFileInfosList. begin ( ) , vFileInfosList. end ( ) , [ & ] ( const std:: shared_ptr< FileInfos> & a, const std:: shared_ptr< FileInfos> & b) -> bool {
1711
bool a_used = a. use_count ( ) != 0 ;
1712
bool b_used = b. use_count ( ) != 0 ;
1713
if ( a_used != b_used) return a_used < b_used;
1714
if ( ! a_used) return true ;
1715
1716
1717
bool a_not_dotdot = a-> fileNameExt != " .." ;
1718
bool b_not_dotdot = b-> fileNameExt != " .." ;
1719
if ( a_not_dotdot != b_not_dotdot) return a_not_dotdot < b_not_dotdot;
1720
1721
auto compare = [ & ] ( auto extractor) {
1722
1723
auto a_type = a-> fileType ;
1724
auto b_type = b-> fileType ;
1725
if ( a_type != b_type) return ascending ? a_type < b_type : b_type < a_type;
1726
1727
1728
auto a_properties = extractor ( a ) ;
1729
auto b_properties = extractor ( b ) ;
1730
return ascending ? a_properties < b_properties : b_properties < a_properties;
1731
} ;
1732
switch ( sortingField) {
1733
case SortingFieldEnum:: FIELD_FILENAME:
1734
return compare ( [ ] ( const auto & x) { return x-> fileNameExt_optimized ; } ) ;
1735
case SortingFieldEnum:: FIELD_TYPE:
1736
return compare ( [ ] ( const auto & x) { return x-> fileExtLevels_optimized [ 0 ] ; } ) ;
1737
case SortingFieldEnum:: FIELD_SIZE:
1738
return compare ( [ ] ( const auto & x) { return x-> fileSize ; } ) ;
1739
case SortingFieldEnum:: FIELD_DATE:
1740
return compare ( [ ] ( const auto & x) { return x-> fileModifDate ; } ) ;
1741
#ifdef USE_THUMBNAILS
1742
case SortingFieldEnum:: FIELD_THUMBNAILS:
1743
return compare ( [ ] ( const auto & x) { return std:: make_tuple ( x-> thumbnailInfo . textureWidth , x-> thumbnailInfo . textureHeight ) ; } ) ;
1744
#endif
1745
default :
1746
return false ;
1747
}
1748
} ) ;
1749
1750
m_ApplyFilteringOnFileList ( vFileDialogInternal, vFileInfosList, vFileInfosFilteredList) ;
1751
}
1752
1753
bool IGFD:: FileManager:: m_CompleteFileInfosWithUserFileAttirbutes ( const FileDialogInternal& vFileDialogInternal , const std:: shared_ptr< FileInfos> & vInfos ) {
1754
if ( vFileDialogInternal. getDialogConfig ( ) . userFileAttributes != nullptr ) {
1755
if ( ! vFileDialogInternal. getDialogConfig ( ) . userFileAttributes ( vInfos. get ( ) , vFileDialogInternal. getDialogConfig ( ) . userDatas ) ) {
1756
return false ;
1757
} else {
1758
if ( ! vInfos-> fileType . isDir ( ) ) {
1759
vInfos-> formatedFileSize = IGFD:: Utils:: FormatFileSize ( vInfos-> fileSize ) ;
1760
}
1761
}
1762
}
1763
return true ;
1764
}
1765
1766
void IGFD:: FileManager:: ClearFileLists ( ) {
1767
m_FilteredFileList . clear ( ) ;
1768
m_FileList . clear ( ) ;
1769
}
1770
1771
void IGFD:: FileManager:: ClearPathLists ( ) {
1772
m_FilteredPathList . clear ( ) ;
1773
m_PathList . clear ( ) ;
1774
}
1775
1776
void IGFD:: FileManager:: m_AddFile ( const FileDialogInternal& vFileDialogInternal , const std:: string& vPath , const std:: string& vFileName , const FileType& vFileType ) {
1777
auto infos = std:: make_shared < FileInfos> ( ) ;
1778
1779
infos-> filePath = vPath;
1780
infos-> fileNameExt = vFileName;
1781
infos-> fileNameExt_optimized = Utils:: LowerCaseString ( infos-> fileNameExt ) ;
1782
infos-> fileType = vFileType;
1783
1784
if ( infos-> fileNameExt . empty ( ) || ( infos-> fileNameExt == " ." && ! vFileDialogInternal. filterManager . dLGFilters . empty ( ) ) ) {
1785
return ;
1786
}
1787
1788
if ( infos-> fileNameExt != " .." && ( vFileDialogInternal. getDialogConfig ( ) . flags & ImGuiFileDialogFlags_DontShowHiddenFiles) && infos-> fileNameExt [ 0 ] == ' .' ) {
1789
if ( ! vFileDialogInternal. filterManager . dLGFilters . empty ( ) || ( vFileDialogInternal. filterManager . dLGFilters . empty ( ) && infos-> fileNameExt != " ." ) ) {
1790
return ;
1791
}
1792
}
1793
1794
if ( infos-> FinalizeFileTypeParsing ( vFileDialogInternal. filterManager . GetSelectedFilter ( ) . count_dots ) ) {
1795
if ( ! vFileDialogInternal. filterManager . IsCoveredByFilters ( * infos. get ( ) , ( vFileDialogInternal. getDialogConfig ( ) . flags & ImGuiFileDialogFlags_CaseInsensitiveExtention) != 0 ) ) {
1796
return ;
1797
}
1798
}
1799
1800
vFileDialogInternal. filterManager . m_FillFileStyle ( infos ) ;
1801
1802
m_CompleteFileInfos ( infos) ;
1803
1804
if ( m_CompleteFileInfosWithUserFileAttirbutes ( vFileDialogInternal, infos) ) {
1805
m_FileList . push_back ( infos ) ;
1806
}
1807
}
1808
1809
void IGFD:: FileManager:: m_AddPath ( const FileDialogInternal& vFileDialogInternal , const std:: string& vPath , const std:: string& vFileName , const FileType& vFileType ) {
1810
if ( ! vFileType. isDir ( ) ) return ;
1811
1812
auto infos = std:: make_shared < FileInfos> ( ) ;
1813
1814
infos-> filePath = vPath;
1815
infos-> fileNameExt = vFileName;
1816
infos-> fileNameExt_optimized = Utils:: LowerCaseString ( infos-> fileNameExt ) ;
1817
infos-> fileType = vFileType;
1818
1819
if ( infos-> fileNameExt . empty ( ) || ( infos-> fileNameExt == " ." && ! vFileDialogInternal. filterManager . dLGFilters . empty ( ) ) ) {
1820
return ;
1821
}
1822
1823
if ( infos-> fileNameExt != " .." && ( vFileDialogInternal. getDialogConfig ( ) . flags & ImGuiFileDialogFlags_DontShowHiddenFiles) && infos-> fileNameExt [ 0 ] == ' .' ) {
1824
if ( ! vFileDialogInternal. filterManager . dLGFilters . empty ( ) || ( vFileDialogInternal. filterManager . dLGFilters . empty ( ) && infos-> fileNameExt != " ." ) ) {
1825
return ;
1826
}
1827
}
1828
1829
vFileDialogInternal. filterManager . m_FillFileStyle ( infos ) ;
1830
1831
m_CompleteFileInfos ( infos) ;
1832
1833
if ( m_CompleteFileInfosWithUserFileAttirbutes ( vFileDialogInternal, infos) ) {
1834
m_PathList . push_back ( infos ) ;
1835
}
1836
}
1837
1838
void IGFD:: FileManager:: ScanDir ( const FileDialogInternal& vFileDialogInternal , const std:: string& vPath ) {
1839
std:: string path = vPath;
1840
1841
if ( m_CurrentPathDecomposition . empty ( ) ) {
1842
SetCurrentDir ( path ) ;
1843
}
1844
1845
if ( ! m_CurrentPathDecomposition . empty ( ) ) {
1846
#ifdef _IGFD_WIN_
1847
if ( path == fsRoot) path += IGFD:: Utils:: GetPathSeparator ( ) ;
1848
#endif
1849
1850
ClearFileLists ( ) ;
1851
1852
const auto & files = m_FileSystemPtr -> ScanDirectory ( vPath ) ;
1853
for ( const auto & file : files) {
1854
m_AddFile ( vFileDialogInternal, path, file. fileNameExt , file. fileType ) ;
1855
}
1856
1857
m_SortFields ( vFileDialogInternal, m_FileList , m_FilteredFileList ) ;
1858
}
1859
}
1860
1861
void IGFD:: FileManager:: m_ScanDirForPathSelection ( const FileDialogInternal& vFileDialogInternal , const std:: string& vPath ) {
1862
std:: string path = vPath;
1863
1864
if ( ! path. empty ( ) ) {
1865
#ifdef _IGFD_WIN_
1866
if ( path == fsRoot) path += IGFD:: Utils:: GetPathSeparator ( ) ;
1867
#endif
1868
1869
ClearPathLists ( ) ;
1870
1871
const auto & files = m_FileSystemPtr -> ScanDirectory ( path ) ;
1872
for ( const auto & file : files) {
1873
if ( file. fileType . isDir ( ) ) {
1874
m_AddPath ( vFileDialogInternal, path, file. fileNameExt , file. fileType ) ;
1875
}
1876
}
1877
1878
m_SortFields ( vFileDialogInternal, m_PathList , m_FilteredPathList ) ;
1879
}
1880
}
1881
1882
void IGFD:: FileManager:: m_OpenPathPopup ( const FileDialogInternal& vFileDialogInternal , std:: vector< std:: string> :: iterator vPathIter ) {
1883
const auto path = ComposeNewPath ( vPathIter ) ;
1884
m_ScanDirForPathSelection ( vFileDialogInternal, path) ;
1885
m_PopupComposedPath = vPathIter;
1886
ImGui:: OpenPopup ( " IGFD_Path_Popup" ) ;
1887
}
1888
1889
bool IGFD:: FileManager:: GetDrives ( ) {
1890
auto drives = m_FileSystemPtr -> GetDrivesList ( ) ;
1891
if ( ! drives. empty ( ) ) {
1892
m_CurrentPath . clear ( ) ;
1893
m_CurrentPathDecomposition . clear ( ) ;
1894
ClearFileLists ( ) ;
1895
for ( auto & drive : drives) {
1896
auto info = std:: make_shared < FileInfos> ( ) ;
1897
info-> fileNameExt = drive;
1898
info-> fileNameExt_optimized = Utils:: LowerCaseString ( drive ) ;
1899
info-> fileType . SetContent ( FileType:: ContentType:: Directory ) ;
1900
1901
if ( ! info-> fileNameExt . empty ( ) ) {
1902
m_FileList . push_back ( info ) ;
1903
}
1904
}
1905
showDrives = true ;
1906
return true ;
1907
}
1908
return false ;
1909
}
1910
1911
bool IGFD:: FileManager:: IsComposerEmpty ( ) {
1912
return m_CurrentPathDecomposition . empty ( ) ;
1913
}
1914
1915
size_t IGFD:: FileManager:: GetComposerSize ( ) {
1916
return m_CurrentPathDecomposition . size ( ) ;
1917
}
1918
1919
bool IGFD:: FileManager:: IsFileListEmpty ( ) {
1920
return m_FileList . empty ( ) ;
1921
}
1922
1923
bool IGFD:: FileManager:: IsPathListEmpty ( ) {
1924
return m_PathList . empty ( ) ;
1925
}
1926
1927
size_t IGFD:: FileManager:: GetFullFileListSize ( ) {
1928
return m_FileList . size ( ) ;
1929
}
1930
1931
std:: shared_ptr< IGFD:: FileInfos> IGFD:: FileManager:: GetFullFileAt ( size_t vIdx ) {
1932
if ( vIdx < m_FileList . size ( ) ) return m_FileList [ vIdx] ;
1933
return nullptr ;
1934
}
1935
1936
bool IGFD:: FileManager:: IsFilteredListEmpty ( ) {
1937
return m_FilteredFileList . empty ( ) ;
1938
}
1939
1940
bool IGFD:: FileManager:: IsPathFilteredListEmpty ( ) {
1941
return m_FilteredPathList . empty ( ) ;
1942
}
1943
1944
size_t IGFD:: FileManager:: GetFilteredListSize ( ) {
1945
return m_FilteredFileList . size ( ) ;
1946
}
1947
1948
size_t IGFD:: FileManager:: GetPathFilteredListSize ( ) {
1949
return m_FilteredPathList . size ( ) ;
1950
}
1951
1952
std:: shared_ptr< IGFD:: FileInfos> IGFD:: FileManager:: GetFilteredFileAt ( size_t vIdx ) {
1953
if ( vIdx < m_FilteredFileList . size ( ) ) return m_FilteredFileList [ vIdx] ;
1954
return nullptr ;
1955
}
1956
1957
std:: shared_ptr< IGFD:: FileInfos> IGFD:: FileManager:: GetFilteredPathAt ( size_t vIdx ) {
1958
if ( vIdx < m_FilteredPathList . size ( ) ) return m_FilteredPathList [ vIdx] ;
1959
return nullptr ;
1960
}
1961
1962
std:: vector< std:: string> :: iterator IGFD:: FileManager:: GetCurrentPopupComposedPath ( ) {
1963
return m_PopupComposedPath ;
1964
}
1965
1966
bool IGFD:: FileManager:: IsFileNameSelected ( const std:: string& vFileName ) {
1967
return m_SelectedFileNames . find ( vFileName ) != m_SelectedFileNames . end ( ) ;
1968
}
1969
1970
std:: string IGFD:: FileManager:: GetBack ( ) {
1971
return m_CurrentPathDecomposition . back ( ) ;
1972
}
1973
1974
void IGFD:: FileManager:: ClearComposer ( ) {
1975
m_CurrentPathDecomposition . clear ( ) ;
1976
}
1977
1978
void IGFD:: FileManager:: ClearAll ( ) {
1979
ClearComposer ( ) ;
1980
ClearFileLists ( ) ;
1981
ClearPathLists ( ) ;
1982
}
1983
void IGFD:: FileManager:: ApplyFilteringOnFileList ( const FileDialogInternal& vFileDialogInternal ) {
1984
m_ApplyFilteringOnFileList ( vFileDialogInternal, m_FileList , m_FilteredFileList ) ;
1985
}
1986
1987
void IGFD:: FileManager:: m_ApplyFilteringOnFileList ( const FileDialogInternal& vFileDialogInternal , std:: vector< std:: shared_ptr< FileInfos> > & vFileInfosList , std:: vector< std:: shared_ptr< FileInfos> > & vFileInfosFilteredList ) {
1988
vFileInfosFilteredList. clear ( ) ;
1989
for ( const auto & file : vFileInfosList) {
1990
if ( ! file. use_count ( ) ) continue ;
1991
bool show = true ;
1992
if ( ! file-> SearchForTag ( vFileDialogInternal. searchManager . searchTag ) )
1993
show = false ;
1994
if ( dLGDirectoryMode && ! file-> fileType . isDir ( ) ) show = false ;
1995
if ( show) vFileInfosFilteredList. push_back ( file ) ;
1996
}
1997
}
1998
1999
void IGFD:: FileManager:: m_CompleteFileInfos ( const std:: shared_ptr< FileInfos> & vInfos ) {
2000
if ( ! vInfos. use_count ( ) ) return ;
2001
2002
if ( vInfos-> fileNameExt != " ." && vInfos-> fileNameExt != " .." ) {
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
std:: string fpn;
2019
2020
2021
if ( vInfos-> fileType . isFile ( ) || vInfos-> fileType . isLinkToUnknown ( ) || vInfos-> fileType . isDir ( ) ) {
2022
fpn = vInfos-> filePath + IGFD:: Utils:: GetPathSeparator ( ) + vInfos-> fileNameExt ;
2023
}
2024
2025
struct stat statInfos = { } ;
2026
char timebuf[ 100 ] ;
2027
int result = stat ( fpn. c_str ( ) , & statInfos ) ;
2028
if ( ! result) {
2029
if ( ! vInfos-> fileType . isDir ( ) ) {
2030
vInfos-> fileSize = ( size_t ) statInfos. st_size ;
2031
vInfos-> formatedFileSize = IGFD:: Utils:: FormatFileSize ( vInfos-> fileSize ) ;
2032
}
2033
2034
size_t len = 0 ;
2035
#ifdef _MSC_VER
2036
struct tm _tm;
2037
errno_t err = localtime_s ( & _tm, & statInfos. st_mtime ) ;
2038
if ( ! err) len = strftime ( timebuf, 99 , DateTimeFormat, & _tm) ;
2039
#else
2040
struct tm* _tm = localtime ( & statInfos. st_mtime ) ;
2041
if ( _tm) len = strftime ( timebuf, 99 , DateTimeFormat, _tm ) ;
2042
#endif
2043
if ( len) {
2044
vInfos-> fileModifDate = std:: string ( timebuf, len ) ;
2045
}
2046
}
2047
}
2048
}
2049
2050
void IGFD:: FileManager:: m_RemoveFileNameInSelection ( const std:: string& vFileName ) {
2051
m_SelectedFileNames . erase ( vFileName ) ;
2052
2053
if ( m_SelectedFileNames . size ( ) == 1 ) {
2054
snprintf ( fileNameBuffer, MAX_FILE_DIALOG_NAME_BUFFER, " %s " , vFileName. c_str ( ) ) ;
2055
} else {
2056
snprintf ( fileNameBuffer, MAX_FILE_DIALOG_NAME_BUFFER, " %zu files Selected" , m_SelectedFileNames . size ( ) ) ;
2057
}
2058
}
2059
2060
void IGFD:: FileManager:: m_m_AddFileNameInSelection ( const std:: string& vFileName , bool vSetLastSelectionFileName ) {
2061
m_SelectedFileNames . emplace ( vFileName ) ;
2062
2063
if ( m_SelectedFileNames . size ( ) == 1 ) {
2064
snprintf ( fileNameBuffer, MAX_FILE_DIALOG_NAME_BUFFER, " %s " , vFileName. c_str ( ) ) ;
2065
} else {
2066
snprintf ( fileNameBuffer, MAX_FILE_DIALOG_NAME_BUFFER, " %zu files Selected" , m_SelectedFileNames . size ( ) ) ;
2067
}
2068
2069
if ( vSetLastSelectionFileName) m_LastSelectedFileName = vFileName;
2070
}
2071
2072
void IGFD:: FileManager:: SetCurrentDir ( const std:: string& vPath ) {
2073
std:: string path = vPath;
2074
#ifdef _IGFD_WIN_
2075
if ( fsRoot == path) path += IGFD:: Utils:: GetPathSeparator ( ) ;
2076
#endif
2077
2078
bool dir_opened = m_FileSystemPtr -> IsDirectory ( path ) ;
2079
if ( ! dir_opened) {
2080
path = " ." ;
2081
dir_opened = m_FileSystemPtr -> IsDirectory ( path ) ;
2082
}
2083
if ( dir_opened) {
2084
#ifdef _IGFD_WIN_
2085
DWORD numchar = 0 ;
2086
std:: wstring wpath = IGFD:: Utils:: UTF8Decode ( path) ;
2087
numchar = GetFullPathNameW ( wpath. c_str ( ) , 0 , nullptr , nullptr ) ;
2088
std:: wstring fpath ( numchar, 0 ) ;
2089
GetFullPathNameW ( wpath. c_str ( ) , numchar, ( wchar_t * ) fpath. data ( ) , nullptr ) ;
2090
std:: string real_path = IGFD:: Utils:: UTF8Encode ( fpath) ;
2091
while ( real_path. back ( ) == ' \0 ' )
2092
real_path = real_path. substr ( 0 , real_path. size ( ) - 1U ) ;
2093
if ( ! real_path. empty ( ) )
2094
#elif defined (_IGFD_UNIX_)
2095
char real_path[ PATH_MAX] ;
2096
char * numchar = realpath ( path. c_str ( ) , real_path ) ;
2097
if ( numchar != nullptr )
2098
#endif
2099
{
2100
m_CurrentPath = std:: move ( real_path ) ;
2101
if ( m_CurrentPath [ m_CurrentPath . size ( ) - 1 ] == PATH_SEP) {
2102
m_CurrentPath = m_CurrentPath . substr ( 0 , m_CurrentPath . size ( ) - 1 ) ;
2103
}
2104
IGFD:: Utils:: SetBuffer ( inputPathBuffer, MAX_PATH_BUFFER_SIZE, m_CurrentPath ) ;
2105
m_CurrentPathDecomposition = IGFD:: Utils:: SplitStringToVector ( m_CurrentPath , PATH_SEP, false ) ;
2106
#ifdef _IGFD_UNIX_
2107
m_CurrentPathDecomposition . insert ( m_CurrentPathDecomposition . begin ( ) , IGFD:: Utils:: GetPathSeparator ( ) ) ;
2108
#endif
2109
if ( ! m_CurrentPathDecomposition . empty ( ) ) {
2110
#ifdef _IGFD_WIN_
2111
fsRoot = m_CurrentPathDecomposition [ 0 ] ;
2112
#endif
2113
}
2114
}
2115
}
2116
}
2117
2118
bool IGFD:: FileManager:: CreateDir ( const std:: string& vPath ) {
2119
if ( ! vPath. empty ( ) ) {
2120
std:: string path = m_CurrentPath + IGFD:: Utils:: GetPathSeparator ( ) + vPath;
2121
return m_FileSystemPtr -> CreateDirectoryIfNotExist ( path ) ;
2122
}
2123
return false ;
2124
}
2125
2126
std:: string IGFD:: FileManager:: ComposeNewPath ( std:: vector< std:: string> :: iterator vIter ) {
2127
std:: string res;
2128
2129
while ( true ) {
2130
if ( ! res. empty ( ) ) {
2131
#ifdef _IGFD_WIN_
2132
res = * vIter + IGFD:: Utils:: GetPathSeparator ( ) + res;
2133
#elif defined (_IGFD_UNIX_)
2134
if ( * vIter == fsRoot)
2135
res = * vIter + res;
2136
else
2137
res = * vIter + PATH_SEP + res;
2138
#endif
2139
} else
2140
res = * vIter;
2141
2142
if ( vIter == m_CurrentPathDecomposition . begin ( ) ) {
2143
#ifdef _IGFD_UNIX_
2144
if ( res[ 0 ] != PATH_SEP) res = PATH_SEP + res;
2145
#else
2146
if ( res. back ( ) != PATH_SEP) res. push_back ( PATH_SEP ) ;
2147
#endif
2148
break ;
2149
}
2150
2151
- - vIter;
2152
}
2153
2154
return res;
2155
}
2156
2157
bool IGFD:: FileManager:: SetPathOnParentDirectoryIfAny ( ) {
2158
if ( m_CurrentPathDecomposition . size ( ) > 1 ) {
2159
m_CurrentPath = ComposeNewPath ( m_CurrentPathDecomposition . end ( ) - 2 ) ;
2160
return true ;
2161
}
2162
return false ;
2163
}
2164
2165
std:: string IGFD:: FileManager:: GetCurrentPath ( ) {
2166
if ( m_CurrentPath . empty ( ) ) m_CurrentPath = " ." ;
2167
return m_CurrentPath ;
2168
}
2169
2170
void IGFD:: FileManager:: SetCurrentPath ( const std:: string& vCurrentPath ) {
2171
if ( vCurrentPath. empty ( ) )
2172
m_CurrentPath = " ." ;
2173
else
2174
m_CurrentPath = vCurrentPath;
2175
}
2176
2177
void IGFD:: FileManager:: SetDefaultFileName ( const std:: string& vFileName ) {
2178
dLGDefaultFileName = vFileName;
2179
IGFD:: Utils:: SetBuffer ( fileNameBuffer, MAX_FILE_DIALOG_NAME_BUFFER, vFileName ) ;
2180
}
2181
2182
bool IGFD:: FileManager:: SelectDirectory ( const std:: shared_ptr< FileInfos> & vInfos ) {
2183
if ( ! vInfos. use_count ( ) ) return false ;
2184
2185
bool pathClick = false ;
2186
2187
if ( vInfos-> fileNameExt == " .." ) {
2188
pathClick = SetPathOnParentDirectoryIfAny ( ) ;
2189
} else {
2190
std:: string newPath;
2191
2192
if ( showDrives) {
2193
newPath = vInfos-> fileNameExt + IGFD:: Utils:: GetPathSeparator ( ) ;
2194
} else {
2195
#ifdef __linux__
2196
if ( fsRoot == m_CurrentPath )
2197
newPath = m_CurrentPath + vInfos-> fileNameExt ;
2198
else
2199
#endif
2200
newPath = m_CurrentPath + IGFD:: Utils:: GetPathSeparator ( ) + vInfos-> fileNameExt ;
2201
}
2202
2203
if ( m_FileSystemPtr -> IsDirectoryCanBeOpened ( newPath ) ) {
2204
if ( showDrives) {
2205
m_CurrentPath = vInfos-> fileNameExt ;
2206
fsRoot = m_CurrentPath ;
2207
} else {
2208
m_CurrentPath = newPath;
2209
}
2210
pathClick = true ;
2211
}
2212
}
2213
2214
return pathClick;
2215
}
2216
2217
void IGFD:: FileManager:: SelectFileName ( const FileDialogInternal& vFileDialogInternal , const std:: shared_ptr< FileInfos> & vInfos ) {
2218
if ( ! vInfos. use_count ( ) ) return ;
2219
2220
if ( ImGui:: IsKeyDown ( ImGuiMod_Ctrl ) ) {
2221
if ( dLGcountSelectionMax == 0 )
2222
{
2223
if ( m_SelectedFileNames . find ( vInfos-> fileNameExt ) == m_SelectedFileNames . end ( ) )
2224
{
2225
m_m_AddFileNameInSelection ( vInfos-> fileNameExt , true ) ;
2226
} else {
2227
m_RemoveFileNameInSelection ( vInfos-> fileNameExt ) ;
2228
}
2229
} else
2230
{
2231
if ( m_SelectedFileNames . size ( ) < dLGcountSelectionMax) {
2232
if ( m_SelectedFileNames . find ( vInfos-> fileNameExt ) == m_SelectedFileNames . end ( ) )
2233
{
2234
m_m_AddFileNameInSelection ( vInfos-> fileNameExt , true ) ;
2235
} else {
2236
m_RemoveFileNameInSelection ( vInfos-> fileNameExt ) ;
2237
}
2238
}
2239
}
2240
} else if ( ImGui:: IsKeyDown ( ImGuiMod_Shift ) ) {
2241
if ( dLGcountSelectionMax != 1 ) {
2242
m_SelectedFileNames . clear ( ) ;
2243
2244
bool startMultiSelection = false ;
2245
std:: string fileNameToSelect = vInfos-> fileNameExt ;
2246
std:: string savedLastSelectedFileName;
2247
for ( const auto & file : m_FileList ) {
2248
if ( ! file. use_count ( ) ) continue ;
2249
2250
bool canTake = true ;
2251
if ( ! file-> SearchForTag ( vFileDialogInternal. searchManager . searchTag ) ) canTake = false ;
2252
if ( canTake)
2253
{
2254
if ( file-> fileNameExt == m_LastSelectedFileName ) {
2255
startMultiSelection = true ;
2256
m_m_AddFileNameInSelection ( m_LastSelectedFileName , false ) ;
2257
} else if ( startMultiSelection) {
2258
if ( dLGcountSelectionMax == 0 )
2259
{
2260
m_m_AddFileNameInSelection ( file-> fileNameExt , false ) ;
2261
} else {
2262
if ( m_SelectedFileNames . size ( ) < dLGcountSelectionMax) {
2263
m_m_AddFileNameInSelection ( file-> fileNameExt , false ) ;
2264
} else {
2265
startMultiSelection = false ;
2266
if ( ! savedLastSelectedFileName. empty ( ) ) m_LastSelectedFileName = savedLastSelectedFileName;
2267
break ;
2268
}
2269
}
2270
}
2271
2272
if ( file-> fileNameExt == fileNameToSelect) {
2273
if ( ! startMultiSelection)
2274
{
2275
savedLastSelectedFileName = m_LastSelectedFileName ;
2276
m_LastSelectedFileName = fileNameToSelect;
2277
fileNameToSelect = savedLastSelectedFileName;
2278
startMultiSelection = true ;
2279
m_m_AddFileNameInSelection ( m_LastSelectedFileName , false ) ;
2280
} else {
2281
startMultiSelection = false ;
2282
if ( ! savedLastSelectedFileName. empty ( ) ) m_LastSelectedFileName = savedLastSelectedFileName;
2283
break ;
2284
}
2285
}
2286
}
2287
}
2288
}
2289
} else {
2290
m_SelectedFileNames . clear ( ) ;
2291
IGFD:: Utils:: ResetBuffer ( fileNameBuffer ) ;
2292
m_m_AddFileNameInSelection ( vInfos-> fileNameExt , true ) ;
2293
}
2294
}
2295
2296
void IGFD:: FileManager:: DrawDirectoryCreation ( const FileDialogInternal& vFileDialogInternal ) {
2297
if ( vFileDialogInternal. getDialogConfig ( ) . flags & ImGuiFileDialogFlags_DisableCreateDirectoryButton) return ;
2298
2299
if ( IMGUI_BUTTON ( createDirButtonString ) ) {
2300
if ( ! m_CreateDirectoryMode ) {
2301
m_CreateDirectoryMode = true ;
2302
IGFD:: Utils:: ResetBuffer ( directoryNameBuffer ) ;
2303
}
2304
}
2305
if ( ImGui:: IsItemHovered ( ) ) ImGui:: SetTooltip ( buttonCreateDirString ) ;
2306
2307
if ( m_CreateDirectoryMode ) {
2308
ImGui:: SameLine ( ) ;
2309
2310
ImGui:: PushItemWidth ( 100.0f ) ;
2311
ImGui:: InputText ( " ##DirectoryFileName" , directoryNameBuffer, MAX_FILE_DIALOG_NAME_BUFFER) ;
2312
ImGui:: PopItemWidth ( ) ;
2313
2314
ImGui:: SameLine ( ) ;
2315
2316
if ( IMGUI_BUTTON ( okButtonString ) ) {
2317
std:: string newDir = std:: string ( directoryNameBuffer ) ;
2318
if ( CreateDir ( newDir ) ) {
2319
SetCurrentPath ( m_CurrentPath + IGFD:: Utils:: GetPathSeparator ( ) + newDir) ;
2320
OpenCurrentPath ( vFileDialogInternal ) ;
2321
}
2322
2323
m_CreateDirectoryMode = false ;
2324
}
2325
2326
ImGui:: SameLine ( ) ;
2327
2328
if ( IMGUI_BUTTON ( cancelButtonString ) ) {
2329
m_CreateDirectoryMode = false ;
2330
}
2331
}
2332
2333
ImGui:: SameLine ( ) ;
2334
}
2335
2336
void IGFD:: FileManager:: DrawPathComposer ( const FileDialogInternal& vFileDialogInternal ) {
2337
if ( IMGUI_BUTTON ( resetButtonString ) ) {
2338
SetCurrentPath ( " ." ) ;
2339
OpenCurrentPath ( vFileDialogInternal ) ;
2340
}
2341
if ( ImGui:: IsItemHovered ( ) ) ImGui:: SetTooltip ( buttonResetPathString ) ;
2342
2343
#ifdef _IGFD_WIN_
2344
ImGui:: SameLine ( ) ;
2345
2346
if ( IMGUI_BUTTON ( drivesButtonString ) ) {
2347
drivesClicked = true ;
2348
}
2349
if ( ImGui:: IsItemHovered ( ) ) ImGui:: SetTooltip ( buttonDriveString) ;
2350
#endif
2351
2352
ImGui:: SameLine ( ) ;
2353
2354
if ( IMGUI_BUTTON ( editPathButtonString ) ) {
2355
inputPathActivated = ! inputPathActivated;
2356
if ( inputPathActivated) {
2357
if ( ! m_CurrentPathDecomposition . empty ( ) ) {
2358
auto endIt = m_CurrentPathDecomposition . end ( ) ;
2359
m_CurrentPath = ComposeNewPath ( - - endIt) ;
2360
IGFD:: Utils:: SetBuffer ( inputPathBuffer, MAX_PATH_BUFFER_SIZE, m_CurrentPath ) ;
2361
}
2362
}
2363
}
2364
if ( ImGui:: IsItemHovered ( ) ) ImGui:: SetTooltip ( buttonEditPathString ) ;
2365
2366
ImGui:: SameLine ( ) ;
2367
2368
ImGui:: SeparatorEx ( ImGuiSeparatorFlags_Vertical ) ;
2369
2370
2371
if ( ! m_CurrentPathDecomposition . empty ( ) ) {
2372
ImGui:: SameLine ( ) ;
2373
2374
if ( inputPathActivated) {
2375
ImGui:: PushItemWidth ( ImGui:: GetContentRegionAvail ( ) . x ) ;
2376
ImGui:: InputText ( " ##pathedition" , inputPathBuffer, MAX_PATH_BUFFER_SIZE) ;
2377
ImGui:: PopItemWidth ( ) ;
2378
} else {
2379
int _id = 0 ;
2380
for ( auto itPathDecomp = m_CurrentPathDecomposition . begin ( ) ; itPathDecomp != m_CurrentPathDecomposition . end ( ) ; + + itPathDecomp) {
2381
if ( itPathDecomp != m_CurrentPathDecomposition . begin ( ) ) {
2382
#if defined (CUSTOM_PATH_SPACING)
2383
ImGui:: SameLine ( 0 , CUSTOM_PATH_SPACING) ;
2384
#else
2385
ImGui:: SameLine ( ) ;
2386
#endif
2387
if ( ! ( vFileDialogInternal. getDialogConfig ( ) . flags & ImGuiFileDialogFlags_DisableQuickPathSelection) ) {
2388
#if defined (_IGFD_WIN_)
2389
const char * sep = " \\ " ;
2390
#elif defined (_IGFD_UNIX_)
2391
const char * sep = " /" ;
2392
if ( itPathDecomp != m_CurrentPathDecomposition . begin ( ) + 1 )
2393
#endif
2394
{
2395
ImGui:: PushID ( _id+ + ) ;
2396
bool click = IMGUI_PATH_BUTTON ( sep ) ;
2397
ImGui:: PopID ( ) ;
2398
2399
#if defined (CUSTOM_PATH_SPACING)
2400
ImGui:: SameLine ( 0 , CUSTOM_PATH_SPACING) ;
2401
#else
2402
ImGui:: SameLine ( ) ;
2403
#endif
2404
2405
if ( click) {
2406
m_OpenPathPopup ( vFileDialogInternal, itPathDecomp - 1 ) ;
2407
} else if ( ImGui:: IsItemClicked ( ImGuiMouseButton_Right ) ) {
2408
m_SetCurrentPath ( itPathDecomp - 1 ) ;
2409
break ;
2410
}
2411
}
2412
}
2413
}
2414
2415
ImGui:: PushID ( _id+ + ) ;
2416
bool click = IMGUI_PATH_BUTTON ( ( * itPathDecomp) . c_str ( ) ) ;
2417
ImGui:: PopID ( ) ;
2418
if ( click) {
2419
m_CurrentPath = ComposeNewPath ( itPathDecomp ) ;
2420
puPathClicked = true ;
2421
break ;
2422
} else if ( ImGui:: IsItemClicked ( ImGuiMouseButton_Right ) ) {
2423
m_SetCurrentPath ( itPathDecomp) ;
2424
break ;
2425
}
2426
}
2427
}
2428
}
2429
}
2430
2431
void IGFD:: FileManager:: m_SetCurrentPath ( std:: vector< std:: string> :: iterator vPathIter ) {
2432
m_CurrentPath = ComposeNewPath ( vPathIter ) ;
2433
IGFD:: Utils:: SetBuffer ( inputPathBuffer, MAX_PATH_BUFFER_SIZE, m_CurrentPath ) ;
2434
inputPathActivated = true ;
2435
}
2436
2437
std:: string IGFD:: FileManager:: GetResultingPath ( ) {
2438
if ( dLGDirectoryMode && m_SelectedFileNames . size ( ) == 1 ) {
2439
std:: string selectedDirectory = fileNameBuffer;
2440
std:: string path = m_CurrentPath ;
2441
if ( ! selectedDirectory. empty ( ) && selectedDirectory != " ." ) {
2442
path += IGFD:: Utils:: GetPathSeparator ( ) + selectedDirectory;
2443
}
2444
return path;
2445
}
2446
return m_CurrentPath ;
2447
}
2448
2449
std:: string IGFD:: FileManager:: GetResultingFileName ( FileDialogInternal& vFileDialogInternal , IGFD_ResultMode vFlag ) {
2450
if ( ! dLGDirectoryMode) {
2451
const auto & filename = std:: string ( fileNameBuffer ) ;
2452
return vFileDialogInternal. filterManager . ReplaceExtentionWithCurrentFilterIfNeeded ( filename, vFlag ) ;
2453
}
2454
return " " ;
2455
}
2456
2457
std:: string IGFD:: FileManager:: GetResultingFilePathName ( FileDialogInternal& vFileDialogInternal , IGFD_ResultMode vFlag ) {
2458
if ( ! dLGDirectoryMode) {
2459
auto result = GetResultingPath ( ) ;
2460
const auto & filename = GetResultingFileName ( vFileDialogInternal, vFlag ) ;
2461
if ( ! filename. empty ( ) ) {
2462
if ( m_FileSystemPtr != nullptr && m_FileSystemPtr -> IsFileExist ( filename ) ) {
2463
result = filename;
2464
} else {
2465
#ifdef _IGFD_UNIX_
2466
if ( fsRoot != result)
2467
#endif
2468
{
2469
result += IGFD:: Utils:: GetPathSeparator ( ) ;
2470
}
2471
result += filename;
2472
}
2473
}
2474
2475
return result;
2476
}
2477
return " " ;
2478
}
2479
2480
std:: map< std:: string, std:: string> IGFD:: FileManager:: GetResultingSelection ( FileDialogInternal& vFileDialogInternal , IGFD_ResultMode vFlag ) {
2481
std:: map< std:: string, std:: string> res;
2482
for ( const auto & selectedFileName : m_SelectedFileNames ) {
2483
auto result = GetResultingPath ( ) ;
2484
#ifdef _IGFD_UNIX_
2485
if ( fsRoot != result)
2486
#endif
2487
{
2488
result += IGFD:: Utils:: GetPathSeparator ( ) ;
2489
}
2490
result += vFileDialogInternal. filterManager . ReplaceExtentionWithCurrentFilterIfNeeded ( selectedFileName, vFlag ) ;
2491
res[ selectedFileName] = result;
2492
}
2493
return res;
2494
}
2495
2496
2497
2498
2499
2500
void IGFD:: FileDialogInternal:: NewFrame ( ) {
2501
canWeContinue = true ;
2502
isOk = false ;
2503
fileManager. drivesClicked = false ;
2504
fileManager. puPathClicked = false ;
2505
2506
needToExitDialog = false ;
2507
2508
#ifdef USE_DIALOG_EXIT_WITH_KEY
2509
if ( ImGui:: IsKeyPressed ( IGFD_EXIT_KEY ) ) {
2510
2511
2512
2513
if ( ! ( fileManager. inputPathActivated || searchManager. searchInputIsActive || fileInputIsActive || fileListViewIsActive) ) {
2514
needToExitDialog = true ;
2515
}
2516
} else
2517
#endif
2518
{
2519
searchManager. searchInputIsActive = false ;
2520
fileInputIsActive = false ;
2521
fileListViewIsActive = false ;
2522
}
2523
}
2524
2525
void IGFD:: FileDialogInternal:: EndFrame ( ) {
2526
2527
if ( fileManager. puPathClicked ) {
2528
fileManager. OpenCurrentPath ( * this ) ;
2529
}
2530
2531
if ( fileManager. drivesClicked ) {
2532
if ( fileManager. GetDrives ( ) ) {
2533
fileManager. ApplyFilteringOnFileList ( * this ) ;
2534
}
2535
}
2536
2537
if ( fileManager. inputPathActivated ) {
2538
auto gio = ImGui:: GetIO ( ) ;
2539
if ( ImGui:: IsKeyReleased ( ImGuiKey_Enter ) ) {
2540
fileManager. SetCurrentPath ( std:: string ( fileManager. inputPathBuffer ) ) ;
2541
fileManager. OpenCurrentPath ( * this ) ;
2542
fileManager. inputPathActivated = false ;
2543
}
2544
if ( ImGui:: IsKeyReleased ( ImGuiKey_Escape ) ) {
2545
fileManager. inputPathActivated = false ;
2546
}
2547
}
2548
}
2549
2550
void IGFD:: FileDialogInternal:: ResetForNewDialog ( ) {
2551
}
2552
2553
void IGFD:: FileDialogInternal:: configureDialog ( const std:: string& vKey , const std:: string& vTitle , const char * vFilters , const FileDialogConfig& vConfig ) {
2554
m_DialogConfig = vConfig;
2555
ResetForNewDialog ( ) ;
2556
dLGkey = vKey;
2557
dLGtitle = vTitle;
2558
2559
2560
if ( m_DialogConfig . sidePane == nullptr ) {
2561
m_DialogConfig . sidePaneWidth = 0.0f ;
2562
}
2563
2564
if ( m_DialogConfig . filePathName . empty ( ) ) {
2565
if ( m_DialogConfig . path . empty ( ) ) {
2566
fileManager. dLGpath = fileManager. GetCurrentPath ( ) ;
2567
} else {
2568
fileManager. dLGpath = m_DialogConfig . path ;
2569
}
2570
fileManager. SetCurrentPath ( m_DialogConfig . path ) ;
2571
fileManager. dLGcountSelectionMax = ( size_t ) m_DialogConfig . countSelectionMax ;
2572
fileManager. SetDefaultFileName ( m_DialogConfig . fileName ) ;
2573
} else {
2574
auto ps = fileManager. GetFileSystemInstance ( ) -> ParsePathFileName ( m_DialogConfig . filePathName ) ;
2575
if ( ps. isOk ) {
2576
fileManager. dLGpath = ps. path ;
2577
fileManager. SetDefaultFileName ( ps. name ) ;
2578
filterManager. dLGdefaultExt = " ." + ps. ext ;
2579
} else {
2580
fileManager. dLGpath = fileManager. GetCurrentPath ( ) ;
2581
fileManager. SetDefaultFileName ( " " ) ;
2582
filterManager. dLGdefaultExt . clear ( ) ;
2583
}
2584
}
2585
2586
filterManager. dLGdefaultExt . clear ( ) ;
2587
filterManager. ParseFilters ( vFilters ) ;
2588
filterManager. SetSelectedFilterWithExt ( filterManager. dLGdefaultExt ) ;
2589
fileManager. SetCurrentPath ( fileManager. dLGpath ) ;
2590
fileManager. dLGDirectoryMode = ( vFilters == nullptr ) ;
2591
fileManager. dLGcountSelectionMax = m_DialogConfig . countSelectionMax ;
2592
fileManager. ClearAll ( ) ;
2593
showDialog = true ;
2594
}
2595
2596
const IGFD:: FileDialogConfig& IGFD:: FileDialogInternal:: getDialogConfig ( ) const {
2597
return m_DialogConfig ;
2598
}
2599
2600
IGFD:: FileDialogConfig& IGFD:: FileDialogInternal:: getDialogConfigRef ( ) {
2601
return m_DialogConfig ;
2602
}
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
IGFD:: ThumbnailFeature:: ThumbnailFeature ( ) {
2613
#ifdef USE_THUMBNAILS
2614
m_DisplayMode = DisplayModeEnum:: FILE_LIST;
2615
#endif
2616
}
2617
2618
IGFD:: ThumbnailFeature:: ~ThumbnailFeature ( ) = default ;
2619
2620
void IGFD:: ThumbnailFeature:: m_NewThumbnailFrame ( FileDialogInternal& ) {
2621
#ifdef USE_THUMBNAILS
2622
m_StartThumbnailFileDatasExtraction ( ) ;
2623
#endif
2624
}
2625
2626
void IGFD:: ThumbnailFeature:: m_EndThumbnailFrame ( FileDialogInternal& vFileDialogInternal ) {
2627
#ifdef USE_THUMBNAILS
2628
m_ClearThumbnails ( vFileDialogInternal) ;
2629
#else
2630
( void ) vFileDialogInternal;
2631
#endif
2632
}
2633
2634
void IGFD:: ThumbnailFeature:: m_QuitThumbnailFrame ( FileDialogInternal& vFileDialogInternal ) {
2635
#ifdef USE_THUMBNAILS
2636
m_StopThumbnailFileDatasExtraction ( ) ;
2637
m_ClearThumbnails ( vFileDialogInternal) ;
2638
#else
2639
( void ) vFileDialogInternal;
2640
#endif
2641
}
2642
2643
#ifdef USE_THUMBNAILS
2644
void IGFD:: ThumbnailFeature:: m_StartThumbnailFileDatasExtraction ( ) {
2645
const bool res = m_ThumbnailGenerationThread . use_count ( ) && m_ThumbnailGenerationThread -> joinable ( ) ;
2646
if ( ! res) {
2647
m_IsWorking = true ;
2648
m_CountFiles = 0U ;
2649
m_ThumbnailGenerationThread = std:: shared_ptr < std:: thread> ( new std:: thread ( & IGFD:: ThumbnailFeature:: m_ThreadThumbnailFileDatasExtractionFunc , this ) , [ this ] ( std:: thread* obj) {
2650
m_IsWorking = false ;
2651
if ( obj) {
2652
m_ThumbnailFileDatasToGetCv . notify_all ( ) ;
2653
obj-> join ( ) ;
2654
}
2655
} ) ;
2656
}
2657
}
2658
2659
bool IGFD:: ThumbnailFeature:: m_StopThumbnailFileDatasExtraction ( ) {
2660
const bool res = m_ThumbnailGenerationThread . use_count ( ) && m_ThumbnailGenerationThread -> joinable ( ) ;
2661
if ( res) {
2662
m_ThumbnailGenerationThread . reset ( ) ;
2663
}
2664
2665
return res;
2666
}
2667
2668
void IGFD:: ThumbnailFeature:: m_ThreadThumbnailFileDatasExtractionFunc ( ) {
2669
m_CountFiles = 0U ;
2670
m_IsWorking = true ;
2671
2672
2673
while ( m_IsWorking ) {
2674
std:: unique_lock< std:: mutex> thumbnailFileDatasToGetLock ( m_ThumbnailFileDatasToGetMutex ) ;
2675
m_ThumbnailFileDatasToGetCv . wait ( thumbnailFileDatasToGetLock ) ;
2676
if ( ! m_ThumbnailFileDatasToGet . empty ( ) ) {
2677
std:: shared_ptr< FileInfos> file = nullptr ;
2678
2679
file = ( * m_ThumbnailFileDatasToGet . begin ( ) ) ;
2680
m_ThumbnailFileDatasToGet . pop_front ( ) ;
2681
thumbnailFileDatasToGetLock. unlock ( ) ;
2682
2683
2684
if ( file. use_count ( ) ) {
2685
if ( file-> fileType . isFile ( ) )
2686
{
2687
2688
if ( file-> SearchForExts ( " .png,.bmp,.tga,.jpg,.jpeg,.gif,.psd,.pic,.ppm,.pgm" , true ) ) {
2689
auto fpn = file-> filePath + IGFD:: Utils:: GetPathSeparator ( ) + file-> fileNameExt ;
2690
2691
int w = 0 ;
2692
int h = 0 ;
2693
int chans = 0 ;
2694
uint8_t * datas = stbi_load ( fpn. c_str ( ) , & w, & h, & chans, STBI_rgb_alpha ) ;
2695
if ( datas) {
2696
if ( w && h) {
2697
2698
const float ratioX = ( float ) w / ( float ) h;
2699
const float newX = DisplayMode_ThumbailsList_ImageHeight * ratioX;
2700
float newY = w / ratioX;
2701
if ( newX < w) newY = DisplayMode_ThumbailsList_ImageHeight;
2702
2703
const auto newWidth = ( int ) newX;
2704
const auto newHeight = ( int ) newY;
2705
const auto newBufSize = ( size_t ) ( newWidth * newHeight * 4U ) ;
2706
auto resizedData = new uint8_t [ newBufSize] ;
2707
2708
const int resizeSucceeded = stbir_resize_uint8 ( datas, w, h, 0 , resizedData, newWidth, newHeight, 0 ,
2709
4 ) ;
2710
2711
if ( resizeSucceeded) {
2712
auto th = & file-> thumbnailInfo ;
2713
2714
th-> textureFileDatas = resizedData;
2715
th-> textureWidth = newWidth;
2716
th-> textureHeight = newHeight;
2717
th-> textureChannels = 4 ;
2718
2719
2720
2721
th-> isReadyToUpload = true ;
2722
2723
2724
m_AddThumbnailToCreate ( file) ;
2725
}
2726
} else {
2727
printf ( " image loading fail : w:%i h:%i c:%i \n " , w, h, 4 ) ;
2728
}
2729
2730
stbi_image_free ( datas ) ;
2731
}
2732
}
2733
}
2734
}
2735
} else {
2736
thumbnailFileDatasToGetLock. unlock ( ) ;
2737
}
2738
}
2739
}
2740
2741
void IGFD:: ThumbnailFeature:: m_VariadicProgressBar ( float fraction , const ImVec2& size_arg , const char * fmt , ... ) {
2742
va_list args;
2743
va_start ( args, fmt ) ;
2744
char TempBuffer[ 512 ] ;
2745
const int w = vsnprintf ( TempBuffer, 511 , fmt, args ) ;
2746
va_end ( args ) ;
2747
if ( w) {
2748
ImGui:: ProgressBar ( fraction, size_arg, TempBuffer ) ;
2749
}
2750
}
2751
2752
void IGFD:: ThumbnailFeature:: m_DrawThumbnailGenerationProgress ( ) {
2753
if ( m_ThumbnailGenerationThread . use_count ( ) && m_ThumbnailGenerationThread -> joinable ( ) ) {
2754
if ( ! m_ThumbnailFileDatasToGet . empty ( ) ) {
2755
const auto p = ( float ) ( ( double ) m_CountFiles / ( double ) m_ThumbnailFileDatasToGet . size ( ) ) ;
2756
m_VariadicProgressBar ( p, ImVec2 ( 50 , 0 ) , " %u /%u " , m_CountFiles ,
2757
( uint32_t ) m_ThumbnailFileDatasToGet . size ( ) ) ;
2758
ImGui:: SameLine ( ) ;
2759
}
2760
}
2761
}
2762
2763
void IGFD:: ThumbnailFeature:: m_AddThumbnailToLoad ( const std:: shared_ptr< FileInfos> & vFileInfos ) {
2764
if ( vFileInfos. use_count ( ) ) {
2765
if ( vFileInfos-> fileType . isFile ( ) ) {
2766
2767
if ( vFileInfos-> SearchForExts ( " .png,.bmp,.tga,.jpg,.jpeg,.gif,.psd,.pic,.ppm,.pgm" , true ) ) {
2768
2769
m_ThumbnailFileDatasToGetMutex . lock ( ) ;
2770
m_ThumbnailFileDatasToGet . push_back ( vFileInfos ) ;
2771
vFileInfos-> thumbnailInfo . isLoadingOrLoaded = true ;
2772
m_ThumbnailFileDatasToGetMutex . unlock ( ) ;
2773
m_ThumbnailFileDatasToGetCv . notify_all ( ) ;
2774
}
2775
}
2776
}
2777
}
2778
2779
void IGFD:: ThumbnailFeature:: m_AddThumbnailToCreate ( const std:: shared_ptr< FileInfos> & vFileInfos ) {
2780
if ( vFileInfos. use_count ( ) ) {
2781
2782
m_ThumbnailToCreateMutex . lock ( ) ;
2783
m_ThumbnailToCreate . push_back ( vFileInfos ) ;
2784
m_ThumbnailToCreateMutex . unlock ( ) ;
2785
}
2786
}
2787
2788
void IGFD:: ThumbnailFeature:: m_AddThumbnailToDestroy ( const IGFD_Thumbnail_Info& vIGFD_Thumbnail_Info ) {
2789
2790
m_ThumbnailToDestroyMutex . lock ( ) ;
2791
m_ThumbnailToDestroy . push_back ( vIGFD_Thumbnail_Info ) ;
2792
m_ThumbnailToDestroyMutex . unlock ( ) ;
2793
}
2794
2795
void IGFD:: ThumbnailFeature:: m_DrawDisplayModeToolBar ( ) {
2796
if ( IMGUI_RADIO_BUTTON ( DisplayMode_FilesList_ButtonString, m_DisplayMode == DisplayModeEnum:: FILE_LIST ) ) m_DisplayMode = DisplayModeEnum:: FILE_LIST;
2797
if ( ImGui:: IsItemHovered ( ) ) ImGui:: SetTooltip ( DisplayMode_FilesList_ButtonHelp ) ;
2798
ImGui:: SameLine ( ) ;
2799
if ( IMGUI_RADIO_BUTTON ( DisplayMode_ThumbailsList_ButtonString, m_DisplayMode == DisplayModeEnum:: THUMBNAILS_LIST ) ) m_DisplayMode = DisplayModeEnum:: THUMBNAILS_LIST;
2800
if ( ImGui:: IsItemHovered ( ) ) ImGui:: SetTooltip ( DisplayMode_ThumbailsList_ButtonHelp ) ;
2801
ImGui:: SameLine ( ) ;
2802
2803
2804
2805
2806
2807
2808
2809
m_DrawThumbnailGenerationProgress ( ) ;
2810
}
2811
2812
void IGFD:: ThumbnailFeature:: m_ClearThumbnails ( FileDialogInternal& vFileDialogInternal ) {
2813
2814
if ( vFileDialogInternal. fileManager . puPathClicked ) {
2815
size_t count = vFileDialogInternal. fileManager . GetFullFileListSize ( ) ;
2816
for ( size_t idx = 0U ; idx < count; idx+ + ) {
2817
auto file = vFileDialogInternal. fileManager . GetFullFileAt ( idx ) ;
2818
if ( file. use_count ( ) ) {
2819
if ( file-> thumbnailInfo . isReadyToDisplay )
2820
{
2821
m_AddThumbnailToDestroy ( file-> thumbnailInfo ) ;
2822
}
2823
}
2824
}
2825
}
2826
}
2827
2828
void IGFD:: ThumbnailFeature:: SetCreateThumbnailCallback ( const CreateThumbnailFun& vCreateThumbnailFun ) {
2829
m_CreateThumbnailFun = vCreateThumbnailFun;
2830
}
2831
2832
void IGFD:: ThumbnailFeature:: SetDestroyThumbnailCallback ( const DestroyThumbnailFun& vCreateThumbnailFun ) {
2833
m_DestroyThumbnailFun = vCreateThumbnailFun;
2834
}
2835
2836
void IGFD:: ThumbnailFeature:: ManageGPUThumbnails ( ) {
2837
if ( m_CreateThumbnailFun ) {
2838
m_ThumbnailToCreateMutex . lock ( ) ;
2839
if ( ! m_ThumbnailToCreate . empty ( ) ) {
2840
for ( const auto & file : m_ThumbnailToCreate ) {
2841
if ( file. use_count ( ) ) {
2842
m_CreateThumbnailFun ( & file-> thumbnailInfo ) ;
2843
}
2844
}
2845
m_ThumbnailToCreate . clear ( ) ;
2846
}
2847
m_ThumbnailToCreateMutex . unlock ( ) ;
2848
} else {
2849
printf (
2850
" No Callback found for create texture\n You need to define the callback with a call to "
2851
" SetCreateThumbnailCallback\n " ) ;
2852
}
2853
2854
if ( m_DestroyThumbnailFun ) {
2855
m_ThumbnailToDestroyMutex . lock ( ) ;
2856
if ( ! m_ThumbnailToDestroy . empty ( ) ) {
2857
for ( auto thumbnail : m_ThumbnailToDestroy ) {
2858
m_DestroyThumbnailFun ( & thumbnail) ;
2859
}
2860
m_ThumbnailToDestroy . clear ( ) ;
2861
}
2862
m_ThumbnailToDestroyMutex . unlock ( ) ;
2863
} else {
2864
printf (
2865
" No Callback found for destroy texture\n You need to define the callback with a call to "
2866
" SetCreateThumbnailCallback\n " ) ;
2867
}
2868
}
2869
2870
#endif
2871
2872
2873
2874
2875
2876
IGFD:: BookMarkFeature:: BookMarkFeature ( ) {
2877
#ifdef USE_BOOKMARK
2878
m_BookmarkWidth = defaultBookmarkPaneWith;
2879
#endif
2880
}
2881
2882
#ifdef USE_BOOKMARK
2883
void IGFD:: BookMarkFeature:: m_DrawBookmarkButton ( ) {
2884
IMGUI_TOGGLE_BUTTON ( bookmarksButtonString, & m_BookmarkPaneShown ) ;
2885
2886
if ( ImGui:: IsItemHovered ( ) ) ImGui:: SetTooltip ( bookmarksButtonHelpString ) ;
2887
}
2888
2889
bool IGFD:: BookMarkFeature:: m_DrawBookmarkPane ( FileDialogInternal& vFileDialogInternal , const ImVec2& vSize ) {
2890
bool res = false ;
2891
2892
ImGui:: BeginChild ( " ##bookmarkpane" , vSize) ;
2893
2894
static int selectedBookmarkForEdition = - 1 ;
2895
2896
if ( IMGUI_BUTTON ( addBookmarkButtonString " ##ImGuiFileDialogAddBookmark" ) ) {
2897
if ( ! vFileDialogInternal. fileManager . IsComposerEmpty ( ) ) {
2898
BookmarkStruct bookmark;
2899
bookmark. name = vFileDialogInternal. fileManager . GetBack ( ) ;
2900
bookmark. path = vFileDialogInternal. fileManager . GetCurrentPath ( ) ;
2901
m_Bookmarks . push_back ( bookmark ) ;
2902
}
2903
}
2904
if ( selectedBookmarkForEdition >= 0 && selectedBookmarkForEdition < ( int ) m_Bookmarks . size ( ) ) {
2905
ImGui:: SameLine ( ) ;
2906
if ( IMGUI_BUTTON ( removeBookmarkButtonString " ##ImGuiFileDialogAddBookmark" ) ) {
2907
m_Bookmarks . erase ( m_Bookmarks . begin ( ) + selectedBookmarkForEdition) ;
2908
if ( selectedBookmarkForEdition == ( int ) m_Bookmarks . size ( ) ) selectedBookmarkForEdition- - ;
2909
}
2910
2911
if ( selectedBookmarkForEdition >= 0 && selectedBookmarkForEdition < ( int ) m_Bookmarks . size ( ) ) {
2912
ImGui:: SameLine ( ) ;
2913
2914
ImGui:: PushItemWidth ( vSize. x - ImGui:: GetCursorPosX ( ) ) ;
2915
if ( ImGui:: InputText ( " ##ImGuiFileDialogBookmarkEdit" , m_BookmarkEditBuffer , MAX_FILE_DIALOG_NAME_BUFFER) ) {
2916
m_Bookmarks [ ( size_t ) selectedBookmarkForEdition] . name = std:: string ( m_BookmarkEditBuffer ) ;
2917
}
2918
ImGui:: PopItemWidth ( ) ;
2919
}
2920
}
2921
2922
ImGui:: Separator ( ) ;
2923
2924
if ( ! m_Bookmarks . empty ( ) ) {
2925
m_BookmarkClipper . Begin ( ( int ) m_Bookmarks . size ( ) , ImGui:: GetTextLineHeightWithSpacing ( ) ) ;
2926
while ( m_BookmarkClipper . Step ( ) ) {
2927
for ( int i = m_BookmarkClipper . DisplayStart ; i < m_BookmarkClipper . DisplayEnd ; i+ + ) {
2928
if ( i < 0 ) continue ;
2929
const BookmarkStruct& bookmark = m_Bookmarks [ ( size_t ) i] ;
2930
ImGui:: PushID ( i ) ;
2931
if ( ImGui:: Selectable ( bookmark. name . c_str ( ) , selectedBookmarkForEdition == i,
2932
ImGuiSelectableFlags_AllowDoubleClick ) ||
2933
( selectedBookmarkForEdition == - 1 && bookmark. path == vFileDialogInternal. fileManager . GetCurrentPath ( ) ) )
2934
{
2935
selectedBookmarkForEdition = i;
2936
IGFD:: Utils:: ResetBuffer ( m_BookmarkEditBuffer ) ;
2937
IGFD:: Utils:: AppendToBuffer ( m_BookmarkEditBuffer , MAX_FILE_DIALOG_NAME_BUFFER, bookmark. name ) ;
2938
2939
if ( ImGui:: IsMouseDoubleClicked ( 0 ) )
2940
{
2941
vFileDialogInternal. fileManager . SetCurrentPath ( bookmark. path ) ;
2942
vFileDialogInternal. fileManager . OpenCurrentPath ( vFileDialogInternal ) ;
2943
res = true ;
2944
}
2945
}
2946
ImGui:: PopID ( ) ;
2947
if ( ImGui:: IsItemHovered ( ) ) ImGui:: SetTooltip ( " %s " , bookmark. path . c_str ( ) ) ;
2948
}
2949
}
2950
m_BookmarkClipper . End ( ) ;
2951
}
2952
2953
ImGui:: EndChild ( ) ;
2954
2955
return res;
2956
}
2957
2958
std:: string IGFD:: BookMarkFeature:: SerializeBookmarks ( const bool & vDontSerializeCodeBasedBookmarks ) {
2959
std:: string res;
2960
2961
size_t idx = 0 ;
2962
for ( auto & it : m_Bookmarks ) {
2963
if ( vDontSerializeCodeBasedBookmarks && it. defined_by_code ) continue ;
2964
2965
if ( idx+ + != 0 ) res += " ##" ;
2966
2967
res += it. name + " ##" + it. path ;
2968
}
2969
2970
return res;
2971
}
2972
2973
void IGFD:: BookMarkFeature:: DeserializeBookmarks ( const std:: string& vBookmarks ) {
2974
if ( ! vBookmarks. empty ( ) ) {
2975
m_Bookmarks . clear ( ) ;
2976
auto arr = IGFD:: Utils:: SplitStringToVector ( vBookmarks, ' #' , false ) ;
2977
for ( size_t i = 0 ; i < arr. size ( ) ; i += 2 ) {
2978
if ( i + 1 < arr. size ( ) )
2979
{
2980
BookmarkStruct bookmark;
2981
bookmark. name = arr[ i] ;
2982
2983
bookmark. path = arr[ i + 1 ] ;
2984
m_Bookmarks . push_back ( bookmark ) ;
2985
}
2986
}
2987
}
2988
}
2989
2990
void IGFD:: BookMarkFeature:: AddBookmark ( const std:: string& vBookMarkName , const std:: string& vBookMarkPath ) {
2991
if ( vBookMarkName. empty ( ) || vBookMarkPath. empty ( ) ) return ;
2992
2993
BookmarkStruct bookmark;
2994
bookmark. name = vBookMarkName;
2995
bookmark. path = vBookMarkPath;
2996
bookmark. defined_by_code = true ;
2997
m_Bookmarks . push_back ( bookmark ) ;
2998
}
2999
3000
bool IGFD:: BookMarkFeature:: RemoveBookmark ( const std:: string& vBookMarkName ) {
3001
if ( vBookMarkName. empty ( ) ) return false ;
3002
3003
for ( auto bookmark_it = m_Bookmarks . begin ( ) ; bookmark_it != m_Bookmarks . end ( ) ; + + bookmark_it) {
3004
if ( ( * bookmark_it) . name == vBookMarkName) {
3005
m_Bookmarks . erase ( bookmark_it ) ;
3006
return true ;
3007
}
3008
}
3009
3010
return false ;
3011
}
3012
#endif
3013
3014
3015
3016
3017
3018
IGFD:: KeyExplorerFeature:: KeyExplorerFeature ( ) = default ;
3019
3020
#ifdef USE_EXPLORATION_BY_KEYS
3021
bool IGFD:: KeyExplorerFeature:: m_LocateItem_Loop ( FileDialogInternal& vFileDialogInternal , ImWchar vC ) {
3022
bool found = false ;
3023
3024
auto & fdi = vFileDialogInternal. fileManager ;
3025
if ( ! fdi. IsFilteredListEmpty ( ) ) {
3026
auto countFiles = fdi. GetFilteredListSize ( ) ;
3027
for ( size_t i = m_LocateFileByInputChar_lastFileIdx ; i < countFiles; i+ + ) {
3028
auto nfo = fdi. GetFilteredFileAt ( i ) ;
3029
if ( nfo. use_count ( ) ) {
3030
if ( nfo-> fileNameExt_optimized [ 0 ] == vC ||
3031
nfo-> fileNameExt [ 0 ] == vC)
3032
{
3033
3034
float p = ( float ) ( ( double ) i / ( double ) countFiles) * ImGui:: GetScrollMaxY ( ) ;
3035
ImGui:: SetScrollY ( p ) ;
3036
m_LocateFileByInputChar_lastFound = true ;
3037
m_LocateFileByInputChar_lastFileIdx = i;
3038
m_StartFlashItem ( m_LocateFileByInputChar_lastFileIdx ) ;
3039
3040
auto infos = fdi. GetFilteredFileAt ( m_LocateFileByInputChar_lastFileIdx ) ;
3041
if ( infos. use_count ( ) ) {
3042
if ( infos-> fileType . isDir ( ) )
3043
{
3044
if ( fdi. dLGDirectoryMode )
3045
{
3046
fdi. SelectFileName ( vFileDialogInternal, infos ) ;
3047
}
3048
} else {
3049
fdi. SelectFileName ( vFileDialogInternal, infos ) ;
3050
}
3051
3052
found = true ;
3053
break ;
3054
}
3055
}
3056
}
3057
}
3058
}
3059
3060
return found;
3061
}
3062
3063
void IGFD:: KeyExplorerFeature:: m_LocateByInputKey ( FileDialogInternal& vFileDialogInternal ) {
3064
ImGuiContext& g = * GImGui;
3065
auto & fdi = vFileDialogInternal. fileManager ;
3066
if ( ! g. ActiveId && ! fdi. IsFilteredListEmpty ( ) ) {
3067
auto & queueChar = ImGui:: GetIO ( ) . InputQueueCharacters ;
3068
auto countFiles = fdi. GetFilteredListSize ( ) ;
3069
3070
3071
if ( ! queueChar. empty ( ) ) {
3072
ImWchar c = queueChar. back ( ) ;
3073
if ( m_LocateFileByInputChar_InputQueueCharactersSize != queueChar. size ( ) ) {
3074
if ( c == m_LocateFileByInputChar_lastChar )
3075
{
3076
if ( m_LocateFileByInputChar_lastFileIdx < countFiles - 1U )
3077
m_LocateFileByInputChar_lastFileIdx + + ;
3078
else
3079
m_LocateFileByInputChar_lastFileIdx = 0 ;
3080
}
3081
3082
if ( ! m_LocateItem_Loop ( vFileDialogInternal, c) ) {
3083
3084
m_LocateFileByInputChar_lastFileIdx = 0 ;
3085
m_LocateItem_Loop ( vFileDialogInternal, c) ;
3086
}
3087
3088
m_LocateFileByInputChar_lastChar = c;
3089
}
3090
}
3091
3092
m_LocateFileByInputChar_InputQueueCharactersSize = queueChar. size ( ) ;
3093
}
3094
}
3095
3096
void IGFD:: KeyExplorerFeature:: m_ExploreWithkeys ( FileDialogInternal& vFileDialogInternal , ImGuiID vListViewID ) {
3097
auto & fdi = vFileDialogInternal. fileManager ;
3098
if ( ! fdi. IsFilteredListEmpty ( ) ) {
3099
bool canWeExplore = false ;
3100
bool hasNav = ( ImGui:: GetIO ( ) . ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) ;
3101
3102
ImGuiContext& g = * GImGui;
3103
if ( ! hasNav && ! g. ActiveId )
3104
canWeExplore = true ;
3105
3106
if ( g. NavId && g. NavId == vListViewID) {
3107
if ( ImGui:: IsKeyPressed ( ImGuiKey_Enter ) || ImGui:: IsKeyPressed ( ImGuiKey_KeypadEnter ) || ImGui:: IsKeyPressed ( ImGuiKey_Space ) ) {
3108
ImGui:: ActivateItemByID ( vListViewID ) ;
3109
ImGui:: SetActiveID ( vListViewID, g. CurrentWindow ) ;
3110
}
3111
}
3112
3113
if ( vListViewID == g. LastActiveId - 1 )
3114
canWeExplore = true ;
3115
3116
if ( canWeExplore && ImGui:: IsWindowFocused ( ) ) {
3117
if ( ImGui:: IsKeyPressed ( ImGuiKey_Escape ) ) {
3118
ImGui:: ClearActiveID ( ) ;
3119
g. LastActiveId = 0 ;
3120
}
3121
3122
auto countFiles = fdi. GetFilteredListSize ( ) ;
3123
3124
3125
bool exploreByKey = false ;
3126
bool enterInDirectory = false ;
3127
bool exitDirectory = false ;
3128
3129
if ( ( hasNav && ImGui:: IsKeyPressed ( ImGuiKey_UpArrow ) ) || ( ! hasNav && ImGui:: IsKeyPressed ( ImGuiKey_UpArrow ) ) ) {
3130
exploreByKey = true ;
3131
if ( m_LocateFileByInputChar_lastFileIdx > 0 )
3132
m_LocateFileByInputChar_lastFileIdx - - ;
3133
else
3134
m_LocateFileByInputChar_lastFileIdx = countFiles - 1U ;
3135
} else if ( ( hasNav && ImGui:: IsKeyPressed ( ImGuiKey_DownArrow ) ) || ( ! hasNav && ImGui:: IsKeyPressed ( ImGuiKey_DownArrow ) ) ) {
3136
exploreByKey = true ;
3137
if ( m_LocateFileByInputChar_lastFileIdx < countFiles - 1U )
3138
m_LocateFileByInputChar_lastFileIdx + + ;
3139
else
3140
m_LocateFileByInputChar_lastFileIdx = 0U ;
3141
} else if ( ImGui:: IsKeyReleased ( ImGuiKey_Enter ) ) {
3142
exploreByKey = true ;
3143
enterInDirectory = true ;
3144
} else if ( ImGui:: IsKeyReleased ( ImGuiKey_Backspace ) ) {
3145
exploreByKey = true ;
3146
exitDirectory = true ;
3147
}
3148
3149
if ( exploreByKey) {
3150
3151
float p = ( float ) ( ( double ) m_LocateFileByInputChar_lastFileIdx / ( double ) ( countFiles - 1U ) ) * ImGui:: GetScrollMaxY ( ) ;
3152
3153
ImGui:: SetScrollY ( p ) ;
3154
m_StartFlashItem ( m_LocateFileByInputChar_lastFileIdx ) ;
3155
3156
auto infos = fdi. GetFilteredFileAt ( m_LocateFileByInputChar_lastFileIdx ) ;
3157
if ( infos. use_count ( ) ) {
3158
if ( infos-> fileType . isDir ( ) )
3159
{
3160
if ( ! fdi. dLGDirectoryMode || enterInDirectory) {
3161
if ( enterInDirectory) {
3162
if ( fdi. SelectDirectory ( infos ) ) {
3163
3164
vFileDialogInternal. fileManager . OpenCurrentPath ( vFileDialogInternal ) ;
3165
if ( m_LocateFileByInputChar_lastFileIdx > countFiles - 1U ) {
3166
m_LocateFileByInputChar_lastFileIdx = 0 ;
3167
}
3168
}
3169
}
3170
} else
3171
{
3172
fdi. SelectFileName ( vFileDialogInternal, infos ) ;
3173
}
3174
} else {
3175
fdi. SelectFileName ( vFileDialogInternal, infos ) ;
3176
3177
if ( enterInDirectory) {
3178
vFileDialogInternal. isOk = true ;
3179
}
3180
}
3181
3182
if ( exitDirectory) {
3183
auto nfo = std:: make_shared < FileInfos> ( ) ;
3184
nfo-> fileNameExt = " .." ;
3185
3186
if ( fdi. SelectDirectory ( nfo ) ) {
3187
3188
vFileDialogInternal. fileManager . OpenCurrentPath ( vFileDialogInternal ) ;
3189
if ( m_LocateFileByInputChar_lastFileIdx > countFiles - 1U ) {
3190
m_LocateFileByInputChar_lastFileIdx = 0 ;
3191
}
3192
}
3193
#ifdef _IGFD_WIN_
3194
else {
3195
if ( fdi. GetComposerSize ( ) == 1U ) {
3196
if ( fdi. GetDrives ( ) ) {
3197
fdi. ApplyFilteringOnFileList ( vFileDialogInternal ) ;
3198
}
3199
}
3200
}
3201
#endif
3202
}
3203
}
3204
}
3205
}
3206
}
3207
}
3208
3209
bool IGFD:: KeyExplorerFeature:: m_FlashableSelectable ( const char * label , bool selected , ImGuiSelectableFlags flags , bool vFlashing , const ImVec2& size_arg ) {
3210
using namespace ImGui;
3211
3212
ImGuiWindow* window = GetCurrentWindow ( ) ;
3213
if ( window-> SkipItems ) return false ;
3214
3215
ImGuiContext& g = * GImGui;
3216
const ImGuiStyle& style = g. Style ;
3217
3218
3219
ImGuiID id = window-> GetID ( label ) ;
3220
ImVec2 label_size = CalcTextSize ( label, NULL , true ) ;
3221
ImVec2 size ( size_arg. x != 0.0f ? size_arg. x : label_size. x , size_arg. y != 0.0f ? size_arg. y : label_size. y ) ;
3222
ImVec2 pos = window-> DC . CursorPos ;
3223
pos. y += window-> DC . CurrLineTextBaseOffset ;
3224
ItemSize ( size, 0.0f ) ;
3225
3226
3227
3228
3229
const bool span_all_columns = ( flags & ImGuiSelectableFlags_SpanAllColumns) != 0 ;
3230
const float min_x = span_all_columns ? window-> ParentWorkRect . Min . x : pos. x ;
3231
const float max_x = span_all_columns ? window-> ParentWorkRect . Max . x : window-> WorkRect . Max . x ;
3232
if ( size_arg. x == 0.0f || ( flags & ImGuiSelectableFlags_SpanAvailWidth) ) size. x = ImMax ( label_size. x , max_x - min_x ) ;
3233
3234
3235
const ImVec2 text_min = pos;
3236
const ImVec2 text_max ( min_x + size. x , pos. y + size. y ) ;
3237
3238
3239
ImRect bb ( min_x, pos. y , text_max. x , text_max. y ) ;
3240
if ( ( flags & ImGuiSelectableFlags_NoPadWithHalfSpacing) == 0 ) {
3241
const float spacing_x = span_all_columns ? 0.0f : style. ItemSpacing . x ;
3242
const float spacing_y = style. ItemSpacing . y ;
3243
const float spacing_L = IM_TRUNC ( spacing_x * 0.50f ) ;
3244
const float spacing_U = IM_TRUNC ( spacing_y * 0.50f ) ;
3245
bb. Min . x -= spacing_L;
3246
bb. Min . y -= spacing_U;
3247
bb. Max . x += ( spacing_x - spacing_L) ;
3248
bb. Max . y += ( spacing_y - spacing_U) ;
3249
}
3250
3251
3252
3253
const float backup_clip_rect_min_x = window-> ClipRect . Min . x ;
3254
const float backup_clip_rect_max_x = window-> ClipRect . Max . x ;
3255
if ( span_all_columns) {
3256
window-> ClipRect . Min . x = window-> ParentWorkRect . Min . x ;
3257
window-> ClipRect . Max . x = window-> ParentWorkRect . Max . x ;
3258
}
3259
3260
const bool disabled_item = ( flags & ImGuiSelectableFlags_Disabled) != 0 ;
3261
const bool item_add = ItemAdd ( bb, id, NULL , disabled_item ? ImGuiItemFlags_Disabled : ImGuiItemFlags_None ) ;
3262
if ( span_all_columns) {
3263
window-> ClipRect . Min . x = backup_clip_rect_min_x;
3264
window-> ClipRect . Max . x = backup_clip_rect_max_x;
3265
}
3266
3267
if ( ! item_add) return false ;
3268
3269
const bool disabled_global = ( g. CurrentItemFlags & ImGuiItemFlags_Disabled) != 0 ;
3270
if ( disabled_item && ! disabled_global)
3271
BeginDisabled ( ) ;
3272
3273
3274
3275
if ( span_all_columns && window-> DC . CurrentColumns )
3276
PushColumnsBackground ( ) ;
3277
else if ( span_all_columns && g. CurrentTable )
3278
TablePushBackgroundChannel ( ) ;
3279
3280
3281
ImGuiButtonFlags button_flags = 0 ;
3282
if ( flags & ImGuiSelectableFlags_NoHoldingActiveID) {
3283
button_flags |= ImGuiButtonFlags_NoHoldingActiveId;
3284
}
3285
if ( flags & ImGuiSelectableFlags_NoSetKeyOwner) {
3286
button_flags |= ImGuiButtonFlags_NoSetKeyOwner;
3287
}
3288
if ( flags & ImGuiSelectableFlags_SelectOnClick) {
3289
button_flags |= ImGuiButtonFlags_PressedOnClick;
3290
}
3291
if ( flags & ImGuiSelectableFlags_SelectOnRelease) {
3292
button_flags |= ImGuiButtonFlags_PressedOnRelease;
3293
}
3294
if ( flags & ImGuiSelectableFlags_AllowDoubleClick) {
3295
button_flags |= ImGuiButtonFlags_PressedOnClickRelease | ImGuiButtonFlags_PressedOnDoubleClick;
3296
}
3297
if ( ( flags & ImGuiSelectableFlags_AllowOverlap) || ( g. LastItemData . ItemFlags & ImGuiItemFlags_AllowOverlap) ) {
3298
button_flags |= ImGuiButtonFlags_AllowOverlap;
3299
}
3300
3301
const bool was_selected = selected;
3302
bool hovered, held;
3303
bool pressed = ButtonBehavior ( bb, id, & hovered, & held, button_flags ) ;
3304
3305
3306
3307
3308
3309
3310
3311
3312
if ( ( flags & ImGuiSelectableFlags_SelectOnNav) && g. NavJustMovedToId != 0 && g. NavJustMovedToFocusScopeId == g. CurrentFocusScopeId )
3313
if ( g. NavJustMovedToId == id) selected = pressed = true ;
3314
3315
3316
if ( pressed || ( hovered && ( flags & ImGuiSelectableFlags_SetNavIdOnHover) ) ) {
3317
if ( ! g. NavHighlightItemUnderNav && g. NavWindow == window && g. NavLayer == window-> DC . NavLayerCurrent ) {
3318
SetNavID ( id, window-> DC . NavLayerCurrent , g. CurrentFocusScopeId , WindowRectAbsToRel ( window, bb ) ) ;
3319
g. NavCursorVisible = true ;
3320
}
3321
}
3322
if ( pressed) MarkItemEdited ( id ) ;
3323
3324
3325
if ( selected != was_selected)
3326
g. LastItemData . StatusFlags |= ImGuiItemStatusFlags_ToggledSelection;
3327
3328
3329
3330
hovered |= vFlashing;
3331
3332
3333
3334
if ( hovered || selected) {
3335
const ImU32 col = GetColorU32 ( ( held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header) ;
3336
RenderFrame ( bb. Min , bb. Max , col, false , 0.0f ) ;
3337
}
3338
if ( g. NavId == id) RenderNavCursor ( bb, id, ImGuiNavRenderCursorFlags_Compact, 0.0f ) ;
3339
3340
if ( span_all_columns && window-> DC . CurrentColumns )
3341
PopColumnsBackground ( ) ;
3342
else if ( span_all_columns && g. CurrentTable )
3343
TablePopBackgroundChannel ( ) ;
3344
3345
RenderTextClipped ( text_min, text_max, label, NULL , & label_size, style. SelectableTextAlign , & bb ) ;
3346
3347
3348
if ( pressed && ( window-> Flags & ImGuiWindowFlags_Popup) && ! ( flags & ImGuiSelectableFlags_NoAutoClosePopups) && ( g. LastItemData . ItemFlags & ImGuiItemFlags_AutoClosePopups) ) CloseCurrentPopup ( ) ;
3349
3350
if ( disabled_item && ! disabled_global) EndDisabled ( ) ;
3351
3352
IMGUI_TEST_ENGINE_ITEM_INFO ( id, label, g. LastItemData . StatusFlags ) ;
3353
return pressed;
3354
}
3355
3356
void IGFD:: KeyExplorerFeature:: m_StartFlashItem ( size_t vIdx ) {
3357
m_FlashAlpha = 1.0f ;
3358
m_FlashedItem = vIdx;
3359
}
3360
3361
bool IGFD:: KeyExplorerFeature:: m_BeginFlashItem ( size_t vIdx ) {
3362
bool res = false ;
3363
3364
if ( m_FlashedItem == vIdx && std:: abs ( m_FlashAlpha - 0.0f ) > 0.00001f ) {
3365
m_FlashAlpha -= m_FlashAlphaAttenInSecs * ImGui:: GetIO ( ) . DeltaTime ;
3366
if ( m_FlashAlpha < 0.0f ) m_FlashAlpha = 0.0f ;
3367
3368
ImVec4 hov = ImGui:: GetStyleColorVec4 ( ImGuiCol_HeaderHovered ) ;
3369
hov. w = m_FlashAlpha ;
3370
ImGui:: PushStyleColor ( ImGuiCol_HeaderHovered, hov ) ;
3371
res = true ;
3372
}
3373
3374
return res;
3375
}
3376
3377
void IGFD:: KeyExplorerFeature:: m_EndFlashItem ( ) {
3378
ImGui:: PopStyleColor ( ) ;
3379
}
3380
3381
void IGFD:: KeyExplorerFeature:: SetFlashingAttenuationInSeconds ( float vAttenValue ) {
3382
m_FlashAlphaAttenInSecs = 1.0f / ImMax ( vAttenValue, 0.01f ) ;
3383
}
3384
#endif
3385
3386
3387
3388
3389
3390
3391
3392
IGFD:: FileDialog:: FileDialog ( ) : BookMarkFeature ( ) , KeyExplorerFeature ( ) , ThumbnailFeature ( ) {
3393
}
3394
IGFD:: FileDialog:: ~FileDialog ( ) = default ;
3395
3396
3397
3398
3399
3400
3401
void IGFD:: FileDialog:: OpenDialog ( const std:: string& vKey , const std:: string& vTitle , const char * vFilters , const FileDialogConfig& vConfig ) {
3402
if ( m_FileDialogInternal . showDialog )
3403
return ;
3404
m_FileDialogInternal . configureDialog ( vKey, vTitle, vFilters, vConfig ) ;
3405
}
3406
3407
3408
3409
3410
3411
bool IGFD:: FileDialog:: Display ( const std:: string& vKey , ImGuiWindowFlags vFlags , ImVec2 vMinSize , ImVec2 vMaxSize ) {
3412
bool res = false ;
3413
3414
if ( m_FileDialogInternal . showDialog && m_FileDialogInternal . dLGkey == vKey) {
3415
if ( m_FileDialogInternal . puUseCustomLocale ) setlocale ( m_FileDialogInternal . localeCategory , m_FileDialogInternal . localeBegin . c_str ( ) ) ;
3416
3417
auto & fdFile = m_FileDialogInternal . fileManager ;
3418
auto & fdFilter = m_FileDialogInternal . filterManager ;
3419
3420
static ImGuiWindowFlags flags;
3421
3422
3423
ImGuiContext& g = * GImGui;
3424
if ( g. FrameCount == m_FileDialogInternal . lastImGuiFrameCount )
3425
3426
return res;
3427
m_FileDialogInternal . lastImGuiFrameCount = g. FrameCount ;
3428
3429
std:: string name = m_FileDialogInternal . dLGtitle + " ##" + m_FileDialogInternal . dLGkey ;
3430
if ( m_FileDialogInternal . name != name) {
3431
fdFile. ClearComposer ( ) ;
3432
fdFile. ClearFileLists ( ) ;
3433
flags = vFlags;
3434
}
3435
3436
m_NewFrame ( ) ;
3437
3438
#ifdef IMGUI_HAS_VIEWPORT
3439
if ( ! ImGui:: GetIO ( ) . ConfigViewportsNoDecoration ) {
3440
3441
ImGuiWindowClass window_class;
3442
window_class. ViewportFlagsOverrideClear = ImGuiViewportFlags_NoDecoration;
3443
ImGui:: SetNextWindowClass ( & window_class) ;
3444
}
3445
#endif
3446
3447
bool beg = false ;
3448
if ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_NoDialog)
3449
{
3450
beg = true ;
3451
} else {
3452
ImGui:: SetNextWindowSizeConstraints ( vMinSize, vMaxSize ) ;
3453
3454
if ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_Modal && ! m_FileDialogInternal . okResultToConfirm )
3455
3456
{
3457
ImGui:: OpenPopup ( name. c_str ( ) ) ;
3458
beg = ImGui:: BeginPopupModal ( name. c_str ( ) , ( bool * ) nullptr , flags | ImGuiWindowFlags_NoScrollbar ) ;
3459
} else {
3460
beg = ImGui:: Begin ( name. c_str ( ) , ( bool * ) nullptr , flags | ImGuiWindowFlags_NoScrollbar ) ;
3461
}
3462
}
3463
if ( beg) {
3464
#ifdef IMGUI_HAS_VIEWPORT
3465
3466
if ( ImGui:: GetIO ( ) . ConfigViewportsNoDecoration ) {
3467
flags = vFlags;
3468
} else {
3469
auto win = ImGui:: GetCurrentWindowRead ( ) ;
3470
if ( win-> Viewport -> Idx != 0 )
3471
flags |= ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar;
3472
else
3473
flags = vFlags;
3474
}
3475
#endif
3476
3477
ImGuiID _frameId = ImGui:: GetID ( name. c_str ( ) ) ;
3478
ImVec2 frameSize = ImVec2 ( 0 , 0 ) ;
3479
if ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_NoDialog) frameSize = vMaxSize;
3480
if ( ImGui:: BeginChild ( _frameId, frameSize, false , flags | ImGuiWindowFlags_NoScrollbar ) ) {
3481
m_FileDialogInternal . name = name;
3482
3483
if ( fdFile. dLGpath . empty ( ) ) fdFile. dLGpath = " ." ;
3484
3485
fdFilter. SetDefaultFilterIfNotDefined ( ) ;
3486
3487
3488
if ( fdFile. IsFileListEmpty ( ) && ! fdFile. showDrives ) {
3489
if ( fdFile. dLGpath != " ." )
3490
IGFD:: Utils:: ReplaceString ( fdFile. dLGDefaultFileName , fdFile. dLGpath , " " ) ;
3491
3492
if ( ! fdFile. dLGDefaultFileName . empty ( ) ) {
3493
fdFile. SetDefaultFileName ( fdFile. dLGDefaultFileName ) ;
3494
fdFilter. SetSelectedFilterWithExt ( fdFilter. dLGdefaultExt ) ;
3495
} else if ( fdFile. dLGDirectoryMode )
3496
fdFile. SetDefaultFileName ( " ." ) ;
3497
fdFile. ScanDir ( m_FileDialogInternal , fdFile. dLGpath ) ;
3498
}
3499
3500
3501
m_DrawHeader ( ) ;
3502
m_DrawContent ( ) ;
3503
res = m_DrawFooter ( ) ;
3504
3505
m_EndFrame ( ) ;
3506
}
3507
ImGui:: EndChild ( ) ;
3508
3509
3510
m_FileDialogInternal . dialogCenterPos = ImGui:: GetCurrentWindowRead ( ) -> ContentRegionRect . GetCenter ( ) ;
3511
3512
3513
3514
3515
if ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_Modal && ! m_FileDialogInternal . okResultToConfirm ) {
3516
ImGui:: EndPopup ( ) ;
3517
}
3518
}
3519
3520
if ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_NoDialog) {
3521
} else {
3522
3523
if ( ! ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_Modal) || m_FileDialogInternal . okResultToConfirm ) {
3524
ImGui:: End ( ) ;
3525
}
3526
}
3527
3528
res = m_Confirm_Or_OpenOverWriteFileDialog_IfNeeded ( res, vFlags) ;
3529
3530
if ( m_FileDialogInternal . puUseCustomLocale ) setlocale ( m_FileDialogInternal . localeCategory , m_FileDialogInternal . localeEnd . c_str ( ) ) ;
3531
}
3532
3533
return res;
3534
}
3535
3536
void IGFD:: FileDialog:: m_NewFrame ( ) {
3537
m_FileDialogInternal . NewFrame ( ) ;
3538
m_NewThumbnailFrame ( m_FileDialogInternal ) ;
3539
}
3540
3541
void IGFD:: FileDialog:: m_EndFrame ( ) {
3542
m_EndThumbnailFrame ( m_FileDialogInternal ) ;
3543
m_FileDialogInternal . EndFrame ( ) ;
3544
}
3545
void IGFD:: FileDialog:: m_QuitFrame ( ) {
3546
m_QuitThumbnailFrame ( m_FileDialogInternal ) ;
3547
}
3548
3549
void IGFD:: FileDialog:: m_DrawHeader ( ) {
3550
#ifdef USE_BOOKMARK
3551
if ( ! ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_DisableBookmarkMode) ) {
3552
m_DrawBookmarkButton ( ) ;
3553
ImGui:: SameLine ( ) ;
3554
}
3555
3556
#endif
3557
3558
m_FileDialogInternal . fileManager . DrawDirectoryCreation ( m_FileDialogInternal ) ;
3559
3560
if (
3561
#ifdef USE_BOOKMARK
3562
! ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_DisableBookmarkMode) ||
3563
#endif
3564
! ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_DisableCreateDirectoryButton) ) {
3565
ImGui:: SeparatorEx ( ImGuiSeparatorFlags_Vertical ) ;
3566
ImGui:: SameLine ( ) ;
3567
}
3568
m_FileDialogInternal . fileManager . DrawPathComposer ( m_FileDialogInternal ) ;
3569
3570
#ifdef USE_THUMBNAILS
3571
if ( ! ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_DisableThumbnailMode) ) {
3572
m_DrawDisplayModeToolBar ( ) ;
3573
ImGui:: SameLine ( ) ;
3574
ImGui:: SeparatorEx ( ImGuiSeparatorFlags_Vertical ) ;
3575
ImGui:: SameLine ( ) ;
3576
}
3577
#endif
3578
3579
m_FileDialogInternal . searchManager . DrawSearchBar ( m_FileDialogInternal ) ;
3580
}
3581
3582
void IGFD:: FileDialog:: m_DrawContent ( ) {
3583
ImVec2 size = ImGui:: GetContentRegionAvail ( ) - ImVec2 ( 0.0f , m_FileDialogInternal . footerHeight ) ;
3584
3585
#ifdef USE_BOOKMARK
3586
if ( ! ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_DisableBookmarkMode) ) {
3587
if ( m_BookmarkPaneShown ) {
3588
3589
float otherWidth = size. x - m_BookmarkWidth ;
3590
ImGui:: PushID ( " ##splitterbookmark" ) ;
3591
IGFD:: Utils:: ImSplitter ( true , 4.0f , & m_BookmarkWidth , & otherWidth, 10.0f , 10.0f + m_FileDialogInternal . getDialogConfig ( ) . sidePaneWidth , size. y ) ;
3592
ImGui:: PopID ( ) ;
3593
size. x -= otherWidth;
3594
m_DrawBookmarkPane ( m_FileDialogInternal , size) ;
3595
ImGui:: SameLine ( ) ;
3596
}
3597
}
3598
#endif
3599
3600
size. x = ImGui:: GetContentRegionAvail ( ) . x - m_FileDialogInternal . getDialogConfig ( ) . sidePaneWidth ;
3601
3602
if ( m_FileDialogInternal . getDialogConfig ( ) . sidePane ) {
3603
ImGui:: PushID ( " ##splittersidepane" ) ;
3604
IGFD:: Utils:: ImSplitter ( true , 4.0f , & size. x , & m_FileDialogInternal . getDialogConfigRef ( ) . sidePaneWidth , 10.0f , 10.0f , size. y ) ;
3605
ImGui:: PopID ( ) ;
3606
}
3607
3608
#ifdef USE_THUMBNAILS
3609
if ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_DisableThumbnailMode) {
3610
m_DrawFileListView ( size) ;
3611
} else {
3612
switch ( m_DisplayMode ) {
3613
case DisplayModeEnum:: FILE_LIST: m_DrawFileListView ( size) ; break ;
3614
case DisplayModeEnum:: THUMBNAILS_LIST: m_DrawThumbnailsListView ( size) ; break ;
3615
case DisplayModeEnum:: THUMBNAILS_GRID: m_DrawThumbnailsGridView ( size) ;
3616
}
3617
}
3618
#else
3619
m_DrawFileListView ( size) ;
3620
#endif
3621
3622
if ( m_FileDialogInternal . getDialogConfig ( ) . sidePane ) {
3623
m_DrawSidePane ( size. y ) ;
3624
}
3625
3626
if ( ! ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_DisableQuickPathSelection) ) {
3627
m_DisplayPathPopup ( size) ;
3628
}
3629
}
3630
3631
void IGFD:: FileDialog:: m_DisplayPathPopup ( ImVec2 vSize ) {
3632
ImVec2 size = ImVec2 ( vSize. x * 0.5f , vSize. y * 0.5f ) ;
3633
if ( ImGui:: BeginPopup ( " IGFD_Path_Popup" ) ) {
3634
auto & fdi = m_FileDialogInternal . fileManager ;
3635
3636
ImGui:: PushID ( this ) ;
3637
3638
static ImGuiTableFlags flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg | ImGuiTableFlags_Hideable | ImGuiTableFlags_ScrollY | ImGuiTableFlags_NoHostExtendY;
3639
auto listViewID = ImGui:: GetID ( " ##FileDialog_pathTable" ) ;
3640
if ( ImGui:: BeginTableEx ( " ##FileDialog_pathTable" , listViewID, 1 , flags, size, 0.0f ) )
3641
{
3642
ImGui:: TableSetupScrollFreeze ( 0 , 1 ) ;
3643
ImGui:: TableSetupColumn ( tableHeaderFileNameString, ImGuiTableColumnFlags_WidthStretch | ( defaultSortOrderFilename ? ImGuiTableColumnFlags_PreferSortAscending : ImGuiTableColumnFlags_PreferSortDescending) , - 1 , 0 ) ;
3644
3645
ImGui:: TableHeadersRow ( ) ;
3646
3647
if ( ! fdi. IsPathFilteredListEmpty ( ) ) {
3648
std:: string _str;
3649
ImFont* _font = nullptr ;
3650
bool _showColor = false ;
3651
3652
m_PathListClipper . Begin ( ( int ) fdi. GetPathFilteredListSize ( ) , ImGui:: GetTextLineHeightWithSpacing ( ) ) ;
3653
while ( m_PathListClipper . Step ( ) ) {
3654
for ( int i = m_PathListClipper . DisplayStart ; i < m_PathListClipper . DisplayEnd ; i+ + ) {
3655
if ( i < 0 ) continue ;
3656
3657
auto infos = fdi. GetFilteredPathAt ( ( size_t ) i) ;
3658
if ( ! infos. use_count ( ) ) continue ;
3659
3660
m_BeginFileColorIconStyle ( infos, _showColor, _str, & _font) ;
3661
3662
bool selected = fdi. IsFileNameSelected ( infos-> fileNameExt ) ;
3663
3664
ImGui:: TableNextRow ( ) ;
3665
3666
if ( ImGui:: TableNextColumn ( ) )
3667
{
3668
if ( ImGui:: Selectable ( infos-> fileNameExt . c_str ( ) , & selected, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_SpanAvailWidth ) ) {
3669
fdi. SetCurrentPath ( fdi. ComposeNewPath ( fdi. GetCurrentPopupComposedPath ( ) ) ) ;
3670
fdi. puPathClicked = fdi. SelectDirectory ( infos ) ;
3671
ImGui:: CloseCurrentPopup ( ) ;
3672
}
3673
}
3674
3675
m_EndFileColorIconStyle ( _showColor, _font) ;
3676
}
3677
}
3678
m_PathListClipper . End ( ) ;
3679
}
3680
3681
ImGui:: EndTable ( ) ;
3682
}
3683
3684
ImGui:: PopID ( ) ;
3685
3686
ImGui:: EndPopup ( ) ;
3687
}
3688
}
3689
3690
bool IGFD:: FileDialog:: m_DrawOkButton ( ) {
3691
auto & fdFile = m_FileDialogInternal . fileManager ;
3692
if ( m_FileDialogInternal . canWeContinue && strlen ( fdFile. fileNameBuffer ) ) {
3693
if ( IMGUI_BUTTON ( okButtonString " ##validationdialog" , ImVec2 ( okButtonWidth, 0.0f ) ) || m_FileDialogInternal . isOk ) {
3694
m_FileDialogInternal . isOk = true ;
3695
return true ;
3696
}
3697
3698
#if !invertOkAndCancelButtons
3699
ImGui:: SameLine ( ) ;
3700
#endif
3701
}
3702
3703
return false ;
3704
}
3705
3706
bool IGFD:: FileDialog:: m_DrawCancelButton ( ) {
3707
if ( IMGUI_BUTTON ( cancelButtonString " ##validationdialog" , ImVec2 ( cancelButtonWidth, 0.0f ) ) || m_FileDialogInternal . needToExitDialog )
3708
{
3709
m_FileDialogInternal . isOk = false ;
3710
return true ;
3711
}
3712
3713
#if invertOkAndCancelButtons
3714
ImGui:: SameLine ( ) ;
3715
#endif
3716
3717
return false ;
3718
}
3719
3720
bool IGFD:: FileDialog:: m_DrawValidationButtons ( ) {
3721
bool res = false ;
3722
3723
ImGui:: SetCursorPosX ( ImGui:: GetCursorPosX ( ) + ( ImGui:: GetContentRegionAvail ( ) . x - prOkCancelButtonWidth) * okCancelButtonAlignement) ;
3724
3725
ImGui:: BeginGroup ( ) ;
3726
3727
if ( invertOkAndCancelButtons) {
3728
res |= m_DrawCancelButton ( ) ;
3729
res |= m_DrawOkButton ( ) ;
3730
} else {
3731
res |= m_DrawOkButton ( ) ;
3732
res |= m_DrawCancelButton ( ) ;
3733
}
3734
3735
ImGui:: EndGroup ( ) ;
3736
3737
prOkCancelButtonWidth = ImGui:: GetItemRectSize ( ) . x ;
3738
3739
return res;
3740
}
3741
3742
bool IGFD:: FileDialog:: m_DrawFooter ( ) {
3743
auto & fdFile = m_FileDialogInternal . fileManager ;
3744
3745
float posY = ImGui:: GetCursorPos ( ) . y ;
3746
ImGui:: AlignTextToFramePadding ( ) ;
3747
if ( ! fdFile. dLGDirectoryMode )
3748
ImGui:: Text ( fileNameString ) ;
3749
else
3750
ImGui:: Text ( dirNameString ) ;
3751
ImGui:: SameLine ( ) ;
3752
3753
3754
float width = ImGui:: GetContentRegionAvail ( ) . x ;
3755
if ( ! fdFile. dLGDirectoryMode ) {
3756
ImGuiContext& g = * GImGui;
3757
width -= m_FileDialogInternal . filterManager . GetFilterComboBoxWidth ( ) + g. Style . ItemSpacing . x ;
3758
}
3759
3760
ImGui:: PushItemWidth ( width ) ;
3761
ImGuiInputTextFlags flags = ImGuiInputTextFlags_EnterReturnsTrue;
3762
if ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_ReadOnlyFileNameField) {
3763
flags |= ImGuiInputTextFlags_ReadOnly;
3764
}
3765
if ( ImGui:: InputText ( " ##FileName" , fdFile. fileNameBuffer , MAX_FILE_DIALOG_NAME_BUFFER, flags) ) {
3766
m_FileDialogInternal . isOk = true ;
3767
}
3768
if ( ImGui:: GetItemID ( ) == ImGui:: GetActiveID ( ) ) m_FileDialogInternal . fileInputIsActive = true ;
3769
ImGui:: PopItemWidth ( ) ;
3770
3771
3772
m_FileDialogInternal . filterManager . DrawFilterComboBox ( m_FileDialogInternal ) ;
3773
3774
bool res = m_DrawValidationButtons ( ) ;
3775
m_FileDialogInternal . footerHeight = ImGui:: GetCursorPosY ( ) - posY;
3776
return res;
3777
}
3778
3779
void IGFD:: FileDialog:: m_SelectableItem ( int vidx , std:: shared_ptr< FileInfos> vInfos , bool vSelected , const char * vFmt , ... ) {
3780
if ( ! vInfos. use_count ( ) ) return ;
3781
3782
auto & fdi = m_FileDialogInternal . fileManager ;
3783
3784
static ImGuiSelectableFlags selectableFlags = ImGuiSelectableFlags_AllowDoubleClick | ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_SpanAvailWidth;
3785
3786
va_list args;
3787
va_start ( args, vFmt ) ;
3788
vsnprintf ( fdi. variadicBuffer , MAX_FILE_DIALOG_NAME_BUFFER, vFmt, args ) ;
3789
va_end ( args ) ;
3790
3791
float h = 0.0f ;
3792
#ifdef USE_THUMBNAILS
3793
if ( m_DisplayMode == DisplayModeEnum:: THUMBNAILS_LIST && ! ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_DisableThumbnailMode) ) {
3794
h = DisplayMode_ThumbailsList_ImageHeight;
3795
}
3796
#endif
3797
#ifdef USE_EXPLORATION_BY_KEYS
3798
bool flashed = m_BeginFlashItem ( ( size_t ) vidx) ;
3799
bool res = m_FlashableSelectable ( fdi. variadicBuffer , vSelected, selectableFlags, flashed, ImVec2 ( - 1.0f , h) ) ;
3800
if ( flashed) m_EndFlashItem ( ) ;
3801
#else
3802
( void ) vidx;
3803
3804
bool res = ImGui:: Selectable ( fdi. variadicBuffer , vSelected, selectableFlags, ImVec2 ( - 1.0f , h) ) ;
3805
#endif
3806
if ( res) {
3807
if ( vInfos-> fileType . isDir ( ) ) {
3808
3809
if ( ImGui:: GetIO ( ) . ConfigFlags & ImGuiConfigFlags_NavEnableKeyboard) {
3810
3811
if ( ImGui:: IsMouseDoubleClicked ( 0 ) )
3812
{
3813
fdi. puPathClicked = fdi. SelectDirectory ( vInfos ) ;
3814
} else if ( fdi. dLGDirectoryMode )
3815
{
3816
fdi. SelectFileName ( m_FileDialogInternal , vInfos) ;
3817
} else {
3818
3819
}
3820
} else
3821
{
3822
if ( ImGui:: IsMouseDoubleClicked ( 0 ) )
3823
{
3824
fdi. puPathClicked = fdi. SelectDirectory ( vInfos ) ;
3825
} else if ( fdi. dLGDirectoryMode )
3826
{
3827
fdi. SelectFileName ( m_FileDialogInternal , vInfos) ;
3828
}
3829
}
3830
} else {
3831
fdi. SelectFileName ( m_FileDialogInternal , vInfos) ;
3832
3833
if ( ImGui:: IsMouseDoubleClicked ( 0 ) ) {
3834
m_FileDialogInternal . isOk = true ;
3835
}
3836
}
3837
}
3838
}
3839
3840
void IGFD:: FileDialog:: m_DisplayFileInfosTooltip ( const int32_t & vRowIdx , const int32_t & vColumnIdx , std:: shared_ptr< FileInfos> vFileInfos ) {
3841
if ( ImGui:: IsItemHovered ( ) ) {
3842
if ( vFileInfos != nullptr && vFileInfos-> tooltipColumn == vColumnIdx) {
3843
if ( ! vFileInfos-> tooltipMessage . empty ( ) ) {
3844
ImGui:: SetTooltip ( " %s " , vFileInfos-> tooltipMessage . c_str ( ) ) ;
3845
}
3846
}
3847
}
3848
}
3849
3850
void IGFD:: FileDialog:: m_BeginFileColorIconStyle ( std:: shared_ptr< FileInfos> vFileInfos , bool & vOutShowColor , std:: string& vOutStr , ImFont* * vOutFont ) {
3851
vOutStr. clear ( ) ;
3852
vOutShowColor = false ;
3853
3854
if ( vFileInfos-> fileStyle . use_count ( ) )
3855
{
3856
vOutShowColor = true ;
3857
3858
* vOutFont = vFileInfos-> fileStyle -> font ;
3859
}
3860
3861
if ( vOutShowColor && ! vFileInfos-> fileStyle -> icon . empty ( ) )
3862
vOutStr = vFileInfos-> fileStyle -> icon ;
3863
else if ( vFileInfos-> fileType . isDir ( ) )
3864
vOutStr = dirEntryString;
3865
else if ( vFileInfos-> fileType . isLinkToUnknown ( ) )
3866
vOutStr = linkEntryString;
3867
else if ( vFileInfos-> fileType . isFile ( ) )
3868
vOutStr = fileEntryString;
3869
3870
vOutStr += " " + vFileInfos-> fileNameExt ;
3871
3872
if ( vOutShowColor) ImGui:: PushStyleColor ( ImGuiCol_Text, vFileInfos-> fileStyle -> color ) ;
3873
if ( * vOutFont) ImGui:: PushFont ( * vOutFont, ( * vOutFont) -> LegacySize ) ;
3874
}
3875
3876
void IGFD:: FileDialog:: m_EndFileColorIconStyle ( const bool & vShowColor , ImFont* vFont ) {
3877
if ( vFont) ImGui:: PopFont ( ) ;
3878
if ( vShowColor) ImGui:: PopStyleColor ( ) ;
3879
}
3880
3881
void IGFD:: FileDialog:: m_DrawFileListView ( ImVec2 vSize ) {
3882
auto & fdi = m_FileDialogInternal . fileManager ;
3883
3884
ImGui:: PushID ( this ) ;
3885
3886
static ImGuiTableFlags flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg | ImGuiTableFlags_Hideable | ImGuiTableFlags_ScrollY | ImGuiTableFlags_NoHostExtendY
3887
#ifndef USE_CUSTOM_SORTING_ICON
3888
| ImGuiTableFlags_Sortable
3889
#endif
3890
;
3891
auto listViewID = ImGui:: GetID ( " ##FileDialog_fileTable" ) ;
3892
if ( ImGui:: BeginTableEx ( " ##FileDialog_fileTable" , listViewID, 4 , flags, vSize, 0.0f ) )
3893
{
3894
ImGui:: TableSetupScrollFreeze ( 0 , 1 ) ;
3895
ImGui:: TableSetupColumn ( fdi. header [ FileManager:: SortingFieldEnum:: FIELD_FILENAME] . c_str ( ) , ImGuiTableColumnFlags_WidthStretch | ( defaultSortOrderFilename ? ImGuiTableColumnFlags_PreferSortAscending : ImGuiTableColumnFlags_PreferSortDescending) , - 1 , 0 ) ;
3896
ImGui:: TableSetupColumn ( fdi. header [ FileManager:: SortingFieldEnum:: FIELD_TYPE] . c_str ( ) ,
3897
ImGuiTableColumnFlags_WidthFixed | ( defaultSortOrderType ? ImGuiTableColumnFlags_PreferSortAscending : ImGuiTableColumnFlags_PreferSortDescending) |
3898
( ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_HideColumnType) ? ImGuiTableColumnFlags_DefaultHide : 0 ) ,
3899
- 1 , 1 ) ;
3900
ImGui:: TableSetupColumn ( fdi. header [ FileManager:: SortingFieldEnum:: FIELD_SIZE] . c_str ( ) ,
3901
ImGuiTableColumnFlags_WidthFixed | ( defaultSortOrderSize ? ImGuiTableColumnFlags_PreferSortAscending : ImGuiTableColumnFlags_PreferSortDescending) |
3902
( ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_HideColumnSize) ? ImGuiTableColumnFlags_DefaultHide : 0 ) ,
3903
- 1 , 2 ) ;
3904
ImGui:: TableSetupColumn ( fdi. header [ FileManager:: SortingFieldEnum:: FIELD_DATE] . c_str ( ) ,
3905
ImGuiTableColumnFlags_WidthFixed | ( defaultSortOrderDate ? ImGuiTableColumnFlags_PreferSortAscending : ImGuiTableColumnFlags_PreferSortDescending) |
3906
( ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_HideColumnDate) ? ImGuiTableColumnFlags_DefaultHide : 0 ) ,
3907
- 1 , 3 ) ;
3908
3909
#ifndef USE_CUSTOM_SORTING_ICON
3910
3911
if ( ImGuiTableSortSpecs* sorts_specs = ImGui:: TableGetSortSpecs ( ) ) {
3912
if ( sorts_specs-> SpecsDirty && ! fdi. IsFileListEmpty ( ) ) {
3913
bool direction = sorts_specs-> Specs -> SortDirection == ImGuiSortDirection_Ascending;
3914
3915
if ( sorts_specs-> Specs -> ColumnUserID == 0 ) {
3916
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_FILENAME;
3917
fdi. sortingDirection [ 0 ] = direction;
3918
fdi. SortFields ( m_FileDialogInternal ) ;
3919
} else if ( sorts_specs-> Specs -> ColumnUserID == 1 ) {
3920
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_TYPE;
3921
fdi. sortingDirection [ 1 ] = direction;
3922
fdi. SortFields ( m_FileDialogInternal ) ;
3923
} else if ( sorts_specs-> Specs -> ColumnUserID == 2 ) {
3924
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_SIZE;
3925
fdi. sortingDirection [ 2 ] = direction;
3926
fdi. SortFields ( m_FileDialogInternal ) ;
3927
} else
3928
3929
{
3930
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_DATE;
3931
fdi. sortingDirection [ 3 ] = direction;
3932
fdi. SortFields ( m_FileDialogInternal ) ;
3933
}
3934
3935
sorts_specs-> SpecsDirty = false ;
3936
}
3937
}
3938
3939
ImGui:: TableHeadersRow ( ) ;
3940
#else
3941
ImGui:: TableNextRow ( ImGuiTableRowFlags_Headers ) ;
3942
for ( int column = 0 ; column < 4 ; column+ + )
3943
{
3944
ImGui:: TableSetColumnIndex ( column ) ;
3945
const char * column_name = ImGui:: TableGetColumnName ( column ) ;
3946
ImGui:: PushID ( column ) ;
3947
ImGui:: TableHeader ( column_name ) ;
3948
ImGui:: PopID ( ) ;
3949
if ( ImGui:: IsItemClicked ( ) ) {
3950
if ( column == 0 ) {
3951
if ( fdi. sortingField == IGFD:: FileManager:: SortingFieldEnum:: FIELD_FILENAME)
3952
fdi. sortingDirection [ 0 ] = ! fdi. sortingDirection [ 0 ] ;
3953
else
3954
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_FILENAME;
3955
3956
fdi. SortFields ( m_FileDialogInternal ) ;
3957
} else if ( column == 1 ) {
3958
if ( fdi. sortingField == IGFD:: FileManager:: SortingFieldEnum:: FIELD_TYPE)
3959
fdi. sortingDirection [ 1 ] = ! fdi. sortingDirection [ 1 ] ;
3960
else
3961
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_TYPE;
3962
3963
fdi. SortFields ( m_FileDialogInternal ) ;
3964
} else if ( column == 2 ) {
3965
if ( fdi. sortingField == IGFD:: FileManager:: SortingFieldEnum:: FIELD_SIZE)
3966
fdi. sortingDirection [ 2 ] = ! fdi. sortingDirection [ 2 ] ;
3967
else
3968
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_SIZE;
3969
3970
fdi. SortFields ( m_FileDialogInternal ) ;
3971
} else
3972
{
3973
if ( fdi. sortingField == IGFD:: FileManager:: SortingFieldEnum:: FIELD_DATE)
3974
fdi. sortingDirection [ 3 ] = ! fdi. sortingDirection [ 3 ] ;
3975
else
3976
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_DATE;
3977
3978
fdi. SortFields ( m_FileDialogInternal ) ;
3979
}
3980
}
3981
}
3982
#endif
3983
if ( ! fdi. IsFilteredListEmpty ( ) ) {
3984
std:: string _str;
3985
ImFont* _font = nullptr ;
3986
bool _showColor = false ;
3987
3988
int column_id = 0 ;
3989
m_FileListClipper . Begin ( ( int ) fdi. GetFilteredListSize ( ) , ImGui:: GetTextLineHeightWithSpacing ( ) ) ;
3990
while ( m_FileListClipper . Step ( ) ) {
3991
for ( int i = m_FileListClipper . DisplayStart ; i < m_FileListClipper . DisplayEnd ; i+ + ) {
3992
if ( i < 0 ) continue ;
3993
3994
auto infos = fdi. GetFilteredFileAt ( ( size_t ) i) ;
3995
if ( ! infos. use_count ( ) ) continue ;
3996
3997
m_BeginFileColorIconStyle ( infos, _showColor, _str, & _font) ;
3998
3999
bool selected = fdi. IsFileNameSelected ( infos-> fileNameExt ) ;
4000
4001
ImGui:: TableNextRow ( ) ;
4002
4003
column_id = 0 ;
4004
if ( ImGui:: TableNextColumn ( ) )
4005
{
4006
m_SelectableItem ( i, infos, selected, _str. c_str ( ) ) ;
4007
m_DisplayFileInfosTooltip ( i, column_id+ + , infos) ;
4008
}
4009
if ( ImGui:: TableNextColumn ( ) )
4010
{
4011
ImGui:: Text ( " %s " , infos-> fileExtLevels [ 0 ] . c_str ( ) ) ;
4012
m_DisplayFileInfosTooltip ( i, column_id+ + , infos) ;
4013
}
4014
if ( ImGui:: TableNextColumn ( ) )
4015
{
4016
if ( ! infos-> fileType . isDir ( ) ) {
4017
RightAlignText ( infos-> formatedFileSize . first . c_str ( ) , " 1888.88" ) ;
4018
ImGui:: SameLine ( 0.0f , 0.0f ) ;
4019
ImGui:: Text ( " %s " , infos-> formatedFileSize . second . c_str ( ) ) ;
4020
} else {
4021
ImGui:: TextUnformatted ( " " ) ;
4022
}
4023
m_DisplayFileInfosTooltip ( i, column_id+ + , infos) ;
4024
}
4025
if ( ImGui:: TableNextColumn ( ) )
4026
{
4027
ImGui:: Text ( " %s " , infos-> fileModifDate . c_str ( ) ) ;
4028
m_DisplayFileInfosTooltip ( i, column_id+ + , infos) ;
4029
}
4030
4031
m_EndFileColorIconStyle ( _showColor, _font) ;
4032
}
4033
}
4034
m_FileListClipper . End ( ) ;
4035
}
4036
4037
#ifdef USE_EXPLORATION_BY_KEYS
4038
if ( ! fdi. inputPathActivated ) {
4039
m_LocateByInputKey ( m_FileDialogInternal ) ;
4040
m_ExploreWithkeys ( m_FileDialogInternal , listViewID) ;
4041
}
4042
#endif
4043
4044
ImGuiContext& g = * GImGui;
4045
if ( g. LastActiveId - 1 == listViewID || g. LastActiveId == listViewID) {
4046
m_FileDialogInternal . fileListViewIsActive = true ;
4047
}
4048
4049
ImGui:: EndTable ( ) ;
4050
}
4051
4052
ImGui:: PopID ( ) ;
4053
}
4054
4055
#ifdef USE_THUMBNAILS
4056
void IGFD:: FileDialog:: m_DrawThumbnailsListView ( ImVec2 vSize ) {
4057
auto & fdi = m_FileDialogInternal . fileManager ;
4058
4059
ImGui:: PushID ( this ) ;
4060
4061
static ImGuiTableFlags flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_RowBg | ImGuiTableFlags_Hideable | ImGuiTableFlags_ScrollY | ImGuiTableFlags_NoHostExtendY
4062
#ifndef USE_CUSTOM_SORTING_ICON
4063
| ImGuiTableFlags_Sortable
4064
#endif
4065
;
4066
auto listViewID = ImGui:: GetID ( " ##FileDialog_fileTable" ) ;
4067
if ( ImGui:: BeginTableEx ( " ##FileDialog_fileTable" , listViewID, 5 , flags, vSize, 0.0f ) ) {
4068
ImGui:: TableSetupScrollFreeze ( 0 , 1 ) ;
4069
ImGui:: TableSetupColumn ( fdi. headerFileName . c_str ( ) , ImGuiTableColumnFlags_WidthStretch | ( defaultSortOrderFilename ? ImGuiTableColumnFlags_PreferSortAscending : ImGuiTableColumnFlags_PreferSortDescending) , - 1 , 0 ) ;
4070
ImGui:: TableSetupColumn ( fdi. headerFileType . c_str ( ) ,
4071
ImGuiTableColumnFlags_WidthFixed | ( defaultSortOrderType ? ImGuiTableColumnFlags_PreferSortAscending : ImGuiTableColumnFlags_PreferSortDescending) |
4072
( ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_HideColumnType) ? ImGuiTableColumnFlags_DefaultHide : 0 ) ,
4073
- 1 , 1 ) ;
4074
ImGui:: TableSetupColumn ( fdi. headerFileSize . c_str ( ) ,
4075
ImGuiTableColumnFlags_WidthFixed | ( defaultSortOrderSize ? ImGuiTableColumnFlags_PreferSortAscending : ImGuiTableColumnFlags_PreferSortDescending) |
4076
( ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_HideColumnSize) ? ImGuiTableColumnFlags_DefaultHide : 0 ) ,
4077
- 1 , 2 ) ;
4078
ImGui:: TableSetupColumn ( fdi. headerFileDate . c_str ( ) ,
4079
ImGuiTableColumnFlags_WidthFixed | ( defaultSortOrderDate ? ImGuiTableColumnFlags_PreferSortAscending : ImGuiTableColumnFlags_PreferSortDescending) |
4080
( ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_HideColumnDate) ? ImGuiTableColumnFlags_DefaultHide : 0 ) ,
4081
- 1 , 3 ) ;
4082
4083
ImGui:: TableSetupColumn ( fdi. header [ FileManager:: SortingFieldEnum:: FIELD_THUMBNAILS] . c_str ( ) , ImGuiTableColumnFlags_WidthFixed | ( defaultSortOrderThumbnails ? ImGuiTableColumnFlags_PreferSortAscending : ImGuiTableColumnFlags_PreferSortDescending) , - 1 , 4 ) ;
4084
4085
#ifndef USE_CUSTOM_SORTING_ICON
4086
4087
if ( ImGuiTableSortSpecs* sorts_specs = ImGui:: TableGetSortSpecs ( ) ) {
4088
if ( sorts_specs-> SpecsDirty && ! fdi. IsFileListEmpty ( ) ) {
4089
bool direction = sorts_specs-> Specs -> SortDirection == ImGuiSortDirection_Ascending;
4090
4091
if ( sorts_specs-> Specs -> ColumnUserID == 0 ) {
4092
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_FILENAME;
4093
fdi. sortingDirection [ 0 ] = direction;
4094
fdi. SortFields ( m_FileDialogInternal ) ;
4095
} else if ( sorts_specs-> Specs -> ColumnUserID == 1 ) {
4096
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_TYPE;
4097
fdi. sortingDirection [ 1 ] = direction;
4098
fdi. SortFields ( m_FileDialogInternal ) ;
4099
} else if ( sorts_specs-> Specs -> ColumnUserID == 2 ) {
4100
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_SIZE;
4101
fdi. sortingDirection [ 2 ] = direction;
4102
fdi. SortFields ( m_FileDialogInternal ) ;
4103
} else if ( sorts_specs-> Specs -> ColumnUserID == 3 ) {
4104
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_DATE;
4105
fdi. sortingDirection [ 3 ] = direction;
4106
fdi. SortFields ( m_FileDialogInternal ) ;
4107
} else
4108
4109
{
4110
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_THUMBNAILS;
4111
fdi. sortingDirection [ 4 ] = direction;
4112
fdi. SortFields ( m_FileDialogInternal ) ;
4113
}
4114
4115
sorts_specs-> SpecsDirty = false ;
4116
}
4117
}
4118
4119
ImGui:: TableHeadersRow ( ) ;
4120
#else
4121
ImGui:: TableNextRow ( ImGuiTableRowFlags_Headers ) ;
4122
for ( int column = 0 ; column < 5 ; column+ + ) {
4123
ImGui:: TableSetColumnIndex ( column ) ;
4124
const char * column_name = ImGui:: TableGetColumnName ( column ) ;
4125
ImGui:: PushID ( column ) ;
4126
ImGui:: TableHeader ( column_name ) ;
4127
ImGui:: PopID ( ) ;
4128
if ( ImGui:: IsItemClicked ( ) ) {
4129
if ( column == 0 ) {
4130
if ( fdi. sortingField == IGFD:: FileManager:: SortingFieldEnum:: FIELD_FILENAME)
4131
fdi. sortingDirection [ 0 ] = ! fdi. sortingDirection [ 0 ] ;
4132
else
4133
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_FILENAME;
4134
4135
fdi. SortFields ( m_FileDialogInternal ) ;
4136
} else if ( column == 1 ) {
4137
if ( fdi. sortingField == IGFD:: FileManager:: SortingFieldEnum:: FIELD_TYPE)
4138
fdi. sortingDirection [ 1 ] = ! fdi. sortingDirection [ 1 ] ;
4139
else
4140
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_TYPE;
4141
4142
fdi. SortFields ( m_FileDialogInternal ) ;
4143
} else if ( column == 2 ) {
4144
if ( fdi. sortingField == IGFD:: FileManager:: SortingFieldEnum:: FIELD_SIZE)
4145
fdi. sortingDirection [ 2 ] = ! fdi. sortingDirection [ 2 ] ;
4146
else
4147
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_SIZE;
4148
4149
fdi. SortFields ( m_FileDialogInternal ) ;
4150
} else if ( column == 3 ) {
4151
if ( fdi. sortingField == IGFD:: FileManager:: SortingFieldEnum:: FIELD_DATE)
4152
fdi. sortingDirection [ 3 ] = ! fdi. sortingDirection [ 3 ] ;
4153
else
4154
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_DATE;
4155
4156
fdi. SortFields ( m_FileDialogInternal ) ;
4157
} else
4158
4159
{
4160
if ( fdi. sortingField == IGFD:: FileManager:: SortingFieldEnum:: FIELD_THUMBNAILS)
4161
fdi. sortingDirection [ 4 ] = ! fdi. sortingDirection [ 4 ] ;
4162
else
4163
fdi. sortingField = IGFD:: FileManager:: SortingFieldEnum:: FIELD_THUMBNAILS;
4164
4165
fdi. SortFields ( m_FileDialogInternal ) ;
4166
}
4167
}
4168
}
4169
#endif
4170
if ( ! fdi. IsFilteredListEmpty ( ) ) {
4171
std:: string _str;
4172
ImFont* _font = nullptr ;
4173
bool _showColor = false ;
4174
4175
ImGuiContext& g = * GImGui;
4176
const float itemHeight = ImMax ( g. FontSize , DisplayMode_ThumbailsList_ImageHeight ) + g. Style . ItemSpacing . y ;
4177
4178
int column_id = 0 ;
4179
m_FileListClipper . Begin ( ( int ) fdi. GetFilteredListSize ( ) , itemHeight) ;
4180
while ( m_FileListClipper . Step ( ) ) {
4181
for ( int i = m_FileListClipper . DisplayStart ; i < m_FileListClipper . DisplayEnd ; i+ + ) {
4182
if ( i < 0 ) continue ;
4183
4184
auto infos = fdi. GetFilteredFileAt ( ( size_t ) i) ;
4185
if ( ! infos. use_count ( ) ) continue ;
4186
4187
m_BeginFileColorIconStyle ( infos, _showColor, _str, & _font) ;
4188
4189
bool selected = fdi. IsFileNameSelected ( infos-> fileNameExt ) ;
4190
4191
ImGui:: TableNextRow ( ) ;
4192
4193
column_id = 0 ;
4194
if ( ImGui:: TableNextColumn ( ) )
4195
{
4196
m_SelectableItem ( i, infos, selected, _str. c_str ( ) ) ;
4197
m_DisplayFileInfosTooltip ( i, column_id+ + , infos) ;
4198
}
4199
if ( ImGui:: TableNextColumn ( ) )
4200
{
4201
ImGui:: Text ( " %s " , infos-> fileExtLevels [ 0 ] . c_str ( ) ) ;
4202
m_DisplayFileInfosTooltip ( i, column_id+ + , infos) ;
4203
}
4204
if ( ImGui:: TableNextColumn ( ) )
4205
{
4206
if ( ! infos-> fileType . isDir ( ) ) {
4207
RightAlignText ( infos-> formatedFileSize . first . c_str ( ) , " 1888.88" ) ;
4208
ImGui:: SameLine ( 0.0f , 0.0f ) ;
4209
ImGui:: Text ( " %s " , infos-> formatedFileSize . second . c_str ( ) ) ;
4210
} else {
4211
ImGui:: TextUnformatted ( " " ) ;
4212
}
4213
m_DisplayFileInfosTooltip ( i, column_id+ + , infos) ;
4214
}
4215
if ( ImGui:: TableNextColumn ( ) )
4216
{
4217
ImGui:: Text ( " %s " , infos-> fileModifDate . c_str ( ) ) ;
4218
m_DisplayFileInfosTooltip ( i, column_id+ + , infos) ;
4219
}
4220
if ( ImGui:: TableNextColumn ( ) )
4221
{
4222
auto th = & infos-> thumbnailInfo ;
4223
4224
if ( ! th-> isLoadingOrLoaded ) {
4225
m_AddThumbnailToLoad ( infos) ;
4226
}
4227
if ( th-> isReadyToDisplay && th-> textureID ) {
4228
ImGui:: Image ( ( ImTextureID) th-> textureID , ImVec2 ( ( float ) th-> textureWidth , ( float ) th-> textureHeight ) ) ;
4229
}
4230
m_DisplayFileInfosTooltip ( i, column_id+ + , infos) ;
4231
}
4232
4233
m_EndFileColorIconStyle ( _showColor, _font) ;
4234
}
4235
}
4236
m_FileListClipper . End ( ) ;
4237
}
4238
4239
#ifdef USE_EXPLORATION_BY_KEYS
4240
if ( ! fdi. inputPathActivated ) {
4241
m_LocateByInputKey ( m_FileDialogInternal ) ;
4242
m_ExploreWithkeys ( m_FileDialogInternal , listViewID) ;
4243
}
4244
#endif
4245
4246
ImGuiContext& g = * GImGui;
4247
if ( g. LastActiveId - 1 == listViewID || g. LastActiveId == listViewID) {
4248
m_FileDialogInternal . fileListViewIsActive = true ;
4249
}
4250
4251
ImGui:: EndTable ( ) ;
4252
}
4253
4254
ImGui:: PopID ( ) ;
4255
}
4256
4257
void IGFD:: FileDialog:: m_DrawThumbnailsGridView ( ImVec2 vSize ) {
4258
if ( ImGui:: BeginChild ( " ##thumbnailsGridsFiles" , vSize) ) {
4259
4260
}
4261
4262
ImGui:: EndChild ( ) ;
4263
}
4264
4265
#endif
4266
4267
void IGFD:: FileDialog:: m_DrawSidePane ( float vHeight ) {
4268
ImGui:: SameLine ( ) ;
4269
4270
ImGui:: BeginChild ( " ##FileTypes" , ImVec2 ( 0 , vHeight) ) ;
4271
4272
m_FileDialogInternal . getDialogConfig ( ) . sidePane (
4273
m_FileDialogInternal . filterManager . GetSelectedFilter ( ) . getFirstFilter ( ) . c_str ( ) ,
4274
m_FileDialogInternal . getDialogConfigRef ( ) . userDatas ,
4275
& m_FileDialogInternal . canWeContinue ) ;
4276
ImGui:: EndChild ( ) ;
4277
}
4278
4279
void IGFD:: FileDialog:: Close ( ) {
4280
m_FileDialogInternal . dLGkey . clear ( ) ;
4281
m_FileDialogInternal . showDialog = false ;
4282
}
4283
4284
bool IGFD:: FileDialog:: WasOpenedThisFrame ( const std:: string& vKey ) const {
4285
bool res = m_FileDialogInternal . showDialog && m_FileDialogInternal . dLGkey == vKey;
4286
if ( res) {
4287
res &= m_FileDialogInternal . lastImGuiFrameCount == GImGui-> FrameCount ;
4288
}
4289
return res;
4290
}
4291
4292
bool IGFD:: FileDialog:: WasOpenedThisFrame ( ) const {
4293
bool res = m_FileDialogInternal . showDialog ;
4294
if ( res) {
4295
res &= m_FileDialogInternal . lastImGuiFrameCount == GImGui-> FrameCount ;
4296
}
4297
return res;
4298
}
4299
4300
bool IGFD:: FileDialog:: IsOpened ( const std:: string& vKey ) const {
4301
return ( m_FileDialogInternal . showDialog && m_FileDialogInternal . dLGkey == vKey) ;
4302
}
4303
4304
bool IGFD:: FileDialog:: IsOpened ( ) const {
4305
return m_FileDialogInternal . showDialog ;
4306
}
4307
4308
std:: string IGFD:: FileDialog:: GetOpenedKey ( ) const {
4309
if ( m_FileDialogInternal . showDialog ) {
4310
return m_FileDialogInternal . dLGkey ;
4311
}
4312
return " " ;
4313
}
4314
4315
std:: string IGFD:: FileDialog:: GetFilePathName ( IGFD_ResultMode vFlag ) {
4316
return m_FileDialogInternal . fileManager . GetResultingFilePathName ( m_FileDialogInternal , vFlag) ;
4317
}
4318
4319
std:: string IGFD:: FileDialog:: GetCurrentPath ( ) {
4320
return m_FileDialogInternal . fileManager . GetResultingPath ( ) ;
4321
}
4322
4323
std:: string IGFD:: FileDialog:: GetCurrentFileName ( IGFD_ResultMode vFlag ) {
4324
return m_FileDialogInternal . fileManager . GetResultingFileName ( m_FileDialogInternal , vFlag) ;
4325
}
4326
4327
std:: string IGFD:: FileDialog:: GetCurrentFilter ( ) {
4328
return m_FileDialogInternal . filterManager . GetSelectedFilter ( ) . title ;
4329
}
4330
4331
std:: map< std:: string, std:: string> IGFD:: FileDialog:: GetSelection ( IGFD_ResultMode vFlag ) {
4332
return m_FileDialogInternal . fileManager . GetResultingSelection ( m_FileDialogInternal , vFlag) ;
4333
}
4334
4335
IGFD:: UserDatas IGFD:: FileDialog:: GetUserDatas ( ) const {
4336
return m_FileDialogInternal . getDialogConfig ( ) . userDatas ;
4337
}
4338
4339
bool IGFD:: FileDialog:: IsOk ( ) const {
4340
return m_FileDialogInternal . isOk ;
4341
}
4342
4343
void IGFD:: FileDialog:: SetFileStyle ( const IGFD_FileStyleFlags& vFlags , const char * vCriteria , const FileStyle& vInfos ) {
4344
m_FileDialogInternal . filterManager . SetFileStyle ( vFlags, vCriteria, vInfos ) ;
4345
}
4346
4347
void IGFD:: FileDialog:: SetFileStyle ( const IGFD_FileStyleFlags& vFlags , const char * vCriteria , const ImVec4& vColor , const std:: string& vIcon , ImFont* vFont ) {
4348
m_FileDialogInternal . filterManager . SetFileStyle ( vFlags, vCriteria, vColor, vIcon, vFont ) ;
4349
}
4350
4351
void IGFD:: FileDialog:: SetFileStyle ( FileStyle:: FileStyleFunctor vFunctor ) {
4352
m_FileDialogInternal . filterManager . SetFileStyle ( vFunctor ) ;
4353
}
4354
4355
bool IGFD:: FileDialog:: GetFileStyle ( const IGFD_FileStyleFlags& vFlags , const std:: string& vCriteria , ImVec4* vOutColor , std:: string* vOutIcon , ImFont* * vOutFont ) {
4356
return m_FileDialogInternal . filterManager . GetFileStyle ( vFlags, vCriteria, vOutColor, vOutIcon, vOutFont ) ;
4357
}
4358
4359
void IGFD:: FileDialog:: ClearFilesStyle ( ) {
4360
m_FileDialogInternal . filterManager . ClearFilesStyle ( ) ;
4361
}
4362
4363
void IGFD:: FileDialog:: SetLocales ( const int & , const std:: string& vLocaleBegin , const std:: string& vLocaleEnd ) {
4364
m_FileDialogInternal . puUseCustomLocale = true ;
4365
m_FileDialogInternal . localeBegin = vLocaleBegin;
4366
m_FileDialogInternal . localeEnd = vLocaleEnd;
4367
}
4368
4369
4370
4371
4372
4373
bool IGFD:: FileDialog:: m_Confirm_Or_OpenOverWriteFileDialog_IfNeeded ( bool vLastAction , ImGuiWindowFlags vFlags ) {
4374
4375
4376
4377
4378
if ( ! m_FileDialogInternal . isOk && vLastAction) {
4379
m_QuitFrame ( ) ;
4380
return true ;
4381
}
4382
4383
4384
if ( m_FileDialogInternal . isOk && vLastAction && ! ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_ConfirmOverwrite) ) {
4385
m_QuitFrame ( ) ;
4386
return true ;
4387
}
4388
4389
4390
if ( ( m_FileDialogInternal . okResultToConfirm || ( m_FileDialogInternal . isOk && vLastAction) ) && ( m_FileDialogInternal . getDialogConfig ( ) . flags & ImGuiFileDialogFlags_ConfirmOverwrite) ) {
4391
if ( m_FileDialogInternal . isOk )
4392
{
4393
if ( ! m_FileDialogInternal . fileManager . GetFileSystemInstance ( ) -> IsFileExist ( GetFilePathName ( ) ) )
4394
{
4395
m_QuitFrame ( ) ;
4396
return true ;
4397
} else
4398
{
4399
m_FileDialogInternal . isOk = false ;
4400
m_FileDialogInternal . okResultToConfirm = true ;
4401
}
4402
}
4403
4404
std:: string name = OverWriteDialogTitleString " ##" + m_FileDialogInternal . dLGtitle + m_FileDialogInternal . dLGkey + " OverWriteDialog" ;
4405
4406
bool res = false ;
4407
4408
ImGui:: OpenPopup ( name. c_str ( ) ) ;
4409
if ( ImGui:: BeginPopupModal ( name. c_str ( ) , ( bool * ) 0 , vFlags | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove ) ) {
4410
ImGui:: SetWindowPos ( m_FileDialogInternal . dialogCenterPos - ImGui:: GetWindowSize ( ) * 0.5f ) ;
4411
4412
ImGui:: Text ( " %s " , OverWriteDialogMessageString) ;
4413
4414
if ( IMGUI_BUTTON ( OverWriteDialogConfirmButtonString ) ) {
4415
m_FileDialogInternal . okResultToConfirm = false ;
4416
m_FileDialogInternal . isOk = true ;
4417
res = true ;
4418
ImGui:: CloseCurrentPopup ( ) ;
4419
}
4420
4421
ImGui:: SameLine ( ) ;
4422
4423
if ( IMGUI_BUTTON ( OverWriteDialogCancelButtonString ) ) {
4424
m_FileDialogInternal . okResultToConfirm = false ;
4425
m_FileDialogInternal . isOk = false ;
4426
res = false ;
4427
ImGui:: CloseCurrentPopup ( ) ;
4428
}
4429
4430
ImGui:: EndPopup ( ) ;
4431
}
4432
4433
if ( res) {
4434
m_QuitFrame ( ) ;
4435
}
4436
return res;
4437
}
4438
4439
return false ;
4440
}
4441
4442
4443
4444
4445
4446
#endif
4447
4448
4449
4450
4451
IGFD_C_API IGFD_FileDialog_Config IGFD_FileDialog_Config_Get ( ) {
4452
IGFD_FileDialog_Config res = { } ;
4453
res. path = " " ;
4454
res. fileName = " " ;
4455
res. filePathName = " " ;
4456
res. countSelectionMax = 1 ;
4457
res. userDatas = nullptr ;
4458
res. sidePane = nullptr ;
4459
res. sidePaneWidth = 250.0f ;
4460
res. flags = ImGuiFileDialogFlags_Default;
4461
return res;
4462
}
4463
4464
4465
IGFD_C_API IGFD_Selection_Pair IGFD_Selection_Pair_Get ( void ) {
4466
IGFD_Selection_Pair res = { } ;
4467
res. fileName = nullptr ;
4468
res. filePathName = nullptr ;
4469
return res;
4470
}
4471
4472
4473
IGFD_C_API void IGFD_Selection_Pair_DestroyContent ( IGFD_Selection_Pair* vSelection_Pair ) {
4474
if ( vSelection_Pair) {
4475
delete[] vSelection_Pair-> fileName ;
4476
delete[] vSelection_Pair-> filePathName ;
4477
}
4478
}
4479
4480
4481
IGFD_C_API IGFD_Selection IGFD_Selection_Get ( void ) {
4482
return { nullptr , 0U } ;
4483
}
4484
4485
4486
IGFD_C_API void IGFD_Selection_DestroyContent ( IGFD_Selection* vSelection ) {
4487
if ( vSelection) {
4488
if ( vSelection-> table ) {
4489
for ( size_t i = 0U ; i < vSelection-> count ; i+ + ) {
4490
IGFD_Selection_Pair_DestroyContent ( & vSelection-> table [ i] ) ;
4491
}
4492
delete[] vSelection-> table ;
4493
}
4494
vSelection-> count = 0U ;
4495
}
4496
}
4497
4498
4499
IGFD_C_API ImGuiFileDialog* IGFD_Create ( void ) {
4500
return new ImGuiFileDialog ( ) ;
4501
}
4502
4503
4504
IGFD_C_API void IGFD_Destroy ( ImGuiFileDialog* vContextPtr ) {
4505
if ( vContextPtr != nullptr ) {
4506
delete vContextPtr;
4507
vContextPtr = nullptr ;
4508
}
4509
}
4510
4511
IGFD_C_API void IGFD_OpenDialog (
4512
ImGuiFileDialog* vContextPtr ,
4513
const char * vKey ,
4514
const char * vTitle ,
4515
const char * vFilters ,
4516
const IGFD_FileDialog_Config vConfig ) {
4517
if ( vContextPtr != nullptr ) {
4518
IGFD:: FileDialogConfig config;
4519
config. path = vConfig. path ;
4520
config. fileName = vConfig. fileName ;
4521
config. filePathName = vConfig. filePathName ;
4522
config. countSelectionMax = vConfig. countSelectionMax ;
4523
config. userDatas = vConfig. userDatas ;
4524
config. flags = vConfig. flags ;
4525
config. sidePane = vConfig. sidePane ;
4526
config. sidePaneWidth = vConfig. sidePaneWidth ;
4527
vContextPtr-> OpenDialog ( vKey, vTitle, vFilters, config ) ;
4528
}
4529
}
4530
4531
IGFD_C_API bool IGFD_DisplayDialog ( ImGuiFileDialog* vContextPtr , const char * vKey , ImGuiWindowFlags vFlags , ImVec2 vMinSize , ImVec2 vMaxSize ) {
4532
if ( vContextPtr != nullptr ) {
4533
return vContextPtr-> Display ( vKey, vFlags, vMinSize, vMaxSize ) ;
4534
}
4535
return false ;
4536
}
4537
4538
IGFD_C_API void IGFD_CloseDialog ( ImGuiFileDialog* vContextPtr ) {
4539
if ( vContextPtr != nullptr ) {
4540
vContextPtr-> Close ( ) ;
4541
}
4542
}
4543
4544
IGFD_C_API bool IGFD_IsOk ( ImGuiFileDialog* vContextPtr ) {
4545
if ( vContextPtr != nullptr ) {
4546
return vContextPtr-> IsOk ( ) ;
4547
}
4548
return false ;
4549
}
4550
4551
IGFD_C_API bool IGFD_WasKeyOpenedThisFrame ( ImGuiFileDialog* vContextPtr , const char * vKey ) {
4552
if ( vContextPtr != nullptr ) {
4553
return vContextPtr-> WasOpenedThisFrame ( vKey ) ;
4554
}
4555
return false ;
4556
}
4557
4558
IGFD_C_API bool IGFD_WasOpenedThisFrame ( ImGuiFileDialog* vContextPtr ) {
4559
if ( vContextPtr != nullptr ) {
4560
return vContextPtr-> WasOpenedThisFrame ( ) ;
4561
}
4562
4563
return false ;
4564
}
4565
4566
IGFD_C_API bool IGFD_IsKeyOpened ( ImGuiFileDialog* vContextPtr , const char * vCurrentOpenedKey ) {
4567
if ( vContextPtr != nullptr ) {
4568
return vContextPtr-> IsOpened ( vCurrentOpenedKey ) ;
4569
}
4570
4571
return false ;
4572
}
4573
4574
IGFD_C_API bool IGFD_IsOpened ( ImGuiFileDialog* vContextPtr ) {
4575
if ( vContextPtr != nullptr ) {
4576
return vContextPtr-> IsOpened ( ) ;
4577
}
4578
4579
return false ;
4580
}
4581
4582
IGFD_C_API IGFD_Selection IGFD_GetSelection ( ImGuiFileDialog* vContextPtr , IGFD_ResultMode vMode ) {
4583
IGFD_Selection res = IGFD_Selection_Get ( ) ;
4584
if ( vContextPtr != nullptr ) {
4585
auto sel = vContextPtr-> GetSelection ( vMode ) ;
4586
if ( ! sel. empty ( ) ) {
4587
res. count = sel. size ( ) ;
4588
res. table = new IGFD_Selection_Pair[ res. count ] ;
4589
4590
size_t idx = 0U ;
4591
for ( const auto & s : sel) {
4592
IGFD_Selection_Pair* pair = res. table + idx+ + ;
4593
4594
4595
if ( ! s. first . empty ( ) ) {
4596
size_t siz = s. first . size ( ) + 1U ;
4597
pair-> fileName = new char [ siz] ;
4598
#ifndef _MSC_VER
4599
strncpy ( pair-> fileName , s. first . c_str ( ) , siz) ;
4600
#else
4601
strncpy_s ( pair-> fileName , siz, s. first . c_str ( ) , siz ) ;
4602
#endif
4603
pair-> fileName [ siz - 1U ] = ' \0 ' ;
4604
}
4605
4606
4607
if ( ! s. second . empty ( ) ) {
4608
size_t siz = s. second . size ( ) + 1U ;
4609
pair-> filePathName = new char [ siz] ;
4610
#ifndef _MSC_VER
4611
strncpy ( pair-> filePathName , s. second . c_str ( ) , siz) ;
4612
#else
4613
strncpy_s ( pair-> filePathName , siz, s. second . c_str ( ) , siz ) ;
4614
#endif
4615
pair-> filePathName [ siz - 1U ] = ' \0 ' ;
4616
}
4617
}
4618
4619
return res;
4620
}
4621
}
4622
4623
return res;
4624
}
4625
4626
IGFD_C_API char * IGFD_GetFilePathName ( ImGuiFileDialog* vContextPtr , IGFD_ResultMode vMode ) {
4627
char * res = nullptr ;
4628
4629
if ( vContextPtr != nullptr ) {
4630
auto s = vContextPtr-> GetFilePathName ( vMode ) ;
4631
if ( ! s. empty ( ) ) {
4632
size_t siz = s. size ( ) + 1U ;
4633
res = ( char * ) malloc ( siz ) ;
4634
if ( res) {
4635
#ifndef _MSC_VER
4636
strncpy ( res, s. c_str ( ) , siz) ;
4637
#else
4638
strncpy_s ( res, siz, s. c_str ( ) , siz ) ;
4639
#endif
4640
res[ siz - 1U ] = ' \0 ' ;
4641
}
4642
}
4643
}
4644
4645
return res;
4646
}
4647
4648
IGFD_C_API char * IGFD_GetCurrentFileName ( ImGuiFileDialog* vContextPtr , IGFD_ResultMode vMode ) {
4649
char * res = nullptr ;
4650
4651
if ( vContextPtr != nullptr ) {
4652
auto s = vContextPtr-> GetCurrentFileName ( vMode ) ;
4653
if ( ! s. empty ( ) ) {
4654
size_t siz = s. size ( ) + 1U ;
4655
res = ( char * ) malloc ( siz ) ;
4656
if ( res) {
4657
#ifndef _MSC_VER
4658
strncpy ( res, s. c_str ( ) , siz) ;
4659
#else
4660
strncpy_s ( res, siz, s. c_str ( ) , siz ) ;
4661
#endif
4662
res[ siz - 1U ] = ' \0 ' ;
4663
}
4664
}
4665
}
4666
4667
return res;
4668
}
4669
4670
IGFD_C_API char * IGFD_GetCurrentPath ( ImGuiFileDialog* vContextPtr ) {
4671
char * res = nullptr ;
4672
4673
if ( vContextPtr != nullptr ) {
4674
auto s = vContextPtr-> GetCurrentPath ( ) ;
4675
if ( ! s. empty ( ) ) {
4676
size_t siz = s. size ( ) + 1U ;
4677
res = ( char * ) malloc ( siz ) ;
4678
if ( res) {
4679
#ifndef _MSC_VER
4680
strncpy ( res, s. c_str ( ) , siz) ;
4681
#else
4682
strncpy_s ( res, siz, s. c_str ( ) , siz ) ;
4683
#endif
4684
res[ siz - 1U ] = ' \0 ' ;
4685
}
4686
}
4687
}
4688
4689
return res;
4690
}
4691
4692
IGFD_C_API char * IGFD_GetCurrentFilter ( ImGuiFileDialog* vContextPtr ) {
4693
char * res = nullptr ;
4694
4695
if ( vContextPtr != nullptr ) {
4696
auto s = vContextPtr-> GetCurrentFilter ( ) ;
4697
if ( ! s. empty ( ) ) {
4698
size_t siz = s. size ( ) + 1U ;
4699
res = ( char * ) malloc ( siz ) ;
4700
if ( res) {
4701
#ifndef _MSC_VER
4702
strncpy ( res, s. c_str ( ) , siz) ;
4703
#else
4704
strncpy_s ( res, siz, s. c_str ( ) , siz ) ;
4705
#endif
4706
res[ siz - 1U ] = ' \0 ' ;
4707
}
4708
}
4709
}
4710
4711
return res;
4712
}
4713
4714
IGFD_C_API void * IGFD_GetUserDatas ( ImGuiFileDialog* vContextPtr ) {
4715
if ( vContextPtr != nullptr ) {
4716
return vContextPtr-> GetUserDatas ( ) ;
4717
}
4718
4719
return nullptr ;
4720
}
4721
4722
IGFD_C_API void IGFD_SetFileStyle ( ImGuiFileDialog* vContextPtr , IGFD_FileStyleFlags vFlags , const char * vCriteria , ImVec4 vColor , const char * vIcon ,
4723
ImFont* vFont )
4724
{
4725
if ( vContextPtr != nullptr ) {
4726
vContextPtr-> SetFileStyle ( vFlags, vCriteria, vColor, vIcon, vFont ) ;
4727
}
4728
}
4729
4730
IGFD_C_API void IGFD_SetFileStyle2 ( ImGuiFileDialog* vContextPtr , IGFD_FileStyleFlags vFlags , const char * vCriteria , float vR , float vG , float vB , float vA , const char * vIcon , ImFont* vFont ) {
4731
if ( vContextPtr != nullptr ) {
4732
vContextPtr-> SetFileStyle ( vFlags, vCriteria, ImVec4 ( vR, vG, vB, vA ) , vIcon, vFont ) ;
4733
}
4734
}
4735
4736
IGFD_C_API bool IGFD_GetFileStyle ( ImGuiFileDialog* vContextPtr , IGFD_FileStyleFlags vFlags , const char * vCriteria , ImVec4* vOutColor , char * * vOutIconText , ImFont* * vOutFont ) {
4737
if ( vContextPtr != nullptr ) {
4738
std:: string icon;
4739
bool res = vContextPtr-> GetFileStyle ( vFlags, vCriteria, vOutColor, & icon, vOutFont ) ;
4740
if ( ! icon. empty ( ) && vOutIconText) {
4741
size_t siz = icon. size ( ) + 1U ;
4742
* vOutIconText = ( char * ) malloc ( siz ) ;
4743
if ( * vOutIconText) {
4744
#ifndef _MSC_VER
4745
strncpy ( * vOutIconText, icon. c_str ( ) , siz) ;
4746
#else
4747
strncpy_s ( * vOutIconText, siz, icon. c_str ( ) , siz) ;
4748
#endif
4749
( * vOutIconText) [ siz - 1U ] = ' \0 ' ;
4750
}
4751
}
4752
return res;
4753
}
4754
4755
return false ;
4756
}
4757
4758
IGFD_C_API void IGFD_ClearFilesStyle ( ImGuiFileDialog* vContextPtr ) {
4759
if ( vContextPtr != nullptr ) {
4760
vContextPtr-> ClearFilesStyle ( ) ;
4761
}
4762
}
4763
4764
IGFD_C_API void SetLocales ( ImGuiFileDialog* vContextPtr , const int vCategory , const char * vBeginLocale , const char * vEndLocale ) {
4765
if ( vContextPtr != nullptr ) {
4766
vContextPtr-> SetLocales ( vCategory, ( vBeginLocale ? vBeginLocale : " " ) , ( vEndLocale ? vEndLocale : " " ) ) ;
4767
}
4768
}
4769
4770
#ifdef USE_EXPLORATION_BY_KEYS
4771
IGFD_C_API void IGFD_SetFlashingAttenuationInSeconds ( ImGuiFileDialog* vContextPtr , float vAttenValue ) {
4772
if ( vContextPtr != nullptr ) {
4773
vContextPtr-> SetFlashingAttenuationInSeconds ( vAttenValue ) ;
4774
}
4775
}
4776
#endif
4777
4778
#ifdef USE_BOOKMARK
4779
IGFD_C_API char * IGFD_SerializeBookmarks ( ImGuiFileDialog* vContextPtr , bool vDontSerializeCodeBasedBookmarks ) {
4780
char * res = nullptr ;
4781
4782
if ( vContextPtr != nullptr ) {
4783
auto s = vContextPtr-> SerializeBookmarks ( vDontSerializeCodeBasedBookmarks ) ;
4784
if ( ! s. empty ( ) ) {
4785
size_t siz = s. size ( ) + 1U ;
4786
res = ( char * ) malloc ( siz ) ;
4787
if ( res) {
4788
#ifndef _MSC_VER
4789
strncpy ( res, s. c_str ( ) , siz) ;
4790
#else
4791
strncpy_s ( res, siz, s. c_str ( ) , siz ) ;
4792
#endif
4793
res[ siz - 1U ] = ' \0 ' ;
4794
}
4795
}
4796
}
4797
4798
return res;
4799
}
4800
4801
IGFD_C_API void IGFD_DeserializeBookmarks ( ImGuiFileDialog* vContextPtr , const char * vBookmarks ) {
4802
if ( vContextPtr != nullptr ) {
4803
vContextPtr-> DeserializeBookmarks ( vBookmarks ) ;
4804
}
4805
}
4806
4807
IGFD_C_API void IGFD_AddBookmark ( ImGuiFileDialog* vContextPtr , const char * vBookMarkName , const char * vBookMarkPath ) {
4808
if ( vContextPtr != nullptr ) {
4809
vContextPtr-> AddBookmark ( vBookMarkName, vBookMarkPath ) ;
4810
}
4811
}
4812
4813
IGFD_C_API void IGFD_RemoveBookmark ( ImGuiFileDialog* vContextPtr , const char * vBookMarkName ) {
4814
if ( vContextPtr != nullptr ) {
4815
vContextPtr-> RemoveBookmark ( vBookMarkName ) ;
4816
}
4817
}
4818
4819
#endif
4820
4821
#ifdef USE_THUMBNAILS
4822
IGFD_C_API void SetCreateThumbnailCallback ( ImGuiFileDialog* vContextPtr , const IGFD_CreateThumbnailFun vCreateThumbnailFun ) {
4823
if ( vContextPtr != nullptr ) {
4824
vContextPtr-> SetCreateThumbnailCallback ( vCreateThumbnailFun ) ;
4825
}
4826
}
4827
4828
IGFD_C_API void SetDestroyThumbnailCallback ( ImGuiFileDialog* vContextPtr , const IGFD_DestroyThumbnailFun vDestroyThumbnailFun ) {
4829
if ( vContextPtr != nullptr ) {
4830
vContextPtr-> SetDestroyThumbnailCallback ( vDestroyThumbnailFun ) ;
4831
}
4832
}
4833
4834
IGFD_C_API void ManageGPUThumbnails ( ImGuiFileDialog* vContextPtr ) {
4835
if ( vContextPtr != nullptr ) {
4836
vContextPtr-> ManageGPUThumbnails ( ) ;
4837
}
4838
}
4839
#endif
4840
4841