/* * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ #include "common.h" #include #include "CommonDialogs_COM.h" #include "com_sun_glass_ui_CommonDialogs_Type.h" /***************************** * IFileDialog implementation *****************************/ _COM_SMARTPTR_TYPEDEF(IFileDialog, __uuidof(IFileDialog)); _COM_SMARTPTR_TYPEDEF(IFileOpenDialog, __uuidof(IFileOpenDialog)); _COM_SMARTPTR_TYPEDEF(IShellItem, __uuidof(IShellItem)); _COM_SMARTPTR_TYPEDEF(IShellItemArray, __uuidof(IShellItemArray)); #if (_WIN32_IE < _WIN32_IE_IE70) SHSTDAPI SHCreateItemFromParsingName(__in PCWSTR pszPath, __in_opt IBindCtx *pbc, __in REFIID riid, __deref_out void **ppv); #endif // (_WIN32_IE < _WIN32_IE_IE70) const HRESULT CANCEL_HRT = HRESULT_FROM_WIN32(ERROR_CANCELLED); jstring CreateJString(JNIEnv *env, IShellItemPtr pFile) { LPWSTR path = NULL; jstring ret = NULL; OLE_TRY OLE_HRT( pFile->GetDisplayName(SIGDN_FILESYSPATH, &path) ); OLE_CATCH ret = CreateJString(env, path); CoTaskMemFree(path); return ret; } wchar_t *GetDescription(JNIEnv *env, jobject jFilter) { JLString jDesc(env, (jstring)env->CallObjectMethod(jFilter, javaIDs.CommonDialogs.ExtensionFilter.getDescription)); CheckAndClearException(env); JString desc(env, jDesc, false); return desc; } wchar_t *GetExtensions(JNIEnv *env, jobject jFilter) { JLObjectArray jExts(env, (jobjectArray)env->CallObjectMethod(jFilter, javaIDs.CommonDialogs.ExtensionFilter.extensionsToArray)); CheckAndClearException(env); jsize size = env->GetArrayLength(jExts); BOOL isHeading = TRUE; // extension without semicolon JLString jExt(env, CreateJString(env, _T(""))); JLString semicolon(env, CreateJString(env, _T(";"))); for (int j = 0; j < size; j++) { if (!isHeading) { jExt.Attach( ConcatJStrings(env, jExt, semicolon) ); } isHeading = FALSE; JLString jExtension(env, (jstring)env->GetObjectArrayElement(jExts, j)); jExt.Attach( ConcatJStrings(env, jExt, jExtension) ); } JString ext(env, jExt, false); return ext; } void SetFilters(IFileDialogPtr pDialog, jobjectArray jFilters, jint defaultFilterIndex) { JNIEnv *env = GetEnv(); jsize size = env->GetArrayLength(jFilters); COMDLG_FILTERSPEC *filterSpec = new COMDLG_FILTERSPEC[size]; for (int i = 0; i < size; i++) { JLObject jFilter(env, env->GetObjectArrayElement(jFilters, i)); COMDLG_FILTERSPEC c = {GetDescription(env, jFilter), GetExtensions(env, jFilter)}; filterSpec[i] = c; } OLE_TRY OLE_HRT( pDialog->SetDefaultExtension(L"") ); OLE_HRT( pDialog->SetFileTypes(size, filterSpec) ); if (size > 0) { OLE_HRT( pDialog->SetFileTypeIndex(defaultFilterIndex + 1) ); // 1-based index required } OLE_CATCH for (int i = 0; i < size; i++) { if (filterSpec[i].pszName) { delete[] filterSpec[i].pszName; } if (filterSpec[i].pszSpec) { delete[] filterSpec[i].pszSpec; } } delete[] filterSpec; } jobjectArray GetFiles(IFileDialogPtr pDialog, BOOL isCancelled, jint type) { JNIEnv* env = GetEnv(); jclass jc = env->FindClass("java/lang/String"); if (CheckAndClearException(env)) return NULL; JLClass cls(env, jc); jobjectArray ret = NULL; if (isCancelled) { ret = env->NewObjectArray(0, cls, NULL); if (CheckAndClearException(env)) return NULL; return ret; } OLE_TRY if (type == com_sun_glass_ui_CommonDialogs_Type_SAVE) { ret = env->NewObjectArray(1, cls, NULL); if (CheckAndClearException(env)) return NULL; IShellItemPtr pFile; OLE_HRT( pDialog->GetResult(&pFile) ); OLE_CHECK_NOTNULLSP(pFile) env->SetObjectArrayElement(ret, 0, jstring(JLString(env, CreateJString(env, pFile)))); CheckAndClearException(env); return ret; } IFileOpenDialogPtr pOpenDialog(pDialog); OLE_CHECK_NOTNULLSP(pOpenDialog) IShellItemArrayPtr pFiles; OLE_HRT( pOpenDialog->GetResults(&pFiles) ); OLE_CHECK_NOTNULLSP(pFiles) DWORD count = 0; OLE_HRT( pFiles->GetCount(&count) ); ret = env->NewObjectArray(count, cls, NULL); if (CheckAndClearException(env)) return NULL; for (DWORD i = 0; i < count; i++) { IShellItemPtr pFile; OLE_HRT( pFiles->GetItemAt(i, &pFile) ); OLE_CHECK_NOTNULLSP(pFile) env->SetObjectArrayElement(ret, i, jstring(JLString(env, CreateJString(env, pFile)))); CheckAndClearException(env); } OLE_CATCH return ret; } jobject COMFileChooser_Show(HWND owner, LPCTSTR folder, LPCTSTR filename, LPCTSTR title, jint type, jboolean multipleMode, jobjectArray jFilters, jint defaultFilterIndex) { OLEHolder _ole_; IFileDialogPtr pDialog; OLE_TRY switch(type) { case com_sun_glass_ui_CommonDialogs_Type_OPEN: OLE_HRT( ::CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL, IID_IFileOpenDialog, (void**)&pDialog) ); if (multipleMode == TRUE) { DWORD dwOptions = 0; OLE_HRT( pDialog->GetOptions(&dwOptions) ); dwOptions |= FOS_ALLOWMULTISELECT; OLE_HRT( pDialog->SetOptions(dwOptions) ); } break; case com_sun_glass_ui_CommonDialogs_Type_SAVE: OLE_HRT( ::CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_ALL, IID_IFileSaveDialog, (void**)&pDialog) ); break; } if (folder) { IShellItemPtr pItem; OLE_HRT( SHCreateItemFromParsingName((PCWSTR)folder, NULL, IID_IShellItem, (void **)&pItem) ); if (pItem) { OLE_HRT( pDialog->SetFolder( pItem ) ); } } if (type == com_sun_glass_ui_CommonDialogs_Type_SAVE && filename && *filename) { OLE_HRT( pDialog->SetFileName(filename); ); } if (title) { OLE_HRT( pDialog->SetTitle(title) ); } if (jFilters != NULL) { SetFilters(pDialog, jFilters, defaultFilterIndex); } OLE_HR = pDialog->Show(owner); if (OLE_HR != CANCEL_HRT && FAILED(OLE_HR)) { OLE_THROW_LASTERROR(_T("pDialog->Show(NULL)")) } OLE_CATCH jobjectArray ret = GetFiles(pDialog, OLE_HR == CANCEL_HRT, type); UINT index = 0; pDialog->GetFileTypeIndex(&index); JNIEnv* env = GetEnv(); jclass jc = env->FindClass("com/sun/glass/ui/CommonDialogs"); if (CheckAndClearException(env)) return NULL; JLClass cls(env, jc); jobject jobj = env->CallStaticObjectMethod(cls, javaIDs.CommonDialogs.createFileChooserResult, ret, jFilters, (jint)(index - 1)); if (CheckAndClearException(env)) return NULL; return jobj; } /***************************** * IFileDialog implementation *****************************/ jstring GetFolder(IFileDialogPtr pDialog, BOOL isCancelled) { if (isCancelled) { return NULL; } JNIEnv* env = GetEnv(); IShellItemPtr pFile; OLE_TRY OLE_HRT( pDialog->GetResult(&pFile) ); OLE_CATCH return CreateJString(env, pFile); } jstring COMFolderChooser_Show(HWND owner, LPCTSTR folder, LPCTSTR title) { OLEHolder _ole_; IFileDialogPtr pDialog; OLE_TRY OLE_HRT( ::CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_ALL, IID_IFileOpenDialog, (void**)&pDialog) ); DWORD dwOptions = 0; OLE_HRT( pDialog->GetOptions(&dwOptions) ); dwOptions |= FOS_PICKFOLDERS | FOS_FORCEFILESYSTEM; OLE_HRT( pDialog->SetOptions(dwOptions) ); if (folder) { IShellItemPtr pItem; OLE_HRT( SHCreateItemFromParsingName((PCWSTR)folder, NULL, IID_IShellItem, (void **)&pItem) ); if (pItem) { OLE_HRT( pDialog->SetFolder( pItem ) ); } } if (title) { OLE_HRT( pDialog->SetTitle(title) ); } OLE_HR = pDialog->Show(owner); if (OLE_HR != CANCEL_HRT && FAILED(OLE_HR)) { OLE_THROW_LASTERROR(_T("pDialog->Show(NULL)")) } OLE_CATCH return GetFolder(pDialog, OLE_HR == CANCEL_HRT); }