Merge pull request #8623 from electron/dialog-options-helper
Add DialogSettings helper
This commit is contained in:
		
				commit
				
					
						c3f3a6f133
					
				
			
		
					 9 changed files with 151 additions and 235 deletions
				
			
		|  | @ -35,6 +35,24 @@ struct Converter<file_dialog::Filter> { | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | template<> | ||||||
|  | struct Converter<file_dialog::DialogSettings> { | ||||||
|  |   static bool FromV8(v8::Isolate* isolate, | ||||||
|  |                      v8::Local<v8::Value> val, | ||||||
|  |                      file_dialog::DialogSettings* out) { | ||||||
|  |     mate::Dictionary dict; | ||||||
|  |     if (!ConvertFromV8(isolate, val, &dict)) | ||||||
|  |       return false; | ||||||
|  |     dict.Get("window", &(out->parent_window)); | ||||||
|  |     dict.Get("title", &(out->title)); | ||||||
|  |     dict.Get("buttonLabel", &(out->button_label)); | ||||||
|  |     dict.Get("defaultPath", &(out->default_path)); | ||||||
|  |     dict.Get("filters", &(out->filters)); | ||||||
|  |     dict.Get("properties", &(out->properties)); | ||||||
|  |     return true; | ||||||
|  |   } | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| }  // namespace mate
 | }  // namespace mate
 | ||||||
| 
 | 
 | ||||||
