Home | History | Annotate | Download | only in bubble
      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 #ifndef CHROME_BROWSER_UI_VIEWS_BUBBLE_BORDER_H_
      6 #define CHROME_BROWSER_UI_VIEWS_BUBBLE_BORDER_H_
      7 #pragma once
      8 
      9 #include "third_party/skia/include/core/SkColor.h"
     10 #include "views/background.h"
     11 #include "views/border.h"
     12 
     13 class SkBitmap;
     14 
     15 // Renders a border, with optional arrow, and a custom dropshadow.
     16 // This can be used to produce floating "bubble" objects with rounded corners.
     17 class BubbleBorder : public views::Border {
     18  public:
     19   // Possible locations for the (optional) arrow.
     20   // 0 bit specifies left or right.
     21   // 1 bit specifies top or bottom.
     22   // 2 bit specifies horizontal or vertical.
     23   enum ArrowLocation {
     24     TOP_LEFT     = 0,
     25     TOP_RIGHT    = 1,
     26     BOTTOM_LEFT  = 2,
     27     BOTTOM_RIGHT = 3,
     28     LEFT_TOP     = 4,
     29     RIGHT_TOP    = 5,
     30     LEFT_BOTTOM  = 6,
     31     RIGHT_BOTTOM = 7,
     32     NONE  = 8,  // No arrow. Positioned under the supplied rect.
     33     FLOAT = 9   // No arrow. Centered over the supplied rect.
     34   };
     35 
     36   explicit BubbleBorder(ArrowLocation arrow_location)
     37       : override_arrow_offset_(0),
     38         arrow_location_(arrow_location),
     39         background_color_(SK_ColorWHITE) {
     40     InitClass();
     41   }
     42 
     43   // Returns the radius of the corner of the border.
     44   static int GetCornerRadius() {
     45     // We can't safely calculate a border radius by comparing the sizes of the
     46     // side and corner images, because either may have been extended in various
     47     // directions in order to do more subtle dropshadow fading or other effects.
     48     // So we hardcode the most accurate value.
     49     return 4;
     50   }
     51 
     52   // Sets the location for the arrow.
     53   void set_arrow_location(ArrowLocation arrow_location) {
     54     arrow_location_ = arrow_location;
     55   }
     56   ArrowLocation arrow_location() const { return arrow_location_; }
     57 
     58   static ArrowLocation horizontal_mirror(ArrowLocation loc) {
     59     return loc >= NONE ? loc : static_cast<ArrowLocation>(loc ^ 1);
     60   }
     61 
     62   static ArrowLocation vertical_mirror(ArrowLocation loc) {
     63     return loc >= NONE ? loc : static_cast<ArrowLocation>(loc ^ 2);
     64   }
     65 
     66   static bool has_arrow(ArrowLocation loc) {
     67     return loc >= NONE ? false : true;
     68   }
     69 
     70   static bool is_arrow_on_left(ArrowLocation loc) {
     71     return loc >= NONE ? false : !(loc & 1);
     72   }
     73 
     74   static bool is_arrow_on_top(ArrowLocation loc) {
     75     return loc >= NONE ? false : !(loc & 2);
     76   }
     77 
     78   static bool is_arrow_on_horizontal(ArrowLocation loc) {
     79     return loc >= NONE ? false : !(loc & 4);
     80   }
     81 
     82   // Sets the background color for the arrow body.  This is irrelevant if you do
     83   // not also set the arrow location to something other than NONE.
     84   void set_background_color(SkColor background_color) {
     85     background_color_ = background_color;
     86   }
     87   SkColor background_color() const { return background_color_; }
     88 
     89   // For borders with an arrow, gives the desired bounds (in screen coordinates)
     90   // given the rect to point to and the size of the contained contents.  This
     91   // depends on the arrow location, so if you change that, you should call this
     92   // again to find out the new coordinates.
     93   gfx::Rect GetBounds(const gfx::Rect& position_relative_to,
     94                       const gfx::Size& contents_size) const;
     95 
     96   // Sets a fixed offset for the arrow from the beginning of corresponding edge.
     97   // The arrow will still point to the same location but the bubble will shift
     98   // location to make that happen. Returns actuall arrow offset, in case of
     99   // overflow it differ from desired.
    100   int SetArrowOffset(int offset, const gfx::Size& contents_size);
    101 
    102   // Overridden from views::Border:
    103   virtual void GetInsets(gfx::Insets* insets) const;
    104 
    105  private:
    106   // Loads images if necessary.
    107   static void InitClass();
    108 
    109   virtual ~BubbleBorder() { }
    110 
    111   // Overridden from views::Border:
    112   virtual void Paint(const views::View& view, gfx::Canvas* canvas) const;
    113 
    114   void DrawEdgeWithArrow(gfx::Canvas* canvas,
    115                          bool is_horizontal,
    116                          SkBitmap* edge,
    117                          SkBitmap* arrow,
    118                          int start_x,
    119                          int start_y,
    120                          int before_arrow,
    121                          int after_arrow,
    122                          int offset) const;
    123 
    124   void DrawArrowInterior(gfx::Canvas* canvas,
    125                          bool is_horizontal,
    126                          int tip_x,
    127                          int tip_y,
    128                          int shift_x,
    129                          int shift_y) const;
    130 
    131   // Border graphics.
    132   static SkBitmap* left_;
    133   static SkBitmap* top_left_;
    134   static SkBitmap* top_;
    135   static SkBitmap* top_right_;
    136   static SkBitmap* right_;
    137   static SkBitmap* bottom_right_;
    138   static SkBitmap* bottom_;
    139   static SkBitmap* bottom_left_;
    140   static SkBitmap* left_arrow_;
    141   static SkBitmap* top_arrow_;
    142   static SkBitmap* right_arrow_;
    143   static SkBitmap* bottom_arrow_;
    144 
    145   // Minimal offset of the arrow from the closet edge of bounding rect.
    146   static int arrow_offset_;
    147 
    148   // If specified, overrides the pre-calculated |arrow_offset_| of the arrow.
    149   int override_arrow_offset_;
    150 
    151   ArrowLocation arrow_location_;
    152   SkColor background_color_;
    153 
    154   DISALLOW_COPY_AND_ASSIGN(BubbleBorder);
    155 };
    156 
    157 // A Background that clips itself to the specified BubbleBorder and uses
    158 // the background color of the BubbleBorder.
    159 class BubbleBackground : public views::Background {
    160  public:
    161   explicit BubbleBackground(BubbleBorder* border) : border_(border) {}
    162 
    163   // Background overrides.
    164   virtual void Paint(gfx::Canvas* canvas, views::View* view) const;
    165 
    166  private:
    167   BubbleBorder* border_;
    168 
    169   DISALLOW_COPY_AND_ASSIGN(BubbleBackground);
    170 };
    171 
    172 #endif  // CHROME_BROWSER_UI_VIEWS_BUBBLE_BORDER_H_
    173