| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 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 | |
| 5 #include "chrome/browser/infobars/infobar.h" | |
| 6 | |
| 7 #include <cmath> | |
| 8 | |
| 9 #include "base/logging.h" | |
| 10 #include "build/build_config.h" | |
| 11 #include "chrome/browser/infobars/infobar_container.h" | |
| 12 #include "chrome/browser/infobars/infobar_manager.h" | |
| 13 #include "ui/gfx/animation/slide_animation.h" | |
| 14 | |
| 15 InfoBar::InfoBar(scoped_ptr<InfoBarDelegate> delegate) | |
| 16 : owner_(NULL), | |
| 17 delegate_(delegate.Pass()), | |
| 18 container_(NULL), | |
| 19 animation_(this), | |
| 20 arrow_height_(0), | |
| 21 arrow_target_height_(kDefaultArrowTargetHeight), | |
| 22 arrow_half_width_(0), | |
| 23 bar_height_(0), | |
| 24 bar_target_height_(kDefaultBarTargetHeight) { | |
| 25 DCHECK(delegate_ != NULL); | |
| 26 animation_.SetTweenType(gfx::Tween::LINEAR); | |
| 27 delegate_->set_infobar(this); | |
| 28 } | |
| 29 | |
| 30 InfoBar::~InfoBar() { | |
| 31 DCHECK(!owner_); | |
| 32 } | |
| 33 | |
| 34 // static | |
| 35 SkColor InfoBar::GetTopColor(InfoBarDelegate::Type infobar_type) { | |
| 36 static const SkColor kWarningBackgroundColorTop = | |
| 37 SkColorSetRGB(255, 242, 183); // Yellow | |
| 38 static const SkColor kPageActionBackgroundColorTop = | |
| 39 SkColorSetRGB(237, 237, 237); // Gray | |
| 40 return (infobar_type == InfoBarDelegate::WARNING_TYPE) ? | |
| 41 kWarningBackgroundColorTop : kPageActionBackgroundColorTop; | |
| 42 } | |
| 43 | |
| 44 // static | |
| 45 SkColor InfoBar::GetBottomColor(InfoBarDelegate::Type infobar_type) { | |
| 46 static const SkColor kWarningBackgroundColorBottom = | |
| 47 SkColorSetRGB(250, 230, 145); // Yellow | |
| 48 static const SkColor kPageActionBackgroundColorBottom = | |
| 49 SkColorSetRGB(217, 217, 217); // Gray | |
| 50 return (infobar_type == InfoBarDelegate::WARNING_TYPE) ? | |
| 51 kWarningBackgroundColorBottom : kPageActionBackgroundColorBottom; | |
| 52 } | |
| 53 | |
| 54 void InfoBar::SetOwner(InfoBarManager* owner) { | |
| 55 DCHECK(!owner_); | |
| 56 owner_ = owner; | |
| 57 delegate_->StoreActiveEntryUniqueID(); | |
| 58 PlatformSpecificSetOwner(); | |
| 59 } | |
| 60 | |
| 61 void InfoBar::Show(bool animate) { | |
| 62 PlatformSpecificShow(animate); | |
| 63 if (animate) { | |
| 64 animation_.Show(); | |
| 65 } else { | |
| 66 animation_.Reset(1.0); | |
| 67 RecalculateHeights(true); | |
| 68 } | |
| 69 } | |
| 70 | |
| 71 void InfoBar::Hide(bool animate) { | |
| 72 PlatformSpecificHide(animate); | |
| 73 if (animate) { | |
| 74 animation_.Hide(); | |
| 75 } else { | |
| 76 animation_.Reset(0.0); | |
| 77 // We want to remove ourselves from the container immediately even if we | |
| 78 // still have an owner, which MaybeDelete() won't do. | |
| 79 DCHECK(container_); | |
| 80 container_->RemoveInfoBar(this); | |
| 81 MaybeDelete(); // Necessary if the infobar was already closing. | |
| 82 } | |
| 83 } | |
| 84 | |
| 85 void InfoBar::SetArrowTargetHeight(int height) { | |
| 86 DCHECK_LE(height, kMaximumArrowTargetHeight); | |
| 87 // Once the closing animation starts, we ignore further requests to change the | |
| 88 // target height. | |
| 89 if ((arrow_target_height_ != height) && !animation_.IsClosing()) { | |
| 90 arrow_target_height_ = height; | |
| 91 RecalculateHeights(false); | |
| 92 } | |
| 93 } | |
| 94 | |
| 95 void InfoBar::CloseSoon() { | |
| 96 owner_ = NULL; | |
| 97 PlatformSpecificOnCloseSoon(); | |
| 98 MaybeDelete(); | |
| 99 } | |
| 100 | |
| 101 void InfoBar::RemoveSelf() { | |
| 102 if (owner_) | |
| 103 owner_->RemoveInfoBar(this); | |
| 104 } | |
| 105 | |
| 106 void InfoBar::SetBarTargetHeight(int height) { | |
| 107 if (bar_target_height_ != height) { | |
| 108 bar_target_height_ = height; | |
| 109 RecalculateHeights(false); | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 void InfoBar::AnimationProgressed(const gfx::Animation* animation) { | |
| 114 RecalculateHeights(false); | |
| 115 } | |
| 116 | |
| 117 void InfoBar::AnimationEnded(const gfx::Animation* animation) { | |
| 118 // When the animation ends, we must ensure the container is notified even if | |
| 119 // the heights haven't changed, lest it never get an "animation finished" | |
| 120 // notification. (If the browser doesn't get this notification, it will not | |
| 121 // bother to re-layout the content area for the new infobar size.) | |
| 122 RecalculateHeights(true); | |
| 123 MaybeDelete(); | |
| 124 } | |
| 125 | |
| 126 void InfoBar::RecalculateHeights(bool force_notify) { | |
| 127 int old_arrow_height = arrow_height_; | |
| 128 int old_bar_height = bar_height_; | |
| 129 | |
| 130 // Find the desired arrow height/half-width. The arrow area is | |
| 131 // |arrow_height_| * |arrow_half_width_|. When the bar is opening or closing, | |
| 132 // scaling each of these with the square root of the animation value causes a | |
| 133 // linear animation of the area, which matches the perception of the animation | |
| 134 // of the bar portion. | |
| 135 double scale_factor = sqrt(animation_.GetCurrentValue()); | |
| 136 arrow_height_ = static_cast<int>(arrow_target_height_ * scale_factor); | |
| 137 if (animation_.is_animating()) { | |
| 138 arrow_half_width_ = static_cast<int>(std::min(arrow_target_height_, | |
| 139 kMaximumArrowTargetHalfWidth) * scale_factor); | |
| 140 } else { | |
| 141 // When the infobar is not animating (i.e. fully open), we set the | |
| 142 // half-width to be proportionally the same distance between its default and | |
| 143 // maximum values as the height is between its. | |
| 144 arrow_half_width_ = kDefaultArrowTargetHalfWidth + | |
| 145 ((kMaximumArrowTargetHalfWidth - kDefaultArrowTargetHalfWidth) * | |
| 146 ((arrow_height_ - kDefaultArrowTargetHeight) / | |
| 147 (kMaximumArrowTargetHeight - kDefaultArrowTargetHeight))); | |
| 148 } | |
| 149 // Add pixels for the stroke, if the arrow is to be visible at all. Without | |
| 150 // this, changing the arrow height from 0 to kSeparatorLineHeight would | |
| 151 // produce no visible effect, because the stroke would paint atop the divider | |
| 152 // line above the infobar. | |
| 153 if (arrow_height_) | |
| 154 arrow_height_ += kSeparatorLineHeight; | |
| 155 | |
| 156 bar_height_ = animation_.CurrentValueBetween(0, bar_target_height_); | |
| 157 | |
| 158 // Don't re-layout if nothing has changed, e.g. because the animation step was | |
| 159 // not large enough to actually change the heights by at least a pixel. | |
| 160 bool heights_differ = | |
| 161 (old_arrow_height != arrow_height_) || (old_bar_height != bar_height_); | |
| 162 if (heights_differ) | |
| 163 PlatformSpecificOnHeightsRecalculated(); | |
| 164 | |
| 165 if (container_ && (heights_differ || force_notify)) | |
| 166 container_->OnInfoBarStateChanged(animation_.is_animating()); | |
| 167 } | |
| 168 | |
| 169 void InfoBar::MaybeDelete() { | |
| 170 if (!owner_ && (animation_.GetCurrentValue() == 0.0)) { | |
| 171 if (container_) | |
| 172 container_->RemoveInfoBar(this); | |
| 173 delete this; | |
| 174 } | |
| 175 } | |
| OLD | NEW |