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