From aa7aee7ab3c63baec2e27823a33d32311bb4d206 Mon Sep 17 00:00:00 2001
From: "varunjain@chromium.org"
 <varunjain@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>
Date: Fri, 15 Mar 2013 07:30:39 +0000
Subject: [PATCH] A couple of fixes to bubble view: 1. Mirror arrow location
 even for centered arrows if the bubble is offscreen 2. Apply insets to
 |anchor_point|. This give the user the ability to specify a generic
 "anchor_rect" (as a combination of center point and insets) instead of either
 a |anchor_point| or an |anchor_view|.

BUG=none


Review URL: https://chromiumcodereview.appspot.com/12545040

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@188285 0039d316-1c4b-4281-b951-d872f2087c98
---
 ui/views/bubble/bubble_delegate.cc            |  5 +--
 ui/views/bubble/bubble_frame_view.cc          |  5 +++
 ui/views/bubble/bubble_frame_view_unittest.cc | 38 +++++++++++++++++++
 3 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/ui/views/bubble/bubble_delegate.cc b/ui/views/bubble/bubble_delegate.cc
index ecee2a0589ff0..21ccd1e38c887 100644
--- a/ui/views/bubble/bubble_delegate.cc
+++ b/ui/views/bubble/bubble_delegate.cc
@@ -231,9 +231,8 @@ void BubbleDelegateView::OnWidgetBoundsChanged(Widget* widget,
 }
 
 gfx::Rect BubbleDelegateView::GetAnchorRect() {
-  if (!anchor_view())
-    return gfx::Rect(anchor_point_, gfx::Size());
-  gfx::Rect anchor_bounds = anchor_view()->GetBoundsInScreen();
+  gfx::Rect anchor_bounds = anchor_view() ? anchor_view()->GetBoundsInScreen() :
+      gfx::Rect(anchor_point_, gfx::Size());
   anchor_bounds.Inset(anchor_insets_);
   return anchor_bounds;
 }
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc
index c7efa375752b4..c8e8cdafdade1 100644
--- a/ui/views/bubble/bubble_frame_view.cc
+++ b/ui/views/bubble/bubble_frame_view.cc
@@ -184,6 +184,11 @@ gfx::Rect BubbleFrameView::GetUpdatedWindowBounds(const gfx::Rect& anchor_rect,
       MirrorArrowIfOffScreen(true, anchor_rect, client_size);
       MirrorArrowIfOffScreen(false, anchor_rect, client_size);
     } else {
+      // Mirror as needed vertically if the arrow is on a horizontal edge and
+      // vice-versa.
+      MirrorArrowIfOffScreen(BubbleBorder::is_arrow_on_horizontal(arrow),
+                             anchor_rect,
+                             client_size);
       OffsetArrowIfOffScreen(anchor_rect, client_size);
     }
   }
diff --git a/ui/views/bubble/bubble_frame_view_unittest.cc b/ui/views/bubble/bubble_frame_view_unittest.cc
index 602d79f9de45a..b90615a6a5e81 100644
--- a/ui/views/bubble/bubble_frame_view_unittest.cc
+++ b/ui/views/bubble/bubble_frame_view_unittest.cc
@@ -228,6 +228,44 @@ TEST_F(BubbleFrameViewTest, GetUpdatedWindowBoundsMirroringFails) {
   EXPECT_EQ(BubbleBorder::TOP_LEFT, frame.bubble_border()->arrow_location());
 }
 
+TEST_F(BubbleFrameViewTest, TestMirroringForCenteredArrow) {
+  TestBubbleFrameView frame;
+
+  // Test bubble not fitting above the anchor.
+  frame.bubble_border()->set_arrow_location(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_location());
+
+  // Test bubble not fitting below the anchor.
+  frame.bubble_border()->set_arrow_location(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_location());
+
+  // Test bubble not fitting to the right of the anchor.
+  frame.bubble_border()->set_arrow_location(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_location());
+
+  // Test bubble not fitting to the left of the anchor.
+  frame.bubble_border()->set_arrow_location(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_location());
+}
+
 // Test that the arrow will not be mirrored when |adjust_if_offscreen| is false.
 TEST_F(BubbleFrameViewTest, GetUpdatedWindowBoundsDontTryMirror) {
   TestBubbleFrameView frame;