| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/infobars/core/infobar.h" | 5 #include "components/infobars/core/infobar.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
| 11 #include "components/infobars/core/infobar_container.h" | 11 #include "components/infobars/core/infobar_container.h" |
| 12 #include "components/infobars/core/infobar_manager.h" | 12 #include "components/infobars/core/infobar_manager.h" |
| 13 #include "ui/gfx/animation/slide_animation.h" | 13 #include "ui/gfx/animation/slide_animation.h" |
| 14 | 14 |
| 15 namespace infobars { | 15 namespace infobars { |
| 16 | 16 |
| 17 InfoBar::InfoBar(scoped_ptr<InfoBarDelegate> delegate) | 17 InfoBar::InfoBar(scoped_ptr<InfoBarDelegate> delegate) |
| 18 : owner_(NULL), | 18 : owner_(NULL), |
| 19 delegate_(delegate.Pass()), | 19 delegate_(delegate.Pass()), |
| 20 container_(NULL), | 20 container_(NULL), |
| 21 animation_(this), | 21 animation_(this), |
| 22 arrow_height_(0), | 22 arrow_height_(0), |
| 23 arrow_target_height_(kDefaultArrowTargetHeight), | 23 arrow_target_height_(0), |
| 24 arrow_half_width_(0), | 24 arrow_half_width_(0), |
| 25 bar_height_(0), | 25 bar_height_(0), |
| 26 bar_target_height_(kDefaultBarTargetHeight) { | 26 bar_target_height_(-1) { |
| 27 DCHECK(delegate_ != NULL); | 27 DCHECK(delegate_ != NULL); |
| 28 animation_.SetTweenType(gfx::Tween::LINEAR); | 28 animation_.SetTweenType(gfx::Tween::LINEAR); |
| 29 delegate_->set_infobar(this); | 29 delegate_->set_infobar(this); |
| 30 } | 30 } |
| 31 | 31 |
| 32 InfoBar::~InfoBar() { | 32 InfoBar::~InfoBar() { |
| 33 DCHECK(!owner_); | 33 DCHECK(!owner_); |
| 34 } | 34 } |
| 35 | 35 |
| 36 // static | 36 // static |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 78 animation_.Reset(0.0); | 78 animation_.Reset(0.0); |
| 79 // We want to remove ourselves from the container immediately even if we | 79 // We want to remove ourselves from the container immediately even if we |
| 80 // still have an owner, which MaybeDelete() won't do. | 80 // still have an owner, which MaybeDelete() won't do. |
| 81 DCHECK(container_); | 81 DCHECK(container_); |
| 82 container_->RemoveInfoBar(this); | 82 container_->RemoveInfoBar(this); |
| 83 MaybeDelete(); // Necessary if the infobar was already closing. | 83 MaybeDelete(); // Necessary if the infobar was already closing. |
| 84 } | 84 } |
| 85 } | 85 } |
| 86 | 86 |
| 87 void InfoBar::SetArrowTargetHeight(int height) { | 87 void InfoBar::SetArrowTargetHeight(int height) { |
| 88 DCHECK_LE(height, kMaximumArrowTargetHeight); | |
| 89 // Once the closing animation starts, we ignore further requests to change the | 88 // Once the closing animation starts, we ignore further requests to change the |
| 90 // target height. | 89 // target height. |
| 91 if ((arrow_target_height_ != height) && !animation_.IsClosing()) { | 90 if ((arrow_target_height_ != height) && !animation_.IsClosing()) { |
| 92 arrow_target_height_ = height; | 91 arrow_target_height_ = height; |
| 93 RecalculateHeights(false); | 92 RecalculateHeights(false); |
| 94 } | 93 } |
| 95 } | 94 } |
| 96 | 95 |
| 97 void InfoBar::CloseSoon() { | 96 void InfoBar::CloseSoon() { |
| 98 owner_ = NULL; | 97 owner_ = NULL; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 119 void InfoBar::AnimationEnded(const gfx::Animation* animation) { | 118 void InfoBar::AnimationEnded(const gfx::Animation* animation) { |
| 120 // When the animation ends, we must ensure the container is notified even if | 119 // When the animation ends, we must ensure the container is notified even if |
| 121 // the heights haven't changed, lest it never get an "animation finished" | 120 // the heights haven't changed, lest it never get an "animation finished" |
| 122 // notification. (If the browser doesn't get this notification, it will not | 121 // notification. (If the browser doesn't get this notification, it will not |
| 123 // bother to re-layout the content area for the new infobar size.) | 122 // bother to re-layout the content area for the new infobar size.) |
| 124 RecalculateHeights(true); | 123 RecalculateHeights(true); |
| 125 MaybeDelete(); | 124 MaybeDelete(); |
| 126 } | 125 } |
| 127 | 126 |
| 128 void InfoBar::RecalculateHeights(bool force_notify) { | 127 void InfoBar::RecalculateHeights(bool force_notify) { |
| 128 // If there's no container delegate, there's no way to compute new element |
| 129 // sizes, so return immediately. We don't need to worry that this might leave |
| 130 // us with bogus sizes, because if we're ever re-added to a container, it will |
| 131 // call Show(false) while re-adding us, which will compute a correct set of |
| 132 // sizes. |
| 133 if (!container_ || !container_->delegate()) |
| 134 return; |
| 135 |
| 129 int old_arrow_height = arrow_height_; | 136 int old_arrow_height = arrow_height_; |
| 130 int old_bar_height = bar_height_; | 137 int old_bar_height = bar_height_; |
| 131 | 138 |
| 132 // Find the desired arrow height/half-width. The arrow area is | 139 container_->delegate()->ComputeInfoBarElementSizes( |
| 133 // |arrow_height_| * |arrow_half_width_|. When the bar is opening or closing, | 140 animation_, arrow_target_height_, bar_target_height_, &arrow_height_, |
| 134 // scaling each of these with the square root of the animation value causes a | 141 &arrow_half_width_, &bar_height_); |
| 135 // linear animation of the area, which matches the perception of the animation | |
| 136 // of the bar portion. | |
| 137 double scale_factor = sqrt(animation_.GetCurrentValue()); | |
| 138 arrow_height_ = static_cast<int>(arrow_target_height_ * scale_factor); | |
| 139 if (animation_.is_animating()) { | |
| 140 arrow_half_width_ = static_cast<int>(std::min(arrow_target_height_, | |
| 141 kMaximumArrowTargetHalfWidth) * scale_factor); | |
| 142 } else { | |
| 143 // When the infobar is not animating (i.e. fully open), we set the | |
| 144 // half-width to be proportionally the same distance between its default and | |
| 145 // maximum values as the height is between its. | |
| 146 arrow_half_width_ = kDefaultArrowTargetHalfWidth + | |
| 147 ((kMaximumArrowTargetHalfWidth - kDefaultArrowTargetHalfWidth) * | |
| 148 ((arrow_height_ - kDefaultArrowTargetHeight) / | |
| 149 (kMaximumArrowTargetHeight - kDefaultArrowTargetHeight))); | |
| 150 } | |
| 151 // Add pixels for the stroke, if the arrow is to be visible at all. Without | |
| 152 // this, changing the arrow height from 0 to kSeparatorLineHeight would | |
| 153 // produce no visible effect, because the stroke would paint atop the divider | |
| 154 // line above the infobar. | |
| 155 if (arrow_height_) | |
| 156 arrow_height_ += kSeparatorLineHeight; | |
| 157 | |
| 158 bar_height_ = animation_.CurrentValueBetween(0, bar_target_height_); | |
| 159 | 142 |
| 160 // Don't re-layout if nothing has changed, e.g. because the animation step was | 143 // Don't re-layout if nothing has changed, e.g. because the animation step was |
| 161 // not large enough to actually change the heights by at least a pixel. | 144 // not large enough to actually change the heights by at least a pixel. |
| 162 bool heights_differ = | 145 bool heights_differ = |
| 163 (old_arrow_height != arrow_height_) || (old_bar_height != bar_height_); | 146 (old_arrow_height != arrow_height_) || (old_bar_height != bar_height_); |
| 164 if (heights_differ) | 147 if (heights_differ) |
| 165 PlatformSpecificOnHeightsRecalculated(); | 148 PlatformSpecificOnHeightsRecalculated(); |
| 166 | 149 |
| 167 if (container_ && (heights_differ || force_notify)) | 150 if (heights_differ || force_notify) |
| 168 container_->OnInfoBarStateChanged(animation_.is_animating()); | 151 container_->OnInfoBarStateChanged(animation_.is_animating()); |
| 169 } | 152 } |
| 170 | 153 |
| 171 void InfoBar::MaybeDelete() { | 154 void InfoBar::MaybeDelete() { |
| 172 if (!owner_ && (animation_.GetCurrentValue() == 0.0)) { | 155 if (!owner_ && (animation_.GetCurrentValue() == 0.0)) { |
| 173 if (container_) | 156 if (container_) |
| 174 container_->RemoveInfoBar(this); | 157 container_->RemoveInfoBar(this); |
| 175 delete this; | 158 delete this; |
| 176 } | 159 } |
| 177 } | 160 } |
| 178 | 161 |
| 179 } // namespace infobars | 162 } // namespace infobars |
| OLD | NEW |