1 // Copyright (c) 2012 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 UI_VIEWS_BUBBLE_BUBBLE_BORDER_H_ 6 #define UI_VIEWS_BUBBLE_BUBBLE_BORDER_H_ 7 8 #include "base/basictypes.h" 9 #include "base/compiler_specific.h" 10 #include "ui/views/background.h" 11 #include "ui/views/border.h" 12 13 namespace gfx { 14 class ImageSkia; 15 class Rect; 16 } 17 18 namespace views { 19 20 namespace internal { 21 struct BorderImages; 22 } 23 24 // Renders a border, with optional arrow, and a custom dropshadow. 25 // This can be used to produce floating "bubble" objects with rounded corners. 26 class VIEWS_EXPORT BubbleBorder : public Border { 27 public: 28 // Possible locations for the (optional) arrow. 29 // 0 bit specifies left or right. 30 // 1 bit specifies top or bottom. 31 // 2 bit specifies horizontal or vertical. 32 // 3 bit specifies whether the arrow at the center of its residing edge. 33 enum ArrowMask { 34 RIGHT = 0x01, 35 BOTTOM = 0x02, 36 VERTICAL = 0x04, 37 CENTER = 0x08, 38 }; 39 40 enum Arrow { 41 TOP_LEFT = 0, 42 TOP_RIGHT = RIGHT, 43 BOTTOM_LEFT = BOTTOM, 44 BOTTOM_RIGHT = BOTTOM | RIGHT, 45 LEFT_TOP = VERTICAL, 46 RIGHT_TOP = VERTICAL | RIGHT, 47 LEFT_BOTTOM = VERTICAL | BOTTOM, 48 RIGHT_BOTTOM = VERTICAL | BOTTOM | RIGHT, 49 TOP_CENTER = CENTER, 50 BOTTOM_CENTER = CENTER | BOTTOM, 51 LEFT_CENTER = CENTER | VERTICAL, 52 RIGHT_CENTER = CENTER | VERTICAL | RIGHT, 53 NONE = 16, // No arrow. Positioned under the supplied rect. 54 FLOAT = 17, // No arrow. Centered over the supplied rect. 55 }; 56 57 enum Shadow { 58 NO_SHADOW = 0, 59 NO_SHADOW_OPAQUE_BORDER, 60 BIG_SHADOW, 61 SMALL_SHADOW, 62 SHADOW_COUNT, 63 }; 64 65 // The position of the bubble in relation to the anchor. 66 enum BubbleAlignment { 67 // The tip of the arrow points to the middle of the anchor. 68 ALIGN_ARROW_TO_MID_ANCHOR, 69 // The edge nearest to the arrow is lined up with the edge of the anchor. 70 ALIGN_EDGE_TO_ANCHOR_EDGE, 71 }; 72 73 // The way the arrow should be painted. 74 enum ArrowPaintType { 75 // Fully render the arrow. 76 PAINT_NORMAL, 77 // Leave space for the arrow, but do not paint it. 78 PAINT_TRANSPARENT, 79 // Neither paint nor leave space for the arrow. 80 PAINT_NONE, 81 }; 82 83 BubbleBorder(Arrow arrow, Shadow shadow, SkColor color); 84 virtual ~BubbleBorder(); 85 86 // Returns the radius of the corner of the border. 87 // TODO(xiyuan): Get rid of this since it's part of BorderImages now? GetCornerRadius()88 static int GetCornerRadius() { 89 // We can't safely calculate a border radius by comparing the sizes of the 90 // side and corner images, because either may have been extended in various 91 // directions in order to do more subtle dropshadow fading or other effects. 92 // So we hardcode the most accurate value. 93 return 4; 94 } 95 has_arrow(Arrow a)96 static bool has_arrow(Arrow a) { return a < NONE; } 97 is_arrow_on_left(Arrow a)98 static bool is_arrow_on_left(Arrow a) { 99 return has_arrow(a) && (a == LEFT_CENTER || !(a & (RIGHT | CENTER))); 100 } 101 is_arrow_on_top(Arrow a)102 static bool is_arrow_on_top(Arrow a) { 103 return has_arrow(a) && (a == TOP_CENTER || !(a & (BOTTOM | CENTER))); 104 } 105 is_arrow_on_horizontal(Arrow a)106 static bool is_arrow_on_horizontal(Arrow a) { 107 return a >= NONE ? false : !(a & VERTICAL); 108 } 109 is_arrow_at_center(Arrow a)110 static bool is_arrow_at_center(Arrow a) { 111 return has_arrow(a) && !!(a & CENTER); 112 } 113 horizontal_mirror(Arrow a)114 static Arrow horizontal_mirror(Arrow a) { 115 return (a == TOP_CENTER || a == BOTTOM_CENTER || a >= NONE) ? 116 a : static_cast<Arrow>(a ^ RIGHT); 117 } 118 vertical_mirror(Arrow a)119 static Arrow vertical_mirror(Arrow a) { 120 return (a == LEFT_CENTER || a == RIGHT_CENTER || a >= NONE) ? 121 a : static_cast<Arrow>(a ^ BOTTOM); 122 } 123 124 // Get or set the arrow type. set_arrow(Arrow arrow)125 void set_arrow(Arrow arrow) { arrow_ = arrow; } arrow()126 Arrow arrow() const { return arrow_; } 127 128 // Get or set the bubble alignment. set_alignment(BubbleAlignment alignment)129 void set_alignment(BubbleAlignment alignment) { alignment_ = alignment; } alignment()130 BubbleAlignment alignment() const { return alignment_; } 131 132 // Get the shadow type. shadow()133 Shadow shadow() const { return shadow_; } 134 135 // Get or set the background color for the bubble and arrow body. set_background_color(SkColor color)136 void set_background_color(SkColor color) { background_color_ = color; } background_color()137 SkColor background_color() const { return background_color_; } 138 139 // If true, the background color should be determined by the host's 140 // NativeTheme. set_use_theme_background_color(bool use_theme_background_color)141 void set_use_theme_background_color(bool use_theme_background_color) { 142 use_theme_background_color_ = use_theme_background_color; 143 } use_theme_background_color()144 bool use_theme_background_color() { return use_theme_background_color_; } 145 146 // Sets a desired pixel distance between the arrow tip and the outside edge of 147 // the neighboring border image. For example: |----offset----| 148 // '(' represents shadow around the '{' edge: ((({ ^ }))) 149 // The arrow will still anchor to the same location but the bubble will shift 150 // location to place the arrow |offset| pixels from the perpendicular edge. set_arrow_offset(int offset)151 void set_arrow_offset(int offset) { arrow_offset_ = offset; } 152 153 // Sets the way the arrow is actually painted. Default is PAINT_NORMAL. set_paint_arrow(ArrowPaintType value)154 void set_paint_arrow(ArrowPaintType value) { arrow_paint_type_ = value; } 155 156 // Get the desired widget bounds (in screen coordinates) given the anchor rect 157 // and bubble content size; calculated from shadow and arrow image dimensions. 158 virtual gfx::Rect GetBounds(const gfx::Rect& anchor_rect, 159 const gfx::Size& contents_size) const; 160 161 // Get the border exterior thickness, including stroke and shadow, in pixels. 162 int GetBorderThickness() const; 163 164 // Returns the corner radius of the current image set. 165 int GetBorderCornerRadius() const; 166 167 // Gets the arrow offset to use. 168 int GetArrowOffset(const gfx::Size& border_size) const; 169 170 // Overridden from Border: 171 virtual void Paint(const View& view, gfx::Canvas* canvas) OVERRIDE; 172 virtual gfx::Insets GetInsets() const OVERRIDE; 173 virtual gfx::Size GetMinimumSize() const OVERRIDE; 174 175 private: 176 gfx::Size GetSizeForContentsSize(const gfx::Size& contents_size) const; 177 gfx::ImageSkia* GetArrowImage() const; 178 gfx::Rect GetArrowRect(const gfx::Rect& bounds) const; 179 void DrawArrow(gfx::Canvas* canvas, const gfx::Rect& arrow_bounds) const; 180 181 Arrow arrow_; 182 int arrow_offset_; 183 ArrowPaintType arrow_paint_type_; 184 BubbleAlignment alignment_; 185 Shadow shadow_; 186 internal::BorderImages* images_; 187 SkColor background_color_; 188 bool use_theme_background_color_; 189 190 DISALLOW_COPY_AND_ASSIGN(BubbleBorder); 191 }; 192 193 // A Background that clips itself to the specified BubbleBorder and uses 194 // the background color of the BubbleBorder. 195 class VIEWS_EXPORT BubbleBackground : public Background { 196 public: BubbleBackground(BubbleBorder * border)197 explicit BubbleBackground(BubbleBorder* border) : border_(border) {} 198 199 // Overridden from Background: 200 virtual void Paint(gfx::Canvas* canvas, View* view) const OVERRIDE; 201 202 private: 203 BubbleBorder* border_; 204 205 DISALLOW_COPY_AND_ASSIGN(BubbleBackground); 206 }; 207 208 } // namespace views 209 210 #endif // UI_VIEWS_BUBBLE_BUBBLE_BORDER_H_ 211