19 # ifndef CSIDL_MYPICTURES
20 # define CSIDL_MYPICTURES 0x0027
21 # endif //CSIDL_MYPICTURES
22 # ifndef CSIDL_MYMUSIC
23 # define CSIDL_MYMUSIC 0x000d
24 # endif //CSIDL_MYMUSIC
25 # ifndef CSIDL_MYVIDEO
26 # define CSIDL_MYVIDEO 0x000e
27 # endif //CSIDL_MYVIDEO
31 #endif //#ifdef _WIN32
80 inline static void PushBack(
ImVector<
char[MAX_FILENAME_BYTES]>& rv,
const char* s) {
81 const size_t sz = rv.size();
83 strcpy(&rv[sz][0], s ? s :
"\0");
85 # if (FILENAME_MAX!=PATH_MAX) // Will this work ? (I don't want to use templates)
86 inline static void PushBack(
ImVector<
char[MAX_PATH_BYTES]>& rv,
const char* s) {
87 const size_t sz = rv.size();
89 strcpy(&rv[sz][0], s ? s :
"\0");
91 # endif //#if (FILENAME_MAX!=PATH_MAX)
92 inline static void Substr(
const char* text,
char* rv,
int start,
int count=-1) {
94 if (count<0) count = (int) strlen(text) - start;
95 if (count>0) strncpy(rv,&text[start],count);
98 inline static int Find(
const char* text,
const char toFind,
int beg=0) {
100 for (
size_t i=beg,len=strlen(text);i<len;i++) {
101 if (text[i]==toFind)
return i;
105 inline static int FindLastOf(
const char* text,
const char toFind) {
106 if (!text)
return -1;
107 for (
int i=(
int)strlen(text)-1;i>=0;i--) {
108 if (text[i]==toFind)
return i;
112 inline static void ToLower(
const char* text,
char* rv) {
117 const size_t len = strlen(text);
118 for (
size_t i=0;i<len;i++) {
119 rv[i]=tolower(text[i]);
123 inline static void ToLowerInPlace(
char* text) {
125 for (
size_t i=0,len = strlen(text);i<len;i++) {
130 inline static void Split(
const char* text,
ImVector<
char[MAX_FILENAME_BYTES]>& rv,
const char c=
' ') {
133 const int len = (int)strlen(text);
136 for (
int i=0;i<len;i++) {
137 const char ch = text[i];
139 Substr(text,tmp,beg,i-beg);
145 Substr(text,tmp,beg,len-beg);
149 inline static void Replace(
const char* baseText,
const char textToReplace,
const char replacement,
char* rv) {
151 ReplaceInPlace(rv,textToReplace,replacement);
153 inline static void ReplaceInPlace(
char* text,
const char toReplace,
const char replacement) {
155 for (
size_t i=0,len = strlen(text);i<len;i++) {
157 if (c==toReplace) c=replacement;
163 inline static void wide_to_utf8(
const wchar_t* wstr,
char* rv) {
166 int size_needed = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
167 WideCharToMultiByte (CP_UTF8, 0, wstr, -1, &rv[0], size_needed, NULL, NULL);
172 inline static void utf8_to_wide(
const char* str,
wchar_t* rv) {
175 int size_needed = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
176 MultiByteToWideChar (CP_UTF8, 0, str, -1, &rv[0], size_needed);
187 static void GetAbsolutePath(
const char *path,
char *rv) {
190 if (!path || strlen(path)==0) realpath(
"./", rv);
191 else realpath(path, rv);
193 static const int bufferSize = PATH_MAX+1;
194 static wchar_t buffer[bufferSize];
195 static wchar_t wpath[bufferSize];
196 String::utf8_to_wide(path ? path :
"",wpath);
197 ::GetFullPathNameW(&wpath[0],bufferSize,&buffer[0],NULL);
198 String::wide_to_utf8(&buffer[0],rv);
200 String::ReplaceInPlace(rv,
'\\',
'/');
202 while ( (len=strlen(rv))>0 && rv[len-1]==
'/') rv[len-1]=
'\0';
206 static void GetDirectoryName(
const char *filePath,
char *rv) {
207 rv[0]=
'\0';
if (!filePath)
return;
208 const int sz = strlen(filePath);
209 if (sz==0 || strcmp(filePath,
"/")==0 || strcmp(filePath,
"\\")==0) {
213 const char c = filePath[sz-1];
214 if (c ==
'/' || c==
'\\') {
216 String::Substr(filePath,tmp,0,sz-1);
217 GetDirectoryName(tmp,rv);
225 int beg=String::FindLastOf(filePath,
'\\');
226 int beg2=String::FindLastOf(filePath,
'/');
227 beg=(beg>beg2?beg:beg2);
229 String::Substr(filePath,rv,0,1);
233 String::Substr(filePath,rv,0,beg);
239 static void GetFileName(
const char *filePath,
char *rv) {
240 int beg=String::FindLastOf(filePath,
'\\');
241 int beg2=String::FindLastOf(filePath,
'/');
242 beg=(beg>beg2?beg:beg2);
244 String::Substr(filePath,rv,beg+1);
250 static void GetExtension(
const char* filePath,
char *rv) {
251 int beg=String::FindLastOf(filePath,
'.');
252 int beg2=String::FindLastOf(filePath,
'/');
253 int beg3=String::FindLastOf(filePath,
'\\');
255 if (beg3!=-1) beg2 = beg3;
256 else beg2 = beg2 > beg3 ? beg2 : beg3;
258 else if (beg3!=-1) beg2 = beg3;
261 String::Substr(filePath,rv,beg);
262 String::ToLowerInPlace(rv);
268 String::Substr(filePath,rv,beg);
269 String::ToLowerInPlace(rv);
276 static void Combine(
const char* directory,
const char* fileName,
char* rv,
bool appendMode=
true) {
277 if (!appendMode) rv[0]=
'\0';
278 const size_t size= directory ? strlen(directory) : 0;
283 strcat(rv,directory);
284 if (directory[size-1]!=
'\\' && directory[size-1]!=
'/') {
288 else strcat(rv,fileName);
291 static void Append(
const char* directory,
char* rv) {
292 if (!directory || strlen(directory)==0)
return;
293 size_t size = strlen(rv);
294 if (size>0 && (rv[size-1]!=
'\\' && rv[size-1]!=
'/')) {strcat(rv,
"/");++size;}
295 strcat(rv,directory);
297 while (size>0 && (rv[size-1]==
'\\' || rv[size-1]==
'/')) {rv[size-1]=
'\0';--size;}
298 if (size==0 || rv[size-1]==
':') strcat(rv,
"/");
300 static void Split(
const char* path,
ImVector<
char[MAX_FILENAME_BYTES]>& rv,
bool leaveIntermediateTrailingSlashes=
true) {
303 String::Replace(path,
'\\',
'/',tex);
304 size_t len = strlen(tex);
307 while ((len = strlen(tex))>0 && tex[len-1]==
'/') {
308 strncpy(tex2,tex,len+1);
309 String::Substr(tex2,tex,0,len-1);
314 while ( (beg = String::Find(tex,
'/'))!=-1) {
316 String::Substr(tex,tmp,0,leaveIntermediateTrailingSlashes ? beg+1 : beg);
317 String::PushBack(rv,tmp);
319 String::Substr(tex2,tex,beg+1);
321 String::PushBack(rv,tex);
322 if (rv.size()>0 && strlen(rv[0])==0) strcpy((
char*)&rv[0][0],
"/\0");
324 if (rv.size()==1 && strlen(rv[0])>0 && rv[0][strlen(rv[0])-1]==
':') strcat((
char*)&rv[0][0],
"/");
346 class SortingHelper {
348 typedef int (*SorterSignature)(
const struct dirent **e1,
const struct dirent **e2);
349 inline static const SorterSignature& SetSorter(
Sorting sorting) {
350 const int isort =(int) sorting;
351 if (isort>=0 && isort<(
int)
SORT_ORDER_COUNT)
return (sorter = Sorters[isort]);
352 return (sorter = Sorters[0]);
356 const static SorterSignature Sorters[];
357 static struct stat stat1;
358 static struct stat stat2;
359 static SorterSignature sorter;
362 inline static int strcasecmp(
const char *s1,
const char *s2 ) {
363 return _stricmp(s1,s2);
368 static int Alphasort(
const struct dirent **e1,
const struct dirent **e2) {
369 return strcasecmp((*e1)->d_name,(*e2)->d_name);
371 static int Alphasortinverse (
const struct dirent **e1,
const struct dirent **e2) {
372 return -strcasecmp((*e1)->d_name,(*e2)->d_name);
375 static int Lastmodsort (
const struct dirent **e1,
const struct dirent **e2) {
376 if (stat((*e1)->d_name,&stat1)==-1)
return -1;
377 if (stat((*e2)->d_name,&stat2)==-1)
return 1;
378 return (stat1.st_mtime < stat2.st_mtime ? -1 : stat1.st_mtime > stat2.st_mtime ? 1 : 0);
380 static int Lastmodsortinverse(
const struct dirent **e1,
const struct dirent **e2) {
381 if (stat((*e1)->d_name,&stat1)==-1)
return 1;
382 if (stat((*e2)->d_name,&stat2)==-1)
return -1;
383 return (stat2.st_mtime < stat1.st_mtime ? -1 : stat2.st_mtime > stat1.st_mtime ? 1 : 0);
385 static int Sizesort (
const struct dirent **e1,
const struct dirent **e2) {
386 if (stat((*e1)->d_name,&stat1)==-1)
return -1;
387 if (stat((*e2)->d_name,&stat2)==-1)
return 1;
388 return (stat1.st_size < stat2.st_size ? -1 : stat1.st_size > stat2.st_size ? 1 : 0);
390 static int Sizesortinverse(
const struct dirent **e1,
const struct dirent **e2) {
391 if (stat((*e1)->d_name,&stat1)==-1)
return 1;
392 if (stat((*e2)->d_name,&stat2)==-1)
return -1;
393 return (stat2.st_size < stat1.st_size ? -1 : stat2.st_size > stat1.st_size ? 1 : 0);
396 static int Typesort(
const struct dirent **e1,
const struct dirent **e2) {
397 static const int dot = (int)
'.';
398 const char * p1 = strrchr((
const char*) (*e1)->d_name, dot );
399 const char * p2 = strrchr((
const char*) (*e2)->d_name, dot );
400 if (!p1)
return (!p2?0:-1);
401 else if (!p2)
return 1;
402 return strcasecmp(p1,p2);
404 static int Typesortinverse (
const struct dirent **e1,
const struct dirent **e2) {
405 static const int dot = (int)
'.';
406 const char * p1 = strrchr((
const char*) (*e1)->d_name, dot );
407 const char * p2 = strrchr((
const char*) (*e2)->d_name, dot );
408 if (!p1)
return (!p2?0:1);
409 else if (!p2)
return -1;
410 return -strcasecmp(p1,p2);
414 const SortingHelper::SorterSignature SortingHelper::Sorters[] = {&SortingHelper::Alphasort,&SortingHelper::Alphasortinverse,&SortingHelper::Lastmodsort,&SortingHelper::Lastmodsortinverse,&SortingHelper::Sizesort,&SortingHelper::Sizesortinverse,&Typesort,&SortingHelper::Typesortinverse};
415 SortingHelper::SorterSignature SortingHelper::sorter;
416 struct stat SortingHelper::stat1;
417 struct stat SortingHelper::stat2;
421 result.clear();
if (pOptionalNamesOut) pOptionalNamesOut->clear();
423 struct dirent **eps = NULL;
425 sz = strlen(directoryName);
427 strcpy(directoryName2,directoryName);
429 if (sz>0 && directoryName[sz-1]==
':') {directoryName2[sz]=
'\\';directoryName2[sz+1]=
'\0';}
431 const int n = scandir (directoryName2, &eps, DirentGetDirectories, SortingHelper::SetSorter(sorting));
434 if (sz>0 && directoryName[sz-1] ==
'/') String::Substr(directoryName,directoryNameWithoutSlash,0,sz-1);
435 else strcpy(directoryNameWithoutSlash,directoryName);
438 result.reserve((
size_t)n);
if (pOptionalNamesOut) pOptionalNamesOut->reserve((
size_t)n);
439 for (
int cnt = 0; cnt < n; ++cnt) {
440 const char* pName = &eps[cnt]->d_name[0];
443 if (strcmp(pName,
".")!=0 && strcmp(pName,
"..")!=0 && pName[0]!=
'.' && pName[sz-1]!=
'~') {
444 strcpy(tempString,directoryNameWithoutSlash);
445 strcat(tempString,
"/");
446 strcat(tempString,pName);
447 String::PushBack(result,tempString);
448 if (pOptionalNamesOut) String::PushBack(*pOptionalNamesOut,pName);
452 if (eps) {free(eps);eps=NULL;}
455 result.clear();
if (pOptionalNamesOut) pOptionalNamesOut->clear();
457 struct dirent **eps = NULL;
459 sz = strlen(directoryName);
461 strcpy(directoryName2,directoryName);
463 if (sz>0 && directoryName[sz-1]==
':') {directoryName2[sz]=
'\\';directoryName2[sz+1]=
'\0';}
465 const int n = scandir (directoryName2, &eps, DirentGetFiles, SortingHelper::SetSorter(sorting));
468 if (sz>0 && directoryName[sz-1] ==
'/') String::Substr(directoryName,directoryNameWithoutSlash,0,sz-1);
469 else strcpy(directoryNameWithoutSlash,directoryName);
472 result.reserve((
size_t)n);
if (pOptionalNamesOut) pOptionalNamesOut->reserve((
size_t)n);
473 for (
int cnt = 0; cnt < n; ++cnt) {
474 const char* pName = &eps[cnt]->d_name[0];
477 if (pName[0]!=
'.' && pName[sz-1]!=
'~') {
478 strcpy(tempString,directoryNameWithoutSlash);
479 strcat(tempString,
"/");
480 strcat(tempString,pName);
481 String::PushBack(result,tempString);
482 if (pOptionalNamesOut) String::PushBack(*pOptionalNamesOut,pName);
486 if (eps) {free(eps);eps=NULL;}
490 static void GetFiles(
const char* path,
ImVector<
char[MAX_PATH_BYTES]>& files,
const char* wantedExtensions,
const char* unwantedExtensions=NULL,
ImVector<
char[MAX_FILENAME_BYTES]>* pOptionalNamesOut=NULL,
Sorting sorting=
SORT_ORDER_ALPHABETIC) {
493 GetFiles(path,filesIn,&namesIn,sorting);
494 if ((wantedExtensions==0 || strlen(wantedExtensions)==0) && (unwantedExtensions==0 || strlen(unwantedExtensions)==0)) {files = filesIn;
return;}
495 files.
clear();
if (pOptionalNamesOut) pOptionalNamesOut->clear();
498 char woext[
MAX_PATH_BYTES];String::ToLower(unwantedExtensions,woext);
501 if (wantedExtensions && strlen(wantedExtensions)>0) {
502 files.reserve(filesIn.
size());
if (pOptionalNamesOut) pOptionalNamesOut->reserve(namesIn.
size());
504 const size_t wExtsSize = wExts.
size();
506 for (
size_t i = 0,sz = filesIn.
size();i<sz;i++) {
507 Path::GetExtension(filesIn[i],ext);
508 for (
size_t e=0;e<wExtsSize;e++) {
509 if (strcmp(ext,wExts[e])==0) {
510 String::PushBack(files,filesIn[i]);
511 if (pOptionalNamesOut) String::PushBack(*pOptionalNamesOut,namesIn[i]);
518 else if (unwantedExtensions && strlen(unwantedExtensions)>0) {
519 files.reserve(filesIn.
size());
if (pOptionalNamesOut) pOptionalNamesOut->reserve(namesIn.
size());
521 const size_t woExtsSize = woExts.
size();
522 if (woExts.
size()==0) {files = filesIn;
return;}
524 for (
size_t i = 0,sz = filesIn.
size();i<sz;i++) {
525 Path::GetExtension(filesIn[i],ext);
527 for (
size_t e=0;e<woExtsSize;e++) {
528 if (strcmp(ext,woExts[e])==0) {
534 String::PushBack(files,filesIn[i]);
535 if (pOptionalNamesOut) String::PushBack(*pOptionalNamesOut,namesIn[i]);
541 if (pOptionalNamesOut) *pOptionalNamesOut = namesIn;
545 inline static void Create(
const char* directoryName) {
547 const mode_t mode = S_IFDIR | S_IREAD | S_IWRITE | S_IRWXU | S_IRWXG | S_IRWXO;
548 mkdir(directoryName,mode);
550 static wchar_t name[PATH_MAX+1];
551 String::utf8_to_wide(directoryName,name);
552 ::CreateDirectoryW(name,NULL);
556 inline static bool Exists(
const char* path) {
558 return (stat(path, &statbuf) != -1 && S_ISDIR(statbuf.st_mode));
560 inline static const ImVector<char[MAX_PATH_BYTES]> &GetUserKnownDirectories(
const ImVector<
char[MAX_FILENAME_BYTES]> **pOptionalUserKnownDirectoryDisplayNamesOut,
const int** pOptionalNumberKnownUserDirectoriesExceptDrives=NULL,
bool forceUpdate=
false) {
561 static bool init =
false;
565 static int numberKnownUserDirectoriesExceptDrives = 0;
566 if (pOptionalUserKnownDirectoryDisplayNamesOut) *pOptionalUserKnownDirectoryDisplayNamesOut = &dn;
567 if (pOptionalNumberKnownUserDirectoriesExceptDrives) *pOptionalNumberKnownUserDirectoriesExceptDrives = &numberKnownUserDirectoriesExceptDrives;
568 if (init && !forceUpdate)
return rv;
572 static const int csid[] = {
581 static const char* name[] = {
590 static const int csidSize =
sizeof(csid)/
sizeof(csid[0]);
591 static const int nameSize =
sizeof(name)/
sizeof(name[0]);
593 if (csidSize!=nameSize) fprintf(stderr,
"ERROR in file: imguifilesystem.cpp. Directory::GetUserKnownDirectories(...) csidSize!=nameSize.\n");
594 char tmp[
MAX_PATH_BYTES] =
"C:/";
while (tmp[0]<=
'Z') {
if (Directory::Exists(tmp)) String::PushBack(mediaFolders,tmp);tmp[0]=(char)((
int)tmp[0]+1);}
597 WCHAR path[MAX_PATH+1];
598 for (
int i=0;i<csidSize;i++) {
599 if (!GetSpecialFolderPathW(csid[i],&path[0],NULL))
continue;
601 String::wide_to_utf8(&path[0],tmp2);
602 String::PushBack(rv,tmp2);
603 String::PushBack(dn,name[i]);
605 numberKnownUserDirectoriesExceptDrives = (int) rv.
size();
607 for (
int i=0,msz=mediaFolders.
size();i<msz;i++) {
608 const char* mediaFolder = mediaFolders[i];
609 String::PushBack(rv,mediaFolder);
610 String::Substr(mediaFolder,mediaFolderName,0,strlen(mediaFolder)-1);
611 String::PushBack(dn,mediaFolderName);
614 const char* homedir = NULL;
615 if ((homedir = getenv(
"HOME")) == NULL) {
616 homedir = getpwuid(getuid())->pw_dir;
618 if (homedir==NULL)
return rv;
620 char userString[
MAX_PATH_BYTES];Path::GetFileName(homeString,userString);
630 static const int folderSize =
sizeof(folder)/
sizeof(folder[0]);
633 String::PushBack(rv,homeString);
636 String::PushBack(dn,temp);
637 for (
int i=0;i<folderSize;i++) {
638 Path::Combine(homeString,folder[i],temp,
false);
639 if (Directory::Exists(temp)) {
640 String::PushBack(rv,temp);
641 String::PushBack(dn,folder[i]);
644 numberKnownUserDirectoriesExceptDrives = (int) rv.
size();
646 static const char* mountLocations[] = {
"/media",
"/mnt",
"/Volumes",
"/vol",
"/data"};
647 static const int mountLocationSize =
sizeof(mountLocations)/
sizeof(mountLocations[0]);
648 static const bool ifHomeSubfolerIsFoundInMountLocationsForgetThatRootMountLocation =
true;
650 for (
int mntLocIndex=0,sz = 2*mountLocationSize;mntLocIndex<sz;mntLocIndex++) {
651 const int index = mntLocIndex/2;
652 const char* mntLocString = mountLocations[index];
653 const bool useUserSuffix = (mntLocIndex%2)==0;
655 Path::Combine(mntLocString,userString,userMediaString,
false);
656 strcpy(temp,userMediaString);
658 else if (lastGood && ifHomeSubfolerIsFoundInMountLocationsForgetThatRootMountLocation) {lastGood =
false;
continue;}
659 else strcpy(userMediaString,mntLocString);
660 lastGood = Directory::Exists(userMediaString);
661 if (!lastGood)
continue;
662 Directory::GetDirectories(userMediaString,mediaFolders);
663 if (mediaFolders.
size()==0)
continue;
666 for (
int i=0,msz=mediaFolders.
size();i<msz;i++) {
667 if (strcmp(mediaFolders[i],temp)==0)
continue;
668 String::PushBack(rv,mediaFolders[i]);
670 Path::GetFileName(mediaFolders[i],tmp);
671 String::PushBack(dn,tmp);
683 static int DirentGetDirectories(
const struct dirent *de) {
684 if (de->d_type==DT_DIR)
return 1;
687 static int DirentGetFiles(
const struct dirent *de) {
688 if (de->d_type==DT_REG)
return 1;
693 static bool GetSpecialFolderPathW(
int specialFolderCSIDL,WCHAR* pathOutWithSizeMaxPathPlusOne,HWND parent) {
702 WCHAR* temp_path = pathOutWithSizeMaxPathPlusOne;
704 LPITEMIDLIST pidl=NULL;
705 if (!SUCCEEDED(::SHGetSpecialFolderLocation(parent,specialFolderCSIDL, &pidl)))
707 temp_path[0]=L
'\0';
return false;
709 bool ok=SUCCEEDED(::SHGetPathFromIDListW(pidl,&temp_path[0]));
712 if ( ::SHGetMalloc( & mal ) == E_FAIL || !mal ) ::free( pidl );
720 temp_path[0]=L
'\0';
return false;
737 void display()
const {
738 fprintf(stderr,
"fullFolder=\"%s\" currentFolder=\"%s\" splitPathIndex=%d\n",fullFolder,currentFolder,splitPathIndex);
740 void getSplitPath(
ImVector<
char[MAX_FILENAME_BYTES]>& splitPath)
const {
741 Path::Split(fullFolder,splitPath);
743 const FolderInfo& operator=(
const FolderInfo& o) {
744 strcpy(currentFolder,o.currentFolder);
745 strcpy(fullFolder,o.fullFolder);
746 splitPathIndex = o.splitPathIndex;
749 inline void reset() {
750 currentFolder[0]=
'\0';fullFolder[0]=
'\0';splitPathIndex=-1;
752 FolderInfo() {reset();}
753 FolderInfo(
const FolderInfo& o) {*
this=o;}
755 void fromCurrentFolder(
const char* path) {
756 if (!path || strlen(path)==0) reset();
758 strcpy(currentFolder,path);
759 strcpy(fullFolder,path);
760 Path::Split(fullFolder,SplitPath);
761 splitPathIndex = (int) SplitPath.
size()-1;
764 bool isEqual(
const FolderInfo& fi)
const {
765 return strcmp(fullFolder,fi.fullFolder)==0 && strcmp(currentFolder,fi.currentFolder)==0;
767 bool isEqual(
const char* path)
const {
768 return strcmp(fullFolder,path)==0 && strcmp(currentFolder,path)==0;
770 int getSplitPathIndexFor(
const char* path)
const {
771 if (!path || strncmp(path,fullFolder,strlen(path))!=0)
return -1;
773 Path::Split(fullFolder,SplitPath);
775 for (
int i=0,sz=(
int)SplitPath.
size();i<sz;i++) {
776 Path::Append(SplitPath[i],tmp);
778 if (strcmp(tmp,path)==0)
return i;
782 bool getFolderInfoForSplitPathIndex(
int _splitPathIndex,FolderInfo& rv)
const {
783 Path::Split(fullFolder,SplitPath);
784 const int splitPathSize = (int)SplitPath.
size();
785 if (_splitPathIndex<0 || _splitPathIndex>=splitPathSize)
return false;
787 rv.splitPathIndex = _splitPathIndex;
789 rv.currentFolder[0]=
'\0';
790 if (_splitPathIndex>=0 && _splitPathIndex<splitPathSize) {
791 for (
int i=0;i<=_splitPathIndex;i++) {
792 Path::Append(SplitPath[i],rv.currentFolder);
807 int currentInfoIndex;
809 inline bool canGoBack() {
810 return currentInfoIndex>0;
812 inline bool canGoForward() {
813 return currentInfoIndex>=0 && currentInfoIndex<(int)info.
size()-1;
815 void reset() {info.
clear();currentInfoIndex=-1;}
820 if (canGoBack()) --currentInfoIndex;
823 if (canGoForward()) ++currentInfoIndex;
825 bool switchTo(
const char* currentFolder) {
826 if (!currentFolder || strlen(currentFolder)==0)
return false;
827 if (currentInfoIndex<0) {
829 info.
resize(currentInfoIndex+1);
830 FolderInfo& fi = info[currentInfoIndex];
831 fi.fromCurrentFolder(currentFolder);
835 const FolderInfo& lastInfo = info[currentInfoIndex];
836 if (lastInfo.isEqual(currentFolder))
return false;
837 const int splitPathIndexInsideLastInfo = lastInfo.getSplitPathIndexFor(currentFolder);
839 info.
resize(currentInfoIndex+1);
840 FolderInfo& fi = info[currentInfoIndex];
841 if (splitPathIndexInsideLastInfo==-1) fi.fromCurrentFolder(currentFolder);
844 fi.splitPathIndex = splitPathIndexInsideLastInfo;
845 strcpy(fi.currentFolder,currentFolder);
850 bool switchTo(
const FolderInfo& fi) {
851 if (!fi.currentFolder || strlen(fi.currentFolder)==0)
return false;
852 if (currentInfoIndex>=0) {
853 const FolderInfo& lastInfo = info[currentInfoIndex];
854 if (lastInfo.isEqual(fi))
return false;
857 info.
resize(currentInfoIndex+1);
858 info[currentInfoIndex] = fi;
863 inline bool isValid()
const {
return (currentInfoIndex>=0 && currentInfoIndex<(
int)info.
size());}
864 const FolderInfo* getCurrentFolderInfo()
const {
return isValid() ? &info[currentInfoIndex] : NULL;}
865 const char* getCurrentFolder()
const {
return isValid() ? &info[currentInfoIndex].currentFolder[0] : NULL;}
866 bool getCurrentSplitPath(
ImVector<
char[MAX_FILENAME_BYTES]>& rv)
const {
868 info[currentInfoIndex].getSplitPath(rv);
873 const int* getCurrentSplitPathIndex()
const {
return isValid() ? &info[currentInfoIndex].splitPathIndex : NULL;}
874 size_t getInfoSize()
const {
return info.
size();}
890 bool isSelectFolderDialog;
891 bool isSaveFileDialog;
893 bool allowDirectoryCreation,forbidDirectoryCreation;
894 bool allowKnownDirectoriesSection;
906 int totalNumBrowsingEntries;
907 int numBrowsingColumns;
908 int numBrowsingEntriesPerColumn;
909 static bool BrowsingPerRow;
910 bool allowDisplayByOption;
912 bool detectKnownDirectoriesAtEveryOpening;
913 bool mustFilterSaveFilePathWithFileFilterExtensionString;
915 bool editLocationCheckButtonPressed;
919 void resetVariables() {
920 strcpy(currentFolder,
"./");
929 isSelectFolderDialog =
false;
930 isSaveFileDialog =
false;
932 allowDirectoryCreation =
true;
933 forbidDirectoryCreation =
false;
934 strcpy(newDirectoryName,
"New Folder");
935 saveFileName[0] =
'\0';
940 chosenPath[0] =
'\0';
943 allowFiltering =
false;
945 totalNumBrowsingEntries = 0;
946 numBrowsingColumns = 1;
947 numBrowsingEntriesPerColumn = 1000;
949 detectKnownDirectoriesAtEveryOpening =
false;
950 allowDisplayByOption =
false;
951 allowKnownDirectoriesSection =
true;
953 mustFilterSaveFilePathWithFileFilterExtensionString =
true;
955 editLocationCheckButtonPressed =
false;
956 strcpy(editLocationInputText,
"\0");
961 ImGuiCol_Dialog_Directory_Background,
962 ImGuiCol_Dialog_Directory_Hover,
963 ImGuiCol_Dialog_Directory_Pressed,
964 ImGuiCol_Dialog_Directory_Text,
966 ImGuiCol_Dialog_File_Background,
967 ImGuiCol_Dialog_File_Hover,
968 ImGuiCol_Dialog_File_Pressed,
969 ImGuiCol_Dialog_File_Text,
971 ImGuiCol_Dialog_SelectedFolder_Text,
976 const float rr = (r.
x+r.
y+r.
z)*0.3334f;
977 c.
x = rr * factor.
x;c.
y = rr * factor.
y;c.
z = rr * factor.
z;c.
w = r.
w;
980 bool Internal::BrowsingPerRow =
false;
983 Dialog::Dialog(
bool noKnownDirectoriesSection,
bool noCreateDirectorySection,
bool noFilteringSection,
bool detectKnownDirectoriesAtEachOpening,
bool addDisplayByOption,
bool dontFilterSaveFilePathsEnteredByTheUser) {
985 new(
internal) Internal();
987 internal->resetVariables();
989 internal->uniqueNumber = un++;
991 internal->detectKnownDirectoriesAtEveryOpening = detectKnownDirectoriesAtEachOpening;
992 internal->allowDisplayByOption = addDisplayByOption;
993 internal->forbidDirectoryCreation = noCreateDirectorySection;
994 internal->allowKnownDirectoriesSection = !noKnownDirectoriesSection;
995 internal->allowFiltering = !noFilteringSection;
996 internal->mustFilterSaveFilePathWithFileFilterExtensionString = !dontFilterSaveFilePathsEnteredByTheUser;
1012 va_start(args, fmt);
1013 int w = vsnprintf(buf, buf_size, fmt, args);
1015 buf[buf_size-1] = 0;
1016 return (w == -1) ? buf_size : (size_t)w;
1021 const char*
ChooseFileMainMethod(
Dialog& ist,
const char* directory,
const bool _isFolderChooserDialog,
const bool _isSaveFileDialog,
const char* _saveFileName,
const char* fileFilterExtensionString,
const char* windowTitle,
const ImVec2& windowSize,
const ImVec2& windowPos,
const float windowAlpha) {
1024 char* rv = I.chosenPath;rv[0] =
'\0';
1026 bool& isSelectFolderDialog = I.isSelectFolderDialog = _isFolderChooserDialog;
1027 bool& isSaveFileDialog = I.isSaveFileDialog = _isSaveFileDialog;
1029 bool& allowDirectoryCreation = I.allowDirectoryCreation = I.forbidDirectoryCreation ?
false : (isSelectFolderDialog || isSaveFileDialog);
1031 static const int* pNumberKnownUserDirectoriesExceptDrives=NULL;
1033 static const ImVector<char[MAX_PATH_BYTES]>* pUserKnownDirectories = &Directory::GetUserKnownDirectories(&pUserKnownDirectoryDisplayNames,&pNumberKnownUserDirectoriesExceptDrives);
1036 ImVec4 dummyButtonColor(0.0f,0.0f,0.0f,0.5f);
1037 static ImVec4 ColorSet[Internal::ImGuiCol_Dialog_Size];
1040 static const ImVec4 df(0.9,0.9,0.3,1);
1041 static const ImVec4 ff(0.7,0.7,0.7,1);
1043 for (
int i=0,sz=(
int)Internal::ImGuiCol_Dialog_Directory_Text;i<=sz;i++) {
1046 Internal::ColorCombine(c,r,df);
1048 for (
int i=(
int)Internal::ImGuiCol_Dialog_File_Background,sz=(
int)Internal::ImGuiCol_Dialog_File_Text;i<=sz;i++) {
1051 Internal::ColorCombine(c,r,ff);
1053 if (dummyButtonColor.
w>0) {
1055 dummyButtonColor.
x = bbc.
x;dummyButtonColor.
y = bbc.
y;dummyButtonColor.
z = bbc.
z;dummyButtonColor.
w *= bbc.
w;
1061 if (directory && strlen(directory)>0) {
1062 if (Directory::Exists(directory)) strcpy(validDirectory,directory);
1064 Path::GetDirectoryName(directory,validDirectory);
1065 if (!Directory::Exists(validDirectory)) validDirectory[0]=
'\0';
1068 Path::GetAbsolutePath(validDirectory,I.currentFolder);
1070 I.editLocationCheckButtonPressed =
false;
1072 I.history.switchTo(I.currentFolder);
1073 I.dirs.clear();I.files.clear();I.dirNames.clear();I.fileNames.clear();I.currentSplitPath.clear();
1074 strcpy(&I.newDirectoryName[0],
"New Folder");
1075 if (_saveFileName) {
1077 Path::GetFileName(_saveFileName,I.saveFileName);
1079 else I.saveFileName[0]=
'\0';
1080 isSelectFolderDialog = _isFolderChooserDialog;
1081 isSaveFileDialog = _isSaveFileDialog;
1082 allowDirectoryCreation = I.forbidDirectoryCreation ?
false : (isSelectFolderDialog || isSaveFileDialog);
1084 I.forceRescan =
true;
1087 if (!windowTitle || strlen(windowTitle)==0) {
1088 if (isSelectFolderDialog) strcpy(I.wndTitle,
"Please select a folder");
1089 else if (isSaveFileDialog) strcpy(I.wndTitle,
"Please choose/create a file for saving");
1090 else strcpy(I.wndTitle,
"Please choose a file");
1092 else strcpy(I.wndTitle,windowTitle);
1093 strcat(I.wndTitle,
"##");
1094 char tmpWndTitleNumber[12];
1096 strcat(I.wndTitle,tmpWndTitleNumber);
1097 I.wndPos = windowPos;
1098 I.wndSize = windowSize;
1099 if (I.wndSize.x<=0) I.wndSize.x = 400;
1100 if (I.wndSize.y<=0) I.wndSize.y = 400;
1103 if (I.wndPos.x<=0) I.wndPos.x = mousePos.
x - I.wndSize.x*0.5f;
1104 if (I.wndPos.y<=0) I.wndPos.y = mousePos.
y - I.wndSize.y*0.5f;
1106 if (I.wndPos.x>screenSize.
x-I.wndSize.x) I.wndPos.x = screenSize.
x-I.wndSize.x;
1107 if (I.wndPos.y>screenSize.
y-I.wndSize.y) I.wndPos.y = screenSize.
y-I.wndSize.y;
1108 if (I.wndPos.x < 0) I.wndPos.x = 0;
1109 if (I.wndPos.y < 0) I.wndPos.y = 0;
1111 if (I.detectKnownDirectoriesAtEveryOpening) pUserKnownDirectories = &Directory::GetUserKnownDirectories(&pUserKnownDirectoryDisplayNames,&pNumberKnownUserDirectoriesExceptDrives,
true);
1113 if (!I.open)
return rv;
1115 if (I.forceRescan) {
1116 I.forceRescan =
false;
1118 Directory::GetDirectories(I.currentFolder,I.dirs,&I.dirNames,(
Sorting)sortingModeForDirectories);
1121 if (!isSelectFolderDialog) {
1122 if (!fileFilterExtensionString || strlen(fileFilterExtensionString)==0) Directory::GetFiles(I.currentFolder,I.files,&I.fileNames,(
Sorting)I.sortingMode);
1123 else Directory::GetFiles(I.currentFolder,I.files,fileFilterExtensionString,NULL,&I.fileNames,(
Sorting)I.sortingMode);
1127 I.files.clear();I.fileNames.clear();
1128 I.saveFileName[0]=
'\0';
1130 Path::GetFileName(I.currentFolder,currentFolderName);
1131 const size_t currentFolderNameSize = strlen(currentFolderName);
1132 if (currentFolderNameSize==0 || currentFolderName[currentFolderNameSize-1]==
':') strcat(currentFolderName,
"/");
1133 strcat(I.saveFileName,currentFolderName);
1136 I.history.getCurrentSplitPath(I.currentSplitPath);
1138 const static int approxNumEntriesPerColumn = 20;
1139 I.totalNumBrowsingEntries = (int)(I.dirs.size()+I.files.size());
1140 I.numBrowsingColumns = I.totalNumBrowsingEntries/approxNumEntriesPerColumn;
1141 if (I.numBrowsingColumns<=0) I.numBrowsingColumns = 1;
1142 if (I.totalNumBrowsingEntries%approxNumEntriesPerColumn>(approxNumEntriesPerColumn/2)) ++I.numBrowsingColumns;
1143 if (I.numBrowsingColumns>6) I.numBrowsingColumns = 6;
1144 I.numBrowsingEntriesPerColumn = I.totalNumBrowsingEntries/I.numBrowsingColumns;
1145 if (I.totalNumBrowsingEntries%I.numBrowsingColumns!=0) ++I.numBrowsingEntriesPerColumn;
1148 # ifdef DEBUG_HISTORY
1149 if (I.history.getInfoSize()>0) fprintf(stderr,
"\nHISTORY: currentFolder:\"%s\" history.canGoBack=%s history.canGoForward=%s currentHistory:\n",I.currentFolder,I.history.canGoBack()?
"true":
"false",I.history.canGoForward()?
"true":
"false");
1150 if (I.history.getCurrentFolderInfo()) I.history.getCurrentFolderInfo()->display();
1151 # endif //DEBUG_HISTORY
1157 ImGui::Begin(I.wndTitle, &I.open, I.wndSize,windowAlpha);
1168 bool historyBackClicked =
false;
1169 bool historyForwardClicked =
false;
1174 const bool historyCanGoBack = I.history.canGoBack();
1175 const bool historyCanGoForward = I.history.canGoForward();
1177 if (!historyCanGoBack) {
1184 if (!historyCanGoBack) {
1190 if (!historyCanGoForward) {
1195 historyForwardClicked =
ImGui::Button(
">")&historyCanGoForward;
1197 if (!historyCanGoForward) {
1206 if (historyBackClicked || historyForwardClicked) {
1209 if (historyBackClicked) I.history.goBack();
1210 else if (historyForwardClicked) I.history.goForward();
1212 I.forceRescan =
true;
1214 strcpy(I.currentFolder,I.history.getCurrentFolder());
1215 strcpy(I.editLocationInputText,I.currentFolder);
1217 # ifdef DEBUG_HISTORY
1218 if (historyBackClicked) fprintf(stderr,
"\nPressed BACK to\t");
1219 else fprintf(stderr,
"\nPressed FORWARD to\t");
1220 fprintf(stderr,
"\"%s\" (%d)\n",I.currentFolder,(
int)*I.history.getCurrentSplitPathIndex());
1221 # undef DEBUG_HISTOTY
1222 # endif //DEBUG_HISTORY
1228 bool editLocationInputTextReturnPressed =
false;
1231 bool mustValidateInputPath =
false;
1235 I.editLocationCheckButtonPressed = !I.editLocationCheckButtonPressed;
1236 if (I.editLocationCheckButtonPressed) {
1237 strcpy(I.editLocationInputText,I.currentFolder);
1245 if (I.editLocationCheckButtonPressed) {
1248 if (editLocationInputTextReturnPressed) mustValidateInputPath =
true;
1252 if (mustValidateInputPath) {
1255 strcpy(cleanEnteredPath,I.editLocationInputText);
1256 size_t len = strlen(cleanEnteredPath);
1257 while (len>0 && (cleanEnteredPath[len-1]==
'/' || cleanEnteredPath[len-1]==
'\\')) {cleanEnteredPath[len-1]=
'\0';len = strlen(cleanEnteredPath);}
1259 if (len==0 || strcmp(I.currentFolder,cleanEnteredPath)==0) I.editLocationCheckButtonPressed =
false;
1260 else if (Directory::Exists(cleanEnteredPath)) {
1261 I.editLocationCheckButtonPressed =
false;
1263 I.history.switchTo(cleanEnteredPath);
1264 strcpy(I.currentFolder,cleanEnteredPath);
1265 I.forceRescan =
true;
1275 if (!I.editLocationCheckButtonPressed && !editLocationInputTextReturnPressed) {
1276 bool mustSwitchSplitPath =
false;
1277 const FolderInfo& fi = *I.history.getCurrentFolderInfo();
1280 const float originalFramePaddingX = framePadding.
x;
1290 const int numTabs=(int) I.currentSplitPath.size();
1291 int newSelectedTab = fi.splitPathIndex;
1292 for (
int t=0;t<numTabs;t++) {
1294 if (t==fi.splitPathIndex) {
1303 if (fi.splitPathIndex!=t && !mustSwitchSplitPath) mustSwitchSplitPath =
true;
1306 if (t==fi.splitPathIndex) {
1312 if (mustSwitchSplitPath) {
1314 fi.getFolderInfoForSplitPathIndex(newSelectedTab,mfi);
1315 I.history.switchTo(mfi);
1316 I.forceRescan =
true;
1317 strcpy(I.currentFolder,I.history.getCurrentFolder());
1318 strcpy(I.editLocationInputText,I.currentFolder);
1324 framePadding.
x = originalFramePaddingX;
1330 if (I.allowKnownDirectoriesSection && pUserKnownDirectories->
size()>0) {
1342 for (
int i=0,sz=(
int)pUserKnownDirectories->
size();i<sz;i++) {
1343 const char* userKnownFolder = (*pUserKnownDirectories)[i];
1344 const char* userKnownFolderDisplayName = (*pUserKnownDirectoryDisplayNames)[i];
1345 if (
ImGui::SmallButton(userKnownFolderDisplayName) && strcmp(userKnownFolder,I.currentFolder)!=0) {
1346 strcpy(I.currentFolder,userKnownFolder);
1347 strcpy(I.editLocationInputText,I.currentFolder);
1348 I.history.switchTo(I.currentFolder);
1349 I.forceRescan =
true;
1352 if (i!=sz-1 && (i>=*pNumberKnownUserDirectoriesExceptDrives || i%7!=6))
ImGui::SameLine();
1366 if (allowDirectoryCreation) {
1368 bool mustCreate =
false;
1374 ImGui::InputText(
"##createNewFolderName",&I.newDirectoryName[0],MAX_FILENAME_BYTES);
1381 if (mustCreate && strlen(I.newDirectoryName)>0) {
1383 Path::Combine(I.currentFolder,I.newDirectoryName,newDirPath,
false);
1384 if (!Directory::Exists(newDirPath)) {
1386 # ifdef SIMULATING_ONLY
1387 fprintf(stderr,
"creating: \"%s\"\n",newDirPath);
1388 # undef SIMULATING_ONLY
1389 # else //SIMULATING_ONLY
1390 Directory::Create(newDirPath);
1391 if (!Directory::Exists(newDirPath)) fprintf(stderr,
"Error creating new folder: \"%s\"\n",newDirPath);
1392 else I.forceRescan =
true;
1393 # endif //SIMULATING_ONLY
1399 if (I.allowFiltering) {
1413 if (isSaveFileDialog || isSelectFolderDialog) {
1415 bool selectionButtonPressed =
false;
1419 if (isSaveFileDialog) {
1429 static const ImVec4 sf(1.0,0.8,0.5,1);
1430 ImVec4& c = ColorSet[Internal::ImGuiCol_Dialog_SelectedFolder_Text];
1432 Internal::ColorCombine(c,r,sf);
1434 ImGui::TextColored(ColorSet[Internal::ImGuiCol_Dialog_SelectedFolder_Text],
"%s",&I.saveFileName[0],MAX_FILENAME_BYTES);
1438 if (isSelectFolderDialog) selectionButtonPressed =
ImGui::Button(
"Select");
1443 if (selectionButtonPressed) {
1444 if (isSelectFolderDialog) {
1445 strcpy(rv,I.currentFolder);
1448 else if (isSaveFileDialog) {
1449 if (strlen(I.saveFileName)>0) {
1451 if (I.mustFilterSaveFilePathWithFileFilterExtensionString && fileFilterExtensionString && strlen(fileFilterExtensionString)>0) {
1453 char saveFileNameExtension[
MAX_FILENAME_BYTES];Path::GetExtension(I.saveFileName,saveFileNameExtension);
1454 const bool saveFileNameHasExtension = strlen(saveFileNameExtension)>0;
1457 const size_t wExtsSize = wExts.
size();
1458 if (!saveFileNameHasExtension) {
1459 if (wExtsSize==0) pathOk =
true;
1460 else strcat(I.saveFileName,wExts[0]);
1464 for (
size_t i = 0;i<wExtsSize;i++) {
1465 const char* ext = wExts[i];
1466 if (strcmp(ext,saveFileNameExtension)==0) {
1471 if (!pathOk && wExtsSize>0) strcat(I.saveFileName,wExts[0]);
1476 Path::Combine(I.currentFolder,I.saveFileName,savePath,
false);
1477 strcpy(rv,savePath);
1492 const int oldSortingMode = I.sortingMode;
1493 const int oldSelectedTab = I.sortingMode/2;
1499 int newSortingMode = oldSortingMode;
1500 static const char* names[numTabs] = {
"Name",
"Modified",
"Size",
"Type"};
1501 const int numUsedTabs = isSelectFolderDialog ? 2 : numTabs;
1502 for (
int t=0;t<numUsedTabs;t++) {
1504 if (t==oldSelectedTab) {
1511 if (oldSelectedTab==t) {
1512 newSortingMode = oldSortingMode;
1513 if (newSortingMode%2==0) ++newSortingMode;
1514 else --newSortingMode;
1516 else newSortingMode = t*2;
1518 if (t==oldSelectedTab) {
1523 if (newSortingMode!=oldSortingMode) {
1524 I.sortingMode = newSortingMode;
1526 I.forceRescan =
true;
1530 if (I.allowDisplayByOption && I.numBrowsingColumns>1) {
1535 if (
ImGui::SmallButton(!Internal::BrowsingPerRow ?
"Column##browsingPerRow" :
"Row##browsingPerRow")) {
1536 Internal::BrowsingPerRow = !Internal::BrowsingPerRow;
1558 if (I.dirs.size()>0) {
1564 for (
int i=0,sz=(
int)I.dirs.size();i<sz;i++) {
1565 const char* dirName = &I.dirNames[i][0];
1566 if (I.filter.PassFilter(dirName)) {
1568 strcpy(I.currentFolder,I.dirs[i]);
1569 strcpy(I.editLocationInputText,I.currentFolder);
1570 I.history.switchTo(I.currentFolder);
1571 I.forceRescan =
true;
1576 else if (cntEntries==I.numBrowsingEntriesPerColumn) {
1589 if (!isSelectFolderDialog && I.files.size()>0) {
1596 for (
int i=0,sz=(
int)I.files.size();i<sz;i++) {
1597 const char* fileName = &I.fileNames[i][0];
1598 if (I.filter.PassFilter(fileName)) {
1600 if (!isSaveFileDialog) {
1601 strcpy(rv,I.files[i]);
1605 Path::GetFileName(I.files[i],I.saveFileName);
1610 else if (cntEntries==I.numBrowsingEntriesPerColumn) {
1633 const char*
Dialog::chooseFileDialog(
bool dialogTriggerButton,
const char* directory,
const char* fileFilterExtensionString,
const char* windowTitle,
const ImVec2& windowSize,
const ImVec2& windowPos,
const float windowAlpha) {
1634 if (dialogTriggerButton) {
internal->rescan =
true;
internal->chosenPath[0]=
'\0';}
1636 ChooseFileMainMethod(*
this,directory,
false,
false,
"",fileFilterExtensionString,windowTitle,windowSize,windowPos,windowAlpha);
1641 if (dialogTriggerButton) {
internal->rescan =
true;
internal->chosenPath[0]=
'\0';}
1643 ChooseFileMainMethod(*
this,directory,
true,
false,
"",
"",windowTitle,windowSize,windowPos,windowAlpha);
1647 const char*
Dialog::saveFileDialog(
bool dialogTriggerButton,
const char* directory,
const char* startingFileNameEntry,
const char* fileFilterExtensionString,
const char* windowTitle,
const ImVec2& windowSize,
const ImVec2& windowPos,
const float windowAlpha) {
1648 if (dialogTriggerButton) {
internal->rescan =
true;
internal->chosenPath[0]=
'\0';}
1650 ChooseFileMainMethod(*
this,directory,
false,
true,startingFileNameEntry,fileFilterExtensionString,windowTitle,windowSize,windowPos,windowAlpha);
const char * chooseFileDialog(bool dialogTriggerButton, const char *directory=NULL, const char *fileFilterExtensionString=NULL, const char *windowTitle=NULL, const ImVec2 &windowSize=ImVec2(-1,-1), const ImVec2 &windowPos=ImVec2(-1,-1), const float windowAlpha=0.875f)
IMGUI_API bool CollapsingHeader(const char *label, const char *str_id=NULL, bool display_frame=true, bool default_open=false)
IMGUI_API void SetWindowPos(const ImVec2 &pos, ImGuiSetCond cond=0)
IMGUI_API void PopStyleColor(int count=1)
IMGUI_API void NextColumn()
IMGUI_API ImVec2 GetCursorPos()
Dialog(bool noKnownDirectoriesSection=false, bool noCreateDirectorySection=false, bool noFilteringSection=false, bool detectKnownDirectoriesAtEachOpening=false, bool addDisplayByOption=false, bool dontFilterSaveFilePathsEnteredByTheUser=false)
IMGUI_API ImVec2 GetMousePos()
const int MAX_FILENAME_BYTES
friend const char * ChooseFileMainMethod(Dialog &ist, const char *directory, const bool _isFolderChooserDialog, const bool _isSaveFileDialog, const char *_saveFileName, const char *fileFilterExtensionString, const char *windowTitle, const ImVec2 &windowSize, const ImVec2 &windowPos, const float windowAlpha)
IMGUI_API bool SmallButton(const char *label)
IMGUI_API void Color(const char *prefix, const ImVec4 &v)
const char * getLastDirectory() const
const char * getChosenPath() const
IMGUI_API void TextColored(const ImVec4 &col, const char *fmt,...)
IMGUI_API void AlignFirstTextHeightToWidgets()
IMGUI_API bool InputText(const char *label, char *buf, size_t buf_size, ImGuiInputTextFlags flags=0, ImGuiTextEditCallback callback=NULL, void *user_data=NULL)
const char * ChooseFileMainMethod(Dialog &ist, const char *directory, const bool _isFolderChooserDialog, const bool _isSaveFileDialog, const char *_saveFileName, const char *fileFilterExtensionString, const char *windowTitle, const ImVec2 &windowSize, const ImVec2 &windowPos, const float windowAlpha)
IMGUI_API bool Button(const char *label, const ImVec2 &size=ImVec2(0, 0), bool repeat_when_held=false)
IMGUI_API void SetKeyboardFocusHere(int offset=0)
const char * saveFileDialog(bool dialogTriggerButton, const char *directory=NULL, const char *startingFileNameEntry=NULL, const char *fileFilterExtensionString=NULL, const char *windowTitle=NULL, const ImVec2 &windowSize=ImVec2(-1,-1), const ImVec2 &windowPos=ImVec2(-1,-1), const float windowAlpha=0.875f)
IMGUI_API ImGuiIO & GetIO()
const char * chooseFolderDialog(bool dialogTriggerButton, const char *directory=NULL, const char *windowTitle=NULL, const ImVec2 &windowSize=ImVec2(-1,-1), const ImVec2 &windowPos=ImVec2(-1,-1), const float windowAlpha=0.875f)
IMGUI_API ImGuiStyle & GetStyle()
IMGUI_API void Columns(int count=1, const char *id=NULL, bool border=true)
IMGUI_API void SameLine(int column_x=0, int spacing_w=-1)
IMGUI_API void EndChild()
IMGUI_API void MemFree(void *ptr)
struct Internal * internal
ImVec4 Colors[ImGuiCol_COUNT]
void reserve(size_t new_capacity)
IMGUI_API void * MemAlloc(size_t sz)
IMGUI_API void Text(const char *fmt,...)
IMGUI_API void SetWindowSize(const ImVec2 &size, ImGuiSetCond cond=0)
IMGUI_API void Separator()
static size_t ImFormatString(char *buf, size_t buf_size, const char *fmt,...)
void resize(size_t new_size)
IMGUI_API bool BeginChild(const char *str_id, const ImVec2 &size=ImVec2(0, 0), bool border=false, ImGuiWindowFlags extra_flags=0)
IMGUI_API bool Begin(const char *name="Debug", bool *p_opened=NULL, const ImVec2 &initial_size=ImVec2(0, 0), float bg_alpha=-1.0f, ImGuiWindowFlags flags=0)
IMGUI_API void PushStyleColor(ImGuiCol idx, const ImVec4 &col)
IMGUI_API void PushID(const char *str_id)