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

Side by Side Diff: chrome/browser/ui/cocoa/tabpose_window.mm

Issue 5764002: Mac: zoom title and favicon during tabpose zoom animation (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: '' Created 10 years 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 425
426 NSRect Tile::GetStartRectRelativeTo(const Tile& tile) const { 426 NSRect Tile::GetStartRectRelativeTo(const Tile& tile) const {
427 NSRect rect = start_thumb_rect_; 427 NSRect rect = start_thumb_rect_;
428 rect.origin.x -= tile.start_thumb_rect_.origin.x; 428 rect.origin.x -= tile.start_thumb_rect_.origin.x;
429 rect.origin.y -= tile.start_thumb_rect_.origin.y; 429 rect.origin.y -= tile.start_thumb_rect_.origin.y;
430 return rect; 430 return rect;
431 } 431 }
432 432
433 NSRect Tile::GetFaviconStartRectRelativeTo(const Tile& tile) const { 433 NSRect Tile::GetFaviconStartRectRelativeTo(const Tile& tile) const {
434 NSRect thumb_start = GetStartRectRelativeTo(tile); 434 NSRect thumb_start = GetStartRectRelativeTo(tile);
435 CGFloat scale_small_to_big = NSWidth(thumb_start) / NSWidth(thumb_rect_);
viettrungluu 2010/12/15 17:36:57 What is this scale and where does it come from? A
Nico 2010/12/15 18:52:29 :-( Renamed the variable. It's the ratio between
435 NSRect rect = favicon_rect_; 436 NSRect rect = favicon_rect_;
436 rect.origin.x += NSMinX(thumb_start) - NSMinX(thumb_rect_); 437 rect.origin.x -= NSMinX(thumb_rect_);
viettrungluu 2010/12/15 17:36:57 Just make a helper function and do: x = ScaleRe
Nico 2010/12/15 18:52:29 Ah, but this doesn't do (x - origin) * scale + ori
437 rect.origin.y += NSMinY(thumb_start) - NSMinY(thumb_rect_); 438 rect.origin.x *= scale_small_to_big;
439 rect.origin.x += NSMinX(thumb_start);
440 rect.origin.y -= NSMinY(thumb_rect_);
441 rect.origin.y *= scale_small_to_big;
442 rect.origin.y += NSMinY(thumb_start);
443 rect.size.width *= scale_small_to_big;
444 rect.size.height *= scale_small_to_big;
438 return rect; 445 return rect;
439 } 446 }
440 447
441 SkBitmap Tile::favicon() const { 448 SkBitmap Tile::favicon() const {
442 if (contents_->is_app()) { 449 if (contents_->is_app()) {
443 SkBitmap* icon = contents_->GetExtensionAppIcon(); 450 SkBitmap* icon = contents_->GetExtensionAppIcon();
444 if (icon) 451 if (icon)
445 return *icon; 452 return *icon;
446 } 453 }
447 return contents_->GetFavIcon(); 454 return contents_->GetFavIcon();
448 } 455 }
449 456
450 NSRect Tile::GetTitleStartRectRelativeTo(const Tile& tile) const { 457 NSRect Tile::GetTitleStartRectRelativeTo(const Tile& tile) const {
451 NSRect thumb_start = GetStartRectRelativeTo(tile); 458 NSRect thumb_start = GetStartRectRelativeTo(tile);
459 CGFloat scale_small_to_big = NSWidth(thumb_start) / NSWidth(thumb_rect_);
452 NSRect rect = title_rect_; 460 NSRect rect = title_rect_;
453 rect.origin.x += NSMinX(thumb_start) - NSMinX(thumb_rect_); 461 rect.origin.x -= NSMinX(thumb_rect_);
454 rect.origin.y += NSMinY(thumb_start) - NSMinY(thumb_rect_); 462 rect.origin.x *= scale_small_to_big;
463 rect.origin.x += NSMinX(thumb_start);
464 rect.origin.y -= NSMinY(thumb_rect_);
465 rect.origin.y *= scale_small_to_big;
466 rect.origin.y += NSMinY(thumb_start);
467 rect.size.width *= scale_small_to_big;
468 rect.size.height *= scale_small_to_big;
455 return rect; 469 return rect;
456 } 470 }
457 471
458 // Changes |title_rect| and |favicon_rect| such that the favicon's and the 472 // 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 473 // title's vertical center is aligned and that the minimum distance between
460 // the thumb rect and favicon and title rects doesn't change. 474 // the thumb rect and favicon and title rects doesn't change.
461 void Tile::set_font_metrics(CGFloat ascender, CGFloat descender) { 475 void Tile::set_font_metrics(CGFloat ascender, CGFloat descender) {
462 // Make the title height big enough to fit the font, and adopt the title 476 // Make the title height big enough to fit the font, and adopt the title
463 // position to keep its distance from the thumb rect. 477 // position to keep its distance from the thumb rect.
464 title_rect_.origin.y -= ascender + descender - NSHeight(title_rect_); 478 title_rect_.origin.y -= ascender + descender - NSHeight(title_rect_);
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
819 tiles_[i]->title_rect_ = tiles_[i + step]->title_rect_; 833 tiles_[i]->title_rect_ = tiles_[i + step]->title_rect_;
820 } 834 }
821 tiles_[from_index]->thumb_rect_ = thumb; 835 tiles_[from_index]->thumb_rect_ = thumb;
822 tiles_[from_index]->start_thumb_rect_ = start_thumb; 836 tiles_[from_index]->start_thumb_rect_ = start_thumb;
823 tiles_[from_index]->favicon_rect_ = favicon; 837 tiles_[from_index]->favicon_rect_ = favicon;
824 tiles_[from_index]->title_rect_ = title; 838 tiles_[from_index]->title_rect_ = title;
825 } 839 }
826 840
827 } // namespace tabpose 841 } // namespace tabpose
828 842
829 void AnimateCALayerFrameFromTo( 843 void AnimateScaledCALayerFrameFromTo(
830 CALayer* layer, const NSRect& from, const NSRect& to, 844 CALayer* layer,
845 const NSRect& from, CGFloat from_scale,
846 const NSRect& to, CGFloat to_scale,
831 NSTimeInterval duration, id boundsAnimationDelegate) { 847 NSTimeInterval duration, id boundsAnimationDelegate) {
832 // http://developer.apple.com/mac/library/qa/qa2008/qa1620.html 848 // http://developer.apple.com/mac/library/qa/qa2008/qa1620.html
833 CABasicAnimation* animation; 849 CABasicAnimation* animation;
834 850
835 animation = [CABasicAnimation animationWithKeyPath:@"bounds"]; 851 animation = [CABasicAnimation animationWithKeyPath:@"bounds"];
836 animation.fromValue = [NSValue valueWithRect:from]; 852 animation.fromValue = [NSValue valueWithRect:from];
837 animation.toValue = [NSValue valueWithRect:to]; 853 animation.toValue = [NSValue valueWithRect:to];
838 animation.duration = duration; 854 animation.duration = duration;
839 animation.timingFunction = 855 animation.timingFunction =
840 [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 856 [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
841 animation.delegate = boundsAnimationDelegate; 857 animation.delegate = boundsAnimationDelegate;
842 858
843 // Update the layer's bounds so the layer doesn't snap back when the animation 859 // Update the layer's bounds so the layer doesn't snap back when the animation
844 // completes. 860 // completes.
845 layer.bounds = NSRectToCGRect(to); 861 layer.bounds = NSRectToCGRect(to);
846 862
847 // Add the animation, overriding the implicit animation. 863 // Add the animation, overriding the implicit animation.
848 [layer addAnimation:animation forKey:@"bounds"]; 864 [layer addAnimation:animation forKey:@"bounds"];
849 865
850 // Prepare the animation from the current position to the new position. 866 // Prepare the animation from the current position to the new position.
851 NSPoint opoint = from.origin; 867 NSPoint opoint = from.origin;
852 NSPoint point = to.origin; 868 NSPoint point = to.origin;
853 869
854 // Adapt to anchorPoint. 870 // Adapt to anchorPoint.
855 opoint.x += NSWidth(from) * layer.anchorPoint.x; 871 opoint.x += NSWidth(from) * from_scale * layer.anchorPoint.x;
856 opoint.y += NSHeight(from) * layer.anchorPoint.y; 872 opoint.y += NSHeight(from) * from_scale * layer.anchorPoint.y;
857 point.x += NSWidth(to) * layer.anchorPoint.x; 873 point.x += NSWidth(to) * to_scale * layer.anchorPoint.x;
858 point.y += NSHeight(to) * layer.anchorPoint.y; 874 point.y += NSHeight(to) * to_scale * layer.anchorPoint.y;
859 875
860 animation = [CABasicAnimation animationWithKeyPath:@"position"]; 876 animation = [CABasicAnimation animationWithKeyPath:@"position"];
861 animation.fromValue = [NSValue valueWithPoint:opoint]; 877 animation.fromValue = [NSValue valueWithPoint:opoint];
862 animation.toValue = [NSValue valueWithPoint:point]; 878 animation.toValue = [NSValue valueWithPoint:point];
863 animation.duration = duration; 879 animation.duration = duration;
864 animation.timingFunction = 880 animation.timingFunction =
865 [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; 881 [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
866 882
867 // Update the layer's position so that the layer doesn't snap back when the 883 // Update the layer's position so that the layer doesn't snap back when the
868 // animation completes. 884 // animation completes.
869 layer.position = NSPointToCGPoint(point); 885 layer.position = NSPointToCGPoint(point);
870 886
871 // Add the animation, overriding the implicit animation. 887 // Add the animation, overriding the implicit animation.
872 [layer addAnimation:animation forKey:@"position"]; 888 [layer addAnimation:animation forKey:@"position"];
873 } 889 }
874 890
891 void AnimateCALayerFrameFromTo(
892 CALayer* layer, const NSRect& from, const NSRect& to,
893 NSTimeInterval duration, id boundsAnimationDelegate) {
894 AnimateScaledCALayerFrameFromTo(
895 layer, from, 1.0, to, 1.0, duration, boundsAnimationDelegate);
896 }
897
875 void AnimateCALayerOpacityFromTo( 898 void AnimateCALayerOpacityFromTo(
876 CALayer* layer, double from, double to, NSTimeInterval duration) { 899 CALayer* layer, double from, double to, NSTimeInterval duration) {
877 CABasicAnimation* animation; 900 CABasicAnimation* animation;
878 animation = [CABasicAnimation animationWithKeyPath:@"opacity"]; 901 animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
879 animation.fromValue = [NSNumber numberWithFloat:from]; 902 animation.fromValue = [NSNumber numberWithFloat:from];
880 animation.toValue = [NSNumber numberWithFloat:to]; 903 animation.toValue = [NSNumber numberWithFloat:to];
881 animation.duration = duration; 904 animation.duration = duration;
882 905
883 layer.opacity = to; 906 layer.opacity = to;
884 // Add the animation, overriding the implicit animation. 907 // Add the animation, overriding the implicit animation.
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1008 nil); 1031 nil);
1009 AnimateCALayerOpacityFromTo(faviconLayer, 0.0, 1.0, interval); 1032 AnimateCALayerOpacityFromTo(faviconLayer, 0.0, 1.0, interval);
1010 } else { 1033 } else {
1011 faviconLayer.frame = NSRectToCGRect(tile.favicon_rect()); 1034 faviconLayer.frame = NSRectToCGRect(tile.favicon_rect());
1012 } 1035 }
1013 faviconLayer.contents = (id)favicon.get(); 1036 faviconLayer.contents = (id)favicon.get();
1014 faviconLayer.zPosition = 1; // On top of the thumb shadow. 1037 faviconLayer.zPosition = 1; // On top of the thumb shadow.
1015 [bgLayer_ addSublayer:faviconLayer]; 1038 [bgLayer_ addSublayer:faviconLayer];
1016 [allFaviconLayers_ addObject:faviconLayer]; 1039 [allFaviconLayers_ addObject:faviconLayer];
1017 1040
1041 // CATextLayers can't animate their fontSize property, at least on 10.5.
1042 // Animate transform.scale instead.
1043
1044 // The scaling should have its origin in the layer's upper left corner.
1045 // This needs to be set before |AnimateCALayerFrameFromTo()| is called.
1018 CATextLayer* titleLayer = [CATextLayer layer]; 1046 CATextLayer* titleLayer = [CATextLayer layer];
1047 titleLayer.anchorPoint = CGPointMake(0, 1);
1019 if (showZoom) { 1048 if (showZoom) {
1020 AnimateCALayerFrameFromTo( 1049 NSRect fromRect =
1021 titleLayer, 1050 tile.GetTitleStartRectRelativeTo(tileSet_->selected_tile());
1022 tile.GetTitleStartRectRelativeTo(tileSet_->selected_tile()), 1051 NSRect toRect = tile.title_rect();
1023 tile.title_rect(), 1052 CGFloat scale = NSWidth(fromRect) / NSWidth(toRect);
1024 interval, 1053 fromRect.size = toRect.size;
1025 nil); 1054
1026 AnimateCALayerOpacityFromTo(titleLayer, 0.0, 1.0, interval); 1055 // Add scale animation.
1056 CABasicAnimation* scaleAnimation =
1057 [CABasicAnimation animationWithKeyPath:@"transform.scale"];
1058 scaleAnimation.fromValue = [NSNumber numberWithDouble:scale];
1059 scaleAnimation.toValue = [NSNumber numberWithDouble:1.0];
1060 scaleAnimation.duration = interval;
1061 scaleAnimation.timingFunction =
1062 [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
1063 [titleLayer addAnimation:scaleAnimation forKey:@"transform.scale"];
1064
1065 // Add the position and opacity animations.
1066 AnimateScaledCALayerFrameFromTo(
1067 titleLayer, fromRect, scale, toRect, 1.0, interval, nil);
1068 AnimateCALayerOpacityFromTo(faviconLayer, 0.0, 1.0, interval);
1027 } else { 1069 } else {
1028 titleLayer.frame = NSRectToCGRect(tile.title_rect()); 1070 titleLayer.frame = NSRectToCGRect(tile.title_rect());
1029 } 1071 }
1030 titleLayer.string = base::SysUTF16ToNSString(tile.title()); 1072 titleLayer.string = base::SysUTF16ToNSString(tile.title());
1031 titleLayer.fontSize = [font pointSize]; 1073 titleLayer.fontSize = [font pointSize];
1032 titleLayer.truncationMode = kCATruncationEnd; 1074 titleLayer.truncationMode = kCATruncationEnd;
1033 titleLayer.font = font; 1075 titleLayer.font = font;
1034 titleLayer.zPosition = 1; // On top of the thumb shadow. 1076 titleLayer.zPosition = 1; // On top of the thumb shadow.
1035 [bgLayer_ addSublayer:titleLayer]; 1077 [bgLayer_ addSublayer:titleLayer];
1036 [allTitleLayers_ addObject:titleLayer]; 1078 [allTitleLayers_ addObject:titleLayer];
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
1276 CALayer* layer = [allThumbnailLayers_ objectAtIndex:i]; 1318 CALayer* layer = [allThumbnailLayers_ objectAtIndex:i];
1277 // Add a delegate to one of the implicit animations to get a notification 1319 // Add a delegate to one of the implicit animations to get a notification
1278 // once the animations are done. 1320 // once the animations are done.
1279 if (static_cast<int>(i) == tileSet_->selected_index()) { 1321 if (static_cast<int>(i) == tileSet_->selected_index()) {
1280 CAAnimation* animation = [CAAnimation animation]; 1322 CAAnimation* animation = [CAAnimation animation];
1281 animation.delegate = self; 1323 animation.delegate = self;
1282 [animation setValue:kAnimationIdFadeOut forKey:kAnimationIdKey]; 1324 [animation setValue:kAnimationIdFadeOut forKey:kAnimationIdKey];
1283 [layer addAnimation:animation forKey:@"frame"]; 1325 [layer addAnimation:animation forKey:@"frame"];
1284 } 1326 }
1285 1327
1328 // Thumbnail.
1286 layer.frame = NSRectToCGRect( 1329 layer.frame = NSRectToCGRect(
1287 tile.GetStartRectRelativeTo(tileSet_->selected_tile())); 1330 tile.GetStartRectRelativeTo(tileSet_->selected_tile()));
1288 1331
1289 if (static_cast<int>(i) == tileSet_->selected_index()) { 1332 if (static_cast<int>(i) == tileSet_->selected_index()) {
1290 // Redraw layer at big resolution, so that zoom-in isn't blocky. 1333 // Redraw layer at big resolution, so that zoom-in isn't blocky.
1291 [layer setNeedsDisplay]; 1334 [layer setNeedsDisplay];
1292 } 1335 }
1293 1336
1337 // Title.
1294 CALayer* faviconLayer = [allFaviconLayers_ objectAtIndex:i]; 1338 CALayer* faviconLayer = [allFaviconLayers_ objectAtIndex:i];
1295 faviconLayer.frame = NSRectToCGRect( 1339 faviconLayer.frame = NSRectToCGRect(
1296 tile.GetFaviconStartRectRelativeTo(tileSet_->selected_tile())); 1340 tile.GetFaviconStartRectRelativeTo(tileSet_->selected_tile()));
1297 faviconLayer.opacity = 0; 1341 faviconLayer.opacity = 0;
1342
1343 // Favicon.
1344 // The |fontSize| cannot be animated directly, animate the layer's scale
1345 // instead. scale affects the rendered width, so keep the small bounds.
viettrungluu 2010/12/15 17:36:57 "|scale|". Or should that be |transform.scale|? ("
Nico 2010/12/15 18:52:29 With "small", it's clear that it refers to the zoo
1298 CALayer* titleLayer = [allTitleLayers_ objectAtIndex:i]; 1346 CALayer* titleLayer = [allTitleLayers_ objectAtIndex:i];
1299 titleLayer.frame = NSRectToCGRect( 1347 NSRect titleRect = tile.title_rect();
1300 tile.GetTitleStartRectRelativeTo(tileSet_->selected_tile())); 1348 NSRect titleToRect =
1349 tile.GetTitleStartRectRelativeTo(tileSet_->selected_tile());
1350 CGFloat scale = NSWidth(titleToRect) / NSWidth(titleRect);
1351 titleToRect.origin.x +=
1352 NSWidth(titleRect) * scale * titleLayer.anchorPoint.x;
1353 titleToRect.origin.y +=
1354 NSHeight(titleRect) * scale * titleLayer.anchorPoint.y;
1355 titleLayer.position = NSPointToCGPoint(titleToRect.origin);
1356 [titleLayer setValue:[NSNumber numberWithDouble:scale]
1357 forKeyPath:@"transform.scale"];
1301 titleLayer.opacity = 0; 1358 titleLayer.opacity = 0;
1302 } 1359 }
1303 } 1360 }
viettrungluu 2010/12/15 17:36:57 This is getting ridiculously big. Please break it
Nico 2010/12/15 18:52:29 It's a sweet 77 lines short! Alright, done.
1304 1361
1305 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished { 1362 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished {
1306 NSString* animationId = [animation valueForKey:kAnimationIdKey]; 1363 NSString* animationId = [animation valueForKey:kAnimationIdKey];
1307 if ([animationId isEqualToString:kAnimationIdFadeIn]) { 1364 if ([animationId isEqualToString:kAnimationIdFadeIn]) {
1308 if (finished && state_ == tabpose::kFadingIn) { 1365 if (finished && state_ == tabpose::kFadingIn) {
1309 // If the user clicks while the fade in animation is still running, 1366 // If the user clicks while the fade in animation is still running,
1310 // |state_| is already kFadingOut. In that case, don't do anything. 1367 // |state_| is already kFadingOut. In that case, don't do anything.
1311 state_ = tabpose::kFadedIn; 1368 state_ = tabpose::kFadedIn;
1312 1369
1313 selectionHighlight_.hidden = NO; 1370 selectionHighlight_.hidden = NO;
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
1483 tile.set_tab_contents(contents->tab_contents()); 1540 tile.set_tab_contents(contents->tab_contents());
1484 ThumbnailLayer* thumbLayer = [allThumbnailLayers_ objectAtIndex:index]; 1541 ThumbnailLayer* thumbLayer = [allThumbnailLayers_ objectAtIndex:index];
1485 [thumbLayer setTabContents:contents->tab_contents()]; 1542 [thumbLayer setTabContents:contents->tab_contents()];
1486 } 1543 }
1487 1544
1488 - (void)tabStripModelDeleted { 1545 - (void)tabStripModelDeleted {
1489 [self close]; 1546 [self close];
1490 } 1547 }
1491 1548
1492 @end 1549 @end
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698