Fix build break
[chromium-blink-merge.git] / chrome / browser / infobars / infobar.cc
bloba7a9647af1dc96a57c448530e011d5c4d1650a37
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.
5 #include "chrome/browser/infobars/infobar.h"
7 #include <cmath>
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_service.h"
13 #include "ui/base/animation/slide_animation.h"
15 SkColor GetInfoBarTopColor(InfoBarDelegate::Type infobar_type) {
16 // Yellow
17 static const SkColor kWarningBackgroundColorTop =
18 SkColorSetRGB(255, 242, 183);
19 // Gray
20 static const SkColor kPageActionBackgroundColorTop =
21 SkColorSetRGB(237, 237, 237);
23 return (infobar_type == InfoBarDelegate::WARNING_TYPE) ?
24 kWarningBackgroundColorTop : kPageActionBackgroundColorTop;
27 SkColor GetInfoBarBottomColor(InfoBarDelegate::Type infobar_type) {
28 // Yellow
29 static const SkColor kWarningBackgroundColorBottom =
30 SkColorSetRGB(250, 230, 145);
31 // Gray
32 static const SkColor kPageActionBackgroundColorBottom =
33 SkColorSetRGB(217, 217, 217);
35 return (infobar_type == InfoBarDelegate::WARNING_TYPE) ?
36 kWarningBackgroundColorBottom : kPageActionBackgroundColorBottom;
39 // TODO(pkasting): Port Mac to use this.
40 #if defined(TOOLKIT_VIEWS) || defined(TOOLKIT_GTK)
42 InfoBar::InfoBar(InfoBarService* owner, InfoBarDelegate* delegate)
43 : owner_(owner),
44 delegate_(delegate),
45 container_(NULL),
46 ALLOW_THIS_IN_INITIALIZER_LIST(animation_(this)),
47 arrow_height_(0),
48 arrow_target_height_(kDefaultArrowTargetHeight),
49 arrow_half_width_(0),
50 bar_height_(0),
51 bar_target_height_(kDefaultBarTargetHeight) {
52 DCHECK(owner_ != NULL);
53 DCHECK(delegate_ != NULL);
54 animation_.SetTweenType(ui::Tween::LINEAR);
57 InfoBar::~InfoBar() {
60 void InfoBar::Show(bool animate) {
61 PlatformSpecificShow(animate);
62 if (animate) {
63 animation_.Show();
64 } else {
65 animation_.Reset(1.0);
66 RecalculateHeights(true);
70 void InfoBar::Hide(bool animate) {
71 PlatformSpecificHide(animate);
72 if (animate) {
73 animation_.Hide();
74 } else {
75 animation_.Reset(0.0);
76 // We want to remove ourselves from the container immediately even if we
77 // still have an owner, which MaybeDelete() won't do.
78 DCHECK(container_);
79 container_->RemoveInfoBar(this);
80 MaybeDelete(); // Necessary if the infobar was already closing.
84 void InfoBar::SetArrowTargetHeight(int height) {
85 DCHECK_LE(height, kMaximumArrowTargetHeight);
86 // Once the closing animation starts, we ignore further requests to change the
87 // target height.
88 if ((arrow_target_height_ != height) && !animation_.IsClosing()) {
89 arrow_target_height_ = height;
90 RecalculateHeights(false);
94 void InfoBar::CloseSoon() {
95 owner_ = NULL;
96 PlatformSpecificOnCloseSoon();
97 MaybeDelete();
100 void InfoBar::AnimationProgressed(const ui::Animation* animation) {
101 RecalculateHeights(false);
104 void InfoBar::RemoveSelf() {
105 // |owner_| should never be NULL here. If it is, then someone violated what
106 // they were supposed to do -- e.g. a ConfirmInfoBarDelegate subclass returned
107 // true from Accept() or Cancel() even though the infobar was already closing.
108 // In the worst case, if we also switched tabs during that process, then
109 // |this| has already been destroyed. But if that's the case, then we're
110 // going to deref a garbage |this| pointer here whether we check |owner_| or
111 // not, and in other cases (where we're still closing and |this| is valid),
112 // checking |owner_| here will avoid a NULL deref.
113 if (owner_)
114 owner_->RemoveInfoBar(delegate_);
117 void InfoBar::SetBarTargetHeight(int height) {
118 if (bar_target_height_ != height) {
119 bar_target_height_ = height;
120 RecalculateHeights(false);
124 int InfoBar::OffsetY(const gfx::Size& prefsize) const {
125 return arrow_height_ +
126 std::max((bar_target_height_ - prefsize.height()) / 2, 0) -
127 (bar_target_height_ - bar_height_);
130 void InfoBar::AnimationEnded(const ui::Animation* animation) {
131 // When the animation ends, we must ensure the container is notified even if
132 // the heights haven't changed, lest it never get an "animation finished"
133 // notification. (If the browser doesn't get this notification, it will not
134 // bother to re-layout the content area for the new infobar size.)
135 RecalculateHeights(true);
136 MaybeDelete();
139 void InfoBar::RecalculateHeights(bool force_notify) {
140 int old_arrow_height = arrow_height_;
141 int old_bar_height = bar_height_;
143 // Find the desired arrow height/half-width. The arrow area is
144 // |arrow_height_| * |arrow_half_width_|. When the bar is opening or closing,
145 // scaling each of these with the square root of the animation value causes a
146 // linear animation of the area, which matches the perception of the animation
147 // of the bar portion.
148 double scale_factor = sqrt(animation_.GetCurrentValue());
149 arrow_height_ = static_cast<int>(arrow_target_height_ * scale_factor);
150 if (animation_.is_animating()) {
151 arrow_half_width_ = static_cast<int>(std::min(arrow_target_height_,
152 kMaximumArrowTargetHalfWidth) * scale_factor);
153 } else {
154 // When the infobar is not animating (i.e. fully open), we set the
155 // half-width to be proportionally the same distance between its default and
156 // maximum values as the height is between its.
157 arrow_half_width_ = kDefaultArrowTargetHalfWidth +
158 ((kMaximumArrowTargetHalfWidth - kDefaultArrowTargetHalfWidth) *
159 ((arrow_height_ - kDefaultArrowTargetHeight) /
160 (kMaximumArrowTargetHeight - kDefaultArrowTargetHeight)));
162 // Add pixels for the stroke, if the arrow is to be visible at all. Without
163 // this, changing the arrow height from 0 to kSeparatorLineHeight would
164 // produce no visible effect, because the stroke would paint atop the divider
165 // line above the infobar.
166 if (arrow_height_)
167 arrow_height_ += kSeparatorLineHeight;
169 bar_height_ = animation_.CurrentValueBetween(0, bar_target_height_);
171 // Don't re-layout if nothing has changed, e.g. because the animation step was
172 // not large enough to actually change the heights by at least a pixel.
173 bool heights_differ =
174 (old_arrow_height != arrow_height_) || (old_bar_height != bar_height_);
175 if (heights_differ)
176 PlatformSpecificOnHeightsRecalculated();
178 if (container_ && (heights_differ || force_notify))
179 container_->OnInfoBarStateChanged(animation_.is_animating());
182 void InfoBar::MaybeDelete() {
183 if (!owner_ && delegate_ && (animation_.GetCurrentValue() == 0.0)) {
184 if (container_)
185 container_->RemoveInfoBar(this);
186 delete delegate_;
187 delegate_ = NULL;
191 #endif // TOOLKIT_VIEWS || TOOLKIT_GTK