diff options
author | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-09 07:35:32 +0000 |
---|---|---|
committer | ben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-09 07:35:32 +0000 |
commit | 213dac2f0bff9162502fe325b6ebb85a255efcb2 (patch) | |
tree | 3640cb1f19976e38677b8632537d2d41f8444d0f /chrome/browser/views/info_bubble.cc | |
parent | 6de53d401aa8dc6c7e0a9874c71a95ce88ade50d (diff) | |
download | chromium_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.cc | 542 |
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; -} |