blob: ffb0fbb0700ae0395af3548f5d9625bf54a41dfa [file] [log] [blame]
// Copyright (c) 2012 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 "ui/views/bubble/bubble_border.h"
#include <stddef.h>
#include <memory>
#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/test/views_test_base.h"
namespace views {
typedef views::ViewsTestBase BubbleBorderTest;
TEST_F(BubbleBorderTest, GetMirroredArrow) {
// Horizontal mirroring.
EXPECT_EQ(BubbleBorder::TOP_RIGHT,
BubbleBorder::horizontal_mirror(BubbleBorder::TOP_LEFT));
EXPECT_EQ(BubbleBorder::TOP_LEFT,
BubbleBorder::horizontal_mirror(BubbleBorder::TOP_RIGHT));
EXPECT_EQ(BubbleBorder::BOTTOM_RIGHT,
BubbleBorder::horizontal_mirror(BubbleBorder::BOTTOM_LEFT));
EXPECT_EQ(BubbleBorder::BOTTOM_LEFT,
BubbleBorder::horizontal_mirror(BubbleBorder::BOTTOM_RIGHT));
EXPECT_EQ(BubbleBorder::RIGHT_TOP,
BubbleBorder::horizontal_mirror(BubbleBorder::LEFT_TOP));
EXPECT_EQ(BubbleBorder::LEFT_TOP,
BubbleBorder::horizontal_mirror(BubbleBorder::RIGHT_TOP));
EXPECT_EQ(BubbleBorder::RIGHT_BOTTOM,
BubbleBorder::horizontal_mirror(BubbleBorder::LEFT_BOTTOM));
EXPECT_EQ(BubbleBorder::LEFT_BOTTOM,
BubbleBorder::horizontal_mirror(BubbleBorder::RIGHT_BOTTOM));
EXPECT_EQ(BubbleBorder::TOP_CENTER,
BubbleBorder::horizontal_mirror(BubbleBorder::TOP_CENTER));
EXPECT_EQ(BubbleBorder::BOTTOM_CENTER,
BubbleBorder::horizontal_mirror(BubbleBorder::BOTTOM_CENTER));
EXPECT_EQ(BubbleBorder::RIGHT_CENTER,
BubbleBorder::horizontal_mirror(BubbleBorder::LEFT_CENTER));
EXPECT_EQ(BubbleBorder::LEFT_CENTER,
BubbleBorder::horizontal_mirror(BubbleBorder::RIGHT_CENTER));
EXPECT_EQ(BubbleBorder::NONE,
BubbleBorder::horizontal_mirror(BubbleBorder::NONE));
EXPECT_EQ(BubbleBorder::FLOAT,
BubbleBorder::horizontal_mirror(BubbleBorder::FLOAT));
// Vertical mirroring.
EXPECT_EQ(BubbleBorder::BOTTOM_LEFT,
BubbleBorder::vertical_mirror(BubbleBorder::TOP_LEFT));
EXPECT_EQ(BubbleBorder::BOTTOM_RIGHT,
BubbleBorder::vertical_mirror(BubbleBorder::TOP_RIGHT));
EXPECT_EQ(BubbleBorder::TOP_LEFT,
BubbleBorder::vertical_mirror(BubbleBorder::BOTTOM_LEFT));
EXPECT_EQ(BubbleBorder::TOP_RIGHT,
BubbleBorder::vertical_mirror(BubbleBorder::BOTTOM_RIGHT));
EXPECT_EQ(BubbleBorder::LEFT_BOTTOM,
BubbleBorder::vertical_mirror(BubbleBorder::LEFT_TOP));
EXPECT_EQ(BubbleBorder::RIGHT_BOTTOM,
BubbleBorder::vertical_mirror(BubbleBorder::RIGHT_TOP));
EXPECT_EQ(BubbleBorder::LEFT_TOP,
BubbleBorder::vertical_mirror(BubbleBorder::LEFT_BOTTOM));
EXPECT_EQ(BubbleBorder::RIGHT_TOP,
BubbleBorder::vertical_mirror(BubbleBorder::RIGHT_BOTTOM));
EXPECT_EQ(BubbleBorder::BOTTOM_CENTER,
BubbleBorder::vertical_mirror(BubbleBorder::TOP_CENTER));
EXPECT_EQ(BubbleBorder::TOP_CENTER,
BubbleBorder::vertical_mirror(BubbleBorder::BOTTOM_CENTER));
EXPECT_EQ(BubbleBorder::LEFT_CENTER,
BubbleBorder::vertical_mirror(BubbleBorder::LEFT_CENTER));
EXPECT_EQ(BubbleBorder::RIGHT_CENTER,
BubbleBorder::vertical_mirror(BubbleBorder::RIGHT_CENTER));
EXPECT_EQ(BubbleBorder::NONE,
BubbleBorder::vertical_mirror(BubbleBorder::NONE));
EXPECT_EQ(BubbleBorder::FLOAT,
BubbleBorder::vertical_mirror(BubbleBorder::FLOAT));
}
TEST_F(BubbleBorderTest, HasArrow) {
EXPECT_TRUE(BubbleBorder::has_arrow(BubbleBorder::TOP_LEFT));
EXPECT_TRUE(BubbleBorder::has_arrow(BubbleBorder::TOP_RIGHT));
EXPECT_TRUE(BubbleBorder::has_arrow(BubbleBorder::BOTTOM_LEFT));
EXPECT_TRUE(BubbleBorder::has_arrow(BubbleBorder::BOTTOM_RIGHT));
EXPECT_TRUE(BubbleBorder::has_arrow(BubbleBorder::LEFT_TOP));
EXPECT_TRUE(BubbleBorder::has_arrow(BubbleBorder::RIGHT_TOP));
EXPECT_TRUE(BubbleBorder::has_arrow(BubbleBorder::LEFT_BOTTOM));
EXPECT_TRUE(BubbleBorder::has_arrow(BubbleBorder::RIGHT_BOTTOM));
EXPECT_TRUE(BubbleBorder::has_arrow(BubbleBorder::TOP_CENTER));
EXPECT_TRUE(BubbleBorder::has_arrow(BubbleBorder::BOTTOM_CENTER));
EXPECT_TRUE(BubbleBorder::has_arrow(BubbleBorder::LEFT_CENTER));
EXPECT_TRUE(BubbleBorder::has_arrow(BubbleBorder::RIGHT_CENTER));
EXPECT_FALSE(BubbleBorder::has_arrow(BubbleBorder::NONE));
EXPECT_FALSE(BubbleBorder::has_arrow(BubbleBorder::FLOAT));
}
TEST_F(BubbleBorderTest, IsArrowOnLeft) {
EXPECT_TRUE(BubbleBorder::is_arrow_on_left(BubbleBorder::TOP_LEFT));
EXPECT_FALSE(BubbleBorder::is_arrow_on_left(BubbleBorder::TOP_RIGHT));
EXPECT_TRUE(BubbleBorder::is_arrow_on_left(BubbleBorder::BOTTOM_LEFT));
EXPECT_FALSE(BubbleBorder::is_arrow_on_left(BubbleBorder::BOTTOM_RIGHT));
EXPECT_TRUE(BubbleBorder::is_arrow_on_left(BubbleBorder::LEFT_TOP));
EXPECT_FALSE(BubbleBorder::is_arrow_on_left(BubbleBorder::RIGHT_TOP));
EXPECT_TRUE(BubbleBorder::is_arrow_on_left(BubbleBorder::LEFT_BOTTOM));
EXPECT_FALSE(BubbleBorder::is_arrow_on_left(BubbleBorder::RIGHT_BOTTOM));
EXPECT_FALSE(BubbleBorder::is_arrow_on_left(BubbleBorder::TOP_CENTER));
EXPECT_FALSE(BubbleBorder::is_arrow_on_left(BubbleBorder::BOTTOM_CENTER));
EXPECT_TRUE(BubbleBorder::is_arrow_on_left(BubbleBorder::LEFT_CENTER));
EXPECT_FALSE(BubbleBorder::is_arrow_on_left(BubbleBorder::RIGHT_CENTER));
EXPECT_FALSE(BubbleBorder::is_arrow_on_left(BubbleBorder::NONE));
EXPECT_FALSE(BubbleBorder::is_arrow_on_left(BubbleBorder::FLOAT));
}
TEST_F(BubbleBorderTest, IsArrowOnTop) {
EXPECT_TRUE(BubbleBorder::is_arrow_on_top(BubbleBorder::TOP_LEFT));
EXPECT_TRUE(BubbleBorder::is_arrow_on_top(BubbleBorder::TOP_RIGHT));
EXPECT_FALSE(BubbleBorder::is_arrow_on_top(BubbleBorder::BOTTOM_LEFT));
EXPECT_FALSE(BubbleBorder::is_arrow_on_top(BubbleBorder::BOTTOM_RIGHT));
EXPECT_TRUE(BubbleBorder::is_arrow_on_top(BubbleBorder::LEFT_TOP));
EXPECT_TRUE(BubbleBorder::is_arrow_on_top(BubbleBorder::RIGHT_TOP));
EXPECT_FALSE(BubbleBorder::is_arrow_on_top(BubbleBorder::LEFT_BOTTOM));
EXPECT_FALSE(BubbleBorder::is_arrow_on_top(BubbleBorder::RIGHT_BOTTOM));
EXPECT_TRUE(BubbleBorder::is_arrow_on_top(BubbleBorder::TOP_CENTER));
EXPECT_FALSE(BubbleBorder::is_arrow_on_top(BubbleBorder::BOTTOM_CENTER));
EXPECT_FALSE(BubbleBorder::is_arrow_on_top(BubbleBorder::LEFT_CENTER));
EXPECT_FALSE(BubbleBorder::is_arrow_on_top(BubbleBorder::RIGHT_CENTER));
EXPECT_FALSE(BubbleBorder::is_arrow_on_top(BubbleBorder::NONE));
EXPECT_FALSE(BubbleBorder::is_arrow_on_top(BubbleBorder::FLOAT));
}
TEST_F(BubbleBorderTest, IsArrowOnHorizontal) {
EXPECT_TRUE(BubbleBorder::is_arrow_on_horizontal(BubbleBorder::TOP_LEFT));
EXPECT_TRUE(BubbleBorder::is_arrow_on_horizontal(BubbleBorder::TOP_RIGHT));
EXPECT_TRUE(BubbleBorder::is_arrow_on_horizontal(BubbleBorder::BOTTOM_LEFT));
EXPECT_TRUE(BubbleBorder::is_arrow_on_horizontal(BubbleBorder::BOTTOM_RIGHT));
EXPECT_FALSE(BubbleBorder::is_arrow_on_horizontal(BubbleBorder::LEFT_TOP));
EXPECT_FALSE(BubbleBorder::is_arrow_on_horizontal(BubbleBorder::RIGHT_TOP));
EXPECT_FALSE(BubbleBorder::is_arrow_on_horizontal(BubbleBorder::LEFT_BOTTOM));
EXPECT_FALSE(
BubbleBorder::is_arrow_on_horizontal(BubbleBorder::RIGHT_BOTTOM));
EXPECT_TRUE(BubbleBorder::is_arrow_on_horizontal(BubbleBorder::TOP_CENTER));
EXPECT_TRUE(
BubbleBorder::is_arrow_on_horizontal(BubbleBorder::BOTTOM_CENTER));
EXPECT_FALSE(BubbleBorder::is_arrow_on_horizontal(BubbleBorder::LEFT_CENTER));
EXPECT_FALSE(
BubbleBorder::is_arrow_on_horizontal(BubbleBorder::RIGHT_CENTER));
EXPECT_FALSE(BubbleBorder::is_arrow_on_horizontal(BubbleBorder::NONE));
EXPECT_FALSE(BubbleBorder::is_arrow_on_horizontal(BubbleBorder::FLOAT));
}
TEST_F(BubbleBorderTest, IsArrowAtCenter) {
EXPECT_FALSE(BubbleBorder::is_arrow_at_center(BubbleBorder::TOP_LEFT));
EXPECT_FALSE(BubbleBorder::is_arrow_at_center(BubbleBorder::TOP_RIGHT));
EXPECT_FALSE(BubbleBorder::is_arrow_at_center(BubbleBorder::BOTTOM_LEFT));
EXPECT_FALSE(BubbleBorder::is_arrow_at_center(BubbleBorder::BOTTOM_RIGHT));
EXPECT_FALSE(BubbleBorder::is_arrow_at_center(BubbleBorder::LEFT_TOP));
EXPECT_FALSE(BubbleBorder::is_arrow_at_center(BubbleBorder::RIGHT_TOP));
EXPECT_FALSE(BubbleBorder::is_arrow_at_center(BubbleBorder::LEFT_BOTTOM));
EXPECT_FALSE(BubbleBorder::is_arrow_at_center(BubbleBorder::RIGHT_BOTTOM));
EXPECT_TRUE(BubbleBorder::is_arrow_at_center(BubbleBorder::TOP_CENTER));
EXPECT_TRUE(BubbleBorder::is_arrow_at_center(BubbleBorder::BOTTOM_CENTER));
EXPECT_TRUE(BubbleBorder::is_arrow_at_center(BubbleBorder::LEFT_CENTER));
EXPECT_TRUE(BubbleBorder::is_arrow_at_center(BubbleBorder::RIGHT_CENTER));
EXPECT_FALSE(BubbleBorder::is_arrow_at_center(BubbleBorder::NONE));
EXPECT_FALSE(BubbleBorder::is_arrow_at_center(BubbleBorder::FLOAT));
}
TEST_F(BubbleBorderTest, GetSizeForContentsSizeTest) {
views::BubbleBorder border(BubbleBorder::NONE,
BubbleBorder::NO_SHADOW,
SK_ColorWHITE);
const views::internal::BorderImages* kImages = border.GetImagesForTest();
// kSmallSize is smaller than the minimum allowable size and does not
// contribute to the resulting size.
const gfx::Size kSmallSize = gfx::Size(1, 2);
// kMediumSize is larger than the minimum allowable size and contributes to
// the resulting size.
const gfx::Size kMediumSize = gfx::Size(50, 60);
const gfx::Size kSmallHorizArrow(
2 * kImages->border_thickness + kImages->arrow_width,
kImages->border_thickness + kImages->arrow_thickness +
kImages->border_interior_thickness);
const gfx::Size kSmallVertArrow(kSmallHorizArrow.height(),
kSmallHorizArrow.width());
const gfx::Size kSmallNoArrow(2 * kImages->border_thickness,
2 * kImages->border_thickness);
const gfx::Size kMediumHorizArrow(
kMediumSize.width() + 2 * border.GetBorderThickness(),
kMediumSize.height() + border.GetBorderThickness() +
kImages->arrow_thickness);
const gfx::Size kMediumVertArrow(
kMediumSize.width() + border.GetBorderThickness() +
kImages->arrow_thickness,
kMediumSize.height() + 2 * border.GetBorderThickness());
const gfx::Size kMediumNoArrow(
kMediumSize.width() + 2 * border.GetBorderThickness(),
kMediumSize.height() + 2 * border.GetBorderThickness());
struct TestCase {
BubbleBorder::Arrow arrow;
gfx::Size content;
gfx::Size expected_with_arrow;
gfx::Size expected_without_arrow;
};
TestCase cases[] = {
// Content size: kSmallSize
{ BubbleBorder::TOP_LEFT, kSmallSize, kSmallHorizArrow, kSmallNoArrow },
{ BubbleBorder::TOP_CENTER, kSmallSize, kSmallHorizArrow, kSmallNoArrow },
{ BubbleBorder::TOP_RIGHT, kSmallSize, kSmallHorizArrow, kSmallNoArrow },
{ BubbleBorder::BOTTOM_LEFT, kSmallSize, kSmallHorizArrow, kSmallNoArrow },
{ BubbleBorder::BOTTOM_CENTER, kSmallSize, kSmallHorizArrow,
kSmallNoArrow },
{ BubbleBorder::BOTTOM_RIGHT, kSmallSize, kSmallHorizArrow, kSmallNoArrow },
{ BubbleBorder::LEFT_TOP, kSmallSize, kSmallVertArrow, kSmallNoArrow },
{ BubbleBorder::LEFT_CENTER, kSmallSize, kSmallVertArrow, kSmallNoArrow },
{ BubbleBorder::LEFT_BOTTOM, kSmallSize, kSmallVertArrow, kSmallNoArrow },
{ BubbleBorder::RIGHT_TOP, kSmallSize, kSmallVertArrow, kSmallNoArrow },
{ BubbleBorder::RIGHT_CENTER, kSmallSize, kSmallVertArrow, kSmallNoArrow },
{ BubbleBorder::RIGHT_BOTTOM, kSmallSize, kSmallVertArrow, kSmallNoArrow },
{ BubbleBorder::NONE, kSmallSize, kSmallNoArrow, kSmallNoArrow },
{ BubbleBorder::FLOAT, kSmallSize, kSmallNoArrow, kSmallNoArrow },
// Content size: kMediumSize
{ BubbleBorder::TOP_LEFT, kMediumSize, kMediumHorizArrow, kMediumNoArrow },
{ BubbleBorder::TOP_CENTER, kMediumSize, kMediumHorizArrow,
kMediumNoArrow },
{ BubbleBorder::TOP_RIGHT, kMediumSize, kMediumHorizArrow, kMediumNoArrow },
{ BubbleBorder::BOTTOM_LEFT, kMediumSize, kMediumHorizArrow,
kMediumNoArrow },
{ BubbleBorder::BOTTOM_CENTER, kMediumSize, kMediumHorizArrow,
kMediumNoArrow },
{ BubbleBorder::BOTTOM_RIGHT, kMediumSize, kMediumHorizArrow,
kMediumNoArrow },
{ BubbleBorder::LEFT_TOP, kMediumSize, kMediumVertArrow, kMediumNoArrow },
{ BubbleBorder::LEFT_CENTER, kMediumSize, kMediumVertArrow,
kMediumNoArrow },
{ BubbleBorder::LEFT_BOTTOM, kMediumSize, kMediumVertArrow,
kMediumNoArrow },
{ BubbleBorder::RIGHT_TOP, kMediumSize, kMediumVertArrow, kMediumNoArrow },
{ BubbleBorder::RIGHT_CENTER, kMediumSize, kMediumVertArrow,
kMediumNoArrow },
{ BubbleBorder::RIGHT_BOTTOM, kMediumSize, kMediumVertArrow,
kMediumNoArrow },
{ BubbleBorder::NONE, kMediumSize, kMediumNoArrow, kMediumNoArrow },
{ BubbleBorder::FLOAT, kMediumSize, kMediumNoArrow, kMediumNoArrow }
};
for (size_t i = 0; i < arraysize(cases); ++i) {
SCOPED_TRACE(base::StringPrintf("i=%d arrow=%d",
static_cast<int>(i), cases[i].arrow));
border.set_arrow(cases[i].arrow);
border.set_paint_arrow(BubbleBorder::PAINT_NORMAL);
EXPECT_EQ(cases[i].expected_with_arrow,
border.GetSizeForContentsSize(cases[i].content));
border.set_paint_arrow(BubbleBorder::PAINT_TRANSPARENT);
EXPECT_EQ(cases[i].expected_without_arrow,
border.GetSizeForContentsSize(cases[i].content));
border.set_paint_arrow(BubbleBorder::PAINT_NONE);
EXPECT_EQ(cases[i].expected_without_arrow,
border.GetSizeForContentsSize(cases[i].content));
}
}
TEST_F(BubbleBorderTest, GetBoundsOriginTest) {
views::BubbleBorder border(BubbleBorder::TOP_LEFT,
BubbleBorder::NO_SHADOW,
SK_ColorWHITE);
const gfx::Rect kAnchor(100, 100, 20, 30);
const gfx::Size kContentSize(50, 60);
const views::internal::BorderImages* kImages = border.GetImagesForTest();
border.set_arrow(BubbleBorder::TOP_LEFT);
const gfx::Size kTotalSizeWithHorizArrow =
border.GetSizeForContentsSize(kContentSize);
border.set_arrow(BubbleBorder::RIGHT_BOTTOM);
const gfx::Size kTotalSizeWithVertArrow =
border.GetSizeForContentsSize(kContentSize);
border.set_arrow(BubbleBorder::NONE);
const gfx::Size kTotalSizeWithNoArrow =
border.GetSizeForContentsSize(kContentSize);
const int kBorderThickness = border.GetBorderThickness();
const int kArrowOffsetForHorizCenter = kTotalSizeWithHorizArrow.width() / 2;
const int kArrowOffsetForVertCenter = kTotalSizeWithVertArrow.height() / 2;
const int kArrowOffsetForNotCenter =
kImages->border_thickness + (kImages->arrow_width / 2);
const int kArrowThickness = kImages->arrow_interior_thickness;
const int kArrowShift =
kArrowThickness + BubbleBorder::kStroke - kImages->arrow_thickness;
const int kHeightDifference = kTotalSizeWithHorizArrow.height() -
kTotalSizeWithNoArrow.height();
const int kWidthDifference = kTotalSizeWithVertArrow.width() -
kTotalSizeWithNoArrow.width();
EXPECT_EQ(kHeightDifference, kWidthDifference);
EXPECT_EQ(kHeightDifference, kArrowThickness);
const int kTopHorizArrowY = kAnchor.y() + kAnchor.height() + kArrowShift;
const int kBottomHorizArrowY =
kAnchor.y() - kArrowShift - kTotalSizeWithHorizArrow.height();
const int kLeftVertArrowX = kAnchor.x() + kAnchor.width() + kArrowShift;
const int kRightVertArrowX =
kAnchor.x() - kArrowShift - kTotalSizeWithVertArrow.width();
struct TestCase {
BubbleBorder::Arrow arrow;
BubbleBorder::BubbleAlignment alignment;
int expected_x;
int expected_y;
};
TestCase cases[] = {
// Horizontal arrow tests.
{ BubbleBorder::TOP_LEFT, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR,
kAnchor.CenterPoint().x() - kArrowOffsetForNotCenter, kTopHorizArrowY },
{ BubbleBorder::TOP_LEFT, BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE,
kAnchor.x() + BubbleBorder::kStroke - kBorderThickness, kTopHorizArrowY },
{ BubbleBorder::TOP_CENTER, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR,
kAnchor.CenterPoint().x() - kArrowOffsetForHorizCenter, kTopHorizArrowY },
{ BubbleBorder::BOTTOM_RIGHT, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR,
kAnchor.CenterPoint().x() + kArrowOffsetForNotCenter -
kTotalSizeWithHorizArrow.width(), kBottomHorizArrowY },
{ BubbleBorder::BOTTOM_RIGHT, BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE,
kAnchor.x() + kAnchor.width() - kTotalSizeWithHorizArrow.width() +
kBorderThickness - BubbleBorder::kStroke, kBottomHorizArrowY },
// Vertical arrow tests.
{ BubbleBorder::LEFT_TOP, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR,
kLeftVertArrowX, kAnchor.CenterPoint().y() - kArrowOffsetForNotCenter },
{ BubbleBorder::LEFT_TOP, BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE,
kLeftVertArrowX, kAnchor.y() + BubbleBorder::kStroke - kBorderThickness },
{ BubbleBorder::LEFT_CENTER, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR,
kLeftVertArrowX, kAnchor.CenterPoint().y() - kArrowOffsetForVertCenter },
{ BubbleBorder::RIGHT_BOTTOM, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR,
kRightVertArrowX, kAnchor.CenterPoint().y() + kArrowOffsetForNotCenter -
kTotalSizeWithVertArrow.height() },
{ BubbleBorder::RIGHT_BOTTOM, BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE,
kRightVertArrowX, kAnchor.y() + kAnchor.height() -
kTotalSizeWithVertArrow.height() + kBorderThickness -
BubbleBorder::kStroke },
// No arrow tests.
{ BubbleBorder::NONE, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR,
kAnchor.x() + (kAnchor.width() - kTotalSizeWithNoArrow.width()) / 2,
kAnchor.y() + kAnchor.height() },
{ BubbleBorder::FLOAT, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR,
kAnchor.x() + (kAnchor.width() - kTotalSizeWithNoArrow.width()) / 2,
kAnchor.y() + (kAnchor.height() - kTotalSizeWithNoArrow.height()) / 2 },
};
for (size_t i = 0; i < arraysize(cases); ++i) {
SCOPED_TRACE(base::StringPrintf("i=%d arrow=%d alignment=%d",
static_cast<int>(i), cases[i].arrow, cases[i].alignment));
const BubbleBorder::Arrow arrow = cases[i].arrow;
border.set_arrow(arrow);
border.set_alignment(cases[i].alignment);
border.set_paint_arrow(BubbleBorder::PAINT_NORMAL);
gfx::Point origin = border.GetBounds(kAnchor, kContentSize).origin();
int expected_x = cases[i].expected_x;
int expected_y = cases[i].expected_y;
EXPECT_EQ(expected_x, origin.x());
EXPECT_EQ(expected_y, origin.y());
border.set_paint_arrow(BubbleBorder::PAINT_TRANSPARENT);
origin = border.GetBounds(kAnchor, kContentSize).origin();
if (border.is_arrow_on_horizontal(arrow)) {
expected_y += BubbleBorder::is_arrow_on_top(arrow)
? kArrowThickness : (-kArrowThickness + kHeightDifference);
} else if (BubbleBorder::has_arrow(arrow)) {
expected_x += BubbleBorder::is_arrow_on_left(arrow)
? kArrowThickness : (-kArrowThickness + kWidthDifference);
}
EXPECT_EQ(expected_x, origin.x());
EXPECT_EQ(expected_y, origin.y());
border.set_paint_arrow(BubbleBorder::PAINT_NONE);
origin = border.GetBounds(kAnchor, kContentSize).origin();
expected_x = cases[i].expected_x;
expected_y = cases[i].expected_y;
if (border.is_arrow_on_horizontal(arrow) &&
!BubbleBorder::is_arrow_on_top(arrow)) {
expected_y += kHeightDifference;
} else if (BubbleBorder::has_arrow(arrow) &&
!border.is_arrow_on_horizontal(arrow) &&
!BubbleBorder::is_arrow_on_left(arrow)) {
expected_x += kWidthDifference;
}
EXPECT_EQ(expected_x, origin.x());
EXPECT_EQ(expected_y, origin.y());
}
}
// Ensure all the shadow types pass some size validation and paint sanely.
TEST_F(BubbleBorderTest, ShadowTypes) {
const gfx::Rect rect(0, 0, 320, 200);
View paint_view;
paint_view.SetBoundsRect(rect);
for (int i = 0; i < BubbleBorder::SHADOW_COUNT; ++i) {
BubbleBorder::Shadow shadow = static_cast<BubbleBorder::Shadow>(i);
SCOPED_TRACE(testing::Message() << "BubbleBorder::Shadow: " << shadow);
gfx::Canvas canvas(gfx::Size(640, 480), 1.0f, false);
BubbleBorder border(BubbleBorder::TOP_LEFT, shadow, SK_ColorWHITE);
internal::BorderImages* border_images = border.GetImagesForTest();
// Arrow assets should always be at least as big as the drawn arrow.
EXPECT_GE(border_images->arrow_thickness,
border_images->arrow_interior_thickness);
EXPECT_GE(border_images->arrow_width,
2 * border_images->arrow_interior_thickness);
// Border assets should always be at least as thick as the hittable border.
EXPECT_GE(border_images->border_thickness,
border_images->border_interior_thickness);
// For a TOP_LEFT arrow, the x-offset always matches the border thickness.
EXPECT_EQ(border.GetArrowRect(rect).x(), border_images->border_thickness);
border.Paint(paint_view, &canvas);
}
}
} // namespace views