OLD | NEW |
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/views/tabs/tab.h" | 5 #include "chrome/browser/ui/views/tabs/tab.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/debug/alias.h" | 10 #include "base/debug/alias.h" |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 public gfx::AnimationDelegate { | 158 public gfx::AnimationDelegate { |
159 public: | 159 public: |
160 explicit FaviconCrashAnimation(Tab* target) | 160 explicit FaviconCrashAnimation(Tab* target) |
161 : gfx::LinearAnimation(1000, 25, this), | 161 : gfx::LinearAnimation(1000, 25, this), |
162 target_(target) { | 162 target_(target) { |
163 } | 163 } |
164 ~FaviconCrashAnimation() override {} | 164 ~FaviconCrashAnimation() override {} |
165 | 165 |
166 // gfx::Animation overrides: | 166 // gfx::Animation overrides: |
167 void AnimateToState(double state) override { | 167 void AnimateToState(double state) override { |
168 const double kHidingOffset = 27; | 168 const double kHidingOffset = |
| 169 Tab::GetMinimumInactiveSize().height() - GetLayoutInsets(TAB).height(); |
169 | 170 |
170 if (state < .5) { | 171 if (state < .5) { |
171 // Animate the normal icon down. | 172 // Animate the normal icon down. |
172 target_->SetFaviconHidingOffset( | 173 target_->SetFaviconHidingOffset( |
173 static_cast<int>(floor(kHidingOffset * 2.0 * state))); | 174 static_cast<int>(floor(kHidingOffset * 2.0 * state))); |
174 } else { | 175 } else { |
175 // Animate the crashed icon up. | 176 // Animate the crashed icon up. |
176 target_->DisplayCrashedFavicon(); | 177 target_->set_should_display_crashed_favicon(); |
177 target_->SetFaviconHidingOffset( | 178 target_->SetFaviconHidingOffset( |
178 static_cast<int>( | 179 static_cast<int>( |
179 floor(kHidingOffset - ((state - .5) * 2.0 * kHidingOffset)))); | 180 floor(kHidingOffset - ((state - .5) * 2.0 * kHidingOffset)))); |
180 } | 181 } |
181 } | 182 } |
182 | 183 |
183 // gfx::AnimationDelegate overrides: | |
184 void AnimationCanceled(const gfx::Animation* animation) override { | |
185 target_->SetFaviconHidingOffset(0); | |
186 } | |
187 | |
188 private: | 184 private: |
189 Tab* target_; | 185 Tab* target_; |
190 | 186 |
191 DISALLOW_COPY_AND_ASSIGN(FaviconCrashAnimation); | 187 DISALLOW_COPY_AND_ASSIGN(FaviconCrashAnimation); |
192 }; | 188 }; |
193 | 189 |
194 //////////////////////////////////////////////////////////////////////////////// | 190 //////////////////////////////////////////////////////////////////////////////// |
195 // TabCloseButton | 191 // TabCloseButton |
196 // | 192 // |
197 // This is a Button subclass that causes middle clicks to be forwarded to the | 193 // This is a Button subclass that causes middle clicks to be forwarded to the |
(...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 if (title.empty()) { | 460 if (title.empty()) { |
465 title = data_.loading ? | 461 title = data_.loading ? |
466 l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) : | 462 l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) : |
467 CoreTabHelper::GetDefaultTitle(); | 463 CoreTabHelper::GetDefaultTitle(); |
468 } else { | 464 } else { |
469 Browser::FormatTitleForDisplay(&title); | 465 Browser::FormatTitleForDisplay(&title); |
470 } | 466 } |
471 title_->SetText(title); | 467 title_->SetText(title); |
472 | 468 |
473 if (data_.IsCrashed()) { | 469 if (data_.IsCrashed()) { |
474 if (!should_display_crashed_favicon_ && !IsPerformingCrashAnimation()) { | 470 if (!should_display_crashed_favicon_ && !crash_icon_animation_) { |
475 data_.media_state = TAB_MEDIA_STATE_NONE; | 471 data_.media_state = TAB_MEDIA_STATE_NONE; |
| 472 bool start_crash_animation = true; |
476 #if defined(OS_CHROMEOS) | 473 #if defined(OS_CHROMEOS) |
477 // On Chrome OS, we reload killed tabs automatically when the user | 474 // On Chrome OS, we reload killed tabs automatically when the user |
478 // switches to them. Don't display animations for these unless they're | 475 // switches to them. Don't display animations for these unless they're |
479 // selected (i.e. in the foreground) -- we won't reload these | 476 // selected (i.e. in the foreground) -- we won't reload these |
480 // automatically since we don't want to get into a crash loop. | 477 // automatically since we don't want to get into a crash loop. |
481 if (IsSelected() || | 478 start_crash_animation = IsSelected() || |
482 (data_.crashed_status | 479 (data_.crashed_status != |
483 != base::TERMINATION_STATUS_PROCESS_WAS_KILLED && | 480 base::TERMINATION_STATUS_PROCESS_WAS_KILLED && |
484 data_.crashed_status | 481 data_.crashed_status != |
485 != base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM)) { | 482 base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM); |
486 StartCrashAnimation(); | 483 #endif |
| 484 if (start_crash_animation) { |
| 485 crash_icon_animation_.reset(new FaviconCrashAnimation(this)); |
| 486 crash_icon_animation_->Start(); |
487 } | 487 } |
488 #else | |
489 StartCrashAnimation(); | |
490 #endif | |
491 } | 488 } |
492 } else { | 489 } else { |
493 if (IsPerformingCrashAnimation()) | 490 if (crash_icon_animation_) |
494 StopCrashAnimation(); | 491 crash_icon_animation_.reset(); |
495 ResetCrashedFavicon(); | 492 should_display_crashed_favicon_ = false; |
| 493 favicon_hiding_offset_ = 0; |
496 } | 494 } |
497 | 495 |
498 if (data_.media_state != old.media_state) | 496 if (data_.media_state != old.media_state) |
499 media_indicator_button_->TransitionToMediaState(data_.media_state); | 497 media_indicator_button_->TransitionToMediaState(data_.media_state); |
500 | 498 |
501 if (old.pinned != data_.pinned) { | 499 if (old.pinned != data_.pinned) |
502 StopAndDeleteAnimation(pinned_title_change_animation_.Pass()); | 500 StopPinnedTabTitleAnimation(); |
503 } | |
504 | 501 |
505 DataChanged(old); | 502 DataChanged(old); |
506 | 503 |
507 Layout(); | 504 Layout(); |
508 SchedulePaint(); | 505 SchedulePaint(); |
509 } | 506 } |
510 | 507 |
511 void Tab::UpdateLoadingAnimation(TabRendererData::NetworkState state) { | 508 void Tab::UpdateLoadingAnimation(TabRendererData::NetworkState state) { |
512 if (state == data_.network_state && | 509 if (state == data_.network_state && |
513 state == TabRendererData::NETWORK_STATE_NONE) { | 510 state == TabRendererData::NETWORK_STATE_NONE) { |
(...skipping 826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1340 | 1337 |
1341 // Now draw the highlights/shadows around the tab edge. | 1338 // Now draw the highlights/shadows around the tab edge. |
1342 canvas->DrawImageInt(*tab_image->image_l, 0, 0); | 1339 canvas->DrawImageInt(*tab_image->image_l, 0, 0); |
1343 canvas->TileImageInt(*tab_image->image_c, tab_image->l_width, 0, | 1340 canvas->TileImageInt(*tab_image->image_c, tab_image->l_width, 0, |
1344 width() - tab_image->l_width - tab_image->r_width, height()); | 1341 width() - tab_image->l_width - tab_image->r_width, height()); |
1345 canvas->DrawImageInt(*tab_image->image_r, width() - tab_image->r_width, 0); | 1342 canvas->DrawImageInt(*tab_image->image_r, width() - tab_image->r_width, 0); |
1346 } | 1343 } |
1347 | 1344 |
1348 void Tab::PaintIcon(gfx::Canvas* canvas) { | 1345 void Tab::PaintIcon(gfx::Canvas* canvas) { |
1349 gfx::Rect bounds = favicon_bounds_; | 1346 gfx::Rect bounds = favicon_bounds_; |
| 1347 bounds.set_x(GetMirroredXForRect(bounds)); |
| 1348 bounds.Offset(0, favicon_hiding_offset_); |
| 1349 bounds.Intersect(GetInteriorBounds()); |
1350 if (bounds.IsEmpty()) | 1350 if (bounds.IsEmpty()) |
1351 return; | 1351 return; |
1352 | 1352 |
1353 bounds.set_x(GetMirroredXForRect(bounds)); | |
1354 | |
1355 if (data().network_state != TabRendererData::NETWORK_STATE_NONE) { | 1353 if (data().network_state != TabRendererData::NETWORK_STATE_NONE) { |
1356 // Paint network activity (aka throbber) animation frame. | 1354 // Paint network activity (aka throbber) animation frame. |
1357 ui::ThemeProvider* tp = GetThemeProvider(); | 1355 ui::ThemeProvider* tp = GetThemeProvider(); |
1358 if (data().network_state == TabRendererData::NETWORK_STATE_WAITING) { | 1356 if (data().network_state == TabRendererData::NETWORK_STATE_WAITING) { |
1359 if (waiting_start_time_ == base::TimeTicks()) | 1357 if (waiting_start_time_ == base::TimeTicks()) |
1360 waiting_start_time_ = base::TimeTicks::Now(); | 1358 waiting_start_time_ = base::TimeTicks::Now(); |
1361 | 1359 |
1362 waiting_state_.elapsed_time = | 1360 waiting_state_.elapsed_time = |
1363 base::TimeTicks::Now() - waiting_start_time_; | 1361 base::TimeTicks::Now() - waiting_start_time_; |
1364 gfx::PaintThrobberWaiting( | 1362 gfx::PaintThrobberWaiting( |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1481 } | 1479 } |
1482 | 1480 |
1483 return is_selected ? kSelectedTabOpacity : 0; | 1481 return is_selected ? kSelectedTabOpacity : 0; |
1484 } | 1482 } |
1485 | 1483 |
1486 void Tab::SetFaviconHidingOffset(int offset) { | 1484 void Tab::SetFaviconHidingOffset(int offset) { |
1487 favicon_hiding_offset_ = offset; | 1485 favicon_hiding_offset_ = offset; |
1488 ScheduleIconPaint(); | 1486 ScheduleIconPaint(); |
1489 } | 1487 } |
1490 | 1488 |
1491 void Tab::DisplayCrashedFavicon() { | |
1492 should_display_crashed_favicon_ = true; | |
1493 } | |
1494 | |
1495 void Tab::ResetCrashedFavicon() { | |
1496 should_display_crashed_favicon_ = false; | |
1497 } | |
1498 | |
1499 void Tab::StopCrashAnimation() { | |
1500 crash_icon_animation_.reset(); | |
1501 } | |
1502 | |
1503 void Tab::StartCrashAnimation() { | |
1504 crash_icon_animation_.reset(new FaviconCrashAnimation(this)); | |
1505 crash_icon_animation_->Start(); | |
1506 } | |
1507 | |
1508 bool Tab::IsPerformingCrashAnimation() const { | |
1509 return crash_icon_animation_.get() && data_.IsCrashed(); | |
1510 } | |
1511 | |
1512 void Tab::OnButtonColorMaybeChanged() { | 1489 void Tab::OnButtonColorMaybeChanged() { |
1513 // The theme provider may be null if we're not currently in a widget | 1490 // The theme provider may be null if we're not currently in a widget |
1514 // hierarchy. | 1491 // hierarchy. |
1515 ui::ThemeProvider* theme_provider = GetThemeProvider(); | 1492 ui::ThemeProvider* theme_provider = GetThemeProvider(); |
1516 if (!theme_provider) | 1493 if (!theme_provider) |
1517 return; | 1494 return; |
1518 | 1495 |
1519 const SkColor title_color = theme_provider->GetColor(IsActive() ? | 1496 const SkColor title_color = theme_provider->GetColor(IsActive() ? |
1520 ThemeProperties::COLOR_TAB_TEXT : | 1497 ThemeProperties::COLOR_TAB_TEXT : |
1521 ThemeProperties::COLOR_BACKGROUND_TAB_TEXT); | 1498 ThemeProperties::COLOR_BACKGROUND_TAB_TEXT); |
1522 const SkColor new_button_color = SkColorSetA(title_color, 0xA0); | 1499 const SkColor new_button_color = SkColorSetA(title_color, 0xA0); |
1523 if (button_color_ != new_button_color) { | 1500 if (button_color_ != new_button_color) { |
1524 button_color_ = new_button_color; | 1501 button_color_ = new_button_color; |
1525 title_->SetEnabledColor(title_color); | 1502 title_->SetEnabledColor(title_color); |
1526 media_indicator_button_->OnParentTabButtonColorChanged(); | 1503 media_indicator_button_->OnParentTabButtonColorChanged(); |
1527 const gfx::ImageSkia& close_button_normal_image = gfx::CreateVectorIcon( | 1504 const gfx::ImageSkia& close_button_normal_image = gfx::CreateVectorIcon( |
1528 gfx::VectorIconId::TAB_CLOSE_NORMAL, kTabCloseButtonSize, | 1505 gfx::VectorIconId::TAB_CLOSE_NORMAL, kTabCloseButtonSize, |
1529 button_color_); | 1506 button_color_); |
1530 close_button_->SetImage(views::CustomButton::STATE_NORMAL, | 1507 close_button_->SetImage(views::CustomButton::STATE_NORMAL, |
1531 &close_button_normal_image); | 1508 &close_button_normal_image); |
1532 } | 1509 } |
1533 } | 1510 } |
1534 | 1511 |
1535 void Tab::ScheduleIconPaint() { | 1512 void Tab::ScheduleIconPaint() { |
1536 gfx::Rect bounds = favicon_bounds_; | 1513 gfx::Rect bounds = favicon_bounds_; |
1537 if (bounds.IsEmpty()) | 1514 if (bounds.IsEmpty()) |
1538 return; | 1515 return; |
1539 | 1516 |
1540 // Extends the area to the bottom when sad_favicon is animating. | 1517 // Extends the area to the bottom when the crash animation is in progress. |
1541 if (IsPerformingCrashAnimation()) | 1518 if (crash_icon_animation_) |
1542 bounds.set_height(height() - bounds.y()); | 1519 bounds.set_height(height() - bounds.y()); |
1543 bounds.set_x(GetMirroredXForRect(bounds)); | 1520 bounds.set_x(GetMirroredXForRect(bounds)); |
1544 SchedulePaintInRect(bounds); | 1521 SchedulePaintInRect(bounds); |
1545 } | 1522 } |
1546 | 1523 |
1547 gfx::Rect Tab::GetInteriorBounds() const { | 1524 gfx::Rect Tab::GetInteriorBounds() const { |
1548 gfx::Rect bounds(GetContentsBounds()); | 1525 gfx::Rect bounds(GetContentsBounds()); |
1549 bounds.Inset(GetLayoutInsets(TAB)); | 1526 bounds.Inset(GetLayoutInsets(TAB)); |
1550 return bounds; | 1527 return bounds; |
1551 } | 1528 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1634 const gfx::ImageSkia& image) { | 1611 const gfx::ImageSkia& image) { |
1635 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); | 1612 DCHECK_NE(scale_factor, ui::SCALE_FACTOR_NONE); |
1636 ImageCacheEntry entry; | 1613 ImageCacheEntry entry; |
1637 entry.resource_id = resource_id; | 1614 entry.resource_id = resource_id; |
1638 entry.scale_factor = scale_factor; | 1615 entry.scale_factor = scale_factor; |
1639 entry.image = image; | 1616 entry.image = image; |
1640 image_cache_->push_front(entry); | 1617 image_cache_->push_front(entry); |
1641 if (image_cache_->size() > kMaxImageCacheSize) | 1618 if (image_cache_->size() > kMaxImageCacheSize) |
1642 image_cache_->pop_back(); | 1619 image_cache_->pop_back(); |
1643 } | 1620 } |
OLD | NEW |