OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/base/dialogs/select_file_dialog.h" | 5 #include "ui/base/dialogs/select_file_dialog.h" |
6 | 6 |
7 #import <Cocoa/Cocoa.h> | 7 #import <Cocoa/Cocoa.h> |
8 #include <CoreServices/CoreServices.h> | 8 #include <CoreServices/CoreServices.h> |
9 | 9 |
10 #include <map> | 10 #include <map> |
(...skipping 30 matching lines...) Expand all Loading... | |
41 | 41 |
42 // A bridge class to act as the modal delegate to the save/open sheet and send | 42 // A bridge class to act as the modal delegate to the save/open sheet and send |
43 // the results to the C++ class. | 43 // the results to the C++ class. |
44 @interface SelectFileDialogBridge : NSObject<NSOpenSavePanelDelegate> { | 44 @interface SelectFileDialogBridge : NSObject<NSOpenSavePanelDelegate> { |
45 @private | 45 @private |
46 SelectFileDialogImpl* selectFileDialogImpl_; // WEAK; owns us | 46 SelectFileDialogImpl* selectFileDialogImpl_; // WEAK; owns us |
47 } | 47 } |
48 | 48 |
49 - (id)initWithSelectFileDialogImpl:(SelectFileDialogImpl*)s; | 49 - (id)initWithSelectFileDialogImpl:(SelectFileDialogImpl*)s; |
50 - (void)endedPanel:(NSSavePanel*)panel | 50 - (void)endedPanel:(NSSavePanel*)panel |
51 withReturn:(int)returnCode | 51 didCancel:(bool)did_cancel |
52 context:(void*)context; | 52 type:(ui::SelectFileDialog::Type)type |
53 parentWindow:(NSWindow*)parentWindow; | |
53 | 54 |
54 // NSSavePanel delegate method | 55 // NSSavePanel delegate method |
55 - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename; | 56 - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename; |
56 | 57 |
57 @end | 58 @end |
58 | 59 |
59 // Implementation of SelectFileDialog that shows Cocoa dialogs for choosing a | 60 // Implementation of SelectFileDialog that shows Cocoa dialogs for choosing a |
60 // file or folder. | 61 // file or folder. |
61 class SelectFileDialogImpl : public ui::SelectFileDialog { | 62 class SelectFileDialogImpl : public ui::SelectFileDialog { |
62 public: | 63 public: |
63 explicit SelectFileDialogImpl(Listener* listener, | 64 explicit SelectFileDialogImpl(Listener* listener, |
64 ui::SelectFilePolicy* policy); | 65 ui::SelectFilePolicy* policy); |
65 | 66 |
66 // BaseShellDialog implementation. | 67 // BaseShellDialog implementation. |
67 virtual bool IsRunning(gfx::NativeWindow parent_window) const; | 68 virtual bool IsRunning(gfx::NativeWindow parent_window) const; |
68 virtual void ListenerDestroyed(); | 69 virtual void ListenerDestroyed(); |
69 | 70 |
70 // Callback from ObjC bridge. | 71 // Callback from ObjC bridge. |
71 void FileWasSelected(NSSavePanel* dialog, | 72 void FileWasSelected(NSSavePanel* dialog, |
72 NSWindow* parent_window, | 73 NSWindow* parent_window, |
73 bool was_cancelled, | 74 bool was_cancelled, |
74 bool is_multi, | 75 bool is_multi, |
75 const std::vector<FilePath>& files, | 76 const std::vector<FilePath>& files, |
76 int index); | 77 int index); |
77 | 78 |
78 bool ShouldEnableFilename(NSSavePanel* dialog, NSString* filename); | 79 bool ShouldEnableFilename(NSSavePanel* dialog, NSString* filename); |
79 | 80 |
80 struct SheetContext { | |
81 Type type; | |
82 NSWindow* owning_window; | |
83 }; | |
84 | |
85 protected: | 81 protected: |
86 // SelectFileDialog implementation. | 82 // SelectFileDialog implementation. |
87 // |params| is user data we pass back via the Listener interface. | 83 // |params| is user data we pass back via the Listener interface. |
88 virtual void SelectFileImpl(Type type, | 84 virtual void SelectFileImpl(Type type, |
89 const string16& title, | 85 const string16& title, |
90 const FilePath& default_path, | 86 const FilePath& default_path, |
91 const FileTypeInfo* file_types, | 87 const FileTypeInfo* file_types, |
92 int file_type_index, | 88 int file_type_index, |
93 const FilePath::StringType& default_extension, | 89 const FilePath::StringType& default_extension, |
94 gfx::NativeWindow owning_window, | 90 gfx::NativeWindow owning_window, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
144 void* params = params_map_[dialog]; | 140 void* params = params_map_[dialog]; |
145 params_map_.erase(dialog); | 141 params_map_.erase(dialog); |
146 parents_.erase(parent_window); | 142 parents_.erase(parent_window); |
147 type_map_.erase(dialog); | 143 type_map_.erase(dialog); |
148 | 144 |
149 [dialog setDelegate:nil]; | 145 [dialog setDelegate:nil]; |
150 | 146 |
151 if (!listener_) | 147 if (!listener_) |
152 return; | 148 return; |
153 | 149 |
154 if (was_cancelled) { | 150 if (was_cancelled || files.empty()) { |
155 listener_->FileSelectionCanceled(params); | 151 listener_->FileSelectionCanceled(params); |
156 } else { | 152 } else { |
157 if (is_multi) { | 153 if (is_multi) { |
158 listener_->MultiFilesSelected(files, params); | 154 listener_->MultiFilesSelected(files, params); |
159 } else { | 155 } else { |
160 listener_->FileSelected(files[0], index, params); | 156 listener_->FileSelected(files[0], index, params); |
161 } | 157 } |
162 } | 158 } |
163 } | 159 } |
164 | 160 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
247 [dialog setAccessoryView:accessory_view]; | 243 [dialog setAccessoryView:accessory_view]; |
248 } | 244 } |
249 } else { | 245 } else { |
250 // If no type info is specified, anything goes. | 246 // If no type info is specified, anything goes. |
251 [dialog setAllowsOtherFileTypes:YES]; | 247 [dialog setAllowsOtherFileTypes:YES]; |
252 } | 248 } |
253 hasMultipleFileTypeChoices_ = | 249 hasMultipleFileTypeChoices_ = |
254 file_types ? file_types->extensions.size() > 1 : true; | 250 file_types ? file_types->extensions.size() > 1 : true; |
255 | 251 |
256 if (!default_extension.empty()) | 252 if (!default_extension.empty()) |
257 [dialog setRequiredFileType:base::SysUTF8ToNSString(default_extension)]; | 253 [dialog setAllowedFileTypes:@[base::SysUTF8ToNSString(default_extension)]]; |
258 | 254 |
259 params_map_[dialog] = params; | 255 params_map_[dialog] = params; |
260 type_map_[dialog] = type; | 256 type_map_[dialog] = type; |
261 | 257 |
262 SheetContext* context = new SheetContext; | |
263 | |
264 // |context| should never be NULL, but we are seeing indications otherwise. | |
265 // This CHECK is here to confirm if we are actually getting NULL | |
266 // |context|s. http://crbug.com/58959 | |
267 CHECK(context); | |
268 context->type = type; | |
269 context->owning_window = owning_window; | |
270 | |
271 if (type == SELECT_SAVEAS_FILE) { | 258 if (type == SELECT_SAVEAS_FILE) { |
272 [dialog setCanSelectHiddenExtension:YES]; | 259 [dialog setCanSelectHiddenExtension:YES]; |
273 [dialog beginSheetForDirectory:default_dir | 260 [dialog setDirectoryURL:[NSURL fileURLWithPath:default_dir]]; |
274 file:default_filename | 261 [dialog setNameFieldStringValue:default_filename]; |
275 modalForWindow:owning_window | 262 [dialog beginSheetModalForWindow:owning_window |
276 modalDelegate:bridge_.get() | 263 completionHandler:^(NSInteger result) { |
277 didEndSelector:@selector(endedPanel:withReturn:context:) | 264 [bridge_.get() endedPanel:dialog |
278 contextInfo:context]; | 265 didCancel:result != NSFileHandlingPanelOKButton |
266 type:type | |
267 parentWindow:owning_window]; | |
268 }]; | |
Avi (use Gerrit)
2012/07/27 14:36:01
This code (from -setDirectoryURL down to here)...
| |
279 } else { | 269 } else { |
280 NSOpenPanel* open_dialog = (NSOpenPanel*)dialog; | 270 NSOpenPanel* open_dialog = (NSOpenPanel*)dialog; |
281 | 271 |
282 if (type == SELECT_OPEN_MULTI_FILE) | 272 if (type == SELECT_OPEN_MULTI_FILE) |
283 [open_dialog setAllowsMultipleSelection:YES]; | 273 [open_dialog setAllowsMultipleSelection:YES]; |
284 else | 274 else |
285 [open_dialog setAllowsMultipleSelection:NO]; | 275 [open_dialog setAllowsMultipleSelection:NO]; |
286 | 276 |
287 if (type == SELECT_FOLDER) { | 277 if (type == SELECT_FOLDER) { |
288 [open_dialog setCanChooseFiles:NO]; | 278 [open_dialog setCanChooseFiles:NO]; |
289 [open_dialog setCanChooseDirectories:YES]; | 279 [open_dialog setCanChooseDirectories:YES]; |
290 [open_dialog setCanCreateDirectories:YES]; | 280 [open_dialog setCanCreateDirectories:YES]; |
291 NSString *prompt = l10n_util::GetNSString(IDS_SELECT_FOLDER_BUTTON_TITLE); | 281 NSString *prompt = l10n_util::GetNSString(IDS_SELECT_FOLDER_BUTTON_TITLE); |
292 [open_dialog setPrompt:prompt]; | 282 [open_dialog setPrompt:prompt]; |
293 } else { | 283 } else { |
294 [open_dialog setCanChooseFiles:YES]; | 284 [open_dialog setCanChooseFiles:YES]; |
295 [open_dialog setCanChooseDirectories:NO]; | 285 [open_dialog setCanChooseDirectories:NO]; |
296 } | 286 } |
297 | 287 |
298 [open_dialog setDelegate:bridge_.get()]; | 288 [open_dialog setDelegate:bridge_.get()]; |
299 [open_dialog beginSheetForDirectory:default_dir | 289 [open_dialog setAllowedFileTypes:allowed_file_types]; |
300 file:default_filename | 290 [open_dialog setDirectoryURL:[NSURL fileURLWithPath:default_dir]]; |
301 types:allowed_file_types | 291 [open_dialog setNameFieldStringValue:default_filename]; |
302 modalForWindow:owning_window | 292 [open_dialog beginSheetModalForWindow:owning_window |
303 modalDelegate:bridge_.get() | 293 completionHandler:^(NSInteger result) { |
304 didEndSelector:@selector(endedPanel:withReturn:context:) | 294 [bridge_.get() endedPanel:dialog |
305 contextInfo:context]; | 295 didCancel:result != NSFileHandlingPanelOKButton |
296 type:type | |
297 parentWindow:owning_window]; | |
298 }]; | |
Avi (use Gerrit)
2012/07/27 14:36:01
...and this code here are identical. Consolidate t
Nico
2012/07/27 14:48:43
Done.
| |
306 } | 299 } |
307 } | 300 } |
308 | 301 |
309 SelectFileDialogImpl::~SelectFileDialogImpl() { | 302 SelectFileDialogImpl::~SelectFileDialogImpl() { |
310 // Walk through the open dialogs and close them all. Use a temporary vector | 303 // Walk through the open dialogs and close them all. Use a temporary vector |
311 // to hold the pointers, since we can't delete from the map as we're iterating | 304 // to hold the pointers, since we can't delete from the map as we're iterating |
312 // through it. | 305 // through it. |
313 std::vector<NSSavePanel*> panels; | 306 std::vector<NSSavePanel*> panels; |
314 for (std::map<NSSavePanel*, void*>::iterator it = params_map_.begin(); | 307 for (std::map<NSSavePanel*, void*>::iterator it = params_map_.begin(); |
315 it != params_map_.end(); ++it) { | 308 it != params_map_.end(); ++it) { |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
367 | 360 |
368 - (id)initWithSelectFileDialogImpl:(SelectFileDialogImpl*)s { | 361 - (id)initWithSelectFileDialogImpl:(SelectFileDialogImpl*)s { |
369 self = [super init]; | 362 self = [super init]; |
370 if (self != nil) { | 363 if (self != nil) { |
371 selectFileDialogImpl_ = s; | 364 selectFileDialogImpl_ = s; |
372 } | 365 } |
373 return self; | 366 return self; |
374 } | 367 } |
375 | 368 |
376 - (void)endedPanel:(NSSavePanel*)panel | 369 - (void)endedPanel:(NSSavePanel*)panel |
377 withReturn:(int)returnCode | 370 didCancel:(bool)did_cancel |
378 context:(void*)context { | 371 type:(ui::SelectFileDialog::Type)type |
379 // |context| should never be NULL, but we are seeing indications otherwise. | 372 parentWindow:(NSWindow*)parentWindow { |
380 // This CHECK is here to confirm if we are actually getting NULL | |
381 // |context|s. http://crbug.com/58959 | |
382 CHECK(context); | |
383 | |
384 int index = 0; | 373 int index = 0; |
385 SelectFileDialogImpl::SheetContext* context_struct = | |
386 (SelectFileDialogImpl::SheetContext*)context; | |
387 | |
388 ui::SelectFileDialog::Type type = context_struct->type; | |
389 NSWindow* parentWindow = context_struct->owning_window; | |
390 delete context_struct; | |
391 | |
392 bool isMulti = type == ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE; | |
393 | |
394 std::vector<FilePath> paths; | 374 std::vector<FilePath> paths; |
395 bool did_cancel = returnCode == NSCancelButton; | |
396 if (!did_cancel) { | 375 if (!did_cancel) { |
397 if (type == ui::SelectFileDialog::SELECT_SAVEAS_FILE) { | 376 if (type == ui::SelectFileDialog::SELECT_SAVEAS_FILE) { |
398 paths.push_back(FilePath(base::SysNSStringToUTF8([panel filename]))); | 377 if ([[panel URL] isFileURL]) |
378 paths.push_back(FilePath(base::SysNSStringToUTF8([[panel URL] path]))); | |
399 | 379 |
400 NSView* accessoryView = [panel accessoryView]; | 380 NSView* accessoryView = [panel accessoryView]; |
401 if (accessoryView) { | 381 if (accessoryView) { |
402 NSPopUpButton* popup = [accessoryView viewWithTag:kFileTypePopupTag]; | 382 NSPopUpButton* popup = [accessoryView viewWithTag:kFileTypePopupTag]; |
403 if (popup) { | 383 if (popup) { |
404 // File type indexes are 1-based. | 384 // File type indexes are 1-based. |
405 index = [popup indexOfSelectedItem] + 1; | 385 index = [popup indexOfSelectedItem] + 1; |
406 } | 386 } |
407 } else { | 387 } else { |
408 index = 1; | 388 index = 1; |
409 } | 389 } |
410 } else { | 390 } else { |
411 CHECK([panel isKindOfClass:[NSOpenPanel class]]); | 391 CHECK([panel isKindOfClass:[NSOpenPanel class]]); |
412 NSArray* filenames = [static_cast<NSOpenPanel*>(panel) filenames]; | 392 NSArray* urls = [static_cast<NSOpenPanel*>(panel) URLs]; |
413 for (NSString* filename in filenames) | 393 for (NSURL* url in urls) |
414 paths.push_back(FilePath(base::SysNSStringToUTF8(filename))); | 394 if ([url isFileURL]) |
395 paths.push_back(FilePath(base::SysNSStringToUTF8([url path]))); | |
415 } | 396 } |
416 } | 397 } |
417 | 398 |
399 bool isMulti = type == ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE; | |
418 selectFileDialogImpl_->FileWasSelected(panel, | 400 selectFileDialogImpl_->FileWasSelected(panel, |
419 parentWindow, | 401 parentWindow, |
420 did_cancel, | 402 did_cancel, |
421 isMulti, | 403 isMulti, |
422 paths, | 404 paths, |
423 index); | 405 index); |
424 [panel release]; | 406 [panel release]; |
425 } | 407 } |
426 | 408 |
427 - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename { | 409 - (BOOL)panel:(id)sender shouldShowFilename:(NSString *)filename { |
428 return selectFileDialogImpl_->ShouldEnableFilename(sender, filename); | 410 return selectFileDialogImpl_->ShouldEnableFilename(sender, filename); |
429 } | 411 } |
430 | 412 |
431 @end | 413 @end |
432 | 414 |
433 namespace ui { | 415 namespace ui { |
434 | 416 |
435 SelectFileDialog* CreateMacSelectFileDialog( | 417 SelectFileDialog* CreateMacSelectFileDialog( |
436 SelectFileDialog::Listener* listener, | 418 SelectFileDialog::Listener* listener, |
437 SelectFilePolicy* policy) { | 419 SelectFilePolicy* policy) { |
438 return new SelectFileDialogImpl(listener, policy); | 420 return new SelectFileDialogImpl(listener, policy); |
439 } | 421 } |
440 | 422 |
441 } // namespace ui | 423 } // namespace ui |
OLD | NEW |