| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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/extensions/toolbar_actions_bar_bubble_mac.h" | 5 #import "chrome/browser/ui/cocoa/extensions/toolbar_actions_bar_bubble_mac.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/mac/foundation_util.h" | 9 #include "base/mac/foundation_util.h" |
| 10 #include "base/strings/sys_string_conversions.h" | 10 #include "base/strings/sys_string_conversions.h" |
| 11 #import "chrome/browser/ui/cocoa/info_bubble_view.h" | 11 #import "chrome/browser/ui/cocoa/info_bubble_view.h" |
| 12 #import "chrome/browser/ui/cocoa/info_bubble_window.h" | 12 #import "chrome/browser/ui/cocoa/info_bubble_window.h" |
| 13 #include "chrome/browser/ui/toolbar/toolbar_actions_bar_bubble_delegate.h" | 13 #include "chrome/browser/ui/toolbar/toolbar_actions_bar_bubble_delegate.h" |
| 14 #include "skia/ext/skia_utils_mac.h" | 14 #include "skia/ext/skia_utils_mac.h" |
| 15 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTw
eaker.h" | 15 #import "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTw
eaker.h" |
| 16 #include "third_party/skia/include/core/SkColor.h" | 16 #include "third_party/skia/include/core/SkColor.h" |
| 17 #import "ui/base/cocoa/controls/hyperlink_button_cell.h" | 17 #import "ui/base/cocoa/controls/hyperlink_button_cell.h" |
| 18 #import "ui/base/cocoa/hover_button.h" | 18 #import "ui/base/cocoa/hover_button.h" |
| 19 #include "ui/base/resource/resource_bundle.h" |
| 19 #import "ui/base/cocoa/window_size_constants.h" | 20 #import "ui/base/cocoa/window_size_constants.h" |
| 21 #include "ui/gfx/color_palette.h" |
| 22 #include "ui/gfx/image/image_skia_util_mac.h" |
| 23 #include "ui/gfx/paint_vector_icon.h" |
| 20 #include "ui/native_theme/native_theme.h" | 24 #include "ui/native_theme/native_theme.h" |
| 21 #include "ui/native_theme/native_theme_mac.h" | 25 #include "ui/native_theme/native_theme_mac.h" |
| 22 | 26 |
| 23 namespace { | 27 namespace { |
| 24 BOOL g_animations_enabled = false; | 28 BOOL g_animations_enabled = false; |
| 25 CGFloat kMinWidth = 320.0; | 29 CGFloat kMinWidth = 320.0; |
| 26 } | 30 } |
| 27 | 31 |
| 28 @interface ToolbarActionsBarBubbleMac () | 32 @interface ToolbarActionsBarBubbleMac () |
| 29 | 33 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 52 // Handles a button being clicked. | 56 // Handles a button being clicked. |
| 53 - (void)onButtonClicked:(id)sender; | 57 - (void)onButtonClicked:(id)sender; |
| 54 | 58 |
| 55 @end | 59 @end |
| 56 | 60 |
| 57 @implementation ToolbarActionsBarBubbleMac | 61 @implementation ToolbarActionsBarBubbleMac |
| 58 | 62 |
| 59 @synthesize actionButton = actionButton_; | 63 @synthesize actionButton = actionButton_; |
| 60 @synthesize itemList = itemList_; | 64 @synthesize itemList = itemList_; |
| 61 @synthesize dismissButton = dismissButton_; | 65 @synthesize dismissButton = dismissButton_; |
| 62 @synthesize learnMoreButton = learnMoreButton_; | 66 @synthesize link = link_; |
| 67 @synthesize label = label_; |
| 68 @synthesize iconView = iconView_; |
| 63 | 69 |
| 64 - (id)initWithParentWindow:(NSWindow*)parentWindow | 70 - (id)initWithParentWindow:(NSWindow*)parentWindow |
| 65 anchorPoint:(NSPoint)anchorPoint | 71 anchorPoint:(NSPoint)anchorPoint |
| 66 anchoredToAction:(BOOL)anchoredToAction | 72 anchoredToAction:(BOOL)anchoredToAction |
| 67 delegate: | 73 delegate: |
| 68 (std::unique_ptr<ToolbarActionsBarBubbleDelegate>) | 74 (std::unique_ptr<ToolbarActionsBarBubbleDelegate>) |
| 69 delegate { | 75 delegate { |
| 70 base::scoped_nsobject<InfoBubbleWindow> window( | 76 base::scoped_nsobject<InfoBubbleWindow> window( |
| 71 [[InfoBubbleWindow alloc] | 77 [[InfoBubbleWindow alloc] |
| 72 initWithContentRect:ui::kWindowSizeDeterminedLater | 78 initWithContentRect:ui::kWindowSizeDeterminedLater |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 } | 148 } |
| 143 | 149 |
| 144 - (NSTextField*)addTextFieldWithString:(const base::string16&)string | 150 - (NSTextField*)addTextFieldWithString:(const base::string16&)string |
| 145 fontSize:(CGFloat)fontSize | 151 fontSize:(CGFloat)fontSize |
| 146 alignment:(NSTextAlignment)alignment { | 152 alignment:(NSTextAlignment)alignment { |
| 147 NSAttributedString* attributedString = | 153 NSAttributedString* attributedString = |
| 148 [self attributedStringWithString:string | 154 [self attributedStringWithString:string |
| 149 fontSize:fontSize | 155 fontSize:fontSize |
| 150 alignment:alignment]; | 156 alignment:alignment]; |
| 151 | 157 |
| 152 base::scoped_nsobject<NSTextField> textField( | 158 NSTextField* textField = |
| 153 [[NSTextField alloc] initWithFrame:NSZeroRect]); | 159 [[[NSTextField alloc] initWithFrame:NSZeroRect] autorelease]; |
| 154 [textField setEditable:NO]; | 160 [textField setEditable:NO]; |
| 155 [textField setBordered:NO]; | 161 [textField setBordered:NO]; |
| 156 [textField setDrawsBackground:NO]; | 162 [textField setDrawsBackground:NO]; |
| 157 [textField setAttributedStringValue:attributedString]; | 163 [textField setAttributedStringValue:attributedString]; |
| 158 [[[self window] contentView] addSubview:textField]; | 164 [[[self window] contentView] addSubview:textField]; |
| 159 [textField sizeToFit]; | 165 [textField sizeToFit]; |
| 160 return textField.autorelease(); | 166 return textField; |
| 161 } | 167 } |
| 162 | 168 |
| 163 - (NSButton*)addButtonWithString:(const base::string16&)string { | 169 - (NSButton*)addButtonWithString:(const base::string16&)string { |
| 164 NSButton* button = [[NSButton alloc] initWithFrame:NSZeroRect]; | 170 NSButton* button = [[[NSButton alloc] initWithFrame:NSZeroRect] autorelease]; |
| 165 NSAttributedString* buttonString = | 171 NSAttributedString* buttonString = |
| 166 [self attributedStringWithString:string | 172 [self attributedStringWithString:string |
| 167 fontSize:13.0 | 173 fontSize:13.0 |
| 168 alignment:NSCenterTextAlignment]; | 174 alignment:NSCenterTextAlignment]; |
| 169 [button setAttributedTitle:buttonString]; | 175 [button setAttributedTitle:buttonString]; |
| 170 [button setBezelStyle:NSRoundedBezelStyle]; | 176 [button setBezelStyle:NSRoundedBezelStyle]; |
| 171 [button setTarget:self]; | 177 [button setTarget:self]; |
| 172 [button setAction:@selector(onButtonClicked:)]; | 178 [button setAction:@selector(onButtonClicked:)]; |
| 173 [[[self window] contentView] addSubview:button]; | 179 [[[self window] contentView] addSubview:button]; |
| 174 [button sizeToFit]; | 180 [button sizeToFit]; |
| 175 return button; | 181 return button; |
| 176 } | 182 } |
| 177 | 183 |
| 178 - (void)layout { | 184 - (void)layout { |
| 179 // First, construct the pieces of the bubble that have a fixed width: the | 185 // First, construct the pieces of the bubble that have a fixed width: the |
| 180 // heading, and the button strip (the learn more link, the action button, and | 186 // heading, and the button strip (the extra view (icon and/or (linked) text), |
| 181 // the dismiss button). | 187 // the action button, and the dismiss button). |
| 182 NSTextField* heading = | 188 NSTextField* heading = |
| 183 [self addTextFieldWithString:delegate_->GetHeadingText() | 189 [self addTextFieldWithString:delegate_->GetHeadingText() |
| 184 fontSize:13.0 | 190 fontSize:13.0 |
| 185 alignment:NSLeftTextAlignment]; | 191 alignment:NSLeftTextAlignment]; |
| 186 NSSize headingSize = [heading frame].size; | 192 NSSize headingSize = [heading frame].size; |
| 187 | 193 |
| 188 base::string16 learnMore = delegate_->GetLearnMoreButtonText(); | 194 std::unique_ptr<ToolbarActionsBarBubbleDelegate::ExtraViewInfo> |
| 189 NSSize learnMoreSize = NSZeroSize; | 195 extra_view_info = delegate_->GetExtraViewInfo(); |
| 190 if (!learnMore.empty()) { // The "learn more" link is optional. | 196 |
| 191 NSAttributedString* learnMoreString = | 197 gfx::VectorIconId resource_id = extra_view_info->resource_id; |
| 192 [self attributedStringWithString:learnMore | 198 |
| 193 fontSize:13.0 | 199 NSSize extraViewIconSize = NSZeroSize; |
| 194 alignment:NSLeftTextAlignment]; | 200 // The extra view icon is optional. |
| 195 learnMoreButton_ = | 201 if (resource_id != gfx::VectorIconId::VECTOR_ICON_NONE) { |
| 196 [[HyperlinkButtonCell buttonWithString:learnMoreString.string] retain]; | 202 NSImage* image = |
| 197 [learnMoreButton_ setTarget:self]; | 203 gfx::Image(gfx::CreateVectorIcon(resource_id, 16, gfx::kChromeIconGrey)) |
| 198 [learnMoreButton_ setAction:@selector(onButtonClicked:)]; | 204 .ToNSImage(); |
| 199 [[[self window] contentView] addSubview:learnMoreButton_]; | 205 NSRect frame = NSMakeRect(0, 0, image.size.width, image.size.height); |
| 200 [learnMoreButton_ sizeToFit]; | 206 iconView_ = [[[NSImageView alloc] initWithFrame:frame] autorelease]; |
| 201 learnMoreSize = NSMakeSize(NSWidth([learnMoreButton_ frame]), | 207 [iconView_ setImage:image]; |
| 202 NSHeight([learnMoreButton_ frame])); | 208 extraViewIconSize = frame.size; |
| 209 |
| 210 [[[self window] contentView] addSubview:iconView_]; |
| 211 } |
| 212 |
| 213 NSSize extraViewTextSize = NSZeroSize; |
| 214 const base::string16& text = extra_view_info->text; |
| 215 if (!text.empty()) { // The extra view text is optional. |
| 216 if (extra_view_info->is_text_linked) { |
| 217 NSAttributedString* linkString = |
| 218 [self attributedStringWithString:text |
| 219 fontSize:13.0 |
| 220 alignment:NSLeftTextAlignment]; |
| 221 link_ = [HyperlinkButtonCell buttonWithString:linkString.string]; |
| 222 [link_ setTarget:self]; |
| 223 [link_ setAction:@selector(onButtonClicked:)]; |
| 224 [[[self window] contentView] addSubview:link_]; |
| 225 [link_ sizeToFit]; |
| 226 } else { |
| 227 label_ = [self addTextFieldWithString:text |
| 228 fontSize:13.0 |
| 229 alignment:NSLeftTextAlignment]; |
| 230 } |
| 231 extraViewTextSize = label_ ? [label_ frame].size : [link_ frame].size; |
| 203 } | 232 } |
| 204 | 233 |
| 205 base::string16 cancelStr = delegate_->GetDismissButtonText(); | 234 base::string16 cancelStr = delegate_->GetDismissButtonText(); |
| 206 NSSize dismissButtonSize = NSZeroSize; | 235 NSSize dismissButtonSize = NSZeroSize; |
| 207 if (!cancelStr.empty()) { // A cancel/dismiss button is optional. | 236 if (!cancelStr.empty()) { // A cancel/dismiss button is optional. |
| 208 dismissButton_ = [self addButtonWithString:cancelStr]; | 237 dismissButton_ = [self addButtonWithString:cancelStr]; |
| 209 dismissButtonSize = | 238 dismissButtonSize = |
| 210 NSMakeSize(NSWidth([dismissButton_ frame]), | 239 NSMakeSize(NSWidth([dismissButton_ frame]), |
| 211 NSHeight([dismissButton_ frame])); | 240 NSHeight([dismissButton_ frame])); |
| 212 } | 241 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 223 DCHECK(actionButton_ || dismissButton_); | 252 DCHECK(actionButton_ || dismissButton_); |
| 224 CGFloat buttonStripHeight = | 253 CGFloat buttonStripHeight = |
| 225 std::max(actionButtonSize.height, dismissButtonSize.height); | 254 std::max(actionButtonSize.height, dismissButtonSize.height); |
| 226 | 255 |
| 227 const CGFloat kButtonPadding = 5.0; | 256 const CGFloat kButtonPadding = 5.0; |
| 228 CGFloat buttonStripWidth = 0; | 257 CGFloat buttonStripWidth = 0; |
| 229 if (actionButton_) | 258 if (actionButton_) |
| 230 buttonStripWidth += actionButtonSize.width + kButtonPadding; | 259 buttonStripWidth += actionButtonSize.width + kButtonPadding; |
| 231 if (dismissButton_) | 260 if (dismissButton_) |
| 232 buttonStripWidth += dismissButtonSize.width + kButtonPadding; | 261 buttonStripWidth += dismissButtonSize.width + kButtonPadding; |
| 233 if (learnMoreButton_) | 262 if (iconView_) |
| 234 buttonStripWidth += learnMoreSize.width + kButtonPadding; | 263 buttonStripWidth += extraViewIconSize.width + kButtonPadding; |
| 264 if (link_ || label_) |
| 265 buttonStripWidth += extraViewTextSize.width + kButtonPadding; |
| 235 | 266 |
| 236 CGFloat headingWidth = headingSize.width; | 267 CGFloat headingWidth = headingSize.width; |
| 237 CGFloat windowWidth = | 268 CGFloat windowWidth = |
| 238 std::max(std::max(kMinWidth, buttonStripWidth), headingWidth); | 269 std::max(std::max(kMinWidth, buttonStripWidth), headingWidth); |
| 239 | 270 |
| 240 NSTextField* content = | 271 NSTextField* content = |
| 241 [self addTextFieldWithString:delegate_->GetBodyText(anchoredToAction_) | 272 [self addTextFieldWithString:delegate_->GetBodyText(anchoredToAction_) |
| 242 fontSize:12.0 | 273 fontSize:12.0 |
| 243 alignment:NSLeftTextAlignment]; | 274 alignment:NSLeftTextAlignment]; |
| 244 [content setFrame:NSMakeRect(0, 0, windowWidth, 0)]; | 275 [content setFrame:NSMakeRect(0, 0, windowWidth, 0)]; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 currentMaxWidth -= (actionButtonSize.width + kButtonPadding); | 311 currentMaxWidth -= (actionButtonSize.width + kButtonPadding); |
| 281 } | 312 } |
| 282 if (dismissButton_) { | 313 if (dismissButton_) { |
| 283 [dismissButton_ setFrame:NSMakeRect( | 314 [dismissButton_ setFrame:NSMakeRect( |
| 284 currentMaxWidth - dismissButtonSize.width, | 315 currentMaxWidth - dismissButtonSize.width, |
| 285 currentHeight, | 316 currentHeight, |
| 286 dismissButtonSize.width, | 317 dismissButtonSize.width, |
| 287 dismissButtonSize.height)]; | 318 dismissButtonSize.height)]; |
| 288 currentMaxWidth -= (dismissButtonSize.width + kButtonPadding); | 319 currentMaxWidth -= (dismissButtonSize.width + kButtonPadding); |
| 289 } | 320 } |
| 290 if (learnMoreButton_) { | 321 if (label_ || link_) { |
| 291 CGFloat learnMoreHeight = | 322 CGFloat extraViewTextHeight = |
| 292 currentHeight + (buttonStripHeight - learnMoreSize.height) / 2.0; | 323 currentHeight + (buttonStripHeight - extraViewTextSize.height) / 2.0; |
| 293 [learnMoreButton_ setFrame:NSMakeRect(kHorizontalPadding, | 324 NSRect frame = NSMakeRect(currentMaxWidth - extraViewTextSize.width, |
| 294 learnMoreHeight, | 325 extraViewTextHeight, extraViewTextSize.width, |
| 295 learnMoreSize.width, | 326 extraViewTextSize.height); |
| 296 learnMoreSize.height)]; | 327 if (link_) { |
| 328 [link_ setFrame:frame]; |
| 329 } else { |
| 330 [label_ setFrame:frame]; |
| 331 } |
| 332 currentMaxWidth -= extraViewTextSize.width + kButtonPadding; |
| 333 } |
| 334 if (iconView_) { |
| 335 CGFloat extraViewIconHeight = |
| 336 currentHeight + (buttonStripHeight - extraViewIconSize.height) / 2.0; |
| 337 |
| 338 [iconView_ |
| 339 setFrame:NSMakeRect(kHorizontalPadding, extraViewIconHeight, |
| 340 extraViewIconSize.width, extraViewIconSize.height)]; |
| 341 currentMaxWidth -= extraViewIconSize.width + kButtonPadding; |
| 297 } | 342 } |
| 298 // Buttons have some inherit padding of their own, so we don't need quite as | 343 // Buttons have some inherit padding of their own, so we don't need quite as |
| 299 // much space here. | 344 // much space here. |
| 300 currentHeight += buttonStripHeight + kVerticalPadding / 2; | 345 currentHeight += buttonStripHeight + kVerticalPadding / 2; |
| 301 | 346 |
| 302 if (itemList_) { | 347 if (itemList_) { |
| 303 [itemList_ setFrame:NSMakeRect(kHorizontalPadding + kItemListIndentation, | 348 [itemList_ setFrame:NSMakeRect(kHorizontalPadding + kItemListIndentation, |
| 304 currentHeight, | 349 currentHeight, |
| 305 itemListSize.width, | 350 itemListSize.width, |
| 306 itemListSize.height)]; | 351 itemListSize.height)]; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 329 windowSize = [heading convertSize:windowSize toView:nil]; | 374 windowSize = [heading convertSize:windowSize toView:nil]; |
| 330 windowFrame.size = windowSize; | 375 windowFrame.size = windowSize; |
| 331 [[self window] setFrame:windowFrame display:YES]; | 376 [[self window] setFrame:windowFrame display:YES]; |
| 332 } | 377 } |
| 333 | 378 |
| 334 - (void)onButtonClicked:(id)sender { | 379 - (void)onButtonClicked:(id)sender { |
| 335 if (acknowledged_) | 380 if (acknowledged_) |
| 336 return; | 381 return; |
| 337 ToolbarActionsBarBubbleDelegate::CloseAction action = | 382 ToolbarActionsBarBubbleDelegate::CloseAction action = |
| 338 ToolbarActionsBarBubbleDelegate::CLOSE_EXECUTE; | 383 ToolbarActionsBarBubbleDelegate::CLOSE_EXECUTE; |
| 339 if (learnMoreButton_ && sender == learnMoreButton_) { | 384 if (link_ && sender == link_) { |
| 340 action = ToolbarActionsBarBubbleDelegate::CLOSE_LEARN_MORE; | 385 action = ToolbarActionsBarBubbleDelegate::CLOSE_LEARN_MORE; |
| 341 } else if (dismissButton_ && sender == dismissButton_) { | 386 } else if (dismissButton_ && sender == dismissButton_) { |
| 342 action = ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_USER_ACTION; | 387 action = ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS_USER_ACTION; |
| 343 } else { | 388 } else { |
| 344 DCHECK_EQ(sender, actionButton_); | 389 DCHECK_EQ(sender, actionButton_); |
| 345 action = ToolbarActionsBarBubbleDelegate::CLOSE_EXECUTE; | 390 action = ToolbarActionsBarBubbleDelegate::CLOSE_EXECUTE; |
| 346 } | 391 } |
| 347 acknowledged_ = YES; | 392 acknowledged_ = YES; |
| 348 delegate_->OnBubbleClosed(action); | 393 delegate_->OnBubbleClosed(action); |
| 349 [self close]; | 394 [self close]; |
| 350 } | 395 } |
| 351 | 396 |
| 352 @end | 397 @end |
| OLD | NEW |