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? 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 96 static bool has_arrow(Arrow a) { return a < NONE; } 97 98 static bool is_arrow_on_left(Arrow a) { 99 return has_arrow(a) && (a == LEFT_CENTER || !(a & (RIGHT | CENTER))); 100 } 101 102 static bool is_arrow_on_top(Arrow a) { 103 return has_arrow(a) && (a == TOP_CENTER || !(a & (BOTTOM | CENTER))); 104 } 105 106 static bool is_arrow_on_horizontal(Arrow a) { 107 return a >= NONE ? false : !(a & VERTICAL); 108 } 109 110 static bool is_arrow_at_center(Arrow a) { 111 return has_arrow(a) && !!(a & CENTER); 112 } 113 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 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. 125 void set_arrow(Arrow arrow) { arrow_ = arrow; } 126 Arrow arrow() const { return arrow_; } 127 128 // Get or set the bubble alignment. 129 void set_alignment(BubbleAlignment alignment) { alignment_ = alignment; } 130 BubbleAlignment alignment() const { return alignment_; } 131 132 // Get the shadow type. 133 Shadow shadow() const { return shadow_; } 134 135 // Get or set the background color for the bubble and arrow body. 136 void set_background_color(SkColor color) { background_color_ = color; } 137 SkColor background_color() const { return background_color_; } 138 139 // Sets a desired pixel distance between the arrow tip and the outside edge of 140 // the neighboring border image. For example: |----offset----| 141 // '(' represents shadow around the '{' edge: ((({ ^ }))) 142 // The arrow will still anchor to the same location but the bubble will shift 143 // location to place the arrow |offset| pixels from the perpendicular edge. 144 void set_arrow_offset(int offset) { arrow_offset_ = offset; } 145 146 // Sets the way the arrow is actually painted. Default is PAINT_NORMAL. 147 void set_paint_arrow(ArrowPaintType value) { arrow_paint_type_ = value; } 148 149 // Get the desired widget bounds (in screen coordinates) given the anchor rect 150 // and bubble content size; calculated from shadow and arrow image dimensions. 151 virtual gfx::Rect GetBounds(const gfx::Rect& anchor_rect, 152 const gfx::Size& contents_size) const; 153 154 // Get the border exterior thickness, including stroke and shadow, in pixels. 155 int GetBorderThickness() const; 156 157 // Returns the corner radius of the current image set. 158 int GetBorderCornerRadius() const; 159 160 // Gets the arrow offset to use. 161 int GetArrowOffset(const gfx::Size& border_size) const; 162 163 // Overridden from Border: 164 virtual void Paint(const View& view, gfx::Canvas* canvas) OVERRIDE; 165 virtual gfx::Insets GetInsets() const OVERRIDE; 166 virtual gfx::Size GetMinimumSize() const OVERRIDE; 167 168 private: 169 gfx::Size GetSizeForContentsSize(const gfx::Size& contents_size) const; 170 gfx::ImageSkia* GetArrowImage() const; 171 gfx::Rect GetArrowRect(const gfx::Rect& bounds) const; 172 void DrawArrow(gfx::Canvas* canvas, const gfx::Rect& arrow_bounds) const; 173 174 Arrow arrow_; 175 int arrow_offset_; 176 ArrowPaintType arrow_paint_type_; 177 BubbleAlignment alignment_; 178 Shadow shadow_; 179 internal::BorderImages* images_; 180 SkColor background_color_; 181 182 DISALLOW_COPY_AND_ASSIGN(BubbleBorder); 183 }; 184 185 // A Background that clips itself to the specified BubbleBorder and uses 186 // the background color of the BubbleBorder. 187 class VIEWS_EXPORT BubbleBackground : public Background { 188 public: 189 explicit BubbleBackground(BubbleBorder* border) : border_(border) {} 190 191 // Overridden from Background: 192 virtual void Paint(gfx::Canvas* canvas, View* view) const OVERRIDE; 193 194 private: 195 BubbleBorder* border_; 196 197 DISALLOW_COPY_AND_ASSIGN(BubbleBackground); 198 }; 199 200 } // namespace views 201 202 #endif // UI_VIEWS_BUBBLE_BUBBLE_BORDER_H_ 203