Consolidate bubble border code.
[chromium-blink-merge.git] / ui / views / bubble / bubble_border.h
blobd883ca7c5ee33b119b38b549aac92f9d8473abf6
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.
5 #ifndef UI_VIEWS_BUBBLE_BUBBLE_BORDER_H_
6 #define UI_VIEWS_BUBBLE_BUBBLE_BORDER_H_
8 #include "base/basictypes.h"
9 #include "base/compiler_specific.h"
10 #include "ui/views/background.h"
11 #include "ui/views/border.h"
13 namespace gfx {
14 class ImageSkia;
17 namespace views {
19 // Renders a border, with optional arrow, and a custom dropshadow.
20 // This can be used to produce floating "bubble" objects with rounded corners.
21 class VIEWS_EXPORT BubbleBorder : public Border {
22 public:
23 // Possible locations for the (optional) arrow.
24 // 0 bit specifies left or right.
25 // 1 bit specifies top or bottom.
26 // 2 bit specifies horizontal or vertical.
27 // 3 bit specifies whether the arrow at the center of its residing edge.
28 enum ArrowLocationMask {
29 RIGHT = 0x01,
30 BOTTOM = 0x02,
31 VERTICAL = 0x04,
32 CENTER = 0x08,
35 enum ArrowLocation {
36 TOP_LEFT = 0,
37 TOP_RIGHT = RIGHT,
38 BOTTOM_LEFT = BOTTOM,
39 BOTTOM_RIGHT = BOTTOM | RIGHT,
40 LEFT_TOP = VERTICAL,
41 RIGHT_TOP = VERTICAL | RIGHT,
42 LEFT_BOTTOM = VERTICAL | BOTTOM,
43 RIGHT_BOTTOM = VERTICAL | BOTTOM | RIGHT,
44 TOP_CENTER = CENTER,
45 BOTTOM_CENTER = CENTER | BOTTOM,
46 LEFT_CENTER = CENTER | VERTICAL,
47 RIGHT_CENTER = CENTER | VERTICAL | RIGHT,
48 NONE = 16, // No arrow. Positioned under the supplied rect.
49 FLOAT = 17, // No arrow. Centered over the supplied rect.
52 enum Shadow {
53 SHADOW = 0,
54 NO_SHADOW,
55 BIG_SHADOW,
56 SMALL_SHADOW,
57 SHADOW_COUNT,
60 // The position of the bubble in relation to the anchor.
61 enum BubbleAlignment {
62 // The tip of the arrow points to the middle of the anchor.
63 ALIGN_ARROW_TO_MID_ANCHOR,
64 // The edge nearest to the arrow is lined up with the edge of the anchor.
65 ALIGN_EDGE_TO_ANCHOR_EDGE
68 BubbleBorder(ArrowLocation arrow_location, Shadow shadow);
70 // Returns the radius of the corner of the border.
71 // TODO(xiyuan): Get rid of this since it's part of BorderImages now?
72 static int GetCornerRadius() {
73 // We can't safely calculate a border radius by comparing the sizes of the
74 // side and corner images, because either may have been extended in various
75 // directions in order to do more subtle dropshadow fading or other effects.
76 // So we hardcode the most accurate value.
77 return 4;
80 // Sets the location for the arrow.
81 void set_arrow_location(ArrowLocation loc) { arrow_location_ = loc; }
82 ArrowLocation arrow_location() const { return arrow_location_; }
84 // Sets the alignment.
85 void set_alignment(BubbleAlignment alignment) { alignment_ = alignment; }
86 BubbleAlignment alignment() const { return alignment_; }
88 static ArrowLocation horizontal_mirror(ArrowLocation loc) {
89 return (loc == TOP_CENTER || loc == BOTTOM_CENTER || loc >= NONE) ?
90 loc : static_cast<ArrowLocation>(loc ^ RIGHT);
93 static ArrowLocation vertical_mirror(ArrowLocation loc) {
94 return (loc == LEFT_CENTER || loc == RIGHT_CENTER || loc >= NONE) ?
95 loc : static_cast<ArrowLocation>(loc ^ BOTTOM);
98 static bool has_arrow(ArrowLocation loc) {
99 return loc >= NONE ? false : true;
102 static bool is_arrow_on_left(ArrowLocation loc) {
103 return (loc == TOP_CENTER || loc == BOTTOM_CENTER || loc >= NONE) ?
104 false : !(loc & RIGHT);
107 static bool is_arrow_on_top(ArrowLocation loc) {
108 return (loc == LEFT_CENTER || loc == RIGHT_CENTER || loc >= NONE) ?
109 false : !(loc & BOTTOM);
112 static bool is_arrow_on_horizontal(ArrowLocation loc) {
113 return loc >= NONE ? false : !(loc & VERTICAL);
116 static bool is_arrow_at_center(ArrowLocation loc) {
117 return has_arrow(loc) && !!(loc & CENTER);
120 // Sets the background color for the arrow body. This is irrelevant if you do
121 // not also set the arrow location to something other than NONE.
122 void set_background_color(SkColor color) { background_color_ = color; }
123 SkColor background_color() const { return background_color_; }
125 void set_client_bounds(const gfx::Rect& bounds) { client_bounds_ = bounds; }
126 const gfx::Rect& client_bounds() const { return client_bounds_; }
128 // Sets a fixed offset for the arrow from the beginning of corresponding edge.
129 // The arrow will still point to the same location but the bubble will shift
130 // location to make that happen.
131 void set_arrow_offset(int offset) { override_arrow_offset_ = offset; }
133 // For borders with an arrow, gives the desired bounds (in screen coordinates)
134 // given the rect to point to and the size of the contained contents. This
135 // depends on the arrow location, so if you change that, you should call this
136 // again to find out the new coordinates.
137 virtual gfx::Rect GetBounds(const gfx::Rect& position_relative_to,
138 const gfx::Size& contents_size) const;
140 // Returns the corner radius of the current image set.
141 int GetBorderCornerRadius() const;
143 // Gets the arrow offset to use.
144 int GetArrowOffset(const gfx::Size& border_size) const;
146 // Overridden from Border:
147 virtual void GetInsets(gfx::Insets* insets) const OVERRIDE;
149 // How many pixels the bubble border is from the edge of the images.
150 virtual int GetBorderThickness() const;
152 protected:
153 virtual ~BubbleBorder();
155 // Calculates the insets for a specific arrow location. Normally called from
156 // GetInsets(arrow_location()), but may be called by specialized BubbleBorder
157 // implementations.
158 virtual void GetInsetsForArrowLocation(gfx::Insets* insets,
159 ArrowLocation arrow_loc) const;
161 private:
162 struct BorderImages;
164 // Loads images if necessary.
165 static BorderImages* GetBorderImages(Shadow shadow);
167 // Overridden from Border:
168 virtual void Paint(const View& view,
169 gfx::Canvas* canvas) const OVERRIDE;
171 void DrawEdgeWithArrow(gfx::Canvas* canvas,
172 bool is_horizontal,
173 const gfx::ImageSkia& edge,
174 const gfx::ImageSkia& arrow,
175 int start_x,
176 int start_y,
177 int before_arrow,
178 int after_arrow,
179 int offset) const;
181 void DrawArrowInterior(gfx::Canvas* canvas, float tip_x, float tip_y) const;
183 // Border graphics.
184 struct BorderImages* images_;
186 // Image bundles.
187 static struct BorderImages* border_images_[SHADOW_COUNT];
189 // Minimal offset of the arrow from the closet edge of bounding rect.
190 int arrow_offset_;
192 // If specified, overrides the pre-calculated |arrow_offset_| of the arrow.
193 int override_arrow_offset_;
195 ArrowLocation arrow_location_;
196 BubbleAlignment alignment_;
197 SkColor background_color_;
199 // The client/content bounds; must be clipped from the background on Windows.
200 // TODO(msw): Clean this up when Windows native controls are no longer needed.
201 gfx::Rect client_bounds_;
203 DISALLOW_COPY_AND_ASSIGN(BubbleBorder);
206 // A Background that clips itself to the specified BubbleBorder and uses
207 // the background color of the BubbleBorder.
208 class VIEWS_EXPORT BubbleBackground : public Background {
209 public:
210 explicit BubbleBackground(BubbleBorder* border) : border_(border) {}
212 // Overridden from Background:
213 virtual void Paint(gfx::Canvas* canvas, View* view) const OVERRIDE;
215 private:
216 BubbleBorder* border_;
218 DISALLOW_COPY_AND_ASSIGN(BubbleBackground);
221 } // namespace views
223 #endif // UI_VIEWS_BUBBLE_BUBBLE_BORDER_H_