Home | History | Annotate | Download | only in location_bar
      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.
      4 
      5 #include <cmath>
      6 
      7 #import "chrome/browser/ui/cocoa/location_bar/bubble_decoration.h"
      8 
      9 #include "base/logging.h"
     10 
     11 namespace {
     12 
     13 // This is used to increase the right margin of this decoration.
     14 const CGFloat kRightSideMargin = 1.0;
     15 
     16 // Padding between the icon/label and bubble edges.
     17 const CGFloat kBubblePadding = 3.0;
     18 
     19 // Padding between the icon and label.
     20 const CGFloat kIconLabelPadding = 4.0;
     21 
     22 // Inset for the background.
     23 const CGFloat kBackgroundYInset = 4.0;
     24 
     25 }  // namespace
     26 
     27 BubbleDecoration::BubbleDecoration() {
     28   attributes_.reset([[NSMutableDictionary alloc] init]);
     29   [attributes_ setObject:GetFont() forKey:NSFontAttributeName];
     30 }
     31 
     32 BubbleDecoration::~BubbleDecoration() {
     33 }
     34 
     35 CGFloat BubbleDecoration::GetWidthForImageAndLabel(NSImage* image,
     36                                                    NSString* label) {
     37   if (!image && !label)
     38     return kOmittedWidth;
     39 
     40   const CGFloat image_width = image ? [image size].width : 0.0;
     41   if (!label)
     42     return kBubblePadding + image_width;
     43 
     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;
     50 }
     51 
     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;
     62 }
     63 
     64 CGFloat BubbleDecoration::GetWidthForSpace(CGFloat width) {
     65   const CGFloat all_width = GetWidthForImageAndLabel(image_, label_);
     66   if (all_width <= width)
     67     return all_width;
     68 
     69   const CGFloat image_width = GetWidthForImageAndLabel(image_, nil);
     70   if (image_width <= width)
     71     return image_width;
     72 
     73   return kOmittedWidth;
     74 }
     75 
     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   }
     94 
     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   }
    101 }
    102 
    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);
    110 
    111   DrawInFrame(frame, control_view);
    112 }
    113 
    114 NSImage* BubbleDecoration::GetImage() {
    115   return image_;
    116 }
    117 
    118 void BubbleDecoration::SetImage(NSImage* image) {
    119   image_.reset([image retain]);
    120 }
    121 
    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]);
    128 }
    129 
    130 void BubbleDecoration::SetTextColor(NSColor* text_color) {
    131   [attributes_ setObject:text_color forKey:NSForegroundColorAttributeName];
    132 }
    133