Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / location_bar / bubble_decoration.mm
blobdf70ed90d51a8bd08b406a286ddb0263d7b4651b
1 // Copyright (c) 2010 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.
5 #include <cmath>
7 #import "chrome/browser/ui/cocoa/location_bar/bubble_decoration.h"
9 #include "base/logging.h"
11 namespace {
13 // This is used to increase the right margin of this decoration.
14 const CGFloat kRightSideMargin = 1.0;
16 // Padding between the icon/label and bubble edges.
17 const CGFloat kBubblePadding = 3.0;
19 // Padding between the icon and label.
20 const CGFloat kIconLabelPadding = 4.0;
22 // Inset for the background.
23 const CGFloat kBackgroundYInset = 4.0;
25 }  // namespace
27 BubbleDecoration::BubbleDecoration() {
28   attributes_.reset([[NSMutableDictionary alloc] init]);
29   [attributes_ setObject:GetFont() forKey:NSFontAttributeName];
32 BubbleDecoration::~BubbleDecoration() {
35 CGFloat BubbleDecoration::GetWidthForImageAndLabel(NSImage* image,
36                                                    NSString* label) {
37   if (!image && !label)
38     return kOmittedWidth;
40   const CGFloat image_width = image ? [image size].width : 0.0;
41   if (!label)
42     return kBubblePadding + image_width;
44   // The bubble needs to take up an integral number of pixels.
45   // Generally -sizeWithAttributes: seems to overestimate rather than
46   // underestimate, so floor() seems to work better.
47   const CGFloat label_width =
48       std::floor([label sizeWithAttributes:attributes_].width);
49   return kBubblePadding + image_width + kIconLabelPadding + label_width;
52 NSRect BubbleDecoration::GetImageRectInFrame(NSRect frame) {
53   NSRect imageRect = NSInsetRect(frame, 0.0, kBackgroundYInset);
54   if (image_) {
55     // Center the image vertically.
56     const NSSize imageSize = [image_ size];
57     imageRect.origin.y +=
58         std::floor((NSHeight(frame) - imageSize.height) / 2.0);
59     imageRect.size = imageSize;
60   }
61   return imageRect;
64 CGFloat BubbleDecoration::GetWidthForSpace(CGFloat width) {
65   const CGFloat all_width = GetWidthForImageAndLabel(image_, label_);
66   if (all_width <= width)
67     return all_width;
69   const CGFloat image_width = GetWidthForImageAndLabel(image_, nil);
70   if (image_width <= width)
71     return image_width;
73   return kOmittedWidth;
76 void BubbleDecoration::DrawInFrame(NSRect frame, NSView* control_view) {
77   const NSRect decoration_frame = NSInsetRect(frame, 0.0, kBackgroundYInset);
78   CGFloat textOffset = NSMinX(decoration_frame);
79   if (image_) {
80     // Center the image vertically.
81     const NSSize imageSize = [image_ size];
82     NSRect imageRect = decoration_frame;
83     imageRect.origin.y +=
84         std::floor((NSHeight(decoration_frame) - imageSize.height) / 2.0);
85     imageRect.size = imageSize;
86     [image_ drawInRect:imageRect
87               fromRect:NSZeroRect  // Entire image
88              operation:NSCompositeSourceOver
89               fraction:1.0
90         respectFlipped:YES
91                  hints:nil];
92     textOffset = NSMaxX(imageRect) + kIconLabelPadding;
93   }
95   if (label_) {
96     NSRect textRect = frame;
97     textRect.origin.x = textOffset;
98     textRect.size.width = NSMaxX(decoration_frame) - NSMinX(textRect);
99     DrawLabel(label_, attributes_, textRect);
100   }
103 void BubbleDecoration::DrawWithBackgroundInFrame(NSRect background_frame,
104                                                  NSRect frame,
105                                                  NSView* control_view) {
106   NSRect rect = NSInsetRect(background_frame, 0, 1);
107   rect.size.width -= kRightSideMargin;
108   ui::DrawNinePartImage(
109       rect, GetBubbleImageIds(), NSCompositeSourceOver, 1.0, true);
111   DrawInFrame(frame, control_view);
114 NSImage* BubbleDecoration::GetImage() {
115   return image_;
118 void BubbleDecoration::SetImage(NSImage* image) {
119   image_.reset([image retain]);
122 void BubbleDecoration::SetLabel(NSString* label) {
123   // If the initializer was called with |nil|, then the code cannot
124   // process a label.
125   DCHECK(attributes_);
126   if (attributes_)
127     label_.reset([label copy]);
130 void BubbleDecoration::SetTextColor(NSColor* text_color) {
131   [attributes_ setObject:text_color forKey:NSForegroundColorAttributeName];