Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / ui / views / bubble / bubble_frame_view.cc
index 37b6c26..1c4d70c 100644 (file)
@@ -12,6 +12,7 @@
 #include "ui/gfx/path.h"
 #include "ui/gfx/screen.h"
 #include "ui/gfx/skia_util.h"
+#include "ui/native_theme/native_theme.h"
 #include "ui/views/bubble/bubble_border.h"
 #include "ui/views/controls/button/label_button.h"
 #include "ui/views/widget/widget.h"
@@ -25,26 +26,27 @@ const int kTitleTopInset = 12;
 const int kTitleLeftInset = 19;
 const int kTitleBottomInset = 12;
 
-// Get the |vertical| or horizontal screen overflow of the |window_bounds|.
-int GetOffScreenLength(const gfx::Rect& monitor_bounds,
+// Get the |vertical| or horizontal amount that |available_bounds| overflows
+// |window_bounds|.
+int GetOffScreenLength(const gfx::Rect& available_bounds,
                        const gfx::Rect& window_bounds,
                        bool vertical) {
-  if (monitor_bounds.IsEmpty() || monitor_bounds.Contains(window_bounds))
+  if (available_bounds.IsEmpty() || available_bounds.Contains(window_bounds))
     return 0;
 
   //  window_bounds
-  //  +-------------------------------+
-  //  |             top               |
-  //  |      +----------------+       |
-  //  | left | monitor_bounds | right |
-  //  |      +----------------+       |
-  //  |            bottom             |
-  //  +-------------------------------+
+  //  +---------------------------------+
+  //  |             top                 |
+  //  |      +------------------+       |
+  //  | left | available_bounds | right |
+  //  |      +------------------+       |
+  //  |            bottom               |
+  //  +---------------------------------+
   if (vertical)
-    return std::max(0, monitor_bounds.y() - window_bounds.y()) +
-           std::max(0, window_bounds.bottom() - monitor_bounds.bottom());
-  return std::max(0, monitor_bounds.x() - window_bounds.x()) +
-         std::max(0, window_bounds.right() - monitor_bounds.right());
+    return std::max(0, available_bounds.y() - window_bounds.y()) +
+           std::max(0, window_bounds.bottom() - available_bounds.bottom());
+  return std::max(0, available_bounds.x() - window_bounds.x()) +
+         std::max(0, window_bounds.right() - available_bounds.right());
 }
 
 }  // namespace
@@ -66,11 +68,12 @@ BubbleFrameView::BubbleFrameView(const gfx::Insets& content_margins)
       close_(NULL),
       titlebar_extra_view_(NULL) {
   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
-  title_ = new Label(string16(), rb.GetFont(ui::ResourceBundle::MediumFont));
+  title_ = new Label(base::string16(),
+                     rb.GetFontList(ui::ResourceBundle::MediumFont));
   title_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   AddChildView(title_);
 
-  close_ = new LabelButton(this, string16());
+  close_ = new LabelButton(this, base::string16());
   close_->SetImage(CustomButton::STATE_NORMAL,
                    *rb.GetImageNamed(IDR_CLOSE_DIALOG).ToImageSkia());
   close_->SetImage(CustomButton::STATE_HOVERED,
@@ -78,7 +81,7 @@ BubbleFrameView::BubbleFrameView(const gfx::Insets& content_margins)
   close_->SetImage(CustomButton::STATE_PRESSED,
                    *rb.GetImageNamed(IDR_CLOSE_DIALOG_P).ToImageSkia());
   close_->SetSize(close_->GetPreferredSize());
-  close_->set_border(NULL);
+  close_->SetBorder(scoped_ptr<Border>());
   close_->SetVisible(false);
   AddChildView(close_);
 }
@@ -153,7 +156,7 @@ void BubbleFrameView::UpdateWindowIcon() {}
 
 void BubbleFrameView::UpdateWindowTitle() {
   title_->SetText(GetWidget()->widget_delegate()->ShouldShowWindowTitle() ?
-      GetWidget()->widget_delegate()->GetWindowTitle() : string16());
+      GetWidget()->widget_delegate()->GetWindowTitle() : base::string16());
   // Update the close button visibility too, otherwise it's not intialized.
   ResetWindowControls();
 }
