diff options
Diffstat (limited to 'views/bubble/bubble_border.cc')
-rw-r--r-- | views/bubble/bubble_border.cc | 450 |
1 files changed, 0 insertions, 450 deletions
diff --git a/views/bubble/bubble_border.cc b/views/bubble/bubble_border.cc deleted file mode 100644 index 80e1bc8..0000000 --- a/views/bubble/bubble_border.cc +++ /dev/null @@ -1,450 +0,0 @@ -// Copyright (c) 2011 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. - -#include "views/bubble/bubble_border.h" - -#include <algorithm> // for std::max - -#include "base/logging.h" -#include "grit/ui_resources.h" -#include "grit/ui_resources_standard.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/canvas_skia.h" -#include "ui/gfx/path.h" - -namespace views { - -// static -SkBitmap* BubbleBorder::left_ = NULL; -SkBitmap* BubbleBorder::top_left_ = NULL; -SkBitmap* BubbleBorder::top_ = NULL; -SkBitmap* BubbleBorder::top_right_ = NULL; -SkBitmap* BubbleBorder::right_ = NULL; -SkBitmap* BubbleBorder::bottom_right_ = NULL; -SkBitmap* BubbleBorder::bottom_ = NULL; -SkBitmap* BubbleBorder::bottom_left_ = NULL; -SkBitmap* BubbleBorder::top_arrow_ = NULL; -SkBitmap* BubbleBorder::bottom_arrow_ = NULL; -SkBitmap* BubbleBorder::left_arrow_ = NULL; -SkBitmap* BubbleBorder::right_arrow_ = NULL; - -// static -int BubbleBorder::arrow_offset_; - -// The height inside the arrow image, in pixels. -static const int kArrowInteriorHeight = 7; - -gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& position_relative_to, - const gfx::Size& contents_size) const { - // Desired size is size of contents enlarged by the size of the border images. - gfx::Size border_size(contents_size); - gfx::Insets insets; - GetInsets(&insets); - border_size.Enlarge(insets.left() + insets.right(), - insets.top() + insets.bottom()); - - // Screen position depends on the arrow location. - // The arrow should overlap the target by some amount since there is space - // for shadow between arrow tip and bitmap bounds. - const int kArrowOverlap = 3; - int x = position_relative_to.x(); - int y = position_relative_to.y(); - int w = position_relative_to.width(); - int h = position_relative_to.height(); - int arrow_offset = override_arrow_offset_ ? override_arrow_offset_ : - arrow_offset_; - - // Calculate bubble x coordinate. - switch (arrow_location_) { - case TOP_LEFT: - case BOTTOM_LEFT: - x += w / 2 - arrow_offset; - break; - - case TOP_RIGHT: - case BOTTOM_RIGHT: - x += w / 2 + arrow_offset - border_size.width() + 1; - break; - - case LEFT_TOP: - case LEFT_BOTTOM: - x += w - kArrowOverlap; - break; - - case RIGHT_TOP: - case RIGHT_BOTTOM: - x += kArrowOverlap - border_size.width(); - break; - - case NONE: - case FLOAT: - x += w / 2 - border_size.width() / 2; - break; - } - - // Calculate bubble y coordinate. - switch (arrow_location_) { - case TOP_LEFT: - case TOP_RIGHT: - y += h - kArrowOverlap; - break; - - case BOTTOM_LEFT: - case BOTTOM_RIGHT: - y += kArrowOverlap - border_size.height(); - break; - - case LEFT_TOP: - case RIGHT_TOP: - y += h / 2 - arrow_offset; - break; - - case LEFT_BOTTOM: - case RIGHT_BOTTOM: - y += h / 2 + arrow_offset - border_size.height() + 1; - break; - - case NONE: - y += h; - break; - - case FLOAT: - y += h / 2 - border_size.height() / 2; - break; - } - - return gfx::Rect(x, y, border_size.width(), border_size.height()); -} - -void BubbleBorder::GetInsets(gfx::Insets* insets) const { - int top = top_->height(); - int bottom = bottom_->height(); - int left = left_->width(); - int right = right_->width(); - switch (arrow_location_) { - case TOP_LEFT: - case TOP_RIGHT: - top = std::max(top, top_arrow_->height()); - break; - - case BOTTOM_LEFT: - case BOTTOM_RIGHT: - bottom = std::max(bottom, bottom_arrow_->height()); - break; - - case LEFT_TOP: - case LEFT_BOTTOM: - left = std::max(left, left_arrow_->width()); - break; - - case RIGHT_TOP: - case RIGHT_BOTTOM: - right = std::max(right, right_arrow_->width()); - break; - - case NONE: - case FLOAT: - // Nothing to do. - break; - } - insets->Set(top, left, bottom, right); -} - -int BubbleBorder::SetArrowOffset(int offset, const gfx::Size& contents_size) { - gfx::Size border_size(contents_size); - gfx::Insets insets; - GetInsets(&insets); - border_size.Enlarge(insets.left() + insets.right(), - insets.top() + insets.bottom()); - offset = std::max(arrow_offset_, - std::min(offset, (is_arrow_on_horizontal(arrow_location_) ? - border_size.width() : border_size.height()) - arrow_offset_)); - override_arrow_offset_ = offset; - return override_arrow_offset_; -} - -// static -void BubbleBorder::InitClass() { - static bool initialized = false; - if (!initialized) { - // Load images. - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - left_ = rb.GetBitmapNamed(IDR_BUBBLE_L); - top_left_ = rb.GetBitmapNamed(IDR_BUBBLE_TL); - top_ = rb.GetBitmapNamed(IDR_BUBBLE_T); - top_right_ = rb.GetBitmapNamed(IDR_BUBBLE_TR); - right_ = rb.GetBitmapNamed(IDR_BUBBLE_R); - bottom_right_ = rb.GetBitmapNamed(IDR_BUBBLE_BR); - bottom_ = rb.GetBitmapNamed(IDR_BUBBLE_B); - bottom_left_ = rb.GetBitmapNamed(IDR_BUBBLE_BL); - left_arrow_ = rb.GetBitmapNamed(IDR_BUBBLE_L_ARROW); - top_arrow_ = rb.GetBitmapNamed(IDR_BUBBLE_T_ARROW); - right_arrow_ = rb.GetBitmapNamed(IDR_BUBBLE_R_ARROW); - bottom_arrow_ = rb.GetBitmapNamed(IDR_BUBBLE_B_ARROW); - - // Calculate horizontal and vertical insets for arrow by ensuring that - // the widest arrow and corner images will have enough room to avoid overlap - int offset_x = - (std::max(top_arrow_->width(), bottom_arrow_->width()) / 2) + - std::max(std::max(top_left_->width(), top_right_->width()), - std::max(bottom_left_->width(), bottom_right_->width())); - int offset_y = - (std::max(left_arrow_->height(), right_arrow_->height()) / 2) + - std::max(std::max(top_left_->height(), top_right_->height()), - std::max(bottom_left_->height(), bottom_right_->height())); - arrow_offset_ = std::max(offset_x, offset_y); - - initialized = true; - } -} - -void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) const { - // Convenience shorthand variables. - const int tl_width = top_left_->width(); - const int tl_height = top_left_->height(); - const int t_height = top_->height(); - const int tr_width = top_right_->width(); - const int tr_height = top_right_->height(); - const int l_width = left_->width(); - const int r_width = right_->width(); - const int br_width = bottom_right_->width(); - const int br_height = bottom_right_->height(); - const int b_height = bottom_->height(); - const int bl_width = bottom_left_->width(); - const int bl_height = bottom_left_->height(); - - gfx::Insets insets; - GetInsets(&insets); - const int top = insets.top() - t_height; - const int bottom = view.height() - insets.bottom() + b_height; - const int left = insets.left() - l_width; - const int right = view.width() - insets.right() + r_width; - const int height = bottom - top; - const int width = right - left; - - // |arrow_offset| is offset of arrow from the begining of the edge. - int arrow_offset = arrow_offset_; - if (override_arrow_offset_) - arrow_offset = override_arrow_offset_; - else if (is_arrow_on_horizontal(arrow_location_) && - !is_arrow_on_left(arrow_location_)) { - arrow_offset = view.width() - arrow_offset - 1; - } else if (!is_arrow_on_horizontal(arrow_location_) && - !is_arrow_on_top(arrow_location_)) { - arrow_offset = view.height() - arrow_offset - 1; - } - - // Left edge. - if (arrow_location_ == LEFT_TOP || arrow_location_ == LEFT_BOTTOM) { - int start_y = top + tl_height; - int before_arrow = arrow_offset - start_y - left_arrow_->height() / 2; - int after_arrow = - height - tl_height - bl_height - left_arrow_->height() - before_arrow; - DrawArrowInterior(canvas, - false, - left_arrow_->width() - kArrowInteriorHeight, - start_y + before_arrow + left_arrow_->height() / 2, - kArrowInteriorHeight, - left_arrow_->height() / 2 - 1); - DrawEdgeWithArrow(canvas, - false, - left_, - left_arrow_, - left, - start_y, - before_arrow, - after_arrow, - left_->width() - left_arrow_->width()); - } else { - canvas->TileImageInt(*left_, left, top + tl_height, l_width, - height - tl_height - bl_height); - } - - // Top left corner. - canvas->DrawBitmapInt(*top_left_, left, top); - - // Top edge. - if (arrow_location_ == TOP_LEFT || arrow_location_ == TOP_RIGHT) { - int start_x = left + tl_width; - int before_arrow = arrow_offset - start_x - top_arrow_->width() / 2; - int after_arrow = - width - tl_width - tr_width - top_arrow_->width() - before_arrow; - DrawArrowInterior(canvas, - true, - start_x + before_arrow + top_arrow_->width() / 2, - top_arrow_->height() - kArrowInteriorHeight, - 1 - top_arrow_->width() / 2, - kArrowInteriorHeight); - DrawEdgeWithArrow(canvas, - true, - top_, - top_arrow_, - start_x, - top, - before_arrow, - after_arrow, - top_->height() - top_arrow_->height()); - } else { - canvas->TileImageInt(*top_, left + tl_width, top, - width - tl_width - tr_width, t_height); - } - - // Top right corner. - canvas->DrawBitmapInt(*top_right_, right - tr_width, top); - - // Right edge. - if (arrow_location_ == RIGHT_TOP || arrow_location_ == RIGHT_BOTTOM) { - int start_y = top + tr_height; - int before_arrow = arrow_offset - start_y - right_arrow_->height() / 2; - int after_arrow = height - tl_height - bl_height - - right_arrow_->height() - before_arrow; - DrawArrowInterior(canvas, - false, - right - r_width + kArrowInteriorHeight, - start_y + before_arrow + right_arrow_->height() / 2, - -kArrowInteriorHeight, - right_arrow_->height() / 2 - 1); - DrawEdgeWithArrow(canvas, - false, - right_, - right_arrow_, - right - r_width, - start_y, - before_arrow, - after_arrow, - 0); - } else { - canvas->TileImageInt(*right_, right - r_width, top + tr_height, r_width, - height - tr_height - br_height); - } - - // Bottom right corner. - canvas->DrawBitmapInt(*bottom_right_, right - br_width, bottom - br_height); - - // Bottom edge. - if (arrow_location_ == BOTTOM_LEFT || arrow_location_ == BOTTOM_RIGHT) { - int start_x = left + bl_width; - int before_arrow = arrow_offset - start_x - bottom_arrow_->width() / 2; - int after_arrow = - width - bl_width - br_width - bottom_arrow_->width() - before_arrow; - DrawArrowInterior(canvas, - true, - start_x + before_arrow + bottom_arrow_->width() / 2, - bottom - b_height + kArrowInteriorHeight, - 1 - bottom_arrow_->width() / 2, - -kArrowInteriorHeight); - DrawEdgeWithArrow(canvas, - true, - bottom_, - bottom_arrow_, - start_x, - bottom - b_height, - before_arrow, - after_arrow, - 0); - } else { - canvas->TileImageInt(*bottom_, left + bl_width, bottom - b_height, - width - bl_width - br_width, b_height); - } - - // Bottom left corner. - canvas->DrawBitmapInt(*bottom_left_, left, bottom - bl_height); -} - -void BubbleBorder::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 { - /* Here's what the parameters mean: - * start_x - * . - * . ┌───┐ ┬ offset - * start_y..........┌────┬────────┤ ▲ ├────────┬────┐ - * │ / │--------│∙ ∙│--------│ \ │ - * │ / ├────────┴───┴────────┤ \ │ - * ├───┬┘ └┬───┤ - * └───┬────┘ └───┬────┘ - * before_arrow ─┘ └─ after_arrow - */ - if (before_arrow) { - canvas->TileImageInt(*edge, start_x, start_y, - is_horizontal ? before_arrow : edge->width(), - is_horizontal ? edge->height() : before_arrow); - } - - canvas->DrawBitmapInt(*arrow, - start_x + (is_horizontal ? before_arrow : offset), - start_y + (is_horizontal ? offset : before_arrow)); - - if (after_arrow) { - start_x += (is_horizontal ? before_arrow + arrow->width() : 0); - start_y += (is_horizontal ? 0 : before_arrow + arrow->height()); - canvas->TileImageInt(*edge, start_x, start_y, - is_horizontal ? after_arrow : edge->width(), - is_horizontal ? edge->height() : after_arrow); - } -} - -void BubbleBorder::DrawArrowInterior(gfx::Canvas* canvas, - bool is_horizontal, - int tip_x, - int tip_y, - int shift_x, - int shift_y) const { - /* This function fills the interior of the arrow with background color. - * It draws isosceles triangle under semitransparent arrow tip. - * - * Here's what the parameters mean: - * - * ┌──────── |tip_x| - * ┌─────┐ - * │ ▲ │ ──── |tip y| - * │∙∙∙∙∙│ ┐ - * └─────┘ └─── |shift_x| (offset from tip to vertexes of isosceles triangle) - * └────────── |shift_y| - */ - SkPaint paint; - paint.setStyle(SkPaint::kFill_Style); - paint.setColor(background_color_); - gfx::Path path; - path.incReserve(4); - path.moveTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); - path.lineTo(SkIntToScalar(tip_x + shift_x), - SkIntToScalar(tip_y + shift_y)); - if (is_horizontal) - path.lineTo(SkIntToScalar(tip_x - shift_x), SkIntToScalar(tip_y + shift_y)); - else - path.lineTo(SkIntToScalar(tip_x + shift_x), SkIntToScalar(tip_y - shift_y)); - path.close(); - canvas->AsCanvasSkia()->drawPath(path, paint); -} - -///////////////////////// - -void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const { - // The border of this view creates an anti-aliased round-rect region for the - // contents, which we need to fill with the background color. - // NOTE: This doesn't handle an arrow location of "NONE", which has square top - // corners. - SkPaint paint; - paint.setAntiAlias(true); - paint.setStyle(SkPaint::kFill_Style); - paint.setColor(border_->background_color()); - gfx::Path path; - gfx::Rect bounds(view->GetContentsBounds()); - SkRect rect; - rect.set(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()), - SkIntToScalar(bounds.right()), SkIntToScalar(bounds.bottom())); - SkScalar radius = SkIntToScalar(BubbleBorder::GetCornerRadius()); - path.addRoundRect(rect, radius, radius); - canvas->AsCanvasSkia()->drawPath(path, paint); -} - -} // namespace views |