Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / infobars / infobar.cc
blob072a009dc578ef0261cd08e9d0c7f0c81c6967c0
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/gfx/animation/slide_animation.h"
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);
30 InfoBar::~InfoBar() {
31 DCHECK(!owner_);
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;
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;
54 void InfoBar::SetOwner(InfoBarService* owner) {
55 DCHECK(!owner_);
56 owner_ = owner;
57 delegate_->StoreActiveEntryUniqueID();
58 PlatformSpecificSetOwner();
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);
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.
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);
95 void InfoBar::CloseSoon() {
96 owner_ = NULL;
97 PlatformSpecificOnCloseSoon();
98 MaybeDelete();
101 void InfoBar::RemoveSelf() {
102 if (owner_)
103 owner_->RemoveInfoBar(this);
106 void InfoBar::SetBarTargetHeight(int height) {
107 if (bar_target_height_ != height) {
108 bar_target_height_ = height;
109 RecalculateHeights(false);
113 void InfoBar::AnimationProgressed(const gfx::Animation* animation) {
114 RecalculateHeights(false);
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();
126 void InfoBar::RecalculateHeights(bool force_notify) {
127 int old_arrow_height = arrow_height_;
128 int old_bar_height = bar_height_;
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)));
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;
156 bar_height_ = animation_.CurrentValueBetween(0, bar_target_height_);
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();
165 if (container_ && (heights_differ || force_notify))
166 container_->OnInfoBarStateChanged(animation_.is_animating());
169 void InfoBar::MaybeDelete() {
170 if (!owner_ && (animation_.GetCurrentValue() == 0.0)) {
171 if (container_)
172 container_->RemoveInfoBar(this);
173 delete this;