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 } 16 17 namespace views { 18 19 namespace internal { 20 struct BorderImages; 21 } 22 23 // Renders a border, with optional arrow, and a custom dropshadow. 24 // This can be used to produce floating "bubble" objects with rounded corners. 25 class VIEWS_EXPORT BubbleBorder : public Border { 26 public: 27 // Possible locations for the (optional) arrow. 28 // 0 bit specifies left or right. 29 // 1 bit specifies top or bottom. 30 // 2 bit specifies horizontal or vertical. 31 // 3 bit specifies whether the arrow at the center of its residing edge. 32 enum ArrowMask { 33 RIGHT = 0x01, 34 BOTTOM = 0x02, 35 VERTICAL = 0x04, 36 CENTER = 0x08, 37 }; 38 39 enum Arrow { 40 TOP_LEFT = 0, 41 TOP_RIGHT = RIGHT, 42 BOTTOM_LEFT = BOTTOM, 43 BOTTOM_RIGHT = BOTTOM | RIGHT, 44 LEFT_TOP = VERTICAL, 45 RIGHT_TOP = VERTICAL | RIGHT, 46 LEFT_BOTTOM = VERTICAL | BOTTOM, 47 RIGHT_BOTTOM = VERTICAL | BOTTOM | RIGHT, 48 TOP_CENTER = CENTER, 49 BOTTOM_CENTER = CENTER | BOTTOM, 50 LEFT_CENTER = CENTER | VERTICAL, 51 RIGHT_CENTER = CENTER | VERTICAL | RIGHT, 52 NONE = 16, // No arrow. Positioned under the supplied rect. 53 FLOAT = 17, // No arrow. Centered over the supplied rect. 54 }; 55 56 enum Shadow { 57 SHADOW = 0, 58 NO_SHADOW, 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 // Get or set the client_bounds, a Windows-only temporary hack. 140 void set_client_bounds(const gfx::Rect& bounds) { client_bounds_ = bounds; } 141 const gfx::Rect& client_bounds() const { return client_bounds_; } 142 143 // Sets a desired pixel distance between the arrow tip and the outside edge of 144 // the neighboring border image. For example: |----offset----| 145 // '(' represents shadow around the '{' edge: ((({ ^ }))) 146 // The arrow will still anchor to the same location but the bubble will shift 147 // location to place the arrow |offset| pixels from the perpendicular edge. 148 void set_arrow_offset(int offset) { arrow_offset_ = offset; } 149 150 // Sets the way the arrow is actually painted. Default is PAINT_NORMAL. 151 void set_paint_arrow(ArrowPaintType value) { arrow_paint_type_ = value; } 152 153 // Get the desired widget bounds (in screen coordinates) given the anchor rect 154 // and bubble content size; calculated from shadow and arrow image dimensions. 155 virtual gfx::Rect GetBounds(const gfx::Rect& anchor_rect, 156 const gfx::Size& contents_size) const; 157 158 // Get the border exterior thickness, including stroke and shadow, in pixels. 159 int GetBorderThickness() const; 160 161 // Returns the corner radius of the current image set. 162 int GetBorderCornerRadius() const; 163 164 // Gets the arrow offset to use. 165 int GetArrowOffset(const gfx::Size& border_size) const; 166 167 // Overridden from Border: 168 virtual gfx::Insets GetInsets() const OVERRIDE; 169 virtual void Paint(const View& view, gfx::Canvas* canvas) OVERRIDE; 170 171 private: 172 gfx::ImageSkia* GetArrowImage() const; 173 gfx::Rect GetArrowRect(const gfx::Rect& bounds) const; 174 void DrawArrow(gfx::Canvas* canvas, const gfx::Rect& arrow_bounds) const; 175 176 Arrow arrow_; 177 int arrow_offset_; 178 ArrowPaintType arrow_paint_type_; 179 BubbleAlignment alignment_; 180 Shadow shadow_; 181 internal::BorderImages* images_; 182 SkColor background_color_; 183 184 // The client/content bounds; must be clipped from the background on Windows. 185 // TODO(msw): Clean this up when Windows native controls are no longer needed. 186 gfx::Rect client_bounds_; 187 188 DISALLOW_COPY_AND_ASSIGN(BubbleBorder); 189 }; 190 191 // A Background that clips itself to the specified BubbleBorder and uses 192 // the background color of the BubbleBorder. 193 class VIEWS_EXPORT BubbleBackground : public Background { 194 public: 195 explicit BubbleBackground(BubbleBorder* border) : border_(border) {} 196 197 // Overridden from Background: 198 virtual void Paint(gfx::Canvas* canvas, View* view) const OVERRIDE; 199 200 private: 201 BubbleBorder* border_; 202 203 DISALLOW_COPY_AND_ASSIGN(BubbleBackground); 204 }; 205 206 } // namespace views 207 208 #endif // UI_VIEWS_BUBBLE_BUBBLE_BORDER_H_ 209