mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-02-28 11:03:49 +00:00
Updates Native File Dialogs lib to enable browsing and selecting of folders, instead of just files.
This commit is contained in:
parent
4f78143dc8
commit
f657f774ce
7 changed files with 250 additions and 15 deletions
|
|
@ -3,7 +3,8 @@
|
|||
#
|
||||
# Scons build script -- GCC, Clang, Visual Studio
|
||||
# Does not build test
|
||||
|
||||
#
|
||||
# SCons builds are deprecated -- see README.md for details.
|
||||
|
||||
import os
|
||||
|
||||
|
|
@ -97,3 +98,5 @@ set_warnings(nfd_env)
|
|||
|
||||
nfd_env.Append( CPPPATH=['.','./include'] )
|
||||
nfd_env.StaticLibrary( get_lib_name('nfd', debug), nfd_files )
|
||||
|
||||
print "*** Scons builds are deprecated! See README.md for details."
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
#define _NFD_COMMON_H
|
||||
|
||||
#define NFD_MAX_STRLEN 256
|
||||
#define _NFD_UNUSED(x) ((void)x)
|
||||
#define _NFD_UNUSED(x) ((void)x)
|
||||
|
||||
void *NFDi_Malloc( size_t bytes );
|
||||
void NFDi_Free( void *ptr );
|
||||
|
|
|
|||
|
|
@ -50,6 +50,11 @@ nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList,
|
|||
const nfdchar_t *defaultPath,
|
||||
nfdchar_t **outPath );
|
||||
|
||||
|
||||
/* select folder dialog */
|
||||
nfdresult_t NFD_PickFolder( const nfdchar_t *defaultPath,
|
||||
nfdchar_t **outPath);
|
||||
|
||||
/* nfd_common.c */
|
||||
|
||||
/* get last error -- set when nfdresult_t returns NFD_ERROR */
|
||||
|
|
|
|||
|
|
@ -122,7 +122,8 @@ nfdresult_t NFD_OpenDialog( const char *filterList,
|
|||
nfdchar_t **outPath )
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
|
||||
NSWindow *keyWindow = [[NSApplication sharedApplication] keyWindow];
|
||||
NSOpenPanel *dialog = [NSOpenPanel openPanel];
|
||||
[dialog setAllowsMultipleSelection:NO];
|
||||
|
||||
|
|
@ -152,6 +153,7 @@ nfdresult_t NFD_OpenDialog( const char *filterList,
|
|||
}
|
||||
[pool release];
|
||||
|
||||
[keyWindow makeKeyAndOrderFront:nil];
|
||||
return nfdResult;
|
||||
}
|
||||
|
||||
|
|
@ -233,3 +235,42 @@ nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList,
|
|||
|
||||
return nfdResult;
|
||||
}
|
||||
|
||||
nfdresult_t NFD_PickFolder(const nfdchar_t *defaultPath,
|
||||
nfdchar_t **outPath)
|
||||
{
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
NSWindow *keyWindow = [[NSApplication sharedApplication] keyWindow];
|
||||
NSOpenPanel *dialog = [NSOpenPanel openPanel];
|
||||
[dialog setAllowsMultipleSelection:NO];
|
||||
[dialog setCanChooseDirectories:YES];
|
||||
[dialog setCanCreateDirectories:YES];
|
||||
[dialog setCanChooseFiles:NO];
|
||||
|
||||
// Set the starting directory
|
||||
SetDefaultPath(dialog, defaultPath);
|
||||
|
||||
nfdresult_t nfdResult = NFD_CANCEL;
|
||||
if ( [dialog runModal] == NSModalResponseOK )
|
||||
{
|
||||
NSURL *url = [dialog URL];
|
||||
const char *utf8Path = [[url path] UTF8String];
|
||||
|
||||
// byte count, not char count
|
||||
size_t len = strlen(utf8Path);//NFDi_UTF8_Strlen(utf8Path);
|
||||
|
||||
*outPath = NFDi_Malloc( len+1 );
|
||||
if ( !*outPath )
|
||||
{
|
||||
[pool release];
|
||||
return NFD_ERROR;
|
||||
}
|
||||
memcpy( *outPath, utf8Path, len+1 ); /* copy null term */
|
||||
nfdResult = NFD_OKAY;
|
||||
}
|
||||
[pool release];
|
||||
|
||||
[keyWindow makeKeyAndOrderFront:nil];
|
||||
return nfdResult;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,14 +47,10 @@ static void AddFiltersToDialog( GtkWidget *dialog, const char *filterList )
|
|||
if ( NFDi_IsFilterSegmentChar(*p_filterList) )
|
||||
{
|
||||
char typebufWildcard[NFD_MAX_STRLEN];
|
||||
|
||||
/* add another type to the filter */
|
||||
if (strlen(typebuf) <= 0 || strlen(typebuf) > NFD_MAX_STRLEN-1)
|
||||
{
|
||||
p_filterList++;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert( strlen(typebuf) > 0 );
|
||||
assert( strlen(typebuf) < NFD_MAX_STRLEN-1 );
|
||||
|
||||
snprintf( typebufWildcard, NFD_MAX_STRLEN, "*.%s", typebuf );
|
||||
AddTypeToFilterName( typebuf, filterName, NFD_MAX_STRLEN );
|
||||
|
||||
|
|
@ -297,6 +293,59 @@ nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList,
|
|||
/* Build the filter list */
|
||||
AddFiltersToDialog(dialog, filterList);
|
||||
|
||||
/* Set the default path */
|
||||
SetDefaultPath(dialog, defaultPath);
|
||||
|
||||
result = NFD_CANCEL;
|
||||
if ( gtk_dialog_run( GTK_DIALOG(dialog) ) == GTK_RESPONSE_ACCEPT )
|
||||
{
|
||||
char *filename;
|
||||
filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER(dialog) );
|
||||
|
||||
{
|
||||
size_t len = strlen(filename);
|
||||
*outPath = NFDi_Malloc( len + 1 );
|
||||
memcpy( *outPath, filename, len + 1 );
|
||||
if ( !*outPath )
|
||||
{
|
||||
g_free( filename );
|
||||
gtk_widget_destroy(dialog);
|
||||
return NFD_ERROR;
|
||||
}
|
||||
}
|
||||
g_free(filename);
|
||||
|
||||
result = NFD_OKAY;
|
||||
}
|
||||
|
||||
WaitForCleanup();
|
||||
gtk_widget_destroy(dialog);
|
||||
WaitForCleanup();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nfdresult_t NFD_PickFolder(const nfdchar_t *defaultPath,
|
||||
nfdchar_t **outPath)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
nfdresult_t result;
|
||||
|
||||
if (!gtk_init_check(NULL, NULL))
|
||||
{
|
||||
NFDi_SetError(INIT_FAIL_MSG);
|
||||
return NFD_ERROR;
|
||||
}
|
||||
|
||||
dialog = gtk_file_chooser_dialog_new( "Select folder",
|
||||
NULL,
|
||||
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||
"_Cancel", GTK_RESPONSE_CANCEL,
|
||||
"_Select", GTK_RESPONSE_ACCEPT,
|
||||
NULL );
|
||||
gtk_file_chooser_set_do_overwrite_confirmation( GTK_FILE_CHOOSER(dialog), TRUE );
|
||||
|
||||
|
||||
/* Set the default path */
|
||||
SetDefaultPath(dialog, defaultPath);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,13 +9,17 @@
|
|||
#define UNICODE
|
||||
#endif
|
||||
|
||||
#ifdef __MINGW32__
|
||||
// Explicitly setting NTDDI version, this is necessary for the MinGW compiler
|
||||
#define NTDDI_VERSION NTDDI_VISTA
|
||||
#define _WIN32_WINNT _WIN32_WINNT_VISTA
|
||||
#endif
|
||||
|
||||
#include <wchar.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <windows.h>
|
||||
#include <ShObjIdl.h>
|
||||
|
||||
#include "nfd_common.h"
|
||||
|
||||
|
||||
|
|
@ -359,14 +363,15 @@ nfdresult_t NFD_OpenDialog( const char *filterList,
|
|||
HRESULT result = ::CoInitializeEx(NULL,
|
||||
::COINIT_APARTMENTTHREADED |
|
||||
::COINIT_DISABLE_OLE1DDE );
|
||||
|
||||
::IFileOpenDialog *fileOpenDialog(NULL);
|
||||
|
||||
if ( !SUCCEEDED(result))
|
||||
{
|
||||
NFDi_SetError("Could not initialize COM.");
|
||||
goto end;
|
||||
}
|
||||
|
||||
::IFileOpenDialog *fileOpenDialog(NULL);
|
||||
|
||||
// Create dialog
|
||||
result = ::CoCreateInstance(::CLSID_FileOpenDialog, NULL,
|
||||
CLSCTX_ALL, ::IID_IFileOpenDialog,
|
||||
|
|
@ -616,3 +621,133 @@ nfdresult_t NFD_SaveDialog( const nfdchar_t *filterList,
|
|||
|
||||
return nfdResult;
|
||||
}
|
||||
|
||||
class AutoCoInit
|
||||
{
|
||||
public:
|
||||
AutoCoInit()
|
||||
{
|
||||
mResult = ::CoInitializeEx(NULL,
|
||||
::COINIT_APARTMENTTHREADED |
|
||||
::COINIT_DISABLE_OLE1DDE);
|
||||
}
|
||||
|
||||
~AutoCoInit()
|
||||
{
|
||||
if (SUCCEEDED(mResult))
|
||||
{
|
||||
::CoUninitialize();
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT Result() const { return mResult; }
|
||||
private:
|
||||
HRESULT mResult;
|
||||
};
|
||||
|
||||
// VS2010 hasn't got a copy of CComPtr - this was first added in the 2003 SDK, so we make our own small CComPtr instead
|
||||
template<class T>
|
||||
class ComPtr
|
||||
{
|
||||
public:
|
||||
ComPtr() : mPtr(NULL) { }
|
||||
~ComPtr()
|
||||
{
|
||||
if (mPtr)
|
||||
{
|
||||
mPtr->Release();
|
||||
}
|
||||
}
|
||||
|
||||
T* Ptr() const { return mPtr; }
|
||||
T** operator&() { return &mPtr; }
|
||||
T* operator->() const { return mPtr; }
|
||||
private:
|
||||
// Don't allow copy or assignment
|
||||
ComPtr(const ComPtr&);
|
||||
ComPtr& operator = (const ComPtr&) const;
|
||||
T* mPtr;
|
||||
};
|
||||
|
||||
nfdresult_t NFD_PickFolder(const nfdchar_t *defaultPath,
|
||||
nfdchar_t **outPath)
|
||||
{
|
||||
// Init COM
|
||||
AutoCoInit autoCoInit;
|
||||
if (!SUCCEEDED(autoCoInit.Result()))
|
||||
{
|
||||
NFDi_SetError("CoInitializeEx failed.");
|
||||
return NFD_ERROR;
|
||||
}
|
||||
|
||||
// Create the file dialog COM object
|
||||
ComPtr<IFileDialog> pFileDialog;
|
||||
if (!SUCCEEDED(CoCreateInstance(CLSID_FileOpenDialog,
|
||||
NULL,
|
||||
CLSCTX_ALL,
|
||||
IID_PPV_ARGS(&pFileDialog))))
|
||||
{
|
||||
NFDi_SetError("CoCreateInstance for CLSID_FileOpenDialog failed.");
|
||||
return NFD_ERROR;
|
||||
}
|
||||
|
||||
// Set the default path
|
||||
if (SetDefaultPath(pFileDialog.Ptr(), defaultPath) != NFD_OKAY)
|
||||
{
|
||||
NFDi_SetError("SetDefaultPath failed.");
|
||||
return NFD_ERROR;
|
||||
}
|
||||
|
||||
// Get the dialogs options
|
||||
DWORD dwOptions = 0;
|
||||
if (!SUCCEEDED(pFileDialog->GetOptions(&dwOptions)))
|
||||
{
|
||||
NFDi_SetError("GetOptions for IFileDialog failed.");
|
||||
return NFD_ERROR;
|
||||
}
|
||||
|
||||
// Add in FOS_PICKFOLDERS which hides files and only allows selection of folders
|
||||
if (!SUCCEEDED(pFileDialog->SetOptions(dwOptions | FOS_PICKFOLDERS)))
|
||||
{
|
||||
NFDi_SetError("SetOptions for IFileDialog failed.");
|
||||
return NFD_ERROR;
|
||||
}
|
||||
|
||||
// Show the dialog to the user
|
||||
const HRESULT result = pFileDialog->Show(NULL);
|
||||
if (result == HRESULT_FROM_WIN32(ERROR_CANCELLED))
|
||||
{
|
||||
return NFD_CANCEL;
|
||||
}
|
||||
else if (!SUCCEEDED(result))
|
||||
{
|
||||
NFDi_SetError("Show for IFileDialog failed.");
|
||||
return NFD_ERROR;
|
||||
}
|
||||
|
||||
// Get the shell item result
|
||||
ComPtr<IShellItem> pShellItem;
|
||||
if (!SUCCEEDED(pFileDialog->GetResult(&pShellItem)))
|
||||
{
|
||||
return NFD_OKAY;
|
||||
}
|
||||
|
||||
// Finally get the path
|
||||
wchar_t *path = NULL;
|
||||
if (!SUCCEEDED(pShellItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &path)))
|
||||
{
|
||||
NFDi_SetError("GetDisplayName for IShellItem failed.");
|
||||
return NFD_ERROR;
|
||||
}
|
||||
|
||||
// Convert string
|
||||
CopyWCharToNFDChar(path, outPath);
|
||||
CoTaskMemFree(path);
|
||||
if (!*outPath)
|
||||
{
|
||||
// error is malloc-based, error message would be redundant
|
||||
return NFD_ERROR;
|
||||
}
|
||||
|
||||
return NFD_OKAY;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue