Skip to content

Commit 7c37cc7

Browse files
authored
Chery-pick FileSavePicker.SuggestedFolder and official specs of Storage.Pickers to 1.8-stable (#5676)
* FileSavePicker.SuggestedFolder (#5669) * SuggestedFolder * update tests * Official API Review for Microsoft.Windows.Storage.Pickers (#5634) * create the files for official API review * add spec notes for official review * update doc * add details; graceful * update the specs * Resolve comments; Fix typos and grammer errors in doc. * FileSavePicker.SuggestedFolder * remove old specs
1 parent 659c7c4 commit 7c37cc7

18 files changed

+509
-802
lines changed

dev/Interop/StoragePickers/FileSavePicker.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,14 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
5757
{
5858
m_defaultFileExtension = value;
5959
}
60-
hstring FileSavePicker::SuggestedSaveFilePath()
60+
hstring FileSavePicker::SuggestedFolder()
6161
{
62-
return m_suggestedSaveFilePath;
62+
return m_suggestedFolder;
6363
}
64-
void FileSavePicker::SuggestedSaveFilePath(hstring const& value)
64+
void FileSavePicker::SuggestedFolder(hstring const& value)
6565
{
66-
PickerCommon::ValidateSuggestedSaveFilePath(value);
67-
m_suggestedSaveFilePath = value;
66+
PickerCommon::ValidateSuggestedFolder(value);
67+
m_suggestedFolder = value;
6868
}
6969

7070
hstring FileSavePicker::SuggestedFileName()
@@ -84,7 +84,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
8484
parameters.CommitButtonText = m_commitButtonText;
8585
parameters.PickerLocationId = m_suggestedStartLocation;
8686
parameters.SuggestedFileName = m_suggestedFileName;
87-
parameters.SuggestedSaveFilePath = m_suggestedSaveFilePath;
87+
parameters.SuggestedFolder = m_suggestedFolder;
8888
parameters.CaptureFilterSpec(m_fileTypeChoices.GetView());
8989
}
9090

@@ -101,7 +101,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
101101
CaptureParameters(parameters);
102102

103103
auto defaultFileExtension = m_defaultFileExtension;
104-
auto suggestedSaveFilePath = m_suggestedSaveFilePath;
104+
auto suggestedFolder = m_suggestedFolder;
105105
auto suggestedFileName = m_suggestedFileName;
106106
auto fileTypeChoices = m_fileTypeChoices;
107107

dev/Interop/StoragePickers/FileSavePicker.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
2626
hstring DefaultFileExtension();
2727
void DefaultFileExtension(hstring const& value);
2828

29-
hstring SuggestedSaveFilePath();
30-
void SuggestedSaveFilePath(hstring const& value);
29+
hstring SuggestedFolder();
30+
void SuggestedFolder(hstring const& value);
3131

3232
hstring SuggestedFileName();
3333
void SuggestedFileName(hstring const& value);
@@ -40,7 +40,7 @@ namespace winrt::Microsoft::Windows::Storage::Pickers::implementation
4040
hstring m_commitButtonText{};
4141
winrt::Windows::Foundation::Collections::IMap<hstring, winrt::Windows::Foundation::Collections::IVector<hstring>> m_fileTypeChoices{ make<FileTypeChoicesMap>() };
4242
hstring m_defaultFileExtension{};
43-
hstring m_suggestedSaveFilePath{};
43+
hstring m_suggestedFolder{};
4444
hstring m_suggestedFileName{};
4545
StoragePickersTelemetryHelper m_telemetryHelper{};
4646

dev/Interop/StoragePickers/Microsoft.Windows.Storage.Pickers.idl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ namespace Microsoft.Windows.Storage.Pickers
5757
Windows.Foundation.Collections.IMap<String, Windows.Foundation.Collections.IVector<String> > FileTypeChoices{ get; };
5858
String DefaultFileExtension;
5959
String SuggestedFileName;
60+
String SuggestedFolder;
6061

6162
[remote_sync] Windows.Foundation.IAsyncOperation<PickFileResult> PickSaveFileAsync();
6263
}

dev/Interop/StoragePickers/PickerCommon.cpp

Lines changed: 18 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -113,32 +113,27 @@ namespace PickerCommon {
113113
return winrt::hstring{ filePath.get() };
114114
}
115115

116-
std::pair<winrt::com_ptr<IShellItem>, std::wstring> ParseFolderItemAndFileName(winrt::hstring const& filePath)
116+
winrt::com_ptr<IShellItem> TryParseFolderItem(winrt::hstring const& folderPathStr)
117117
{
118-
std::filesystem::path path(filePath.c_str());
119-
if (path.empty())
118+
std::filesystem::path folderPath(folderPathStr.c_str());
119+
if (folderPath.empty())
120120
{
121-
return { nullptr, L"" };
121+
return nullptr;
122122
}
123123

124-
auto fileName = path.filename().wstring();
125-
126-
// If the parent folder does not exist or is not a directory, we cannot set folder.
127-
auto folderPath = path.parent_path();
128124
if (!std::filesystem::exists(folderPath) || !std::filesystem::is_directory(folderPath))
129125
{
130-
return { nullptr, fileName };
126+
return nullptr;
131127
}
132128

133129
winrt::com_ptr<IShellItem> shellItem;
134130
HRESULT hr = SHCreateItemFromParsingName(folderPath.c_str(), nullptr, IID_PPV_ARGS(shellItem.put()));
135131
if (SUCCEEDED(hr))
136132
{
137-
return { shellItem, fileName };
133+
return shellItem;
138134
}
139135

140-
// If the we cannot set the folder, we can at least set the file name suggested by developer.
141-
return { nullptr, fileName};
136+
return nullptr;
142137
}
143138

144139
void ValidateViewMode(winrt::Microsoft::Windows::Storage::Pickers::PickerViewMode const& value)
@@ -229,7 +224,7 @@ namespace PickerCommon {
229224
ValidateStringNoEmbeddedNulls(suggestedFileName);
230225
}
231226

232-
void ValidateSuggestedSaveFilePath(winrt::hstring const& path)
227+
void ValidateSuggestedFolder(winrt::hstring const& path)
233228
{
234229
if (path.empty())
235230
{
@@ -239,25 +234,16 @@ namespace PickerCommon {
239234

240235
ValidateStringNoEmbeddedNulls(path);
241236

242-
wil::unique_cotaskmem_ptr<ITEMIDLIST> pidl(SHSimpleIDListFromPath(path.c_str()));
243-
if (!pidl)
244-
{
245-
throw std::invalid_argument("SuggestedSaveFilePath");
246-
}
247-
248-
std::filesystem::path p(path.c_str());
249-
auto folderPath = p.parent_path();
250-
if (folderPath.empty())
237+
auto pathObj = std::filesystem::path(path.c_str());
238+
if (!pathObj.is_absolute())
251239
{
252-
// If the path does not have a parent, we cannot set folder.
253-
throw std::invalid_argument("SuggestedSaveFilePath");
240+
throw std::invalid_argument("SuggestedFolder");
254241
}
255242

256-
auto fileName = p.filename().wstring();
257-
if (fileName.size() > MAX_PATH)
243+
wil::unique_cotaskmem_ptr<ITEMIDLIST> pidl(SHSimpleIDListFromPath(path.c_str()));
244+
if (!pidl)
258245
{
259-
throw winrt::hresult_invalid_argument(
260-
PickerLocalization::GetStoragePickersLocalizationText(MaxSaveFileLengthExceededLocalizationKey));
246+
throw std::invalid_argument("SuggestedFolder");
261247
}
262248
}
263249

@@ -404,28 +390,18 @@ namespace PickerCommon {
404390
/// <param name="dialog"></param>
405391
void PickerParameters::ConfigureFileSaveDialog(winrt::com_ptr<IFileSaveDialog> dialog)
406392
{
407-
winrt::hstring fileNameToSet;
408393
if (!IsHStringNullOrEmpty(SuggestedFileName))
409394
{
410-
fileNameToSet = SuggestedFileName;
395+
check_hresult(dialog->SetFileName(SuggestedFileName.c_str()));
411396
}
412-
413-
if (!PickerCommon::IsHStringNullOrEmpty(SuggestedSaveFilePath))
397+
398+
if (!PickerCommon::IsHStringNullOrEmpty(SuggestedFolder))
414399
{
415-
auto result = ParseFolderItemAndFileName(SuggestedSaveFilePath);
416-
winrt::com_ptr<IShellItem> folderItem = result.first;
417-
fileNameToSet = result.second;
400+
winrt::com_ptr<IShellItem> folderItem = TryParseFolderItem(SuggestedFolder);
418401
if (folderItem)
419402
{
420403
check_hresult(dialog->SetFolder(folderItem.get()));
421404
}
422405
}
423-
424-
// Set the filename (either from SuggestedSaveFilePath or SuggestedFileName)
425-
if (!PickerCommon::IsHStringNullOrEmpty(fileNameToSet))
426-
{
427-
check_hresult(dialog->SetFileName(fileNameToSet.c_str()));
428-
}
429-
430406
}
431407
}

dev/Interop/StoragePickers/PickerCommon.h

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace PickerCommon {
1313
winrt::hstring GetPathFromShellItem(winrt::com_ptr<IShellItem> shellItem);
14+
winrt::com_ptr<IShellItem> TryParseFolderItem(winrt::hstring const& folderPathStr);
1415
const winrt::hstring AllFilesLocalizationKey = L"Microsoft.WindowsAppRuntime/StoragePickers/All Files";
1516

1617
const winrt::hstring InvalidViewModeLocalizationKey{ L"Microsoft.WindowsAppRuntime/StoragePickers/IDS_APIERROR_INVALIDVIEWMODEVALUE"};
@@ -20,15 +21,12 @@ namespace PickerCommon {
2021
const winrt::hstring MaxSaveFileLengthExceededLocalizationKey{L"Microsoft.WindowsAppRuntime/StoragePickers/IDS_APIERROR_MAXSAVEFILELENGTHEXCEEDED"};
2122

2223
bool IsHStringNullOrEmpty(winrt::hstring value);
23-
24-
std::pair<winrt::com_ptr<IShellItem>, std::wstring> ParseFolderItemAndFileName(winrt::hstring const& filePath);
25-
2624
void ValidateStringNoEmbeddedNulls(winrt::hstring const& value);
2725
void ValidateViewMode(winrt::Microsoft::Windows::Storage::Pickers::PickerViewMode const& value);
2826
void ValidateSuggestedStartLocation(winrt::Microsoft::Windows::Storage::Pickers::PickerLocationId const& value);
2927
void ValidateSingleFileTypeFilterElement(winrt::hstring const& filter);
3028
void ValidateSuggestedFileName(winrt::hstring const& suggestedFileName);
31-
void ValidateSuggestedSaveFilePath(winrt::hstring const& path);
29+
void ValidateSuggestedFolder(winrt::hstring const& path);
3230

3331
struct PickerParameters {
3432
HWND HWnd{};
@@ -39,7 +37,7 @@ namespace PickerCommon {
3937
winrt::hstring AllFilesText{ L"All Files" }; // initialize to All Files as a default value, will be updated by localization
4038

4139
winrt::hstring SuggestedFileName;
42-
winrt::hstring SuggestedSaveFilePath;
40+
winrt::hstring SuggestedFolder;
4341

4442
winrt::hstring FormatExtensionWithWildcard(winrt::hstring extension);
4543
winrt::hstring JoinExtensions(winrt::Windows::Foundation::Collections::IVectorView<winrt::hstring> extensions);

specs/StoragePickers/FileOpenPicker.md renamed to specs/Storage.Pickers/FileOpenPicker.md

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ runtimeclass FileOpenPicker
1919
FileOpenPicker(Microsoft.UI.WindowId windowId);
2020

2121
string CommitButtonText;
22-
string SettingsIdentifier;
2322
IVector<string> FileTypeFilter{ get; };
2423
PickerLocationId SuggestedStartLocation;
2524
PickerViewMode ViewMode;
@@ -39,15 +38,20 @@ using Microsoft.Windows.Storage.Pickers;
3938

4039
var openPicker = new FileOpenPicker(this.AppWindow.Id)
4140
{
42-
// (Optional) specify the initial location.
43-
// If not specified, using PickerLocationId.Unspecified by default.
41+
// (Optional) Specify the initial location for the picker.
42+
// If the specified location doesn't exist on the user's machine, it falls back to the DocumentsLibrary.
43+
// If not set, it defaults to PickerLocationId.Unspecified, and the system will use its default location.
4444
SuggestedStartLocation = PickerLocationId.DocumentsLibrary,
4545

46-
// (Optional) specify the text displayed on commit button. If not specified, use system default.
46+
// (Optional) specify the text displayed on the commit button.
47+
// If not specified, the system uses a default label of "Open" (suitably translated).
4748
CommitButtonText = "Choose selected files",
4849

49-
// (Optional) specify file extensions filters. If not specified, default to all (*.*)
50+
// (Optional) specify file extension filters. If not specified, defaults to all files (*.*).
5051
FileTypeFilter = { ".txt", ".pdf", ".doc", ".docx" },
52+
53+
// (Optional) specify the view mode of the picker dialog. If not specified, defaults to List.
54+
ViewMode = PickerViewMode.List,
5155
};
5256
```
5357

@@ -59,27 +63,29 @@ using namespace winrt::Microsoft::Windows::Storage::Pickers;
5963

6064
FileOpenPicker openPicker(AppWindow().Id());
6165

62-
// (Optional) specify the initial location.
63-
// If not specified, using PickerLocationId.Unspecified by default.
66+
// (Optional) Specify the initial location for the picker.
67+
// If the specified location doesn't exist on the user's machine, it falls back to the DocumentsLibrary.
68+
// If not set, it defaults to PickerLocationId.Unspecified, and the system will use its default location.
6469
openPicker.SuggestedStartLocation(PickerLocationId::DocumentsLibrary);
6570

66-
// (Optional) specify the text displayed on commit button. If not specified, use system default.
71+
// (Optional) specify the text displayed on the commit button.
72+
// If not specified, the system uses a default label of "Open" (suitably translated).
6773
openPicker.CommitButtonText(L"Choose selected files");
6874

69-
// (Optional) specify file extensions filters. If not specified, default to all (*.*)
70-
openPicker.FileTypeFilter().Append(L".txt");
71-
openPicker.FileTypeFilter().Append(L".pdf");
72-
openPicker.FileTypeFilter().Append(L".doc");
73-
openPicker.FileTypeFilter().Append(L".docx");
75+
// (Optional) specify file extension filters. If not specified, defaults to all files (*.*).
76+
openPicker.FileTypeFilter().ReplaceAll({ L".txt", L".pdf", L".doc", L".docx" });
77+
78+
// (Optional) specify the view mode of the picker dialog. If not specified, defaults to List.
79+
openPicker.ViewMode(PickerViewMode::List);
7480
```
7581
7682
## FileOpenPicker.PickSingleFileAsync
7783
78-
Displays a UI element that allows user to choose and open one file.
84+
Displays a UI element that allows the user to choose and open one file.
7985
80-
Returns a light weight object that has the path of the picked file.
86+
Returns a lightweight object that has the path of the picked file.
8187
82-
Return null if the file dialog was cancelled or closed without selection.
88+
Returns `null` if the file dialog was cancelled or closed without a selection.
8389
8490
### Examples
8591
@@ -109,11 +115,11 @@ C++
109115
using namespace winrt::Microsoft::Windows::Storage::Pickers;
110116

111117
FileOpenPicker openPicker(AppWindow().Id());
112-
auto& result{ co_await openPicker.PickSingleFileAsync() };
118+
auto result{ co_await openPicker.PickSingleFileAsync() };
113119
if (result)
114120
{
115121
std::ifstream fileReader(result.Path().c_str());
116-
std::string text((std::istreambuf_iterator<char>(fileReader)), std::istreambuf_iterator<char>());
122+
std::string text(std::istreambuf_iterator(fileReader), {});
117123
winrt::hstring hText = winrt::to_hstring(text);
118124
}
119125
else
@@ -124,11 +130,11 @@ else
124130

125131
## FileOpenPicker.PickMultipleFilesAsync
126132

127-
Displays a UI element that allows user to choose and open multiple files.
133+
Displays a UI element that allows the user to choose and open multiple files.
128134

129-
Returns a collection of light weight objects that has the path of picked files.
135+
Returns a collection of lightweight objects that have the path of the picked files.
130136

131-
Return an empty list (Count = 0) if the file dialog's cancelled or closed without selection.
137+
Returns an empty list (`Count` = 0) if the file dialog was cancelled or closed without a selection.
132138

133139
### Examples
134140

@@ -162,7 +168,7 @@ C++
162168
using namespace winrt::Microsoft::Windows::Storage::Pickers;
163169

164170
FileOpenPicker openPicker(AppWindow().Id());
165-
auto& results{ co_await openPicker.PickMultipleFilesAsync() };
171+
auto results{ co_await openPicker.PickMultipleFilesAsync() };
166172
if (results.Size() > 0)
167173
{
168174
for (auto const& result : results)

0 commit comments

Comments
 (0)