blob: c733507be26666078026ccf52289c355c13251c4 [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/gfx/insets.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/bubble/bubble_frame_view.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/widget/widget.h"
namespace views {
typedef ViewsTestBase BubbleFrameViewTest;
namespace {
const BubbleBorder::Arrow kArrow = BubbleBorder::TOP_LEFT;
const SkColor kColor = SK_ColorRED;
const int kMargin = 6;
class TestBubbleFrameView : public BubbleFrameView {
public:
TestBubbleFrameView()
: BubbleFrameView(gfx::Insets(kMargin, kMargin, kMargin, kMargin)),
monitor_bounds_(gfx::Rect(0, 0, 1000, 1000)) {
SetBubbleBorder(new BubbleBorder(kArrow, BubbleBorder::NO_SHADOW, kColor));
}
virtual ~TestBubbleFrameView() {}
// BubbleFrameView overrides:
virtual gfx::Rect GetMonitorBounds(const gfx::Rect& rect) OVERRIDE {
return monitor_bounds_;
}
private:
gfx::Rect monitor_bounds_;
DISALLOW_COPY_AND_ASSIGN(TestBubbleFrameView);
};
} // namespace
TEST_F(BubbleFrameViewTest, GetBoundsForClientView) {
TestBubbleFrameView frame;
EXPECT_EQ(kArrow, frame.bubble_border()->arrow());
EXPECT_EQ(kColor, frame.bubble_border()->background_color());
int margin_x = frame.content_margins().left();
int margin_y = frame.content_margins().top();
gfx::Insets insets = frame.bubble_border()->GetInsets();
EXPECT_EQ(insets.left() + margin_x, frame.GetBoundsForClientView().x());
EXPECT_EQ(insets.top() + margin_y, frame.GetBoundsForClientView().y());
}
// Tests that the arrow is mirrored as needed to better fit the screen.
TEST_F(BubbleFrameViewTest, GetUpdatedWindowBounds) {
TestBubbleFrameView frame;
gfx::Rect window_bounds;
gfx::Insets insets = frame.bubble_border()->GetInsets();
int xposition = 95 - insets.width();
// Test that the info bubble displays normally when it fits.
frame.bubble_border()->set_arrow(BubbleBorder::TOP_LEFT);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(100, 100, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::TOP_LEFT, frame.bubble_border()->arrow());
EXPECT_GT(window_bounds.x(), xposition);
EXPECT_GT(window_bounds.y(), 100 + 50 - 10); // -10 to roughly compensate for
// arrow overlap.
// Test bubble not fitting on left.
frame.bubble_border()->set_arrow(BubbleBorder::TOP_RIGHT);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(100, 100, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::TOP_LEFT, frame.bubble_border()->arrow());
EXPECT_GT(window_bounds.x(), xposition);
EXPECT_GT(window_bounds.y(), 100 + 50 - 10); // -10 to roughly compensate for
// arrow overlap.
// Test bubble not fitting on left or top.
frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_RIGHT);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(100, 100, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::TOP_LEFT, frame.bubble_border()->arrow());
EXPECT_GT(window_bounds.x(), xposition);
EXPECT_GT(window_bounds.y(), 100 + 50 - 10); // -10 to roughly compensate for
// arrow overlap.
// Test bubble not fitting on top.
frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_LEFT);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(100, 100, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::TOP_LEFT, frame.bubble_border()->arrow());
EXPECT_GT(window_bounds.x(), xposition);
EXPECT_GT(window_bounds.y(), 100 + 50 - 10); // -10 to roughly compensate for
// arrow overlap.
// Test bubble not fitting on top and right.
frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_LEFT);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(900, 100, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::TOP_RIGHT, frame.bubble_border()->arrow());
EXPECT_LT(window_bounds.x(), 900 + 50 - 500);
EXPECT_GT(window_bounds.y(), 100 + 50 - 10); // -10 to roughly compensate for
// arrow overlap.
// Test bubble not fitting on right.
frame.bubble_border()->set_arrow(BubbleBorder::TOP_LEFT);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(900, 100, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::TOP_RIGHT, frame.bubble_border()->arrow());
EXPECT_LT(window_bounds.x(), 900 + 50 - 500);
EXPECT_GT(window_bounds.y(), 100 + 50 - 10); // -10 to roughly compensate for
// arrow overlap.
// Test bubble not fitting on bottom and right.
frame.bubble_border()->set_arrow(BubbleBorder::TOP_LEFT);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(900, 900, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::BOTTOM_RIGHT, frame.bubble_border()->arrow());
EXPECT_LT(window_bounds.x(), 900 + 50 - 500);
EXPECT_LT(window_bounds.y(), 900 - 500 - 15); // -15 to roughly compensate
// for arrow height.
// Test bubble not fitting at the bottom.
frame.bubble_border()->set_arrow(BubbleBorder::TOP_LEFT);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(100, 900, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::BOTTOM_LEFT, frame.bubble_border()->arrow());
// The window should be right aligned with the anchor_rect.
EXPECT_LT(window_bounds.x(), 900 + 50 - 500);
EXPECT_LT(window_bounds.y(), 900 - 500 - 15); // -15 to roughly compensate
// for arrow height.
// Test bubble not fitting at the bottom and left.
frame.bubble_border()->set_arrow(BubbleBorder::TOP_RIGHT);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(100, 900, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::BOTTOM_LEFT, frame.bubble_border()->arrow());
// The window should be right aligned with the anchor_rect.
EXPECT_LT(window_bounds.x(), 900 + 50 - 500);
EXPECT_LT(window_bounds.y(), 900 - 500 - 15); // -15 to roughly compensate
// for arrow height.
}
// Tests that the arrow is not moved when the info-bubble does not fit the
// screen but moving it would make matter worse.
TEST_F(BubbleFrameViewTest, GetUpdatedWindowBoundsMirroringFails) {
TestBubbleFrameView frame;
frame.bubble_border()->set_arrow(BubbleBorder::TOP_LEFT);
gfx::Rect window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(400, 100, 50, 50), // |anchor_rect|
gfx::Size(500, 700), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::TOP_LEFT, frame.bubble_border()->arrow());
}
TEST_F(BubbleFrameViewTest, TestMirroringForCenteredArrow) {
TestBubbleFrameView frame;
// Test bubble not fitting above the anchor.
frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_CENTER);
gfx::Rect window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(100, 100, 50, 50), // |anchor_rect|
gfx::Size(500, 700), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::TOP_CENTER, frame.bubble_border()->arrow());
// Test bubble not fitting below the anchor.
frame.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(300, 800, 50, 50), // |anchor_rect|
gfx::Size(500, 200), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::BOTTOM_CENTER, frame.bubble_border()->arrow());
// Test bubble not fitting to the right of the anchor.
frame.bubble_border()->set_arrow(BubbleBorder::LEFT_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(800, 300, 50, 50), // |anchor_rect|
gfx::Size(200, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::RIGHT_CENTER, frame.bubble_border()->arrow());
// Test bubble not fitting to the left of the anchor.
frame.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(100, 300, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::LEFT_CENTER, frame.bubble_border()->arrow());
}
// Test that the arrow will not be mirrored when |adjust_if_offscreen| is false.
TEST_F(BubbleFrameViewTest, GetUpdatedWindowBoundsDontTryMirror) {
TestBubbleFrameView frame;
frame.bubble_border()->set_arrow(BubbleBorder::TOP_RIGHT);
gfx::Rect window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(100, 900, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
false); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::TOP_RIGHT, frame.bubble_border()->arrow());
// The coordinates should be pointing to anchor_rect from TOP_RIGHT.
EXPECT_LT(window_bounds.x(), 100 + 50 - 500);
EXPECT_GT(window_bounds.y(), 900 + 50 - 10); // -10 to roughly compensate for
// arrow overlap.
}
// Test that the center arrow is moved as needed to fit the screen.
TEST_F(BubbleFrameViewTest, GetUpdatedWindowBoundsCenterArrows) {
TestBubbleFrameView frame;
gfx::Rect window_bounds;
// Test that the bubble displays normally when it fits.
frame.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(500, 100, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::TOP_CENTER, frame.bubble_border()->arrow());
EXPECT_EQ(window_bounds.x() + window_bounds.width() / 2, 525);
frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(500, 900, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::BOTTOM_CENTER, frame.bubble_border()->arrow());
EXPECT_EQ(window_bounds.x() + window_bounds.width() / 2, 525);
frame.bubble_border()->set_arrow(BubbleBorder::LEFT_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(100, 400, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::LEFT_CENTER, frame.bubble_border()->arrow());
EXPECT_EQ(window_bounds.y() + window_bounds.height() / 2, 425);
frame.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(900, 400, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::RIGHT_CENTER, frame.bubble_border()->arrow());
EXPECT_EQ(window_bounds.y() + window_bounds.height() / 2, 425);
// Test bubble not fitting left screen edge.
frame.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(100, 100, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::TOP_CENTER, frame.bubble_border()->arrow());
EXPECT_EQ(window_bounds.x(), 0);
EXPECT_EQ(window_bounds.x() +
frame.bubble_border()->GetArrowOffset(window_bounds.size()), 125);
frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(100, 900, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::BOTTOM_CENTER, frame.bubble_border()->arrow());
EXPECT_EQ(window_bounds.x(), 0);
EXPECT_EQ(window_bounds.x() +
frame.bubble_border()->GetArrowOffset(window_bounds.size()), 125);
// Test bubble not fitting right screen edge.
frame.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(900, 100, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::TOP_CENTER, frame.bubble_border()->arrow());
EXPECT_EQ(window_bounds.right(), 1000);
EXPECT_EQ(window_bounds.x() +
frame.bubble_border()->GetArrowOffset(window_bounds.size()), 925);
frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(900, 900, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::BOTTOM_CENTER, frame.bubble_border()->arrow());
EXPECT_EQ(window_bounds.right(), 1000);
EXPECT_EQ(window_bounds.x() +
frame.bubble_border()->GetArrowOffset(window_bounds.size()), 925);
// Test bubble not fitting top screen edge.
frame.bubble_border()->set_arrow(BubbleBorder::LEFT_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(100, 100, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::LEFT_CENTER, frame.bubble_border()->arrow());
EXPECT_EQ(window_bounds.y(), 0);
EXPECT_EQ(window_bounds.y() +
frame.bubble_border()->GetArrowOffset(window_bounds.size()), 125);
frame.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(900, 100, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::RIGHT_CENTER, frame.bubble_border()->arrow());
EXPECT_EQ(window_bounds.y(), 0);
EXPECT_EQ(window_bounds.y() +
frame.bubble_border()->GetArrowOffset(window_bounds.size()), 125);
// Test bubble not fitting bottom screen edge.
frame.bubble_border()->set_arrow(BubbleBorder::LEFT_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(100, 900, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::LEFT_CENTER, frame.bubble_border()->arrow());
EXPECT_EQ(window_bounds.bottom(), 1000);
EXPECT_EQ(window_bounds.y() +
frame.bubble_border()->GetArrowOffset(window_bounds.size()), 925);
frame.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
gfx::Rect(900, 900, 50, 50), // |anchor_rect|
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::RIGHT_CENTER, frame.bubble_border()->arrow());
EXPECT_EQ(window_bounds.bottom(), 1000);
EXPECT_EQ(window_bounds.y() +
frame.bubble_border()->GetArrowOffset(window_bounds.size()), 925);
}
} // namespace views