mac: Add asynchronous ShowOpenDialog.
authorCheng Zhao <zcbenz@gmail.com>
Mon, 23 Sep 2013 11:22:36 +0000 (19:22 +0800)
committerCheng Zhao <zcbenz@gmail.com>
Mon, 23 Sep 2013 11:22:36 +0000 (19:22 +0800)
browser/ui/file_dialog.h
browser/ui/file_dialog_mac.mm

index 77e5ac4..250ba5c 100644 (file)
@@ -8,6 +8,7 @@
 #include <string>
 #include <vector>
 
+#include "base/callback_forward.h"
 #include "base/files/file_path.h"
 
 namespace atom {
@@ -23,12 +24,21 @@ enum FileDialogProperty {
   FILE_DIALOG_CREATE_DIRECTORY = 8,
 };
 
+typedef base::Callback<void(
+    bool result, std::vector<base::FilePath> paths)> OpenDialogCallback;
+
 bool ShowOpenDialog(atom::NativeWindow* parent_window,
                     const std::string& title,
                     const base::FilePath& default_path,
                     int properties,
                     std::vector<base::FilePath>* paths);
 
+void ShowOpenDialog(atom::NativeWindow* parent_window,
+                    const std::string& title,
+                    const base::FilePath& default_path,
+                    int properties,
+                    const OpenDialogCallback& callback);
+
 bool ShowSaveDialog(atom::NativeWindow* parent_window,
                     const std::string& title,
                     const base::FilePath& default_path,
index 54a901c..539fe91 100644 (file)
@@ -41,6 +41,23 @@ void SetupDialog(NSSavePanel* dialog,
   [dialog setAllowsOtherFileTypes:YES];
 }
 
+void SetupDialogForProperties(NSOpenPanel* dialog, int properties) {
+  [dialog setCanChooseFiles:(properties & FILE_DIALOG_OPEN_FILE)];
+  if (properties & FILE_DIALOG_OPEN_DIRECTORY)
+    [dialog setCanChooseDirectories:YES];
+  if (properties & FILE_DIALOG_CREATE_DIRECTORY)
+    [dialog setCanCreateDirectories:YES];
+  if (properties & FILE_DIALOG_MULTI_SELECTIONS)
+    [dialog setAllowsMultipleSelection:YES];
+}
+
+void ReadDialogPaths(NSOpenPanel* dialog, std::vector<base::FilePath>* paths) {
+  NSArray* urls = [dialog URLs];
+  for (NSURL* url in urls)
+    if ([url isFileURL])
+      paths->push_back(base::FilePath(base::SysNSStringToUTF8([url path])));
+}
+
 }  // namespace
 
 bool ShowOpenDialog(atom::NativeWindow* parent_window,
@@ -52,14 +69,7 @@ bool ShowOpenDialog(atom::NativeWindow* parent_window,
   NSOpenPanel* dialog = [NSOpenPanel openPanel];
 
   SetupDialog(dialog, title, default_path);
-
-  [dialog setCanChooseFiles:(properties & FILE_DIALOG_OPEN_FILE)];
-  if (properties & FILE_DIALOG_OPEN_DIRECTORY)
-    [dialog setCanChooseDirectories:YES];
-  if (properties & FILE_DIALOG_CREATE_DIRECTORY)
-    [dialog setCanCreateDirectories:YES];
-  if (properties & FILE_DIALOG_MULTI_SELECTIONS)
-    [dialog setAllowsMultipleSelection:YES];
+  SetupDialogForProperties(dialog, properties);
 
   __block int chosen = -1;
 
@@ -79,14 +89,37 @@ bool ShowOpenDialog(atom::NativeWindow* parent_window,
   if (chosen == NSFileHandlingPanelCancelButton)
     return false;
 
-  NSArray* urls = [dialog URLs];
-  for (NSURL* url in urls)
-    if ([url isFileURL])
-      paths->push_back(base::FilePath(base::SysNSStringToUTF8([url path])));
-
+  ReadDialogPaths(dialog, paths);
   return true;
 }
 
+void ShowOpenDialog(atom::NativeWindow* parent_window,
+                    const std::string& title,
+                    const base::FilePath& default_path,
+                    int properties,
+                    const OpenDialogCallback& c) {
+  NSOpenPanel* dialog = [NSOpenPanel openPanel];
+
+  SetupDialog(dialog, title, default_path);
+  SetupDialogForProperties(dialog, properties);
+
+  // 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.
+  __block OpenDialogCallback callback = c;
+
+  NSWindow* window = parent_window ? parent_window->GetNativeWindow() : NULL;
+  [dialog beginSheetModalForWindow:window
+                 completionHandler:^(NSInteger chosen) {
+    if (chosen == NSFileHandlingPanelCancelButton) {
+      callback.Run(false, std::vector<base::FilePath>());
+    } else {
+      std::vector<base::FilePath> paths;
+      ReadDialogPaths(dialog, &paths);
+      callback.Run(true, paths);
+    }
+  }];
+}
+
 bool ShowSaveDialog(atom::NativeWindow* window,
                     const std::string& title,
                     const base::FilePath& default_path,