@@ -176,8 +179,10 @@ gfx::Size BubbleFrameView::GetMinimumSize() {
 }
 
 void BubbleFrameView::Layout() {
-  gfx::Rect bounds(GetLocalBounds());
-  bounds.Inset(border()->GetInsets());
+  gfx::Rect bounds(GetContentsBounds());
+  if (bounds.IsEmpty())
+    return;
+
   // Small additional insets yield the desired 10px visual close button insets.
   bounds.Inset(0, 0, close_->width() + 1, 0);
   close_->SetPosition(gfx::Point(bounds.right(), bounds.y() + 2));
@@ -219,17 +224,25 @@ void BubbleFrameView::OnThemeChanged() {
   UpdateWindowIcon();
 }
 
+void BubbleFrameView::OnNativeThemeChanged(const ui::NativeTheme* theme) {
+  if (bubble_border_ && bubble_border_->use_theme_background_color()) {
+    bubble_border_->set_background_color(GetNativeTheme()->
+        GetSystemColor(ui::NativeTheme::kColorId_DialogBackground));
+    SchedulePaint();
+  }
+}
+
 void BubbleFrameView::ButtonPressed(Button* sender, const ui::Event& event) {
   if (sender == close_)
     GetWidget()->Close();
 }
 
-void BubbleFrameView::SetBubbleBorder(BubbleBorder* border) {
-  bubble_border_ = border;
-  set_border(bubble_border_);
+void BubbleFrameView::SetBubbleBorder(scoped_ptr<BubbleBorder> border) {
+  bubble_border_ = border.get();
+  SetBorder(border.PassAs<Border>());
 
   // Update the background, which relies on the border.
-  set_background(new views::BubbleBackground(border));
+  set_background(new views::BubbleBackground(bubble_border_));
 }
 
 void BubbleFrameView::SetTitlebarExtraView(View* view) {
@@ -242,30 +255,27 @@ void BubbleFrameView::SetTitlebarExtraView(View* view) {
 gfx::Rect BubbleFrameView::GetUpdatedWindowBounds(const gfx::Rect& anchor_rect,
                                                   gfx::Size client_size,
                                                   bool adjust_if_offscreen) {
-  gfx::Insets insets(GetInsets());
-  client_size.Enlarge(insets.width(), insets.height());
+  gfx::Size size(GetSizeForClientSize(client_size));
 
   const BubbleBorder::Arrow arrow = bubble_border_->arrow();
   if (adjust_if_offscreen && BubbleBorder::has_arrow(arrow)) {
+    // Try to mirror the anchoring if the bubble does not fit on the screen.
     if (!bubble_border_->is_arrow_at_center(arrow)) {
-      // Try to mirror the anchoring if the bubble does not fit on the screen.
-      MirrorArrowIfOffScreen(true, anchor_rect, client_size);
-      MirrorArrowIfOffScreen(false, anchor_rect, client_size);
+      MirrorArrowIfOffScreen(true, anchor_rect, size);
+      MirrorArrowIfOffScreen(false, anchor_rect, 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);
+      const bool mirror_vertical = BubbleBorder::is_arrow_on_horizontal(arrow);
+      MirrorArrowIfOffScreen(mirror_vertical, anchor_rect, size);
+      OffsetArrowIfOffScreen(anchor_rect, size);
     }
   }
 
   // Calculate the bounds with the arrow in its updated location and offset.
-  return bubble_border_->GetBounds(anchor_rect, client_size);
+  return bubble_border_->GetBounds(anchor_rect, size);
 }
 
-gfx::Rect BubbleFrameView::GetMonitorBounds(const gfx::Rect& rect) {
+gfx::Rect BubbleFrameView::GetAvailableScreenBounds(const gfx::Rect& rect) {
+  // The bubble attempts to fit within the current screen bounds.
   // TODO(scottmg): Native is wrong. http://crbug.com/133312
   return gfx::Screen::GetNativeScreen()->GetDisplayNearestPoint(
       rect.CenterPoint()).work_area();
@@ -276,9 +286,9 @@ void BubbleFrameView::MirrorArrowIfOffScreen(
     const gfx::Rect& anchor_rect,
     const gfx::Size& client_size) {
   // Check if the bounds don't fit on screen.
-  gfx::Rect monitor_rect(GetMonitorBounds(anchor_rect));
+  gfx::Rect available_bounds(GetAvailableScreenBounds(anchor_rect));
   gfx::Rect window_bounds(bubble_border_->GetBounds(anchor_rect, client_size));
-  if (GetOffScreenLength(monitor_rect, window_bounds, vertical) > 0) {
+  if (GetOffScreenLength(available_bounds, window_bounds, vertical) > 0) {
     BubbleBorder::Arrow arrow = bubble_border()->arrow();
     // Mirror the arrow and get the new bounds.
     bubble_border_->set_arrow(
@@ -287,11 +297,13 @@ void BubbleFrameView::MirrorArrowIfOffScreen(
     gfx::Rect mirror_bounds =
         bubble_border_->GetBounds(anchor_rect, client_size);
     // Restore the original arrow if mirroring doesn't show more of the bubble.
-    if (GetOffScreenLength(monitor_rect, mirror_bounds, vertical) >=
-        GetOffScreenLength(monitor_rect, window_bounds, vertical))
+    // Otherwise it should invoke parent's Layout() to layout the content based
+    // on the new bubble border.
+    if (GetOffScreenLength(available_bounds, mirror_bounds, vertical) >=
+        GetOffScreenLength(available_bounds, window_bounds, vertical))
       bubble_border_->set_arrow(arrow);
-    else
-      SchedulePaint();
+    else if (parent())
+      parent()->Layout();
   }
 }
 
@@ -304,23 +316,23 @@ void BubbleFrameView::OffsetArrowIfOffScreen(const gfx::Rect& anchor_rect,
   bubble_border_->set_arrow_offset(0);
   gfx::Rect window_bounds(bubble_border_->GetBounds(anchor_rect, client_size));
 
-  gfx::Rect monitor_rect(GetMonitorBounds(anchor_rect));
-  if (monitor_rect.IsEmpty() || monitor_rect.Contains(window_bounds))
+  gfx::Rect available_bounds(GetAvailableScreenBounds(anchor_rect));
+  if (available_bounds.IsEmpty() || available_bounds.Contains(window_bounds))
     return;
 
   // Calculate off-screen adjustment.
   const bool is_horizontal = BubbleBorder::is_arrow_on_horizontal(arrow);
   int offscreen_adjust = 0;
   if (is_horizontal) {
-    if (window_bounds.x() < monitor_rect.x())
-      offscreen_adjust = monitor_rect.x() - window_bounds.x();
-    else if (window_bounds.right() > monitor_rect.right())
-      offscreen_adjust = monitor_rect.right() - window_bounds.right();
+    if (window_bounds.x() < available_bounds.x())
+      offscreen_adjust = available_bounds.x() - window_bounds.x();
+    else if (window_bounds.right() > available_bounds.right())
+      offscreen_adjust = available_bounds.right() - window_bounds.right();
   } else {
-    if (window_bounds.y() < monitor_rect.y())
-      offscreen_adjust = monitor_rect.y() - window_bounds.y();
-    else if (window_bounds.bottom() > monitor_rect.bottom())
-      offscreen_adjust = monitor_rect.bottom() - window_bounds.bottom();
+    if (window_bounds.y() < available_bounds.y())
+      offscreen_adjust = available_bounds.y() - window_bounds.y();
+    else if (window_bounds.bottom() > available_bounds.bottom())
+      offscreen_adjust = available_bounds.bottom() - window_bounds.bottom();
   }
 
   // For center arrows, arrows are moved in the opposite direction of
@@ -334,8 +346,6 @@ void BubbleFrameView::OffsetArrowIfOffScreen(const gfx::Rect& anchor_rect,
 }
 
 gfx::Size BubbleFrameView::GetSizeForClientSize(const gfx::Size& client_size) {
-  gfx::Size size(
-      GetUpdatedWindowBounds(gfx::Rect(), client_size, false).size());
   // Accommodate the width of the title bar elements.
   int title_bar_width = GetInsets().width() + border()->GetInsets().width();
   if (!title_->text().empty())
@@ -344,7 +354,10 @@ gfx::Size BubbleFrameView::GetSizeForClientSize(const gfx::Size& client_size) {
     title_bar_width += close_->width() + 1;
   if (titlebar_extra_view_ != NULL)
     title_bar_width += titlebar_extra_view_->GetPreferredSize().width();
+  gfx::Size size(client_size);
   size.SetToMax(gfx::Size(title_bar_width, 0));
+  const gfx::Insets insets(GetInsets());
+  size.Enlarge(insets.width(), insets.height());
   return size;
 }