| Index: chrome/browser/ui/cocoa/website_settings/chooser_bubble_ui_cocoa.mm
|
| diff --git a/chrome/browser/ui/cocoa/website_settings/chooser_bubble_ui_cocoa.mm b/chrome/browser/ui/cocoa/website_settings/chooser_bubble_ui_cocoa.mm
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..323c230eec54638dfd3fe1c4336660cf2c70a35e
|
| --- /dev/null
|
| +++ b/chrome/browser/ui/cocoa/website_settings/chooser_bubble_ui_cocoa.mm
|
| @@ -0,0 +1,559 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#import "chrome/browser/ui/cocoa/website_settings/chooser_bubble_ui_cocoa.h"
|
| +
|
| +#include <algorithm>
|
| +#include <cmath>
|
| +#include <vector>
|
| +
|
| +#include "base/mac/scoped_nsobject.h"
|
| +#include "base/strings/sys_string_conversions.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| +#include "chrome/browser/ui/browser.h"
|
| +#include "chrome/browser/ui/browser_finder.h"
|
| +#include "chrome/browser/ui/browser_window.h"
|
| +#import "chrome/browser/ui/chrome_style.h"
|
| +#import "chrome/browser/ui/cocoa/base_bubble_controller.h"
|
| +#import "chrome/browser/ui/cocoa/browser_window_controller.h"
|
| +#import "chrome/browser/ui/cocoa/browser_window_utils.h"
|
| +#import "chrome/browser/ui/cocoa/constrained_window/constrained_window_button.h"
|
| +#import "chrome/browser/ui/cocoa/hover_close_button.h"
|
| +#import "chrome/browser/ui/cocoa/info_bubble_view.h"
|
| +#import "chrome/browser/ui/cocoa/info_bubble_window.h"
|
| +#import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
|
| +#include "chrome/browser/ui/website_settings/chooser_bubble_delegate.h"
|
| +#include "chrome/grit/generated_resources.h"
|
| +#include "content/public/browser/native_web_keyboard_event.h"
|
| +#include "ui/base/cocoa/window_size_constants.h"
|
| +#include "ui/base/l10n/l10n_util_mac.h"
|
| +
|
| +namespace {
|
| +
|
| +// Chooser bubble width.
|
| +const CGFloat kChooserBubbleWidth = 320.0f;
|
| +
|
| +// Chooser bubble height.
|
| +const CGFloat kChooserBubbleHeight = 220.0f;
|
| +
|
| +// Distance between the bubble border and the view that is closest to the
|
| +// border.
|
| +const CGFloat kMarginX = 20.0f;
|
| +const CGFloat kMarginY = 20.0f;
|
| +
|
| +// Distance between two views inside the bubble.
|
| +const CGFloat kHorizontalPadding = 10.0f;
|
| +const CGFloat kVerticalPadding = 10.0f;
|
| +
|
| +const CGFloat kTitlePaddingX = 50.0f;
|
| +}
|
| +
|
| +// static
|
| +scoped_ptr<BubbleUi> ChooserBubbleDelegate::CreateBubbleUi(
|
| + Browser* browser,
|
| + ChooserOptions* chooser_options,
|
| + ChooserBubbleDelegate* chooser_bubble_delegate) {
|
| + scoped_ptr<BubbleUi> bubble_ui(new ChooserBubbleUiCocoa(
|
| + browser, chooser_options, chooser_bubble_delegate));
|
| + return bubble_ui.Pass();
|
| +}
|
| +
|
| +@interface ChooserBubbleUiController
|
| + : BaseBubbleController<NSTableViewDataSource, NSTableViewDelegate> {
|
| + @private
|
| + // Bridge to the C++ class that created this object.
|
| + ChooserBubbleUiCocoa* bridge_;
|
| +
|
| + base::scoped_nsobject<NSTextField> titleView_;
|
| + base::scoped_nsobject<NSButton> closeButton_;
|
| + base::scoped_nsobject<NSScrollView> scrollView_;
|
| + base::scoped_nsobject<NSTableColumn> tableColumn_;
|
| + base::scoped_nsobject<NSTableView> tableView_;
|
| + base::scoped_nsobject<NSButton> connectButton_;
|
| + base::scoped_nsobject<NSButton> cancelButton_;
|
| +
|
| + Browser* browser_; // Weak.
|
| + ChooserOptions* chooser_options_; // Weak.
|
| + ChooserBubbleDelegate* chooser_bubble_delegate_; // Weak.
|
| +}
|
| +
|
| +// Designated initializer. |browser| and |bridge| must both be non-nil.
|
| +- (id)initWithBrowser:(Browser*)browser
|
| + initWithChooserOptions:(ChooserOptions*)chooser_options
|
| + initWithChooserBubbleDelegate:
|
| + (ChooserBubbleDelegate*)chooser_bubble_delegate
|
| + bridge:(ChooserBubbleUiCocoa*)bridge;
|
| +
|
| +// Makes the bubble visible.
|
| +- (void)show;
|
| +
|
| +// Will reposition the bubble based in case the anchor or parent should change.
|
| +- (void)updateAnchorPosition;
|
| +
|
| +// Will calculate the expected anchor point for this bubble.
|
| +// Should only be used outside this class for tests.
|
| +- (NSPoint)getExpectedAnchorPoint;
|
| +
|
| +// Returns true of the browser has support for the location bar.
|
| +// Should only be used outside this class for tests.
|
| +- (bool)hasLocationBar;
|
| +
|
| +// Update table view when chooser options were initialized.
|
| +- (void)onOptionsInitialized;
|
| +
|
| +// Update table view when chooser option was added.
|
| +- (void)onOptionAdded:(NSInteger)index;
|
| +
|
| +// Update table view when chooser option was removed.
|
| +- (void)onOptionRemoved:(NSInteger)index;
|
| +
|
| +// Update table view when chooser options changed.
|
| +- (void)updateTableView;
|
| +
|
| +// Determines if the bubble has an anchor in a corner or no anchor at all.
|
| +- (info_bubble::BubbleArrowLocation)getExpectedArrowLocation;
|
| +
|
| +// Returns the expected parent for this bubble.
|
| +- (NSWindow*)getExpectedParentWindow;
|
| +
|
| +// Returns an autoreleased NSView displaying the title for the bubble.
|
| +- (NSTextField*)bubbleTitle;
|
| +
|
| +// Returns an autoreleased NSView displaying the close 'x' button.
|
| +- (NSButton*)closeButton;
|
| +
|
| +// Returns an autoreleased NSView of a button with |title| and |action|.
|
| +- (NSButton*)buttonWithTitle:(NSString*)title action:(SEL)action;
|
| +
|
| +// Returns an autoreleased NSView displaying a connect button.
|
| +- (NSButton*)connectButton;
|
| +
|
| +// Returns an autoreleased NSView displaying a cancel button.
|
| +- (NSButton*)cancelButton;
|
| +
|
| +// Called when the 'Connect' button is pressed.
|
| +- (void)onConnect:(id)sender;
|
| +
|
| +// Called when the 'Cancel' button is pressed.
|
| +- (void)onCancel:(id)sender;
|
| +
|
| +// Called when the 'close' button is pressed.
|
| +- (void)onClose:(id)sender;
|
| +
|
| +@end
|
| +
|
| +@implementation ChooserBubbleUiController
|
| +
|
| +- (id)initWithBrowser:(Browser*)browser
|
| + initWithChooserOptions:(ChooserOptions*)chooser_options
|
| + initWithChooserBubbleDelegate:
|
| + (ChooserBubbleDelegate*)chooser_bubble_delegate
|
| + bridge:(ChooserBubbleUiCocoa*)bridge {
|
| + DCHECK(browser);
|
| + DCHECK(chooser_options);
|
| + DCHECK(chooser_bubble_delegate);
|
| + DCHECK(bridge);
|
| + browser_ = browser;
|
| + chooser_options_ = chooser_options;
|
| + chooser_bubble_delegate_ = chooser_bubble_delegate;
|
| +
|
| + base::scoped_nsobject<InfoBubbleWindow> window([[InfoBubbleWindow alloc]
|
| + initWithContentRect:ui::kWindowSizeDeterminedLater
|
| + styleMask:NSBorderlessWindowMask
|
| + backing:NSBackingStoreBuffered
|
| + defer:NO]);
|
| + [window setAllowedAnimations:info_bubble::kAnimateNone];
|
| + [window setReleasedWhenClosed:NO];
|
| + if ((self = [super initWithWindow:window
|
| + parentWindow:[self getExpectedParentWindow]
|
| + anchoredAt:NSZeroPoint])) {
|
| + [self setShouldCloseOnResignKey:NO];
|
| + [self setShouldOpenAsKeyWindow:YES];
|
| + [[self bubble] setArrowLocation:[self getExpectedArrowLocation]];
|
| + bridge_ = bridge;
|
| + NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
|
| + [center addObserver:self
|
| + selector:@selector(parentWindowDidMove:)
|
| + name:NSWindowDidMoveNotification
|
| + object:[self getExpectedParentWindow]];
|
| + }
|
| + return self;
|
| +}
|
| +
|
| +- (void)windowWillClose:(NSNotification*)notification {
|
| + bridge_->OnBubbleClosing();
|
| + [super windowWillClose:notification];
|
| +}
|
| +
|
| +- (void)parentWindowWillToggleFullScreen:(NSNotification*)notification {
|
| + // Override the base class implementation, which would have closed the bubble.
|
| +}
|
| +
|
| +- (void)parentWindowDidResize:(NSNotification*)notification {
|
| + DCHECK(bridge_);
|
| + [self setAnchorPoint:[self getExpectedAnchorPoint]];
|
| +}
|
| +
|
| +- (void)parentWindowDidMove:(NSNotification*)notification {
|
| + DCHECK(bridge_);
|
| + [self setAnchorPoint:[self getExpectedAnchorPoint]];
|
| +}
|
| +
|
| +- (void)show {
|
| + NSView* view = [[self window] contentView];
|
| + [view setSubviews:@[]];
|
| +
|
| + // ------------------------------------
|
| + // | Chooser bubble title x |
|
| + // | -------------------------------- |
|
| + // | | option 0 | |
|
| + // | | option 1 | |
|
| + // | | option 2 | |
|
| + // | | | |
|
| + // | | | |
|
| + // | | | |
|
| + // | -------------------------------- |
|
| + // | [ Connect] [ Cancel ] |
|
| + // ------------------------------------
|
| +
|
| + // Determine the dimensions of the bubble.
|
| + // Once the height and width are set, the buttons and permission menus can
|
| + // be laid out correctly.
|
| + NSRect bubbleFrame =
|
| + NSMakeRect(0, 0, kChooserBubbleWidth, kChooserBubbleHeight);
|
| +
|
| + // Create the views.
|
| + // Title.
|
| + titleView_.reset([[self bubbleTitle] retain]);
|
| + CGFloat titleOriginX = kMarginX;
|
| + CGFloat titleHeight = NSHeight([titleView_ frame]);
|
| + CGFloat titleOriginY = kChooserBubbleHeight - kMarginY - titleHeight;
|
| + [titleView_ setFrameOrigin:NSMakePoint(titleOriginX, titleOriginY)];
|
| + [view addSubview:titleView_];
|
| +
|
| + // Close button.
|
| + // 'x' button in the upper-right-hand corner.
|
| + closeButton_.reset([[self closeButton] retain]);
|
| + CGFloat closeButtonOriginX =
|
| + kChooserBubbleWidth - kMarginX - NSWidth([closeButton_ frame]);
|
| + CGFloat closeButtonOriginY =
|
| + kChooserBubbleHeight - kMarginY - NSHeight([closeButton_ frame]);
|
| + [closeButton_
|
| + setFrameOrigin:NSMakePoint(closeButtonOriginX, closeButtonOriginY)];
|
| + [view addSubview:closeButton_];
|
| +
|
| + // Connect button.
|
| + connectButton_.reset([[self connectButton] retain]);
|
| + // Cancel button.
|
| + cancelButton_.reset([[self cancelButton] retain]);
|
| + CGFloat connectButtonWidth = NSWidth([connectButton_ frame]);
|
| + CGFloat connectButtonHeight = NSHeight([connectButton_ frame]);
|
| + CGFloat cancelButtonWidth = NSWidth([cancelButton_ frame]);
|
| +
|
| + // ScollView embedding with TableView.
|
| + CGFloat scrollViewWidth = kChooserBubbleWidth - 2 * kMarginX;
|
| + CGFloat scrollViewHeight = kChooserBubbleHeight - 2 * kMarginY -
|
| + 2 * kVerticalPadding - titleHeight -
|
| + connectButtonHeight;
|
| + NSRect scrollFrame =
|
| + NSMakeRect(kMarginX, kMarginY + connectButtonHeight + kVerticalPadding,
|
| + scrollViewWidth, scrollViewHeight);
|
| + scrollView_.reset([[[NSScrollView alloc] initWithFrame:scrollFrame] retain]);
|
| + [scrollView_ setBorderType:NSBezelBorder];
|
| + [scrollView_ setHasVerticalScroller:YES];
|
| + [scrollView_ setHasHorizontalScroller:YES];
|
| + [scrollView_ setAutohidesScrollers:YES];
|
| +
|
| + // TableView.
|
| + tableView_.reset([[[NSTableView alloc] initWithFrame:NSZeroRect] retain]);
|
| + tableColumn_.reset([[[NSTableColumn alloc] initWithIdentifier:@""] retain]);
|
| + [tableColumn_ setWidth:scrollViewWidth];
|
| + [tableView_ addTableColumn:tableColumn_];
|
| + [tableView_ setDelegate:self];
|
| + [tableView_ setDataSource:self];
|
| + // Make the column title invisible.
|
| + [tableView_ setHeaderView:nil];
|
| + [tableView_ setFocusRingType:NSFocusRingTypeNone];
|
| +
|
| + [scrollView_ setDocumentView:tableView_];
|
| + [view addSubview:scrollView_];
|
| +
|
| + // Set connect button and cancel button to the right place.
|
| + CGFloat connectButtonOriginX = kChooserBubbleWidth - kMarginX -
|
| + kHorizontalPadding - connectButtonWidth -
|
| + cancelButtonWidth;
|
| + CGFloat connectButtonOriginY = kMarginY;
|
| + [connectButton_
|
| + setFrameOrigin:NSMakePoint(connectButtonOriginX, connectButtonOriginY)];
|
| + [connectButton_ setEnabled:NO];
|
| + [view addSubview:connectButton_];
|
| +
|
| + CGFloat cancelButtonOriginX =
|
| + kChooserBubbleWidth - kMarginX - cancelButtonWidth;
|
| + CGFloat cancelButtonOriginY = kMarginY;
|
| + [cancelButton_
|
| + setFrameOrigin:NSMakePoint(cancelButtonOriginX, cancelButtonOriginY)];
|
| + [view addSubview:cancelButton_];
|
| +
|
| + bubbleFrame = [[self window] frameRectForContentRect:bubbleFrame];
|
| + if ([[self window] isVisible]) {
|
| + // Unfortunately, calling -setFrame followed by -setFrameOrigin (called
|
| + // within -setAnchorPoint) causes flickering. Avoid the flickering by
|
| + // manually adjusting the new frame's origin so that the top left stays the
|
| + // same, and only calling -setFrame.
|
| + NSRect currentWindowFrame = [[self window] frame];
|
| + bubbleFrame.origin = currentWindowFrame.origin;
|
| + bubbleFrame.origin.y = bubbleFrame.origin.y +
|
| + currentWindowFrame.size.height -
|
| + bubbleFrame.size.height;
|
| + [[self window] setFrame:bubbleFrame display:YES];
|
| + } else {
|
| + [[self window] setFrame:bubbleFrame display:NO];
|
| + [self setAnchorPoint:[self getExpectedAnchorPoint]];
|
| + [self showWindow:nil];
|
| + [[self window] makeFirstResponder:nil];
|
| + [[self window] setInitialFirstResponder:connectButton_.get()];
|
| + }
|
| +}
|
| +
|
| +- (NSInteger)numberOfRowsInTableView:(NSTableView*)tableView {
|
| + const std::vector<base::string16>& device_names =
|
| + chooser_options_->GetOptions();
|
| + if (device_names.empty()) {
|
| + return 1;
|
| + } else {
|
| + return static_cast<NSInteger>(device_names.size());
|
| + }
|
| +}
|
| +
|
| +- (id)tableView:(NSTableView*)tableView
|
| + objectValueForTableColumn:(NSTableColumn*)tableColumn
|
| + row:(NSInteger)rowIndex {
|
| + const std::vector<base::string16>& device_names =
|
| + chooser_options_->GetOptions();
|
| + if (device_names.empty()) {
|
| + DCHECK(rowIndex == 0);
|
| + return l10n_util::GetNSString(IDS_CHOOSER_BUBBLE_NO_DEVICES_FOUND_PROMPT);
|
| + } else {
|
| + if (rowIndex >= 0 && rowIndex < static_cast<int>(device_names.size())) {
|
| + return base::SysUTF16ToNSString(device_names[rowIndex]);
|
| + } else {
|
| + return @"";
|
| + }
|
| + }
|
| +}
|
| +
|
| +- (BOOL)tableView:(NSTableView*)aTableView
|
| + shouldEditTableColumn:(NSTableColumn*)aTableColumn
|
| + row:(NSInteger)rowIndex {
|
| + return NO;
|
| +}
|
| +
|
| +- (void)onOptionsInitialized {
|
| + [self updateTableView];
|
| +}
|
| +
|
| +- (void)onOptionAdded:(NSInteger)index {
|
| + [self updateTableView];
|
| +}
|
| +
|
| +- (void)onOptionRemoved:(NSInteger)index {
|
| + // Table view will automatically selects the next item if the current
|
| + // item is removed, so here it tracks if the removed item is the item
|
| + // that was previously selected, if so, deselect it.
|
| + if ([tableView_ selectedRow] == index)
|
| + [tableView_ deselectRow:index];
|
| +
|
| + [self updateTableView];
|
| +}
|
| +
|
| +- (void)updateTableView {
|
| + const std::vector<base::string16>& device_names =
|
| + chooser_options_->GetOptions();
|
| + [tableView_ setEnabled:!device_names.empty()];
|
| + [tableView_ reloadData];
|
| +}
|
| +
|
| +- (void)tableViewSelectionDidChange:(NSNotification*)aNotification {
|
| + [connectButton_ setEnabled:[tableView_ numberOfSelectedRows] > 0];
|
| +}
|
| +
|
| +- (void)updateAnchorPosition {
|
| + [self setParentWindow:[self getExpectedParentWindow]];
|
| + [self setAnchorPoint:[self getExpectedAnchorPoint]];
|
| +}
|
| +
|
| +- (NSPoint)getExpectedAnchorPoint {
|
| + NSPoint anchor;
|
| + if ([self hasLocationBar]) {
|
| + LocationBarViewMac* location_bar =
|
| + [[[self getExpectedParentWindow] windowController] locationBarBridge];
|
| + anchor = location_bar->GetPageInfoBubblePoint();
|
| + } else {
|
| + // Center the bubble if there's no location bar.
|
| + NSRect contentFrame = [[[self getExpectedParentWindow] contentView] frame];
|
| + anchor = NSMakePoint(NSMidX(contentFrame), NSMaxY(contentFrame));
|
| + }
|
| +
|
| + return [[self getExpectedParentWindow] convertBaseToScreen:anchor];
|
| +}
|
| +
|
| +- (bool)hasLocationBar {
|
| + return browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR);
|
| +}
|
| +
|
| +- (info_bubble::BubbleArrowLocation)getExpectedArrowLocation {
|
| + return [self hasLocationBar] ? info_bubble::kTopLeft : info_bubble::kNoArrow;
|
| +}
|
| +
|
| +- (NSWindow*)getExpectedParentWindow {
|
| + DCHECK(browser_->window());
|
| + return browser_->window()->GetNativeWindow();
|
| +}
|
| +
|
| +- (NSTextField*)bubbleTitle {
|
| + NSTextField* titleView =
|
| + [[[NSTextField alloc] initWithFrame:NSZeroRect] autorelease];
|
| + [titleView setDrawsBackground:NO];
|
| + [titleView setBezeled:NO];
|
| + [titleView setEditable:NO];
|
| + [titleView setSelectable:NO];
|
| + [titleView setStringValue:l10n_util::GetNSString(IDS_CHOOSER_BUBBLE_PROMPT)];
|
| + [titleView setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
|
| + [titleView sizeToFit];
|
| + NSRect titleFrame = [titleView frame];
|
| + [titleView setFrameSize:NSMakeSize(NSWidth(titleFrame) + kTitlePaddingX,
|
| + NSHeight(titleFrame))];
|
| + return titleView;
|
| +}
|
| +
|
| +- (NSButton*)closeButton {
|
| + int dimension = chrome_style::GetCloseButtonSize();
|
| + NSRect frame = NSMakeRect(0, 0, dimension, dimension);
|
| + NSButton* button =
|
| + [[[WebUIHoverCloseButton alloc] initWithFrame:frame] autorelease];
|
| + [button setAction:@selector(onClose:)];
|
| + [button setTarget:self];
|
| + return button;
|
| +}
|
| +
|
| +- (NSButton*)buttonWithTitle:(NSString*)title action:(SEL)action {
|
| + NSButton* button =
|
| + [[[ConstrainedWindowButton alloc] initWithFrame:NSZeroRect] autorelease];
|
| + [button setButtonType:NSMomentaryPushInButton];
|
| + [button setTitle:title];
|
| + [button setTarget:self];
|
| + [button setAction:action];
|
| + [button sizeToFit];
|
| + return button;
|
| +}
|
| +
|
| +- (NSButton*)connectButton {
|
| + NSString* connectTitle =
|
| + l10n_util::GetNSString(IDS_CHOOSER_BUBBLE_CONNECT_BUTTON_TEXT);
|
| + return [self buttonWithTitle:connectTitle action:@selector(onConnect:)];
|
| +}
|
| +
|
| +- (NSButton*)cancelButton {
|
| + NSString* cancelTitle =
|
| + l10n_util::GetNSString(IDS_CHOOSER_BUBBLE_CANCEL_BUTTON_TEXT);
|
| + return [self buttonWithTitle:cancelTitle action:@selector(onCancel:)];
|
| +}
|
| +
|
| ++ (CGFloat)matchWidthsOf:(NSView*)viewA andOf:(NSView*)viewB {
|
| + NSRect frameA = [viewA frame];
|
| + NSRect frameB = [viewB frame];
|
| + CGFloat width = std::max(NSWidth(frameA), NSWidth(frameB));
|
| + [viewA setFrameSize:NSMakeSize(width, NSHeight(frameA))];
|
| + [viewB setFrameSize:NSMakeSize(width, NSHeight(frameB))];
|
| + return width;
|
| +}
|
| +
|
| ++ (void)alignCenterOf:(NSView*)viewA verticallyToCenterOf:(NSView*)viewB {
|
| + NSRect frameA = [viewA frame];
|
| + NSRect frameB = [viewB frame];
|
| + frameA.origin.y =
|
| + NSMinY(frameB) + std::floor((NSHeight(frameB) - NSHeight(frameA)) / 2);
|
| + [viewA setFrameOrigin:frameA.origin];
|
| +}
|
| +
|
| +- (void)onConnect:(id)sender {
|
| + NSInteger row = [tableView_ selectedRow];
|
| + chooser_bubble_delegate_->Select(row);
|
| + [self close];
|
| +}
|
| +
|
| +- (void)onCancel:(id)sender {
|
| + chooser_bubble_delegate_->Cancel();
|
| + [self close];
|
| +}
|
| +
|
| +- (void)onClose:(id)sender {
|
| + chooser_bubble_delegate_->Close();
|
| + [self close];
|
| +}
|
| +
|
| +@end
|
| +
|
| +ChooserBubbleUiCocoa::ChooserBubbleUiCocoa(
|
| + Browser* browser,
|
| + ChooserOptions* chooser_options,
|
| + ChooserBubbleDelegate* chooser_bubble_delegate)
|
| + : browser_(browser),
|
| + chooser_options_(chooser_options),
|
| + chooser_bubble_delegate_(chooser_bubble_delegate),
|
| + chooser_bubble_ui_controller_(nil) {
|
| + DCHECK(browser);
|
| + DCHECK(chooser_options);
|
| + DCHECK(chooser_bubble_delegate);
|
| + chooser_options_->set_observer(this);
|
| +}
|
| +
|
| +ChooserBubbleUiCocoa::~ChooserBubbleUiCocoa() {
|
| + chooser_options_->set_observer(nullptr);
|
| + if (chooser_bubble_ui_controller_) {
|
| + [chooser_bubble_ui_controller_ close];
|
| + chooser_bubble_ui_controller_ = nil;
|
| + }
|
| +}
|
| +
|
| +void ChooserBubbleUiCocoa::Show(BubbleReference bubble_reference) {
|
| + if (!chooser_bubble_ui_controller_) {
|
| + chooser_bubble_ui_controller_ = [[ChooserBubbleUiController alloc]
|
| + initWithBrowser:browser_
|
| + initWithChooserOptions:chooser_options_
|
| + initWithChooserBubbleDelegate:chooser_bubble_delegate_
|
| + bridge:this];
|
| + }
|
| +
|
| + [chooser_bubble_ui_controller_ show];
|
| + [chooser_bubble_ui_controller_ updateTableView];
|
| +}
|
| +
|
| +void ChooserBubbleUiCocoa::Close() {
|
| + if (chooser_bubble_ui_controller_) {
|
| + [chooser_bubble_ui_controller_ close];
|
| + chooser_bubble_ui_controller_ = nil;
|
| + }
|
| +}
|
| +
|
| +void ChooserBubbleUiCocoa::UpdateAnchorPosition() {
|
| + [chooser_bubble_ui_controller_ updateAnchorPosition];
|
| +}
|
| +
|
| +void ChooserBubbleUiCocoa::OnOptionsInitialized() {
|
| + [chooser_bubble_ui_controller_ onOptionsInitialized];
|
| +}
|
| +
|
| +void ChooserBubbleUiCocoa::OnOptionAdded(int index) {
|
| + [chooser_bubble_ui_controller_ onOptionAdded:index];
|
| +}
|
| +
|
| +void ChooserBubbleUiCocoa::OnOptionRemoved(int index) {
|
| + [chooser_bubble_ui_controller_ onOptionRemoved:index];
|
| +}
|
| +
|
| +void ChooserBubbleUiCocoa::OnBubbleClosing() {
|
| + chooser_bubble_ui_controller_ = nil;
|
| +}
|
|
|