From 6cb2ece285a6a9ccd6f6244043a240f653165b7b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 18 Sep 2013 21:42:14 +0800 Subject: [PATCH] win: Make common part of ShowSaveDialog a independet class. --- browser/ui/file_dialog_win.cc | 126 ++++++++++++++++++++++++------------------ 1 file changed, 72 insertions(+), 54 deletions(-) diff --git a/browser/ui/file_dialog_win.cc b/browser/ui/file_dialog_win.cc index d319db0..8be4f76 100644 --- a/browser/ui/file_dialog_win.cc +++ b/browser/ui/file_dialog_win.cc @@ -124,6 +124,69 @@ void FormatFilterForExtensions( } } +// Generic class to delegate common open/save dialog's behaviours, users need to +// call interface methods via GetPtr(). +template +class FileDialog { + public: + FileDialog(const base::FilePath& default_path, + const std::string title, + const std::vector& file_ext, + const std::vector& desc_ext) + : file_ext_(file_ext), + desc_ext_(desc_ext) { + std::vector filters; + FormatFilterForExtensions(file_ext_, true, &desc_ext_, &filters); + + std::wstring file_part; + if (!IsDirectory(default_path)) + file_part = default_path.BaseName().value(); + + dialog_.reset(new T( + file_part.c_str(), + FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT, + NULL, + filters.data(), + filters.size())); + + if (!title.empty()) + GetPtr()->SetTitle(UTF8ToUTF16(title).c_str()); + + SetDefaultFolder(default_path); + } + + bool Show(atom::NativeWindow* window) { + return dialog_->DoModal(window->GetNativeWindow()) == IDOK; + } + + T* GetDialog() { return dialog_.get(); } + + IFileDialog* GetPtr() const { return dialog_->GetPtr(); } + + private: + // Set up the initial directory for the dialog. + void SetDefaultFolder(const base::FilePath file_path) { + std::wstring directory = IsDirectory(file_path) ? + file_path.value() : + file_path.DirName().value(); + + ATL::CComPtr folder_item; + HRESULT hr = SHCreateItemFromParsingName(directory.c_str(), + NULL, + IID_PPV_ARGS(&folder_item)); + if (SUCCEEDED(hr)) + GetPtr()->SetDefaultFolder(folder_item); + } + + scoped_ptr dialog_; + + std::vector file_ext_; + std::vector desc_ext_; + std::vector filters_; + + DISALLOW_COPY_AND_ASSIGN(FileDialog); +}; + } // namespace bool ShowOpenDialog(const std::string& title, @@ -137,67 +200,22 @@ bool ShowSaveDialog(atom::NativeWindow* window, const std::string& title, const base::FilePath& default_path, base::FilePath* path) { - HRESULT hr; - - std::vector file_ext; - std::vector desc_ext; - std::vector filters; - // TODO(zcbenz): Accept custom filters from caller. + std::vector file_ext; std::wstring extension = default_path.Extension(); if (!extension.empty()) file_ext.push_back(extension.insert(0, L"*")); - desc_ext.reserve(file_ext.size() + 1); - FormatFilterForExtensions(file_ext, true, &desc_ext, &filters); - - std::wstring file_part = default_path.BaseName().value(); - // If the default_path is a root directory, file_part will be '\', and the - // call to GetSaveFileName below will fail. - if (file_part.size() == 1 && file_part[0] == L'\\') - file_part.clear(); - - // The size of the in/out buffer in number of characters we pass to win32 - // GetSaveFileName. From MSDN "The buffer must be large enough to store the - // path and file name string or strings, including the terminating NULL - // character. ... The buffer should be at least 256 characters long.". - // _IsValidPathComDlg does a copy expecting at most MAX_PATH, otherwise will - // result in an error of FNERR_INVALIDFILENAME. So we should only pass the - // API a buffer of at most MAX_PATH. - wchar_t file_name[MAX_PATH]; - base::wcslcpy(file_name, file_part.c_str(), arraysize(file_name)); - - CShellFileSaveDialog save_dialog( - file_name, - FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT, - NULL, - filters.data(), - filters.size()); - // Set dialog's title if specified. - if (!title.empty()) - save_dialog.GetPtr()->SetTitle(UTF8ToUTF16(title).c_str()); - - // Set up the initial directory for the dialog. - std::wstring directory; - if (IsDirectory(default_path)) { - directory = default_path.value(); - file_part.clear(); - } else { - directory = default_path.DirName().value(); - } - - ATL::CComPtr folder_item; - hr = SHCreateItemFromParsingName(directory.c_str(), - NULL, - IID_PPV_ARGS(&folder_item)); - if (SUCCEEDED(hr)) - save_dialog.GetPtr()->SetDefaultFolder(folder_item); - - // Show the save as dialog. - if (save_dialog.DoModal(window->GetNativeWindow()) == IDCANCEL) + FileDialog save_dialog( + default_path, + title, + file_ext, + std::vector()); + if (!save_dialog.Show(window)) return false; - hr = save_dialog.GetFilePath(file_name, MAX_PATH); + wchar_t file_name[MAX_PATH]; + HRESULT hr = save_dialog.GetDialog()->GetFilePath(file_name, MAX_PATH); if (FAILED(hr)) return false; -- 2.7.4