summaryrefslogtreecommitdiffstats
path: root/chrome/browser/views/info_bubble.cc
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-09 07:35:32 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-09 07:35:32 +0000
commit213dac2f0bff9162502fe325b6ebb85a255efcb2 (patch)
tree3640cb1f19976e38677b8632537d2d41f8444d0f /chrome/browser/views/info_bubble.cc
parent6de53d401aa8dc6c7e0a9874c71a95ce88ade50d (diff)
downloadchromium_src-213dac2f0bff9162502fe325b6ebb85a255efcb2.zip
chromium_src-213dac2f0bff9162502fe325b6ebb85a255efcb2.tar.gz
chromium_src-213dac2f0bff9162502fe325b6ebb85a255efcb2.tar.bz2
Move browser/views to browser/ui/views
TBR=brettw BUG=none TEST=none Review URL: http://codereview.chromium.org/4694005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@65508 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/views/info_bubble.cc')
-rw-r--r--chrome/browser/views/info_bubble.cc542
1 files changed, 0 insertions, 542 deletions
diff --git a/chrome/browser/views/info_bubble.cc b/chrome/browser/views/info_bubble.cc
deleted file mode 100644
index 3ee1317..0000000
--- a/chrome/browser/views/info_bubble.cc
+++ /dev/null
@@ -1,542 +0,0 @@
-// Copyright (c) 2010 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 "chrome/browser/views/info_bubble.h"
-
-#include "app/keyboard_codes.h"
-#include "chrome/browser/window_sizer.h"
-#include "chrome/common/notification_service.h"
-#include "gfx/canvas_skia.h"
-#include "gfx/color_utils.h"
-#include "gfx/path.h"
-#include "third_party/skia/include/core/SkPaint.h"
-#include "views/fill_layout.h"
-#include "views/widget/root_view.h"
-#include "views/widget/widget.h"
-#include "views/window/client_view.h"
-#include "views/window/window.h"
-
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/wm_ipc.h"
-#include "cros/chromeos_wm_ipc_enums.h"
-#endif
-
-// How long the fade should last for.
-static const int kHideFadeDurationMS = 200;
-
-// Background color of the bubble.
-#if defined(OS_WIN)
-const SkColor InfoBubble::kBackgroundColor =
- color_utils::GetSysSkColor(COLOR_WINDOW);
-#else
-// TODO(beng): source from theme provider.
-const SkColor InfoBubble::kBackgroundColor = SK_ColorWHITE;
-#endif
-
-void BorderContents::Init() {
- // Default arrow location.
- BubbleBorder::ArrowLocation arrow_location = BubbleBorder::TOP_LEFT;
- if (base::i18n::IsRTL())
- arrow_location = BubbleBorder::horizontal_mirror(arrow_location);
- DCHECK(!bubble_border_);
- bubble_border_ = new BubbleBorder(arrow_location);
- set_border(bubble_border_);
- bubble_border_->set_background_color(InfoBubble::kBackgroundColor);
-}
-
-void BorderContents::SizeAndGetBounds(
- const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
- bool allow_bubble_offscreen,
- const gfx::Size& contents_size,
- gfx::Rect* contents_bounds,
- gfx::Rect* window_bounds) {
- if (base::i18n::IsRTL())
- arrow_location = BubbleBorder::horizontal_mirror(arrow_location);
- bubble_border_->set_arrow_location(arrow_location);
- // Set the border.
- set_border(bubble_border_);
- bubble_border_->set_background_color(InfoBubble::kBackgroundColor);
-
- // Give the contents a margin.
- gfx::Size local_contents_size(contents_size);
- local_contents_size.Enlarge(kLeftMargin + kRightMargin,
- kTopMargin + kBottomMargin);
-
- // Try putting the arrow in its initial location, and calculating the bounds.
- *window_bounds =
- bubble_border_->GetBounds(position_relative_to, local_contents_size);
- if (!allow_bubble_offscreen) {
- gfx::Rect monitor_bounds = GetMonitorBounds(position_relative_to);
- if (!monitor_bounds.IsEmpty()) {
- // Try to resize vertically if this does not fit on the screen.
- MirrorArrowIfOffScreen(true, // |vertical|.
- position_relative_to, monitor_bounds,
- local_contents_size, &arrow_location,
- window_bounds);
- // Then try to resize horizontally if it still does not fit on the screen.
- MirrorArrowIfOffScreen(false, // |vertical|.
- position_relative_to, monitor_bounds,
- local_contents_size, &arrow_location,
- window_bounds);
- }
- }
-
- // Calculate the bounds of the contained contents (in window coordinates) by
- // subtracting the border dimensions and margin amounts.
- *contents_bounds = gfx::Rect(gfx::Point(), window_bounds->size());
- gfx::Insets insets;
- bubble_border_->GetInsets(&insets);
- contents_bounds->Inset(insets.left() + kLeftMargin, insets.top() + kTopMargin,
- insets.right() + kRightMargin, insets.bottom() + kBottomMargin);
-}
-
-gfx::Rect BorderContents::GetMonitorBounds(const gfx::Rect& rect) {
- scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_provider(
- WindowSizer::CreateDefaultMonitorInfoProvider());
- return monitor_provider->GetMonitorWorkAreaMatching(rect);
-}
-
-void BorderContents::Paint(gfx::Canvas* canvas) {
- // 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(InfoBubble::kBackgroundColor);
- gfx::Path path;
- gfx::Rect bounds(GetLocalBounds(false));
- 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);
-
- // Now we paint the border, so it will be alpha-blended atop the contents.
- // This looks slightly better in the corners than drawing the contents atop
- // the border.
- PaintBorder(canvas);
-}
-
-void BorderContents::MirrorArrowIfOffScreen(
- bool vertical,
- const gfx::Rect& position_relative_to,
- const gfx::Rect& monitor_bounds,
- const gfx::Size& local_contents_size,
- BubbleBorder::ArrowLocation* arrow_location,
- gfx::Rect* window_bounds) {
- // If the bounds don't fit, move the arrow to its mirrored position to see if
- // it improves things.
- gfx::Insets offscreen_insets;
- if (ComputeOffScreenInsets(monitor_bounds, *window_bounds,
- &offscreen_insets) &&
- GetInsetsLength(offscreen_insets, vertical) > 0) {
- BubbleBorder::ArrowLocation original_arrow_location = *arrow_location;
- *arrow_location =
- vertical ? BubbleBorder::vertical_mirror(*arrow_location) :
- BubbleBorder::horizontal_mirror(*arrow_location);
-
- // Change the arrow and get the new bounds.
- bubble_border_->set_arrow_location(*arrow_location);
- *window_bounds = bubble_border_->GetBounds(position_relative_to,
- local_contents_size);
- gfx::Insets new_offscreen_insets;
- // If there is more of the window offscreen, we'll keep the old arrow.
- if (ComputeOffScreenInsets(monitor_bounds, *window_bounds,
- &new_offscreen_insets) &&
- GetInsetsLength(new_offscreen_insets, vertical) >=
- GetInsetsLength(offscreen_insets, vertical)) {
- *arrow_location = original_arrow_location;
- bubble_border_->set_arrow_location(*arrow_location);
- *window_bounds = bubble_border_->GetBounds(position_relative_to,
- local_contents_size);
- }
- }
-}
-
-// static
-bool BorderContents::ComputeOffScreenInsets(const gfx::Rect& monitor_bounds,
- const gfx::Rect& window_bounds,
- gfx::Insets* offscreen_insets) {
- if (monitor_bounds.Contains(window_bounds))
- return false;
-
- if (!offscreen_insets)
- return true;
-
- int top = 0;
- int left = 0;
- int bottom = 0;
- int right = 0;
-
- if (window_bounds.y() < monitor_bounds.y())
- top = monitor_bounds.y() - window_bounds.y();
- if (window_bounds.x() < monitor_bounds.x())
- left = monitor_bounds.x() - window_bounds.x();
- if (window_bounds.bottom() > monitor_bounds.bottom())
- bottom = window_bounds.bottom() - monitor_bounds.bottom();
- if (window_bounds.right() > monitor_bounds.right())
- right = window_bounds.right() - monitor_bounds.right();
-
- offscreen_insets->Set(top, left, bottom, right);
- return true;
-}
-
-// static
-int BorderContents::GetInsetsLength(const gfx::Insets& insets, bool vertical) {
- return vertical ? insets.height() : insets.width();
-}
-
-#if defined(OS_WIN)
-// BorderWidget ---------------------------------------------------------------
-
-BorderWidget::BorderWidget() : border_contents_(NULL) {
- set_window_style(WS_POPUP);
- set_window_ex_style(WS_EX_TOOLWINDOW | WS_EX_LAYERED);
-}
-
-void BorderWidget::Init(BorderContents* border_contents, HWND owner) {
- DCHECK(!border_contents_);
- border_contents_ = border_contents;
- border_contents_->Init();
- WidgetWin::Init(owner, gfx::Rect());
- SetContentsView(border_contents_);
- SetWindowPos(owner, 0, 0, 0, 0,
- SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOREDRAW);
-}
-
-gfx::Rect BorderWidget::SizeAndGetBounds(
- const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
- const gfx::Size& contents_size) {
- // Ask the border view to calculate our bounds (and our contents').
- gfx::Rect contents_bounds;
- gfx::Rect window_bounds;
- border_contents_->SizeAndGetBounds(position_relative_to, arrow_location,
- false, contents_size, &contents_bounds,
- &window_bounds);
- SetBounds(window_bounds);
-
- // Return |contents_bounds| in screen coordinates.
- contents_bounds.Offset(window_bounds.origin());
- return contents_bounds;
-}
-
-LRESULT BorderWidget::OnMouseActivate(HWND window,
- UINT hit_test,
- UINT mouse_message) {
- // Never activate.
- return MA_NOACTIVATE;
-}
-#endif
-
-// InfoBubble -----------------------------------------------------------------
-
-// static
-InfoBubble* InfoBubble::Show(views::Widget* parent,
- const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
- views::View* contents,
- InfoBubbleDelegate* delegate) {
- InfoBubble* window = new InfoBubble;
- window->Init(parent, position_relative_to, arrow_location,
- contents, delegate);
- return window;
-}
-
-#if defined(OS_CHROMEOS)
-// static
-InfoBubble* InfoBubble::ShowFocusless(
- views::Widget* parent,
- const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
- views::View* contents,
- InfoBubbleDelegate* delegate) {
- InfoBubble* window = new InfoBubble(views::WidgetGtk::TYPE_POPUP);
- window->Init(parent, position_relative_to, arrow_location,
- contents, delegate);
- return window;
-}
-#endif
-
-void InfoBubble::Close() {
- if (show_status_ != kOpen)
- return;
-
- show_status_ = kClosing;
-
- if (fade_away_on_close_)
- FadeOut();
- else
- DoClose(false);
-}
-
-void InfoBubble::AnimationEnded(const Animation* animation) {
- if (static_cast<int>(animation_->GetCurrentValue()) == 0) {
- // When fading out we just need to close the bubble at the end
- DoClose(false);
- } else {
-#if defined(OS_WIN)
- // When fading in we need to remove the layered window style flag, since
- // that style prevents some bubble content from working properly.
- SetWindowLong(GWL_EXSTYLE, GetWindowLong(GWL_EXSTYLE) & ~WS_EX_LAYERED);
-#endif
- }
-}
-
-void InfoBubble::AnimationProgressed(const Animation* animation) {
-#if defined(OS_WIN)
- // Set the opacity for the main contents window.
- unsigned char opacity = static_cast<unsigned char>(
- animation_->GetCurrentValue() * 255);
- SetLayeredWindowAttributes(GetNativeView(), 0,
- static_cast<byte>(opacity), LWA_ALPHA);
- contents_->SchedulePaint();
-
- // Also fade in/out the bubble border window.
- border_->SetOpacity(opacity);
- border_->border_contents()->SchedulePaint();
-#else
- NOTIMPLEMENTED();
-#endif
-}
-
-InfoBubble::InfoBubble()
- :
-#if defined(OS_LINUX)
- WidgetGtk(TYPE_WINDOW),
- border_contents_(NULL),
-#elif defined(OS_WIN)
- border_(NULL),
-#endif
- delegate_(NULL),
- show_status_(kOpen),
- fade_away_on_close_(false) {
-}
-
-#if defined(OS_CHROMEOS)
-InfoBubble::InfoBubble(views::WidgetGtk::Type type)
- : WidgetGtk(type),
- border_contents_(NULL),
- delegate_(NULL),
- show_status_(kOpen),
- fade_away_on_close_(false) {
-}
-#endif
-
-void InfoBubble::Init(views::Widget* parent,
- const gfx::Rect& position_relative_to,
- BubbleBorder::ArrowLocation arrow_location,
- views::View* contents,
- InfoBubbleDelegate* delegate) {
- delegate_ = delegate;
- position_relative_to_ = position_relative_to;
- arrow_location_ = arrow_location;
- contents_ = contents;
-
- // Create the main window.
-#if defined(OS_WIN)
- views::Window* parent_window = parent->GetWindow();
- if (parent_window)
- parent_window->DisableInactiveRendering();
- set_window_style(WS_POPUP | WS_CLIPCHILDREN);
- int extended_style = WS_EX_TOOLWINDOW;
- // During FadeIn we need to turn on the layered window style to deal with
- // transparency. This flag needs to be reset after fading in is complete.
- bool fade_in = delegate_ && delegate_->FadeInOnShow();
- if (fade_in)
- extended_style |= WS_EX_LAYERED;
- set_window_ex_style(extended_style);
-
- DCHECK(!border_);
- border_ = new BorderWidget();
-
- if (fade_in) {
- border_->SetOpacity(0);
- SetOpacity(0);
- }
-
- border_->Init(CreateBorderContents(), parent->GetNativeView());
-
- // We make the BorderWidget the owner of the InfoBubble HWND, so that the
- // latter is displayed on top of the former.
- WidgetWin::Init(border_->GetNativeView(), gfx::Rect());
-
- SetWindowText(GetNativeView(), delegate_->accessible_name().c_str());
-#elif defined(OS_LINUX)
- MakeTransparent();
- make_transient_to_parent();
- WidgetGtk::InitWithWidget(parent, gfx::Rect());
-#if defined(OS_CHROMEOS)
- chromeos::WmIpc::instance()->SetWindowType(
- GetNativeView(),
- chromeos::WM_IPC_WINDOW_CHROME_INFO_BUBBLE,
- NULL);
-#endif
-#endif
-
- // Create a View to hold the contents of the main window.
- views::View* contents_view = new views::View;
- // We add |contents_view| to ourselves before the AddChildView() call below so
- // that when |contents| gets added, it will already have a widget, and thus
- // any NativeButtons it creates in ViewHierarchyChanged() will be functional
- // (e.g. calling SetChecked() on checkboxes is safe).
- SetContentsView(contents_view);
- // Adding |contents| as a child has to be done before we call
- // contents->GetPreferredSize() below, since some supplied views don't
- // actually initialize themselves until they're added to a hierarchy.
- contents_view->AddChildView(contents);
-
- // Calculate and set the bounds for all windows and views.
- gfx::Rect window_bounds;
-
-#if defined(OS_WIN)
- // Initialize and position the border window.
- window_bounds = border_->SizeAndGetBounds(position_relative_to,
- arrow_location,
- contents->GetPreferredSize());
-
- // Make |contents| take up the entire contents view.
- contents_view->SetLayoutManager(new views::FillLayout);
-
- // Paint the background color behind the contents.
- contents_view->set_background(
- views::Background::CreateSolidBackground(kBackgroundColor));
-#else
- // Create a view to paint the border and background.
- border_contents_ = CreateBorderContents();
- border_contents_->Init();
- gfx::Rect contents_bounds;
- border_contents_->SizeAndGetBounds(position_relative_to,
- arrow_location, false, contents->GetPreferredSize(),
- &contents_bounds, &window_bounds);
- // This new view must be added before |contents| so it will paint under it.
- contents_view->AddChildView(0, border_contents_);
-
- // |contents_view| has no layout manager, so we have to explicitly position
- // its children.
- border_contents_->SetBounds(gfx::Rect(gfx::Point(), window_bounds.size()));
- contents->SetBounds(contents_bounds);
-#endif
- SetBounds(window_bounds);
-
- // Register the Escape accelerator for closing.
- GetFocusManager()->RegisterAccelerator(
- views::Accelerator(app::VKEY_ESCAPE, false, false, false), this);
-
- // Done creating the bubble.
- NotificationService::current()->Notify(NotificationType::INFO_BUBBLE_CREATED,
- Source<InfoBubble>(this),
- NotificationService::NoDetails());
-
- // Show the window.
-#if defined(OS_WIN)
- border_->ShowWindow(SW_SHOW);
- ShowWindow(SW_SHOW);
- if (fade_in)
- FadeIn();
-#elif defined(OS_LINUX)
- views::WidgetGtk::Show();
-#endif
-}
-
-BorderContents* InfoBubble::CreateBorderContents() {
- return new BorderContents();
-}
-
-void InfoBubble::SizeToContents() {
- gfx::Rect window_bounds;
-
-#if defined(OS_WIN)
- // Initialize and position the border window.
- window_bounds = border_->SizeAndGetBounds(position_relative_to_,
- arrow_location_,
- contents_->GetPreferredSize());
-#else
- gfx::Rect contents_bounds;
- border_contents_->SizeAndGetBounds(position_relative_to_,
- arrow_location_, false, contents_->GetPreferredSize(),
- &contents_bounds, &window_bounds);
- // |contents_view| has no layout manager, so we have to explicitly position
- // its children.
- border_contents_->SetBounds(gfx::Rect(gfx::Point(), window_bounds.size()));
- contents_->SetBounds(contents_bounds);
-#endif
- SetBounds(window_bounds);
-}
-
-#if defined(OS_WIN)
-void InfoBubble::OnActivate(UINT action, BOOL minimized, HWND window) {
- // The popup should close when it is deactivated.
- if (action == WA_INACTIVE) {
- Close();
- } else if (action == WA_ACTIVE) {
- DCHECK_GT(GetRootView()->GetChildViewCount(), 0);
- GetRootView()->GetChildViewAt(0)->RequestFocus();
- }
-}
-#elif defined(OS_LINUX)
-void InfoBubble::IsActiveChanged() {
- if (!IsActive())
- Close();
-}
-#endif
-
-void InfoBubble::DoClose(bool closed_by_escape) {
- if (show_status_ == kClosed)
- return;
-
- GetFocusManager()->UnregisterAccelerator(
- views::Accelerator(app::VKEY_ESCAPE, false, false, false), this);
- if (delegate_)
- delegate_->InfoBubbleClosing(this, closed_by_escape);
- show_status_ = kClosed;
-#if defined(OS_WIN)
- border_->Close();
- WidgetWin::Close();
-#elif defined(OS_LINUX)
- WidgetGtk::Close();
-#endif
-}
-
-void InfoBubble::FadeIn() {
- Fade(true); // |fade_in|.
-}
-
-void InfoBubble::FadeOut() {
-#if defined(OS_WIN)
- // The contents window cannot have the layered flag on by default, since its
- // content doesn't always work inside a layered window, but when animating it
- // is ok to set that style on the window for the purpose of fading it out.
- SetWindowLong(GWL_EXSTYLE, GetWindowLong(GWL_EXSTYLE) | WS_EX_LAYERED);
- // This must be the very next call, otherwise we can get flicker on close.
- SetLayeredWindowAttributes(GetNativeView(), 0,
- static_cast<byte>(255), LWA_ALPHA);
-#endif
-
- Fade(false); // |fade_in|.
-}
-
-void InfoBubble::Fade(bool fade_in) {
- animation_.reset(new SlideAnimation(this));
- animation_->SetSlideDuration(kHideFadeDurationMS);
- animation_->SetTweenType(Tween::LINEAR);
-
- animation_->Reset(fade_in ? 0.0 : 1.0);
- if (fade_in)
- animation_->Show();
- else
- animation_->Hide();
-}
-
-bool InfoBubble::AcceleratorPressed(const views::Accelerator& accelerator) {
- if (!delegate_ || delegate_->CloseOnEscape()) {
- DoClose(true);
- return true;
- }
- return false;
-}