| 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 #import "chrome/browser/ui/cocoa/tabpose_window.h" | 5 #import "chrome/browser/ui/cocoa/tabpose_window.h" |
| 6 | 6 |
| 7 #import <QuartzCore/QuartzCore.h> | 7 #import <QuartzCore/QuartzCore.h> |
| 8 | 8 |
| 9 #include "app/resource_bundle.h" | 9 #include "app/resource_bundle.h" |
| 10 #include "base/mac_util.h" | 10 #include "base/mac_util.h" |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 // This function returns ny. | 362 // This function returns ny. |
| 363 return (sqrt(pow(n * (a * dy - dx), 2) + | 363 return (sqrt(pow(n * (a * dy - dx), 2) + |
| 364 4 * n * a * (dx + w_c) * (dy + h_c)) - | 364 4 * n * a * (dx + w_c) * (dy + h_c)) - |
| 365 n * (a * dy - dx)) | 365 n * (a * dy - dx)) |
| 366 / | 366 / |
| 367 (2 * (dx + w_c)); | 367 (2 * (dx + w_c)); |
| 368 } | 368 } |
| 369 | 369 |
| 370 namespace tabpose { | 370 namespace tabpose { |
| 371 | 371 |
| 372 CGFloat ScaleWithOrigin(CGFloat x, CGFloat origin, CGFloat scale) { |
| 373 return (x - origin) * scale + origin; |
| 374 } |
| 375 |
| 376 NSRect ScaleRectWithOrigin(NSRect r, NSPoint p, CGFloat scale) { |
| 377 return NSMakeRect(ScaleWithOrigin(NSMinX(r), p.x, scale), |
| 378 ScaleWithOrigin(NSMinY(r), p.y, scale), |
| 379 NSWidth(r) * scale, |
| 380 NSHeight(r) * scale); |
| 381 } |
| 382 |
| 372 // A tile is what is shown for a single tab in tabpose mode. It consists of a | 383 // A tile is what is shown for a single tab in tabpose mode. It consists of a |
| 373 // title, favicon, thumbnail image, and pre- and postanimation rects. | 384 // title, favicon, thumbnail image, and pre- and postanimation rects. |
| 374 class Tile { | 385 class Tile { |
| 375 public: | 386 public: |
| 376 Tile() {} | 387 Tile() {} |
| 377 | 388 |
| 378 // Returns the rectangle this thumbnail is at at the beginning of the zoom-in | 389 // Returns the rectangle this thumbnail is at at the beginning of the zoom-in |
| 379 // animation. |tile| is the rectangle that's covering the whole tab area when | 390 // animation. |tile| is the rectangle that's covering the whole tab area when |
| 380 // the animation starts. | 391 // the animation starts. |
| 381 NSRect GetStartRectRelativeTo(const Tile& tile) const; | 392 NSRect GetStartRectRelativeTo(const Tile& tile) const; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 | 436 |
| 426 NSRect Tile::GetStartRectRelativeTo(const Tile& tile) const { | 437 NSRect Tile::GetStartRectRelativeTo(const Tile& tile) const { |
| 427 NSRect rect = start_thumb_rect_; | 438 NSRect rect = start_thumb_rect_; |
| 428 rect.origin.x -= tile.start_thumb_rect_.origin.x; | 439 rect.origin.x -= tile.start_thumb_rect_.origin.x; |
| 429 rect.origin.y -= tile.start_thumb_rect_.origin.y; | 440 rect.origin.y -= tile.start_thumb_rect_.origin.y; |
| 430 return rect; | 441 return rect; |
| 431 } | 442 } |
| 432 | 443 |
| 433 NSRect Tile::GetFaviconStartRectRelativeTo(const Tile& tile) const { | 444 NSRect Tile::GetFaviconStartRectRelativeTo(const Tile& tile) const { |
| 434 NSRect thumb_start = GetStartRectRelativeTo(tile); | 445 NSRect thumb_start = GetStartRectRelativeTo(tile); |
| 435 NSRect rect = favicon_rect_; | 446 CGFloat scale_to_start = NSWidth(thumb_start) / NSWidth(thumb_rect_); |
| 447 NSRect rect = |
| 448 ScaleRectWithOrigin(favicon_rect_, thumb_rect_.origin, scale_to_start); |
| 436 rect.origin.x += NSMinX(thumb_start) - NSMinX(thumb_rect_); | 449 rect.origin.x += NSMinX(thumb_start) - NSMinX(thumb_rect_); |
| 437 rect.origin.y += NSMinY(thumb_start) - NSMinY(thumb_rect_); | 450 rect.origin.y += NSMinY(thumb_start) - NSMinY(thumb_rect_); |
| 438 return rect; | 451 return rect; |
| 439 } | 452 } |
| 440 | 453 |
| 441 SkBitmap Tile::favicon() const { | 454 SkBitmap Tile::favicon() const { |
| 442 if (contents_->is_app()) { | 455 if (contents_->is_app()) { |
| 443 SkBitmap* icon = contents_->GetExtensionAppIcon(); | 456 SkBitmap* icon = contents_->GetExtensionAppIcon(); |
| 444 if (icon) | 457 if (icon) |
| 445 return *icon; | 458 return *icon; |
| 446 } | 459 } |
| 447 return contents_->GetFavIcon(); | 460 return contents_->GetFavIcon(); |
| 448 } | 461 } |
| 449 | 462 |
| 450 NSRect Tile::GetTitleStartRectRelativeTo(const Tile& tile) const { | 463 NSRect Tile::GetTitleStartRectRelativeTo(const Tile& tile) const { |
| 451 NSRect thumb_start = GetStartRectRelativeTo(tile); | 464 NSRect thumb_start = GetStartRectRelativeTo(tile); |
| 452 NSRect rect = title_rect_; | 465 CGFloat scale_to_start = NSWidth(thumb_start) / NSWidth(thumb_rect_); |
| 466 NSRect rect = |
| 467 ScaleRectWithOrigin(title_rect_, thumb_rect_.origin, scale_to_start); |
| 453 rect.origin.x += NSMinX(thumb_start) - NSMinX(thumb_rect_); | 468 rect.origin.x += NSMinX(thumb_start) - NSMinX(thumb_rect_); |
| 454 rect.origin.y += NSMinY(thumb_start) - NSMinY(thumb_rect_); | 469 rect.origin.y += NSMinY(thumb_start) - NSMinY(thumb_rect_); |
| 455 return rect; | 470 return rect; |
| 456 } | 471 } |
| 457 | 472 |
| 458 // Changes |title_rect| and |favicon_rect| such that the favicon's and the | 473 // Changes |title_rect| and |favicon_rect| such that the favicon's and the |
| 459 // title's vertical center is aligned and that the minimum distance between | 474 // title's vertical center is aligned and that the minimum distance between |
| 460 // the thumb rect and favicon and title rects doesn't change. | 475 // the thumb rect and favicon and title rects doesn't change. |
| 461 void Tile::set_font_metrics(CGFloat ascender, CGFloat descender) { | 476 void Tile::set_font_metrics(CGFloat ascender, CGFloat descender) { |
| 462 // Make the title height big enough to fit the font, and adopt the title | 477 // Make the title height big enough to fit the font, and adopt the title |
| (...skipping 356 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 819 tiles_[i]->title_rect_ = tiles_[i + step]->title_rect_; | 834 tiles_[i]->title_rect_ = tiles_[i + step]->title_rect_; |
| 820 } | 835 } |
| 821 tiles_[from_index]->thumb_rect_ = thumb; | 836 tiles_[from_index]->thumb_rect_ = thumb; |
| 822 tiles_[from_index]->start_thumb_rect_ = start_thumb; | 837 tiles_[from_index]->start_thumb_rect_ = start_thumb; |
| 823 tiles_[from_index]->favicon_rect_ = favicon; | 838 tiles_[from_index]->favicon_rect_ = favicon; |
| 824 tiles_[from_index]->title_rect_ = title; | 839 tiles_[from_index]->title_rect_ = title; |
| 825 } | 840 } |
| 826 | 841 |
| 827 } // namespace tabpose | 842 } // namespace tabpose |
| 828 | 843 |
| 829 void AnimateCALayerFrameFromTo( | 844 void AnimateScaledCALayerFrameFromTo( |
| 830 CALayer* layer, const NSRect& from, const NSRect& to, | 845 CALayer* layer, |
| 846 const NSRect& from, CGFloat from_scale, |
| 847 const NSRect& to, CGFloat to_scale, |
| 831 NSTimeInterval duration, id boundsAnimationDelegate) { | 848 NSTimeInterval duration, id boundsAnimationDelegate) { |
| 832 // http://developer.apple.com/mac/library/qa/qa2008/qa1620.html | 849 // http://developer.apple.com/mac/library/qa/qa2008/qa1620.html |
| 833 CABasicAnimation* animation; | 850 CABasicAnimation* animation; |
| 834 | 851 |
| 835 animation = [CABasicAnimation animationWithKeyPath:@"bounds"]; | 852 animation = [CABasicAnimation animationWithKeyPath:@"bounds"]; |
| 836 animation.fromValue = [NSValue valueWithRect:from]; | 853 animation.fromValue = [NSValue valueWithRect:from]; |
| 837 animation.toValue = [NSValue valueWithRect:to]; | 854 animation.toValue = [NSValue valueWithRect:to]; |
| 838 animation.duration = duration; | 855 animation.duration = duration; |
| 839 animation.timingFunction = | 856 animation.timingFunction = |
| 840 [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; | 857 [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; |
| 841 animation.delegate = boundsAnimationDelegate; | 858 animation.delegate = boundsAnimationDelegate; |
| 842 | 859 |
| 843 // Update the layer's bounds so the layer doesn't snap back when the animation | 860 // Update the layer's bounds so the layer doesn't snap back when the animation |
| 844 // completes. | 861 // completes. |
| 845 layer.bounds = NSRectToCGRect(to); | 862 layer.bounds = NSRectToCGRect(to); |
| 846 | 863 |
| 847 // Add the animation, overriding the implicit animation. | 864 // Add the animation, overriding the implicit animation. |
| 848 [layer addAnimation:animation forKey:@"bounds"]; | 865 [layer addAnimation:animation forKey:@"bounds"]; |
| 849 | 866 |
| 850 // Prepare the animation from the current position to the new position. | 867 // Prepare the animation from the current position to the new position. |
| 851 NSPoint opoint = from.origin; | 868 NSPoint opoint = from.origin; |
| 852 NSPoint point = to.origin; | 869 NSPoint point = to.origin; |
| 853 | 870 |
| 854 // Adapt to anchorPoint. | 871 // Adapt to anchorPoint. |
| 855 opoint.x += NSWidth(from) * layer.anchorPoint.x; | 872 opoint.x += NSWidth(from) * from_scale * layer.anchorPoint.x; |
| 856 opoint.y += NSHeight(from) * layer.anchorPoint.y; | 873 opoint.y += NSHeight(from) * from_scale * layer.anchorPoint.y; |
| 857 point.x += NSWidth(to) * layer.anchorPoint.x; | 874 point.x += NSWidth(to) * to_scale * layer.anchorPoint.x; |
| 858 point.y += NSHeight(to) * layer.anchorPoint.y; | 875 point.y += NSHeight(to) * to_scale * layer.anchorPoint.y; |
| 859 | 876 |
| 860 animation = [CABasicAnimation animationWithKeyPath:@"position"]; | 877 animation = [CABasicAnimation animationWithKeyPath:@"position"]; |
| 861 animation.fromValue = [NSValue valueWithPoint:opoint]; | 878 animation.fromValue = [NSValue valueWithPoint:opoint]; |
| 862 animation.toValue = [NSValue valueWithPoint:point]; | 879 animation.toValue = [NSValue valueWithPoint:point]; |
| 863 animation.duration = duration; | 880 animation.duration = duration; |
| 864 animation.timingFunction = | 881 animation.timingFunction = |
| 865 [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; | 882 [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; |
| 866 | 883 |
| 867 // Update the layer's position so that the layer doesn't snap back when the | 884 // Update the layer's position so that the layer doesn't snap back when the |
| 868 // animation completes. | 885 // animation completes. |
| 869 layer.position = NSPointToCGPoint(point); | 886 layer.position = NSPointToCGPoint(point); |
| 870 | 887 |
| 871 // Add the animation, overriding the implicit animation. | 888 // Add the animation, overriding the implicit animation. |
| 872 [layer addAnimation:animation forKey:@"position"]; | 889 [layer addAnimation:animation forKey:@"position"]; |
| 873 } | 890 } |
| 874 | 891 |
| 892 void AnimateCALayerFrameFromTo( |
| 893 CALayer* layer, const NSRect& from, const NSRect& to, |
| 894 NSTimeInterval duration, id boundsAnimationDelegate) { |
| 895 AnimateScaledCALayerFrameFromTo( |
| 896 layer, from, 1.0, to, 1.0, duration, boundsAnimationDelegate); |
| 897 } |
| 898 |
| 875 void AnimateCALayerOpacityFromTo( | 899 void AnimateCALayerOpacityFromTo( |
| 876 CALayer* layer, double from, double to, NSTimeInterval duration) { | 900 CALayer* layer, double from, double to, NSTimeInterval duration) { |
| 877 CABasicAnimation* animation; | 901 CABasicAnimation* animation; |
| 878 animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; | 902 animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; |
| 879 animation.fromValue = [NSNumber numberWithFloat:from]; | 903 animation.fromValue = [NSNumber numberWithFloat:from]; |
| 880 animation.toValue = [NSNumber numberWithFloat:to]; | 904 animation.toValue = [NSNumber numberWithFloat:to]; |
| 881 animation.duration = duration; | 905 animation.duration = duration; |
| 882 | 906 |
| 883 layer.opacity = to; | 907 layer.opacity = to; |
| 884 // Add the animation, overriding the implicit animation. | 908 // Add the animation, overriding the implicit animation. |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1008 nil); | 1032 nil); |
| 1009 AnimateCALayerOpacityFromTo(faviconLayer, 0.0, 1.0, interval); | 1033 AnimateCALayerOpacityFromTo(faviconLayer, 0.0, 1.0, interval); |
| 1010 } else { | 1034 } else { |
| 1011 faviconLayer.frame = NSRectToCGRect(tile.favicon_rect()); | 1035 faviconLayer.frame = NSRectToCGRect(tile.favicon_rect()); |
| 1012 } | 1036 } |
| 1013 faviconLayer.contents = (id)favicon.get(); | 1037 faviconLayer.contents = (id)favicon.get(); |
| 1014 faviconLayer.zPosition = 1; // On top of the thumb shadow. | 1038 faviconLayer.zPosition = 1; // On top of the thumb shadow. |
| 1015 [bgLayer_ addSublayer:faviconLayer]; | 1039 [bgLayer_ addSublayer:faviconLayer]; |
| 1016 [allFaviconLayers_ addObject:faviconLayer]; | 1040 [allFaviconLayers_ addObject:faviconLayer]; |
| 1017 | 1041 |
| 1042 // CATextLayers can't animate their fontSize property, at least on 10.5. |
| 1043 // Animate transform.scale instead. |
| 1044 |
| 1045 // The scaling should have its origin in the layer's upper left corner. |
| 1046 // This needs to be set before |AnimateCALayerFrameFromTo()| is called. |
| 1018 CATextLayer* titleLayer = [CATextLayer layer]; | 1047 CATextLayer* titleLayer = [CATextLayer layer]; |
| 1048 titleLayer.anchorPoint = CGPointMake(0, 1); |
| 1019 if (showZoom) { | 1049 if (showZoom) { |
| 1020 AnimateCALayerFrameFromTo( | 1050 NSRect fromRect = |
| 1021 titleLayer, | 1051 tile.GetTitleStartRectRelativeTo(tileSet_->selected_tile()); |
| 1022 tile.GetTitleStartRectRelativeTo(tileSet_->selected_tile()), | 1052 NSRect toRect = tile.title_rect(); |
| 1023 tile.title_rect(), | 1053 CGFloat scale = NSWidth(fromRect) / NSWidth(toRect); |
| 1024 interval, | 1054 fromRect.size = toRect.size; |
| 1025 nil); | 1055 |
| 1026 AnimateCALayerOpacityFromTo(titleLayer, 0.0, 1.0, interval); | 1056 // Add scale animation. |
| 1057 CABasicAnimation* scaleAnimation = |
| 1058 [CABasicAnimation animationWithKeyPath:@"transform.scale"]; |
| 1059 scaleAnimation.fromValue = [NSNumber numberWithDouble:scale]; |
| 1060 scaleAnimation.toValue = [NSNumber numberWithDouble:1.0]; |
| 1061 scaleAnimation.duration = interval; |
| 1062 scaleAnimation.timingFunction = |
| 1063 [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; |
| 1064 [titleLayer addAnimation:scaleAnimation forKey:@"transform.scale"]; |
| 1065 |
| 1066 // Add the position and opacity animations. |
| 1067 AnimateScaledCALayerFrameFromTo( |
| 1068 titleLayer, fromRect, scale, toRect, 1.0, interval, nil); |
| 1069 AnimateCALayerOpacityFromTo(faviconLayer, 0.0, 1.0, interval); |
| 1027 } else { | 1070 } else { |
| 1028 titleLayer.frame = NSRectToCGRect(tile.title_rect()); | 1071 titleLayer.frame = NSRectToCGRect(tile.title_rect()); |
| 1029 } | 1072 } |
| 1030 titleLayer.string = base::SysUTF16ToNSString(tile.title()); | 1073 titleLayer.string = base::SysUTF16ToNSString(tile.title()); |
| 1031 titleLayer.fontSize = [font pointSize]; | 1074 titleLayer.fontSize = [font pointSize]; |
| 1032 titleLayer.truncationMode = kCATruncationEnd; | 1075 titleLayer.truncationMode = kCATruncationEnd; |
| 1033 titleLayer.font = font; | 1076 titleLayer.font = font; |
| 1034 titleLayer.zPosition = 1; // On top of the thumb shadow. | 1077 titleLayer.zPosition = 1; // On top of the thumb shadow. |
| 1035 [bgLayer_ addSublayer:titleLayer]; | 1078 [bgLayer_ addSublayer:titleLayer]; |
| 1036 [allTitleLayers_ addObject:titleLayer]; | 1079 [allTitleLayers_ addObject:titleLayer]; |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1232 [self fadeAway:NO]; | 1275 [self fadeAway:NO]; |
| 1233 } | 1276 } |
| 1234 | 1277 |
| 1235 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { | 1278 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { |
| 1236 // Disable all browser-related menu items except the tab overview toggle. | 1279 // Disable all browser-related menu items except the tab overview toggle. |
| 1237 SEL action = [item action]; | 1280 SEL action = [item action]; |
| 1238 NSInteger tag = [item tag]; | 1281 NSInteger tag = [item tag]; |
| 1239 return action == @selector(commandDispatch:) && tag == IDC_TABPOSE; | 1282 return action == @selector(commandDispatch:) && tag == IDC_TABPOSE; |
| 1240 } | 1283 } |
| 1241 | 1284 |
| 1285 - (void)fadeAwayTileAtIndex:(int)index { |
| 1286 const tabpose::Tile& tile = tileSet_->tile_at(index); |
| 1287 CALayer* layer = [allThumbnailLayers_ objectAtIndex:index]; |
| 1288 // Add a delegate to one of the implicit animations to get a notification |
| 1289 // once the animations are done. |
| 1290 if (static_cast<int>(index) == tileSet_->selected_index()) { |
| 1291 CAAnimation* animation = [CAAnimation animation]; |
| 1292 animation.delegate = self; |
| 1293 [animation setValue:kAnimationIdFadeOut forKey:kAnimationIdKey]; |
| 1294 [layer addAnimation:animation forKey:@"frame"]; |
| 1295 } |
| 1296 |
| 1297 // Thumbnail. |
| 1298 layer.frame = NSRectToCGRect( |
| 1299 tile.GetStartRectRelativeTo(tileSet_->selected_tile())); |
| 1300 |
| 1301 if (static_cast<int>(index) == tileSet_->selected_index()) { |
| 1302 // Redraw layer at big resolution, so that zoom-in isn't blocky. |
| 1303 [layer setNeedsDisplay]; |
| 1304 } |
| 1305 |
| 1306 // Title. |
| 1307 CALayer* faviconLayer = [allFaviconLayers_ objectAtIndex:index]; |
| 1308 faviconLayer.frame = NSRectToCGRect( |
| 1309 tile.GetFaviconStartRectRelativeTo(tileSet_->selected_tile())); |
| 1310 faviconLayer.opacity = 0; |
| 1311 |
| 1312 // Favicon. |
| 1313 // The |fontSize| cannot be animated directly, animate the layer's scale |
| 1314 // instead. |transform.scale| affects the rendered width, so keep the small |
| 1315 // bounds. |
| 1316 CALayer* titleLayer = [allTitleLayers_ objectAtIndex:index]; |
| 1317 NSRect titleRect = tile.title_rect(); |
| 1318 NSRect titleToRect = |
| 1319 tile.GetTitleStartRectRelativeTo(tileSet_->selected_tile()); |
| 1320 CGFloat scale = NSWidth(titleToRect) / NSWidth(titleRect); |
| 1321 titleToRect.origin.x += |
| 1322 NSWidth(titleRect) * scale * titleLayer.anchorPoint.x; |
| 1323 titleToRect.origin.y += |
| 1324 NSHeight(titleRect) * scale * titleLayer.anchorPoint.y; |
| 1325 titleLayer.position = NSPointToCGPoint(titleToRect.origin); |
| 1326 [titleLayer setValue:[NSNumber numberWithDouble:scale] |
| 1327 forKeyPath:@"transform.scale"]; |
| 1328 titleLayer.opacity = 0; |
| 1329 } |
| 1330 |
| 1242 - (void)fadeAway:(BOOL)slomo { | 1331 - (void)fadeAway:(BOOL)slomo { |
| 1243 if (state_ == tabpose::kFadingOut) | 1332 if (state_ == tabpose::kFadingOut) |
| 1244 return; | 1333 return; |
| 1245 | 1334 |
| 1246 state_ = tabpose::kFadingOut; | 1335 state_ = tabpose::kFadingOut; |
| 1247 [self setAcceptsMouseMovedEvents:NO]; | 1336 [self setAcceptsMouseMovedEvents:NO]; |
| 1248 | 1337 |
| 1249 // Select chosen tab. | 1338 // Select chosen tab. |
| 1250 if (tileSet_->selected_index() < tabStripModel_->count()) { | 1339 if (tileSet_->selected_index() < tabStripModel_->count()) { |
| 1251 tabStripModel_->SelectTabContentsAt(tileSet_->selected_index(), | 1340 tabStripModel_->SelectTabContentsAt(tileSet_->selected_index(), |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1264 // Running animations with shadows is slow, so turn shadows off before | 1353 // Running animations with shadows is slow, so turn shadows off before |
| 1265 // running the exit animation. | 1354 // running the exit animation. |
| 1266 for (CALayer* layer in allThumbnailLayers_.get()) | 1355 for (CALayer* layer in allThumbnailLayers_.get()) |
| 1267 layer.shadowOpacity = 0.0; | 1356 layer.shadowOpacity = 0.0; |
| 1268 } | 1357 } |
| 1269 | 1358 |
| 1270 // Animate layers out, all in one transaction. | 1359 // Animate layers out, all in one transaction. |
| 1271 CGFloat duration = | 1360 CGFloat duration = |
| 1272 1.3 * kDefaultAnimationDuration * (slomo ? kSlomoFactor : 1); | 1361 1.3 * kDefaultAnimationDuration * (slomo ? kSlomoFactor : 1); |
| 1273 ScopedCAActionSetDuration durationSetter(duration); | 1362 ScopedCAActionSetDuration durationSetter(duration); |
| 1274 for (int i = 0; i < tabStripModel_->count(); ++i) { | 1363 for (int i = 0; i < tabStripModel_->count(); ++i) |
| 1275 const tabpose::Tile& tile = tileSet_->tile_at(i); | 1364 [self fadeAwayTileAtIndex:i]; |
| 1276 CALayer* layer = [allThumbnailLayers_ objectAtIndex:i]; | |
| 1277 // Add a delegate to one of the implicit animations to get a notification | |
| 1278 // once the animations are done. | |
| 1279 if (static_cast<int>(i) == tileSet_->selected_index()) { | |
| 1280 CAAnimation* animation = [CAAnimation animation]; | |
| 1281 animation.delegate = self; | |
| 1282 [animation setValue:kAnimationIdFadeOut forKey:kAnimationIdKey]; | |
| 1283 [layer addAnimation:animation forKey:@"frame"]; | |
| 1284 } | |
| 1285 | |
| 1286 layer.frame = NSRectToCGRect( | |
| 1287 tile.GetStartRectRelativeTo(tileSet_->selected_tile())); | |
| 1288 | |
| 1289 if (static_cast<int>(i) == tileSet_->selected_index()) { | |
| 1290 // Redraw layer at big resolution, so that zoom-in isn't blocky. | |
| 1291 [layer setNeedsDisplay]; | |
| 1292 } | |
| 1293 | |
| 1294 CALayer* faviconLayer = [allFaviconLayers_ objectAtIndex:i]; | |
| 1295 faviconLayer.frame = NSRectToCGRect( | |
| 1296 tile.GetFaviconStartRectRelativeTo(tileSet_->selected_tile())); | |
| 1297 faviconLayer.opacity = 0; | |
| 1298 CALayer* titleLayer = [allTitleLayers_ objectAtIndex:i]; | |
| 1299 titleLayer.frame = NSRectToCGRect( | |
| 1300 tile.GetTitleStartRectRelativeTo(tileSet_->selected_tile())); | |
| 1301 titleLayer.opacity = 0; | |
| 1302 } | |
| 1303 } | 1365 } |
| 1304 | 1366 |
| 1305 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished { | 1367 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished { |
| 1306 NSString* animationId = [animation valueForKey:kAnimationIdKey]; | 1368 NSString* animationId = [animation valueForKey:kAnimationIdKey]; |
| 1307 if ([animationId isEqualToString:kAnimationIdFadeIn]) { | 1369 if ([animationId isEqualToString:kAnimationIdFadeIn]) { |
| 1308 if (finished && state_ == tabpose::kFadingIn) { | 1370 if (finished && state_ == tabpose::kFadingIn) { |
| 1309 // If the user clicks while the fade in animation is still running, | 1371 // If the user clicks while the fade in animation is still running, |
| 1310 // |state_| is already kFadingOut. In that case, don't do anything. | 1372 // |state_| is already kFadingOut. In that case, don't do anything. |
| 1311 state_ = tabpose::kFadedIn; | 1373 state_ = tabpose::kFadedIn; |
| 1312 | 1374 |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1483 tile.set_tab_contents(contents->tab_contents()); | 1545 tile.set_tab_contents(contents->tab_contents()); |
| 1484 ThumbnailLayer* thumbLayer = [allThumbnailLayers_ objectAtIndex:index]; | 1546 ThumbnailLayer* thumbLayer = [allThumbnailLayers_ objectAtIndex:index]; |
| 1485 [thumbLayer setTabContents:contents->tab_contents()]; | 1547 [thumbLayer setTabContents:contents->tab_contents()]; |
| 1486 } | 1548 } |
| 1487 | 1549 |
| 1488 - (void)tabStripModelDeleted { | 1550 - (void)tabStripModelDeleted { |
| 1489 [self close]; | 1551 [self close]; |
| 1490 } | 1552 } |
| 1491 | 1553 |
| 1492 @end | 1554 @end |
| OLD | NEW |