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

Side by Side Diff: chrome/browser/ui/views/sidebar/sidebar_base_tab.cc

Issue 6250141: Sidebar mini tabs UI (views version).... Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 10 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
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2010 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/ui/views/sidebar/sidebar_base_tab.h"
6
7 #include <limits>
8
9 #include "base/utf_string_conversions.h"
10 #include "chrome/browser/tab_contents/tab_contents.h"
11 #include "chrome/browser/ui/view_ids.h"
12 #include "chrome/browser/ui/views/sidebar/sidebar_tab_controller.h"
13 #include "gfx/canvas_skia.h"
14 #include "gfx/favicon_size.h"
15 #include "grit/app_resources.h"
16 #include "grit/generated_resources.h"
17 #include "grit/theme_resources.h"
18 #include "ui/base/animation/animation_container.h"
19 #include "ui/base/animation/linear_animation.h"
20 #include "ui/base/animation/slide_animation.h"
21 #include "ui/base/animation/throb_animation.h"
22 #include "ui/base/resource/resource_bundle.h"
23 #include "ui/base/theme_provider.h"
24
25 namespace {
26
27 // How long the pulse throb takes.
28 const int kPulseDurationMs = 200;
29
30 // How long the hover state takes.
31 const int kHoverDurationMs = 90;
32
33 // How opaque to make the hover state (out of 1).
34 const double kHoverOpacity = 0.33;
35
36 } // namespace
37
38 // A custom animation subclass to manage the icon crash animation.
39 class SidebarBaseTab::IconCrashAnimation : public ui::LinearAnimation,
40 public ui::AnimationDelegate {
41 public:
42 explicit IconCrashAnimation(SidebarBaseTab* target)
43 : ALLOW_THIS_IN_INITIALIZER_LIST(LinearAnimation(1000, 25, this)),
44 target_(target) {
45 }
46 virtual ~IconCrashAnimation() {}
47
48 // ui::AnimationDelegate overrides:
49 virtual void AnimateToState(double state) {
50 const double kHidingOffset = 27;
51
52 if (state < .5) {
53 target_->SetIconHidingOffset(
54 static_cast<int>(floor(kHidingOffset * 2.0 * state)));
55 } else {
56 target_->DisplayCrashedIcon();
57 target_->SetIconHidingOffset(
58 static_cast<int>(
59 floor(kHidingOffset - ((state - .5) * 2.0 * kHidingOffset))));
60 }
61 }
62
63 // ui::AnimationDelegate overrides:
64 virtual void AnimationCanceled(const ui::Animation* animation) {
65 target_->SetIconHidingOffset(0);
66 }
67
68 private:
69 SidebarBaseTab* const target_;
70
71 DISALLOW_COPY_AND_ASSIGN(IconCrashAnimation);
72 };
73
74 SidebarBaseTab::SidebarBaseTab(SidebarTabController* controller)
75 : controller_(controller),
76 closing_(false),
77 icon_hiding_offset_(0),
78 should_display_crashed_icon_(false),
79 loading_animation_frame_(0) {
80 DCHECK(controller_);
81
82 SetID(VIEW_ID_SIDEBAR_TAB);
83 }
84
85 SidebarBaseTab::~SidebarBaseTab() {
86 }
87
88 // views::View overrides.
89
90 void SidebarBaseTab::OnMouseEntered(const views::MouseEvent& e) {
91 if (!hover_animation_.get()) {
92 hover_animation_.reset(new ui::SlideAnimation(this));
93 hover_animation_->SetContainer(animation_container_.get());
94 hover_animation_->SetSlideDuration(kHoverDurationMs);
95 }
96 hover_animation_->SetTweenType(ui::Tween::EASE_OUT);
97 hover_animation_->Show();
98 }
99
100 void SidebarBaseTab::OnMouseExited(const views::MouseEvent& e) {
101 hover_animation_->SetTweenType(ui::Tween::EASE_IN);
102 hover_animation_->Hide();
103 }
104
105 bool SidebarBaseTab::OnMousePressed(const views::MouseEvent& event) {
106 if (event.IsOnlyLeftMouseButton())
107 controller_->SelectTab(this);
108 return true;
109 }
110
111 bool SidebarBaseTab::GetTooltipText(const gfx::Point& p,
112 std::wstring* tooltip) {
113 if (data_.title.empty())
114 return false;
115 *tooltip = UTF16ToWide(data_.title);
116 return true;
117 }
118
119 AccessibilityTypes::Role SidebarBaseTab::GetAccessibleRole() {
120 return AccessibilityTypes::ROLE_PAGETAB;
121 }
122
123 // SidebarBaseTab, public.
124
125 void SidebarBaseTab::SetData(const SidebarTabRendererData& data) {
126 SidebarTabRendererData old(data_);
127 data_ = data;
128
129 bool is_performing_crash_animation =
130 crash_animation_.get() && crash_animation_->is_animating();
131 if (data_.crashed) {
132 if (!should_display_crashed_icon_ && !is_performing_crash_animation)
133 StartCrashAnimation();
134 } else {
135 if (is_performing_crash_animation)
136 StopCrashAnimation();
137 ResetCrashedIcon();
138 }
139
140 // Sets the accessible name for the tab.
141 SetAccessibleName(data_.title);
142
143 DCHECK(data_.icon.isNull() ||
144 (data_.icon.width() == kFavIconSize &&
145 data_.icon.height() == kFavIconSize));
146
147 DataChanged(old);
148
149 Layout();
150 }
151
152 bool SidebarBaseTab::UpdateLoadingAnimation(
153 SidebarTabRendererData::NetworkState state) {
154 if (state == data_.network_state &&
155 state == SidebarTabRendererData::NETWORK_STATE_NONE) {
156 // If the network state is none and hasn't changed, do nothing. Otherwise
157 // we need to advance the animation frame.
158 return false;
159 }
160
161 SidebarTabRendererData::NetworkState old_state = data_.network_state;
162 data_.network_state = state;
163 AdvanceLoadingAnimation(old_state, state);
164 return true;
165 }
166
167 void SidebarBaseTab::StartPulse() {
168 if (!pulse_animation_.get()) {
169 pulse_animation_.reset(new ui::ThrobAnimation(this));
170 pulse_animation_->SetSlideDuration(kPulseDurationMs);
171 if (animation_container_.get())
172 pulse_animation_->SetContainer(animation_container_.get());
173 }
174 pulse_animation_->Reset();
175 pulse_animation_->StartThrobbing(std::numeric_limits<int>::max());
176 }
177
178 void SidebarBaseTab::StopPulse() {
179 if (!pulse_animation_.get())
180 return;
181
182 pulse_animation_->Stop(); // Do stop so we get notified.
183 pulse_animation_.reset(NULL);
184 }
185
186 bool SidebarBaseTab::IsSelected() const {
187 return controller_->IsTabSelected(this);
188 }
189
190 bool SidebarBaseTab::IsExpanded() const {
191 return controller_->IsSidebarExpanded();
192 }
193
194 // SidebarBaseTab, protected.
195
196 void SidebarBaseTab::AdvanceLoadingAnimation(
197 SidebarTabRendererData::NetworkState old_state,
198 SidebarTabRendererData::NetworkState state) {
199 static bool initialized = false;
200 static int loading_animation_frame_count = 0;
201 static int waiting_animation_frame_count = 0;
202 static int waiting_to_loading_frame_count_ratio = 0;
203 if (!initialized) {
204 initialized = true;
205 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
206 SkBitmap loading_animation(*rb.GetBitmapNamed(IDR_THROBBER));
207 loading_animation_frame_count =
208 loading_animation.width() / loading_animation.height();
209 SkBitmap waiting_animation(*rb.GetBitmapNamed(IDR_THROBBER_WAITING));
210 waiting_animation_frame_count =
211 waiting_animation.width() / waiting_animation.height();
212 waiting_to_loading_frame_count_ratio =
213 waiting_animation_frame_count / loading_animation_frame_count;
214 }
215
216 // The waiting animation is the reverse of the loading animation, but at a
217 // different rate - the following reverses and scales the animation_frame_
218 // so that the frame is at an equivalent position when going from one
219 // animation to the other.
220 if (state != old_state) {
221 loading_animation_frame_ = loading_animation_frame_count -
222 (loading_animation_frame_ / waiting_to_loading_frame_count_ratio);
223 }
224
225 if (state != SidebarTabRendererData::NETWORK_STATE_NONE) {
226 loading_animation_frame_ = (loading_animation_frame_ + 1) %
227 ((state == SidebarTabRendererData::NETWORK_STATE_WAITING) ?
228 waiting_animation_frame_count : loading_animation_frame_count);
229 } else {
230 loading_animation_frame_ = 0;
231 }
232 SchedulePaint();
233 }
234
235 double SidebarBaseTab::GetThrobValue() {
236 if (pulse_animation_.get() && pulse_animation_->is_animating())
237 return pulse_animation_->GetCurrentValue() * kHoverOpacity;
238
239 return hover_animation_.get() ?
240 kHoverOpacity * hover_animation_->GetCurrentValue() : 0;
241 }
242
243 void SidebarBaseTab::PaintIcon(gfx::Canvas* canvas, int x, int y, int alpha) {
244 SkPaint paint;
245 paint.setAlpha(alpha);
246 if (data().network_state != SidebarTabRendererData::NETWORK_STATE_NONE) {
247 ThemeProvider* tp = GetThemeProvider();
248 SkBitmap frames(*tp->GetBitmapNamed(
249 data().network_state == SidebarTabRendererData::NETWORK_STATE_WAITING ?
250 IDR_THROBBER_WAITING : IDR_THROBBER));
251 int image_size = frames.height();
252 int image_offset = loading_animation_frame_ * image_size;
253 int dst_y = (height() - image_size) / 2;
254 canvas->DrawBitmapInt(frames, image_offset, 0, image_size,
255 image_size, x, dst_y, image_size, image_size,
256 false, paint);
257 } else {
258 canvas->Save();
259 canvas->ClipRectInt(0, 0, width(), height());
260 if (should_display_crashed_icon_) {
261 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
262 SkBitmap crashed_icon(*rb.GetBitmapNamed(IDR_SAD_FAVICON));
263 canvas->DrawBitmapInt(crashed_icon, 0, 0, crashed_icon.width(),
264 crashed_icon.height(), x,
265 (height() - crashed_icon.height()) / 2 + icon_hiding_offset_,
266 kFavIconSize, kFavIconSize, true, paint);
267 } else {
268 if (!data().icon.isNull()) {
269 int size = data().icon.width();
270 canvas->DrawBitmapInt(data().icon, 0, 0,
271 data().icon.width(),
272 data().icon.height(),
273 x, y + icon_hiding_offset_, size, size,
274 true, paint);
275 }
276 }
277 canvas->Restore();
278 }
279 }
280
281 // ui::AnimationDelegate overrides.
282
283 void SidebarBaseTab::AnimationProgressed(const ui::Animation* animation) {
284 SchedulePaint();
285 }
286
287 void SidebarBaseTab::AnimationCanceled(const ui::Animation* animation) {
288 SchedulePaint();
289 }
290
291 void SidebarBaseTab::AnimationEnded(const ui::Animation* animation) {
292 SchedulePaint();
293 }
294
295 // SidebarBaseTab, private.
296
297 void SidebarBaseTab::SetIconHidingOffset(int offset) {
298 icon_hiding_offset_ = offset;
299 SchedulePaint();
300 }
301
302 void SidebarBaseTab::DisplayCrashedIcon() {
303 should_display_crashed_icon_ = true;
304 }
305
306 void SidebarBaseTab::ResetCrashedIcon() {
307 should_display_crashed_icon_ = false;
308 }
309
310 void SidebarBaseTab::StartCrashAnimation() {
311 if (!crash_animation_.get())
312 crash_animation_.reset(new IconCrashAnimation(this));
313 crash_animation_->Stop();
314 crash_animation_->Start();
315 }
316
317 void SidebarBaseTab::StopCrashAnimation() {
318 if (crash_animation_.get())
319 crash_animation_->Stop();
320 }
321
OLDNEW
« no previous file with comments | « chrome/browser/ui/views/sidebar/sidebar_base_tab.h ('k') | chrome/browser/ui/views/sidebar/sidebar_base_tab_strip.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698