infobar.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Copyright 2014 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/infobars/core/infobar.h"
  5. #include <cmath>
  6. #include <memory>
  7. #include <utility>
  8. #include "base/check.h"
  9. #include "build/build_config.h"
  10. #include "components/infobars/core/infobar_container.h"
  11. #include "components/infobars/core/infobar_manager.h"
  12. #include "ui/gfx/animation/slide_animation.h"
  13. namespace infobars {
  14. InfoBar::InfoBar(std::unique_ptr<InfoBarDelegate> delegate)
  15. : owner_(nullptr),
  16. delegate_(std::move(delegate)),
  17. container_(nullptr),
  18. notifier_(std::make_unique<gfx::AnimationDelegateNotifier<>>(this)),
  19. animation_(notifier_.get()),
  20. height_(0),
  21. target_height_(0) {
  22. DCHECK(delegate_ != nullptr);
  23. animation_.SetTweenType(gfx::Tween::LINEAR);
  24. if (!gfx::Animation::ShouldRenderRichAnimation() ||
  25. !delegate_->ShouldAnimate()) {
  26. animation_.SetSlideDuration(base::TimeDelta());
  27. }
  28. delegate_->set_infobar(this);
  29. }
  30. InfoBar::~InfoBar() {
  31. DCHECK(!owner_);
  32. }
  33. void InfoBar::SetOwner(InfoBarManager* owner) {
  34. DCHECK(!owner_);
  35. owner_ = owner;
  36. delegate_->set_nav_entry_id(owner->GetActiveEntryID());
  37. PlatformSpecificSetOwner();
  38. }
  39. void InfoBar::SetNotifier(std::unique_ptr<gfx::AnimationDelegate> notifier) {
  40. notifier_ = std::move(notifier);
  41. animation_.set_delegate(notifier_.get());
  42. }
  43. void InfoBar::Show(bool animate) {
  44. PlatformSpecificShow(animate);
  45. if (animate) {
  46. animation_.Show();
  47. } else {
  48. animation_.Reset(1.0);
  49. RecalculateHeight(true);
  50. }
  51. }
  52. void InfoBar::Hide(bool animate) {
  53. PlatformSpecificHide(animate);
  54. if (animate) {
  55. animation_.Hide();
  56. } else {
  57. animation_.Reset(0.0);
  58. // We want to remove ourselves from the container immediately even if we
  59. // still have an owner, which MaybeDelete() won't do.
  60. DCHECK(container_);
  61. container_->RemoveInfoBar(this);
  62. MaybeDelete(); // Necessary if the infobar was already closing.
  63. }
  64. }
  65. void InfoBar::CloseSoon() {
  66. owner_ = nullptr;
  67. PlatformSpecificOnCloseSoon();
  68. MaybeDelete();
  69. }
  70. void InfoBar::RemoveSelf() {
  71. if (owner_)
  72. owner_->RemoveInfoBar(this);
  73. }
  74. void InfoBar::SetTargetHeight(int height) {
  75. if (target_height_ != height) {
  76. target_height_ = height;
  77. RecalculateHeight(false);
  78. }
  79. }
  80. void InfoBar::AnimationProgressed(const gfx::Animation* animation) {
  81. RecalculateHeight(false);
  82. }
  83. void InfoBar::AnimationEnded(const gfx::Animation* animation) {
  84. // When the animation ends, we must ensure the container is notified even if
  85. // the heights haven't changed, lest it never get an "animation finished"
  86. // notification. (If the browser doesn't get this notification, it will not
  87. // bother to re-layout the content area for the new infobar size.)
  88. RecalculateHeight(true);
  89. MaybeDelete();
  90. }
  91. void InfoBar::RecalculateHeight(bool force_notify) {
  92. // If there's no container delegate, there's no way to compute the new height,
  93. // so return immediately. We don't need to worry that this might leave us
  94. // with bogus sizes, because if we're ever re-added to a container, it will
  95. // call Show(false) while re-adding us, which will compute a correct set of
  96. // sizes.
  97. if (!container_ || !container_->delegate())
  98. return;
  99. int old_height = height_;
  100. height_ = animation_.CurrentValueBetween(0, target_height_);
  101. // Don't re-layout if nothing has changed, e.g. because the animation step was
  102. // not large enough to actually change the height by at least a pixel.
  103. bool height_differs = old_height != height_;
  104. if (height_differs)
  105. PlatformSpecificOnHeightRecalculated();
  106. if (height_differs || force_notify)
  107. container_->OnInfoBarStateChanged(animation_.is_animating());
  108. }
  109. void InfoBar::MaybeDelete() {
  110. if (!owner_ && (animation_.GetCurrentValue() == 0.0)) {
  111. if (container_)
  112. container_->RemoveInfoBar(this);
  113. delete this;
  114. }
  115. }
  116. } // namespace infobars