| namespace { | namespace { | ||||||
|  | @ -68,45 +86,32 @@ void ShowMessageBox(int type, | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ShowOpenDialog(const std::string& title, | void ShowOpenDialog(const file_dialog::DialogSettings& settings, | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const file_dialog::Filters& filters, |  | ||||||
|                     int properties, |  | ||||||
|                     atom::NativeWindow* window, |  | ||||||
|                     mate::Arguments* args) { |                     mate::Arguments* args) { | ||||||
|   v8::Local<v8::Value> peek = args->PeekNext(); |   v8::Local<v8::Value> peek = args->PeekNext(); | ||||||
|   file_dialog::OpenDialogCallback callback; |   file_dialog::OpenDialogCallback callback; | ||||||
|   if (mate::Converter<file_dialog::OpenDialogCallback>::FromV8(args->isolate(), |   if (mate::Converter<file_dialog::OpenDialogCallback>::FromV8(args->isolate(), | ||||||
|                                                                peek, |                                                                peek, | ||||||
|                                                                &callback)) { |                                                                &callback)) { | ||||||
|     file_dialog::ShowOpenDialog(window, title, button_label, default_path, |     file_dialog::ShowOpenDialog(settings, callback); | ||||||
|                                 filters, properties, callback); |  | ||||||
|   } else { |   } else { | ||||||
|     std::vector<base::FilePath> paths; |     std::vector<base::FilePath> paths; | ||||||
|     if (file_dialog::ShowOpenDialog(window, title, button_label, default_path, |     if (file_dialog::ShowOpenDialog(settings, &paths)) | ||||||
|                                     filters, properties, &paths)) |  | ||||||
|       args->Return(paths); |       args->Return(paths); | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ShowSaveDialog(const std::string& title, | void ShowSaveDialog(const file_dialog::DialogSettings& settings, | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const file_dialog::Filters& filters, |  | ||||||
|                     atom::NativeWindow* window, |  | ||||||
|                     mate::Arguments* args) { |                     mate::Arguments* args) { | ||||||
|   v8::Local<v8::Value> peek = args->PeekNext(); |   v8::Local<v8::Value> peek = args->PeekNext(); | ||||||
|   file_dialog::SaveDialogCallback callback; |   file_dialog::SaveDialogCallback callback; | ||||||
|   if (mate::Converter<file_dialog::SaveDialogCallback>::FromV8(args->isolate(), |   if (mate::Converter<file_dialog::SaveDialogCallback>::FromV8(args->isolate(), | ||||||
|                                                                peek, |                                                                peek, | ||||||
|                                                                &callback)) { |                                                                &callback)) { | ||||||
|     file_dialog::ShowSaveDialog(window, title, button_label, default_path, |     file_dialog::ShowSaveDialog(settings, callback); | ||||||
|                                 filters, callback); |  | ||||||
|   } else { |   } else { | ||||||
|     base::FilePath path; |     base::FilePath path; | ||||||
|     if (file_dialog::ShowSaveDialog(window, title, button_label, default_path, |     if (file_dialog::ShowSaveDialog(settings, &path)) | ||||||
|                                     filters, &path)) |  | ||||||
|       args->Return(path); |       args->Return(path); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -90,10 +90,11 @@ void AtomDownloadManagerDelegate::OnDownloadPathGenerated( | ||||||
|   base::FilePath path; |   base::FilePath path; | ||||||
|   GetItemSavePath(item, &path); |   GetItemSavePath(item, &path); | ||||||
|   // Show save dialog if save path was not set already on item
 |   // Show save dialog if save path was not set already on item
 | ||||||
|   if (path.empty() && file_dialog::ShowSaveDialog(window, item->GetURL().spec(), |   file_dialog::DialogSettings settings; | ||||||
|                                                   "", default_path, |   settings.parent_window = window; | ||||||
|                                                   file_dialog::Filters(), |   settings.title = item->GetURL().spec(); | ||||||
|                                                   &path)) { |   settings.default_path = default_path; | ||||||
|  |   if (path.empty() && file_dialog::ShowSaveDialog(settings, &path)) { | ||||||
|     // Remember the last selected download directory.
 |     // Remember the last selected download directory.
 | ||||||
|     AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>( |     AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>( | ||||||
|         download_manager_->GetBrowserContext()); |         download_manager_->GetBrowserContext()); | ||||||
|  |  | ||||||
|  | @ -294,10 +294,11 @@ void CommonWebContentsDelegate::DevToolsSaveToFile( | ||||||
|   if (it != saved_files_.end() && !save_as) { |   if (it != saved_files_.end() && !save_as) { | ||||||
|     path = it->second; |     path = it->second; | ||||||
|   } else { |   } else { | ||||||
|     file_dialog::Filters filters; |     file_dialog::DialogSettings settings; | ||||||
|     base::FilePath default_path(base::FilePath::FromUTF8Unsafe(url)); |     settings.parent_window = owner_window(); | ||||||
|     if (!file_dialog::ShowSaveDialog(owner_window(), url, "", default_path, |     settings.title = url; | ||||||
|                                      filters, &path)) { |     settings.default_path = base::FilePath::FromUTF8Unsafe(url); | ||||||
|  |     if (!file_dialog::ShowSaveDialog(settings, &path)) { | ||||||
|       base::StringValue url_value(url); |       base::StringValue url_value(url); | ||||||
|       web_contents_->CallClientFunction( |       web_contents_->CallClientFunction( | ||||||
|           "DevToolsAPI.canceledSaveURL", &url_value, nullptr, nullptr); |           "DevToolsAPI.canceledSaveURL", &url_value, nullptr, nullptr); | ||||||
|  | @ -358,12 +359,11 @@ void CommonWebContentsDelegate::DevToolsAddFileSystem( | ||||||
|     const base::FilePath& file_system_path) { |     const base::FilePath& file_system_path) { | ||||||
|   base::FilePath path = file_system_path; |   base::FilePath path = file_system_path; | ||||||
|   if (path.empty()) { |   if (path.empty()) { | ||||||
|     file_dialog::Filters filters; |  | ||||||
|     base::FilePath default_path; |  | ||||||
|     std::vector<base::FilePath> paths; |     std::vector<base::FilePath> paths; | ||||||
|     int flag = file_dialog::FILE_DIALOG_OPEN_DIRECTORY; |     file_dialog::DialogSettings settings; | ||||||
|     if (!file_dialog::ShowOpenDialog(owner_window(), "", "", default_path, |     settings.parent_window = owner_window(); | ||||||
|                                      filters, flag, &paths)) |     settings.properties = file_dialog::FILE_DIALOG_OPEN_DIRECTORY; | ||||||
|  |     if (!file_dialog::ShowOpenDialog(settings, &paths)) | ||||||
|       return; |       return; | ||||||
| 
 | 
 | ||||||
|     path = paths[0]; |     path = paths[0]; | ||||||
|  |  | ||||||
|  | @ -37,34 +37,25 @@ typedef base::Callback<void( | ||||||
| typedef base::Callback<void( | typedef base::Callback<void( | ||||||
|     bool result, const base::FilePath& path)> SaveDialogCallback; |     bool result, const base::FilePath& path)> SaveDialogCallback; | ||||||
| 
 | 
 | ||||||
| bool ShowOpenDialog(atom::NativeWindow* parent_window, | struct DialogSettings { | ||||||
|                     const std::string& title, |   atom::NativeWindow* parent_window = nullptr; | ||||||
|                     const std::string& button_label, |   std::string title; | ||||||
|                     const base::FilePath& default_path, |   std::string button_label; | ||||||
|                     const Filters& filters, |   base::FilePath default_path; | ||||||
|                     int properties, |   Filters filters; | ||||||
|  |   int properties = 0; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | bool ShowOpenDialog(const DialogSettings& settings, | ||||||
|                     std::vector<base::FilePath>* paths); |                     std::vector<base::FilePath>* paths); | ||||||
| 
 | 
 | ||||||
| void ShowOpenDialog(atom::NativeWindow* parent_window, | void ShowOpenDialog(const DialogSettings& settings, | ||||||
|                     const std::string& title, |  | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const Filters& filters, |  | ||||||
|                     int properties, |  | ||||||
|                     const OpenDialogCallback& callback); |                     const OpenDialogCallback& callback); | ||||||
| 
 | 
 | ||||||
| bool ShowSaveDialog(atom::NativeWindow* parent_window, | bool ShowSaveDialog(const DialogSettings& settings, | ||||||
|                     const std::string& title, |  | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const Filters& filters, |  | ||||||
|                     base::FilePath* path); |                     base::FilePath* path); | ||||||
| 
 | 
 | ||||||
| void ShowSaveDialog(atom::NativeWindow* parent_window, | void ShowSaveDialog(const DialogSettings& settings, | ||||||
|                     const std::string& title, |  | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const Filters& filters, |  | ||||||
|                     const SaveDialogCallback& callback); |                     const SaveDialogCallback& callback); | ||||||
| 
 | 
 | ||||||
| }  // namespace file_dialog
 | }  // namespace file_dialog
 | ||||||
|  |  | ||||||
|  | @ -36,24 +36,20 @@ void OnFileFilterDataDestroyed(std::string* file_extension) { | ||||||
| class FileChooserDialog { | class FileChooserDialog { | ||||||
|  public: |  public: | ||||||
|   FileChooserDialog(GtkFileChooserAction action, |   FileChooserDialog(GtkFileChooserAction action, | ||||||
|                     atom::NativeWindow* parent_window, |                     const DialogSettings& settings) | ||||||
|                     const std::string& title, |       : parent_(static_cast<atom::NativeWindowViews*>(settings.parent_window)), | ||||||
|                     const std::string& button_label, |         filters_(settings.filters) { | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const Filters& filters) |  | ||||||
|       : parent_(static_cast<atom::NativeWindowViews*>(parent_window)), |  | ||||||
|         filters_(filters) { |  | ||||||
|     const char* confirm_text = GTK_STOCK_OK; |     const char* confirm_text = GTK_STOCK_OK; | ||||||
| 
 | 
 | ||||||
|     if (!button_label.empty()) |     if (!settings.button_label.empty()) | ||||||
|       confirm_text = button_label.c_str(); |       confirm_text = settings.button_label.c_str(); | ||||||
|     else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) |     else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) | ||||||
|       confirm_text = GTK_STOCK_SAVE; |       confirm_text = GTK_STOCK_SAVE; | ||||||
|     else if (action == GTK_FILE_CHOOSER_ACTION_OPEN) |     else if (action == GTK_FILE_CHOOSER_ACTION_OPEN) | ||||||
|       confirm_text = GTK_STOCK_OPEN; |       confirm_text = GTK_STOCK_OPEN; | ||||||
| 
 | 
 | ||||||
|     dialog_ = gtk_file_chooser_dialog_new( |     dialog_ = gtk_file_chooser_dialog_new( | ||||||
|         title.c_str(), |         settings.title.c_str(), | ||||||
|         NULL, |         NULL, | ||||||
|         action, |         action, | ||||||
|         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |         GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | ||||||
|  | @ -71,20 +67,20 @@ class FileChooserDialog { | ||||||
|     if (action != GTK_FILE_CHOOSER_ACTION_OPEN) |     if (action != GTK_FILE_CHOOSER_ACTION_OPEN) | ||||||
|       gtk_file_chooser_set_create_folders(GTK_FILE_CHOOSER(dialog_), TRUE); |       gtk_file_chooser_set_create_folders(GTK_FILE_CHOOSER(dialog_), TRUE); | ||||||
| 
 | 
 | ||||||
|     if (!default_path.empty()) { |     if (!settings.default_path.empty()) { | ||||||
|       if (base::DirectoryExists(default_path)) { |       if (base::DirectoryExists(settings.default_path)) { | ||||||
|         gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog_), |         gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog_), | ||||||
|                                             default_path.value().c_str()); |             settings.default_path.value().c_str()); | ||||||
|       } else { |       } else { | ||||||
|         gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog_), |         gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog_), | ||||||
|             default_path.DirName().value().c_str()); |             settings.default_path.DirName().value().c_str()); | ||||||
|         gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog_), |         gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog_), | ||||||
|             default_path.BaseName().value().c_str()); |             settings.default_path.BaseName().value().c_str()); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!filters.empty()) |     if (!settings.filters.empty()) | ||||||
|       AddFilters(filters); |       AddFilters(settings.filters); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   ~FileChooserDialog() { |   ~FileChooserDialog() { | ||||||
|  | @ -230,19 +226,13 @@ base::FilePath FileChooserDialog::AddExtensionForFilename( | ||||||
| 
 | 
 | ||||||
| }  // namespace
 | }  // namespace
 | ||||||
| 
 | 
 | ||||||
| bool ShowOpenDialog(atom::NativeWindow* parent_window, | bool ShowOpenDialog(const DialogSettings& settings, | ||||||
|                     const std::string& title, |  | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const Filters& filters, |  | ||||||
|                     int properties, |  | ||||||
|                     std::vector<base::FilePath>* paths) { |                     std::vector<base::FilePath>* paths) { | ||||||
|   GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN; |   GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN; | ||||||
|   if (properties & FILE_DIALOG_OPEN_DIRECTORY) |   if (settings.properties & FILE_DIALOG_OPEN_DIRECTORY) | ||||||
|     action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; |     action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; | ||||||
|   FileChooserDialog open_dialog(action, parent_window, title, button_label, |   FileChooserDialog open_dialog(action, settings); | ||||||
|                                 default_path, filters); |   open_dialog.SetupProperties(settings.properties); | ||||||
|   open_dialog.SetupProperties(properties); |  | ||||||
| 
 | 
 | ||||||
|   gtk_widget_show_all(open_dialog.dialog()); |   gtk_widget_show_all(open_dialog.dialog()); | ||||||
|   int response = gtk_dialog_run(GTK_DIALOG(open_dialog.dialog())); |   int response = gtk_dialog_run(GTK_DIALOG(open_dialog.dialog())); | ||||||
|  | @ -254,30 +244,19 @@ bool ShowOpenDialog(atom::NativeWindow* parent_window, | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ShowOpenDialog(atom::NativeWindow* parent_window, | void ShowOpenDialog(const DialogSettings& settings, | ||||||
|                     const std::string& title, |  | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const Filters& filters, |  | ||||||
|                     int properties, |  | ||||||
|                     const OpenDialogCallback& callback) { |                     const OpenDialogCallback& callback) { | ||||||
|   GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN; |   GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN; | ||||||
|   if (properties & FILE_DIALOG_OPEN_DIRECTORY) |   if (settings.properties & FILE_DIALOG_OPEN_DIRECTORY) | ||||||
|     action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; |     action = GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER; | ||||||
|   FileChooserDialog* open_dialog = new FileChooserDialog( |   FileChooserDialog* open_dialog = new FileChooserDialog(action, settings); | ||||||
|       action, parent_window, title, button_label, default_path, filters); |   open_dialog->SetupProperties(settings.properties); | ||||||
|   open_dialog->SetupProperties(properties); |  | ||||||
|   open_dialog->RunOpenAsynchronous(callback); |   open_dialog->RunOpenAsynchronous(callback); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool ShowSaveDialog(atom::NativeWindow* parent_window, | bool ShowSaveDialog(const DialogSettings& settings, | ||||||
|                     const std::string& title, |  | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const Filters& filters, |  | ||||||
|                     base::FilePath* path) { |                     base::FilePath* path) { | ||||||
|   FileChooserDialog save_dialog(GTK_FILE_CHOOSER_ACTION_SAVE, parent_window, |   FileChooserDialog save_dialog(GTK_FILE_CHOOSER_ACTION_SAVE, settings); | ||||||
|                                 title, button_label, default_path, filters); |  | ||||||
|   gtk_widget_show_all(save_dialog.dialog()); |   gtk_widget_show_all(save_dialog.dialog()); | ||||||
|   int response = gtk_dialog_run(GTK_DIALOG(save_dialog.dialog())); |   int response = gtk_dialog_run(GTK_DIALOG(save_dialog.dialog())); | ||||||
|   if (response == GTK_RESPONSE_ACCEPT) { |   if (response == GTK_RESPONSE_ACCEPT) { | ||||||
|  | @ -288,15 +267,10 @@ bool ShowSaveDialog(atom::NativeWindow* parent_window, | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ShowSaveDialog(atom::NativeWindow* parent_window, | void ShowSaveDialog(const DialogSettings& settings, | ||||||
|                     const std::string& title, |  | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const Filters& filters, |  | ||||||
|                     const SaveDialogCallback& callback) { |                     const SaveDialogCallback& callback) { | ||||||
|   FileChooserDialog* save_dialog = new FileChooserDialog( |   FileChooserDialog* save_dialog = new FileChooserDialog( | ||||||
|       GTK_FILE_CHOOSER_ACTION_SAVE, parent_window, title, button_label, |       GTK_FILE_CHOOSER_ACTION_SAVE, settings); | ||||||
|       default_path, filters); |  | ||||||
|   save_dialog->RunSaveAsynchronous(callback); |   save_dialog->RunSaveAsynchronous(callback); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -44,25 +44,23 @@ void SetAllowedFileTypes(NSSavePanel* dialog, const Filters& filters) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SetupDialog(NSSavePanel* dialog, | void SetupDialog(NSSavePanel* dialog, | ||||||
|                  const std::string& title, |                  const DialogSettings& settings) { | ||||||
|                  const std::string& button_label, |   if (!settings.title.empty()) | ||||||
|                  const base::FilePath& default_path, |     [dialog setTitle:base::SysUTF8ToNSString(settings.title)]; | ||||||
|                  const Filters& filters) { |  | ||||||
|   if (!title.empty()) |  | ||||||
|     [dialog setTitle:base::SysUTF8ToNSString(title)]; |  | ||||||
| 
 | 
 | ||||||
|   if (!button_label.empty()) |   if (!settings.button_label.empty()) | ||||||
|     [dialog setPrompt:base::SysUTF8ToNSString(button_label)]; |     [dialog setPrompt:base::SysUTF8ToNSString(settings.button_label)]; | ||||||
| 
 | 
 | ||||||
|   NSString* default_dir = nil; |   NSString* default_dir = nil; | ||||||
|   NSString* default_filename = nil; |   NSString* default_filename = nil; | ||||||
|   if (!default_path.empty()) { |   if (!settings.default_path.empty()) { | ||||||
|     if (base::DirectoryExists(default_path)) { |     if (base::DirectoryExists(settings.default_path)) { | ||||||
|       default_dir = base::SysUTF8ToNSString(default_path.value()); |       default_dir = base::SysUTF8ToNSString(settings.default_path.value()); | ||||||
|     } else { |     } else { | ||||||
|       default_dir = base::SysUTF8ToNSString(default_path.DirName().value()); |       default_dir = | ||||||
|  |           base::SysUTF8ToNSString(settings.default_path.DirName().value()); | ||||||
|       default_filename = |       default_filename = | ||||||
|           base::SysUTF8ToNSString(default_path.BaseName().value()); |           base::SysUTF8ToNSString(settings.default_path.BaseName().value()); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | @ -71,10 +69,10 @@ void SetupDialog(NSSavePanel* dialog, | ||||||
|   if (default_filename) |   if (default_filename) | ||||||
|     [dialog setNameFieldStringValue:default_filename]; |     [dialog setNameFieldStringValue:default_filename]; | ||||||
| 
 | 
 | ||||||
|   if (filters.empty()) |   if (settings.filters.empty()) | ||||||
|     [dialog setAllowsOtherFileTypes:YES]; |     [dialog setAllowsOtherFileTypes:YES]; | ||||||
|   else |   else | ||||||
|     SetAllowedFileTypes(dialog, filters); |     SetAllowedFileTypes(dialog, settings.filters); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void SetupDialogForProperties(NSOpenPanel* dialog, int properties) { | void SetupDialogForProperties(NSOpenPanel* dialog, int properties) { | ||||||
|  | @ -117,20 +115,15 @@ void ReadDialogPaths(NSOpenPanel* dialog, std::vector<base::FilePath>* paths) { | ||||||
| 
 | 
 | ||||||
| }  // namespace | }  // namespace | ||||||
| 
 | 
 | ||||||
| bool ShowOpenDialog(atom::NativeWindow* parent_window, | bool ShowOpenDialog(const DialogSettings& settings, | ||||||
|                     const std::string& title, |  | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const Filters& filters, |  | ||||||
|                     int properties, |  | ||||||
|                     std::vector<base::FilePath>* paths) { |                     std::vector<base::FilePath>* paths) { | ||||||
|   DCHECK(paths); |   DCHECK(paths); | ||||||
|   NSOpenPanel* dialog = [NSOpenPanel openPanel]; |   NSOpenPanel* dialog = [NSOpenPanel openPanel]; | ||||||
| 
 | 
 | ||||||
|   SetupDialog(dialog, title, button_label, default_path, filters); |   SetupDialog(dialog, settings); | ||||||
|   SetupDialogForProperties(dialog, properties); |   SetupDialogForProperties(dialog, settings.properties); | ||||||
| 
 | 
 | ||||||
|   int chosen = RunModalDialog(dialog, parent_window); |   int chosen = RunModalDialog(dialog, settings.parent_window); | ||||||
|   if (chosen == NSFileHandlingPanelCancelButton) |   if (chosen == NSFileHandlingPanelCancelButton) | ||||||
|     return false; |     return false; | ||||||
| 
 | 
 | ||||||
|  | @ -138,23 +131,20 @@ bool ShowOpenDialog(atom::NativeWindow* parent_window, | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ShowOpenDialog(atom::NativeWindow* parent_window, | void ShowOpenDialog(const DialogSettings& settings, | ||||||
|                     const std::string& title, |  | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const Filters& filters, |  | ||||||
|                     int properties, |  | ||||||
|                     const OpenDialogCallback& c) { |                     const OpenDialogCallback& c) { | ||||||
|   NSOpenPanel* dialog = [NSOpenPanel openPanel]; |   NSOpenPanel* dialog = [NSOpenPanel openPanel]; | ||||||
| 
 | 
 | ||||||
|   SetupDialog(dialog, title, button_label, default_path, filters); |   SetupDialog(dialog, settings); | ||||||
|   SetupDialogForProperties(dialog, properties); |   SetupDialogForProperties(dialog, settings.properties); | ||||||
| 
 | 
 | ||||||
|   // Duplicate the callback object here since c is a reference and gcd would |   // Duplicate the callback object here since c is a reference and gcd would | ||||||
|   // only store the pointer, by duplication we can force gcd to store a copy. |   // only store the pointer, by duplication we can force gcd to store a copy. | ||||||
|   __block OpenDialogCallback callback = c; |   __block OpenDialogCallback callback = c; | ||||||
| 
 | 
 | ||||||
|   NSWindow* window = parent_window ? parent_window->GetNativeWindow() : NULL; |   NSWindow* window = settings.parent_window ? | ||||||
|  |       settings.parent_window->GetNativeWindow() : | ||||||
|  |       NULL; | ||||||
|   [dialog beginSheetModalForWindow:window |   [dialog beginSheetModalForWindow:window | ||||||
|                  completionHandler:^(NSInteger chosen) { |                  completionHandler:^(NSInteger chosen) { | ||||||
|     if (chosen == NSFileHandlingPanelCancelButton) { |     if (chosen == NSFileHandlingPanelCancelButton) { | ||||||
|  | @ -167,18 +157,14 @@ void ShowOpenDialog(atom::NativeWindow* parent_window, | ||||||
|   }]; |   }]; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool ShowSaveDialog(atom::NativeWindow* parent_window, | bool ShowSaveDialog(const DialogSettings& settings, | ||||||
|                     const std::string& title, |  | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const Filters& filters, |  | ||||||
|                     base::FilePath* path) { |                     base::FilePath* path) { | ||||||
|   DCHECK(path); |   DCHECK(path); | ||||||
|   NSSavePanel* dialog = [NSSavePanel savePanel]; |   NSSavePanel* dialog = [NSSavePanel savePanel]; | ||||||
| 
 | 
 | ||||||
|   SetupDialog(dialog, title, button_label, default_path, filters); |   SetupDialog(dialog, settings); | ||||||
| 
 | 
 | ||||||
|   int chosen = RunModalDialog(dialog, parent_window); |   int chosen = RunModalDialog(dialog, settings.parent_window); | ||||||
|   if (chosen == NSFileHandlingPanelCancelButton || ![[dialog URL] isFileURL]) |   if (chosen == NSFileHandlingPanelCancelButton || ![[dialog URL] isFileURL]) | ||||||
|     return false; |     return false; | ||||||
| 
 | 
 | ||||||
|  | @ -186,20 +172,18 @@ bool ShowSaveDialog(atom::NativeWindow* parent_window, | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ShowSaveDialog(atom::NativeWindow* parent_window, | void ShowSaveDialog(const DialogSettings& settings, | ||||||
|                     const std::string& title, |  | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const Filters& filters, |  | ||||||
|                     const SaveDialogCallback& c) { |                     const SaveDialogCallback& c) { | ||||||
|   NSSavePanel* dialog = [NSSavePanel savePanel]; |   NSSavePanel* dialog = [NSSavePanel savePanel]; | ||||||
| 
 | 
 | ||||||
|   SetupDialog(dialog, title, button_label, default_path, filters); |   SetupDialog(dialog, settings); | ||||||
|   [dialog setCanSelectHiddenExtension:YES]; |   [dialog setCanSelectHiddenExtension:YES]; | ||||||
| 
 | 
 | ||||||
|   __block SaveDialogCallback callback = c; |   __block SaveDialogCallback callback = c; | ||||||
| 
 | 
 | ||||||
|   NSWindow* window = parent_window ? parent_window->GetNativeWindow() : NULL; |   NSWindow* window = settings.parent_window ? | ||||||
|  |     settings.parent_window->GetNativeWindow() : | ||||||
|  |     NULL; | ||||||
|   [dialog beginSheetModalForWindow:window |   [dialog beginSheetModalForWindow:window | ||||||
|                  completionHandler:^(NSInteger chosen) { |                  completionHandler:^(NSInteger chosen) { | ||||||
|     if (chosen == NSFileHandlingPanelCancelButton) { |     if (chosen == NSFileHandlingPanelCancelButton) { | ||||||
|  |  | ||||||
|  | @ -66,26 +66,24 @@ void ConvertFilters(const Filters& filters, | ||||||
| template <typename T> | template <typename T> | ||||||
| class FileDialog { | class FileDialog { | ||||||
|  public: |  public: | ||||||
|   FileDialog(const base::FilePath& default_path, |   FileDialog(const DialogSettings& settings, int options) { | ||||||
|              const std::string& title, |  | ||||||
|              const std::string& button_label, |  | ||||||
|              const Filters& filters, int options) { |  | ||||||
|     std::wstring file_part; |     std::wstring file_part; | ||||||
|     if (!IsDirectory(default_path)) |     if (!IsDirectory(settings.default_path)) | ||||||
|       file_part = default_path.BaseName().value(); |       file_part = settings.default_path.BaseName().value(); | ||||||
| 
 | 
 | ||||||
|     std::vector<std::wstring> buffer; |     std::vector<std::wstring> buffer; | ||||||
|     std::vector<COMDLG_FILTERSPEC> filterspec; |     std::vector<COMDLG_FILTERSPEC> filterspec; | ||||||
|     ConvertFilters(filters, &buffer, &filterspec); |     ConvertFilters(settings.filters, &buffer, &filterspec); | ||||||
| 
 | 
 | ||||||
|     dialog_.reset(new T(file_part.c_str(), options, NULL, |     dialog_.reset(new T(file_part.c_str(), options, NULL, | ||||||
|                         filterspec.data(), filterspec.size())); |                         filterspec.data(), filterspec.size())); | ||||||
| 
 | 
 | ||||||
|     if (!title.empty()) |     if (!settings.title.empty()) | ||||||
|       GetPtr()->SetTitle(base::UTF8ToUTF16(title).c_str()); |       GetPtr()->SetTitle(base::UTF8ToUTF16(settings.title).c_str()); | ||||||
| 
 | 
 | ||||||
|     if (!button_label.empty()) |     if (!settings.button_label.empty()) | ||||||
|       GetPtr()->SetOkButtonLabel(base::UTF8ToUTF16(button_label).c_str()); |       GetPtr()->SetOkButtonLabel( | ||||||
|  |           base::UTF8ToUTF16(settings.button_label).c_str()); | ||||||
| 
 | 
 | ||||||
|     // By default, *.* will be added to the file name if file type is "*.*". In
 |     // By default, *.* will be added to the file name if file type is "*.*". In
 | ||||||
|     // Electron, we disable it to make a better experience.
 |     // Electron, we disable it to make a better experience.
 | ||||||
|  | @ -107,7 +105,7 @@ class FileDialog { | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     SetDefaultFolder(default_path); |     SetDefaultFolder(settings.default_path); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   bool Show(atom::NativeWindow* parent_window) { |   bool Show(atom::NativeWindow* parent_window) { | ||||||
|  | @ -160,31 +158,20 @@ bool CreateDialogThread(RunState* run_state) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RunOpenDialogInNewThread(const RunState& run_state, | void RunOpenDialogInNewThread(const RunState& run_state, | ||||||
|                               atom::NativeWindow* parent, |                               const DialogSettings& settings, | ||||||
|                               const std::string& title, |  | ||||||
|                               const std::string& button_label, |  | ||||||
|                               const base::FilePath& default_path, |  | ||||||
|                               const Filters& filters, |  | ||||||
|                               int properties, |  | ||||||
|                               const OpenDialogCallback& callback) { |                               const OpenDialogCallback& callback) { | ||||||
|   std::vector<base::FilePath> paths; |   std::vector<base::FilePath> paths; | ||||||
|   bool result = ShowOpenDialog(parent, title, button_label, default_path, |   bool result = ShowOpenDialog(settings, &paths); | ||||||
|                                filters, properties, &paths); |  | ||||||
|   run_state.ui_task_runner->PostTask(FROM_HERE, |   run_state.ui_task_runner->PostTask(FROM_HERE, | ||||||
|                                       base::Bind(callback, result, paths)); |                                       base::Bind(callback, result, paths)); | ||||||
|   run_state.ui_task_runner->DeleteSoon(FROM_HERE, run_state.dialog_thread); |   run_state.ui_task_runner->DeleteSoon(FROM_HERE, run_state.dialog_thread); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RunSaveDialogInNewThread(const RunState& run_state, | void RunSaveDialogInNewThread(const RunState& run_state, | ||||||
|                               atom::NativeWindow* parent, |                               const DialogSettings& settings, | ||||||
|                               const std::string& title, |  | ||||||
|                               const std::string& button_label, |  | ||||||
|                               const base::FilePath& default_path, |  | ||||||
|                               const Filters& filters, |  | ||||||
|                               const SaveDialogCallback& callback) { |                               const SaveDialogCallback& callback) { | ||||||
|   base::FilePath path; |   base::FilePath path; | ||||||
|   bool result = ShowSaveDialog(parent, title, button_label, default_path, |   bool result = ShowSaveDialog(settings, &path); | ||||||
|                                filters, &path); |  | ||||||
|   run_state.ui_task_runner->PostTask(FROM_HERE, |   run_state.ui_task_runner->PostTask(FROM_HERE, | ||||||
|                                      base::Bind(callback, result, path)); |                                      base::Bind(callback, result, path)); | ||||||
|   run_state.ui_task_runner->DeleteSoon(FROM_HERE, run_state.dialog_thread); |   run_state.ui_task_runner->DeleteSoon(FROM_HERE, run_state.dialog_thread); | ||||||
|  | @ -192,26 +179,20 @@ void RunSaveDialogInNewThread(const RunState& run_state, | ||||||
| 
 | 
 | ||||||
| }  // namespace
 | }  // namespace
 | ||||||
| 
 | 
 | ||||||
| bool ShowOpenDialog(atom::NativeWindow* parent_window, | bool ShowOpenDialog(const DialogSettings& settings, | ||||||
|                     const std::string& title, |  | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const Filters& filters, |  | ||||||
|                     int properties, |  | ||||||
|                     std::vector<base::FilePath>* paths) { |                     std::vector<base::FilePath>* paths) { | ||||||
|   int options = FOS_FORCEFILESYSTEM | FOS_FILEMUSTEXIST; |   int options = FOS_FORCEFILESYSTEM | FOS_FILEMUSTEXIST; | ||||||
|   if (properties & FILE_DIALOG_OPEN_DIRECTORY) |   if (settings.properties & FILE_DIALOG_OPEN_DIRECTORY) | ||||||
|     options |= FOS_PICKFOLDERS; |     options |= FOS_PICKFOLDERS; | ||||||
|   if (properties & FILE_DIALOG_MULTI_SELECTIONS) |   if (settings.properties & FILE_DIALOG_MULTI_SELECTIONS) | ||||||
|     options |= FOS_ALLOWMULTISELECT; |     options |= FOS_ALLOWMULTISELECT; | ||||||
|   if (properties & FILE_DIALOG_SHOW_HIDDEN_FILES) |   if (settings.properties & FILE_DIALOG_SHOW_HIDDEN_FILES) | ||||||
|     options |= FOS_FORCESHOWHIDDEN; |     options |= FOS_FORCESHOWHIDDEN; | ||||||
|   if (properties & FILE_DIALOG_PROMPT_TO_CREATE) |   if (settings.properties & FILE_DIALOG_PROMPT_TO_CREATE) | ||||||
|     options |= FOS_CREATEPROMPT; |     options |= FOS_CREATEPROMPT; | ||||||
| 
 | 
 | ||||||
|   FileDialog<CShellFileOpenDialog> open_dialog( |   FileDialog<CShellFileOpenDialog> open_dialog(settings, options); | ||||||
|       default_path, title, button_label, filters, options); |   if (!open_dialog.Show(settings.parent_window)) | ||||||
|   if (!open_dialog.Show(parent_window)) |  | ||||||
|     return false; |     return false; | ||||||
| 
 | 
 | ||||||
|   ATL::CComPtr<IShellItemArray> items; |   ATL::CComPtr<IShellItemArray> items; | ||||||
|  | @ -244,12 +225,7 @@ bool ShowOpenDialog(atom::NativeWindow* parent_window, | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ShowOpenDialog(atom::NativeWindow* parent, | void ShowOpenDialog(const DialogSettings& settings, | ||||||
|                     const std::string& title, |  | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const Filters& filters, |  | ||||||
|                     int properties, |  | ||||||
|                     const OpenDialogCallback& callback) { |                     const OpenDialogCallback& callback) { | ||||||
|   RunState run_state; |   RunState run_state; | ||||||
|   if (!CreateDialogThread(&run_state)) { |   if (!CreateDialogThread(&run_state)) { | ||||||
|  | @ -259,20 +235,14 @@ void ShowOpenDialog(atom::NativeWindow* parent, | ||||||
| 
 | 
 | ||||||
|   run_state.dialog_thread->task_runner()->PostTask( |   run_state.dialog_thread->task_runner()->PostTask( | ||||||
|       FROM_HERE, |       FROM_HERE, | ||||||
|       base::Bind(&RunOpenDialogInNewThread, run_state, parent, title, |       base::Bind(&RunOpenDialogInNewThread, run_state, settings, callback)); | ||||||
|                  button_label, default_path, filters, properties, callback)); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool ShowSaveDialog(atom::NativeWindow* parent_window, | bool ShowSaveDialog(const DialogSettings& settings, | ||||||
|                     const std::string& title, |  | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const Filters& filters, |  | ||||||
|                     base::FilePath* path) { |                     base::FilePath* path) { | ||||||
|   FileDialog<CShellFileSaveDialog> save_dialog( |   FileDialog<CShellFileSaveDialog> save_dialog( | ||||||
|       default_path, title, button_label, filters, |       settings, FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT); | ||||||
|       FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_OVERWRITEPROMPT); |   if (!save_dialog.Show(settings.parent_window)) | ||||||
|   if (!save_dialog.Show(parent_window)) |  | ||||||
|     return false; |     return false; | ||||||
| 
 | 
 | ||||||
|   wchar_t buffer[MAX_PATH]; |   wchar_t buffer[MAX_PATH]; | ||||||
|  | @ -284,11 +254,7 @@ bool ShowSaveDialog(atom::NativeWindow* parent_window, | ||||||
|   return true; |   return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ShowSaveDialog(atom::NativeWindow* parent, | void ShowSaveDialog(const DialogSettings& settings, | ||||||
|                     const std::string& title, |  | ||||||
|                     const std::string& button_label, |  | ||||||
|                     const base::FilePath& default_path, |  | ||||||
|                     const Filters& filters, |  | ||||||
|                     const SaveDialogCallback& callback) { |                     const SaveDialogCallback& callback) { | ||||||
|   RunState run_state; |   RunState run_state; | ||||||
|   if (!CreateDialogThread(&run_state)) { |   if (!CreateDialogThread(&run_state)) { | ||||||
|  | @ -298,8 +264,7 @@ void ShowSaveDialog(atom::NativeWindow* parent, | ||||||
| 
 | 
 | ||||||
|   run_state.dialog_thread->task_runner()->PostTask( |   run_state.dialog_thread->task_runner()->PostTask( | ||||||
|       FROM_HERE, |       FROM_HERE, | ||||||
|       base::Bind(&RunSaveDialogInNewThread, run_state, parent, title, |       base::Bind(&RunSaveDialogInNewThread, run_state, settings, callback)); | ||||||
|                  button_label, default_path, filters, callback)); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| }  // namespace file_dialog
 | }  // namespace file_dialog
 | ||||||
|  |  | ||||||
|  | @ -81,16 +81,16 @@ void WebDialogHelper::RunFileChooser( | ||||||
|     content::RenderFrameHost* render_frame_host, |     content::RenderFrameHost* render_frame_host, | ||||||
|     const content::FileChooserParams& params) { |     const content::FileChooserParams& params) { | ||||||
|   std::vector<content::FileChooserFileInfo> result; |   std::vector<content::FileChooserFileInfo> result; | ||||||
|   file_dialog::Filters filters = GetFileTypesFromAcceptType( | 
 | ||||||
|       params.accept_types); |   file_dialog::DialogSettings settings; | ||||||
|  |   settings.filters = GetFileTypesFromAcceptType(params.accept_types); | ||||||
|  |   settings.parent_window = window_; | ||||||
|  |   settings.title = base::UTF16ToUTF8(params.title); | ||||||
|  | 
 | ||||||
|   if (params.mode == content::FileChooserParams::Save) { |   if (params.mode == content::FileChooserParams::Save) { | ||||||
|     base::FilePath path; |     base::FilePath path; | ||||||
|     if (file_dialog::ShowSaveDialog(window_, |     settings.default_path = params.default_file_name; | ||||||
|                                     base::UTF16ToUTF8(params.title), |     if (file_dialog::ShowSaveDialog(settings, &path)) { | ||||||
|                                     "", |  | ||||||
|                                     params.default_file_name, |  | ||||||
|                                     filters, |  | ||||||
|                                     &path)) { |  | ||||||
|       content::FileChooserFileInfo info; |       content::FileChooserFileInfo info; | ||||||
|       info.file_path = path; |       info.file_path = path; | ||||||
|       info.display_name = path.BaseName().value(); |       info.display_name = path.BaseName().value(); | ||||||
|  | @ -114,15 +114,10 @@ void WebDialogHelper::RunFileChooser( | ||||||
|     std::vector<base::FilePath> paths; |     std::vector<base::FilePath> paths; | ||||||
|     AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>( |     AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>( | ||||||
|         window_->web_contents()->GetBrowserContext()); |         window_->web_contents()->GetBrowserContext()); | ||||||
|     base::FilePath default_file_path = browser_context->prefs()->GetFilePath( |     settings.default_path = browser_context->prefs()->GetFilePath( | ||||||
|         prefs::kSelectFileLastDirectory).Append(params.default_file_name); |         prefs::kSelectFileLastDirectory).Append(params.default_file_name); | ||||||
|     if (file_dialog::ShowOpenDialog(window_, |     settings.properties = flags; | ||||||
|                                     base::UTF16ToUTF8(params.title), |     if (file_dialog::ShowOpenDialog(settings, &paths)) { | ||||||
|                                     "", |  | ||||||
|                                     default_file_path, |  | ||||||
|                                     filters, |  | ||||||
|                                     flags, |  | ||||||
|                                     &paths)) { |  | ||||||
|       for (auto& path : paths) { |       for (auto& path : paths) { | ||||||
|         content::FileChooserFileInfo info; |         content::FileChooserFileInfo info; | ||||||
|         info.file_path = path; |         info.file_path = path; | ||||||
|  |  | ||||||
|  | @ -121,8 +121,9 @@ module.exports = { | ||||||
|     const wrappedCallback = typeof callback === 'function' ? function (success, result) { |     const wrappedCallback = typeof callback === 'function' ? function (success, result) { | ||||||
|       return callback(success ? result : void 0) |       return callback(success ? result : void 0) | ||||||
|     } : null |     } : null | ||||||
|     return binding.showOpenDialog(title, buttonLabel, defaultPath, filters, |     const settings = {title, buttonLabel, defaultPath, filters, window} | ||||||
|                                   dialogProperties, window, wrappedCallback) |     settings.properties = dialogProperties | ||||||
|  |     return binding.showOpenDialog(settings, wrappedCallback) | ||||||
|   }, |   }, | ||||||
| 
 | 
 | ||||||
|   showSaveDialog: function (...args) { |   showSaveDialog: function (...args) { | ||||||
|  | @ -163,8 +164,8 @@ module.exports = { | ||||||
|     const wrappedCallback = typeof callback === 'function' ? function (success, result) { |     const wrappedCallback = typeof callback === 'function' ? function (success, result) { | ||||||
|       return callback(success ? result : void 0) |       return callback(success ? result : void 0) | ||||||
|     } : null |     } : null | ||||||
|     return binding.showSaveDialog(title, buttonLabel, defaultPath, filters, |     const settings = {title, buttonLabel, defaultPath, filters, window} | ||||||
|                                   window, wrappedCallback) |     return binding.showSaveDialog(settings, wrappedCallback) | ||||||
|   }, |   }, | ||||||
| 
 | 
 | ||||||
|   showMessageBox: function (...args) { |   showMessageBox: function (...args) { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Kevin Sawicki
				Kevin Sawicki