OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 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 | 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/views/tabs/base_tab.h" | 5 #include "chrome/browser/views/tabs/base_tab.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "app/animation_container.h" | 9 #include "app/animation_container.h" |
10 #include "app/l10n_util.h" | 10 #include "app/l10n_util.h" |
11 #include "app/resource_bundle.h" | 11 #include "app/resource_bundle.h" |
12 #include "app/slide_animation.h" | 12 #include "app/slide_animation.h" |
| 13 #include "app/theme_provider.h" |
13 #include "app/throb_animation.h" | 14 #include "app/throb_animation.h" |
14 #include "base/command_line.h" | 15 #include "base/command_line.h" |
15 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
16 #include "chrome/browser/browser.h" | 17 #include "chrome/browser/browser.h" |
17 #include "chrome/browser/tab_contents/tab_contents.h" | 18 #include "chrome/browser/tab_contents/tab_contents.h" |
18 #include "chrome/browser/views/tabs/tab_controller.h" | 19 #include "chrome/browser/views/tabs/tab_controller.h" |
19 #include "chrome/browser/view_ids.h" | 20 #include "chrome/browser/view_ids.h" |
20 #include "chrome/common/chrome_switches.h" | 21 #include "chrome/common/chrome_switches.h" |
21 #include "gfx/canvas_skia.h" | 22 #include "gfx/canvas_skia.h" |
22 #include "gfx/favicon_size.h" | 23 #include "gfx/favicon_size.h" |
23 #include "gfx/font.h" | 24 #include "gfx/font.h" |
24 #include "grit/app_resources.h" | 25 #include "grit/app_resources.h" |
25 #include "grit/generated_resources.h" | 26 #include "grit/generated_resources.h" |
26 #include "grit/theme_resources.h" | 27 #include "grit/theme_resources.h" |
27 #include "views/controls/button/image_button.h" | 28 #include "views/controls/button/image_button.h" |
28 | 29 |
29 #ifdef WIN32 | 30 #ifdef WIN32 |
30 #include "app/win_util.h" | 31 #include "app/win_util.h" |
31 #endif | 32 #endif |
32 | 33 |
33 // How long the pulse throb takes. | 34 // How long the pulse throb takes. |
34 static const int kPulseDurationMs = 200; | 35 static const int kPulseDurationMs = 200; |
35 | 36 |
36 // How long the hover state takes. | 37 // How long the hover state takes. |
37 static const int kHoverDurationMs = 90; | 38 static const int kHoverDurationMs = 90; |
38 | 39 |
39 static SkBitmap* waiting_animation_frames = NULL; | |
40 static SkBitmap* loading_animation_frames = NULL; | |
41 static int loading_animation_frame_count = 0; | |
42 static int waiting_animation_frame_count = 0; | |
43 static int waiting_to_loading_frame_count_ratio = 0; | |
44 | |
45 // Close button images. | |
46 static SkBitmap* close_button_n = NULL; | |
47 static SkBitmap* close_button_h = NULL; | |
48 static SkBitmap* close_button_p = NULL; | |
49 | |
50 static SkBitmap* crashed_fav_icon = NULL; | |
51 | |
52 namespace { | 40 namespace { |
53 | 41 |
54 //////////////////////////////////////////////////////////////////////////////// | 42 //////////////////////////////////////////////////////////////////////////////// |
55 // TabCloseButton | 43 // TabCloseButton |
56 // | 44 // |
57 // This is a Button subclass that causes middle clicks to be forwarded to the | 45 // This is a Button subclass that causes middle clicks to be forwarded to the |
58 // parent View by explicitly not handling them in OnMousePressed. | 46 // parent View by explicitly not handling them in OnMousePressed. |
59 class TabCloseButton : public views::ImageButton { | 47 class TabCloseButton : public views::ImageButton { |
60 public: | 48 public: |
61 explicit TabCloseButton(views::ButtonListener* listener) | 49 explicit TabCloseButton(views::ButtonListener* listener) |
(...skipping 21 matching lines...) Expand all Loading... |
83 GetParent()->OnMouseExited(event); | 71 GetParent()->OnMouseExited(event); |
84 } | 72 } |
85 | 73 |
86 private: | 74 private: |
87 DISALLOW_COPY_AND_ASSIGN(TabCloseButton); | 75 DISALLOW_COPY_AND_ASSIGN(TabCloseButton); |
88 }; | 76 }; |
89 | 77 |
90 } // namespace | 78 } // namespace |
91 | 79 |
92 // static | 80 // static |
93 int BaseTab::close_button_width_ = 0; | |
94 // static | |
95 int BaseTab::close_button_height_ = 0; | |
96 // static | |
97 int BaseTab::loading_animation_size_ = 0; | |
98 | |
99 // static | |
100 gfx::Font* BaseTab::font_ = NULL; | 81 gfx::Font* BaseTab::font_ = NULL; |
101 // static | 82 // static |
102 int BaseTab::font_height_ = 0; | 83 int BaseTab::font_height_ = 0; |
103 | 84 |
104 //////////////////////////////////////////////////////////////////////////////// | 85 //////////////////////////////////////////////////////////////////////////////// |
105 // FaviconCrashAnimation | 86 // FaviconCrashAnimation |
106 // | 87 // |
107 // A custom animation subclass to manage the favicon crash animation. | 88 // A custom animation subclass to manage the favicon crash animation. |
108 class BaseTab::FavIconCrashAnimation : public LinearAnimation, | 89 class BaseTab::FavIconCrashAnimation : public LinearAnimation, |
109 public AnimationDelegate { | 90 public AnimationDelegate { |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 loading_animation_frame_(0), | 128 loading_animation_frame_(0), |
148 throbber_disabled_(false), | 129 throbber_disabled_(false), |
149 theme_provider_(NULL), | 130 theme_provider_(NULL), |
150 fav_icon_hiding_offset_(0), | 131 fav_icon_hiding_offset_(0), |
151 should_display_crashed_favicon_(false) { | 132 should_display_crashed_favicon_(false) { |
152 BaseTab::InitResources(); | 133 BaseTab::InitResources(); |
153 | 134 |
154 SetID(VIEW_ID_TAB); | 135 SetID(VIEW_ID_TAB); |
155 | 136 |
156 // Add the Close Button. | 137 // Add the Close Button. |
157 TabCloseButton* close_button = new TabCloseButton(this); | 138 close_button_ = new TabCloseButton(this); |
158 close_button_ = close_button; | 139 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
159 close_button->SetImage(views::CustomButton::BS_NORMAL, close_button_n); | 140 close_button_->SetImage(views::CustomButton::BS_NORMAL, |
160 close_button->SetImage(views::CustomButton::BS_HOT, close_button_h); | 141 rb.GetBitmapNamed(IDR_TAB_CLOSE)); |
161 close_button->SetImage(views::CustomButton::BS_PUSHED, close_button_p); | 142 close_button_->SetImage(views::CustomButton::BS_HOT, |
162 close_button->SetTooltipText(l10n_util::GetString(IDS_TOOLTIP_CLOSE_TAB)); | 143 rb.GetBitmapNamed(IDR_TAB_CLOSE_H)); |
163 close_button->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_CLOSE)); | 144 close_button_->SetImage(views::CustomButton::BS_PUSHED, |
| 145 rb.GetBitmapNamed(IDR_TAB_CLOSE_P)); |
| 146 close_button_->SetTooltipText(l10n_util::GetString(IDS_TOOLTIP_CLOSE_TAB)); |
| 147 close_button_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_CLOSE)); |
164 // Disable animation so that the red danger sign shows up immediately | 148 // Disable animation so that the red danger sign shows up immediately |
165 // to help avoid mis-clicks. | 149 // to help avoid mis-clicks. |
166 close_button->SetAnimationDuration(0); | 150 close_button_->SetAnimationDuration(0); |
167 AddChildView(close_button); | 151 AddChildView(close_button_); |
168 | 152 |
169 SetContextMenuController(this); | 153 SetContextMenuController(this); |
170 } | 154 } |
171 | 155 |
172 BaseTab::~BaseTab() { | 156 BaseTab::~BaseTab() { |
173 } | 157 } |
174 | 158 |
175 void BaseTab::SetData(const TabRendererData& data) { | 159 void BaseTab::SetData(const TabRendererData& data) { |
176 TabRendererData old(data_); | 160 TabRendererData old(data_); |
177 data_ = data; | 161 data_ = data; |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
328 return true; | 312 return true; |
329 } | 313 } |
330 | 314 |
331 ThemeProvider* BaseTab::GetThemeProvider() { | 315 ThemeProvider* BaseTab::GetThemeProvider() { |
332 ThemeProvider* tp = View::GetThemeProvider(); | 316 ThemeProvider* tp = View::GetThemeProvider(); |
333 return tp ? tp : theme_provider_; | 317 return tp ? tp : theme_provider_; |
334 } | 318 } |
335 | 319 |
336 void BaseTab::AdvanceLoadingAnimation(TabRendererData::NetworkState old_state, | 320 void BaseTab::AdvanceLoadingAnimation(TabRendererData::NetworkState old_state, |
337 TabRendererData::NetworkState state) { | 321 TabRendererData::NetworkState state) { |
| 322 static bool initialized = false; |
| 323 static int loading_animation_frame_count = 0, |
| 324 waiting_animation_frame_count = 0, |
| 325 waiting_to_loading_frame_count_ratio = 0; |
| 326 if (!initialized) { |
| 327 initialized = true; |
| 328 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
| 329 SkBitmap loading_animation(*rb.GetBitmapNamed(IDR_THROBBER)); |
| 330 loading_animation_frame_count = |
| 331 loading_animation.width() / loading_animation.height(); |
| 332 SkBitmap waiting_animation(*rb.GetBitmapNamed(IDR_THROBBER_WAITING)); |
| 333 waiting_animation_frame_count = |
| 334 waiting_animation.width() / waiting_animation.height(); |
| 335 waiting_to_loading_frame_count_ratio = |
| 336 waiting_animation_frame_count / loading_animation_frame_count; |
| 337 } |
| 338 |
338 // The waiting animation is the reverse of the loading animation, but at a | 339 // The waiting animation is the reverse of the loading animation, but at a |
339 // different rate - the following reverses and scales the animation_frame_ | 340 // different rate - the following reverses and scales the animation_frame_ |
340 // so that the frame is at an equivalent position when going from one | 341 // so that the frame is at an equivalent position when going from one |
341 // animation to the other. | 342 // animation to the other. |
342 if (state != old_state) { | 343 if (state != old_state) { |
343 loading_animation_frame_ = loading_animation_frame_count - | 344 loading_animation_frame_ = loading_animation_frame_count - |
344 (loading_animation_frame_ / waiting_to_loading_frame_count_ratio); | 345 (loading_animation_frame_ / waiting_to_loading_frame_count_ratio); |
345 } | 346 } |
346 | 347 |
347 if (state != TabRendererData::NETWORK_STATE_NONE) { | 348 if (state != TabRendererData::NETWORK_STATE_NONE) { |
(...skipping 12 matching lines...) Expand all Loading... |
360 x = width() - x - data().favicon.width(); | 361 x = width() - x - data().favicon.width(); |
361 else | 362 else |
362 x = width() - x - kFavIconSize; | 363 x = width() - x - kFavIconSize; |
363 } | 364 } |
364 | 365 |
365 int favicon_x = x; | 366 int favicon_x = x; |
366 if (!data().favicon.isNull() && data().favicon.width() != kFavIconSize) | 367 if (!data().favicon.isNull() && data().favicon.width() != kFavIconSize) |
367 favicon_x += (data().favicon.width() - kFavIconSize) / 2; | 368 favicon_x += (data().favicon.width() - kFavIconSize) / 2; |
368 | 369 |
369 if (data().network_state != TabRendererData::NETWORK_STATE_NONE) { | 370 if (data().network_state != TabRendererData::NETWORK_STATE_NONE) { |
370 SkBitmap* frames = | 371 ThemeProvider* tp = GetThemeProvider(); |
| 372 SkBitmap frames(*tp->GetBitmapNamed( |
371 (data().network_state == TabRendererData::NETWORK_STATE_WAITING) ? | 373 (data().network_state == TabRendererData::NETWORK_STATE_WAITING) ? |
372 waiting_animation_frames : loading_animation_frames; | 374 IDR_THROBBER_WAITING : IDR_THROBBER)); |
373 int image_size = frames->height(); | 375 int image_size = frames.height(); |
374 int image_offset = loading_animation_frame_ * image_size; | 376 int image_offset = loading_animation_frame_ * image_size; |
375 int dst_y = (height() - image_size) / 2; | 377 int dst_y = (height() - image_size) / 2; |
376 canvas->DrawBitmapInt(*frames, image_offset, 0, image_size, | 378 canvas->DrawBitmapInt(frames, image_offset, 0, image_size, |
377 image_size, favicon_x, dst_y, image_size, image_size, | 379 image_size, favicon_x, dst_y, image_size, image_size, |
378 false); | 380 false); |
379 } else { | 381 } else { |
380 canvas->Save(); | 382 canvas->Save(); |
381 canvas->ClipRectInt(0, 0, width(), height()); | 383 canvas->ClipRectInt(0, 0, width(), height()); |
382 if (should_display_crashed_favicon_) { | 384 if (should_display_crashed_favicon_) { |
383 canvas->DrawBitmapInt(*crashed_fav_icon, 0, 0, | 385 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
384 crashed_fav_icon->width(), | 386 SkBitmap crashed_fav_icon(*rb.GetBitmapNamed(IDR_SAD_FAVICON)); |
385 crashed_fav_icon->height(), | 387 canvas->DrawBitmapInt(crashed_fav_icon, 0, 0, crashed_fav_icon.width(), |
386 favicon_x, | 388 crashed_fav_icon.height(), favicon_x, |
387 (height() - crashed_fav_icon->height()) / 2 + | 389 (height() - crashed_fav_icon.height()) / 2 + fav_icon_hiding_offset_, |
388 fav_icon_hiding_offset_, | 390 kFavIconSize, kFavIconSize, true); |
389 kFavIconSize, kFavIconSize, | |
390 true); | |
391 } else { | 391 } else { |
392 if (!data().favicon.isNull()) { | 392 if (!data().favicon.isNull()) { |
393 // TODO(pkasting): Use code in tab_icon_view.cc:PaintIcon() (or switch | 393 // TODO(pkasting): Use code in tab_icon_view.cc:PaintIcon() (or switch |
394 // to using that class to render the favicon). | 394 // to using that class to render the favicon). |
395 int size = data().favicon.width(); | 395 int size = data().favicon.width(); |
396 canvas->DrawBitmapInt(data().favicon, 0, 0, | 396 canvas->DrawBitmapInt(data().favicon, 0, 0, |
397 data().favicon.width(), | 397 data().favicon.width(), |
398 data().favicon.height(), | 398 data().favicon.height(), |
399 x, y + fav_icon_hiding_offset_, size, size, | 399 x, y + fav_icon_hiding_offset_, size, size, |
400 true); | 400 true); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
437 controller()->CloseTab(this); | 437 controller()->CloseTab(this); |
438 } | 438 } |
439 | 439 |
440 void BaseTab::ShowContextMenu(views::View* source, | 440 void BaseTab::ShowContextMenu(views::View* source, |
441 const gfx::Point& p, | 441 const gfx::Point& p, |
442 bool is_mouse_gesture) { | 442 bool is_mouse_gesture) { |
443 if (controller()) | 443 if (controller()) |
444 controller()->ShowContextMenu(this, p); | 444 controller()->ShowContextMenu(this, p); |
445 } | 445 } |
446 | 446 |
447 void BaseTab::ThemeChanged() { | |
448 views::View::ThemeChanged(); | |
449 LoadThemeImages(); | |
450 } | |
451 | |
452 void BaseTab::SetFavIconHidingOffset(int offset) { | 447 void BaseTab::SetFavIconHidingOffset(int offset) { |
453 fav_icon_hiding_offset_ = offset; | 448 fav_icon_hiding_offset_ = offset; |
454 SchedulePaint(); | 449 SchedulePaint(); |
455 } | 450 } |
456 | 451 |
457 void BaseTab::DisplayCrashedFavIcon() { | 452 void BaseTab::DisplayCrashedFavIcon() { |
458 should_display_crashed_favicon_ = true; | 453 should_display_crashed_favicon_ = true; |
459 } | 454 } |
460 | 455 |
461 void BaseTab::ResetCrashedFavIcon() { | 456 void BaseTab::ResetCrashedFavIcon() { |
(...skipping 13 matching lines...) Expand all Loading... |
475 crash_animation_->Stop(); | 470 crash_animation_->Stop(); |
476 } | 471 } |
477 | 472 |
478 bool BaseTab::IsPerformingCrashAnimation() const { | 473 bool BaseTab::IsPerformingCrashAnimation() const { |
479 return crash_animation_.get() && crash_animation_->is_animating(); | 474 return crash_animation_.get() && crash_animation_->is_animating(); |
480 } | 475 } |
481 | 476 |
482 // static | 477 // static |
483 void BaseTab::InitResources() { | 478 void BaseTab::InitResources() { |
484 static bool initialized = false; | 479 static bool initialized = false; |
485 if (initialized) | 480 if (!initialized) { |
486 return; | 481 initialized = true; |
487 | 482 font_ = new gfx::Font( |
488 initialized = true; | 483 ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BaseFont)); |
489 | 484 font_height_ = font_->height(); |
490 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 485 } |
491 | |
492 crashed_fav_icon = rb.GetBitmapNamed(IDR_SAD_FAVICON); | |
493 | |
494 close_button_n = rb.GetBitmapNamed(IDR_TAB_CLOSE); | |
495 close_button_h = rb.GetBitmapNamed(IDR_TAB_CLOSE_H); | |
496 close_button_p = rb.GetBitmapNamed(IDR_TAB_CLOSE_P); | |
497 | |
498 close_button_width_ = close_button_n->width(); | |
499 close_button_height_ = close_button_n->height(); | |
500 | |
501 // The loading animation image is a strip of states. Each state must be | |
502 // square, so the height must divide the width evenly. | |
503 loading_animation_frames = rb.GetBitmapNamed(IDR_THROBBER); | |
504 loading_animation_size_ = loading_animation_frames->height(); | |
505 DCHECK(loading_animation_frames); | |
506 DCHECK(loading_animation_frames->width() % | |
507 loading_animation_frames->height() == 0); | |
508 loading_animation_frame_count = | |
509 loading_animation_frames->width() / loading_animation_frames->height(); | |
510 | |
511 waiting_animation_frames = rb.GetBitmapNamed(IDR_THROBBER_WAITING); | |
512 DCHECK(waiting_animation_frames); | |
513 DCHECK(waiting_animation_frames->width() % | |
514 waiting_animation_frames->height() == 0); | |
515 waiting_animation_frame_count = | |
516 waiting_animation_frames->width() / waiting_animation_frames->height(); | |
517 | |
518 waiting_to_loading_frame_count_ratio = | |
519 waiting_animation_frame_count / loading_animation_frame_count; | |
520 | |
521 font_ = new gfx::Font(rb.GetFont(ResourceBundle::BaseFont)); | |
522 font_height_ = font_->height(); | |
523 } | 486 } |
524 | |
525 // static | |
526 void BaseTab::LoadThemeImages() { | |
527 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | |
528 loading_animation_frames = rb.GetBitmapNamed(IDR_THROBBER); | |
529 waiting_animation_frames = rb.GetBitmapNamed(IDR_THROBBER_WAITING); | |
530 loading_animation_size_ = loading_animation_frames->height(); | |
531 } | |
OLD | NEW |