Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / browser / avatar_button_controller.mm
1 // Copyright 2014 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/browser/avatar_button_controller.h"
6
7 #include "base/mac/foundation_util.h"
8 #include "base/strings/sys_string_conversions.h"
9 #include "chrome/browser/profiles/profiles_state.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/browser_window.h"
12 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
13 #include "grit/generated_resources.h"
14 #include "grit/theme_resources.h"
15 #import "ui/base/cocoa/appkit_utils.h"
16 #import "ui/base/cocoa/hover_image_button.h"
17 #include "ui/base/l10n/l10n_util_mac.h"
18 #include "ui/base/nine_image_painter_factory.h"
19 #include "ui/base/resource/resource_bundle.h"
20 #include "ui/gfx/text_elider.h"
21
22 namespace {
23
24 const CGFloat kButtonPadding = 12;
25 const CGFloat kButtonDefaultPadding = 5;
26 const CGFloat kButtonHeight = 27;
27 const CGFloat kButtonTitleImageSpacing = 10;
28 const CGFloat kMaxButtonWidth = 120;
29
30 const ui::NinePartImageIds kNormalBorderImageIds =
31     IMAGE_GRID(IDR_AVATAR_MAC_BUTTON_NORMAL);
32 const ui::NinePartImageIds kHoverBorderImageIds =
33     IMAGE_GRID(IDR_AVATAR_MAC_BUTTON_HOVER);
34 const ui::NinePartImageIds kPressedBorderImageIds =
35     IMAGE_GRID(IDR_AVATAR_MAC_BUTTON_PRESSED);
36
37 NSImage* GetImageFromResourceID(int resourceId) {
38   return ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
39       resourceId).ToNSImage();
40 }
41
42 }  // namespace
43
44 // Button cell with a custom border given by a set of nine-patch image grids.
45 @interface CustomThemeButtonCell : NSButtonCell
46 @end
47
48 @implementation CustomThemeButtonCell
49 - (NSSize)cellSize {
50   NSSize buttonSize = [super cellSize];
51   buttonSize.width += 2 * kButtonPadding - 2 * kButtonDefaultPadding;
52   buttonSize.height = kButtonHeight;
53   return buttonSize;
54 }
55
56 - (NSRect)drawTitle:(NSAttributedString*)title
57           withFrame:(NSRect)frame
58              inView:(NSView*)controlView {
59   frame.origin.x = kButtonPadding;
60   // Ensure there's always a padding between the text and the image.
61   frame.size.width -= kButtonTitleImageSpacing;
62   return [super drawTitle:title withFrame:frame inView:controlView];
63 }
64
65 - (void)drawImage:(NSImage*)image
66         withFrame:(NSRect)frame
67            inView:(NSView*)controlView {
68   // For the x-offset, we need to undo the default padding and apply the
69   // new one. For the y-offset, increasing the button height means we need
70   // to move the image a little down to align it nicely with the text; this
71   // was chosen by visual inspection.
72   frame = NSOffsetRect(frame, kButtonDefaultPadding - kButtonPadding, 2);
73   [super drawImage:image withFrame:frame inView:controlView];
74 }
75
76 - (void)drawBezelWithFrame:(NSRect)frame
77                     inView:(NSView*)controlView {
78   HoverState hoverState =
79       [base::mac::ObjCCastStrict<HoverImageButton>(controlView) hoverState];
80   ui::NinePartImageIds imageIds = kNormalBorderImageIds;
81
82   if (hoverState == kHoverStateMouseDown)
83     imageIds = kPressedBorderImageIds;
84   else if (hoverState == kHoverStateMouseOver)
85     imageIds = kHoverBorderImageIds;
86   ui::DrawNinePartImage(frame, imageIds, NSCompositeSourceOver, 1.0, true);
87 }
88 @end
89
90 @interface AvatarButtonController (Private)
91 - (void)updateAvatarButtonAndLayoutParent:(BOOL)layoutParent;
92 @end
93
94 @implementation AvatarButtonController
95
96 - (id)initWithBrowser:(Browser*)browser {
97   if ((self = [super initWithBrowser:browser])) {
98     HoverImageButton* hoverButton =
99         [[HoverImageButton alloc] initWithFrame:NSZeroRect];
100     [hoverButton setDefaultImage:GetImageFromResourceID(
101         IDR_AVATAR_MAC_BUTTON_DROPARROW)];
102     [hoverButton setHoverImage:GetImageFromResourceID(
103         IDR_AVATAR_MAC_BUTTON_DROPARROW_HOVER)];
104     [hoverButton setPressedImage:GetImageFromResourceID(
105         IDR_AVATAR_MAC_BUTTON_DROPARROW_PRESSED)];
106
107     button_.reset(hoverButton);
108     base::scoped_nsobject<CustomThemeButtonCell> cell(
109         [[CustomThemeButtonCell alloc] init]);
110     [button_ setCell:cell.get()];
111     [self setView:button_];
112
113     [button_ setBezelStyle:NSShadowlessSquareBezelStyle];
114     [button_ setButtonType:NSMomentaryChangeButton];
115     [button_ setBordered:YES];
116     // This is a workaround for an issue in the HoverImageButton where the
117     // button is initially sized incorrectly unless a default image is provided.
118     [button_ setImage:GetImageFromResourceID(IDR_AVATAR_MAC_BUTTON_DROPARROW)];
119     [button_ setImagePosition:NSImageRight];
120     [button_ setAutoresizingMask:NSViewMinXMargin | NSViewMinYMargin];
121     [button_ setTarget:self];
122     [button_ setAction:@selector(buttonClicked:)];
123
124     [self updateAvatarButtonAndLayoutParent:NO];
125   }
126   return self;
127 }
128
129 - (void)updateAvatarButtonAndLayoutParent:(BOOL)layoutParent {
130   // The button text has a white drop shadow.
131   base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
132   [shadow setShadowOffset:NSMakeSize(0, -1)];
133   [shadow setShadowBlurRadius:0];
134   [shadow setShadowColor:[NSColor whiteColor]];
135
136   base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
137       [[NSMutableParagraphStyle alloc] init]);
138   [paragraphStyle setLineBreakMode:NSLineBreakByTruncatingTail];
139   [paragraphStyle setAlignment:NSLeftTextAlignment];
140
141   NSString* buttonTitle = base::SysUTF16ToNSString(
142       profiles::GetActiveProfileDisplayName(browser_));
143
144   base::scoped_nsobject<NSAttributedString> attributedTitle(
145       [[NSAttributedString alloc]
146           initWithString:buttonTitle
147               attributes:@{ NSShadowAttributeName : shadow.get(),
148                             NSParagraphStyleAttributeName : paragraphStyle }]);
149   [button_ setAttributedTitle:attributedTitle];
150   [button_ sizeToFit];
151
152   // Truncate the title if needed.
153   if (NSWidth([button_ bounds]) > kMaxButtonWidth)
154     [button_ setFrameSize:NSMakeSize(kMaxButtonWidth, kButtonHeight)];
155
156   if (layoutParent) {
157     // Because the width of the button might have changed, the parent browser
158     // frame needs to recalculate the button bounds and redraw it.
159     [[BrowserWindowController
160         browserWindowControllerForWindow:browser_->window()->GetNativeWindow()]
161         layoutSubviews];
162   }
163 }
164
165 @end