• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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?
GetCornerRadius()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 
has_arrow(Arrow a)124   static bool has_arrow(Arrow a) { return a < NONE; }
125 
is_arrow_on_left(Arrow a)126   static bool is_arrow_on_left(Arrow a) {
127     return has_arrow(a) && (a == LEFT_CENTER || !(a & (RIGHT | CENTER)));
128   }
129 
is_arrow_on_top(Arrow a)130   static bool is_arrow_on_top(Arrow a) {
131     return has_arrow(a) && (a == TOP_CENTER || !(a & (BOTTOM | CENTER)));
132   }
133 
is_arrow_on_horizontal(Arrow a)134   static bool is_arrow_on_horizontal(Arrow a) {
135     return a >= NONE ? false : !(a & VERTICAL);
136   }
137 
is_arrow_at_center(Arrow a)138   static bool is_arrow_at_center(Arrow a) {
139     return has_arrow(a) && !!(a & CENTER);
140   }
141 
horizontal_mirror(Arrow a)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 
vertical_mirror(Arrow a)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.
set_arrow(Arrow arrow)153   void set_arrow(Arrow arrow) { arrow_ = arrow; }
arrow()154   Arrow arrow() const { return arrow_; }
155 
156   // Get or set the bubble alignment.
set_alignment(BubbleAlignment alignment)157   void set_alignment(BubbleAlignment alignment) { alignment_ = alignment; }
alignment()158   BubbleAlignment alignment() const { return alignment_; }
159 
160   // Get the shadow type.
shadow()161   Shadow shadow() const { return shadow_; }
162 
163   // Get or set the background color for the bubble and arrow body.
set_background_color(SkColor color)164   void set_background_color(SkColor color) { background_color_ = color; }
background_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.
set_use_theme_background_color(bool use_theme_background_color)169   void set_use_theme_background_color(bool use_theme_background_color) {
170     use_theme_background_color_ = use_theme_background_color;
171   }
use_theme_background_color()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.
set_arrow_offset(int offset)179   void set_arrow_offset(int offset) { arrow_offset_ = offset; }
180 
181   // Sets the way the arrow is actually painted.  Default is PAINT_NORMAL.
set_paint_arrow(ArrowPaintType value)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:
BubbleBackground(BubbleBorder * border)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_
247