| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/shell_dialogs.h" | 5 #include "chrome/browser/shell_dialogs.h" |
| 6 | 6 |
| 7 #include <CoreServices/CoreServices.h> | 7 #include <CoreServices/CoreServices.h> |
| 8 #import <Cocoa/Cocoa.h> | 8 #import <Cocoa/Cocoa.h> |
| 9 #include <map> | 9 #include <map> |
| 10 #include <set> | 10 #include <set> |
| 11 | 11 |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/scoped_cftyperef.h" | 13 #include "base/scoped_cftyperef.h" |
| 14 #import "base/scoped_nsobject.h" | 14 #import "base/scoped_nsobject.h" |
| 15 #include "base/sys_string_conversions.h" | 15 #include "base/sys_string_conversions.h" |
| 16 #include "chrome/app/chrome_dll_resource.h" |
| 17 #include "chrome/browser/cocoa/constrained_window_mac.h" |
| 18 #include "chrome/browser/tab_contents/tab_contents.h" |
| 16 | 19 |
| 17 static const int kFileTypePopupTag = 1234; | 20 static const int kFileTypePopupTag = 1234; |
| 18 | 21 |
| 19 class SelectFileDialogImpl; | 22 class SelectFileDialogImpl; |
| 20 | 23 |
| 21 // A bridge class to act as the modal delegate to the save/open sheet and send | 24 // A bridge class to act as the modal delegate to the save/open sheet and send |
| 22 // the results to the C++ class. | 25 // the results to the C++ class. |
| 23 @interface SelectFileDialogBridge : NSObject { | 26 @interface SelectFileDialogBridge : NSObject { |
| 24 @private | 27 @private |
| 25 SelectFileDialogImpl* selectFileDialogImpl_; // WEAK; owns us | 28 SelectFileDialogImpl* selectFileDialogImpl_; // WEAK; owns us |
| (...skipping 10 matching lines...) Expand all Loading... |
| 36 // file or folder. | 39 // file or folder. |
| 37 class SelectFileDialogImpl : public SelectFileDialog { | 40 class SelectFileDialogImpl : public SelectFileDialog { |
| 38 public: | 41 public: |
| 39 explicit SelectFileDialogImpl(Listener* listener); | 42 explicit SelectFileDialogImpl(Listener* listener); |
| 40 virtual ~SelectFileDialogImpl(); | 43 virtual ~SelectFileDialogImpl(); |
| 41 | 44 |
| 42 // BaseShellDialog implementation. | 45 // BaseShellDialog implementation. |
| 43 virtual bool IsRunning(gfx::NativeWindow parent_window) const; | 46 virtual bool IsRunning(gfx::NativeWindow parent_window) const; |
| 44 virtual void ListenerDestroyed(); | 47 virtual void ListenerDestroyed(); |
| 45 | 48 |
| 49 // BaseShellDialog override. |
| 50 virtual bool IsRunningInTab(const TabContents* parent_tab) const; |
| 51 |
| 46 // SelectFileDialog implementation. | 52 // SelectFileDialog implementation. |
| 47 // |params| is user data we pass back via the Listener interface. | 53 // |params| is user data we pass back via the Listener interface. |
| 48 virtual void SelectFile(Type type, | 54 virtual void SelectFile(Type type, |
| 49 const string16& title, | 55 const string16& title, |
| 50 const FilePath& default_path, | 56 const FilePath& default_path, |
| 51 const FileTypeInfo* file_types, | 57 const FileTypeInfo* file_types, |
| 52 int file_type_index, | 58 int file_type_index, |
| 53 const FilePath::StringType& default_extension, | 59 const FilePath::StringType& default_extension, |
| 54 gfx::NativeWindow owning_window, | 60 gfx::NativeWindow owning_window, |
| 55 void* params); | 61 void* params); |
| 56 | 62 |
| 57 // Callback from ObjC bridge. | 63 // SelectFileDialog override. |
| 64 // |params| is user data we pass back via the Listener interface. |
| 65 virtual void SelectFileInTab(Type type, |
| 66 const string16& title, |
| 67 const FilePath& default_path, |
| 68 const FileTypeInfo* file_types, |
| 69 int file_type_index, |
| 70 const FilePath::StringType& default_extension, |
| 71 TabContents* owning_tab, |
| 72 void* params); |
| 73 |
| 74 // Callbacks from ObjC bridge. |
| 58 void FileWasSelected(NSPanel* dialog, | 75 void FileWasSelected(NSPanel* dialog, |
| 59 NSWindow* parent_window, | 76 NSWindow* parent_window, |
| 60 bool was_cancelled, | 77 bool was_cancelled, |
| 61 bool is_multi, | 78 bool is_multi, |
| 62 const std::vector<FilePath>& files, | 79 const std::vector<FilePath>& files, |
| 63 int index); | 80 int index); |
| 81 void FileWasSelectedInTab(NSPanel* dialog, |
| 82 TabContents* parent_tab, |
| 83 bool was_cancelled, |
| 84 bool was_killed, |
| 85 bool is_multi, |
| 86 const std::vector<FilePath>& files, |
| 87 int index); |
| 64 | 88 |
| 65 struct SheetContext { | 89 struct SheetContext { |
| 66 Type type; | 90 Type type; |
| 67 NSWindow* owning_window; | 91 NSWindow* owning_window; // Only one of |owning_...| should be non-NULL. |
| 92 TabContents* owning_tab; |
| 68 }; | 93 }; |
| 69 | 94 |
| 70 private: | 95 private: |
| 96 void NotifyListenerOfFileSelection(bool was_cancelled, |
| 97 bool is_multi, |
| 98 const std::vector<FilePath>& files, |
| 99 int index, |
| 100 void* params); |
| 101 |
| 71 // Gets the accessory view for the save dialog. | 102 // Gets the accessory view for the save dialog. |
| 72 NSView* GetAccessoryView(const FileTypeInfo* file_types, | 103 NSView* GetAccessoryView(const FileTypeInfo* file_types, |
| 73 int file_type_index); | 104 int file_type_index); |
| 74 | 105 |
| 75 // The listener to be notified of selection completion. | 106 // The listener to be notified of selection completion. |
| 76 Listener* listener_; | 107 Listener* listener_; |
| 77 | 108 |
| 78 // The bridge for results from Cocoa to return to us. | 109 // The bridge for results from Cocoa to return to us. |
| 79 scoped_nsobject<SelectFileDialogBridge> bridge_; | 110 scoped_nsobject<SelectFileDialogBridge> bridge_; |
| 80 | 111 |
| 81 // A map from file dialogs to the |params| user data associated with them. | 112 // A map from file dialogs to the |params| user data associated with them. |
| 82 std::map<NSPanel*, void*> params_map_; | 113 std::map<NSPanel*, void*> params_map_; |
| 83 | 114 |
| 115 // A map from dialogs to constrained windows. |
| 116 std::map<NSPanel*, ConstrainedWindow*> window_map_; |
| 117 |
| 84 // The set of all parent windows for which we are currently running dialogs. | 118 // The set of all parent windows for which we are currently running dialogs. |
| 85 std::set<NSWindow*> parents_; | 119 std::set<NSWindow*> parent_windows_; |
| 120 |
| 121 // The set of all parent tabs for which we are currently running sheets. |
| 122 std::set<const TabContents*> parent_tabs_; |
| 86 | 123 |
| 87 DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl); | 124 DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl); |
| 88 }; | 125 }; |
| 89 | 126 |
| 127 // Class to create a select file sheet as a "constrained window" (i.e., sheet |
| 128 // attached to a tab). |
| 129 class SelectFileInTabDelegate |
| 130 : public ConstrainedWindowMacDelegateSystemSheetParams { |
| 131 public: |
| 132 SelectFileInTabDelegate() |
| 133 : ConstrainedWindowMacDelegateSystemSheetParams(nil) { } |
| 134 |
| 135 void InitForSavePanel(NSSavePanel* sheet, |
| 136 SelectFileDialogImpl* s, |
| 137 NSString* directory, |
| 138 NSString* file, |
| 139 void* context) { |
| 140 set_sheet(sheet); |
| 141 // Note: we need NSValue's to guard against |directory|, etc. being nil. |
| 142 NSArray* params = [NSArray arrayWithObjects: |
| 143 [NSValue valueWithPointer:directory], |
| 144 [NSValue valueWithPointer:file], |
| 145 [NSNull null], // window, must be [NSNull null] |
| 146 [[[SelectFileDialogBridge alloc] |
| 147 initWithSelectFileDialogImpl:s] autorelease], |
| 148 [NSValue valueWithPointer:@selector(endedPanel:withReturn:context:)], |
| 149 [NSValue valueWithPointer:context], |
| 150 nil]; |
| 151 set_params(params); |
| 152 } |
| 153 |
| 154 void InitForOpenPanel(NSOpenPanel* sheet, |
| 155 SelectFileDialogImpl* s, |
| 156 NSString* directory, |
| 157 NSString* file, |
| 158 NSArray* file_types, |
| 159 void* context) { |
| 160 set_sheet(sheet); |
| 161 // Note: we need NSValue's to guard against |directory|, etc. being nil. |
| 162 NSArray* params = [NSArray arrayWithObjects: |
| 163 [NSValue valueWithPointer:directory], |
| 164 [NSValue valueWithPointer:file], |
| 165 [NSValue valueWithPointer:file_types], |
| 166 [NSNull null], // window, must be [NSNull null] |
| 167 [[[SelectFileDialogBridge alloc] |
| 168 initWithSelectFileDialogImpl:s] autorelease], |
| 169 [NSValue valueWithPointer:@selector(endedPanel:withReturn:context:)], |
| 170 [NSValue valueWithPointer:context], |
| 171 nil]; |
| 172 set_params(params); |
| 173 } |
| 174 |
| 175 // Implementation of method defined in ConstrainedWindowMacDelegate: |
| 176 virtual void DeleteDelegate() { |
| 177 if (is_sheet_open()) { |
| 178 // Close sheet if it's still open; inform the end-sheet routine that it's |
| 179 // being closed by the delegate, so it can avoid calling |
| 180 // |CloseConstrainedWindow()| (which leads to an attempt to delete us |
| 181 // again). |
| 182 [NSApp endSheet:(NSSavePanel*)sheet() |
| 183 returnCode:kClosedByDelegate]; |
| 184 } |
| 185 delete this; |
| 186 } |
| 187 |
| 188 // Overridden from ConstrainedWindowMacDelegate: |
| 189 virtual bool ParentWillDo(ConstrainedWindow::Event event) { |
| 190 switch(event) { |
| 191 case ConstrainedWindow::kEventNavigate: |
| 192 // We don't want to close! (Note: typically, we *shouldn't* be |
| 193 // navigating during file selection. However, this happens for open file |
| 194 // dialogs run on very new tabs. |
| 195 return true; |
| 196 |
| 197 default: |
| 198 break; |
| 199 } |
| 200 return false; |
| 201 } |
| 202 |
| 203 virtual ConstrainedWindow::ModalityLevel GetModalityLevel() { |
| 204 return ConstrainedWindow::kModalForTab; |
| 205 } |
| 206 |
| 207 // Return value passed to the end-sheet routine to indicate that the sheet was |
| 208 // ended by |DeleteDelegate()|. This just needs to be some value never used by |
| 209 // Apple as a return value for the sheet. |
| 210 static const int kClosedByDelegate = 658042027; |
| 211 }; |
| 212 |
| 90 // static | 213 // static |
| 91 SelectFileDialog* SelectFileDialog::Create(Listener* listener) { | 214 SelectFileDialog* SelectFileDialog::Create(Listener* listener) { |
| 92 return new SelectFileDialogImpl(listener); | 215 return new SelectFileDialogImpl(listener); |
| 93 } | 216 } |
| 94 | 217 |
| 95 SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener) | 218 SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener) |
| 96 : listener_(listener), | 219 : listener_(listener), |
| 97 bridge_([[SelectFileDialogBridge alloc] | 220 bridge_([[SelectFileDialogBridge alloc] |
| 98 initWithSelectFileDialogImpl:this]) { | 221 initWithSelectFileDialogImpl:this]) { |
| 99 } | 222 } |
| 100 | 223 |
| 101 SelectFileDialogImpl::~SelectFileDialogImpl() { | 224 SelectFileDialogImpl::~SelectFileDialogImpl() { |
| 102 } | 225 } |
| 103 | 226 |
| 104 bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow parent_window) const { | 227 bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow parent_window) const { |
| 105 return parents_.find(parent_window) != parents_.end(); | 228 return (parent_windows_.find(parent_window) != parent_windows_.end()); |
| 229 } |
| 230 |
| 231 bool SelectFileDialogImpl::IsRunningInTab(const TabContents* parent_tab) const { |
| 232 return (parent_tabs_.find(parent_tab) != parent_tabs_.end()); |
| 106 } | 233 } |
| 107 | 234 |
| 108 void SelectFileDialogImpl::ListenerDestroyed() { | 235 void SelectFileDialogImpl::ListenerDestroyed() { |
| 109 listener_ = NULL; | 236 listener_ = NULL; |
| 110 } | 237 } |
| 111 | 238 |
| 112 void SelectFileDialogImpl::SelectFile( | 239 void SelectFileDialogImpl::SelectFile( |
| 113 Type type, | 240 Type type, |
| 114 const string16& title, | 241 const string16& title, |
| 115 const FilePath& default_path, | 242 const FilePath& default_path, |
| 116 const FileTypeInfo* file_types, | 243 const FileTypeInfo* file_types, |
| 117 int file_type_index, | 244 int file_type_index, |
| 118 const FilePath::StringType& default_extension, | 245 const FilePath::StringType& default_extension, |
| 119 gfx::NativeWindow owning_window, | 246 gfx::NativeWindow owning_window, |
| 120 void* params) { | 247 void* params) { |
| 121 DCHECK(type == SELECT_FOLDER || | 248 DCHECK(type == SELECT_FOLDER || |
| 122 type == SELECT_OPEN_FILE || | 249 type == SELECT_OPEN_FILE || |
| 123 type == SELECT_OPEN_MULTI_FILE || | 250 type == SELECT_OPEN_MULTI_FILE || |
| 124 type == SELECT_SAVEAS_FILE); | 251 type == SELECT_SAVEAS_FILE); |
| 125 DCHECK(owning_window); | 252 DCHECK(owning_window); //FIXME(viettrungluu@gmail.com): this goes against |
| 126 parents_.insert(owning_window); | 253 // what is explicitly stated in shell_dialogs.h (and |
| 254 // may cause problems)! |
| 255 parent_windows_.insert(owning_window); |
| 127 | 256 |
| 128 NSSavePanel* dialog; | 257 NSSavePanel* dialog; |
| 129 if (type == SELECT_SAVEAS_FILE) | 258 if (type == SELECT_SAVEAS_FILE) |
| 130 dialog = [NSSavePanel savePanel]; | 259 dialog = [NSSavePanel savePanel]; |
| 131 else | 260 else |
| 132 dialog = [NSOpenPanel openPanel]; | 261 dialog = [NSOpenPanel openPanel]; |
| 133 | 262 |
| 134 if (!title.empty()) | 263 if (!title.empty()) |
| 135 [dialog setTitle:base::SysUTF16ToNSString(title)]; | 264 [dialog setTitle:base::SysUTF16ToNSString(title)]; |
| 136 | 265 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 170 } | 299 } |
| 171 | 300 |
| 172 if (!default_extension.empty()) | 301 if (!default_extension.empty()) |
| 173 [dialog setRequiredFileType:base::SysUTF8ToNSString(default_extension)]; | 302 [dialog setRequiredFileType:base::SysUTF8ToNSString(default_extension)]; |
| 174 | 303 |
| 175 params_map_[dialog] = params; | 304 params_map_[dialog] = params; |
| 176 | 305 |
| 177 SheetContext* context = new SheetContext; | 306 SheetContext* context = new SheetContext; |
| 178 context->type = type; | 307 context->type = type; |
| 179 context->owning_window = owning_window; | 308 context->owning_window = owning_window; |
| 309 context->owning_tab = NULL; |
| 180 | 310 |
| 181 if (type == SELECT_SAVEAS_FILE) { | 311 if (type == SELECT_SAVEAS_FILE) { |
| 182 [dialog beginSheetForDirectory:default_dir | 312 [dialog beginSheetForDirectory:default_dir |
| 183 file:default_filename | 313 file:default_filename |
| 184 modalForWindow:owning_window | 314 modalForWindow:owning_window |
| 185 modalDelegate:bridge_.get() | 315 modalDelegate:bridge_.get() |
| 186 didEndSelector:@selector(endedPanel:withReturn:context:) | 316 didEndSelector:@selector(endedPanel:withReturn:context:) |
| 187 contextInfo:context]; | 317 contextInfo:context]; |
| 188 } else { | 318 } else { |
| 189 NSOpenPanel* open_dialog = (NSOpenPanel*)dialog; | 319 NSOpenPanel* open_dialog = (NSOpenPanel*)dialog; |
| 190 | 320 |
| 191 if (type == SELECT_OPEN_MULTI_FILE) | 321 if (type == SELECT_OPEN_MULTI_FILE) |
| 192 [open_dialog setAllowsMultipleSelection:YES]; | 322 [open_dialog setAllowsMultipleSelection:YES]; |
| 193 else | 323 else |
| 194 [open_dialog setAllowsMultipleSelection:NO]; | 324 [open_dialog setAllowsMultipleSelection:NO]; |
| 195 | 325 |
| 196 if (type == SELECT_FOLDER) { | 326 if (type == SELECT_FOLDER) { |
| 197 [open_dialog setCanChooseFiles:NO]; | 327 [open_dialog setCanChooseFiles:NO]; |
| 198 [open_dialog setCanChooseDirectories:YES]; | 328 [open_dialog setCanChooseDirectories:YES]; |
| 199 } else { | 329 } else { |
| 200 [open_dialog setCanChooseFiles:YES]; | 330 [open_dialog setCanChooseFiles:YES]; |
| 201 [open_dialog setCanChooseDirectories:NO]; | 331 [open_dialog setCanChooseDirectories:NO]; |
| 202 } | 332 } |
| 203 | 333 |
| 204 [open_dialog beginSheetForDirectory:default_dir | 334 [open_dialog beginSheetForDirectory:default_dir |
| 205 file:default_filename | 335 file:default_filename |
| 206 types:allowed_file_types | 336 types:allowed_file_types |
| 207 modalForWindow:owning_window | 337 modalForWindow:owning_window |
| 208 modalDelegate:bridge_.get() | 338 modalDelegate:bridge_.get() |
| 209 didEndSelector:@selector(endedPanel:withReturn:context:) | 339 didEndSelector:@selector( |
| 340 endedPanel:withReturn:context:) |
| 210 contextInfo:context]; | 341 contextInfo:context]; |
| 211 } | 342 } |
| 212 } | 343 } |
| 213 | 344 |
| 214 void SelectFileDialogImpl::FileWasSelected(NSPanel* dialog, | 345 void SelectFileDialogImpl::SelectFileInTab( |
| 215 NSWindow* parent_window, | 346 Type type, |
| 216 bool was_cancelled, | 347 const string16& title, |
| 217 bool is_multi, | 348 const FilePath& default_path, |
| 218 const std::vector<FilePath>& files, | 349 const FileTypeInfo* file_types, |
| 219 int index) { | 350 int file_type_index, |
| 351 const FilePath::StringType& default_extension, |
| 352 TabContents* owning_tab, |
| 353 void* params) { |
| 354 // Go modeless if no |owning_tab|. |
| 355 // FIXME(viettrungluu@gmail.com): Despite the docs in shell_dialogs.h, we |
| 356 // don't support this (see the FIXME in SelectFile()). |
| 357 if (!owning_tab) { |
| 358 SelectFile(type, title, default_path, file_types, file_type_index, |
| 359 default_extension, NULL, params); |
| 360 return; |
| 361 } |
| 362 |
| 363 // This shouldn't be needed, but prevents crashing if someone calls us when |
| 364 // there's already a constrained dialog. |
| 365 if (!owning_tab->CanCreateConstrainedDialog()) { |
| 366 // FIXME(viettrungluu@gmail.com): This should be a NOTREACHED(), but it's |
| 367 // annoying to have my browser constantly die. |
| 368 LOG(WARNING) << "Not allowed to create constrained dialog."; |
| 369 |
| 370 // Make sure the listener doesn't hang. |
| 371 if (listener_) |
| 372 listener_->FileSelectionCanceled(params); |
| 373 return; |
| 374 } |
| 375 |
| 376 DCHECK(type == SELECT_FOLDER || |
| 377 type == SELECT_OPEN_FILE || |
| 378 type == SELECT_OPEN_MULTI_FILE || |
| 379 type == SELECT_SAVEAS_FILE); |
| 380 parent_tabs_.insert(owning_tab); |
| 381 |
| 382 NSSavePanel* dialog = (type == SELECT_SAVEAS_FILE) ? [NSSavePanel savePanel] : |
| 383 [NSOpenPanel openPanel]; |
| 384 |
| 385 if (!title.empty()) |
| 386 [dialog setTitle:base::SysUTF16ToNSString(title)]; |
| 387 |
| 388 NSString* default_dir = nil; |
| 389 NSString* default_filename = nil; |
| 390 if (!default_path.empty()) { |
| 391 default_dir = base::SysUTF8ToNSString(default_path.DirName().value()); |
| 392 default_filename = base::SysUTF8ToNSString(default_path.BaseName().value()); |
| 393 } |
| 394 |
| 395 NSMutableArray* allowed_file_types = nil; |
| 396 if (file_types) { |
| 397 if (!file_types->extensions.empty()) { |
| 398 allowed_file_types = [NSMutableArray array]; |
| 399 for (size_t i=0; i < file_types->extensions.size(); ++i) { |
| 400 const std::vector<FilePath::StringType>& ext_list = |
| 401 file_types->extensions[i]; |
| 402 for (size_t j=0; j < ext_list.size(); ++j) { |
| 403 [allowed_file_types addObject:base::SysUTF8ToNSString(ext_list[j])]; |
| 404 } |
| 405 } |
| 406 } |
| 407 if (type == SELECT_SAVEAS_FILE) |
| 408 [dialog setAllowedFileTypes:allowed_file_types]; |
| 409 // else we'll pass it in when we run the open panel |
| 410 |
| 411 if (file_types->include_all_files) |
| 412 [dialog setAllowsOtherFileTypes:YES]; |
| 413 |
| 414 if (!file_types->extension_description_overrides.empty()) { |
| 415 NSView* accessory_view = GetAccessoryView(file_types, file_type_index); |
| 416 [dialog setAccessoryView:accessory_view]; |
| 417 } |
| 418 } else { |
| 419 // If no type info is specified, anything goes. |
| 420 [dialog setAllowsOtherFileTypes:YES]; |
| 421 } |
| 422 |
| 423 if (!default_extension.empty()) |
| 424 [dialog setRequiredFileType:base::SysUTF8ToNSString(default_extension)]; |
| 425 |
| 426 params_map_[dialog] = params; |
| 427 |
| 428 SheetContext* context = new SheetContext; |
| 429 context->type = type; |
| 430 context->owning_window = NULL; |
| 431 context->owning_tab = owning_tab; |
| 432 |
| 433 // It will delete itself when its |DeleteDelegate()| method is called. |
| 434 SelectFileInTabDelegate* delegate = new SelectFileInTabDelegate; |
| 435 DCHECK(delegate); |
| 436 |
| 437 if (type == SELECT_SAVEAS_FILE) { |
| 438 delegate->InitForSavePanel(dialog, |
| 439 this, |
| 440 default_dir, |
| 441 default_filename, |
| 442 context); |
| 443 } else { |
| 444 NSOpenPanel* open_dialog = (NSOpenPanel*)dialog; |
| 445 |
| 446 if (type == SELECT_OPEN_MULTI_FILE) |
| 447 [open_dialog setAllowsMultipleSelection:YES]; |
| 448 else |
| 449 [open_dialog setAllowsMultipleSelection:NO]; |
| 450 |
| 451 if (type == SELECT_FOLDER) { |
| 452 [open_dialog setCanChooseFiles:NO]; |
| 453 [open_dialog setCanChooseDirectories:YES]; |
| 454 } else { |
| 455 [open_dialog setCanChooseFiles:YES]; |
| 456 [open_dialog setCanChooseDirectories:NO]; |
| 457 } |
| 458 |
| 459 delegate->InitForOpenPanel(open_dialog, |
| 460 this, |
| 461 default_dir, |
| 462 default_filename, |
| 463 allowed_file_types, |
| 464 context); |
| 465 } |
| 466 |
| 467 window_map_[dialog] = owning_tab->CreateConstrainedDialog(delegate); |
| 468 } |
| 469 |
| 470 void SelectFileDialogImpl::FileWasSelected( |
| 471 NSPanel* dialog, |
| 472 NSWindow* parent_window, |
| 473 bool was_cancelled, |
| 474 bool is_multi, |
| 475 const std::vector<FilePath>& files, |
| 476 int index) { |
| 220 void* params = params_map_[dialog]; | 477 void* params = params_map_[dialog]; |
| 221 params_map_.erase(dialog); | 478 params_map_.erase(dialog); |
| 222 parents_.erase(parent_window); | 479 parent_windows_.erase(parent_window); |
| 223 | 480 |
| 481 NotifyListenerOfFileSelection(was_cancelled, is_multi, files, index, params); |
| 482 } |
| 483 |
| 484 // The |was_killed| parameter indicates whether or not we need to call |
| 485 // |CloseConstrainedWindow()|. If the dialog was ended by |
| 486 // |CloseConstrainedWindow()|, the delegate then closes the sheet (leading to |
| 487 // this method being called) and deletes itself. |
| 488 void SelectFileDialogImpl::FileWasSelectedInTab( |
| 489 NSPanel* dialog, |
| 490 TabContents* parent_tab, |
| 491 bool was_cancelled, |
| 492 bool was_killed, |
| 493 bool is_multi, |
| 494 const std::vector<FilePath>& files, |
| 495 int index) { |
| 496 void* params = params_map_[dialog]; |
| 497 params_map_.erase(dialog); |
| 498 if (!was_killed) { |
| 499 ConstrainedWindow* window = window_map_[dialog]; |
| 500 window->CloseConstrainedWindow(); |
| 501 } |
| 502 window_map_.erase(dialog); |
| 503 parent_tabs_.erase(parent_tab); |
| 504 |
| 505 NotifyListenerOfFileSelection(was_cancelled, is_multi, files, index, params); |
| 506 } |
| 507 |
| 508 void SelectFileDialogImpl::NotifyListenerOfFileSelection( |
| 509 bool was_cancelled, |
| 510 bool is_multi, |
| 511 const std::vector<FilePath>& files, |
| 512 int index, |
| 513 void* params) { |
| 224 if (!listener_) | 514 if (!listener_) |
| 225 return; | 515 return; |
| 226 | 516 |
| 227 if (was_cancelled) { | 517 if (was_cancelled) { |
| 228 listener_->FileSelectionCanceled(params); | 518 listener_->FileSelectionCanceled(params); |
| 229 } else { | 519 } else { |
| 230 if (is_multi) { | 520 if (is_multi) { |
| 231 listener_->MultiFilesSelected(files, params); | 521 listener_->MultiFilesSelected(files, params); |
| 232 } else { | 522 } else { |
| 233 listener_->FileSelected(files[0], index, params); | 523 listener_->FileSelected(files[0], index, params); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 | 592 |
| 303 - (void)endedPanel:(id)panel | 593 - (void)endedPanel:(id)panel |
| 304 withReturn:(int)returnCode | 594 withReturn:(int)returnCode |
| 305 context:(void *)context { | 595 context:(void *)context { |
| 306 int index = 0; | 596 int index = 0; |
| 307 SelectFileDialogImpl::SheetContext* context_struct = | 597 SelectFileDialogImpl::SheetContext* context_struct = |
| 308 (SelectFileDialogImpl::SheetContext*)context; | 598 (SelectFileDialogImpl::SheetContext*)context; |
| 309 | 599 |
| 310 SelectFileDialog::Type type = context_struct->type; | 600 SelectFileDialog::Type type = context_struct->type; |
| 311 NSWindow* parentWindow = context_struct->owning_window; | 601 NSWindow* parentWindow = context_struct->owning_window; |
| 602 TabContents* parentTab = context_struct->owning_tab; |
| 603 DCHECK(parentWindow || parentTab); |
| 604 DCHECK(!(parentWindow && parentTab)); |
| 312 delete context_struct; | 605 delete context_struct; |
| 313 | 606 |
| 314 bool isMulti = type == SelectFileDialog::SELECT_OPEN_MULTI_FILE; | 607 bool isMulti = type == SelectFileDialog::SELECT_OPEN_MULTI_FILE; |
| 315 | 608 |
| 316 std::vector<FilePath> paths; | 609 std::vector<FilePath> paths; |
| 317 bool did_cancel = returnCode == NSCancelButton; | 610 // The negative check for cancellation covers the NSRun...Response codes. |
| 611 bool did_cancel = (returnCode != NSOKButton); |
| 318 if (!did_cancel) { | 612 if (!did_cancel) { |
| 319 if (type == SelectFileDialog::SELECT_SAVEAS_FILE) { | 613 if (type == SelectFileDialog::SELECT_SAVEAS_FILE) { |
| 320 paths.push_back(FilePath(base::SysNSStringToUTF8([panel filename]))); | 614 paths.push_back(FilePath(base::SysNSStringToUTF8([panel filename]))); |
| 321 | 615 |
| 322 NSView* accessoryView = [panel accessoryView]; | 616 NSView* accessoryView = [panel accessoryView]; |
| 323 if (accessoryView) { | 617 if (accessoryView) { |
| 324 NSPopUpButton* popup = [accessoryView viewWithTag:kFileTypePopupTag]; | 618 NSPopUpButton* popup = [accessoryView viewWithTag:kFileTypePopupTag]; |
| 325 if (popup) { | 619 if (popup) { |
| 326 // File type indexes are 1-based. | 620 // File type indexes are 1-based. |
| 327 index = [popup indexOfSelectedItem] + 1; | 621 index = [popup indexOfSelectedItem] + 1; |
| 328 } | 622 } |
| 329 } else { | 623 } else { |
| 330 index = 1; | 624 index = 1; |
| 331 } | 625 } |
| 332 } else { | 626 } else { |
| 333 NSArray* filenames = [panel filenames]; | 627 NSArray* filenames = [panel filenames]; |
| 334 for (NSString* filename in filenames) | 628 for (NSString* filename in filenames) |
| 335 paths.push_back(FilePath(base::SysNSStringToUTF8(filename))); | 629 paths.push_back(FilePath(base::SysNSStringToUTF8(filename))); |
| 336 } | 630 } |
| 337 } | 631 } |
| 338 | 632 |
| 339 selectFileDialogImpl_->FileWasSelected(panel, | 633 if (parentWindow) { |
| 340 parentWindow, | 634 selectFileDialogImpl_->FileWasSelected(panel, |
| 341 did_cancel, | 635 parentWindow, |
| 342 isMulti, | 636 did_cancel, |
| 343 paths, | 637 isMulti, |
| 344 index); | 638 paths, |
| 639 index); |
| 640 } else { |
| 641 bool was_killed = |
| 642 (returnCode == SelectFileInTabDelegate::kClosedByDelegate); |
| 643 selectFileDialogImpl_->FileWasSelectedInTab(panel, |
| 644 parentTab, |
| 645 did_cancel, |
| 646 was_killed, |
| 647 isMulti, |
| 648 paths, |
| 649 index); |
| 650 } |
| 345 } | 651 } |
| 346 | 652 |
| 347 @end | 653 @end |
| OLD | NEW |