Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(491)

Side by Side Diff: chrome/browser/ui/cocoa/website_settings/chooser_bubble_ui_cocoa.mm

Issue 1473393003: Add chooser permission UI code for Mac (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@wpu_1
Patch Set: updated code to calculate width for table column Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #import "chrome/browser/ui/cocoa/website_settings/chooser_bubble_ui_cocoa.h"
6
7 #include <algorithm>
8 #include <cmath>
9 #include <vector>
10
11 #include "base/mac/scoped_nsobject.h"
12 #include "base/strings/sys_string_conversions.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_finder.h"
16 #include "chrome/browser/ui/browser_window.h"
17 #import "chrome/browser/ui/chrome_style.h"
18 #import "chrome/browser/ui/cocoa/base_bubble_controller.h"
19 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
20 #import "chrome/browser/ui/cocoa/browser_window_utils.h"
21 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h"
22 #import "chrome/browser/ui/cocoa/hover_close_button.h"
23 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
24 #import "chrome/browser/ui/cocoa/info_bubble_window.h"
25 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
26 #include "chrome/browser/ui/website_settings/chooser_bubble_delegate.h"
27 #include "chrome/grit/generated_resources.h"
28 #include "content/public/browser/native_web_keyboard_event.h"
29 #include "ui/base/cocoa/window_size_constants.h"
30 #include "ui/base/l10n/l10n_util_mac.h"
31
32 namespace {
33
34 // Chooser bubble width.
35 const CGFloat kChooserBubbleWidth = 320.0f;
36
37 // Chooser bubble height.
38 const CGFloat kChooserBubbleHeight = 220.0f;
39
40 // Distance between the bubble border and the view that is closest to the
41 // border.
42 const CGFloat kMarginX = 20.0f;
43 const CGFloat kMarginY = 20.0f;
44
45 // Distance between two views inside the bubble.
46 const CGFloat kHorizontalPadding = 10.0f;
47 const CGFloat kVerticalPadding = 10.0f;
48
49 const CGFloat kTitlePaddingX = 50.0f;
50 }
51
52 // static
53 scoped_ptr<BubbleUi> ChooserBubbleDelegate::CreateBubbleUi(
54 Browser* browser,
55 ChooserOptions* chooser_options,
56 ChooserBubbleDelegate* chooser_bubble_delegate) {
57 scoped_ptr<BubbleUi> bubble_ui(new ChooserBubbleUiCocoa(
58 browser, chooser_options, chooser_bubble_delegate));
59 return bubble_ui.Pass();
Reilly Grant (use Gerrit) 2015/12/08 19:26:57 You can shorten this to: return make_scoped_ptr(n
juncai 2015/12/09 03:23:54 Done.
60 }
61
62 @interface ChooserBubbleUiController
63 : BaseBubbleController<NSTableViewDataSource, NSTableViewDelegate> {
64 @private
65 // Bridge to the C++ class that created this object.
66 ChooserBubbleUiCocoa* bridge_;
67
68 base::scoped_nsobject<NSTextField> titleView_;
69 base::scoped_nsobject<NSButton> closeButton_;
70 base::scoped_nsobject<NSScrollView> scrollView_;
71 base::scoped_nsobject<NSTableColumn> tableColumn_;
72 base::scoped_nsobject<NSTableView> tableView_;
73 base::scoped_nsobject<NSButton> connectButton_;
74 base::scoped_nsobject<NSButton> cancelButton_;
75
76 Browser* browser_; // Weak.
77 ChooserOptions* chooser_options_; // Weak.
78 ChooserBubbleDelegate* chooser_bubble_delegate_; // Weak.
79 }
80
81 // Designated initializer. |browser| and |bridge| must both be non-nil.
82 - (id)initWithBrowser:(Browser*)browser
83 initWithChooserOptions:(ChooserOptions*)chooser_options
84 initWithChooserBubbleDelegate:
85 (ChooserBubbleDelegate*)chooser_bubble_delegate
86 bridge:(ChooserBubbleUiCocoa*)bridge;
87
88 // Makes the bubble visible.
89 - (void)show;
90
91 // Will reposition the bubble based in case the anchor or parent should change.
92 - (void)updateAnchorPosition;
93
94 // Will calculate the expected anchor point for this bubble.
95 // Should only be used outside this class for tests.
96 - (NSPoint)getExpectedAnchorPoint;
97
98 // Returns true of the browser has support for the location bar.
99 // Should only be used outside this class for tests.
100 - (bool)hasLocationBar;
101
102 // Update table view when chooser options were initialized.
103 - (void)onOptionsInitialized;
104
105 // Update table view when chooser option was added.
106 - (void)onOptionAdded:(NSInteger)index;
107
108 // Update table view when chooser option was removed.
109 - (void)onOptionRemoved:(NSInteger)index;
110
111 // Update table view when chooser options changed.
112 - (void)updateTableView;
113
114 // Determines if the bubble has an anchor in a corner or no anchor at all.
115 - (info_bubble::BubbleArrowLocation)getExpectedArrowLocation;
116
117 // Returns the expected parent for this bubble.
118 - (NSWindow*)getExpectedParentWindow;
119
120 // Returns an autoreleased NSView displaying the title for the bubble.
121 - (NSTextField*)bubbleTitle;
122
123 // Returns an autoreleased NSView displaying the close 'x' button.
124 - (NSButton*)closeButton;
125
126 // Returns an autoreleased NSView of a button with |title| and |action|.
127 - (NSButton*)buttonWithTitle:(NSString*)title action:(SEL)action;
128
129 // Returns an autoreleased NSView displaying a connect button.
130 - (NSButton*)connectButton;
131
132 // Returns an autoreleased NSView displaying a cancel button.
133 - (NSButton*)cancelButton;
134
135 // Called when the 'Connect' button is pressed.
136 - (void)onConnect:(id)sender;
137
138 // Called when the 'Cancel' button is pressed.
139 - (void)onCancel:(id)sender;
140
141 // Called when the 'close' button is pressed.
142 - (void)onClose:(id)sender;
143
144 @end
145
146 @implementation ChooserBubbleUiController
147
148 - (id)initWithBrowser:(Browser*)browser
149 initWithChooserOptions:(ChooserOptions*)chooser_options
150 initWithChooserBubbleDelegate:
151 (ChooserBubbleDelegate*)chooser_bubble_delegate
152 bridge:(ChooserBubbleUiCocoa*)bridge {
153 DCHECK(browser);
154 DCHECK(chooser_options);
155 DCHECK(chooser_bubble_delegate);
156 DCHECK(bridge);
157 browser_ = browser;
158 chooser_options_ = chooser_options;
159 chooser_bubble_delegate_ = chooser_bubble_delegate;
160
161 base::scoped_nsobject<InfoBubbleWindow> window([[InfoBubbleWindow alloc]
162 initWithContentRect:ui::kWindowSizeDeterminedLater
163 styleMask:NSBorderlessWindowMask
164 backing:NSBackingStoreBuffered
165 defer:NO]);
166 [window setAllowedAnimations:info_bubble::kAnimateNone];
167 [window setReleasedWhenClosed:NO];
168 if ((self = [super initWithWindow:window
169 parentWindow:[self getExpectedParentWindow]
170 anchoredAt:NSZeroPoint])) {
171 [self setShouldCloseOnResignKey:NO];
172 [self setShouldOpenAsKeyWindow:YES];
173 [[self bubble] setArrowLocation:[self getExpectedArrowLocation]];
174 bridge_ = bridge;
175 NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
176 [center addObserver:self
177 selector:@selector(parentWindowDidMove:)
178 name:NSWindowDidMoveNotification
179 object:[self getExpectedParentWindow]];
180 }
181 return self;
182 }
183
184 - (void)windowWillClose:(NSNotification*)notification {
185 bridge_->OnBubbleClosing();
186 [super windowWillClose:notification];
187 }
188
189 - (void)parentWindowWillToggleFullScreen:(NSNotification*)notification {
190 // Override the base class implementation, which would have closed the bubble.
191 }
192
193 - (void)parentWindowDidResize:(NSNotification*)notification {
194 DCHECK(bridge_);
195 [self setAnchorPoint:[self getExpectedAnchorPoint]];
196 }
197
198 - (void)parentWindowDidMove:(NSNotification*)notification {
199 DCHECK(bridge_);
200 [self setAnchorPoint:[self getExpectedAnchorPoint]];
201 }
202
203 - (void)show {
204 NSView* view = [[self window] contentView];
205 [view setSubviews:@[]];
206
207 // ------------------------------------
208 // | Chooser bubble title x |
209 // | -------------------------------- |
210 // | | option 0 | |
211 // | | option 1 | |
212 // | | option 2 | |
213 // | | | |
214 // | | | |
215 // | | | |
216 // | -------------------------------- |
217 // | [ Connect] [ Cancel ] |
218 // ------------------------------------
219
220 // Determine the dimensions of the bubble.
221 // Once the height and width are set, the buttons and permission menus can
222 // be laid out correctly.
223 NSRect bubbleFrame =
224 NSMakeRect(0, 0, kChooserBubbleWidth, kChooserBubbleHeight);
225
226 // Create the views.
227 // Title.
228 titleView_.reset([[self bubbleTitle] retain]);
Reilly Grant (use Gerrit) 2015/12/08 19:26:57 retain should not be necessary when assigning to a
juncai 2015/12/09 03:23:54 Done.
229 CGFloat titleOriginX = kMarginX;
230 CGFloat titleHeight = NSHeight([titleView_ frame]);
231 CGFloat titleOriginY = kChooserBubbleHeight - kMarginY - titleHeight;
232 [titleView_ setFrameOrigin:NSMakePoint(titleOriginX, titleOriginY)];
233 [view addSubview:titleView_];
234
235 // Close button.
236 // 'x' button in the upper-right-hand corner.
237 closeButton_.reset([[self closeButton] retain]);
238 CGFloat closeButtonOriginX =
239 kChooserBubbleWidth - kMarginX - NSWidth([closeButton_ frame]);
240 CGFloat closeButtonOriginY =
241 kChooserBubbleHeight - kMarginY - NSHeight([closeButton_ frame]);
242 [closeButton_
243 setFrameOrigin:NSMakePoint(closeButtonOriginX, closeButtonOriginY)];
244 [view addSubview:closeButton_];
245
246 // Connect button.
247 connectButton_.reset([[self connectButton] retain]);
248 // Cancel button.
249 cancelButton_.reset([[self cancelButton] retain]);
250 CGFloat connectButtonWidth = NSWidth([connectButton_ frame]);
251 CGFloat connectButtonHeight = NSHeight([connectButton_ frame]);
252 CGFloat cancelButtonWidth = NSWidth([cancelButton_ frame]);
253
254 // ScollView embedding with TableView.
255 CGFloat scrollViewWidth = kChooserBubbleWidth - 2 * kMarginX;
256 CGFloat scrollViewHeight = kChooserBubbleHeight - 2 * kMarginY -
257 2 * kVerticalPadding - titleHeight -
258 connectButtonHeight;
259 NSRect scrollFrame =
260 NSMakeRect(kMarginX, kMarginY + connectButtonHeight + kVerticalPadding,
261 scrollViewWidth, scrollViewHeight);
262 scrollView_.reset([[[NSScrollView alloc] initWithFrame:scrollFrame] retain]);
263 [scrollView_ setBorderType:NSBezelBorder];
264 [scrollView_ setHasVerticalScroller:YES];
265 [scrollView_ setHasHorizontalScroller:YES];
266 [scrollView_ setAutohidesScrollers:YES];
267
268 // TableView.
269 tableView_.reset([[[NSTableView alloc] initWithFrame:NSZeroRect] retain]);
270 tableColumn_.reset([[[NSTableColumn alloc] initWithIdentifier:@""] retain]);
271 [tableView_ addTableColumn:tableColumn_];
272 [tableView_ setDelegate:self];
273 [tableView_ setDataSource:self];
274 // Make the column title invisible.
275 [tableView_ setHeaderView:nil];
276 [tableView_ setFocusRingType:NSFocusRingTypeNone];
277
278 [scrollView_ setDocumentView:tableView_];
279 [view addSubview:scrollView_];
280
281 // Set connect button and cancel button to the right place.
282 CGFloat connectButtonOriginX = kChooserBubbleWidth - kMarginX -
283 kHorizontalPadding - connectButtonWidth -
284 cancelButtonWidth;
285 CGFloat connectButtonOriginY = kMarginY;
286 [connectButton_
287 setFrameOrigin:NSMakePoint(connectButtonOriginX, connectButtonOriginY)];
288 [connectButton_ setEnabled:NO];
289 [view addSubview:connectButton_];
290
291 CGFloat cancelButtonOriginX =
292 kChooserBubbleWidth - kMarginX - cancelButtonWidth;
293 CGFloat cancelButtonOriginY = kMarginY;
294 [cancelButton_
295 setFrameOrigin:NSMakePoint(cancelButtonOriginX, cancelButtonOriginY)];
296 [view addSubview:cancelButton_];
297
298 bubbleFrame = [[self window] frameRectForContentRect:bubbleFrame];
299 if ([[self window] isVisible]) {
300 // Unfortunately, calling -setFrame followed by -setFrameOrigin (called
301 // within -setAnchorPoint) causes flickering. Avoid the flickering by
302 // manually adjusting the new frame's origin so that the top left stays the
303 // same, and only calling -setFrame.
304 NSRect currentWindowFrame = [[self window] frame];
305 bubbleFrame.origin = currentWindowFrame.origin;
306 bubbleFrame.origin.y = bubbleFrame.origin.y +
307 currentWindowFrame.size.height -
308 bubbleFrame.size.height;
309 [[self window] setFrame:bubbleFrame display:YES];
310 } else {
311 [[self window] setFrame:bubbleFrame display:NO];
312 [self setAnchorPoint:[self getExpectedAnchorPoint]];
313 [self showWindow:nil];
314 [[self window] makeFirstResponder:nil];
315 [[self window] setInitialFirstResponder:connectButton_.get()];
316 }
317 }
318
319 - (NSInteger)numberOfRowsInTableView:(NSTableView*)tableView {
320 const std::vector<base::string16>& device_names =
321 chooser_options_->GetOptions();
322 if (device_names.empty()) {
323 return 1;
324 } else {
325 return static_cast<NSInteger>(device_names.size());
326 }
327 }
328
329 - (id)tableView:(NSTableView*)tableView
330 objectValueForTableColumn:(NSTableColumn*)tableColumn
331 row:(NSInteger)rowIndex {
332 const std::vector<base::string16>& device_names =
333 chooser_options_->GetOptions();
334 if (device_names.empty()) {
335 DCHECK(rowIndex == 0);
336 return l10n_util::GetNSString(IDS_CHOOSER_BUBBLE_NO_DEVICES_FOUND_PROMPT);
337 } else {
338 if (rowIndex >= 0 && rowIndex < static_cast<int>(device_names.size())) {
339 return base::SysUTF16ToNSString(device_names[rowIndex]);
340 } else {
341 return @"";
342 }
343 }
344 }
345
346 - (BOOL)tableView:(NSTableView*)aTableView
347 shouldEditTableColumn:(NSTableColumn*)aTableColumn
348 row:(NSInteger)rowIndex {
349 return NO;
350 }
351
352 - (void)onOptionsInitialized {
353 [self updateTableView];
354 }
355
356 - (void)onOptionAdded:(NSInteger)index {
357 [self updateTableView];
358 }
359
360 - (void)onOptionRemoved:(NSInteger)index {
361 // Table view will automatically selects the next item if the current
362 // item is removed, so here it tracks if the removed item is the item
363 // that was previously selected, if so, deselect it.
364 if ([tableView_ selectedRow] == index)
365 [tableView_ deselectRow:index];
366
367 [self updateTableView];
368 }
369
370 - (void)updateTableView {
371 const std::vector<base::string16>& device_names =
372 chooser_options_->GetOptions();
373 [tableView_ setEnabled:!device_names.empty()];
374
375 CGFloat tableColumnWidth = 0.0f;
376 if (device_names.empty()) {
377 [tableView_ setEnabled:NO];
378 NSString* text =
379 l10n_util::GetNSString(IDS_CHOOSER_BUBBLE_NO_DEVICES_FOUND_PROMPT);
380 CGSize textSize = [text sizeWithAttributes:@{
381 NSFontAttributeName : [NSFont systemFontOfSize:[NSFont systemFontSize]]
382 }];
383 tableColumnWidth = textSize.width;
384 } else {
385 [tableView_ setEnabled:YES];
386 for (const auto& device_name : device_names) {
387 NSString* text = base::SysUTF16ToNSString(device_name);
388 CGSize textSize = [text sizeWithAttributes:@{
389 NSFontAttributeName : [NSFont systemFontOfSize:[NSFont systemFontSize]]
390 }];
391 tableColumnWidth = std::max(tableColumnWidth, textSize.width);
392 }
393 }
394 [tableColumn_ setWidth:tableColumnWidth];
395
396 [tableView_ reloadData];
397 }
398
399 - (void)tableViewSelectionDidChange:(NSNotification*)aNotification {
400 [connectButton_ setEnabled:[tableView_ numberOfSelectedRows] > 0];
401 }
402
403 - (void)updateAnchorPosition {
404 [self setParentWindow:[self getExpectedParentWindow]];
405 [self setAnchorPoint:[self getExpectedAnchorPoint]];
406 }
407
408 - (NSPoint)getExpectedAnchorPoint {
409 NSPoint anchor;
410 if ([self hasLocationBar]) {
411 LocationBarViewMac* location_bar =
412 [[[self getExpectedParentWindow] windowController] locationBarBridge];
413 anchor = location_bar->GetPageInfoBubblePoint();
414 } else {
415 // Center the bubble if there's no location bar.
416 NSRect contentFrame = [[[self getExpectedParentWindow] contentView] frame];
417 anchor = NSMakePoint(NSMidX(contentFrame), NSMaxY(contentFrame));
418 }
419
420 return [[self getExpectedParentWindow] convertBaseToScreen:anchor];
421 }
422
423 - (bool)hasLocationBar {
424 return browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR);
425 }
426
427 - (info_bubble::BubbleArrowLocation)getExpectedArrowLocation {
428 return [self hasLocationBar] ? info_bubble::kTopLeft : info_bubble::kNoArrow;
429 }
430
431 - (NSWindow*)getExpectedParentWindow {
432 DCHECK(browser_->window());
433 return browser_->window()->GetNativeWindow();
434 }
435
436 - (NSTextField*)bubbleTitle {
437 NSTextField* titleView =
438 [[[NSTextField alloc] initWithFrame:NSZeroRect] autorelease];
439 [titleView setDrawsBackground:NO];
440 [titleView setBezeled:NO];
441 [titleView setEditable:NO];
442 [titleView setSelectable:NO];
443 [titleView setStringValue:l10n_util::GetNSString(IDS_CHOOSER_BUBBLE_PROMPT)];
444 [titleView setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
445 [titleView sizeToFit];
446 NSRect titleFrame = [titleView frame];
447 [titleView setFrameSize:NSMakeSize(NSWidth(titleFrame) + kTitlePaddingX,
448 NSHeight(titleFrame))];
449 return titleView;
450 }
451
452 - (NSButton*)closeButton {
453 int dimension = chrome_style::GetCloseButtonSize();
454 NSRect frame = NSMakeRect(0, 0, dimension, dimension);
455 NSButton* button =
456 [[[WebUIHoverCloseButton alloc] initWithFrame:frame] autorelease];
457 [button setAction:@selector(onClose:)];
458 [button setTarget:self];
459 return button;
460 }
461
462 - (NSButton*)buttonWithTitle:(NSString*)title action:(SEL)action {
463 NSButton* button =
464 [[[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect] autorelease];
465 [button setButtonType:NSMomentaryPushInButton];
466 [button setTitle:title];
467 [button setTarget:self];
468 [button setAction:action];
469 [button sizeToFit];
470 return button;
471 }
472
473 - (NSButton*)connectButton {
474 NSString* connectTitle =
475 l10n_util::GetNSString(IDS_CHOOSER_BUBBLE_CONNECT_BUTTON_TEXT);
476 return [self buttonWithTitle:connectTitle action:@selector(onConnect:)];
477 }
478
479 - (NSButton*)cancelButton {
480 NSString* cancelTitle =
481 l10n_util::GetNSString(IDS_CHOOSER_BUBBLE_CANCEL_BUTTON_TEXT);
482 return [self buttonWithTitle:cancelTitle action:@selector(onCancel:)];
483 }
484
485 + (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB {
486 NSRect frameA = [viewA frame];
487 NSRect frameB = [viewB frame];
488 CGFloat width = std::max(NSWidth(frameA), NSWidth(frameB));
489 [viewA setFrameSize:NSMakeSize(width, NSHeight(frameA))];
490 [viewB setFrameSize:NSMakeSize(width, NSHeight(frameB))];
491 return width;
492 }
493
494 + (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB {
495 NSRect frameA = [viewA frame];
496 NSRect frameB = [viewB frame];
497 frameA.origin.y =
498 NSMinY(frameB) + std::floor((NSHeight(frameB) - NSHeight(frameA)) / 2);
499 [viewA setFrameOrigin:frameA.origin];
500 }
501
502 - (void)onConnect:(id)sender {
503 NSInteger row = [tableView_ selectedRow];
504 chooser_bubble_delegate_->Select(row);
505 [self close];
506 }
507
508 - (void)onCancel:(id)sender {
509 chooser_bubble_delegate_->Cancel();
510 [self close];
511 }
512
513 - (void)onClose:(id)sender {
514 chooser_bubble_delegate_->Close();
515 [self close];
516 }
517
518 @end
519
520 ChooserBubbleUiCocoa::ChooserBubbleUiCocoa(
521 Browser* browser,
522 ChooserOptions* chooser_options,
523 ChooserBubbleDelegate* chooser_bubble_delegate)
524 : browser_(browser),
525 chooser_options_(chooser_options),
526 chooser_bubble_delegate_(chooser_bubble_delegate),
527 chooser_bubble_ui_controller_(nil) {
528 DCHECK(browser);
529 DCHECK(chooser_options);
530 DCHECK(chooser_bubble_delegate);
531 chooser_options_->set_observer(this);
532 }
533
534 ChooserBubbleUiCocoa::~ChooserBubbleUiCocoa() {
535 chooser_options_->set_observer(nullptr);
536 if (chooser_bubble_ui_controller_) {
537 [chooser_bubble_ui_controller_ close];
538 chooser_bubble_ui_controller_ = nil;
539 }
540 }
541
542 void ChooserBubbleUiCocoa::Show(BubbleReference bubble_reference) {
543 if (!chooser_bubble_ui_controller_) {
544 chooser_bubble_ui_controller_ = [[ChooserBubbleUiController alloc]
545 initWithBrowser:browser_
546 initWithChooserOptions:chooser_options_
547 initWithChooserBubbleDelegate:chooser_bubble_delegate_
548 bridge:this];
549 }
550
551 [chooser_bubble_ui_controller_ show];
552 [chooser_bubble_ui_controller_ updateTableView];
553 }
554
555 void ChooserBubbleUiCocoa::Close() {
556 if (chooser_bubble_ui_controller_) {
557 [chooser_bubble_ui_controller_ close];
558 chooser_bubble_ui_controller_ = nil;
559 }
560 }
561
562 void ChooserBubbleUiCocoa::UpdateAnchorPosition() {
563 [chooser_bubble_ui_controller_ updateAnchorPosition];
564 }
565
566 void ChooserBubbleUiCocoa::OnOptionsInitialized() {
567 [chooser_bubble_ui_controller_ onOptionsInitialized];
568 }
569
570 void ChooserBubbleUiCocoa::OnOptionAdded(int index) {
571 [chooser_bubble_ui_controller_ onOptionAdded:index];
572 }
573
574 void ChooserBubbleUiCocoa::OnOptionRemoved(int index) {
575 [chooser_bubble_ui_controller_ onOptionRemoved:index];
576 }
577
578 void ChooserBubbleUiCocoa::OnBubbleClosing() {
579 chooser_bubble_ui_controller_ = nil;
580 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698