| Index: chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm | 
| diff --git a/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm b/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm | 
| index 529bd3f51f425945791df3fa32bb88ac7a5ecc3c..3760b1e127d0824aff25861c5fd232de9704d4b4 100644 | 
| --- a/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm | 
| +++ b/chrome/browser/ui/cocoa/browser/zoom_bubble_controller.mm | 
| @@ -4,19 +4,35 @@ | 
|  | 
| #include "chrome/browser/ui/cocoa/browser/zoom_bubble_controller.h" | 
|  | 
| +#include "base/mac/foundation_util.h" | 
| #include "base/strings/string_number_conversions.h" | 
| #include "chrome/browser/chrome_page_zoom.h" | 
| +#import "chrome/browser/ui/cocoa/hover_button.h" | 
| #import "chrome/browser/ui/cocoa/info_bubble_window.h" | 
| #import "chrome/browser/ui/cocoa/info_bubble_view.h" | 
| #include "chrome/browser/ui/zoom/zoom_controller.h" | 
| #include "content/public/common/page_zoom.h" | 
| #include "grit/generated_resources.h" | 
| +#include "skia/ext/skia_utils_mac.h" | 
| #import "ui/base/cocoa/window_size_constants.h" | 
| #include "ui/base/l10n/l10n_util.h" | 
| +#include "ui/native_theme/native_theme.h" | 
|  | 
| @interface ZoomBubbleController (Private) | 
| - (void)performLayout; | 
| - (void)autoCloseBubble; | 
| +- (NSAttributedString*)attributedStringWithString:(NSString*)string | 
| +                                         fontSize:(CGFloat)fontSize; | 
| +// Adds a new zoom button to the bubble. | 
| +- (NSButton*)addButtonWithTitleID:(int)titleID | 
| +                         fontSize:(CGFloat)fontSize | 
| +                           action:(SEL)action; | 
| +- (NSTextField*)addZoomPercentTextField; | 
| +- (void)updateAutoCloseTimer; | 
| +@end | 
| + | 
| +// Button that highlights the background on mouse over. | 
| +@interface ZoomHoverButton : HoverButton | 
| @end | 
|  | 
| namespace { | 
| @@ -26,8 +42,23 @@ namespace { | 
| // src/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc. | 
| const NSTimeInterval kAutoCloseDelay = 1.5; | 
|  | 
| -// The amount of padding between the window frame and controls. | 
| -const CGFloat kPadding = 10.0; | 
| +// The height of the window. | 
| +const CGFloat kWindowHeight = 29.0; | 
| + | 
| +// Width of the zoom in and zoom out buttons. | 
| +const CGFloat kZoomInOutButtonWidth = 44.0; | 
| + | 
| +// Width of zoom label. | 
| +const CGFloat kZoomLabelWidth = 55.0; | 
| + | 
| +// Horizontal margin for the reset zoom button. | 
| +const CGFloat kResetZoomMargin = 9.0; | 
| + | 
| +// The font size text shown in the bubble. | 
| +const CGFloat kTextFontSize = 12.0; | 
| + | 
| +// The font size of the zoom in and zoom out buttons. | 
| +const CGFloat kZoomInOutButtonFontSize = 16.0; | 
|  | 
| }  // namespace | 
|  | 
| @@ -44,6 +75,14 @@ const CGFloat kPadding = 10.0; | 
| parentWindow:parentWindow | 
| anchoredAt:NSZeroPoint])) { | 
| closeObserver_.reset(Block_copy(closeObserver)); | 
| + | 
| +    ui::NativeTheme* nativeTheme = ui::NativeTheme::instance(); | 
| +    [[self bubble] setAlignment:info_bubble::kAlignRightEdgeToAnchorEdge]; | 
| +    [[self bubble] setArrowLocation:info_bubble::kNoArrow]; | 
| +    [[self bubble] setBackgroundColor: | 
| +        gfx::SkColorToCalibratedNSColor(nativeTheme->GetSystemColor( | 
| +            ui::NativeTheme::kColorId_DialogBackground))]; | 
| + | 
| [self performLayout]; | 
| } | 
| return self; | 
| @@ -54,16 +93,17 @@ const CGFloat kPadding = 10.0; | 
| autoClose:(BOOL)autoClose { | 
| contents_ = contents; | 
| [self onZoomChanged]; | 
| +  InfoBubbleWindow* window = | 
| +      base::mac::ObjCCastStrict<InfoBubbleWindow>([self window]); | 
| +  [window setAllowedAnimations:autoClose | 
| +      ? info_bubble::kAnimateOrderIn | info_bubble::kAnimateOrderOut | 
| +      : info_bubble::kAnimateNone]; | 
|  | 
| self.anchorPoint = anchorPoint; | 
| [self showWindow:nil]; | 
|  | 
| autoClose_ = autoClose; | 
| -  if (autoClose_) { | 
| -    [self performSelector:@selector(autoCloseBubble) | 
| -               withObject:nil | 
| -               afterDelay:kAutoCloseDelay]; | 
| -  } | 
| +  [self updateAutoCloseTimer]; | 
| } | 
|  | 
| - (void)onZoomChanged { | 
| @@ -72,15 +112,27 @@ const CGFloat kPadding = 10.0; | 
|  | 
| ZoomController* zoomController = ZoomController::FromWebContents(contents_); | 
| int percent = zoomController->zoom_percent(); | 
| -  [zoomPercent_ setStringValue: | 
| -      l10n_util::GetNSStringF(IDS_TOOLTIP_ZOOM, base::IntToString16(percent))]; | 
| +  NSString* string = | 
| +      l10n_util::GetNSStringF(IDS_ZOOM_PERCENT, base::IntToString16(percent)); | 
| +  [zoomPercent_ setAttributedStringValue: | 
| +      [self attributedStringWithString:string | 
| +                              fontSize:kTextFontSize]]; | 
| + | 
| +  [self updateAutoCloseTimer]; | 
| } | 
|  | 
| - (void)resetToDefault:(id)sender { | 
| -  [self close]; | 
| chrome_page_zoom::Zoom(contents_, content::PAGE_ZOOM_RESET); | 
| } | 
|  | 
| +- (void)zoomIn:(id)sender { | 
| +  chrome_page_zoom::Zoom(contents_, content::PAGE_ZOOM_IN); | 
| +} | 
| + | 
| +- (void)zoomOut:(id)sender { | 
| +  chrome_page_zoom::Zoom(contents_, content::PAGE_ZOOM_OUT); | 
| +} | 
| + | 
| - (void)windowWillClose:(NSNotification*)notification { | 
| contents_ = NULL; | 
| closeObserver_.get()(self); | 
| @@ -93,39 +145,56 @@ const CGFloat kPadding = 10.0; | 
| // Private ///////////////////////////////////////////////////////////////////// | 
|  | 
| - (void)performLayout { | 
| -  NSView* parent = [[self window] contentView]; | 
| - | 
| -  // Create the reset zoom button. | 
| -  scoped_nsobject<NSButton> resetButton( | 
| -      [[NSButton alloc] initWithFrame:NSMakeRect(0, kPadding, 0, 0)]); | 
| -  [resetButton setTitle:l10n_util::GetNSStringWithFixup(IDS_ZOOM_SET_DEFAULT)]; | 
| -  [resetButton setButtonType:NSMomentaryPushInButton]; | 
| -  [[resetButton cell] setControlSize:NSSmallControlSize]; | 
| -  [resetButton setBezelStyle:NSRoundedBezelStyle]; | 
| -  [resetButton setTarget:self]; | 
| -  [resetButton setAction:@selector(resetToDefault:)]; | 
| -  [resetButton sizeToFit]; | 
| - | 
| -  // Center it within the window. | 
| -  NSRect buttonFrame = [resetButton frame]; | 
| -  buttonFrame.origin.x = NSMidX([parent frame]) - NSMidX(buttonFrame); | 
| -  [resetButton setFrame:buttonFrame]; | 
| -  [parent addSubview:resetButton]; | 
| +  // Zoom out button. | 
| +  NSButton* zoomOutButton = [self addButtonWithTitleID:IDS_ZOOM_MINUS2 | 
| +                                              fontSize:kZoomInOutButtonFontSize | 
| +                                                action:@selector(zoomOut:)]; | 
| +  NSRect rect = NSMakeRect(0, 0, kZoomInOutButtonWidth, kWindowHeight); | 
| +  [zoomOutButton setFrame:rect]; | 
|  | 
| -  NSRect windowFrame = [[self window] frame]; | 
| +  // Zoom label. | 
| +  zoomPercent_.reset([[self addZoomPercentTextField] retain]); | 
| +  rect.origin.x += NSWidth(rect); | 
| +  rect.size.width = kZoomLabelWidth; | 
| +  [zoomPercent_ sizeToFit]; | 
| +  NSRect zoomRect = rect; | 
| +  zoomRect.size.height = NSHeight([zoomPercent_ frame]); | 
| +  zoomRect.origin.y = roundf((NSHeight(rect) - NSHeight(zoomRect)) / 2.0); | 
| +  [zoomPercent_ setFrame:zoomRect]; | 
| + | 
| +  // Zoom in button. | 
| +  NSButton* zoomInButton = [self addButtonWithTitleID:IDS_ZOOM_PLUS2 | 
| +                                             fontSize:kZoomInOutButtonFontSize | 
| +                                               action:@selector(zoomIn:)]; | 
| +  rect.origin.x += NSWidth(rect); | 
| +  rect.size.width = kZoomInOutButtonWidth; | 
| +  [zoomInButton setFrame:rect]; | 
| + | 
| +  // Separator view. | 
| +  rect.origin.x += NSWidth(rect); | 
| +  rect.size.width = 1; | 
| +  scoped_nsobject<NSBox> separatorView([[NSBox alloc] initWithFrame:rect]); | 
| +  [separatorView setBoxType:NSBoxCustom]; | 
| +  ui::NativeTheme* nativeTheme = ui::NativeTheme::instance(); | 
| +  [separatorView setBorderColor: | 
| +      gfx::SkColorToCalibratedNSColor(nativeTheme->GetSystemColor( | 
| +          ui::NativeTheme::kColorId_MenuSeparatorColor))]; | 
| +  [[[self window] contentView] addSubview:separatorView]; | 
| + | 
| +  // Reset zoom button. | 
| +  NSButton* resetButton = | 
| +      [self addButtonWithTitleID:IDS_ZOOM_SET_DEFAULT_SHORT | 
| +                        fontSize:kTextFontSize | 
| +                          action:@selector(resetToDefault:)]; | 
| +  rect.origin.x += NSWidth(rect); | 
| +  rect.size.width = | 
| +      [[resetButton attributedTitle] size].width + kResetZoomMargin * 2.0; | 
| +  [resetButton setFrame:rect]; | 
|  | 
| -  // Create the label to display the current zoom amount. | 
| -  zoomPercent_.reset([[NSTextField alloc] initWithFrame: | 
| -      NSMakeRect(kPadding, NSMaxY(buttonFrame), | 
| -                 NSWidth(windowFrame) - 2 * kPadding, 22)]); | 
| -  [zoomPercent_ setEditable:NO]; | 
| -  [zoomPercent_ setBezeled:NO]; | 
| -  [zoomPercent_ setAlignment:NSCenterTextAlignment]; | 
| -  [parent addSubview:zoomPercent_]; | 
| - | 
| -  // Adjust the height of the window to fit the content. | 
| -  windowFrame.size.height = NSMaxY([zoomPercent_ frame]) + kPadding + | 
| -      info_bubble::kBubbleArrowHeight; | 
| +  // Update window frame. | 
| +  NSRect windowFrame = [[self window] frame]; | 
| +  windowFrame.size.height = NSHeight(rect); | 
| +  windowFrame.size.width = NSMaxX(rect); | 
| [[self window] setFrame:windowFrame display:YES]; | 
| } | 
|  | 
| @@ -135,4 +204,76 @@ const CGFloat kPadding = 10.0; | 
| [self close]; | 
| } | 
|  | 
| +- (NSAttributedString*)attributedStringWithString:(NSString*)string | 
| +                                           fontSize:(CGFloat)fontSize { | 
| +  scoped_nsobject<NSMutableParagraphStyle> paragraphStyle( | 
| +      [[NSMutableParagraphStyle alloc] init]); | 
| +  [paragraphStyle setAlignment:NSCenterTextAlignment]; | 
| +  NSDictionary* attributes = @{ | 
| +      NSFontAttributeName: | 
| +      [NSFont systemFontOfSize:fontSize], | 
| +      NSForegroundColorAttributeName: | 
| +      [NSColor colorWithCalibratedWhite:0.58 alpha:1.0], | 
| +      NSParagraphStyleAttributeName: | 
| +      paragraphStyle.get() | 
| +  }; | 
| +  return [[[NSAttributedString alloc] | 
| +      initWithString:string | 
| +          attributes:attributes] autorelease]; | 
| +} | 
| + | 
| +- (NSButton*)addButtonWithTitleID:(int)titleID | 
| +                         fontSize:(CGFloat)fontSize | 
| +                           action:(SEL)action { | 
| +  scoped_nsobject<NSButton> button( | 
| +      [[ZoomHoverButton alloc] initWithFrame:NSZeroRect]); | 
| +  NSString* title = l10n_util::GetNSStringWithFixup(titleID); | 
| +  [button setAttributedTitle:[self attributedStringWithString:title | 
| +                                                     fontSize:fontSize]]; | 
| +  [[button cell] setBordered:NO]; | 
| +  [button setTarget:self]; | 
| +  [button setAction:action]; | 
| +  [[[self window] contentView] addSubview:button]; | 
| +  return button.autorelease(); | 
| +} | 
| + | 
| +- (NSTextField*)addZoomPercentTextField { | 
| +  scoped_nsobject<NSTextField> textField( | 
| +      [[NSTextField alloc] initWithFrame:NSZeroRect]); | 
| +  [textField setEditable:NO]; | 
| +  [textField setBordered:NO]; | 
| +  [textField setDrawsBackground:NO]; | 
| +  [[[self window] contentView] addSubview:textField]; | 
| +  return textField.autorelease(); | 
| +} | 
| + | 
| +- (void)updateAutoCloseTimer { | 
| +  [NSObject cancelPreviousPerformRequestsWithTarget:self | 
| +                                           selector:@selector(autoCloseBubble) | 
| +                                             object:nil]; | 
| +  if (autoClose_) { | 
| +    [self performSelector:@selector(autoCloseBubble) | 
| +               withObject:nil | 
| +               afterDelay:kAutoCloseDelay]; | 
| +  } | 
| +} | 
| + | 
| +@end | 
| + | 
| +@implementation ZoomHoverButton | 
| + | 
| +- (void)drawRect:(NSRect)rect { | 
| +  NSRect bounds = [self bounds]; | 
| +  if ([self hoverState] != kHoverStateNone) { | 
| +    ui::NativeTheme* nativeTheme = ui::NativeTheme::instance(); | 
| +    [gfx::SkColorToCalibratedNSColor(nativeTheme->GetSystemColor( | 
| +        ui::NativeTheme::kColorId_FocusedMenuItemBackgroundColor)) set]; | 
| +    NSRectFillUsingOperation(bounds, NSCompositeSourceOver); | 
| +  } | 
| + | 
| +  [[self cell] drawTitle:[self attributedTitle] | 
| +               withFrame:bounds | 
| +                  inView:self]; | 
| +} | 
| + | 
| @end | 
|  |