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.
5 #include "components/infobars/core/infobar.h"
9 #include "base/logging.h"
10 #include "build/build_config.h"
11 #include "components/infobars/core/infobar_container.h"
12 #include "components/infobars/core/infobar_manager.h"
13 #include "ui/gfx/animation/slide_animation.h"
17 InfoBar::InfoBar(scoped_ptr
<InfoBarDelegate
> delegate
)
19 delegate_(delegate
.Pass()),
23 arrow_target_height_(kDefaultArrowTargetHeight
),
26 bar_target_height_(kDefaultBarTargetHeight
) {
27 DCHECK(delegate_
!= NULL
);
28 animation_
.SetTweenType(gfx::Tween::LINEAR
);
29 delegate_
->set_infobar(this);
37 SkColor
InfoBar::GetTopColor(InfoBarDelegate::Type infobar_type
) {
38 static const SkColor kWarningBackgroundColorTop
=
39 SkColorSetRGB(255, 242, 183); // Yellow
40 static const SkColor kPageActionBackgroundColorTop
=
41 SkColorSetRGB(237, 237, 237); // Gray
42 return (infobar_type
== InfoBarDelegate::WARNING_TYPE
) ?
43 kWarningBackgroundColorTop
: kPageActionBackgroundColorTop
;
47 SkColor
InfoBar::GetBottomColor(InfoBarDelegate::Type infobar_type
) {
48 static const SkColor kWarningBackgroundColorBottom
=
49 SkColorSetRGB(250, 230, 145); // Yellow
50 static const SkColor kPageActionBackgroundColorBottom
=
51 SkColorSetRGB(217, 217, 217); // Gray
52 return (infobar_type
== InfoBarDelegate::WARNING_TYPE
) ?
53 kWarningBackgroundColorBottom
: kPageActionBackgroundColorBottom
;
56 void InfoBar::SetOwner(InfoBarManager
* owner
) {
59 delegate_
->StoreActiveEntryUniqueID();
60 PlatformSpecificSetOwner();
63 void InfoBar::Show(bool animate
) {
64 PlatformSpecificShow(animate
);
68 animation_
.Reset(1.0);
69 RecalculateHeights(true);
73 void InfoBar::Hide(bool animate
) {
74 PlatformSpecificHide(animate
);
78 animation_
.Reset(0.0);
79 // We want to remove ourselves from the container immediately even if we
80 // still have an owner, which MaybeDelete() won't do.
82 container_
->RemoveInfoBar(this);
83 MaybeDelete(); // Necessary if the infobar was already closing.
87 void InfoBar::SetArrowTargetHeight(int height
) {
88 DCHECK_LE(height
, kMaximumArrowTargetHeight
);
89 // Once the closing animation starts, we ignore further requests to change the
91 if ((arrow_target_height_
!= height
) && !animation_
.IsClosing()) {
92 arrow_target_height_
= height
;
93 RecalculateHeights(false);
97 void InfoBar::CloseSoon() {
99 PlatformSpecificOnCloseSoon();
103 void InfoBar::RemoveSelf() {
105 owner_
->RemoveInfoBar(this);
108 void InfoBar::SetBarTargetHeight(int height
) {
109 if (bar_target_height_
!= height
) {
110 bar_target_height_
= height
;
111 RecalculateHeights(false);
115 void InfoBar::AnimationProgressed(const gfx::Animation
* animation
) {
116 RecalculateHeights(false);
119 void InfoBar::AnimationEnded(const gfx::Animation
* animation
) {
120 // 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"
122 // 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.)
124 RecalculateHeights(true);
128 void InfoBar::RecalculateHeights(bool force_notify
) {
129 int old_arrow_height
= arrow_height_
;
130 int old_bar_height
= bar_height_
;
132 // Find the desired arrow height/half-width. The arrow area is
133 // |arrow_height_| * |arrow_half_width_|. When the bar is opening or closing,
134 // scaling each of these with the square root of the animation value causes a
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
);
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
)));
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.
156 arrow_height_
+= kSeparatorLineHeight
;
158 bar_height_
= animation_
.CurrentValueBetween(0, bar_target_height_
);
160 // 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.
162 bool heights_differ
=
163 (old_arrow_height
!= arrow_height_
) || (old_bar_height
!= bar_height_
);
165 PlatformSpecificOnHeightsRecalculated();
167 if (container_
&& (heights_differ
|| force_notify
))
168 container_
->OnInfoBarStateChanged(animation_
.is_animating());
171 void InfoBar::MaybeDelete() {
172 if (!owner_
&& (animation_
.GetCurrentValue() == 0.0)) {
174 container_
->RemoveInfoBar(this);
179 } // namespace infobars