| 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 <algorithm> |
| 10 |
| 9 #include "app/resource_bundle.h" | 11 #include "app/resource_bundle.h" |
| 10 #include "base/mac/mac_util.h" | 12 #include "base/mac/mac_util.h" |
| 11 #include "base/mac/scoped_cftyperef.h" | 13 #include "base/mac/scoped_cftyperef.h" |
| 12 #include "base/scoped_callback_factory.h" | 14 #include "base/scoped_callback_factory.h" |
| 13 #include "base/sys_string_conversions.h" | 15 #include "base/sys_string_conversions.h" |
| 14 #include "chrome/app/chrome_command_ids.h" | 16 #include "chrome/app/chrome_command_ids.h" |
| 15 #include "chrome/browser/browser_process.h" | 17 #include "chrome/browser/browser_process.h" |
| 16 #import "chrome/browser/debugger/devtools_window.h" | 18 #import "chrome/browser/debugger/devtools_window.h" |
| 17 #include "chrome/browser/prefs/pref_service.h" | 19 #include "chrome/browser/prefs/pref_service.h" |
| 18 #include "chrome/browser/profiles/profile.h" | 20 #include "chrome/browser/profiles/profile.h" |
| 19 #include "chrome/browser/renderer_host/backing_store_mac.h" | 21 #include "chrome/browser/renderer_host/backing_store_mac.h" |
| 20 #include "chrome/browser/renderer_host/render_view_host.h" | 22 #include "chrome/browser/renderer_host/render_view_host.h" |
| 21 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" | 23 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" |
| 22 #include "chrome/browser/tab_contents/tab_contents.h" | 24 #include "chrome/browser/tab_contents/tab_contents.h" |
| 23 #include "chrome/browser/tab_contents/thumbnail_generator.h" | 25 #include "chrome/browser/tab_contents/thumbnail_generator.h" |
| 24 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h" | 26 #import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_constants.h" |
| 25 #import "chrome/browser/ui/cocoa/browser_window_controller.h" | 27 #import "chrome/browser/ui/cocoa/browser_window_controller.h" |
| 26 #import "chrome/browser/ui/cocoa/tab_strip_controller.h" | 28 #import "chrome/browser/ui/cocoa/tab_strip_controller.h" |
| 27 #import "chrome/browser/ui/cocoa/tab_strip_model_observer_bridge.h" | 29 #import "chrome/browser/ui/cocoa/tab_strip_model_observer_bridge.h" |
| 28 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" | 30 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 29 #include "chrome/common/pref_names.h" | 31 #include "chrome/common/pref_names.h" |
| 30 #include "gfx/scoped_cg_context_state_mac.h" | 32 #include "gfx/scoped_cg_context_state_mac.h" |
| 31 #include "grit/app_resources.h" | 33 #include "grit/app_resources.h" |
| 34 #include "grit/theme_resources.h" |
| 32 #include "skia/ext/skia_utils_mac.h" | 35 #include "skia/ext/skia_utils_mac.h" |
| 33 #include "third_party/skia/include/utils/mac/SkCGUtils.h" | 36 #include "third_party/skia/include/utils/mac/SkCGUtils.h" |
| 34 | 37 |
| 35 const int kTopGradientHeight = 15; | 38 const int kTopGradientHeight = 15; |
| 36 | 39 |
| 37 NSString* const kAnimationIdKey = @"AnimationId"; | 40 NSString* const kAnimationIdKey = @"AnimationId"; |
| 38 NSString* const kAnimationIdFadeIn = @"FadeIn"; | 41 NSString* const kAnimationIdFadeIn = @"FadeIn"; |
| 39 NSString* const kAnimationIdFadeOut = @"FadeOut"; | 42 NSString* const kAnimationIdFadeOut = @"FadeOut"; |
| 40 | 43 |
| 41 const CGFloat kDefaultAnimationDuration = 0.25; // In seconds. | 44 const CGFloat kDefaultAnimationDuration = 0.25; // In seconds. |
| 42 const CGFloat kSlomoFactor = 4; | 45 const CGFloat kSlomoFactor = 4; |
| 43 const CGFloat kObserverChangeAnimationDuration = 0.75; // In seconds. | 46 const CGFloat kObserverChangeAnimationDuration = 0.25; // In seconds. |
| 47 const CGFloat kSelectionInset = 5; |
| 44 | 48 |
| 45 // CAGradientLayer is 10.6-only -- roll our own. | 49 // CAGradientLayer is 10.6-only -- roll our own. |
| 46 @interface DarkGradientLayer : CALayer | 50 @interface DarkGradientLayer : CALayer |
| 47 - (void)drawInContext:(CGContextRef)context; | 51 - (void)drawInContext:(CGContextRef)context; |
| 48 @end | 52 @end |
| 49 | 53 |
| 50 @implementation DarkGradientLayer | 54 @implementation DarkGradientLayer |
| 51 - (void)drawInContext:(CGContextRef)context { | 55 - (void)drawInContext:(CGContextRef)context { |
| 52 base::mac::ScopedCFTypeRef<CGColorSpaceRef> grayColorSpace( | 56 base::mac::ScopedCFTypeRef<CGColorSpaceRef> grayColorSpace( |
| 53 CGColorSpaceCreateWithName(kCGColorSpaceGenericGray)); | 57 CGColorSpaceCreateWithName(kCGColorSpaceGenericGray)); |
| (...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 696 kTitleHeight); | 700 kTitleHeight); |
| 697 | 701 |
| 698 // Compute the big, pre-zoom thumbnail rect. | 702 // Compute the big, pre-zoom thumbnail rect. |
| 699 tiles_[i]->start_thumb_rect_.size = containing_rect.size; | 703 tiles_[i]->start_thumb_rect_.size = containing_rect.size; |
| 700 | 704 |
| 701 int big_x = col * (NSWidth(containing_rect) + big_padding_x); | 705 int big_x = col * (NSWidth(containing_rect) + big_padding_x); |
| 702 int big_y = row * (NSHeight(containing_rect) + big_padding_y); | 706 int big_y = row * (NSHeight(containing_rect) + big_padding_y); |
| 703 tiles_[i]->start_thumb_rect_.origin = NSMakePoint(big_x, -big_y); | 707 tiles_[i]->start_thumb_rect_.origin = NSMakePoint(big_x, -big_y); |
| 704 } | 708 } |
| 705 } | 709 } |
| 706 | |
| 707 // Go through last row and center it: | |
| 708 // X X X X | |
| 709 // X X X X | |
| 710 // X X | |
| 711 int last_row_empty_tiles_x = count_x() - last_row_count_x(); | |
| 712 CGFloat small_last_row_shift_x = | |
| 713 last_row_empty_tiles_x * (small_width + kSmallPaddingX) / 2; | |
| 714 CGFloat big_last_row_shift_x = | |
| 715 last_row_empty_tiles_x * (NSWidth(containing_rect) + big_padding_x) / 2; | |
| 716 for (int i = tile_count - last_row_count_x(); i < tile_count; ++i) { | |
| 717 tiles_[i]->thumb_rect_.origin.x += small_last_row_shift_x; | |
| 718 tiles_[i]->start_thumb_rect_.origin.x += big_last_row_shift_x; | |
| 719 tiles_[i]->favicon_rect_.origin.x += small_last_row_shift_x; | |
| 720 tiles_[i]->title_rect_.origin.x += small_last_row_shift_x; | |
| 721 } | |
| 722 } | 710 } |
| 723 | 711 |
| 724 void TileSet::set_selected_index(int index) { | 712 void TileSet::set_selected_index(int index) { |
| 725 CHECK_GE(index, 0); | 713 CHECK_GE(index, 0); |
| 726 CHECK_LT(index, static_cast<int>(tiles_.size())); | 714 CHECK_LT(index, static_cast<int>(tiles_.size())); |
| 727 selected_index_ = index; | 715 selected_index_ = index; |
| 728 } | 716 } |
| 729 | 717 |
| 730 // Given a |value| in [0, from_scale), map it into [0, to_scale) such that: | 718 // Given a |value| in [0, from_scale), map it into [0, to_scale) such that: |
| 731 // * [0, from_scale) ends up in the middle of [0, to_scale) if the latter is | 719 // * [0, from_scale) ends up in the middle of [0, to_scale) if the latter is |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 908 layer.opacity = to; | 896 layer.opacity = to; |
| 909 // Add the animation, overriding the implicit animation. | 897 // Add the animation, overriding the implicit animation. |
| 910 [layer addAnimation:animation forKey:@"opacity"]; | 898 [layer addAnimation:animation forKey:@"opacity"]; |
| 911 } | 899 } |
| 912 | 900 |
| 913 @interface TabposeWindow (Private) | 901 @interface TabposeWindow (Private) |
| 914 - (id)initForWindow:(NSWindow*)parent | 902 - (id)initForWindow:(NSWindow*)parent |
| 915 rect:(NSRect)rect | 903 rect:(NSRect)rect |
| 916 slomo:(BOOL)slomo | 904 slomo:(BOOL)slomo |
| 917 tabStripModel:(TabStripModel*)tabStripModel; | 905 tabStripModel:(TabStripModel*)tabStripModel; |
| 906 |
| 907 // Creates and initializes the CALayer in the background and all the CALayers |
| 908 // for the thumbnails, favicons, and titles. |
| 918 - (void)setUpLayersInSlomo:(BOOL)slomo; | 909 - (void)setUpLayersInSlomo:(BOOL)slomo; |
| 919 - (void)fadeAway:(BOOL)slomo; | 910 |
| 920 - (void)selectTileAtIndex:(int)newIndex; | 911 // Tells the browser to make the tab corresponding to currently selected |
| 912 // thumbnail the current tab and starts the tabpose exit animmation. |
| 913 - (void)fadeAwayInSlomo:(BOOL)slomo; |
| 914 |
| 915 // Returns the CALayer for the close button belonging to the thumbnail at |
| 916 // index |index|. |
| 917 - (CALayer*)closebuttonLayerAtIndex:(NSUInteger)index; |
| 918 |
| 919 // Updates the visibility of all closebutton layers. |
| 920 - (void)updateClosebuttonLayersVisibility; |
| 921 @end | 921 @end |
| 922 | 922 |
| 923 @implementation TabposeWindow | 923 @implementation TabposeWindow |
| 924 | 924 |
| 925 + (id)openTabposeFor:(NSWindow*)parent | 925 + (id)openTabposeFor:(NSWindow*)parent |
| 926 rect:(NSRect)rect | 926 rect:(NSRect)rect |
| 927 slomo:(BOOL)slomo | 927 slomo:(BOOL)slomo |
| 928 tabStripModel:(TabStripModel*)tabStripModel { | 928 tabStripModel:(TabStripModel*)tabStripModel { |
| 929 // Releases itself when closed. | 929 // Releases itself when closed. |
| 930 return [[TabposeWindow alloc] | 930 return [[TabposeWindow alloc] |
| 931 initForWindow:parent rect:rect slomo:slomo tabStripModel:tabStripModel]; | 931 initForWindow:parent rect:rect slomo:slomo tabStripModel:tabStripModel]; |
| 932 } | 932 } |
| 933 | 933 |
| 934 - (id)initForWindow:(NSWindow*)parent | 934 - (id)initForWindow:(NSWindow*)parent |
| 935 rect:(NSRect)rect | 935 rect:(NSRect)rect |
| 936 slomo:(BOOL)slomo | 936 slomo:(BOOL)slomo |
| 937 tabStripModel:(TabStripModel*)tabStripModel { | 937 tabStripModel:(TabStripModel*)tabStripModel { |
| 938 NSRect frame = [parent frame]; | 938 NSRect frame = [parent frame]; |
| 939 if ((self = [super initWithContentRect:frame | 939 if ((self = [super initWithContentRect:frame |
| 940 styleMask:NSBorderlessWindowMask | 940 styleMask:NSBorderlessWindowMask |
| 941 backing:NSBackingStoreBuffered | 941 backing:NSBackingStoreBuffered |
| 942 defer:NO])) { | 942 defer:NO])) { |
| 943 containingRect_ = rect; | 943 containingRect_ = rect; |
| 944 tabStripModel_ = tabStripModel; | 944 tabStripModel_ = tabStripModel; |
| 945 state_ = tabpose::kFadingIn; | 945 state_ = tabpose::kFadingIn; |
| 946 tileSet_.reset(new tabpose::TileSet); | 946 tileSet_.reset(new tabpose::TileSet); |
| 947 tabStripModelObserverBridge_.reset( | 947 tabStripModelObserverBridge_.reset( |
| 948 new TabStripModelObserverBridge(tabStripModel_, self)); | 948 new TabStripModelObserverBridge(tabStripModel_, self)); |
| 949 NSImage* nsCloseIcon = |
| 950 ResourceBundle::GetSharedInstance().GetNativeImageNamed( |
| 951 IDR_TABPOSE_CLOSE); |
| 952 closeIcon_.reset(base::mac::CopyNSImageToCGImage(nsCloseIcon)); |
| 949 [self setReleasedWhenClosed:YES]; | 953 [self setReleasedWhenClosed:YES]; |
| 950 [self setOpaque:NO]; | 954 [self setOpaque:NO]; |
| 951 [self setBackgroundColor:[NSColor clearColor]]; | 955 [self setBackgroundColor:[NSColor clearColor]]; |
| 952 [self setUpLayersInSlomo:slomo]; | 956 [self setUpLayersInSlomo:slomo]; |
| 953 [self setAcceptsMouseMovedEvents:YES]; | 957 [self setAcceptsMouseMovedEvents:YES]; |
| 954 [parent addChildWindow:self ordered:NSWindowAbove]; | 958 [parent addChildWindow:self ordered:NSWindowAbove]; |
| 955 [self makeKeyAndOrderFront:self]; | 959 [self makeKeyAndOrderFront:self]; |
| 956 } | 960 } |
| 957 return self; | 961 return self; |
| 958 } | 962 } |
| 959 | 963 |
| 960 - (CALayer*)selectedLayer { | 964 - (CALayer*)selectedLayer { |
| 961 return [allThumbnailLayers_ objectAtIndex:tileSet_->selected_index()]; | 965 return [allThumbnailLayers_ objectAtIndex:tileSet_->selected_index()]; |
| 962 } | 966 } |
| 963 | 967 |
| 964 - (void)selectTileAtIndex:(int)newIndex { | |
| 965 const tabpose::Tile& tile = tileSet_->tile_at(newIndex); | |
| 966 selectionHighlight_.frame = | |
| 967 NSRectToCGRect(NSInsetRect(tile.thumb_rect(), -5, -5)); | |
| 968 tileSet_->set_selected_index(newIndex); | |
| 969 } | |
| 970 | |
| 971 - (void)selectTileAtIndexWithoutAnimation:(int)newIndex { | 968 - (void)selectTileAtIndexWithoutAnimation:(int)newIndex { |
| 972 ScopedCAActionDisabler disabler; | 969 ScopedCAActionDisabler disabler; |
| 973 [self selectTileAtIndex:newIndex]; | 970 const tabpose::Tile& tile = tileSet_->tile_at(newIndex); |
| 971 selectionHighlight_.frame = |
| 972 NSRectToCGRect(NSInsetRect(tile.thumb_rect(), |
| 973 -kSelectionInset, -kSelectionInset)); |
| 974 tileSet_->set_selected_index(newIndex); |
| 975 |
| 976 [self updateClosebuttonLayersVisibility]; |
| 974 } | 977 } |
| 975 | 978 |
| 976 - (void)addLayersForTile:(tabpose::Tile&)tile | 979 - (void)addLayersForTile:(tabpose::Tile&)tile |
| 977 showZoom:(BOOL)showZoom | 980 showZoom:(BOOL)showZoom |
| 978 slomo:(BOOL)slomo | 981 slomo:(BOOL)slomo |
| 979 animationDelegate:(id)animationDelegate { | 982 animationDelegate:(id)animationDelegate { |
| 980 scoped_nsobject<CALayer> layer([[ThumbnailLayer alloc] | 983 scoped_nsobject<CALayer> layer([[ThumbnailLayer alloc] |
| 981 initWithTabContents:tile.tab_contents() | 984 initWithTabContents:tile.tab_contents() |
| 982 fullSize:tile.GetStartRectRelativeTo( | 985 fullSize:tile.GetStartRectRelativeTo( |
| 983 tileSet_->selected_tile()).size]); | 986 tileSet_->selected_tile()).size]); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 997 animationDelegate); | 1000 animationDelegate); |
| 998 } else { | 1001 } else { |
| 999 layer.get().frame = NSRectToCGRect(tile.thumb_rect()); | 1002 layer.get().frame = NSRectToCGRect(tile.thumb_rect()); |
| 1000 } | 1003 } |
| 1001 | 1004 |
| 1002 layer.get().shadowRadius = 10; | 1005 layer.get().shadowRadius = 10; |
| 1003 layer.get().shadowOffset = CGSizeMake(0, -10); | 1006 layer.get().shadowOffset = CGSizeMake(0, -10); |
| 1004 if (state_ == tabpose::kFadedIn) | 1007 if (state_ == tabpose::kFadedIn) |
| 1005 layer.get().shadowOpacity = 0.5; | 1008 layer.get().shadowOpacity = 0.5; |
| 1006 | 1009 |
| 1010 // Add a close button to the thumb layer. |
| 1011 CALayer* closeLayer = [CALayer layer]; |
| 1012 closeLayer.contents = reinterpret_cast<id>(closeIcon_.get()); |
| 1013 CGRect closeBounds = {}; |
| 1014 closeBounds.size.width = CGImageGetWidth(closeIcon_); |
| 1015 closeBounds.size.height = CGImageGetHeight(closeIcon_); |
| 1016 closeLayer.bounds = closeBounds; |
| 1017 closeLayer.hidden = YES; |
| 1018 |
| 1019 [closeLayer addConstraint: |
| 1020 [CAConstraint constraintWithAttribute:kCAConstraintMidX |
| 1021 relativeTo:@"superlayer" |
| 1022 attribute:kCAConstraintMinX]]; |
| 1023 [closeLayer addConstraint: |
| 1024 [CAConstraint constraintWithAttribute:kCAConstraintMidY |
| 1025 relativeTo:@"superlayer" |
| 1026 attribute:kCAConstraintMaxY]]; |
| 1027 |
| 1028 layer.get().layoutManager = [CAConstraintLayoutManager layoutManager]; |
| 1029 [layer.get() addSublayer:closeLayer]; |
| 1030 |
| 1007 [bgLayer_ addSublayer:layer]; | 1031 [bgLayer_ addSublayer:layer]; |
| 1008 [allThumbnailLayers_ addObject:layer]; | 1032 [allThumbnailLayers_ addObject:layer]; |
| 1009 | 1033 |
| 1010 // Favicon and title. | 1034 // Favicon and title. |
| 1011 NSFont* font = [NSFont systemFontOfSize:tile.title_font_size()]; | 1035 NSFont* font = [NSFont systemFontOfSize:tile.title_font_size()]; |
| 1012 tile.set_font_metrics([font ascender], -[font descender]); | 1036 tile.set_font_metrics([font ascender], -[font descender]); |
| 1013 | 1037 |
| 1014 NSImage* nsFavicon = gfx::SkBitmapToNSImage(tile.favicon()); | 1038 NSImage* nsFavicon = gfx::SkBitmapToNSImage(tile.favicon()); |
| 1015 // Either we don't have a valid favicon or there was some issue converting | 1039 // Either we don't have a valid favicon or there was some issue converting |
| 1016 // it from an SkBitmap. Either way, just show the default. | 1040 // it from an SkBitmap. Either way, just show the default. |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1193 NSString* characters = [event characters]; | 1217 NSString* characters = [event characters]; |
| 1194 if ([characters length] < 1) | 1218 if ([characters length] < 1) |
| 1195 return; | 1219 return; |
| 1196 | 1220 |
| 1197 unichar character = [characters characterAtIndex:0]; | 1221 unichar character = [characters characterAtIndex:0]; |
| 1198 switch (character) { | 1222 switch (character) { |
| 1199 case NSEnterCharacter: | 1223 case NSEnterCharacter: |
| 1200 case NSNewlineCharacter: | 1224 case NSNewlineCharacter: |
| 1201 case NSCarriageReturnCharacter: | 1225 case NSCarriageReturnCharacter: |
| 1202 case ' ': | 1226 case ' ': |
| 1203 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0]; | 1227 [self fadeAwayInSlomo:([event modifierFlags] & NSShiftKeyMask) != 0]; |
| 1204 break; | 1228 break; |
| 1205 case '\e': // Escape | 1229 case '\e': // Escape |
| 1206 tileSet_->set_selected_index(tabStripModel_->selected_index()); | 1230 tileSet_->set_selected_index(tabStripModel_->selected_index()); |
| 1207 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0]; | 1231 [self fadeAwayInSlomo:([event modifierFlags] & NSShiftKeyMask) != 0]; |
| 1208 break; | 1232 break; |
| 1209 } | 1233 } |
| 1210 } | 1234 } |
| 1211 | 1235 |
| 1212 // Handle keyboard events that contain cmd or ctrl. | 1236 // Handle keyboard events that contain cmd or ctrl. |
| 1213 - (BOOL)performKeyEquivalent:(NSEvent*)event { | 1237 - (BOOL)performKeyEquivalent:(NSEvent*)event { |
| 1214 if (state_ == tabpose::kFadingOut) | 1238 if (state_ == tabpose::kFadingOut) |
| 1215 return NO; | 1239 return NO; |
| 1216 NSString* characters = [event characters]; | 1240 NSString* characters = [event characters]; |
| 1217 if ([characters length] < 1) | 1241 if ([characters length] < 1) |
| 1218 return NO; | 1242 return NO; |
| 1219 unichar character = [characters characterAtIndex:0]; | 1243 unichar character = [characters characterAtIndex:0]; |
| 1220 if ([event modifierFlags] & NSCommandKeyMask) { | 1244 if ([event modifierFlags] & NSCommandKeyMask) { |
| 1221 if (character >= '1' && character <= '9') { | 1245 if (character >= '1' && character <= '9') { |
| 1222 int index = | 1246 int index = |
| 1223 character == '9' ? tabStripModel_->count() - 1 : character - '1'; | 1247 character == '9' ? tabStripModel_->count() - 1 : character - '1'; |
| 1224 if (index < tabStripModel_->count()) { | 1248 if (index < tabStripModel_->count()) { |
| 1225 tileSet_->set_selected_index(index); | 1249 tileSet_->set_selected_index(index); |
| 1226 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0]; | 1250 [self fadeAwayInSlomo:([event modifierFlags] & NSShiftKeyMask) != 0]; |
| 1227 return YES; | 1251 return YES; |
| 1228 } | 1252 } |
| 1229 } | 1253 } |
| 1230 } | 1254 } |
| 1231 return NO; | 1255 return NO; |
| 1232 } | 1256 } |
| 1233 | 1257 |
| 1234 -(void)selectTileFromMouseEvent:(NSEvent*)event { | 1258 - (void)flagsChanged:(NSEvent*)event { |
| 1259 showAllCloseLayers_ = ([event modifierFlags] & NSAlternateKeyMask) != 0; |
| 1260 [self updateClosebuttonLayersVisibility]; |
| 1261 } |
| 1262 |
| 1263 - (void)selectTileFromMouseEvent:(NSEvent*)event { |
| 1235 int newIndex = -1; | 1264 int newIndex = -1; |
| 1236 CGPoint p = NSPointToCGPoint([event locationInWindow]); | 1265 CGPoint p = NSPointToCGPoint([event locationInWindow]); |
| 1237 for (NSUInteger i = 0; i < [allThumbnailLayers_ count]; ++i) { | 1266 for (NSUInteger i = 0; i < [allThumbnailLayers_ count]; ++i) { |
| 1238 CALayer* layer = [allThumbnailLayers_ objectAtIndex:i]; | 1267 CALayer* layer = [allThumbnailLayers_ objectAtIndex:i]; |
| 1239 CGPoint lp = [layer convertPoint:p fromLayer:rootLayer_]; | 1268 CGPoint lp = [layer convertPoint:p fromLayer:rootLayer_]; |
| 1240 if ([static_cast<CALayer*>([layer presentationLayer]) containsPoint:lp]) | 1269 if ([static_cast<CALayer*>([layer presentationLayer]) containsPoint:lp]) |
| 1241 newIndex = i; | 1270 newIndex = i; |
| 1242 } | 1271 } |
| 1243 if (newIndex >= 0) | 1272 if (newIndex >= 0) |
| 1244 [self selectTileAtIndexWithoutAnimation:newIndex]; | 1273 [self selectTileAtIndexWithoutAnimation:newIndex]; |
| 1245 } | 1274 } |
| 1246 | 1275 |
| 1247 - (void)mouseMoved:(NSEvent*)event { | 1276 - (void)mouseMoved:(NSEvent*)event { |
| 1248 [self selectTileFromMouseEvent:event]; | 1277 [self selectTileFromMouseEvent:event]; |
| 1249 } | 1278 } |
| 1250 | 1279 |
| 1280 - (CALayer*)closebuttonLayerAtIndex:(NSUInteger)index { |
| 1281 CALayer* layer = [allThumbnailLayers_ objectAtIndex:index]; |
| 1282 return [[layer sublayers] objectAtIndex:0]; |
| 1283 } |
| 1284 |
| 1285 - (void)updateClosebuttonLayersVisibility { |
| 1286 for (NSUInteger i = 0; i < [allThumbnailLayers_ count]; ++i) { |
| 1287 CALayer* layer = [self closebuttonLayerAtIndex:i]; |
| 1288 BOOL isSelectedTile = static_cast<int>(i) == tileSet_->selected_index(); |
| 1289 BOOL isVisible = state_ == tabpose::kFadedIn && |
| 1290 (isSelectedTile || showAllCloseLayers_); |
| 1291 layer.hidden = !isVisible; |
| 1292 } |
| 1293 } |
| 1294 |
| 1251 - (void)mouseDown:(NSEvent*)event { | 1295 - (void)mouseDown:(NSEvent*)event { |
| 1252 // Just in case the user clicked without ever moving the mouse. | 1296 // Just in case the user clicked without ever moving the mouse. |
| 1253 [self selectTileFromMouseEvent:event]; | 1297 [self selectTileFromMouseEvent:event]; |
| 1254 | 1298 |
| 1255 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0]; | 1299 // If the click occurred in a close box, close that tab and don't do anything |
| 1300 // else. |
| 1301 CGPoint p = NSPointToCGPoint([event locationInWindow]); |
| 1302 for (NSUInteger i = 0; i < [allThumbnailLayers_ count]; ++i) { |
| 1303 CALayer* layer = [self closebuttonLayerAtIndex:i]; |
| 1304 CGPoint lp = [layer convertPoint:p fromLayer:rootLayer_]; |
| 1305 if ([static_cast<CALayer*>([layer presentationLayer]) containsPoint:lp] && |
| 1306 !layer.hidden) { |
| 1307 tabStripModel_->CloseTabContentsAt(i, |
| 1308 TabStripModel::CLOSE_USER_GESTURE | |
| 1309 TabStripModel::CLOSE_CREATE_HISTORICAL_TAB); |
| 1310 return; |
| 1311 } |
| 1312 } |
| 1313 |
| 1314 [self fadeAwayInSlomo:([event modifierFlags] & NSShiftKeyMask) != 0]; |
| 1256 } | 1315 } |
| 1257 | 1316 |
| 1258 - (void)swipeWithEvent:(NSEvent*)event { | 1317 - (void)swipeWithEvent:(NSEvent*)event { |
| 1259 if (abs([event deltaY]) > 0.5) // Swipe up or down. | 1318 if (abs([event deltaY]) > 0.5) // Swipe up or down. |
| 1260 [self fadeAway:([event modifierFlags] & NSShiftKeyMask) != 0]; | 1319 [self fadeAwayInSlomo:([event modifierFlags] & NSShiftKeyMask) != 0]; |
| 1261 } | 1320 } |
| 1262 | 1321 |
| 1263 - (void)close { | 1322 - (void)close { |
| 1264 // Prevent parent window from disappearing. | 1323 // Prevent parent window from disappearing. |
| 1265 [[self parentWindow] removeChildWindow:self]; | 1324 [[self parentWindow] removeChildWindow:self]; |
| 1266 | 1325 |
| 1267 // We're dealloc'd in an autorelease pool – by then the observer registry | 1326 // We're dealloc'd in an autorelease pool – by then the observer registry |
| 1268 // might be dead, so explicitly reset the observer now. | 1327 // might be dead, so explicitly reset the observer now. |
| 1269 tabStripModelObserverBridge_.reset(); | 1328 tabStripModelObserverBridge_.reset(); |
| 1270 | 1329 |
| 1271 [super close]; | 1330 [super close]; |
| 1272 } | 1331 } |
| 1273 | 1332 |
| 1274 - (void)commandDispatch:(id)sender { | 1333 - (void)commandDispatch:(id)sender { |
| 1275 if ([sender tag] == IDC_TABPOSE) | 1334 if ([sender tag] == IDC_TABPOSE) |
| 1276 [self fadeAway:NO]; | 1335 [self fadeAwayInSlomo:NO]; |
| 1277 } | 1336 } |
| 1278 | 1337 |
| 1279 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { | 1338 - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { |
| 1280 // Disable all browser-related menu items except the tab overview toggle. | 1339 // Disable all browser-related menu items except the tab overview toggle. |
| 1281 SEL action = [item action]; | 1340 SEL action = [item action]; |
| 1282 NSInteger tag = [item tag]; | 1341 NSInteger tag = [item tag]; |
| 1283 return action == @selector(commandDispatch:) && tag == IDC_TABPOSE; | 1342 return action == @selector(commandDispatch:) && tag == IDC_TABPOSE; |
| 1284 } | 1343 } |
| 1285 | 1344 |
| 1286 - (void)fadeAwayTileAtIndex:(int)index { | 1345 - (void)fadeAwayTileAtIndex:(int)index { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1322 titleToRect.origin.x += | 1381 titleToRect.origin.x += |
| 1323 NSWidth(titleRect) * scale * titleLayer.anchorPoint.x; | 1382 NSWidth(titleRect) * scale * titleLayer.anchorPoint.x; |
| 1324 titleToRect.origin.y += | 1383 titleToRect.origin.y += |
| 1325 NSHeight(titleRect) * scale * titleLayer.anchorPoint.y; | 1384 NSHeight(titleRect) * scale * titleLayer.anchorPoint.y; |
| 1326 titleLayer.position = NSPointToCGPoint(titleToRect.origin); | 1385 titleLayer.position = NSPointToCGPoint(titleToRect.origin); |
| 1327 [titleLayer setValue:[NSNumber numberWithDouble:scale] | 1386 [titleLayer setValue:[NSNumber numberWithDouble:scale] |
| 1328 forKeyPath:@"transform.scale"]; | 1387 forKeyPath:@"transform.scale"]; |
| 1329 titleLayer.opacity = 0; | 1388 titleLayer.opacity = 0; |
| 1330 } | 1389 } |
| 1331 | 1390 |
| 1332 - (void)fadeAway:(BOOL)slomo { | 1391 - (void)fadeAwayInSlomo:(BOOL)slomo { |
| 1333 if (state_ == tabpose::kFadingOut) | 1392 if (state_ == tabpose::kFadingOut) |
| 1334 return; | 1393 return; |
| 1335 | 1394 |
| 1336 state_ = tabpose::kFadingOut; | 1395 state_ = tabpose::kFadingOut; |
| 1337 [self setAcceptsMouseMovedEvents:NO]; | 1396 [self setAcceptsMouseMovedEvents:NO]; |
| 1338 | 1397 |
| 1339 // Select chosen tab. | 1398 // Select chosen tab. |
| 1340 if (tileSet_->selected_index() < tabStripModel_->count()) { | 1399 if (tileSet_->selected_index() < tabStripModel_->count()) { |
| 1341 tabStripModel_->SelectTabContentsAt(tileSet_->selected_index(), | 1400 tabStripModel_->SelectTabContentsAt(tileSet_->selected_index(), |
| 1342 /*user_gesture=*/true); | 1401 /*user_gesture=*/true); |
| 1343 } else { | 1402 } else { |
| 1344 DCHECK_EQ(tileSet_->selected_index(), 0); | 1403 DCHECK_EQ(tileSet_->selected_index(), 0); |
| 1345 } | 1404 } |
| 1346 | 1405 |
| 1347 { | 1406 { |
| 1348 ScopedCAActionDisabler disableCAActions; | 1407 ScopedCAActionDisabler disableCAActions; |
| 1349 | 1408 |
| 1350 // Move the selected layer on top of all other layers. | 1409 // Move the selected layer on top of all other layers. |
| 1351 [self selectedLayer].zPosition = 1; | 1410 [self selectedLayer].zPosition = 1; |
| 1352 | 1411 |
| 1353 selectionHighlight_.hidden = YES; | 1412 selectionHighlight_.hidden = YES; |
| 1354 // Running animations with shadows is slow, so turn shadows off before | 1413 // Running animations with shadows is slow, so turn shadows off before |
| 1355 // running the exit animation. | 1414 // running the exit animation. |
| 1356 for (CALayer* layer in allThumbnailLayers_.get()) | 1415 for (CALayer* layer in allThumbnailLayers_.get()) |
| 1357 layer.shadowOpacity = 0.0; | 1416 layer.shadowOpacity = 0.0; |
| 1417 |
| 1418 [self updateClosebuttonLayersVisibility]; |
| 1358 } | 1419 } |
| 1359 | 1420 |
| 1360 // Animate layers out, all in one transaction. | 1421 // Animate layers out, all in one transaction. |
| 1361 CGFloat duration = | 1422 CGFloat duration = |
| 1362 1.3 * kDefaultAnimationDuration * (slomo ? kSlomoFactor : 1); | 1423 1.3 * kDefaultAnimationDuration * (slomo ? kSlomoFactor : 1); |
| 1363 ScopedCAActionSetDuration durationSetter(duration); | 1424 ScopedCAActionSetDuration durationSetter(duration); |
| 1364 for (int i = 0; i < tabStripModel_->count(); ++i) | 1425 for (int i = 0; i < tabStripModel_->count(); ++i) |
| 1365 [self fadeAwayTileAtIndex:i]; | 1426 [self fadeAwayTileAtIndex:i]; |
| 1366 } | 1427 } |
| 1367 | 1428 |
| 1368 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished { | 1429 - (void)animationDidStop:(CAAnimation*)animation finished:(BOOL)finished { |
| 1369 NSString* animationId = [animation valueForKey:kAnimationIdKey]; | 1430 NSString* animationId = [animation valueForKey:kAnimationIdKey]; |
| 1370 if ([animationId isEqualToString:kAnimationIdFadeIn]) { | 1431 if ([animationId isEqualToString:kAnimationIdFadeIn]) { |
| 1371 if (finished && state_ == tabpose::kFadingIn) { | 1432 if (finished && state_ == tabpose::kFadingIn) { |
| 1372 // If the user clicks while the fade in animation is still running, | 1433 // If the user clicks while the fade in animation is still running, |
| 1373 // |state_| is already kFadingOut. In that case, don't do anything. | 1434 // |state_| is already kFadingOut. In that case, don't do anything. |
| 1374 state_ = tabpose::kFadedIn; | 1435 state_ = tabpose::kFadedIn; |
| 1375 | 1436 |
| 1376 selectionHighlight_.hidden = NO; | 1437 selectionHighlight_.hidden = NO; |
| 1377 | 1438 |
| 1378 // Running animations with shadows is slow, so turn shadows on only after | 1439 // Running animations with shadows is slow, so turn shadows on only after |
| 1379 // the animation is done. | 1440 // the animation is done. |
| 1380 ScopedCAActionDisabler disableCAActions; | 1441 ScopedCAActionDisabler disableCAActions; |
| 1381 for (CALayer* layer in allThumbnailLayers_.get()) | 1442 for (CALayer* layer in allThumbnailLayers_.get()) |
| 1382 layer.shadowOpacity = 0.5; | 1443 layer.shadowOpacity = 0.5; |
| 1444 |
| 1445 [self updateClosebuttonLayersVisibility]; |
| 1383 } | 1446 } |
| 1384 } else if ([animationId isEqualToString:kAnimationIdFadeOut]) { | 1447 } else if ([animationId isEqualToString:kAnimationIdFadeOut]) { |
| 1385 DCHECK_EQ(tabpose::kFadingOut, state_); | 1448 DCHECK_EQ(tabpose::kFadingOut, state_); |
| 1386 [self close]; | 1449 [self close]; |
| 1387 } | 1450 } |
| 1388 } | 1451 } |
| 1389 | 1452 |
| 1390 - (NSUInteger)thumbnailLayerCount { | 1453 - (NSUInteger)thumbnailLayerCount { |
| 1391 return [allThumbnailLayers_ count]; | 1454 return [allThumbnailLayers_ count]; |
| 1392 } | 1455 } |
| 1393 | 1456 |
| 1394 - (int)selectedIndex { | 1457 - (int)selectedIndex { |
| 1395 return tileSet_->selected_index(); | 1458 return tileSet_->selected_index(); |
| 1396 } | 1459 } |
| 1397 | 1460 |
| 1398 #pragma mark TabStripModelBridge | 1461 #pragma mark TabStripModelBridge |
| 1399 | 1462 |
| 1400 - (void)refreshLayerFramesAtIndex:(int)i { | 1463 - (void)refreshLayerFramesAtIndex:(int)i { |
| 1401 const tabpose::Tile& tile = tileSet_->tile_at(i); | 1464 const tabpose::Tile& tile = tileSet_->tile_at(i); |
| 1402 | 1465 |
| 1466 CALayer* thumbLayer = [allThumbnailLayers_ objectAtIndex:i]; |
| 1467 |
| 1468 if (i == tileSet_->selected_index()) { |
| 1469 AnimateCALayerFrameFromTo( |
| 1470 selectionHighlight_, |
| 1471 NSInsetRect(NSRectFromCGRect(thumbLayer.frame), |
| 1472 -kSelectionInset, -kSelectionInset), |
| 1473 NSInsetRect(tile.thumb_rect(), |
| 1474 -kSelectionInset, -kSelectionInset), |
| 1475 kObserverChangeAnimationDuration, |
| 1476 nil); |
| 1477 } |
| 1478 |
| 1479 // Repaint layer if necessary. |
| 1480 if (!NSEqualSizes(NSRectFromCGRect(thumbLayer.frame).size, |
| 1481 tile.thumb_rect().size)) { |
| 1482 [thumbLayer setNeedsDisplay]; |
| 1483 } |
| 1484 |
| 1485 // Use AnimateCALayerFrameFromTo() instead of just setting |frame| to let |
| 1486 // the animation match the selection animation -- |
| 1487 // |kCAMediaTimingFunctionDefault| is 10.6-only. |
| 1488 AnimateCALayerFrameFromTo( |
| 1489 thumbLayer, |
| 1490 NSRectFromCGRect(thumbLayer.frame), |
| 1491 tile.thumb_rect(), |
| 1492 kObserverChangeAnimationDuration, |
| 1493 nil); |
| 1494 |
| 1403 CALayer* faviconLayer = [allFaviconLayers_ objectAtIndex:i]; | 1495 CALayer* faviconLayer = [allFaviconLayers_ objectAtIndex:i]; |
| 1404 faviconLayer.frame = NSRectToCGRect(tile.favicon_rect()); | 1496 AnimateCALayerFrameFromTo( |
| 1497 faviconLayer, |
| 1498 NSRectFromCGRect(faviconLayer.frame), |
| 1499 tile.favicon_rect(), |
| 1500 kObserverChangeAnimationDuration, |
| 1501 nil); |
| 1502 |
| 1405 CALayer* titleLayer = [allTitleLayers_ objectAtIndex:i]; | 1503 CALayer* titleLayer = [allTitleLayers_ objectAtIndex:i]; |
| 1406 titleLayer.frame = NSRectToCGRect(tile.title_rect()); | 1504 AnimateCALayerFrameFromTo( |
| 1407 CALayer* thumbLayer = [allThumbnailLayers_ objectAtIndex:i]; | 1505 titleLayer, |
| 1408 thumbLayer.frame = NSRectToCGRect(tile.thumb_rect()); | 1506 NSRectFromCGRect(titleLayer.frame), |
| 1507 tile.title_rect(), |
| 1508 kObserverChangeAnimationDuration, |
| 1509 nil); |
| 1409 } | 1510 } |
| 1410 | 1511 |
| 1411 - (void)insertTabWithContents:(TabContentsWrapper*)contents | 1512 - (void)insertTabWithContents:(TabContentsWrapper*)contents |
| 1412 atIndex:(NSInteger)index | 1513 atIndex:(NSInteger)index |
| 1413 inForeground:(bool)inForeground { | 1514 inForeground:(bool)inForeground { |
| 1414 // This happens if you cmd-click a link and then immediately open tabpose | 1515 // This happens if you cmd-click a link and then immediately open tabpose |
| 1415 // on a slowish machine. | 1516 // on a slowish machine. |
| 1416 ScopedCAActionSetDuration durationSetter(kObserverChangeAnimationDuration); | 1517 ScopedCAActionSetDuration durationSetter(kObserverChangeAnimationDuration); |
| 1417 | 1518 |
| 1418 // Insert new layer and relayout. | 1519 // Insert new layer and relayout. |
| 1419 tileSet_->InsertTileAt(index, contents->tab_contents()); | 1520 tileSet_->InsertTileAt(index, contents->tab_contents()); |
| 1420 tileSet_->Layout(containingRect_); | 1521 tileSet_->Layout(containingRect_); |
| 1421 [self addLayersForTile:tileSet_->tile_at(index) | 1522 [self addLayersForTile:tileSet_->tile_at(index) |
| 1422 showZoom:NO | 1523 showZoom:NO |
| 1423 slomo:NO | 1524 slomo:NO |
| 1424 animationDelegate:nil]; | 1525 animationDelegate:nil]; |
| 1425 | 1526 |
| 1426 // Update old layers. | 1527 // Update old layers. |
| 1427 DCHECK_EQ(tabStripModel_->count(), | 1528 DCHECK_EQ(tabStripModel_->count(), |
| 1428 static_cast<int>([allThumbnailLayers_ count])); | 1529 static_cast<int>([allThumbnailLayers_ count])); |
| 1429 DCHECK_EQ(tabStripModel_->count(), | 1530 DCHECK_EQ(tabStripModel_->count(), |
| 1430 static_cast<int>([allTitleLayers_ count])); | 1531 static_cast<int>([allTitleLayers_ count])); |
| 1431 DCHECK_EQ(tabStripModel_->count(), | 1532 DCHECK_EQ(tabStripModel_->count(), |
| 1432 static_cast<int>([allFaviconLayers_ count])); | 1533 static_cast<int>([allFaviconLayers_ count])); |
| 1433 | 1534 |
| 1535 // Update selection. |
| 1536 int selectedIndex = tileSet_->selected_index(); |
| 1537 if (selectedIndex >= index) |
| 1538 selectedIndex++; |
| 1539 [self selectTileAtIndexWithoutAnimation:selectedIndex]; |
| 1540 |
| 1541 // Animate everything into its new place. |
| 1434 for (int i = 0; i < tabStripModel_->count(); ++i) { | 1542 for (int i = 0; i < tabStripModel_->count(); ++i) { |
| 1435 if (i == index) // The new layer. | 1543 if (i == index) // The new layer. |
| 1436 continue; | 1544 continue; |
| 1437 [self refreshLayerFramesAtIndex:i]; | 1545 [self refreshLayerFramesAtIndex:i]; |
| 1438 } | 1546 } |
| 1439 | |
| 1440 // Update selection. | |
| 1441 int selectedIndex = tileSet_->selected_index(); | |
| 1442 if (selectedIndex >= index) | |
| 1443 selectedIndex++; | |
| 1444 [self selectTileAtIndex:selectedIndex]; | |
| 1445 } | 1547 } |
| 1446 | 1548 |
| 1447 - (void)tabClosingWithContents:(TabContentsWrapper*)contents | 1549 - (void)tabClosingWithContents:(TabContentsWrapper*)contents |
| 1448 atIndex:(NSInteger)index { | 1550 atIndex:(NSInteger)index { |
| 1449 // We will also get a -tabDetachedWithContents:atIndex: notification for | 1551 // We will also get a -tabDetachedWithContents:atIndex: notification for |
| 1450 // closing tabs, so do nothing here. | 1552 // closing tabs, so do nothing here. |
| 1451 } | 1553 } |
| 1452 | 1554 |
| 1453 - (void)tabDetachedWithContents:(TabContentsWrapper*)contents | 1555 - (void)tabDetachedWithContents:(TabContentsWrapper*)contents |
| 1454 atIndex:(NSInteger)index { | 1556 atIndex:(NSInteger)index { |
| 1455 ScopedCAActionSetDuration durationSetter(kObserverChangeAnimationDuration); | 1557 ScopedCAActionSetDuration durationSetter(kObserverChangeAnimationDuration); |
| 1456 | 1558 |
| 1457 // Remove layer and relayout. | 1559 // Remove layer and relayout. |
| 1458 tileSet_->RemoveTileAt(index); | 1560 tileSet_->RemoveTileAt(index); |
| 1459 tileSet_->Layout(containingRect_); | 1561 tileSet_->Layout(containingRect_); |
| 1460 | 1562 |
| 1461 [[allThumbnailLayers_ objectAtIndex:index] removeFromSuperlayer]; | 1563 { |
| 1462 [allThumbnailLayers_ removeObjectAtIndex:index]; | 1564 ScopedCAActionDisabler disabler; |
| 1463 [[allTitleLayers_ objectAtIndex:index] removeFromSuperlayer]; | 1565 [[allThumbnailLayers_ objectAtIndex:index] removeFromSuperlayer]; |
| 1464 [allTitleLayers_ removeObjectAtIndex:index]; | 1566 [allThumbnailLayers_ removeObjectAtIndex:index]; |
| 1465 [[allFaviconLayers_ objectAtIndex:index] removeFromSuperlayer]; | 1567 [[allTitleLayers_ objectAtIndex:index] removeFromSuperlayer]; |
| 1466 [allFaviconLayers_ removeObjectAtIndex:index]; | 1568 [allTitleLayers_ removeObjectAtIndex:index]; |
| 1569 [[allFaviconLayers_ objectAtIndex:index] removeFromSuperlayer]; |
| 1570 [allFaviconLayers_ removeObjectAtIndex:index]; |
| 1571 } |
| 1467 | 1572 |
| 1468 // Update old layers. | 1573 // Update old layers. |
| 1469 DCHECK_EQ(tabStripModel_->count(), | 1574 DCHECK_EQ(tabStripModel_->count(), |
| 1470 static_cast<int>([allThumbnailLayers_ count])); | 1575 static_cast<int>([allThumbnailLayers_ count])); |
| 1471 DCHECK_EQ(tabStripModel_->count(), | 1576 DCHECK_EQ(tabStripModel_->count(), |
| 1472 static_cast<int>([allTitleLayers_ count])); | 1577 static_cast<int>([allTitleLayers_ count])); |
| 1473 DCHECK_EQ(tabStripModel_->count(), | 1578 DCHECK_EQ(tabStripModel_->count(), |
| 1474 static_cast<int>([allFaviconLayers_ count])); | 1579 static_cast<int>([allFaviconLayers_ count])); |
| 1475 | 1580 |
| 1476 if (tabStripModel_->count() == 0) | 1581 if (tabStripModel_->count() == 0) |
| 1477 [self close]; | 1582 [self close]; |
| 1478 | 1583 |
| 1584 // Update selection. |
| 1585 int selectedIndex = tileSet_->selected_index(); |
| 1586 if (selectedIndex > index || selectedIndex >= tabStripModel_->count()) |
| 1587 selectedIndex--; |
| 1588 if (selectedIndex >= 0) |
| 1589 [self selectTileAtIndexWithoutAnimation:selectedIndex]; |
| 1590 |
| 1591 // Animate everything into its new place. |
| 1479 for (int i = 0; i < tabStripModel_->count(); ++i) | 1592 for (int i = 0; i < tabStripModel_->count(); ++i) |
| 1480 [self refreshLayerFramesAtIndex:i]; | 1593 [self refreshLayerFramesAtIndex:i]; |
| 1481 | |
| 1482 // Update selection. | |
| 1483 int selectedIndex = tileSet_->selected_index(); | |
| 1484 if (selectedIndex >= index) | |
| 1485 selectedIndex--; | |
| 1486 if (selectedIndex >= 0) | |
| 1487 [self selectTileAtIndex:selectedIndex]; | |
| 1488 } | 1594 } |
| 1489 | 1595 |
| 1490 - (void)tabMovedWithContents:(TabContentsWrapper*)contents | 1596 - (void)tabMovedWithContents:(TabContentsWrapper*)contents |
| 1491 fromIndex:(NSInteger)from | 1597 fromIndex:(NSInteger)from |
| 1492 toIndex:(NSInteger)to { | 1598 toIndex:(NSInteger)to { |
| 1493 ScopedCAActionSetDuration durationSetter(kObserverChangeAnimationDuration); | 1599 ScopedCAActionSetDuration durationSetter(kObserverChangeAnimationDuration); |
| 1494 | 1600 |
| 1495 // Move tile from |from| to |to|. | 1601 // Move tile from |from| to |to|. |
| 1496 tileSet_->MoveTileFromTo(from, to); | 1602 tileSet_->MoveTileFromTo(from, to); |
| 1497 | 1603 |
| 1498 // Move corresponding layers from |from| to |to|. | 1604 // Move corresponding layers from |from| to |to|. |
| 1499 scoped_nsobject<CALayer> thumbLayer( | 1605 scoped_nsobject<CALayer> thumbLayer( |
| 1500 [[allThumbnailLayers_ objectAtIndex:from] retain]); | 1606 [[allThumbnailLayers_ objectAtIndex:from] retain]); |
| 1501 [allThumbnailLayers_ removeObjectAtIndex:from]; | 1607 [allThumbnailLayers_ removeObjectAtIndex:from]; |
| 1502 [allThumbnailLayers_ insertObject:thumbLayer.get() atIndex:to]; | 1608 [allThumbnailLayers_ insertObject:thumbLayer.get() atIndex:to]; |
| 1503 scoped_nsobject<CALayer> faviconLayer( | 1609 scoped_nsobject<CALayer> faviconLayer( |
| 1504 [[allFaviconLayers_ objectAtIndex:from] retain]); | 1610 [[allFaviconLayers_ objectAtIndex:from] retain]); |
| 1505 [allFaviconLayers_ removeObjectAtIndex:from]; | 1611 [allFaviconLayers_ removeObjectAtIndex:from]; |
| 1506 [allFaviconLayers_ insertObject:faviconLayer.get() atIndex:to]; | 1612 [allFaviconLayers_ insertObject:faviconLayer.get() atIndex:to]; |
| 1507 scoped_nsobject<CALayer> titleLayer( | 1613 scoped_nsobject<CALayer> titleLayer( |
| 1508 [[allTitleLayers_ objectAtIndex:from] retain]); | 1614 [[allTitleLayers_ objectAtIndex:from] retain]); |
| 1509 [allTitleLayers_ removeObjectAtIndex:from]; | 1615 [allTitleLayers_ removeObjectAtIndex:from]; |
| 1510 [allTitleLayers_ insertObject:titleLayer.get() atIndex:to]; | 1616 [allTitleLayers_ insertObject:titleLayer.get() atIndex:to]; |
| 1511 | 1617 |
| 1512 // Update frames of the layers. | |
| 1513 for (int i = std::min(from, to); i <= std::max(from, to); ++i) | |
| 1514 [self refreshLayerFramesAtIndex:i]; | |
| 1515 | |
| 1516 // Update selection. | 1618 // Update selection. |
| 1517 int selectedIndex = tileSet_->selected_index(); | 1619 int selectedIndex = tileSet_->selected_index(); |
| 1518 if (from == selectedIndex) | 1620 if (from == selectedIndex) |
| 1519 selectedIndex = to; | 1621 selectedIndex = to; |
| 1520 else if (from < selectedIndex && selectedIndex <= to) | 1622 else if (from < selectedIndex && selectedIndex <= to) |
| 1521 selectedIndex--; | 1623 selectedIndex--; |
| 1522 else if (to <= selectedIndex && selectedIndex < from) | 1624 else if (to <= selectedIndex && selectedIndex < from) |
| 1523 selectedIndex++; | 1625 selectedIndex++; |
| 1524 [self selectTileAtIndex:selectedIndex]; | 1626 [self selectTileAtIndexWithoutAnimation:selectedIndex]; |
| 1627 |
| 1628 // Update frames of the layers. |
| 1629 for (int i = std::min(from, to); i <= std::max(from, to); ++i) |
| 1630 [self refreshLayerFramesAtIndex:i]; |
| 1525 } | 1631 } |
| 1526 | 1632 |
| 1527 - (void)tabChangedWithContents:(TabContentsWrapper*)contents | 1633 - (void)tabChangedWithContents:(TabContentsWrapper*)contents |
| 1528 atIndex:(NSInteger)index | 1634 atIndex:(NSInteger)index |
| 1529 changeType:(TabStripModelObserver::TabChangeType)change { | 1635 changeType:(TabStripModelObserver::TabChangeType)change { |
| 1530 // Tell the window to update text, title, and thumb layers at |index| to get | 1636 // Tell the window to update text, title, and thumb layers at |index| to get |
| 1531 // their data from |contents|. |contents| can be different from the old | 1637 // their data from |contents|. |contents| can be different from the old |
| 1532 // contents at that index! | 1638 // contents at that index! |
| 1533 // While a tab is loading, this is unfortunately called quite often for | 1639 // While a tab is loading, this is unfortunately called quite often for |
| 1534 // both the "loading" and the "all" change types, so we don't really want to | 1640 // both the "loading" and the "all" change types, so we don't really want to |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1546 tile.set_tab_contents(contents->tab_contents()); | 1652 tile.set_tab_contents(contents->tab_contents()); |
| 1547 ThumbnailLayer* thumbLayer = [allThumbnailLayers_ objectAtIndex:index]; | 1653 ThumbnailLayer* thumbLayer = [allThumbnailLayers_ objectAtIndex:index]; |
| 1548 [thumbLayer setTabContents:contents->tab_contents()]; | 1654 [thumbLayer setTabContents:contents->tab_contents()]; |
| 1549 } | 1655 } |
| 1550 | 1656 |
| 1551 - (void)tabStripModelDeleted { | 1657 - (void)tabStripModelDeleted { |
| 1552 [self close]; | 1658 [self close]; |
| 1553 } | 1659 } |
| 1554 | 1660 |
| 1555 @end | 1661 @end |
| OLD | NEW |