| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 #import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.h" | 5 #import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_controller.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #import "base/mac/bundle_locations.h" | 11 #import "base/mac/bundle_locations.h" |
| 12 #include "base/strings/sys_string_conversions.h" | 12 #include "base/strings/sys_string_conversions.h" |
| 13 #include "chrome/browser/media/combined_desktop_media_list.h" | 13 #include "chrome/browser/media/combined_desktop_media_list.h" |
| 14 #include "chrome/browser/ui/browser_finder.h" | 14 #include "chrome/browser/ui/browser_finder.h" |
| 15 #include "chrome/browser/ui/browser_window.h" | 15 #include "chrome/browser/ui/browser_window.h" |
| 16 #import "chrome/browser/ui/cocoa/key_equivalent_constants.h" | 16 #import "chrome/browser/ui/cocoa/key_equivalent_constants.h" |
| 17 #import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_item.h" | 17 #import "chrome/browser/ui/cocoa/media_picker/desktop_media_picker_item.h" |
| 18 #include "chrome/common/chrome_switches.h" | 18 #include "chrome/common/chrome_switches.h" |
| 19 #include "chrome/grit/chromium_strings.h" |
| 19 #include "chrome/grit/generated_resources.h" | 20 #include "chrome/grit/generated_resources.h" |
| 21 #include "chrome/grit/google_chrome_strings.h" |
| 20 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
| 21 #include "content/public/browser/render_frame_host.h" | 23 #include "content/public/browser/render_frame_host.h" |
| 22 #include "content/public/browser/web_contents.h" | 24 #include "content/public/browser/web_contents.h" |
| 23 #include "content/public/browser/web_contents_delegate.h" | 25 #include "content/public/browser/web_contents_delegate.h" |
| 24 #include "grit/components_strings.h" | 26 #include "grit/components_strings.h" |
| 25 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTw
eaker.h" | 27 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTw
eaker.h" |
| 26 #import "ui/base/cocoa/flipped_view.h" | 28 #import "ui/base/cocoa/flipped_view.h" |
| 27 #import "ui/base/cocoa/window_size_constants.h" | 29 #import "ui/base/cocoa/window_size_constants.h" |
| 28 #include "ui/base/l10n/l10n_util.h" | 30 #include "ui/base/l10n/l10n_util.h" |
| 29 #include "ui/gfx/image/image_skia_util_mac.h" | 31 #include "ui/gfx/image/image_skia_util_mac.h" |
| 30 | 32 |
| 33 using content::DesktopMediaID; |
| 34 |
| 31 namespace { | 35 namespace { |
| 32 | 36 |
| 33 const int kInitialContentWidth = 620; | 37 const CGFloat kInitialContentWidth = 620; |
| 34 const int kMinimumContentWidth = 500; | 38 const CGFloat kMinimumContentWidth = 500; |
| 35 const int kMinimumContentHeight = 390; | 39 const CGFloat kMinimumContentHeight = 390; |
| 36 const int kThumbnailWidth = 150; | 40 const CGFloat kThumbnailWidth = 150; |
| 37 const int kThumbnailHeight = 150; | 41 const CGFloat kThumbnailHeight = 150; |
| 38 const int kFramePadding = 20; | 42 const CGFloat kSingleScreenWidth = 300; |
| 39 const int kControlSpacing = 10; | 43 const CGFloat kSingleScreenHeight = 300; |
| 40 const int kExcessButtonPadding = 6; | 44 const CGFloat kFramePadding = 20; |
| 45 const CGFloat kControlSpacing = 10; |
| 46 const CGFloat kExcessButtonPadding = 6; |
| 47 const CGFloat kRowHeight = 20; |
| 48 const CGFloat kRowWidth = 500; |
| 49 const CGFloat kIconWidth = 20; |
| 50 const CGFloat kPaddedWidth = kInitialContentWidth - (kFramePadding * 2); |
| 51 const CGFloat kFontSize = 13; |
| 52 |
| 53 NSString* const kIconId = @"icon"; |
| 54 NSString* const kTitleId = @"title"; |
| 41 | 55 |
| 42 } // namespace | 56 } // namespace |
| 43 | 57 |
| 44 @interface DesktopMediaPickerController (Private) | 58 @interface DesktopMediaPickerController () |
| 45 | 59 |
| 46 // Populate the window with controls and views. | 60 // Populate the window with controls and views. |
| 47 - (void)initializeContentsWithAppName:(const base::string16&)appName; | 61 - (void)initializeContentsWithAppName:(const base::string16&)appName |
| 62 targetName:(const base::string16&)targetName |
| 63 requestAudio:(bool)requestAudio; |
| 64 |
| 65 // Add |NSSegmentControl| for source type switch. |
| 66 - (void)createTypeButtonAtOrigin:(NSPoint)origin; |
| 67 |
| 68 // Add |IKImageBrowerView| for screen and window source view. |
| 69 // Add |NSTableView| for tab source view. |
| 70 - (void)createSourceViewsAtOrigin:(NSPoint)origin; |
| 71 |
| 72 // Add check box for audio sharing. |
| 73 - (void)createAudioCheckboxAtOrigin:(NSPoint)origin; |
| 74 |
| 75 // Create the share and cancel button. |
| 76 - (void)createActionButtonsAtOrigin:(NSPoint)origin; |
| 48 | 77 |
| 49 // Create a |NSTextField| with label traits given |width|. Frame height is | 78 // Create a |NSTextField| with label traits given |width|. Frame height is |
| 50 // automatically adjusted to fit. | 79 // automatically adjusted to fit. |
| 51 - (NSTextField*)createTextFieldWithText:(NSString*)text | 80 - (NSTextField*)createTextFieldWithText:(NSString*)text |
| 52 frameWidth:(CGFloat)width; | 81 frameWidth:(CGFloat)width; |
| 53 | 82 |
| 54 // Create a button with |title|, with size adjusted to fit. | 83 // Create a button with |title|, with size adjusted to fit. |
| 55 - (NSButton*)createButtonWithTitle:(NSString*)title; | 84 - (NSButton*)createButtonWithTitle:(NSString*)title; |
| 56 | 85 |
| 86 - (IKImageBrowserView*)createImageBrowserWithSize:(NSSize)size; |
| 87 |
| 57 // Report result by invoking |doneCallback_|. The callback is invoked only on | 88 // Report result by invoking |doneCallback_|. The callback is invoked only on |
| 58 // the first call to |reportResult:|. Subsequent calls will be no-ops. | 89 // the first call to |reportResult:|. Subsequent calls will be no-ops. |
| 59 - (void)reportResult:(content::DesktopMediaID)sourceID; | 90 - (void)reportResult:(DesktopMediaID)sourceID; |
| 60 | 91 |
| 61 // Action handlers. | 92 // Action handlers. |
| 62 - (void)sharePressed:(id)sender; | 93 - (void)sharePressed:(id)sender; |
| 63 - (void)cancelPressed:(id)sender; | 94 - (void)cancelPressed:(id)sender; |
| 64 | 95 |
| 96 // Helper functions to get source type, or get data entities based on source |
| 97 // type. |
| 98 - (DesktopMediaID::Type)selectedSourceType; |
| 99 - (DesktopMediaID::Type)sourceTypeForList:(DesktopMediaList*)list; |
| 100 - (DesktopMediaID::Type)sourceTypeForBrowser:(id)browser; |
| 101 - (id)browserViewForType:(DesktopMediaID::Type)sourceType; |
| 102 - (NSMutableArray*)itemSetForType:(DesktopMediaID::Type)sourceType; |
| 103 - (NSInteger)selectedIndexForType:(DesktopMediaID::Type)sourceType; |
| 104 - (void)setTabBrowserIndex:(NSInteger)index; |
| 105 |
| 65 @end | 106 @end |
| 66 | 107 |
| 67 @implementation DesktopMediaPickerController | 108 @implementation DesktopMediaPickerController |
| 68 | 109 |
| 69 - (id)initWithScreenList:(std::unique_ptr<DesktopMediaList>)screen_list | 110 - (id)initWithScreenList:(std::unique_ptr<DesktopMediaList>)screenList |
| 70 windowList:(std::unique_ptr<DesktopMediaList>)window_list | 111 windowList:(std::unique_ptr<DesktopMediaList>)windowList |
| 71 tabList:(std::unique_ptr<DesktopMediaList>)tab_list | 112 tabList:(std::unique_ptr<DesktopMediaList>)tabList |
| 72 parent:(NSWindow*)parent | 113 parent:(NSWindow*)parent |
| 73 callback:(const DesktopMediaPicker::DoneCallback&)callback | 114 callback:(const DesktopMediaPicker::DoneCallback&)callback |
| 74 appName:(const base::string16&)appName | 115 appName:(const base::string16&)appName |
| 75 targetName:(const base::string16&)targetName | 116 targetName:(const base::string16&)targetName |
| 76 requestAudio:(bool)requestAudio { | 117 requestAudio:(bool)requestAudio { |
| 77 const NSUInteger kStyleMask = | 118 const NSUInteger kStyleMask = |
| 78 NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask; | 119 NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask; |
| 79 base::scoped_nsobject<NSWindow> window( | 120 base::scoped_nsobject<NSWindow> window( |
| 80 [[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater | 121 [[NSWindow alloc] initWithContentRect:ui::kWindowSizeDeterminedLater |
| 81 styleMask:kStyleMask | 122 styleMask:kStyleMask |
| 82 backing:NSBackingStoreBuffered | 123 backing:NSBackingStoreBuffered |
| 83 defer:NO]); | 124 defer:NO]); |
| 84 | 125 |
| 85 if ((self = [super initWithWindow:window])) { | 126 if ((self = [super initWithWindow:window])) { |
| 86 [parent addChildWindow:window ordered:NSWindowAbove]; | 127 [parent addChildWindow:window ordered:NSWindowAbove]; |
| 87 [window setDelegate:self]; | 128 [window setDelegate:self]; |
| 129 if (screenList) { |
| 130 screenList_ = std::move(screenList); |
| 131 screenItems_.reset([[NSMutableArray alloc] init]); |
| 132 } |
| 133 |
| 134 if (windowList) { |
| 135 windowList_ = std::move(windowList); |
| 136 windowList_->SetViewDialogWindowId( |
| 137 DesktopMediaID(DesktopMediaID::TYPE_WINDOW, [window windowNumber])); |
| 138 windowItems_.reset([[NSMutableArray alloc] init]); |
| 139 } |
| 140 |
| 141 if (tabList) { |
| 142 tabList_ = std::move(tabList); |
| 143 tabItems_.reset([[NSMutableArray alloc] init]); |
| 144 } |
| 145 |
| 88 [self initializeContentsWithAppName:appName | 146 [self initializeContentsWithAppName:appName |
| 89 targetName:targetName | 147 targetName:targetName |
| 90 requestAudio:requestAudio]; | 148 requestAudio:requestAudio]; |
| 91 std::vector<std::unique_ptr<DesktopMediaList>> media_lists; | 149 doneCallback_ = callback; |
| 92 if (screen_list) | |
| 93 media_lists.push_back(std::move(screen_list)); | |
| 94 | 150 |
| 95 if (window_list) | |
| 96 media_lists.push_back(std::move(window_list)); | |
| 97 | |
| 98 if (tab_list) | |
| 99 media_lists.push_back(std::move(tab_list)); | |
| 100 | |
| 101 if (media_lists.size() > 1) | |
| 102 media_list_.reset(new CombinedDesktopMediaList(media_lists)); | |
| 103 else | |
| 104 media_list_ = std::move(media_lists[0]); | |
| 105 media_list_->SetViewDialogWindowId(content::DesktopMediaID( | |
| 106 content::DesktopMediaID::TYPE_WINDOW, [window windowNumber])); | |
| 107 doneCallback_ = callback; | |
| 108 items_.reset([[NSMutableArray alloc] init]); | |
| 109 bridge_.reset(new DesktopMediaPickerBridge(self)); | 151 bridge_.reset(new DesktopMediaPickerBridge(self)); |
| 110 } | 152 } |
| 111 return self; | 153 return self; |
| 112 } | 154 } |
| 113 | 155 |
| 114 - (void)dealloc { | 156 - (void)dealloc { |
| 115 [shareButton_ setTarget:nil]; | 157 [shareButton_ setTarget:nil]; |
| 116 [cancelButton_ setTarget:nil]; | 158 [cancelButton_ setTarget:nil]; |
| 117 [sourceBrowser_ setDelegate:nil]; | 159 [screenBrowser_ setDelegate:nil]; |
| 118 [sourceBrowser_ setDataSource:nil]; | 160 [screenBrowser_ setDataSource:nil]; |
| 161 [windowBrowser_ setDelegate:nil]; |
| 162 [windowBrowser_ setDataSource:nil]; |
| 163 [tabBrowser_ setDataSource:nil]; |
| 164 [tabBrowser_ setDelegate:nil]; |
| 119 [[self window] close]; | 165 [[self window] close]; |
| 120 [super dealloc]; | 166 [super dealloc]; |
| 121 } | 167 } |
| 122 | 168 |
| 123 - (void)initializeContentsWithAppName:(const base::string16&)appName | 169 - (void)initializeContentsWithAppName:(const base::string16&)appName |
| 124 targetName:(const base::string16&)targetName | 170 targetName:(const base::string16&)targetName |
| 125 requestAudio:(bool)requestAudio { | 171 requestAudio:(bool)requestAudio { |
| 126 // Use flipped coordinates to facilitate manual layout. | 172 // Use flipped coordinates to facilitate manual layout. |
| 127 const CGFloat kPaddedWidth = kInitialContentWidth - (kFramePadding * 2); | |
| 128 base::scoped_nsobject<FlippedView> content( | 173 base::scoped_nsobject<FlippedView> content( |
| 129 [[FlippedView alloc] initWithFrame:NSZeroRect]); | 174 [[FlippedView alloc] initWithFrame:NSZeroRect]); |
| 130 [[self window] setContentView:content]; | 175 [[self window] setContentView:content]; |
| 131 NSPoint origin = NSMakePoint(kFramePadding, kFramePadding); | 176 NSPoint origin = NSMakePoint(kFramePadding, kFramePadding); |
| 132 | 177 |
| 133 // Set the dialog's title. | 178 // Set the dialog's title. |
| 134 NSString* titleText = l10n_util::GetNSStringF( | 179 NSString* titleText = l10n_util::GetNSString(IDS_DESKTOP_MEDIA_PICKER_TITLE); |
| 135 IDS_DESKTOP_MEDIA_PICKER_TITLE_DEPRECATED, appName); | |
| 136 [[self window] setTitle:titleText]; | 180 [[self window] setTitle:titleText]; |
| 137 | 181 |
| 138 // Set the dialog's description. | 182 // Set the dialog's description. |
| 139 NSString* descriptionText; | 183 NSString* descriptionText; |
| 140 if (appName == targetName) { | 184 if (appName == targetName) { |
| 141 descriptionText = l10n_util::GetNSStringF( | 185 descriptionText = l10n_util::GetNSStringF( |
| 142 IDS_DESKTOP_MEDIA_PICKER_TEXT, appName); | 186 IDS_DESKTOP_MEDIA_PICKER_TEXT, appName); |
| 143 } else { | 187 } else { |
| 144 descriptionText = l10n_util::GetNSStringF( | 188 descriptionText = l10n_util::GetNSStringF( |
| 145 IDS_DESKTOP_MEDIA_PICKER_TEXT_DELEGATED, appName, targetName); | 189 IDS_DESKTOP_MEDIA_PICKER_TEXT_DELEGATED, appName, targetName); |
| 146 } | 190 } |
| 147 NSTextField* description = [self createTextFieldWithText:descriptionText | 191 NSTextField* description = [self createTextFieldWithText:descriptionText |
| 148 frameWidth:kPaddedWidth]; | 192 frameWidth:kPaddedWidth]; |
| 149 [description setFrameOrigin:origin]; | 193 [description setFrameOrigin:origin]; |
| 150 [content addSubview:description]; | 194 [content addSubview:description]; |
| 151 origin.y += NSHeight([description frame]) + kControlSpacing; | 195 origin.y += NSHeight([description frame]) + kControlSpacing; |
| 152 | 196 |
| 153 // Create the image browser. | 197 [self createTypeButtonAtOrigin:origin]; |
| 154 sourceBrowser_.reset([[IKImageBrowserView alloc] initWithFrame:NSZeroRect]); | 198 origin.y += NSHeight([sourceTypeControl_ frame]) + kControlSpacing; |
| 155 NSUInteger cellStyle = IKCellsStyleShadowed | IKCellsStyleTitled; | |
| 156 [sourceBrowser_ setDelegate:self]; | |
| 157 [sourceBrowser_ setDataSource:self]; | |
| 158 [sourceBrowser_ setCellsStyleMask:cellStyle]; | |
| 159 [sourceBrowser_ setCellSize:NSMakeSize(kThumbnailWidth, kThumbnailHeight)]; | |
| 160 [sourceBrowser_ setAllowsMultipleSelection:NO]; | |
| 161 | 199 |
| 162 // Create a scroll view to host the image browser. | 200 [self createSourceViewsAtOrigin:origin]; |
| 163 NSRect imageBrowserScrollFrame = NSMakeRect( | 201 origin.y += NSHeight([imageBrowserScroll_ frame]) + kControlSpacing; |
| 164 origin.x, origin.y, kPaddedWidth, 350); | |
| 165 base::scoped_nsobject<NSScrollView> imageBrowserScroll( | |
| 166 [[NSScrollView alloc] initWithFrame:imageBrowserScrollFrame]); | |
| 167 [imageBrowserScroll setHasVerticalScroller:YES]; | |
| 168 [imageBrowserScroll setDocumentView:sourceBrowser_]; | |
| 169 [imageBrowserScroll setBorderType:NSBezelBorder]; | |
| 170 [imageBrowserScroll setAutoresizingMask: | |
| 171 NSViewWidthSizable | NSViewHeightSizable]; | |
| 172 [content addSubview:imageBrowserScroll]; | |
| 173 origin.y += NSHeight(imageBrowserScrollFrame) + kControlSpacing; | |
| 174 | 202 |
| 175 // Create a checkbox for audio sharing. | |
| 176 if (requestAudio) { | 203 if (requestAudio) { |
| 177 audioShareCheckbox_.reset([[NSButton alloc] initWithFrame:NSZeroRect]); | 204 [self createAudioCheckboxAtOrigin:origin]; |
| 178 [audioShareCheckbox_ setFrameOrigin:origin]; | |
| 179 [audioShareCheckbox_ | |
| 180 setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin]; | |
| 181 [audioShareCheckbox_ setButtonType:NSSwitchButton]; | |
| 182 audioShareState_ = NSOnState; | |
| 183 [audioShareCheckbox_ | |
| 184 setTitle:l10n_util::GetNSString(IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE)]; | |
| 185 [audioShareCheckbox_ sizeToFit]; | |
| 186 [audioShareCheckbox_ setEnabled:NO]; | |
| 187 [audioShareCheckbox_ | |
| 188 setToolTip:l10n_util::GetNSString( | |
| 189 IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_TOOLTIP_MAC)]; | |
| 190 [content addSubview:audioShareCheckbox_]; | |
| 191 origin.y += NSHeight([audioShareCheckbox_ frame]) + kControlSpacing; | 205 origin.y += NSHeight([audioShareCheckbox_ frame]) + kControlSpacing; |
| 192 } | 206 } |
| 193 | 207 |
| 208 [self createActionButtonsAtOrigin:origin]; |
| 209 origin.y += |
| 210 kFramePadding + (NSHeight([cancelButton_ frame]) - kExcessButtonPadding); |
| 211 |
| 212 // Resize window to fit. |
| 213 [content setAutoresizesSubviews:NO]; |
| 214 [[self window] setContentSize:NSMakeSize(kInitialContentWidth, origin.y)]; |
| 215 [[self window] setContentMinSize:NSMakeSize(kMinimumContentWidth, |
| 216 kMinimumContentHeight)]; |
| 217 [content setAutoresizesSubviews:YES]; |
| 218 |
| 219 // Initialize the type selection at the first segment. |
| 220 [sourceTypeControl_ setSelected:YES forSegment:0]; |
| 221 [self typeButtonPressed:sourceTypeControl_]; |
| 222 [[self window] |
| 223 makeFirstResponder:[self browserViewForType:[self selectedSourceType]]]; |
| 224 } |
| 225 |
| 226 - (void)createTypeButtonAtOrigin:(NSPoint)origin { |
| 227 // Create segmented button. |
| 228 sourceTypeControl_.reset( |
| 229 [[NSSegmentedControl alloc] initWithFrame:NSZeroRect]); |
| 230 |
| 231 NSInteger segmentCount = |
| 232 (screenList_ ? 1 : 0) + (windowList_ ? 1 : 0) + (tabList_ ? 1 : 0); |
| 233 [sourceTypeControl_ setSegmentCount:segmentCount]; |
| 234 NSInteger segmentIndex = 0; |
| 235 |
| 236 if (screenList_) { |
| 237 [sourceTypeControl_ |
| 238 setLabel:l10n_util::GetNSString( |
| 239 IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_SCREEN) |
| 240 forSegment:segmentIndex]; |
| 241 |
| 242 [[sourceTypeControl_ cell] setTag:DesktopMediaID::TYPE_SCREEN |
| 243 forSegment:segmentIndex]; |
| 244 ++segmentIndex; |
| 245 } |
| 246 |
| 247 if (windowList_) { |
| 248 [sourceTypeControl_ |
| 249 setLabel:l10n_util::GetNSString( |
| 250 IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_WINDOW) |
| 251 forSegment:segmentIndex]; |
| 252 [[sourceTypeControl_ cell] setTag:DesktopMediaID::TYPE_WINDOW |
| 253 forSegment:segmentIndex]; |
| 254 ++segmentIndex; |
| 255 } |
| 256 |
| 257 if (tabList_) { |
| 258 [sourceTypeControl_ setLabel:l10n_util::GetNSString( |
| 259 IDS_DESKTOP_MEDIA_PICKER_SOURCE_TYPE_TAB) |
| 260 forSegment:segmentIndex]; |
| 261 [[sourceTypeControl_ cell] setTag:DesktopMediaID::TYPE_WEB_CONTENTS |
| 262 forSegment:segmentIndex]; |
| 263 } |
| 264 [sourceTypeControl_ setTarget:self]; |
| 265 [sourceTypeControl_ setAction:@selector(typeButtonPressed:)]; |
| 266 |
| 267 [[sourceTypeControl_ cell] setTrackingMode:NSSegmentSwitchTrackingSelectOne]; |
| 268 |
| 269 [[[self window] contentView] addSubview:sourceTypeControl_]; |
| 270 |
| 271 [sourceTypeControl_ sizeToFit]; |
| 272 [sourceTypeControl_ setAutoresizingMask:NSViewMaxXMargin | NSViewMinXMargin]; |
| 273 CGFloat controlWidth = NSWidth([sourceTypeControl_ frame]); |
| 274 CGFloat controlHeight = NSHeight([sourceTypeControl_ frame]); |
| 275 NSRect centerFrame = NSMakeRect((kInitialContentWidth - controlWidth) / 2, |
| 276 origin.y, controlWidth, controlHeight); |
| 277 |
| 278 [sourceTypeControl_ setFrame:NSIntegralRect(centerFrame)]; |
| 279 } |
| 280 |
| 281 - (void)createSourceViewsAtOrigin:(NSPoint)origin { |
| 282 if (screenList_) { |
| 283 screenBrowser_.reset([[self |
| 284 createImageBrowserWithSize:NSMakeSize(kSingleScreenWidth, |
| 285 kSingleScreenHeight)] retain]); |
| 286 } |
| 287 |
| 288 if (windowList_) { |
| 289 windowBrowser_.reset([ |
| 290 [self createImageBrowserWithSize:NSMakeSize(kThumbnailWidth, |
| 291 kThumbnailHeight)] retain]); |
| 292 } |
| 293 |
| 294 if (tabList_) { |
| 295 tabBrowser_.reset([[NSTableView alloc] initWithFrame:NSZeroRect]); |
| 296 [tabBrowser_ setDelegate:self]; |
| 297 [tabBrowser_ setDataSource:self]; |
| 298 [tabBrowser_ setAllowsMultipleSelection:NO]; |
| 299 [tabBrowser_ setRowHeight:kRowHeight]; |
| 300 [tabBrowser_ setDoubleAction:@selector(sharePressed:)]; |
| 301 base::scoped_nsobject<NSTableColumn> iconColumn( |
| 302 [[NSTableColumn alloc] initWithIdentifier:kIconId]); |
| 303 [iconColumn setEditable:NO]; |
| 304 [iconColumn setWidth:kIconWidth]; |
| 305 [tabBrowser_ addTableColumn:iconColumn]; |
| 306 base::scoped_nsobject<NSTableColumn> titleColumn( |
| 307 [[NSTableColumn alloc] initWithIdentifier:kTitleId]); |
| 308 [titleColumn setEditable:NO]; |
| 309 [titleColumn setWidth:kRowWidth]; |
| 310 [tabBrowser_ addTableColumn:titleColumn]; |
| 311 [tabBrowser_ setHeaderView:nil]; |
| 312 } |
| 313 |
| 314 // Create a scroll view to host the image browsers. |
| 315 NSRect imageBrowserScrollFrame = |
| 316 NSMakeRect(origin.x, origin.y, kPaddedWidth, 350); |
| 317 imageBrowserScroll_.reset( |
| 318 [[NSScrollView alloc] initWithFrame:imageBrowserScrollFrame]); |
| 319 [imageBrowserScroll_ setHasVerticalScroller:YES]; |
| 320 [imageBrowserScroll_ setBorderType:NSBezelBorder]; |
| 321 [imageBrowserScroll_ |
| 322 setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; |
| 323 [[[self window] contentView] addSubview:imageBrowserScroll_]; |
| 324 } |
| 325 |
| 326 - (void)createAudioCheckboxAtOrigin:(NSPoint)origin { |
| 327 audioShareCheckbox_.reset([[NSButton alloc] initWithFrame:NSZeroRect]); |
| 328 [audioShareCheckbox_ setFrameOrigin:origin]; |
| 329 [audioShareCheckbox_ setAutoresizingMask:NSViewMaxXMargin | NSViewMinYMargin]; |
| 330 [audioShareCheckbox_ setButtonType:NSSwitchButton]; |
| 331 [audioShareCheckbox_ setState:NSOnState]; |
| 332 [audioShareCheckbox_ |
| 333 setTitle:l10n_util::GetNSString(IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE)]; |
| 334 [audioShareCheckbox_ sizeToFit]; |
| 335 [[[self window] contentView] addSubview:audioShareCheckbox_]; |
| 336 } |
| 337 |
| 338 - (void)createActionButtonsAtOrigin:(NSPoint)origin { |
| 339 FlippedView* content = [[self window] contentView]; |
| 340 |
| 194 // Create the share button. | 341 // Create the share button. |
| 195 shareButton_ = [self createButtonWithTitle:l10n_util::GetNSString( | 342 shareButton_ = |
| 196 IDS_DESKTOP_MEDIA_PICKER_SHARE)]; | 343 [self createButtonWithTitle:l10n_util::GetNSString( |
| 344 IDS_DESKTOP_MEDIA_PICKER_SHARE)]; |
| 197 origin.x = kInitialContentWidth - kFramePadding - | 345 origin.x = kInitialContentWidth - kFramePadding - |
| 198 (NSWidth([shareButton_ frame]) - kExcessButtonPadding); | 346 (NSWidth([shareButton_ frame]) - kExcessButtonPadding); |
| 199 [shareButton_ setEnabled:NO]; | 347 [shareButton_ setEnabled:NO]; |
| 200 [shareButton_ setFrameOrigin:origin]; | 348 [shareButton_ setFrameOrigin:origin]; |
| 201 [shareButton_ setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin]; | 349 [shareButton_ setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin]; |
| 202 [shareButton_ setTarget:self]; | 350 [shareButton_ setTarget:self]; |
| 203 [shareButton_ setKeyEquivalent:kKeyEquivalentReturn]; | 351 [shareButton_ setKeyEquivalent:kKeyEquivalentReturn]; |
| 204 [shareButton_ setAction:@selector(sharePressed:)]; | 352 [shareButton_ setAction:@selector(sharePressed:)]; |
| 205 [content addSubview:shareButton_]; | 353 [content addSubview:shareButton_]; |
| 206 | 354 |
| 207 // Create the cancel button. | 355 // Create the cancel button. |
| 208 cancelButton_ = | 356 cancelButton_ = |
| 209 [self createButtonWithTitle:l10n_util::GetNSString(IDS_CANCEL)]; | 357 [self createButtonWithTitle:l10n_util::GetNSString(IDS_CANCEL)]; |
| 210 origin.x -= kControlSpacing + | 358 origin.x -= kControlSpacing + |
| 211 (NSWidth([cancelButton_ frame]) - (kExcessButtonPadding * 2)); | 359 (NSWidth([cancelButton_ frame]) - (kExcessButtonPadding * 2)); |
| 212 [cancelButton_ setFrameOrigin:origin]; | 360 [cancelButton_ setFrameOrigin:origin]; |
| 213 [cancelButton_ setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin]; | 361 [cancelButton_ setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin]; |
| 214 [cancelButton_ setTarget:self]; | 362 [cancelButton_ setTarget:self]; |
| 215 [cancelButton_ setKeyEquivalent:kKeyEquivalentEscape]; | 363 [cancelButton_ setKeyEquivalent:kKeyEquivalentEscape]; |
| 216 [cancelButton_ setAction:@selector(cancelPressed:)]; | 364 [cancelButton_ setAction:@selector(cancelPressed:)]; |
| 217 [content addSubview:cancelButton_]; | 365 [content addSubview:cancelButton_]; |
| 218 origin.y += kFramePadding + | |
| 219 (NSHeight([cancelButton_ frame]) - kExcessButtonPadding); | |
| 220 | |
| 221 // Resize window to fit. | |
| 222 [[[self window] contentView] setAutoresizesSubviews:NO]; | |
| 223 [[self window] setContentSize:NSMakeSize(kInitialContentWidth, origin.y)]; | |
| 224 [[self window] setContentMinSize: | |
| 225 NSMakeSize(kMinimumContentWidth, kMinimumContentHeight)]; | |
| 226 [[[self window] contentView] setAutoresizesSubviews:YES]; | |
| 227 | |
| 228 // Make sourceBrowser_ get keyboard focus. | |
| 229 [[self window] makeFirstResponder:sourceBrowser_]; | |
| 230 } | 366 } |
| 231 | 367 |
| 368 - (NSTextField*)createTextFieldWithText:(NSString*)text |
| 369 frameWidth:(CGFloat)width { |
| 370 NSRect frame = NSMakeRect(0, 0, width, 1); |
| 371 base::scoped_nsobject<NSTextField> textField( |
| 372 [[NSTextField alloc] initWithFrame:frame]); |
| 373 [textField setEditable:NO]; |
| 374 [textField setSelectable:YES]; |
| 375 [textField setDrawsBackground:NO]; |
| 376 [textField setBezeled:NO]; |
| 377 [textField setStringValue:text]; |
| 378 [textField setFont:[NSFont systemFontOfSize:kFontSize]]; |
| 379 [textField setAutoresizingMask:NSViewWidthSizable]; |
| 380 [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:textField]; |
| 381 return textField.autorelease(); |
| 382 } |
| 383 |
| 384 - (NSButton*)createButtonWithTitle:(NSString*)title { |
| 385 base::scoped_nsobject<NSButton> button( |
| 386 [[NSButton alloc] initWithFrame:NSZeroRect]); |
| 387 [button setButtonType:NSMomentaryPushInButton]; |
| 388 [button setBezelStyle:NSRoundedBezelStyle]; |
| 389 [button setTitle:title]; |
| 390 [GTMUILocalizerAndLayoutTweaker sizeToFitView:button]; |
| 391 return button.autorelease(); |
| 392 } |
| 393 |
| 394 - (IKImageBrowserView*)createImageBrowserWithSize:(NSSize)size { |
| 395 NSUInteger cellStyle = IKCellsStyleShadowed | IKCellsStyleTitled; |
| 396 base::scoped_nsobject<IKImageBrowserView> browser( |
| 397 [[IKImageBrowserView alloc] initWithFrame:NSZeroRect]); |
| 398 [browser setDelegate:self]; |
| 399 [browser setDataSource:self]; |
| 400 [browser setCellsStyleMask:cellStyle]; |
| 401 [browser setCellSize:size]; |
| 402 [browser setAllowsMultipleSelection:NO]; |
| 403 return browser.autorelease(); |
| 404 } |
| 405 |
| 406 #pragma mark Event Actions |
| 407 |
| 232 - (void)showWindow:(id)sender { | 408 - (void)showWindow:(id)sender { |
| 233 // Signal the media_list to start sending thumbnails. |bridge_| is used as the | 409 // Signal the source lists to start sending thumbnails. |bridge_| is used as |
| 234 // observer, and will forward notifications to this object. | 410 // the observer, and will forward notifications to this object. |
| 235 media_list_->SetThumbnailSize(gfx::Size(kThumbnailWidth, kThumbnailHeight)); | 411 if (screenList_) { |
| 236 media_list_->StartUpdating(bridge_.get()); | 412 screenList_->SetThumbnailSize( |
| 413 gfx::Size(kSingleScreenWidth, kSingleScreenHeight)); |
| 414 screenList_->StartUpdating(bridge_.get()); |
| 415 } |
| 416 |
| 417 if (windowList_) { |
| 418 windowList_->SetThumbnailSize(gfx::Size(kThumbnailWidth, kThumbnailHeight)); |
| 419 windowList_->StartUpdating(bridge_.get()); |
| 420 } |
| 421 |
| 422 if (tabList_) { |
| 423 tabList_->SetThumbnailSize(gfx::Size(kIconWidth, kRowHeight)); |
| 424 tabList_->StartUpdating(bridge_.get()); |
| 425 } |
| 237 | 426 |
| 238 [self.window center]; | 427 [self.window center]; |
| 239 [super showWindow:sender]; | 428 [super showWindow:sender]; |
| 240 } | 429 } |
| 241 | 430 |
| 242 - (void)reportResult:(content::DesktopMediaID)sourceID { | 431 - (void)reportResult:(DesktopMediaID)sourceID { |
| 243 if (doneCallback_.is_null()) { | 432 if (doneCallback_.is_null()) { |
| 244 return; | 433 return; |
| 245 } | 434 } |
| 246 | 435 |
| 247 sourceID.audio_share = [audioShareCheckbox_ isEnabled] && | 436 sourceID.audio_share = ![audioShareCheckbox_ isHidden] && |
| 248 [audioShareCheckbox_ state] == NSOnState; | 437 [audioShareCheckbox_ state] == NSOnState; |
| 249 | 438 |
| 250 if (sourceID.type == content::DesktopMediaID::TYPE_WEB_CONTENTS) { | 439 // If the media source is an tab, activate it. |
| 251 // Activate the selected tab and bring the browser window for the selected | 440 if (sourceID.type == DesktopMediaID::TYPE_WEB_CONTENTS) { |
| 252 // tab to the front. | |
| 253 content::WebContents* tab = content::WebContents::FromRenderFrameHost( | 441 content::WebContents* tab = content::WebContents::FromRenderFrameHost( |
| 254 content::RenderFrameHost::FromID( | 442 content::RenderFrameHost::FromID( |
| 255 sourceID.web_contents_id.render_process_id, | 443 sourceID.web_contents_id.render_process_id, |
| 256 sourceID.web_contents_id.main_render_frame_id)); | 444 sourceID.web_contents_id.main_render_frame_id)); |
| 257 if (tab) { | 445 if (tab) { |
| 258 tab->GetDelegate()->ActivateContents(tab); | 446 tab->GetDelegate()->ActivateContents(tab); |
| 259 Browser* browser = chrome::FindBrowserWithWebContents(tab); | 447 Browser* browser = chrome::FindBrowserWithWebContents(tab); |
| 260 if (browser && browser->window()) | 448 if (browser && browser->window()) |
| 261 browser->window()->Activate(); | 449 browser->window()->Activate(); |
| 262 } | 450 } |
| 263 } | 451 } |
| 264 | 452 |
| 265 // Notify the |callback_| asynchronously because it may release the | 453 // Notify the |callback_| asynchronously because it may release the |
| 266 // controller. | 454 // controller. |
| 267 content::BrowserThread::PostTask( | 455 content::BrowserThread::PostTask( |
| 268 content::BrowserThread::UI, FROM_HERE, | 456 content::BrowserThread::UI, FROM_HERE, |
| 269 base::Bind(doneCallback_, sourceID)); | 457 base::Bind(doneCallback_, sourceID)); |
| 270 doneCallback_.Reset(); | 458 doneCallback_.Reset(); |
| 271 } | 459 } |
| 272 | 460 |
| 273 - (void)sharePressed:(id)sender { | 461 - (void)sharePressed:(id)sender { |
| 274 NSIndexSet* indexes = [sourceBrowser_ selectionIndexes]; | 462 DesktopMediaID::Type selectedType = [self selectedSourceType]; |
| 275 NSUInteger selectedIndex = [indexes firstIndex]; | 463 NSMutableArray* items = [self itemSetForType:selectedType]; |
| 276 DesktopMediaPickerItem* item = | 464 NSInteger selectedIndex = [self selectedIndexForType:selectedType]; |
| 277 [items_ objectAtIndex:selectedIndex]; | 465 DesktopMediaPickerItem* item = [items objectAtIndex:selectedIndex]; |
| 278 [self reportResult:[item sourceID]]; | 466 [self reportResult:[item sourceID]]; |
| 279 [self close]; | 467 [self close]; |
| 280 } | 468 } |
| 281 | 469 |
| 282 - (void)cancelPressed:(id)sender { | 470 - (void)cancelPressed:(id)sender { |
| 283 [self reportResult:content::DesktopMediaID()]; | 471 [self reportResult:DesktopMediaID()]; |
| 284 [self close]; | 472 [self close]; |
| 285 } | 473 } |
| 286 | 474 |
| 287 - (NSTextField*)createTextFieldWithText:(NSString*)text | 475 - (void)typeButtonPressed:(id)sender { |
| 288 frameWidth:(CGFloat)width { | 476 DesktopMediaID::Type selectedType = [self selectedSourceType]; |
| 289 NSRect frame = NSMakeRect(0, 0, width, 1); | 477 id browser = [self browserViewForType:selectedType]; |
| 290 base::scoped_nsobject<NSTextField> textField( | 478 |
| 291 [[NSTextField alloc] initWithFrame:frame]); | 479 [audioShareCheckbox_ |
| 292 [textField setEditable:NO]; | 480 setHidden:selectedType != DesktopMediaID::TYPE_WEB_CONTENTS]; |
| 293 [textField setSelectable:YES]; | 481 [imageBrowserScroll_ setDocumentView:browser]; |
| 294 [textField setDrawsBackground:NO]; | 482 |
| 295 [textField setBezeled:NO]; | 483 if (selectedType == DesktopMediaID::TYPE_WEB_CONTENTS) { |
| 296 [textField setStringValue:text]; | 484 NSInteger selectedIndex = [self selectedIndexForType:selectedType]; |
| 297 [textField setFont:[NSFont systemFontOfSize:13]]; | 485 [tabBrowser_ reloadData]; |
| 298 [textField setAutoresizingMask:NSViewWidthSizable]; | 486 [self setTabBrowserIndex:selectedIndex]; |
| 299 [GTMUILocalizerAndLayoutTweaker sizeToFitFixedWidthTextField:textField]; | 487 } else { |
| 300 return textField.autorelease(); | 488 [browser reloadData]; |
| 489 [self imageBrowserSelectionDidChange:browser]; |
| 490 } |
| 301 } | 491 } |
| 302 | 492 |
| 303 - (NSButton*)createButtonWithTitle:(NSString*)title { | 493 #pragma mark Data Retrieve Helper |
| 304 base::scoped_nsobject<NSButton> button( | 494 |
| 305 [[NSButton alloc] initWithFrame:NSZeroRect]); | 495 - (DesktopMediaID::Type)selectedSourceType { |
| 306 [button setButtonType:NSMomentaryPushInButton]; | 496 NSInteger segment = [sourceTypeControl_ selectedSegment]; |
| 307 [button setBezelStyle:NSRoundedBezelStyle]; | 497 return static_cast<DesktopMediaID::Type>( |
| 308 [button setTitle:title]; | 498 [[sourceTypeControl_ cell] tagForSegment:segment]); |
| 309 [GTMUILocalizerAndLayoutTweaker sizeToFitView:button]; | 499 } |
| 310 return button.autorelease(); | 500 |
| 501 - (DesktopMediaID::Type)sourceTypeForList:(DesktopMediaList*)list { |
| 502 if (list == screenList_.get()) |
| 503 return DesktopMediaID::TYPE_SCREEN; |
| 504 if (list == windowList_.get()) |
| 505 return DesktopMediaID::TYPE_WINDOW; |
| 506 return DesktopMediaID::TYPE_WEB_CONTENTS; |
| 507 } |
| 508 |
| 509 - (DesktopMediaID::Type)sourceTypeForBrowser:(id)browser { |
| 510 if (browser == screenBrowser_.get()) |
| 511 return DesktopMediaID::TYPE_SCREEN; |
| 512 if (browser == windowBrowser_.get()) |
| 513 return DesktopMediaID::TYPE_WINDOW; |
| 514 return DesktopMediaID::TYPE_WEB_CONTENTS; |
| 515 } |
| 516 |
| 517 - (id)browserViewForType:(DesktopMediaID::Type)sourceType { |
| 518 switch (sourceType) { |
| 519 case DesktopMediaID::TYPE_SCREEN: |
| 520 return screenBrowser_; |
| 521 case DesktopMediaID::TYPE_WINDOW: |
| 522 return windowBrowser_; |
| 523 case DesktopMediaID::TYPE_WEB_CONTENTS: |
| 524 return tabBrowser_; |
| 525 case DesktopMediaID::TYPE_NONE: |
| 526 NOTREACHED(); |
| 527 return nil; |
| 528 } |
| 529 } |
| 530 |
| 531 - (NSMutableArray*)itemSetForType:(DesktopMediaID::Type)sourceType { |
| 532 switch (sourceType) { |
| 533 case DesktopMediaID::TYPE_SCREEN: |
| 534 return screenItems_; |
| 535 case DesktopMediaID::TYPE_WINDOW: |
| 536 return windowItems_; |
| 537 case DesktopMediaID::TYPE_WEB_CONTENTS: |
| 538 return tabItems_; |
| 539 case DesktopMediaID::TYPE_NONE: |
| 540 NOTREACHED(); |
| 541 return nil; |
| 542 } |
| 543 } |
| 544 |
| 545 - (NSInteger)selectedIndexForType:(DesktopMediaID::Type)sourceType { |
| 546 NSIndexSet* indexes = nil; |
| 547 switch (sourceType) { |
| 548 case DesktopMediaID::TYPE_SCREEN: |
| 549 indexes = [screenBrowser_ selectionIndexes]; |
| 550 break; |
| 551 case DesktopMediaID::TYPE_WINDOW: |
| 552 indexes = [windowBrowser_ selectionIndexes]; |
| 553 break; |
| 554 case DesktopMediaID::TYPE_WEB_CONTENTS: |
| 555 indexes = [tabBrowser_ selectedRowIndexes]; |
| 556 break; |
| 557 case DesktopMediaID::TYPE_NONE: |
| 558 NOTREACHED(); |
| 559 } |
| 560 |
| 561 if ([indexes count] == 0) |
| 562 return -1; |
| 563 return [indexes firstIndex]; |
| 564 } |
| 565 |
| 566 - (void)setTabBrowserIndex:(NSInteger)index { |
| 567 NSIndexSet* indexes; |
| 568 |
| 569 if (index < 0) |
| 570 indexes = [NSIndexSet indexSet]; |
| 571 else |
| 572 indexes = [NSIndexSet indexSetWithIndex:index]; |
| 573 |
| 574 [tabBrowser_ selectRowIndexes:indexes byExtendingSelection:NO]; |
| 311 } | 575 } |
| 312 | 576 |
| 313 #pragma mark NSWindowDelegate | 577 #pragma mark NSWindowDelegate |
| 314 | 578 |
| 315 - (void)windowWillClose:(NSNotification*)notification { | 579 - (void)windowWillClose:(NSNotification*)notification { |
| 316 // Report the result if it hasn't been reported yet. |reportResult:| ensures | 580 // Report the result if it hasn't been reported yet. |reportResult:| ensures |
| 317 // that the result is only reported once. | 581 // that the result is only reported once. |
| 318 [self reportResult:content::DesktopMediaID()]; | 582 [self reportResult:DesktopMediaID()]; |
| 319 | 583 |
| 320 // Remove self from the parent. | 584 // Remove self from the parent. |
| 321 NSWindow* window = [self window]; | 585 NSWindow* window = [self window]; |
| 322 [[window parentWindow] removeChildWindow:window]; | 586 [[window parentWindow] removeChildWindow:window]; |
| 323 } | 587 } |
| 324 | 588 |
| 325 #pragma mark IKImageBrowserDataSource | 589 #pragma mark IKImageBrowserDataSource |
| 326 | 590 |
| 327 - (NSUInteger)numberOfItemsInImageBrowser:(IKImageBrowserView*)browser { | 591 - (NSUInteger)numberOfItemsInImageBrowser:(IKImageBrowserView*)browser { |
| 328 return [items_ count]; | 592 DesktopMediaID::Type sourceType = [self sourceTypeForBrowser:browser]; |
| 593 NSMutableArray* items = [self itemSetForType:sourceType]; |
| 594 return [items count]; |
| 329 } | 595 } |
| 330 | 596 |
| 331 - (id)imageBrowser:(IKImageBrowserView *)browser | 597 - (id)imageBrowser:(IKImageBrowserView*)browser itemAtIndex:(NSUInteger)index { |
| 332 itemAtIndex:(NSUInteger)index { | 598 DesktopMediaID::Type sourceType = [self sourceTypeForBrowser:browser]; |
| 333 return [items_ objectAtIndex:index]; | 599 NSMutableArray* items = [self itemSetForType:sourceType]; |
| 600 return [items objectAtIndex:index]; |
| 334 } | 601 } |
| 335 | 602 |
| 336 #pragma mark IKImageBrowserDelegate | 603 #pragma mark IKImageBrowserDelegate |
| 337 | 604 |
| 338 - (void)imageBrowser:(IKImageBrowserView *)browser | 605 - (void)imageBrowser:(IKImageBrowserView*)browser |
| 339 cellWasDoubleClickedAtIndex:(NSUInteger)index { | 606 cellWasDoubleClickedAtIndex:(NSUInteger)index { |
| 340 DesktopMediaPickerItem* item = [items_ objectAtIndex:index]; | 607 DesktopMediaPickerItem* item; |
| 608 if (browser == screenBrowser_) |
| 609 item = [screenItems_ objectAtIndex:index]; |
| 610 else |
| 611 item = [windowItems_ objectAtIndex:index]; |
| 341 [self reportResult:[item sourceID]]; | 612 [self reportResult:[item sourceID]]; |
| 342 [self close]; | 613 [self close]; |
| 343 } | 614 } |
| 344 | 615 |
| 345 - (void)imageBrowserSelectionDidChange:(IKImageBrowserView*)browser { | 616 - (void)imageBrowserSelectionDidChange:(IKImageBrowserView*)browser { |
| 346 NSIndexSet* indexes = [sourceBrowser_ selectionIndexes]; | 617 DesktopMediaID::Type selectedType = [self selectedSourceType]; |
| 618 NSInteger selectedIndex = [self selectedIndexForType:selectedType]; |
| 619 // Enable or disable the OK button based on whether we have a selection. |
| 620 [shareButton_ setEnabled:(selectedIndex >= 0)]; |
| 621 } |
| 622 |
| 623 #pragma mark NSTableViewDataSource |
| 624 |
| 625 - (NSInteger)numberOfRowsInTableView:(NSTableView*)table { |
| 626 return [tabItems_ count]; |
| 627 } |
| 628 |
| 629 #pragma mark NSTableViewDelegate |
| 630 |
| 631 - (NSView*)tableView:(NSTableView*)table |
| 632 viewForTableColumn:(NSTableColumn*)column |
| 633 row:(NSInteger)rowIndex { |
| 634 if ([[column identifier] isEqualToString:kIconId]) { |
| 635 NSImage* image = [[tabItems_ objectAtIndex:rowIndex] imageRepresentation]; |
| 636 base::scoped_nsobject<NSImageView> iconView( |
| 637 [[table makeViewWithIdentifier:kIconId owner:self] retain]); |
| 638 if (!iconView) { |
| 639 iconView.reset([[NSImageView alloc] |
| 640 initWithFrame:NSMakeRect(0, 0, kIconWidth, kRowWidth)]); |
| 641 [iconView setIdentifier:kIconId]; |
| 642 } |
| 643 [iconView setImage:image]; |
| 644 return iconView.autorelease(); |
| 645 } |
| 646 |
| 647 NSString* string = [[tabItems_ objectAtIndex:rowIndex] imageTitle]; |
| 648 base::scoped_nsobject<NSTextField> titleView( |
| 649 [[table makeViewWithIdentifier:kTitleId owner:self] retain]); |
| 650 if (!titleView) { |
| 651 titleView.reset( |
| 652 [[self createTextFieldWithText:string frameWidth:kMinimumContentWidth] |
| 653 retain]); |
| 654 [titleView setIdentifier:kTitleId]; |
| 655 } else { |
| 656 [titleView setStringValue:string]; |
| 657 } |
| 658 return titleView.autorelease(); |
| 659 } |
| 660 |
| 661 - (void)tableViewSelectionDidChange:(NSNotification*)notification { |
| 662 NSIndexSet* indexes = [tabBrowser_ selectedRowIndexes]; |
| 347 | 663 |
| 348 // Enable or disable the OK button based on whether we have a selection. | 664 // Enable or disable the OK button based on whether we have a selection. |
| 349 [shareButton_ setEnabled:([indexes count] > 0)]; | 665 [shareButton_ setEnabled:([indexes count] > 0)]; |
| 350 | |
| 351 // Enable or disable the checkbox based on whether we can support audio for | |
| 352 // the selected source. | |
| 353 // On Mac, the checkbox will enabled for tab sharing, namely | |
| 354 // TYPE_WEB_CONTENTS. | |
| 355 if ([indexes count] == 0) { | |
| 356 if ([audioShareCheckbox_ isEnabled]) { | |
| 357 [audioShareCheckbox_ setEnabled:NO]; | |
| 358 audioShareState_ = [audioShareCheckbox_ state]; | |
| 359 [audioShareCheckbox_ setState:NSOffState]; | |
| 360 } | |
| 361 [audioShareCheckbox_ | |
| 362 setToolTip:l10n_util::GetNSString( | |
| 363 IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_TOOLTIP_MAC)]; | |
| 364 return; | |
| 365 } | |
| 366 | |
| 367 NSUInteger selectedIndex = [indexes firstIndex]; | |
| 368 DesktopMediaPickerItem* item = [items_ objectAtIndex:selectedIndex]; | |
| 369 switch ([item sourceID].type) { | |
| 370 case content::DesktopMediaID::TYPE_SCREEN: | |
| 371 case content::DesktopMediaID::TYPE_WINDOW: | |
| 372 if ([audioShareCheckbox_ isEnabled]) { | |
| 373 [audioShareCheckbox_ setEnabled:NO]; | |
| 374 audioShareState_ = [audioShareCheckbox_ state]; | |
| 375 [audioShareCheckbox_ setState:NSOffState]; | |
| 376 } | |
| 377 [audioShareCheckbox_ | |
| 378 setToolTip:l10n_util::GetNSString( | |
| 379 IDS_DESKTOP_MEDIA_PICKER_AUDIO_SHARE_TOOLTIP_MAC)]; | |
| 380 break; | |
| 381 case content::DesktopMediaID::TYPE_WEB_CONTENTS: | |
| 382 if (![audioShareCheckbox_ isEnabled]) { | |
| 383 [audioShareCheckbox_ setEnabled:YES]; | |
| 384 [audioShareCheckbox_ setState:audioShareState_]; | |
| 385 } | |
| 386 [audioShareCheckbox_ setToolTip:@""]; | |
| 387 break; | |
| 388 case content::DesktopMediaID::TYPE_NONE: | |
| 389 NOTREACHED(); | |
| 390 } | |
| 391 } | 666 } |
| 392 | 667 |
| 393 #pragma mark DesktopMediaPickerObserver | 668 #pragma mark DesktopMediaPickerObserver |
| 394 | 669 |
| 395 - (void)sourceAddedAtIndex:(int)index { | 670 - (void)sourceAddedForList:(DesktopMediaList*)list atIndex:(int)index { |
| 396 const DesktopMediaList::Source& source = media_list_->GetSource(index); | 671 DesktopMediaID::Type sourceType = [self sourceTypeForList:list]; |
| 672 NSMutableArray* items = [self itemSetForType:sourceType]; |
| 673 id browser = [self browserViewForType:sourceType]; |
| 674 NSInteger selectedIndex = [self selectedIndexForType:sourceType]; |
| 675 if (selectedIndex >= index) |
| 676 ++selectedIndex; |
| 677 |
| 678 const DesktopMediaList::Source& source = list->GetSource(index); |
| 397 NSString* imageTitle = base::SysUTF16ToNSString(source.name); | 679 NSString* imageTitle = base::SysUTF16ToNSString(source.name); |
| 398 base::scoped_nsobject<DesktopMediaPickerItem> item( | 680 base::scoped_nsobject<DesktopMediaPickerItem> item( |
| 399 [[DesktopMediaPickerItem alloc] initWithSourceId:source.id | 681 [[DesktopMediaPickerItem alloc] initWithSourceId:source.id |
| 400 imageUID:++lastImageUID_ | 682 imageUID:++lastImageUID_ |
| 401 imageTitle:imageTitle]); | 683 imageTitle:imageTitle]); |
| 402 [items_ insertObject:item atIndex:index]; | 684 [items insertObject:item atIndex:index]; |
| 403 [sourceBrowser_ reloadData]; | 685 [browser reloadData]; |
| 686 if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS) |
| 687 [self setTabBrowserIndex:selectedIndex]; |
| 404 | 688 |
| 405 NSString* autoselectSource = base::SysUTF8ToNSString( | 689 NSString* autoselectSource = base::SysUTF8ToNSString( |
| 406 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 690 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 407 switches::kAutoSelectDesktopCaptureSource)); | 691 switches::kAutoSelectDesktopCaptureSource)); |
| 408 | 692 |
| 409 if ([autoselectSource isEqualToString:imageTitle]) { | 693 if ([autoselectSource isEqualToString:imageTitle]) { |
| 410 [self reportResult:[item sourceID]]; | 694 [self reportResult:[item sourceID]]; |
| 411 [self close]; | 695 [self close]; |
| 412 } | 696 } |
| 413 } | 697 } |
| 414 | 698 |
| 415 - (void)sourceRemovedAtIndex:(int)index { | 699 - (void)sourceRemovedForList:(DesktopMediaList*)list atIndex:(int)index { |
| 416 if ([[sourceBrowser_ selectionIndexes] containsIndex:index]) { | 700 DesktopMediaID::Type sourceType = [self sourceTypeForList:list]; |
| 701 NSMutableArray* items = [self itemSetForType:sourceType]; |
| 702 id browser = [self browserViewForType:sourceType]; |
| 703 |
| 704 if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS) { |
| 705 NSInteger selectedIndex = [self selectedIndexForType:sourceType]; |
| 706 if (selectedIndex > index) |
| 707 --selectedIndex; |
| 708 else if (selectedIndex == index) |
| 709 selectedIndex = -1; |
| 710 [tabItems_ removeObjectAtIndex:index]; |
| 711 [tabBrowser_ reloadData]; |
| 712 [self setTabBrowserIndex:selectedIndex]; |
| 713 return; |
| 714 } |
| 715 |
| 716 if ([[browser selectionIndexes] containsIndex:index]) { |
| 417 // Selected item was removed. Clear selection. | 717 // Selected item was removed. Clear selection. |
| 418 [sourceBrowser_ setSelectionIndexes:[NSIndexSet indexSet] | 718 [browser setSelectionIndexes:[NSIndexSet indexSet] byExtendingSelection:NO]; |
| 419 byExtendingSelection:FALSE]; | |
| 420 } | 719 } |
| 421 [items_ removeObjectAtIndex:index]; | 720 [items removeObjectAtIndex:index]; |
| 422 [sourceBrowser_ reloadData]; | 721 [browser reloadData]; |
| 423 } | 722 } |
| 424 | 723 |
| 425 - (void)sourceMovedFrom:(int)oldIndex to:(int)newIndex { | 724 - (void)sourceMovedForList:(DesktopMediaList*)list |
| 725 from:(int)oldIndex |
| 726 to:(int)newIndex { |
| 727 DesktopMediaID::Type sourceType = [self sourceTypeForList:list]; |
| 728 NSMutableArray* items = [self itemSetForType:sourceType]; |
| 729 id browser = [self browserViewForType:sourceType]; |
| 730 NSInteger selectedIndex = [self selectedIndexForType:sourceType]; |
| 731 if (selectedIndex > oldIndex && selectedIndex <= newIndex) |
| 732 --selectedIndex; |
| 733 else if (selectedIndex < oldIndex && selectedIndex >= newIndex) |
| 734 ++selectedIndex; |
| 735 else if (selectedIndex == oldIndex) |
| 736 selectedIndex = newIndex; |
| 737 |
| 426 base::scoped_nsobject<DesktopMediaPickerItem> item( | 738 base::scoped_nsobject<DesktopMediaPickerItem> item( |
| 427 [[items_ objectAtIndex:oldIndex] retain]); | 739 [[items objectAtIndex:oldIndex] retain]); |
| 428 [items_ removeObjectAtIndex:oldIndex]; | 740 [items removeObjectAtIndex:oldIndex]; |
| 429 [items_ insertObject:item atIndex:newIndex]; | 741 [items insertObject:item atIndex:newIndex]; |
| 430 [sourceBrowser_ reloadData]; | 742 [browser reloadData]; |
| 743 |
| 744 if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS) |
| 745 [self setTabBrowserIndex:selectedIndex]; |
| 431 } | 746 } |
| 432 | 747 |
| 433 - (void)sourceNameChangedAtIndex:(int)index { | 748 - (void)sourceNameChangedForList:(DesktopMediaList*)list atIndex:(int)index { |
| 434 DesktopMediaPickerItem* item = [items_ objectAtIndex:index]; | 749 DesktopMediaID::Type sourceType = [self sourceTypeForList:list]; |
| 435 const DesktopMediaList::Source& source = media_list_->GetSource(index); | 750 NSMutableArray* items = [self itemSetForType:sourceType]; |
| 751 id browser = [self browserViewForType:sourceType]; |
| 752 NSInteger selectedIndex = [self selectedIndexForType:sourceType]; |
| 753 |
| 754 DesktopMediaPickerItem* item = [items objectAtIndex:index]; |
| 755 const DesktopMediaList::Source& source = list->GetSource(index); |
| 436 [item setImageTitle:base::SysUTF16ToNSString(source.name)]; | 756 [item setImageTitle:base::SysUTF16ToNSString(source.name)]; |
| 437 [sourceBrowser_ reloadData]; | 757 [browser reloadData]; |
| 758 if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS) |
| 759 [self setTabBrowserIndex:selectedIndex]; |
| 438 } | 760 } |
| 439 | 761 |
| 440 - (void)sourceThumbnailChangedAtIndex:(int)index { | 762 - (void)sourceThumbnailChangedForList:(DesktopMediaList*)list |
| 441 const DesktopMediaList::Source& source = media_list_->GetSource(index); | 763 atIndex:(int)index { |
| 764 DesktopMediaID::Type sourceType = [self sourceTypeForList:list]; |
| 765 NSMutableArray* items = [self itemSetForType:sourceType]; |
| 766 id browser = [self browserViewForType:sourceType]; |
| 767 NSInteger selectedIndex = [self selectedIndexForType:sourceType]; |
| 768 |
| 769 const DesktopMediaList::Source& source = list->GetSource(index); |
| 442 NSImage* image = gfx::NSImageFromImageSkia(source.thumbnail); | 770 NSImage* image = gfx::NSImageFromImageSkia(source.thumbnail); |
| 443 | 771 |
| 444 DesktopMediaPickerItem* item = [items_ objectAtIndex:index]; | 772 DesktopMediaPickerItem* item = [items objectAtIndex:index]; |
| 445 [item setImageRepresentation:image]; | 773 [item setImageRepresentation:image]; |
| 446 [sourceBrowser_ reloadData]; | 774 [browser reloadData]; |
| 775 |
| 776 if (sourceType == DesktopMediaID::TYPE_WEB_CONTENTS) |
| 777 [self setTabBrowserIndex:selectedIndex]; |
| 447 } | 778 } |
| 448 | 779 |
| 449 @end // @interface DesktopMediaPickerController | 780 @end // @interface DesktopMediaPickerController |
| OLD | NEW |