Chromium Code Reviews| Index: chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm |
| diff --git a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm |
| index 4e8d5c8446a07d4d17c8a1843e8ef204033f5135..801afc5c5907c189d2916e75b534841bd9f16805 100644 |
| --- a/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm |
| +++ b/chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.mm |
| @@ -14,7 +14,9 @@ |
| #import "chrome/browser/ui/cocoa/key_equivalent_constants.h" |
| #import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_item.h" |
| #include "chrome/common/chrome_switches.h" |
| +#include "chrome/grit/chromium_strings.h" |
| #include "chrome/grit/generated_resources.h" |
| +#include "chrome/grit/google_chrome_strings.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/render_frame_host.h" |
| #include "content/public/browser/web_contents.h" |
| @@ -28,21 +30,47 @@ |
| namespace { |
| -const int kInitialContentWidth = 620; |
| -const int kMinimumContentWidth = 500; |
| -const int kMinimumContentHeight = 390; |
| -const int kThumbnailWidth = 150; |
| -const int kThumbnailHeight = 150; |
| -const int kFramePadding = 20; |
| -const int kControlSpacing = 10; |
| -const int kExcessButtonPadding = 6; |
| +const CGFloat kInitialContentWidth = 620; |
| +const CGFloat kMinimumContentWidth = 500; |
| +const CGFloat kMinimumContentHeight = 390; |
| +const CGFloat kThumbnailWidth = 150; |
| +const CGFloat kThumbnailHeight = 150; |
| +const CGFloat kSingleScreenWidth = 300; |
| +const CGFloat kSingleScreenHeight = 300; |
| +const CGFloat kFramePadding = 20; |
| +const CGFloat kControlSpacing = 10; |
| +const CGFloat kExcessButtonPadding = 6; |
| +const CGFloat kRowHeight = 20; |
| +const CGFloat kRowWidth = 500; |
| +const CGFloat kIconWidth = 20; |
| +const CGFloat kPaddedWidth = kInitialContentWidth - (kFramePadding * 2); |
| + |
| +NSString* const kIconId = @"icon"; |
| +NSString* const kTitleId = @"title"; |
| } // namespace |
| -@interface DesktopMediaPickerController (Private) |
| +using content::DesktopMediaID; |
|
tapted
2016/06/23 03:38:14
nit: this typically comes immediately after the #i
qiangchen
2016/06/23 17:49:37
Done.
|
| + |
| +@interface DesktopMediaPickerController () |
| // Populate the window with controls and views. |
| -- (void)initializeContentsWithAppName:(const base::string16&)appName; |
| +- (void)initializeContentsWithAppName:(const base::string16&)appName |
| + targetName:(const base::string16&)targetName |
| + requestAudio:(bool)requestAudio; |
| + |
| +// Add |NSSegmentControl| for source type switch. |
| +- (void)createTypeButtonAtOrigin:(NSPoint)origin; |
| + |
| +// Add |IKImageBrowerView| for screen and window source view. |
| +// Add |NSTableView| for tab source view. |
| +- (void)createSourceViewsAtOrigin:(NSPoint)origin; |
| + |
| +// Add check box for audio sharing. |
| +- (void)createAudioCheckboxAtOrigin:(NSPoint)origin; |
| + |
| +// Create the share and cancel button. |
| +- (void)createActionButtonsAtOrigin:(NSPoint)origin; |
| // Create a |NSTextField| with label traits given |width|. Frame height is |
| // automatically adjusted to fit. |
| @@ -52,21 +80,33 @@ const int kExcessButtonPadding = 6; |
| // Create a button with |title|, with size adjusted to fit. |
| - (NSButton*)createButtonWithTitle:(NSString*)title; |
| +- (IKImageBrowserView*)createImageBrowserWithSize:(NSSize)size; |
| + |
| // Report result by invoking |doneCallback_|. The callback is invoked only on |
| // the first call to |reportResult:|. Subsequent calls will be no-ops. |
| -- (void)reportResult:(content::DesktopMediaID)sourceID; |
| +- (void)reportResult:(DesktopMediaID)sourceID; |
| // Action handlers. |
| - (void)sharePressed:(id)sender; |
| - (void)cancelPressed:(id)sender; |
| +// Helper functions to get source type, or get data entities based on source |
| +// type. |
| +- (DesktopMediaID::Type)selectedSourceType; |
| +- (DesktopMediaID::Type)sourceTypeForList:(DesktopMediaList*)list; |
| +- (DesktopMediaID::Type)sourceTypeForBrowser:(id)browser; |
| +- (id)browserViewForType:(DesktopMediaID::Type)sourceType; |
| +- (NSMutableArray*)itemSetForType:(DesktopMediaID::Type)sourceType; |
| +- (NSInteger)selectedIndexForType:(DesktopMediaID::Type)sourceType; |
| +- (void)setTabBrowserIndex:(NSInteger)index; |
| + |
| @end |
| @implementation DesktopMediaPickerController |
| -- (id)initWithScreenList:(std::unique_ptr<DesktopMediaList>)screen_list |
| - windowList:(std::unique_ptr<DesktopMediaList>)window_list |
| - tabList:(std::unique_ptr<DesktopMediaList>)tab_list |
| +- (id)initWithScreenList:(std::unique_ptr<DesktopMediaList>)screenList |
| + windowList:(std::unique_ptr<DesktopMediaList>)windowList |
| + tabList:(std::unique_ptr<DesktopMediaList>)tabList |
| parent:(NSWindow*)parent |
| callback:(const DesktopMediaPicker::DoneCallback&)callback |
| appName:(const base::string16&)appName |
| @@ -83,27 +123,28 @@ const int kExcessButtonPadding = 6; |
| if ((self = [super initWithWindow:window])) { |
| [parent addChildWindow:window ordered:NSWindowAbove]; |
| [window setDelegate:self]; |
| + if (screenList) { |
| + screenList_ = std::move(screenList); |
| + screenItems_.reset([[NSMutableArray alloc] init]); |
| + } |
| + |
| + if (windowList) { |
| + windowList_ = std::move(windowList); |
| + windowList_->SetViewDialogWindowId( |
| + DesktopMediaID(DesktopMediaID::TYPE_WINDOW, [window windowNumber])); |
| + windowItems_.reset([[NSMutableArray alloc] init]); |
| + } |
| + |
| + if (tabList) { |
| + tabList_ = std::move(tabList); |
| + tabItems_.reset([[NSMutableArray alloc] init]); |
| + } |
| + |
| [self initializeContentsWithAppName:appName |
| targetName:targetName |
| requestAudio:requestAudio]; |
| - std::vector<std::unique_ptr<DesktopMediaList>> media_lists; |
| - if (screen_list) |
| - media_lists.push_back(std::move(screen_list)); |
| - |
| - if (window_list) |
| - media_lists.push_back(std::move(window_list)); |
| - |
| - if (tab_list) |
| - media_lists.push_back(std::move(tab_list)); |
| - |
| - if (media_lists.size() > 1) |
| - media_list_.reset(new CombinedDesktopMediaList(media_lists)); |
| - else |
| - media_list_ = std::move(media_lists[0]); |
| - media_list_->SetViewDialogWindowId(content::DesktopMediaID( |
| - content::DesktopMediaID::TYPE_WINDOW, [window windowNumber])); |
| doneCallback_ = callback; |
| - items_.reset([[NSMutableArray alloc] init]); |
| + |
| bridge_.reset(new DesktopMediaPickerBridge(self)); |
| } |
| return self; |
| @@ -112,8 +153,12 @@ const int kExcessButtonPadding = 6; |
| - (void)dealloc { |
| [shareButton_ setTarget:nil]; |
| [cancelButton_ setTarget:nil]; |
| - [sourceBrowser_ setDelegate:nil]; |
| - [sourceBrowser_ setDataSource:nil]; |
| + [screenBrowser_ setDelegate:nil]; |
| + [screenBrowser_ setDataSource:nil]; |
| + [windowBrowser_ setDelegate:nil]; |
| + [windowBrowser_ setDataSource:nil]; |
| + [tabBrowser_ setDataSource:nil]; |
| + [tabBrowser_ setDelegate:nil]; |
| [[self window] close]; |
| [super dealloc]; |
| } |
| @@ -122,15 +167,13 @@ const int kExcessButtonPadding = 6; |
| targetName:(const base::string16&)targetName |
| requestAudio:(bool)requestAudio { |
| // Use flipped coordinates to facilitate manual layout. |
| - const CGFloat kPaddedWidth = kInitialContentWidth - (kFramePadding * 2); |
| base::scoped_nsobject<FlippedView> content( |
| [[FlippedView alloc] initWithFrame:NSZeroRect]); |
| [[self window] setContentView:content]; |
| NSPoint origin = NSMakePoint(kFramePadding, kFramePadding); |
| // Set the dialog's title. |
| - NSString* titleText = l10n_util::GetNSStringF( |
| - IDS_DESKTOP_MEDIA_PICKER_TITLE_DEPRECATED, appName); |
| + NSString* titleText = l10n_util::GetNSString(IDS_DESKTOP_MEDIA_PICKER_TITLE); |
| [[self window] setTitle:titleText]; |
| // Set the dialog's description. |
| @@ -148,52 +191,155 @@ const int kExcessButtonPadding = 6; |
| [content addSubview:description]; |
| origin.y += NSHeight([description frame]) + kControlSpacing; |
| - // Create the image browser. |
| - sourceBrowser_.reset([[IKImageBrowserView alloc] initWithFrame:NSZeroRect]); |
| - NSUInteger cellStyle = IKCellsStyleShadowed | IKCellsStyleTitled; |
| - [sourceBrowser_ setDelegate:self]; |
| - [sourceBrowser_ setDataSource:self]; |
| - [sourceBrowser_ setCellsStyleMask:cellStyle]; |
| - [sourceBrowser_ setCellSize:NSMakeSize(kThumbnailWidth, kThumbnailHeight)]; |
| - [sourceBrowser_ setAllowsMultipleSelection:NO]; |
| - |
| - // Create a scroll view to host the image browser. |
| - NSRect imageBrowserScrollFrame = NSMakeRect( |
| - origin.x, origin.y, kPaddedWidth, 350); |
| - base::scoped_nsobject<NSScrollView> imageBrowserScroll( |
| - [[NSScrollView alloc] initWithFrame:imageBrowserScrollFrame]); |
| - [imageBrowserScroll setHasVerticalScroller:YES]; |
| - [imageBrowserScroll setDocumentView:sourceBrowser_]; |
| - [imageBrowserScroll setBorderType:NSBezelBorder]; |
| - [imageBrowserScroll setAutoresizingMask: |
| - NSViewWidthSizable | NSViewHeightSizable]; |
| - [content addSubview:imageBrowserScroll]; |
| - origin.y += NSHeight(imageBrowserScrollFrame) + kControlSpacing; |
| - |
| - // Create a checkbox for audio sharing. |
| + [self createTypeButtonAtOrigin:origin]; |
| + origin.y += NSHeight([sourceTypeControl_ frame]) + kControlSpacing; |
| + |
| + [self createSourceViewsAtOrigin:origin]; |
| + origin.y += NSHeight([imageBrowserScroll_ frame]) + kControlSpacing; |
| + |
| if (requestAudio) { |
| - audioShareCheckbox_.reset([[NSButton alloc] initWithFrame:NSZeroRect]); |
| - [audioShareCheckbox_ setFrameOrigin:origin]; |
| - [audioShareCheckbox_ |
| - setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin]; |
| - [audioShareCheckbox_ setButtonType:NSSwitchButton]; |
| - audioShareState_ = NSOnState; |
| - [audioShareCheckbox_ |
| - setTitle:l10n_util::GetNSString(IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE)]; |
| - [audioShareCheckbox_ sizeToFit]; |
| - [audioShareCheckbox_ setEnabled:NO]; |
| - [audioShareCheckbox_ |
| - setToolTip:l10n_util::GetNSString( |
| - IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_TOOLTIP_MAC)]; |
| - [content addSubview:audioShareCheckbox_]; |
| + [self createAudioCheckboxAtOrigin:origin]; |
| origin.y += NSHeight([audioShareCheckbox_ frame]) + kControlSpacing; |
| } |
| + [self createActionButtonsAtOrigin:origin]; |
| + origin.y += |
| + kFramePadding + (NSHeight([cancelButton_ frame]) - kExcessButtonPadding); |
| + |
| + // Resize window to fit. |
| + [content setAutoresizesSubviews:NO]; |
| + [[self window] setContentSize:NSMakeSize(kInitialContentWidth, origin.y)]; |
| + [[self window] setContentMinSize:NSMakeSize(kMinimumContentWidth, |
| + kMinimumContentHeight)]; |
| + [content setAutoresizesSubviews:YES]; |
| + |
| + // Initialize the type selection at the first segment. |
| + [sourceTypeControl_ setSelected:YES forSegment:0]; |
| + [self typeButtonPressed:sourceTypeControl_]; |
| + [[self window] |
| + makeFirstResponder:[self browserViewForType:[self selectedSourceType]]]; |
| +} |
| + |
| +- (void)createTypeButtonAtOrigin:(NSPoint)origin { |
| + FlippedView* content = [[self window] contentView]; |
| + // Create segmented button. |
| + sourceTypeControl_.reset([[NSSegmentedControl alloc] init]); |
|
tapted
2016/06/23 03:38:15
nit: initWthFrame:NSZeroRect (to invoke the desig
qiangchen
2016/06/23 17:49:38
Done.
|
| + |
| + NSInteger segmentCount = |
| + (screenList_ ? 1 : 0) + (windowList_ ? 1 : 0) + (tabList_ ? 1 : 0); |
| + [sourceTypeControl_ setSegmentCount:segmentCount]; |
| + NSInteger segmentIndex = 0; |
| + |
| + if (screenList_) { |
| + [sourceTypeControl_ |
| + setLabel:l10n_util::GetNSString( |
| + IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_SCREEN) |
| + forSegment:segmentIndex]; |
| + |
| + [[sourceTypeControl_ cell] setTag:DesktopMediaID::TYPE_SCREEN |
| + forSegment:segmentIndex]; |
| + ++segmentIndex; |
| + } |
| + |
| + if (windowList_) { |
| + [sourceTypeControl_ |
| + setLabel:l10n_util::GetNSString( |
| + IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_WINDOW) |
| + forSegment:segmentIndex]; |
| + [[sourceTypeControl_ cell] setTag:DesktopMediaID::TYPE_WINDOW |
| + forSegment:segmentIndex]; |
| + ++segmentIndex; |
| + } |
| + |
| + if (tabList_) { |
| + [sourceTypeControl_ setLabel:l10n_util::GetNSString( |
| + IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_TAB) |
| + forSegment:segmentIndex]; |
| + [[sourceTypeControl_ cell] setTag:DesktopMediaID::TYPE_WEB_CONTENTS |
| + forSegment:segmentIndex]; |
| + } |
| + [sourceTypeControl_ setAction:@selector(typeButtonPressed:)]; |
| + |
| + [[sourceTypeControl_ cell] setTrackingMode:NSSegmentSwitchTrackingSelectOne]; |
| + |
| + [content addSubview:sourceTypeControl_]; |
|
tapted
2016/06/23 03:38:14
nit: just make this [[self window] contentView] ad
qiangchen
2016/06/23 17:49:37
Done.
|
| + |
| + [sourceTypeControl_ sizeToFit]; |
| + [sourceTypeControl_ setAutoresizingMask:NSViewMaxXMargin | NSViewMinXMargin]; |
| + CGFloat controlWidth = NSWidth([sourceTypeControl_ frame]); |
| + CGFloat controlHeight = NSHeight([sourceTypeControl_ frame]); |
| + NSRect centerFrame = NSMakeRect((kInitialContentWidth - controlWidth) / 2, |
| + origin.y, controlWidth, controlHeight); |
| + |
| + [sourceTypeControl_ setFrame:NSIntegralRect(centerFrame)]; |
| +} |
| + |
| +- (void)createSourceViewsAtOrigin:(NSPoint)origin { |
| + if (screenList_) { |
| + screenBrowser_.reset( |
|
tapted
2016/06/23 02:49:48
the scoped_nsobject constructor, and reset, expect
qiangchen
2016/06/23 17:49:37
Done.
|
| + [self createImageBrowserWithSize:NSMakeSize(kSingleScreenWidth, |
| + kSingleScreenHeight)]); |
| + } |
| + |
| + if (windowList_) { |
| + windowBrowser_.reset( |
| + [self createImageBrowserWithSize:NSMakeSize(kThumbnailWidth, |
| + kThumbnailHeight)]); |
| + } |
| + |
| + if (tabList_) { |
| + tabBrowser_.reset([[NSTableView alloc] initWithFrame:NSZeroRect]); |
| + [tabBrowser_ setDelegate:self]; |
| + [tabBrowser_ setDataSource:self]; |
| + [tabBrowser_ setAllowsMultipleSelection:NO]; |
| + [tabBrowser_ setRowHeight:kRowHeight]; |
| + [tabBrowser_ setDoubleAction:@selector(sharePressed:)]; |
| + base::scoped_nsobject<NSTableColumn> iconColumn( |
| + [[NSTableColumn alloc] initWithIdentifier:kIconId]); |
| + [iconColumn setEditable:NO]; |
| + [iconColumn setWidth:kIconWidth]; |
| + [tabBrowser_ addTableColumn:iconColumn]; |
| + base::scoped_nsobject<NSTableColumn> titleColumn( |
| + [[NSTableColumn alloc] initWithIdentifier:kTitleId]); |
| + [titleColumn setEditable:NO]; |
| + [titleColumn setWidth:kRowWidth]; |
| + [tabBrowser_ addTableColumn:titleColumn]; |
| + [tabBrowser_ setHeaderView:nil]; |
| + } |
| + |
| + // Create a scroll view to host the image browsers. |
| + NSRect imageBrowserScrollFrame = |
| + NSMakeRect(origin.x, origin.y, kPaddedWidth, 350); |
| + imageBrowserScroll_.reset( |
| + [[NSScrollView alloc] initWithFrame:imageBrowserScrollFrame]); |
| + [imageBrowserScroll_ setHasVerticalScroller:YES]; |
| + [imageBrowserScroll_ setBorderType:NSBezelBorder]; |
| + [imageBrowserScroll_ |
| + setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; |
| + [[[self window] contentView] addSubview:imageBrowserScroll_]; |
| +} |
| + |
| +- (void)createAudioCheckboxAtOrigin:(NSPoint)origin { |
| + audioShareCheckbox_.reset([[NSButton alloc] initWithFrame:NSZeroRect]); |
| + [audioShareCheckbox_ setFrameOrigin:origin]; |
| + [audioShareCheckbox_ setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin]; |
| + [audioShareCheckbox_ setButtonType:NSSwitchButton]; |
| + [audioShareCheckbox_ setState:NSOnState]; |
| + [audioShareCheckbox_ |
| + setTitle:l10n_util::GetNSString(IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE)]; |
| + [audioShareCheckbox_ sizeToFit]; |
| + [[[self window] contentView] addSubview:audioShareCheckbox_]; |
| +} |
| + |
| +- (void)createActionButtonsAtOrigin:(NSPoint)origin { |
| + FlippedView* content = [[self window] contentView]; |
| + |
| // Create the share button. |
| - shareButton_ = [self createButtonWithTitle:l10n_util::GetNSString( |
| - IDS_DESKTOP_MEDIA_PICKER_SHARE)]; |
| + shareButton_ = |
| + [self createButtonWithTitle:l10n_util::GetNSString( |
| + IDS_DESKTOP_MEDIA_PICKER_SHARE)]; |
| origin.x = kInitialContentWidth - kFramePadding - |
| - (NSWidth([shareButton_ frame]) - kExcessButtonPadding); |
| + (NSWidth([shareButton_ frame]) - kExcessButtonPadding); |
| [shareButton_ setEnabled:NO]; |
| [shareButton_ setFrameOrigin:origin]; |
| [shareButton_ setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin]; |
| @@ -206,47 +352,88 @@ const int kExcessButtonPadding = 6; |
| cancelButton_ = |
| [self createButtonWithTitle:l10n_util::GetNSString(IDS_CANCEL)]; |
| origin.x -= kControlSpacing + |
| - (NSWidth([cancelButton_ frame]) - (kExcessButtonPadding * 2)); |
| + (NSWidth([cancelButton_ frame]) - (kExcessButtonPadding * 2)); |
| [cancelButton_ setFrameOrigin:origin]; |
| [cancelButton_ setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin]; |
| [cancelButton_ setTarget:self]; |
| [cancelButton_ setKeyEquivalent:kKeyEquivalentEscape]; |
| [cancelButton_ setAction:@selector(cancelPressed:)]; |
| [content addSubview:cancelButton_]; |
| - origin.y += kFramePadding + |
| - (NSHeight([cancelButton_ frame]) - kExcessButtonPadding); |
| +} |
| - // Resize window to fit. |
| - [[[self window] contentView] setAutoresizesSubviews:NO]; |
| - [[self window] setContentSize:NSMakeSize(kInitialContentWidth, origin.y)]; |
| - [[self window] setContentMinSize: |
| - NSMakeSize(kMinimumContentWidth, kMinimumContentHeight)]; |
| - [[[self window] contentView] setAutoresizesSubviews:YES]; |
| +- (NSTextField*)createTextFieldWithText:(NSString*)text |
| + frameWidth:(CGFloat)width { |
| + NSRect frame = NSMakeRect(0, 0, width, 1); |
| + base::scoped_nsobject<NSTextField> textField( |
| + [[NSTextField alloc] initWithFrame:frame]); |
| + [textField setEditable:NO]; |
| + [textField setSelectable:YES]; |
| + [textField setDrawsBackground:NO]; |
| + [textField setBezeled:NO]; |
| + [textField setStringValue:text]; |
| + [textField setFont:[NSFont systemFontOfSize:13]]; |
|
tapted
2016/06/23 03:38:14
nit: 13 should be a constant, if it's coming from
qiangchen
2016/06/23 17:49:38
Done.
Actually this is the existing code.
As we h
|
| + [textField setAutoresizingMask:NSViewWidthSizable]; |
| + [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:textField]; |
| + return textField.autorelease(); |
| +} |
| + |
| +- (NSButton*)createButtonWithTitle:(NSString*)title { |
| + base::scoped_nsobject<NSButton> button( |
| + [[NSButton alloc] initWithFrame:NSZeroRect]); |
| + [button setButtonType:NSMomentaryPushInButton]; |
| + [button setBezelStyle:NSRoundedBezelStyle]; |
| + [button setTitle:title]; |
| + [GTMUILocalizerAndLayoutTweaker sizeToFitView:button]; |
| + return button.autorelease(); |
| +} |
| - // Make sourceBrowser_ get keyboard focus. |
| - [[self window] makeFirstResponder:sourceBrowser_]; |
| +- (IKImageBrowserView*)createImageBrowserWithSize:(NSSize)size { |
| + NSUInteger cellStyle = IKCellsStyleShadowed | IKCellsStyleTitled; |
| + IKImageBrowserView* browser = |
|
tapted
2016/06/23 02:49:48
Use scoped_nsobject and autorelease - it should be
qiangchen
2016/06/23 17:49:37
Done.
|
| + [[IKImageBrowserView alloc] initWithFrame:NSZeroRect]; |
| + [browser setDelegate:self]; |
| + [browser setDataSource:self]; |
| + [browser setCellsStyleMask:cellStyle]; |
| + [browser setCellSize:size]; |
| + [browser setAllowsMultipleSelection:NO]; |
| + return browser; |
| } |
| +#pragma mark Event Actions |
| + |
| - (void)showWindow:(id)sender { |
| - // Signal the media_list to start sending thumbnails. |bridge_| is used as the |
| - // observer, and will forward notifications to this object. |
| - media_list_->SetThumbnailSize(gfx::Size(kThumbnailWidth, kThumbnailHeight)); |
| - media_list_->StartUpdating(bridge_.get()); |
| + // Signal the source lists to start sending thumbnails. |bridge_| is used as |
| + // the observer, and will forward notifications to this object. |
| + if (screenList_) { |
| + screenList_->SetThumbnailSize( |
| + gfx::Size(kSingleScreenWidth, kSingleScreenHeight)); |
| + screenList_->StartUpdating(bridge_.get()); |
| + } |
| + |
| + if (windowList_) { |
| + windowList_->SetThumbnailSize(gfx::Size(kThumbnailWidth, kThumbnailHeight)); |
| + windowList_->StartUpdating(bridge_.get()); |
| + } |
| + |
| + if (tabList_) { |
| + tabList_->SetThumbnailSize(gfx::Size(kIconWidth, kRowHeight)); |
| + tabList_->StartUpdating(bridge_.get()); |
| + } |
| [self.window center]; |
| [super showWindow:sender]; |
| } |
| -- (void)reportResult:(content::DesktopMediaID)sourceID { |
| +- (void)reportResult:(DesktopMediaID)sourceID { |
| if (doneCallback_.is_null()) { |
| return; |
| } |
| - sourceID.audio_share = [audioShareCheckbox_ isEnabled] && |
| + sourceID.audio_share = ![audioShareCheckbox_ isHidden] && |
| [audioShareCheckbox_ state] == NSOnState; |
| // If the media source is an tab, activate it. |
| - if (sourceID.type == content::DesktopMediaID::TYPE_WEB_CONTENTS) { |
| + if (sourceID.type == DesktopMediaID::TYPE_WEB_CONTENTS) { |
| content::WebContents* tab = content::WebContents::FromRenderFrameHost( |
| content::RenderFrameHost::FromID( |
| sourceID.web_contents_id.render_process_id, |
| @@ -264,43 +451,119 @@ const int kExcessButtonPadding = 6; |
| } |
| - (void)sharePressed:(id)sender { |
| - NSIndexSet* indexes = [sourceBrowser_ selectionIndexes]; |
| - NSUInteger selectedIndex = [indexes firstIndex]; |
| - DesktopMediaPickerItem* item = |
| - [items_ objectAtIndex:selectedIndex]; |
| + DesktopMediaID::Type selectedType = [self selectedSourceType]; |
| + NSMutableArray* items = [self itemSetForType:selectedType]; |
| + NSInteger selectedIndex = [self selectedIndexForType:selectedType]; |
| + DesktopMediaPickerItem* item = [items objectAtIndex:selectedIndex]; |
| [self reportResult:[item sourceID]]; |
| [self close]; |
| } |
| - (void)cancelPressed:(id)sender { |
| - [self reportResult:content::DesktopMediaID()]; |
| + [self reportResult:DesktopMediaID()]; |
| [self close]; |
| } |
| -- (NSTextField*)createTextFieldWithText:(NSString*)text |
| - frameWidth:(CGFloat)width { |
| - NSRect frame = NSMakeRect(0, 0, width, 1); |
| - base::scoped_nsobject<NSTextField> textField( |
| - [[NSTextField alloc] initWithFrame:frame]); |
| - [textField setEditable:NO]; |
| - [textField setSelectable:YES]; |
| - [textField setDrawsBackground:NO]; |
| - [textField setBezeled:NO]; |
| - [textField setStringValue:text]; |
| - [textField setFont:[NSFont systemFontOfSize:13]]; |
| - [textField setAutoresizingMask:NSViewWidthSizable]; |
| - [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:textField]; |
| - return textField.autorelease(); |
| +- (void)typeButtonPressed:(id)sender { |
| + DesktopMediaID::Type selectedType = [self selectedSourceType]; |
| + id browser = [self browserViewForType:selectedType]; |
| + |
| + [audioShareCheckbox_ |
| + setHidden:selectedType != DesktopMediaID::TYPE_WEB_CONTENTS]; |
| + [imageBrowserScroll_ setDocumentView:browser]; |
| + |
| + if (selectedType == DesktopMediaID::TYPE_WEB_CONTENTS) { |
| + NSInteger selectedIndex = [self selectedIndexForType:selectedType]; |
| + [tabBrowser_ reloadData]; |
| + [self setTabBrowserIndex:selectedIndex]; |
| + } else { |
| + [browser reloadData]; |
| + [self imageBrowserSelectionDidChange:browser]; |
| + } |
| } |
| -- (NSButton*)createButtonWithTitle:(NSString*)title { |
| - base::scoped_nsobject<NSButton> button( |
| - [[NSButton alloc] initWithFrame:NSZeroRect]); |
| - [button setButtonType:NSMomentaryPushInButton]; |
| - [button setBezelStyle:NSRoundedBezelStyle]; |
| - [button setTitle:title]; |
| - [GTMUILocalizerAndLayoutTweaker sizeToFitView:button]; |
| - return button.autorelease(); |
| +#pragma mark Data Retrieve Helper |
| + |
| +- (DesktopMediaID::Type)selectedSourceType { |
| + NSInteger segment = [sourceTypeControl_ selectedSegment]; |
| + return static_cast<DesktopMediaID::Type>( |
| + [[sourceTypeControl_ cell] tagForSegment:segment]); |
| +} |
| + |
| +- (DesktopMediaID::Type)sourceTypeForList:(DesktopMediaList*)list { |
| + if (list == screenList_.get()) |
| + return DesktopMediaID::TYPE_SCREEN; |
| + if (list == windowList_.get()) |
| + return DesktopMediaID::TYPE_WINDOW; |
| + return DesktopMediaID::TYPE_WEB_CONTENTS; |
| +} |
| + |
| +- (DesktopMediaID::Type)sourceTypeForBrowser:(id)browser { |
| + if (browser == screenBrowser_.get()) |
| + return DesktopMediaID::TYPE_SCREEN; |
| + if (browser == windowBrowser_.get()) |
| + return DesktopMediaID::TYPE_WINDOW; |
| + return DesktopMediaID::TYPE_WEB_CONTENTS; |
| +} |
| + |
| +- (id)browserViewForType:(DesktopMediaID::Type)sourceType { |
| + switch (sourceType) { |
| + case DesktopMediaID::TYPE_SCREEN: |
| + return screenBrowser_; |
| + case DesktopMediaID::TYPE_WINDOW: |
| + return windowBrowser_; |
| + case DesktopMediaID::TYPE_WEB_CONTENTS: |
| + return tabBrowser_; |
| + case DesktopMediaID::TYPE_NONE: |
| + NOTREACHED(); |
| + return nil; |
| + } |
| +} |
| + |
| +- (NSMutableArray*)itemSetForType:(DesktopMediaID::Type)sourceType { |
| + switch (sourceType) { |
| + case DesktopMediaID::TYPE_SCREEN: |
| + return screenItems_; |
| + case DesktopMediaID::TYPE_WINDOW: |
| + return windowItems_; |
| + case DesktopMediaID::TYPE_WEB_CONTENTS: |
| + return tabItems_; |
| + case DesktopMediaID::TYPE_NONE: |
| + NOTREACHED(); |
| + return nil; |
| + } |
| +} |
| + |
| +- (NSInteger)selectedIndexForType:(DesktopMediaID::Type)sourceType { |
| + NSIndexSet* indexes = nil; |
| + switch (sourceType) { |
| + case DesktopMediaID::TYPE_SCREEN: |
| + indexes = [screenBrowser_ selectionIndexes]; |
| + break; |
| + case DesktopMediaID::TYPE_WINDOW: |
| + indexes = [windowBrowser_ selectionIndexes]; |
| + break; |
| + case DesktopMediaID::TYPE_WEB_CONTENTS: |
| + indexes = [tabBrowser_ selectedRowIndexes]; |
| + break; |
| + case DesktopMediaID::TYPE_NONE: |
| + NOTREACHED(); |
| + } |
| + |
| + if ([indexes count] == 0) |
| + return -1; |
| + return [indexes firstIndex]; |
| +} |
| + |
| +- (void)setTabBrowserIndex:(NSInteger)index { |
| + NSIndexSet* indexes; |
| + |
| + if (index < 0) |
| + indexes = [NSIndexSet indexSet]; |
| + else |
| + indexes = [NSIndexSet indexSetWithIndex:index]; |
| + |
| + [tabBrowser_ selectRowIndexes:indexes byExtendingSelection:NO]; |
| } |
| #pragma mark NSWindowDelegate |
| @@ -308,7 +571,7 @@ const int kExcessButtonPadding = 6; |
| - (void)windowWillClose:(NSNotification*)notification { |
| // Report the result if it hasn't been reported yet. |reportResult:| ensures |
| // that the result is only reported once. |
| - [self reportResult:content::DesktopMediaID()]; |
| + [self reportResult:DesktopMediaID()]; |
| // Remove self from the parent. |
| NSWindow* window = [self window]; |
| @@ -318,82 +581,101 @@ const int kExcessButtonPadding = 6; |
| #pragma mark IKImageBrowserDataSource |
| - (NSUInteger)numberOfItemsInImageBrowser:(IKImageBrowserView*)browser { |
| - return [items_ count]; |
| + DesktopMediaID::Type sourceType = [self sourceTypeForBrowser:browser]; |
| + NSMutableArray* items = [self itemSetForType:sourceType]; |
| + return [items count]; |
| } |
| -- (id)imageBrowser:(IKImageBrowserView *)browser |
| - itemAtIndex:(NSUInteger)index { |
| - return [items_ objectAtIndex:index]; |
| +- (id)imageBrowser:(IKImageBrowserView*)browser itemAtIndex:(NSUInteger)index { |
| + DesktopMediaID::Type sourceType = [self sourceTypeForBrowser:browser]; |
| + NSMutableArray* items = [self itemSetForType:sourceType]; |
| + return [items objectAtIndex:index]; |
| } |
| #pragma mark IKImageBrowserDelegate |
| -- (void)imageBrowser:(IKImageBrowserView *)browser |
| - cellWasDoubleClickedAtIndex:(NSUInteger)index { |
| - DesktopMediaPickerItem* item = [items_ objectAtIndex:index]; |
| +- (void)imageBrowser:(IKImageBrowserView*)browser |
| + cellWasDoubleClickedAtIndex:(NSUInteger)index { |
| + DesktopMediaPickerItem* item; |
| + if (browser == screenBrowser_) |
| + item = [screenItems_ objectAtIndex:index]; |
| + else |
| + item = [windowItems_ objectAtIndex:index]; |
| [self reportResult:[item sourceID]]; |
| [self close]; |
| } |
| - (void)imageBrowserSelectionDidChange:(IKImageBrowserView*)browser { |
| - NSIndexSet* indexes = [sourceBrowser_ selectionIndexes]; |
| - |
| + DesktopMediaID::Type selectedType = [self selectedSourceType]; |
| + NSInteger selectedIndex = [self selectedIndexForType:selectedType]; |
| // Enable or disable the OK button based on whether we have a selection. |
| - [shareButton_ setEnabled:([indexes count] > 0)]; |
| + [shareButton_ setEnabled:(selectedIndex >= 0)]; |
| +} |
| + |
| +#pragma mark NSTableViewDataSource |
| + |
| +- (NSInteger)numberOfRowsInTableView:(NSTableView*)table { |
| + return [tabItems_ count]; |
| +} |
| - // Enable or disable the checkbox based on whether we can support audio for |
| - // the selected source. |
| - // On Mac, the checkbox will enabled for tab sharing, namely |
| - // TYPE_WEB_CONTENTS. |
| - if ([indexes count] == 0) { |
| - if ([audioShareCheckbox_ isEnabled]) { |
| - [audioShareCheckbox_ setEnabled:NO]; |
| - audioShareState_ = [audioShareCheckbox_ state]; |
| - [audioShareCheckbox_ setState:NSOffState]; |
| +#pragma mark NSTableViewDelegate |
| + |
| +- (NSView*)tableView:(NSTableView*)table |
| + viewForTableColumn:(NSTableColumn*)column |
| + row:(NSInteger)rowIndex { |
| + if ([[column identifier] isEqualToString:kIconId]) { |
| + NSImage* image = [[tabItems_ objectAtIndex:rowIndex] imageRepresentation]; |
| + NSImageView* iconView = [ |
| + [[table makeViewWithIdentifier:kIconId owner:self] retain] autorelease]; |
| + if (!iconView) { |
| + iconView = [[[NSImageView alloc] |
|
tapted
2016/06/23 02:49:48
things should always be `alloced` into a scoped_ns
qiangchen
2016/06/23 17:49:37
Acknowledged.
|
| + initWithFrame:NSMakeRect(0, 0, kIconWidth, kRowWidth)] autorelease]; |
| + [iconView setIdentifier:kIconId]; |
| } |
| - [audioShareCheckbox_ |
| - setToolTip:l10n_util::GetNSString( |
| - IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_TOOLTIP_MAC)]; |
| - return; |
| + [iconView setImage:image]; |
| + return iconView; |
| } |
| - NSUInteger selectedIndex = [indexes firstIndex]; |
| - DesktopMediaPickerItem* item = [items_ objectAtIndex:selectedIndex]; |
| - switch ([item sourceID].type) { |
| - case content::DesktopMediaID::TYPE_SCREEN: |
| - case content::DesktopMediaID::TYPE_WINDOW: |
| - if ([audioShareCheckbox_ isEnabled]) { |
| - [audioShareCheckbox_ setEnabled:NO]; |
| - audioShareState_ = [audioShareCheckbox_ state]; |
| - [audioShareCheckbox_ setState:NSOffState]; |
| - } |
| - [audioShareCheckbox_ |
| - setToolTip:l10n_util::GetNSString( |
| - IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_TOOLTIP_MAC)]; |
| - break; |
| - case content::DesktopMediaID::TYPE_WEB_CONTENTS: |
| - if (![audioShareCheckbox_ isEnabled]) { |
| - [audioShareCheckbox_ setEnabled:YES]; |
| - [audioShareCheckbox_ setState:audioShareState_]; |
| - } |
| - [audioShareCheckbox_ setToolTip:@""]; |
| - break; |
| - case content::DesktopMediaID::TYPE_NONE: |
| - NOTREACHED(); |
| + NSString* string = [[tabItems_ objectAtIndex:rowIndex] imageTitle]; |
| + NSTextField* titleView = |
|
tapted
2016/06/23 02:49:48
so removing scoped_nsobject here is OK, since noth
qiangchen
2016/06/23 17:49:37
Done.
|
| + [[[table makeViewWithIdentifier:kTitleId owner:self] retain] autorelease]; |
|
tapted
2016/06/23 02:49:48
but here the retain] autorelease] does nothing. Th
qiangchen
2016/06/23 17:49:38
Done.
|
| + if (!titleView) { |
| + titleView = |
| + [self createTextFieldWithText:string frameWidth:kMinimumContentWidth]; |
| + [titleView setIdentifier:kTitleId]; |
| + } else { |
| + [titleView setStringValue:string]; |
| } |
| + return titleView; |
| +} |
| + |
| +- (void)tableViewSelectionDidChange:(NSNotification*)notification { |
| + NSIndexSet* indexes = [tabBrowser_ selectedRowIndexes]; |
| + |
| + // Enable or disable the OK button based on whether we have a selection. |
| + [shareButton_ setEnabled:([indexes count] > 0)]; |
| } |
| #pragma mark DesktopMediaPickerObserver |
| -- (void)sourceAddedAtIndex:(int)index { |
| - const DesktopMediaList::Source& source = media_list_->GetSource(index); |
| +- (void)sourceAddedForList:(DesktopMediaList*)list atIndex:(int)index { |
| + DesktopMediaID::Type sourceType = [self sourceTypeForList:list]; |
| + NSMutableArray* items = [self itemSetForType:sourceType]; |
| + id browser = [self browserViewForType:sourceType]; |
| + NSInteger selectedIndex = [self selectedIndexForType:sourceType]; |
| + if (selectedIndex >= index) |
| + ++selectedIndex; |
| + |
| + const DesktopMediaList::Source& source = list->GetSource(index); |
| NSString* imageTitle = base::SysUTF16ToNSString(source.name); |
| base::scoped_nsobject<DesktopMediaPickerItem> item( |
| [[DesktopMediaPickerItem alloc] initWithSourceId:source.id |
| imageUID:++lastImageUID_ |
| imageTitle:imageTitle]); |
| - [items_ insertObject:item atIndex:index]; |
| - [sourceBrowser_ reloadData]; |
| + [items insertObject:item atIndex:index]; |
| + [browser reloadData]; |
| + if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS) |
| + [self setTabBrowserIndex:selectedIndex]; |
| NSString* autoselectSource = base::SysUTF8ToNSString( |
| base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| @@ -405,38 +687,85 @@ const int kExcessButtonPadding = 6; |
| } |
| } |
| -- (void)sourceRemovedAtIndex:(int)index { |
| - if ([[sourceBrowser_ selectionIndexes] containsIndex:index]) { |
| +- (void)sourceRemovedForList:(DesktopMediaList*)list atIndex:(int)index { |
| + DesktopMediaID::Type sourceType = [self sourceTypeForList:list]; |
| + NSMutableArray* items = [self itemSetForType:sourceType]; |
| + id browser = [self browserViewForType:sourceType]; |
| + |
| + if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS) { |
| + NSInteger selectedIndex = [self selectedIndexForType:sourceType]; |
| + if (selectedIndex > index) |
| + --selectedIndex; |
| + else if (selectedIndex == index) |
| + selectedIndex = -1; |
| + [tabItems_ removeObjectAtIndex:index]; |
| + [tabBrowser_ reloadData]; |
| + [self setTabBrowserIndex:selectedIndex]; |
| + return; |
| + } |
| + |
| + if ([[browser selectionIndexes] containsIndex:index]) { |
| // Selected item was removed. Clear selection. |
| - [sourceBrowser_ setSelectionIndexes:[NSIndexSet indexSet] |
| - byExtendingSelection:FALSE]; |
| + [browser setSelectionIndexes:[NSIndexSet indexSet] byExtendingSelection:NO]; |
| } |
| - [items_ removeObjectAtIndex:index]; |
| - [sourceBrowser_ reloadData]; |
| + [items removeObjectAtIndex:index]; |
| + [browser reloadData]; |
| } |
| -- (void)sourceMovedFrom:(int)oldIndex to:(int)newIndex { |
| +- (void)sourceMovedForList:(DesktopMediaList*)list |
| + from:(int)oldIndex |
| + to:(int)newIndex { |
| + DesktopMediaID::Type sourceType = [self sourceTypeForList:list]; |
| + NSMutableArray* items = [self itemSetForType:sourceType]; |
| + id browser = [self browserViewForType:sourceType]; |
| + NSInteger selectedIndex = [self selectedIndexForType:sourceType]; |
| + if (selectedIndex > oldIndex && selectedIndex <= newIndex) |
| + --selectedIndex; |
| + else if (selectedIndex < oldIndex && selectedIndex >= newIndex) |
| + ++selectedIndex; |
| + else if (selectedIndex == oldIndex) |
| + selectedIndex = newIndex; |
| + |
| base::scoped_nsobject<DesktopMediaPickerItem> item( |
| - [[items_ objectAtIndex:oldIndex] retain]); |
| - [items_ removeObjectAtIndex:oldIndex]; |
| - [items_ insertObject:item atIndex:newIndex]; |
| - [sourceBrowser_ reloadData]; |
| + [[items objectAtIndex:oldIndex] retain]); |
| + [items removeObjectAtIndex:oldIndex]; |
| + [items insertObject:item atIndex:newIndex]; |
| + [browser reloadData]; |
| + |
| + if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS) |
| + [self setTabBrowserIndex:selectedIndex]; |
| } |
| -- (void)sourceNameChangedAtIndex:(int)index { |
| - DesktopMediaPickerItem* item = [items_ objectAtIndex:index]; |
| - const DesktopMediaList::Source& source = media_list_->GetSource(index); |
| +- (void)sourceNameChangedForList:(DesktopMediaList*)list atIndex:(int)index { |
| + DesktopMediaID::Type sourceType = [self sourceTypeForList:list]; |
| + NSMutableArray* items = [self itemSetForType:sourceType]; |
| + id browser = [self browserViewForType:sourceType]; |
| + NSInteger selectedIndex = [self selectedIndexForType:sourceType]; |
| + |
| + DesktopMediaPickerItem* item = [items objectAtIndex:index]; |
| + const DesktopMediaList::Source& source = list->GetSource(index); |
| [item setImageTitle:base::SysUTF16ToNSString(source.name)]; |
| - [sourceBrowser_ reloadData]; |
| + [browser reloadData]; |
| + if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS) |
| + [self setTabBrowserIndex:selectedIndex]; |
| } |
| -- (void)sourceThumbnailChangedAtIndex:(int)index { |
| - const DesktopMediaList::Source& source = media_list_->GetSource(index); |
| +- (void)sourceThumbnailChangedForList:(DesktopMediaList*)list |
| + atIndex:(int)index { |
| + DesktopMediaID::Type sourceType = [self sourceTypeForList:list]; |
| + NSMutableArray* items = [self itemSetForType:sourceType]; |
| + id browser = [self browserViewForType:sourceType]; |
| + NSInteger selectedIndex = [self selectedIndexForType:sourceType]; |
| + |
| + const DesktopMediaList::Source& source = list->GetSource(index); |
| NSImage* image = gfx::NSImageFromImageSkia(source.thumbnail); |
| - DesktopMediaPickerItem* item = [items_ objectAtIndex:index]; |
| + DesktopMediaPickerItem* item = [items objectAtIndex:index]; |
| [item setImageRepresentation:image]; |
| - [sourceBrowser_ reloadData]; |
| + [browser reloadData]; |
| + |
| + if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS) |
| + [self setTabBrowserIndex:selectedIndex]; |
| } |
| @end // @interface DesktopMediaPickerController |