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 BubbleBorder(ArrowLocation arrow_location)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. GetCornerRadius()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. set_arrow_location(ArrowLocation arrow_location)53 void set_arrow_location(ArrowLocation arrow_location) { 54 arrow_location_ = arrow_location; 55 } arrow_location()56 ArrowLocation arrow_location() const { return arrow_location_; } 57 horizontal_mirror(ArrowLocation loc)58 static ArrowLocation horizontal_mirror(ArrowLocation loc) { 59 return loc >= NONE ? loc : static_cast<ArrowLocation>(loc ^ 1); 60 } 61 vertical_mirror(ArrowLocation loc)62 static ArrowLocation vertical_mirror(ArrowLocation loc) { 63 return loc >= NONE ? loc : static_cast<ArrowLocation>(loc ^ 2); 64 } 65 has_arrow(ArrowLocation loc)66 static bool has_arrow(ArrowLocation loc) { 67 return loc >= NONE ? false : true; 68 } 69 is_arrow_on_left(ArrowLocation loc)70 static bool is_arrow_on_left(ArrowLocation loc) { 71 return loc >= NONE ? false : !(loc & 1); 72 } 73 is_arrow_on_top(ArrowLocation loc)74 static bool is_arrow_on_top(ArrowLocation loc) { 75 return loc >= NONE ? false : !(loc & 2); 76 } 77 is_arrow_on_horizontal(ArrowLocation loc)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. set_background_color(SkColor background_color)84 void set_background_color(SkColor background_color) { 85 background_color_ = background_color; 86 } background_color()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 ~BubbleBorder()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: BubbleBackground(BubbleBorder * border)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