diff options
Diffstat (limited to 'chrome/browser/ui/views/bubble_border.h')
-rw-r--r-- | chrome/browser/ui/views/bubble_border.h | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/chrome/browser/ui/views/bubble_border.h b/chrome/browser/ui/views/bubble_border.h new file mode 100644 index 0000000..4082d28 --- /dev/null +++ b/chrome/browser/ui/views/bubble_border.h @@ -0,0 +1,172 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_BUBBLE_BORDER_H_ +#define CHROME_BROWSER_UI_VIEWS_BUBBLE_BORDER_H_ +#pragma once + +#include "third_party/skia/include/core/SkColor.h" +#include "views/background.h" +#include "views/border.h" + +class SkBitmap; + +// Renders a border, with optional arrow, and a custom dropshadow. +// This can be used to produce floating "bubble" objects with rounded corners. +class BubbleBorder : public views::Border { + public: + // Possible locations for the (optional) arrow. + // 0 bit specifies left or right. + // 1 bit specifies top or bottom. + // 2 bit specifies horizontal or vertical. + enum ArrowLocation { + TOP_LEFT = 0, + TOP_RIGHT = 1, + BOTTOM_LEFT = 2, + BOTTOM_RIGHT = 3, + LEFT_TOP = 4, + RIGHT_TOP = 5, + LEFT_BOTTOM = 6, + RIGHT_BOTTOM = 7, + NONE = 8, // No arrow. Positioned under the supplied rect. + FLOAT = 9 // No arrow. Centered over the supplied rect. + }; + + explicit BubbleBorder(ArrowLocation arrow_location) + : override_arrow_offset_(0), + arrow_location_(arrow_location), + background_color_(SK_ColorWHITE) { + InitClass(); + } + + // Returns the radius of the corner of the border. + static int GetCornerRadius() { + // We can't safely calculate a border radius by comparing the sizes of the + // side and corner images, because either may have been extended in various + // directions in order to do more subtle dropshadow fading or other effects. + // So we hardcode the most accurate value. + return 4; + } + + // Sets the location for the arrow. + void set_arrow_location(ArrowLocation arrow_location) { + arrow_location_ = arrow_location; + } + ArrowLocation arrow_location() const { return arrow_location_; } + + static ArrowLocation horizontal_mirror(ArrowLocation loc) { + return loc >= NONE ? loc : static_cast<ArrowLocation>(loc ^ 1); + } + + static ArrowLocation vertical_mirror(ArrowLocation loc) { + return loc >= NONE ? loc : static_cast<ArrowLocation>(loc ^ 2); + } + + static bool has_arrow(ArrowLocation loc) { + return loc >= NONE ? false : true; + } + + static bool is_arrow_on_left(ArrowLocation loc) { + return loc >= NONE ? false : !(loc & 1); + } + + static bool is_arrow_on_top(ArrowLocation loc) { + return loc >= NONE ? false : !(loc & 2); + } + + static bool is_arrow_on_horizontal(ArrowLocation loc) { + return loc >= NONE ? false : !(loc & 4); + } + + // Sets the background color for the arrow body. This is irrelevant if you do + // not also set the arrow location to something other than NONE. + void set_background_color(SkColor background_color) { + background_color_ = background_color; + } + SkColor background_color() const { return background_color_; } + + // For borders with an arrow, gives the desired bounds (in screen coordinates) + // given the rect to point to and the size of the contained contents. This + // depends on the arrow location, so if you change that, you should call this + // again to find out the new coordinates. + gfx::Rect GetBounds(const gfx::Rect& position_relative_to, + const gfx::Size& contents_size) const; + + // Sets a fixed offset for the arrow from the beginning of corresponding edge. + // The arrow will still point to the same location but the bubble will shift + // location to make that happen. Returns actuall arrow offset, in case of + // overflow it differ from desired. + int SetArrowOffset(int offset, const gfx::Size& contents_size); + + // Overridden from views::Border: + virtual void GetInsets(gfx::Insets* insets) const; + + private: + // Loads images if necessary. + static void InitClass(); + + virtual ~BubbleBorder() { } + + // Overridden from views::Border: + virtual void Paint(const views::View& view, gfx::Canvas* canvas) const; + + void DrawEdgeWithArrow(gfx::Canvas* canvas, + bool is_horizontal, + SkBitmap* edge, + SkBitmap* arrow, + int start_x, + int start_y, + int before_arrow, + int after_arrow, + int offset) const; + + void DrawArrowInterior(gfx::Canvas* canvas, + bool is_horizontal, + int tip_x, + int tip_y, + int shift_x, + int shift_y) const; + + // Border graphics. + static SkBitmap* left_; + static SkBitmap* top_left_; + static SkBitmap* top_; + static SkBitmap* top_right_; + static SkBitmap* right_; + static SkBitmap* bottom_right_; + static SkBitmap* bottom_; + static SkBitmap* bottom_left_; + static SkBitmap* left_arrow_; + static SkBitmap* top_arrow_; + static SkBitmap* right_arrow_; + static SkBitmap* bottom_arrow_; + + // Minimal offset of the arrow from the closet edge of bounding rect. + static int arrow_offset_; + + // If specified, overrides the pre-calculated |arrow_offset_| of the arrow. + int override_arrow_offset_; + + ArrowLocation arrow_location_; + SkColor background_color_; + + DISALLOW_COPY_AND_ASSIGN(BubbleBorder); +}; + +// A Background that clips itself to the specified BubbleBorder and uses +// the background color of the BubbleBorder. +class BubbleBackground : public views::Background { + public: + explicit BubbleBackground(BubbleBorder* border) : border_(border) {} + + // Background overrides. + virtual void Paint(gfx::Canvas* canvas, views::View* view) const; + + private: + BubbleBorder* border_; + + DISALLOW_COPY_AND_ASSIGN(BubbleBackground); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_BUBBLE_BORDER_H_ |