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