Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: chrome/browser/ui/search/toolbar_search_animator.cc

Issue 10816027: alternate ntp: toolbar background and separator animation (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: update comments Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/browser/ui/search/toolbar_search_animator.h" 5 #include "chrome/browser/ui/search/toolbar_search_animator.h"
6 6
7 #include "chrome/browser/ui/search/search_model.h" 7 #include "chrome/browser/ui/search/search_model.h"
8 #include "chrome/browser/ui/search/search_types.h" 8 #include "chrome/browser/ui/search/search_types.h"
9 #include "chrome/browser/ui/search/toolbar_search_animator_observer.h" 9 #include "chrome/browser/ui/search/toolbar_search_animator_observer.h"
10 #include "chrome/browser/ui/tab_contents/tab_contents.h" 10 #include "chrome/browser/ui/tab_contents/tab_contents.h"
11 #include "chrome/browser/ui/webui/instant_ui.h" 11 #include "chrome/browser/ui/webui/instant_ui.h"
12 #include "ui/base/animation/multi_animation.h"
12 #include "ui/base/animation/slide_animation.h" 13 #include "ui/base/animation/slide_animation.h"
13 14
14 namespace { 15 namespace {
15 16
16 const int kBackgroundChangeDelayMs = 100; 17 const int kBackgroundChangeDelayMs = 100;
17 const int kBackgroundChangeDurationMs = 200; 18 const int kBackgroundChangeDurationMs = 200;
18 19
20 const int kSeparatorFadeDurationMs = 100;
21
19 const double kMinOpacity = 0.0f; 22 const double kMinOpacity = 0.0f;
20 const double kMaxOpacity = 1.0f; 23 const double kMaxOpacity = 1.0f;
21 24
22 } // namespace 25 } // namespace
23 26
24 namespace chrome { 27 namespace chrome {
25 namespace search { 28 namespace search {
26 29
27 ToolbarSearchAnimator::ToolbarSearchAnimator(SearchModel* search_model) 30 ToolbarSearchAnimator::ToolbarSearchAnimator(SearchModel* search_model)
28 : search_model_(search_model), 31 : search_model_(search_model) {
29 animate_state_(ANIMATE_STATE_NONE) {
30 search_model_->AddObserver(this); 32 search_model_->AddObserver(this);
33
34 ui::MultiAnimation::Parts parts;
35 parts.push_back(ui::MultiAnimation::Part(
36 kBackgroundChangeDelayMs * InstantUI::GetSlowAnimationScaleFactor(),
37 ui::Tween::ZERO));
38 parts.push_back(ui::MultiAnimation::Part(
39 kBackgroundChangeDurationMs * InstantUI::GetSlowAnimationScaleFactor(),
40 ui::Tween::LINEAR));
41 background_animation_.reset(new ui::MultiAnimation(parts));
42 background_animation_->set_continuous(false);
43
44 separator_animation_.reset(new ui::SlideAnimation(this));
45 separator_animation_->SetTweenType(ui::Tween::LINEAR);
46 separator_animation_->SetSlideDuration(
47 kSeparatorFadeDurationMs * InstantUI::GetSlowAnimationScaleFactor());
31 } 48 }
32 49
33 ToolbarSearchAnimator::~ToolbarSearchAnimator() { 50 ToolbarSearchAnimator::~ToolbarSearchAnimator() {
51 background_animation_->Stop();
52 separator_animation_->Stop();
34 search_model_->RemoveObserver(this); 53 search_model_->RemoveObserver(this);
35 } 54 }
36 55
37 void ToolbarSearchAnimator::GetCurrentBackgroundState( 56 double ToolbarSearchAnimator::GetGradientOpacity() const {
38 BackgroundState* background_state, 57 if (background_animation_->is_animating())
39 double* search_background_opacity) const { 58 return background_animation_->CurrentValueBetween(kMinOpacity, kMaxOpacity);
40 // Should only be called for SEARCH mode. 59 return search_model_->mode().is_ntp() ? kMinOpacity : kMaxOpacity;
41 DCHECK(search_model_->mode().is_search()); 60 }
42 *background_state = BACKGROUND_STATE_DEFAULT; 61
43 *search_background_opacity = -1.0f; 62 double ToolbarSearchAnimator::GetSeparatorOpacity() const {
44 switch (animate_state_) { 63 if (separator_animation_->is_animating())
45 case ANIMATE_STATE_WAITING: 64 return separator_animation_->CurrentValueBetween(kMinOpacity, kMaxOpacity);
46 *background_state = BACKGROUND_STATE_NTP; 65 return search_model_->mode().is_default() ? kMaxOpacity : kMinOpacity;
47 break;
48 case ANIMATE_STATE_RUNNING:
49 *background_state = BACKGROUND_STATE_NTP_SEARCH;
50 *search_background_opacity = background_animation_->CurrentValueBetween(
51 kMinOpacity, kMaxOpacity);
52 break;
53 case ANIMATE_STATE_NONE:
54 break;
55 }
56 } 66 }
57 67
58 void ToolbarSearchAnimator::FinishAnimation(TabContents* tab_contents) { 68 void ToolbarSearchAnimator::FinishAnimation(TabContents* tab_contents) {
59 Reset(tab_contents); 69 Reset(tab_contents);
60 } 70 }
61 71
62 void ToolbarSearchAnimator::AddObserver( 72 void ToolbarSearchAnimator::AddObserver(
63 ToolbarSearchAnimatorObserver* observer) { 73 ToolbarSearchAnimatorObserver* observer) {
64 observers_.AddObserver(observer); 74 observers_.AddObserver(observer);
65 } 75 }
66 76
67 void ToolbarSearchAnimator::RemoveObserver( 77 void ToolbarSearchAnimator::RemoveObserver(
68 ToolbarSearchAnimatorObserver* observer) { 78 ToolbarSearchAnimatorObserver* observer) {
69 observers_.RemoveObserver(observer); 79 observers_.RemoveObserver(observer);
70 } 80 }
71 81
72 void ToolbarSearchAnimator::ModeChanged(const Mode& mode) { 82 void ToolbarSearchAnimator::ModeChanged(const Mode& old_mode,
73 int delay_ms = kBackgroundChangeDelayMs * 83 const Mode& new_mode) {
74 InstantUI::GetSlowAnimationScaleFactor(); 84 // If mode transitions from |NTP| to |SEARCH| and we're not animating
dhollowa 2012/08/01 22:26:23 "If the mode"...
kuan 2012/08/02 21:54:03 Done.
75 if (mode.is_search() && mode.animate && 85 // background, start fading in gradient background.
76 animate_state_ == ANIMATE_STATE_NONE) { 86 // TODO(kuan): check with UX folks if we need to animate from gradient to flat
77 background_change_timer_.Start( 87 // when mode transitions from |SEARCH| or |DEFAULT| to |NTP|.
78 FROM_HERE, 88 if (new_mode.animate && old_mode.is_ntp() && new_mode.is_search() &&
79 base::TimeDelta::FromMilliseconds(delay_ms), 89 !background_animation_->is_animating()) {
80 this, 90 StartBackgroundChange();
81 &ToolbarSearchAnimator::StartBackgroundChange);
82 animate_state_ = ANIMATE_STATE_WAITING;
83 return; 91 return;
84 } 92 }
85 // For all other cases, reset |animate_state_| and stop timer or animation. 93
94 // If mode transitions from non-|DEFAULT| to |DEFAULT|, fade in separator;
95 // if we're already fading out separator, reverse to fade it in.
96 // Note that if we're still fading in gradient background when this mode
97 // transition happens (e.g. when user quickly hits enter on the auto-completed
98 // query in omnibox, triggering mode to transition from |SEARCH| to
99 // |DEFAULT|), we should continue fading in the gradient background to its
100 // full course.
101 // TODO(kuan): however, for now, sometimes, the first auto-completed query in
102 // omnibox is pre-rendered and gets swapped in when chosen by user, causing
103 // OnTabDetached for original tab to be fired, and hence causing us to Reset,
104 // immediately jumping to end state of background animation. I'll look into
105 // this together with the above TODO for reverse background animation.
106 if (new_mode.animate && (new_mode.is_default() ||
107 (separator_animation_->is_animating() &&
108 separator_animation_->IsClosing()))) {
109 StartSeparatorFade(true);
110 return;
111 }
112
113 // If mode transitions from |DEFAULT| to non-|DEFAULT|, fade out separator;
114 // if we're already fading in separator, reverse to fade it out.
115 // TODO(kuan): for now, if we're still fading in gradient background when this
116 // mode transition happens (e.g. when user quickly hits back button on a
117 // website that he/she just entered from a |SEARCH| mode, triggering mode to
118 // transition from |DEFAULT| to |NTP|), we'll continue fading in the gradient
119 // background to its full course, which is undesirable. I'll handle this
120 // together with the above TODO for reverse background animation.
121 if (new_mode.animate && (old_mode.is_default() ||
122 (separator_animation_->is_animating() &&
123 separator_animation_->IsShowing()))) {
124 StartSeparatorFade(false);
125 return;
126 }
127
128 // For all other cases, reset animate states and stop animation(s).
86 // Stopping animation will jump to the end of it. 129 // Stopping animation will jump to the end of it.
87 Reset(NULL); 130 Reset(NULL);
88 } 131 }
89 132
90 void ToolbarSearchAnimator::AnimationProgressed( 133 void ToolbarSearchAnimator::AnimationProgressed(
91 const ui::Animation* animation) { 134 const ui::Animation* animation) {
92 DCHECK_EQ(animation, background_animation_.get()); 135 if (animation == background_animation_.get()) {
93 animate_state_ = ANIMATE_STATE_RUNNING; 136 FOR_EACH_OBSERVER(ToolbarSearchAnimatorObserver, observers_,
94 FOR_EACH_OBSERVER(ToolbarSearchAnimatorObserver, observers_, 137 OnToolbarBackgroundAnimatorProgressed());
95 OnToolbarBackgroundAnimatorProgressed()); 138 return;
139 }
140
141 if (animation == separator_animation_.get()) {
142 FOR_EACH_OBSERVER(ToolbarSearchAnimatorObserver, observers_,
143 OnToolbarSeparatorAnimatorProgressed());
144 }
96 } 145 }
97 146
98 void ToolbarSearchAnimator::AnimationEnded(const ui::Animation* animation) { 147 void ToolbarSearchAnimator::AnimationEnded(const ui::Animation* animation) {
99 DCHECK_EQ(animation, background_animation_.get()); 148 // We only get this callback when |animation| has run its full course.
100 // Only notify observers via OnToolbarBackgroundAnimatorProgressed if the 149 // If animation was canceled (in Reset()), we won't get an AnimationEnded()
101 // animation has runs its full course i.e |animate_state_| is still 150 // callback because we had cleared the animation's delegate in Reset().
102 // ANIMATE_STATE_RUNNING. 151 if (animation == background_animation_.get()) {
103 // Animation that is canceled, i.e. |animate_state_| has been set to
104 // ANIMATE_STATE_NONE in Reset, should notify observers via
105 // OnToolbarBackgroundAnimatorCanceled.
106 if (animate_state_ == ANIMATE_STATE_RUNNING) {
107 animate_state_ = ANIMATE_STATE_NONE;
108 FOR_EACH_OBSERVER(ToolbarSearchAnimatorObserver, observers_, 152 FOR_EACH_OBSERVER(ToolbarSearchAnimatorObserver, observers_,
109 OnToolbarBackgroundAnimatorProgressed()); 153 OnToolbarBackgroundAnimatorProgressed());
154 return;
155 }
156
157 if (animation == separator_animation_.get()) {
158 FOR_EACH_OBSERVER(ToolbarSearchAnimatorObserver, observers_,
159 OnToolbarSeparatorAnimatorProgressed());
110 } 160 }
111 } 161 }
112 162
113 void ToolbarSearchAnimator::StartBackgroundChange() { 163 void ToolbarSearchAnimator::StartBackgroundChange() {
114 if (!background_animation_.get()) { 164 background_animation_->set_delegate(this);
115 background_animation_.reset(new ui::SlideAnimation(this)); 165 background_animation_->Start();
116 background_animation_->SetTweenType(ui::Tween::LINEAR); 166 }
117 background_animation_->SetSlideDuration( 167
118 kBackgroundChangeDurationMs * InstantUI::GetSlowAnimationScaleFactor()); 168 void ToolbarSearchAnimator::StartSeparatorFade(bool show) {
169 if (!separator_animation_->is_animating()) {
170 separator_animation_->set_delegate(this);
171 separator_animation_->Reset(show ? 0.0 : 1.0);
119 } 172 }
120 background_animation_->Reset(0.0); 173 if (show)
121 background_animation_->Show(); 174 separator_animation_->Show();
175 else
176 separator_animation_->Hide();
122 } 177 }
123 178
124 void ToolbarSearchAnimator::Reset(TabContents* tab_contents) { 179 void ToolbarSearchAnimator::Reset(TabContents* tab_contents) {
125 bool notify_observers = animate_state_ != ANIMATE_STATE_NONE; 180 bool notify_background_observers = background_animation_->is_animating();
126 animate_state_ = ANIMATE_STATE_NONE; 181 bool notify_separator_observers = separator_animation_->is_animating();
127 background_change_timer_.Stop(); 182
128 // If animation is still running, stopping it will trigger AnimationEnded 183 // Clear the animations' delegates so that we don't get AnimationEnded()
129 // where we've prevented from notifying observers via BackgroundChanged; 184 // callbacks.
130 // see comments in AnimationEnded. 185 background_animation_->set_delegate(NULL);
131 if (background_animation_.get()) 186 separator_animation_->set_delegate(NULL);
132 background_animation_->Stop(); 187 background_animation_->Stop();
133 if (notify_observers) { 188 separator_animation_->Stop();
189
190 // Notify observers of animation(s) cancelation.
191 if (notify_background_observers) {
134 FOR_EACH_OBSERVER(ToolbarSearchAnimatorObserver, observers_, 192 FOR_EACH_OBSERVER(ToolbarSearchAnimatorObserver, observers_,
135 OnToolbarBackgroundAnimatorCanceled(tab_contents)); 193 OnToolbarBackgroundAnimatorCanceled(tab_contents));
136 } 194 }
195 if (notify_separator_observers) {
196 FOR_EACH_OBSERVER(ToolbarSearchAnimatorObserver, observers_,
197 OnToolbarSeparatorAnimatorCanceled());
198 }
137 } 199 }
138 200
139 } // namespace search 201 } // namespace search
140 } // namespace chrome 202 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698