diff options
author | pkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-01 01:10:04 +0000 |
---|---|---|
committer | pkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-01 01:10:04 +0000 |
commit | fc3c351a3d995f73ead5c92354396a7ec2b14e3f (patch) | |
tree | 33af8d2ebcce3421b61f184e98d550112d378eec /chrome/browser/ui/views/infobars/infobar_view.cc | |
parent | d1bc344d61be8d5c885f6b0f65c8c749d8c9d7df (diff) | |
download | chromium_src-fc3c351a3d995f73ead5c92354396a7ec2b14e3f.zip chromium_src-fc3c351a3d995f73ead5c92354396a7ec2b14e3f.tar.gz chromium_src-fc3c351a3d995f73ead5c92354396a7ec2b14e3f.tar.bz2 |
Split infobars.{cc,h} into separate pieces for the different classes defined within, so that each piece is shorter and clearer.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/6250057
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@73235 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/ui/views/infobars/infobar_view.cc')
-rw-r--r-- | chrome/browser/ui/views/infobars/infobar_view.cc | 269 |
1 files changed, 269 insertions, 0 deletions
diff --git a/chrome/browser/ui/views/infobars/infobar_view.cc b/chrome/browser/ui/views/infobars/infobar_view.cc new file mode 100644 index 0000000..a45021f --- /dev/null +++ b/chrome/browser/ui/views/infobars/infobar_view.cc @@ -0,0 +1,269 @@ +// Copyright (c) 2011 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/ui/views/infobars/infobar_view.h" + +#include "base/message_loop.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/ui/views/infobars/infobar_background.h" +#include "chrome/browser/ui/views/infobars/infobar_container.h" +#include "chrome/browser/tab_contents/infobar_delegate.h" +#include "grit/generated_resources.h" +#include "grit/theme_resources.h" +#include "ui/base/animation/slide_animation.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/resource/resource_bundle.h" +#include "views/controls/button/image_button.h" +#include "views/controls/image_view.h" +#include "views/controls/label.h" +#include "views/focus/external_focus_tracker.h" +#include "views/widget/widget.h" + +#if defined(OS_WIN) +#include "ui/base/win/hwnd_util.h" +#endif + +// static +const double InfoBarView::kDefaultTargetHeight = 36.0; +const int InfoBarView::kHorizontalPadding = 6; +const int InfoBarView::kIconLabelSpacing = 6; +const int InfoBarView::kButtonButtonSpacing = 10; +const int InfoBarView::kEndOfLabelSpacing = 16; +const int InfoBarView::kCloseButtonSpacing = 12; +const int InfoBarView::kButtonInLabelSpacing = 5; + +// InfoBarView, public: ------------------------------------------------------- + +InfoBarView::InfoBarView(InfoBarDelegate* delegate) + : InfoBar(delegate), + delegate_(delegate), + ALLOW_THIS_IN_INITIALIZER_LIST( + close_button_(new views::ImageButton(this))), + ALLOW_THIS_IN_INITIALIZER_LIST(delete_factory_(this)), + target_height_(kDefaultTargetHeight) { + // We delete ourselves when we're removed from the view hierarchy. + set_parent_owned(false); + + set_background(new InfoBarBackground(delegate->GetInfoBarType())); + + switch (delegate->GetInfoBarType()) { + case InfoBarDelegate::WARNING_TYPE: + SetAccessibleName( + l10n_util::GetStringUTF16(IDS_ACCNAME_INFOBAR_WARNING)); + break; + case InfoBarDelegate::PAGE_ACTION_TYPE: + SetAccessibleName( + l10n_util::GetStringUTF16(IDS_ACCNAME_INFOBAR_PAGE_ACTION)); + break; + default: + NOTREACHED(); + break; + } + + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + close_button_->SetImage(views::CustomButton::BS_NORMAL, + rb.GetBitmapNamed(IDR_CLOSE_BAR)); + close_button_->SetImage(views::CustomButton::BS_HOT, + rb.GetBitmapNamed(IDR_CLOSE_BAR_H)); + close_button_->SetImage(views::CustomButton::BS_PUSHED, + rb.GetBitmapNamed(IDR_CLOSE_BAR_P)); + close_button_->SetAccessibleName( + l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); + AddChildView(close_button_); + + animation_.reset(new ui::SlideAnimation(this)); + animation_->SetTweenType(ui::Tween::LINEAR); +} + +InfoBarView::~InfoBarView() { +} + +// InfoBarView, views::View overrides: ---------------------------------------- + +AccessibilityTypes::Role InfoBarView::GetAccessibleRole() { + return AccessibilityTypes::ROLE_ALERT; +} + +gfx::Size InfoBarView::GetPreferredSize() { + int height = static_cast<int>(target_height_ * animation_->GetCurrentValue()); + return gfx::Size(0, height); +} + +void InfoBarView::Layout() { + gfx::Size button_ps = close_button_->GetPreferredSize(); + close_button_->SetBounds(width() - kHorizontalPadding - button_ps.width(), + OffsetY(this, button_ps), button_ps.width(), + button_ps.height()); +} + +void InfoBarView::ViewHierarchyChanged(bool is_add, + views::View* parent, + views::View* child) { + if (child == this) { + if (is_add) { + InfoBarAdded(); + } else { + InfoBarRemoved(); + } + } + + if (GetWidget() && GetWidget()->IsAccessibleWidget()) { + // For accessibility, make the close button the last child view. + if (parent == this && child != close_button_ && + HasChildView(close_button_) && + GetChildViewAt(GetChildViewCount() - 1) != close_button_) { + RemoveChildView(close_button_); + AddChildView(close_button_); + } + + // Allow screen reader users to focus the close button. + close_button_->SetFocusable(true); + } +} + +// InfoBarView, protected: ---------------------------------------------------- + +int InfoBarView::GetAvailableWidth() const { + return close_button_->x() - kCloseButtonSpacing; +} + +void InfoBarView::RemoveInfoBar() const { + if (container_) + container_->RemoveDelegate(delegate()); +} + +int InfoBarView::CenterY(const gfx::Size prefsize) { + return std::max((static_cast<int>(target_height_) - + prefsize.height()) / 2, 0); +} + +int InfoBarView::OffsetY(views::View* parent, const gfx::Size prefsize) { + return CenterY(prefsize) - + (static_cast<int>(target_height_) - parent->height()); +} + +// InfoBarView, views::ButtonListener implementation: ------------------------- + +void InfoBarView::ButtonPressed(views::Button* sender, + const views::Event& event) { + if (sender == close_button_) { + if (delegate_) + delegate_->InfoBarDismissed(); + RemoveInfoBar(); + } +} + +// InfoBarView, views::FocusChangeListener implementation: -------------------- + +void InfoBarView::FocusWillChange(View* focused_before, View* focused_now) { + // This will trigger some screen readers to read the entire contents of this + // infobar. + if (focused_before && focused_now && + !this->IsParentOf(focused_before) && this->IsParentOf(focused_now)) { + NotifyAccessibilityEvent(AccessibilityTypes::EVENT_ALERT); + } +} + +// InfoBarView, ui::AnimationDelegate implementation: ------------------------- + +void InfoBarView::AnimationProgressed(const ui::Animation* animation) { + if (container_) + container_->InfoBarAnimated(true); +} + +void InfoBarView::AnimationEnded(const ui::Animation* animation) { + if (container_) { + container_->InfoBarAnimated(false); + + if (!animation_->IsShowing()) + Close(); + } +} + +// InfoBarView, private: ------------------------------------------------------ + +void InfoBarView::AnimateOpen() { + animation_->Show(); +} + +void InfoBarView::Open() { + // Set the animation value to 1.0 so that GetPreferredSize() returns the right + // size. + animation_->Reset(1.0); + if (container_) + container_->InfoBarAnimated(false); +} + +void InfoBarView::AnimateClose() { + bool restore_focus = true; +#if defined(OS_WIN) + // Do not restore focus (and active state with it) on Windows if some other + // top-level window became active. + if (GetWidget() && + !ui::DoesWindowBelongToActiveWindow(GetWidget()->GetNativeView())) { + restore_focus = false; + } +#endif // defined(OS_WIN) + DestroyFocusTracker(restore_focus); + animation_->Hide(); +} + +void InfoBarView::Close() { + GetParent()->RemoveChildView(this); + // Note that we only tell the delegate we're closed here, and not when we're + // simply destroyed (by virtue of a tab switch or being moved from window to + // window), since this action can cause the delegate to destroy itself. + if (delegate_) { + delegate_->InfoBarClosed(); + delegate_ = NULL; + } +} + +void InfoBarView::InfoBarAdded() { + // The container_ pointer must be set before adding to the view hierarchy. + DCHECK(container_); +#if defined(OS_WIN) + // When we're added to a view hierarchy within a widget, we create an + // external focus tracker to track what was focused in case we obtain + // focus so that we can restore focus when we're removed. + views::Widget* widget = GetWidget(); + if (widget) { + focus_tracker_.reset(new views::ExternalFocusTracker(this, + GetFocusManager())); + } +#endif + + if (GetFocusManager()) + GetFocusManager()->AddFocusChangeListener(this); + + NotifyAccessibilityEvent(AccessibilityTypes::EVENT_ALERT); +} + +void InfoBarView::InfoBarRemoved() { + DestroyFocusTracker(false); + // NULL our container_ pointer so that if Animation::Stop results in + // AnimationEnded being called, we do not try and delete ourselves twice. + container_ = NULL; + animation_->Stop(); + // Finally, clean ourselves up when we're removed from the view hierarchy + // since no-one refers to us now. + MessageLoop::current()->PostTask(FROM_HERE, + delete_factory_.NewRunnableMethod(&InfoBarView::DeleteSelf)); + + if (GetFocusManager()) + GetFocusManager()->RemoveFocusChangeListener(this); +} + +void InfoBarView::DestroyFocusTracker(bool restore_focus) { + if (focus_tracker_.get()) { + if (restore_focus) + focus_tracker_->FocusLastFocusedExternalView(); + focus_tracker_->SetFocusManager(NULL); + focus_tracker_.reset(NULL); + } +} + +void InfoBarView::DeleteSelf() { + delete this; +} |