#ifndef UI_VIEWS_BUBBLE_BUBBLE_BORDER_H_
#define UI_VIEWS_BUBBLE_BUBBLE_BORDER_H_
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
namespace gfx {
class ImageSkia;
}
namespace views {
class VIEWS_EXPORT BubbleBorder : public Border {
public:
enum ArrowLocationMask {
RIGHT = 0x01,
BOTTOM = 0x02,
VERTICAL = 0x04,
CENTER = 0x08,
};
enum ArrowLocation {
TOP_LEFT = 0,
TOP_RIGHT = RIGHT,
BOTTOM_LEFT = BOTTOM,
BOTTOM_RIGHT = BOTTOM | RIGHT,
LEFT_TOP = VERTICAL,
RIGHT_TOP = VERTICAL | RIGHT,
LEFT_BOTTOM = VERTICAL | BOTTOM,
RIGHT_BOTTOM = VERTICAL | BOTTOM | RIGHT,
TOP_CENTER = CENTER,
BOTTOM_CENTER = CENTER | BOTTOM,
LEFT_CENTER = CENTER | VERTICAL,
RIGHT_CENTER = CENTER | VERTICAL | RIGHT,
NONE = 16,
FLOAT = 17,
};
enum Shadow {
SHADOW = 0,
NO_SHADOW,
BIG_SHADOW,
SMALL_SHADOW,
SHADOW_COUNT,
};
enum BubbleAlignment {
ALIGN_ARROW_TO_MID_ANCHOR,
ALIGN_EDGE_TO_ANCHOR_EDGE
};
BubbleBorder(ArrowLocation arrow_location, Shadow shadow);
static int GetCornerRadius() {
return 4;
}
void set_arrow_location(ArrowLocation loc) { arrow_location_ = loc; }
ArrowLocation arrow_location() const { return arrow_location_; }
void set_alignment(BubbleAlignment alignment) { alignment_ = alignment; }
BubbleAlignment alignment() const { return alignment_; }
static ArrowLocation horizontal_mirror(ArrowLocation loc) {
return (loc == TOP_CENTER || loc == BOTTOM_CENTER || loc >= NONE) ?
loc : static_cast<ArrowLocation>(loc ^ RIGHT);
}
static ArrowLocation vertical_mirror(ArrowLocation loc) {
return (loc == LEFT_CENTER || loc == RIGHT_CENTER || loc >= NONE) ?
loc : static_cast<ArrowLocation>(loc ^ BOTTOM);
}
static bool has_arrow(ArrowLocation loc) {
return loc >= NONE ? false : true;
}
static bool is_arrow_on_left(ArrowLocation loc) {
return (loc == TOP_CENTER || loc == BOTTOM_CENTER || loc >= NONE) ?
false : !(loc & RIGHT);
}
static bool is_arrow_on_top(ArrowLocation loc) {
return (loc == LEFT_CENTER || loc == RIGHT_CENTER || loc >= NONE) ?
false : !(loc & BOTTOM);
}
static bool is_arrow_on_horizontal(ArrowLocation loc) {
return loc >= NONE ? false : !(loc & VERTICAL);
}
static bool is_arrow_at_center(ArrowLocation loc) {
return has_arrow(loc) && !!(loc & CENTER);
}
void set_background_color(SkColor color) { background_color_ = color; }
SkColor background_color() const { return background_color_; }
void set_client_bounds(const gfx::Rect& bounds) { client_bounds_ = bounds; }
const gfx::Rect& client_bounds() const { return client_bounds_; }
void set_arrow_offset(int offset) { override_arrow_offset_ = offset; }
virtual gfx::Rect GetBounds(const gfx::Rect& position_relative_to,
const gfx::Size& contents_size) const;
int GetBorderCornerRadius() const;
int GetArrowOffset(const gfx::Size& border_size) const;
virtual void GetInsets(gfx::Insets* insets) const OVERRIDE;
virtual int GetBorderThickness() const;
protected:
virtual ~BubbleBorder();
virtual void GetInsetsForArrowLocation(gfx::Insets* insets,
ArrowLocation arrow_loc) const;
private:
struct BorderImages;
static BorderImages* GetBorderImages(Shadow shadow);
virtual void Paint(const View& view,
gfx::Canvas* canvas) const OVERRIDE;
void DrawEdgeWithArrow(gfx::Canvas* canvas,
bool is_horizontal,
const gfx::ImageSkia& edge,
const gfx::ImageSkia& arrow,
int start_x,
int start_y,
int before_arrow,
int after_arrow,
int offset) const;
void DrawArrowInterior(gfx::Canvas* canvas, float tip_x, float tip_y) const;
struct BorderImages* images_;
static struct BorderImages* border_images_[SHADOW_COUNT];
int arrow_offset_;
int override_arrow_offset_;
ArrowLocation arrow_location_;
BubbleAlignment alignment_;
SkColor background_color_;
gfx::Rect client_bounds_;
DISALLOW_COPY_AND_ASSIGN(BubbleBorder);
};
class VIEWS_EXPORT BubbleBackground : public Background {
public:
explicit BubbleBackground(BubbleBorder* border) : border_(border) {}
virtual void Paint(gfx::Canvas* canvas, View* view) const OVERRIDE;
private:
BubbleBorder* border_;
DISALLOW_COPY_AND_ASSIGN(BubbleBackground);
};
}
#endif