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

Side by Side Diff: chrome/browser/cocoa/tab_strip_controller.mm

Issue 390014: Total guess fix for the bug.... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month 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 | « chrome/browser/cocoa/download_shelf_controller.mm ('k') | 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) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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/cocoa/tab_strip_controller.h" 5 #import "chrome/browser/cocoa/tab_strip_controller.h"
6 6
7 #import <QuartzCore/QuartzCore.h> 7 #import <QuartzCore/QuartzCore.h>
8 8
9 #include <limits> 9 #include <limits>
10 10
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 // view. 44 // view.
45 static const float kUseFullAvailableWidth = -1.0; 45 static const float kUseFullAvailableWidth = -1.0;
46 46
47 // Left-side indent for tab layout so tabs don't overlap with the window 47 // Left-side indent for tab layout so tabs don't overlap with the window
48 // controls. 48 // controls.
49 static const float kIndentLeavingSpaceForControls = 64.0; 49 static const float kIndentLeavingSpaceForControls = 64.0;
50 50
51 // Time (in seconds) in which tabs animate to their final position. 51 // Time (in seconds) in which tabs animate to their final position.
52 static const NSTimeInterval kAnimationDuration = 0.2; 52 static const NSTimeInterval kAnimationDuration = 0.2;
53 53
54 namespace {
55
56 // Helper class for doing NSAnimationContext calls that takes a bool to disable
57 // all the work. Useful for code that wants to conditionally animate.
58 class ScopedNSAnimationContextGroup {
59 public:
60 explicit ScopedNSAnimationContextGroup(bool animate)
61 : animate_(animate) {
62 if (animate_) {
63 [NSAnimationContext beginGrouping];
64 }
65 }
66
67 ~ScopedNSAnimationContextGroup() {
68 if (animate_) {
69 [NSAnimationContext endGrouping];
70 }
71 }
72
73 void SetCurrentContextDuration(NSTimeInterval duration) {
74 if (animate_) {
75 [[NSAnimationContext currentContext] gtm_setDuration:duration];
76 }
77 }
78
79 void SetCurrentContextShortestDuration() {
80 if (animate_) {
81 // The minimum representable time interval. This used to stop an
82 // in-progress animation as quickly as possible.
83 const NSTimeInterval kMinimumTimeInterval =
84 std::numeric_limits<NSTimeInterval>::min();
85 // Directly set the duration to be short, avoiding the Steve slowmotion
86 // ettect the gtm_setDuration: provides.
87 [[NSAnimationContext currentContext] setDuration:kMinimumTimeInterval];
88 }
89 }
90 private:
91 bool animate_;
92 DISALLOW_COPY_AND_ASSIGN(ScopedNSAnimationContextGroup);
93 };
94
95 } // namespace
96
54 @interface TabStripController(Private) 97 @interface TabStripController(Private)
55 - (void)installTrackingArea; 98 - (void)installTrackingArea;
56 - (void)addSubviewToPermanentList:(NSView*)aView; 99 - (void)addSubviewToPermanentList:(NSView*)aView;
57 - (void)regenerateSubviewList; 100 - (void)regenerateSubviewList;
58 - (NSInteger)indexForContentsView:(NSView*)view; 101 - (NSInteger)indexForContentsView:(NSView*)view;
59 - (void)updateFavIconForContents:(TabContents*)contents 102 - (void)updateFavIconForContents:(TabContents*)contents
60 atIndex:(NSInteger)index; 103 atIndex:(NSInteger)index;
61 - (void)layoutTabsWithAnimation:(BOOL)animate 104 - (void)layoutTabsWithAnimation:(BOOL)animate
62 regenerateSubviews:(BOOL)doUpdate; 105 regenerateSubviews:(BOOL)doUpdate;
63 - (void)animationDidStopForController:(TabController*)controller 106 - (void)animationDidStopForController:(TabController*)controller
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 // the ordering in the TabStripModel. This call isn't that expensive, though 567 // the ordering in the TabStripModel. This call isn't that expensive, though
525 // it is O(n) in the number of tabs. Tabs will animate to their new position 568 // it is O(n) in the number of tabs. Tabs will animate to their new position
526 // if the window is visible and |animate| is YES. 569 // if the window is visible and |animate| is YES.
527 // TODO(pinkerton): Handle drag placeholders via proxy objects, perhaps a 570 // TODO(pinkerton): Handle drag placeholders via proxy objects, perhaps a
528 // subclass of TabContentsController with everything stubbed out or by 571 // subclass of TabContentsController with everything stubbed out or by
529 // abstracting a base class interface. 572 // abstracting a base class interface.
530 // TODO(pinkerton): Note this doesn't do too well when the number of min-sized 573 // TODO(pinkerton): Note this doesn't do too well when the number of min-sized
531 // tabs would cause an overflow. 574 // tabs would cause an overflow.
532 - (void)layoutTabsWithAnimation:(BOOL)animate 575 - (void)layoutTabsWithAnimation:(BOOL)animate
533 regenerateSubviews:(BOOL)doUpdate { 576 regenerateSubviews:(BOOL)doUpdate {
577 DCHECK([NSThread isMainThread]);
534 if (![tabArray_ count]) 578 if (![tabArray_ count])
535 return; 579 return;
536 580
537 // The minimum representable time interval. This can be used as the value
538 // passed to +[NSAnimationContext setDuration:] to stop an in-progress
539 // animation as quickly as possible.
540 const NSTimeInterval kMinimumTimeInterval =
541 std::numeric_limits<NSTimeInterval>::min();
542 const float kTabOverlap = 20.0; 581 const float kTabOverlap = 20.0;
543 const float kNewTabButtonOffset = 8.0; 582 const float kNewTabButtonOffset = 8.0;
544 const float kMaxTabWidth = [TabController maxTabWidth]; 583 const float kMaxTabWidth = [TabController maxTabWidth];
545 const float kMinTabWidth = [TabController minTabWidth]; 584 const float kMinTabWidth = [TabController minTabWidth];
546 const float kMinSelectedTabWidth = [TabController minSelectedTabWidth]; 585 const float kMinSelectedTabWidth = [TabController minSelectedTabWidth];
547 586
548 NSRect enclosingRect = NSZeroRect; 587 NSRect enclosingRect = NSZeroRect;
549 [NSAnimationContext beginGrouping]; 588 ScopedNSAnimationContextGroup mainAnimationGroup(animate);
550 [[NSAnimationContext currentContext] gtm_setDuration:kAnimationDuration]; 589 mainAnimationGroup.SetCurrentContextDuration(kAnimationDuration);
551 590
552 // Update the current subviews and their z-order if requested. 591 // Update the current subviews and their z-order if requested.
553 if (doUpdate) 592 if (doUpdate)
554 [self regenerateSubviewList]; 593 [self regenerateSubviewList];
555 594
556 // Compute the base width of tabs given how much room we're allowed. We 595 // Compute the base width of tabs given how much room we're allowed. We
557 // may not be able to use the entire width if the user is quickly closing 596 // may not be able to use the entire width if the user is quickly closing
558 // tabs. 597 // tabs.
559 float availableWidth = 0; 598 float availableWidth = 0;
560 if ([self inRapidClosureMode]) { 599 if ([self inRapidClosureMode]) {
561 availableWidth = availableResizeWidth_; 600 availableWidth = availableResizeWidth_;
562 } else { 601 } else {
563 availableWidth = NSWidth([tabView_ frame]); 602 availableWidth = NSWidth([tabView_ frame]);
564 availableWidth -= NSWidth([newTabButton_ frame]) + kNewTabButtonOffset; 603 availableWidth -= NSWidth([newTabButton_ frame]) + kNewTabButtonOffset;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 // If the tab is hidden, we consider it a new tab. We make it visible 635 // If the tab is hidden, we consider it a new tab. We make it visible
597 // and animate it in. 636 // and animate it in.
598 BOOL newTab = [[tab view] isHidden]; 637 BOOL newTab = [[tab view] isHidden];
599 if (newTab) { 638 if (newTab) {
600 [[tab view] setHidden:NO]; 639 [[tab view] setHidden:NO];
601 } 640 }
602 641
603 if (isPlaceholder) { 642 if (isPlaceholder) {
604 // Move the current tab to the correct location instantly. 643 // Move the current tab to the correct location instantly.
605 // We need a duration or else it doesn't cancel an inflight animation. 644 // We need a duration or else it doesn't cancel an inflight animation.
606 [NSAnimationContext beginGrouping]; 645 ScopedNSAnimationContextGroup localAnimationGroup(animate);
607 [[NSAnimationContext currentContext] setDuration:kMinimumTimeInterval]; 646 localAnimationGroup.SetCurrentContextShortestDuration();
608 tabFrame.origin.x = placeholderFrame_.origin.x; 647 tabFrame.origin.x = placeholderFrame_.origin.x;
609 // TODO(alcor): reenable this 648 // TODO(alcor): reenable this
610 //tabFrame.size.height += 10.0 * placeholderStretchiness_; 649 //tabFrame.size.height += 10.0 * placeholderStretchiness_;
611 id target = animate ? [[tab view] animator] : [tab view]; 650 id target = animate ? [[tab view] animator] : [tab view];
612 [target setFrame:tabFrame]; 651 [target setFrame:tabFrame];
613 [NSAnimationContext endGrouping];
614 652
615 // Store the frame by identifier to aviod redundant calls to animator. 653 // Store the frame by identifier to aviod redundant calls to animator.
616 NSValue* identifier = [NSValue valueWithPointer:[tab view]]; 654 NSValue* identifier = [NSValue valueWithPointer:[tab view]];
617 [targetFrames_ setObject:[NSValue valueWithRect:tabFrame] 655 [targetFrames_ setObject:[NSValue valueWithRect:tabFrame]
618 forKey:identifier]; 656 forKey:identifier];
619 continue; 657 continue;
620 } else { 658 } else {
621 // If our left edge is to the left of the placeholder's left, but our mid 659 // If our left edge is to the left of the placeholder's left, but our mid
622 // is to the right of it we should slide over to make space for it. 660 // is to the right of it we should slide over to make space for it.
623 if (placeholderTab_ && !hasPlaceholderGap && NSMidX(tabFrame) > minX) { 661 if (placeholderTab_ && !hasPlaceholderGap && NSMidX(tabFrame) > minX) {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
692 imageName = @"newtab"; 730 imageName = @"newtab";
693 } 731 }
694 [newTabButton_ setImage:nsimage_cache::ImageNamed(imageName)]; 732 [newTabButton_ setImage:nsimage_cache::ImageNamed(imageName)];
695 733
696 // Move the new tab button into place. We want to animate the new tab 734 // Move the new tab button into place. We want to animate the new tab
697 // button if it's moving to the left (closing a tab), but not when it's 735 // button if it's moving to the left (closing a tab), but not when it's
698 // moving to the right (inserting a new tab). If moving right, we need 736 // moving to the right (inserting a new tab). If moving right, we need
699 // to use a very small duration to make sure we cancel any in-flight 737 // to use a very small duration to make sure we cancel any in-flight
700 // animation to the left. 738 // animation to the left.
701 if (visible && animate) { 739 if (visible && animate) {
702 [NSAnimationContext beginGrouping]; 740 ScopedNSAnimationContextGroup localAnimationGroup(true);
703 BOOL movingLeft = NSMinX(newTabNewFrame) < NSMinX(newTabTargetFrame_); 741 BOOL movingLeft = NSMinX(newTabNewFrame) < NSMinX(newTabTargetFrame_);
704 if (!movingLeft) { 742 if (!movingLeft) {
705 [[NSAnimationContext currentContext] 743 localAnimationGroup.SetCurrentContextShortestDuration();
706 setDuration:kMinimumTimeInterval];
707 } 744 }
708 [[newTabButton_ animator] setFrame:newTabNewFrame]; 745 [[newTabButton_ animator] setFrame:newTabNewFrame];
709 newTabTargetFrame_ = newTabNewFrame; 746 newTabTargetFrame_ = newTabNewFrame;
710 [NSAnimationContext endGrouping];
711 } else { 747 } else {
712 [newTabButton_ setFrame:newTabNewFrame]; 748 [newTabButton_ setFrame:newTabNewFrame];
713 newTabTargetFrame_ = newTabNewFrame; 749 newTabTargetFrame_ = newTabNewFrame;
714 } 750 }
715 } 751 }
716 } 752 }
717 753
718 [NSAnimationContext endGrouping];
719 [dragBlockingView_ setFrame:enclosingRect]; 754 [dragBlockingView_ setFrame:enclosingRect];
720 755
721 // Mark that we've successfully completed layout of at least one tab. 756 // Mark that we've successfully completed layout of at least one tab.
722 initialLayoutComplete_ = YES; 757 initialLayoutComplete_ = YES;
723 } 758 }
724 759
725 // When we're told to layout from the public API we usually want to animate, 760 // When we're told to layout from the public API we usually want to animate,
726 // except when it's the first time. 761 // except when it's the first time.
727 - (void)layoutTabs { 762 - (void)layoutTabs {
728 [self layoutTabsWithAnimation:initialLayoutComplete_ regenerateSubviews:YES]; 763 [self layoutTabsWithAnimation:initialLayoutComplete_ regenerateSubviews:YES];
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
880 - (void)animationDidStopForController:(TabController*)controller 915 - (void)animationDidStopForController:(TabController*)controller
881 finished:(BOOL)finished { 916 finished:(BOOL)finished {
882 [closingControllers_ removeObject:controller]; 917 [closingControllers_ removeObject:controller];
883 [self removeTab:controller]; 918 [self removeTab:controller];
884 } 919 }
885 920
886 // Save off which TabController is closing and tell its view's animator 921 // Save off which TabController is closing and tell its view's animator
887 // where to move the tab to. Registers a delegate to call back when the 922 // where to move the tab to. Registers a delegate to call back when the
888 // animation is complete in order to remove the tab from the model. 923 // animation is complete in order to remove the tab from the model.
889 - (void)startClosingTabWithAnimation:(TabController*)closingTab { 924 - (void)startClosingTabWithAnimation:(TabController*)closingTab {
925 DCHECK([NSThread isMainThread]);
890 // Save off the controller into the set of animating tabs. This alerts 926 // Save off the controller into the set of animating tabs. This alerts
891 // the layout method to not do anything with it and allows us to correctly 927 // the layout method to not do anything with it and allows us to correctly
892 // calculate offsets when working with indices into the model. 928 // calculate offsets when working with indices into the model.
893 [closingControllers_ addObject:closingTab]; 929 [closingControllers_ addObject:closingTab];
894 930
895 // Mark the tab as closing. This prevents it from generating any drags or 931 // Mark the tab as closing. This prevents it from generating any drags or
896 // selections while it's animating closed. 932 // selections while it's animating closed.
897 [(TabView*)[closingTab view] setIsClosing:YES]; 933 [(TabView*)[closingTab view] setIsClosing:YES];
898 934
899 // Register delegate (owned by the animation system). 935 // Register delegate (owned by the animation system).
900 NSView* tabView = [closingTab view]; 936 NSView* tabView = [closingTab view];
901 CAAnimation* animation = [[tabView animationForKey:@"frameOrigin"] copy]; 937 CAAnimation* animation = [[tabView animationForKey:@"frameOrigin"] copy];
902 [animation autorelease]; 938 [animation autorelease];
903 scoped_nsobject<TabCloseAnimationDelegate> delegate( 939 scoped_nsobject<TabCloseAnimationDelegate> delegate(
904 [[TabCloseAnimationDelegate alloc] initWithTabStrip:self 940 [[TabCloseAnimationDelegate alloc] initWithTabStrip:self
905 tabController:closingTab]); 941 tabController:closingTab]);
906 [animation setDelegate:delegate.get()]; // Retains delegate. 942 [animation setDelegate:delegate.get()]; // Retains delegate.
907 NSMutableDictionary* animationDictionary = 943 NSMutableDictionary* animationDictionary =
908 [NSMutableDictionary dictionaryWithDictionary:[tabView animations]]; 944 [NSMutableDictionary dictionaryWithDictionary:[tabView animations]];
909 [animationDictionary setObject:animation forKey:@"frameOrigin"]; 945 [animationDictionary setObject:animation forKey:@"frameOrigin"];
910 [tabView setAnimations:animationDictionary]; 946 [tabView setAnimations:animationDictionary];
911 947
912 // Periscope down! Animate the tab. 948 // Periscope down! Animate the tab.
913 NSRect newFrame = [tabView frame]; 949 NSRect newFrame = [tabView frame];
914 newFrame = NSOffsetRect(newFrame, 0, -newFrame.size.height); 950 newFrame = NSOffsetRect(newFrame, 0, -newFrame.size.height);
915 [NSAnimationContext beginGrouping]; 951 ScopedNSAnimationContextGroup animationGroup(true);
916 [[NSAnimationContext currentContext] gtm_setDuration:kAnimationDuration]; 952 animationGroup.SetCurrentContextDuration(kAnimationDuration);
917 [[tabView animator] setFrame:newFrame]; 953 [[tabView animator] setFrame:newFrame];
918 [NSAnimationContext endGrouping];
919 } 954 }
920 955
921 // Called when a notification is received from the model that the given tab 956 // Called when a notification is received from the model that the given tab
922 // has gone away. Start an animation then force a layout to put everything 957 // has gone away. Start an animation then force a layout to put everything
923 // in motion. 958 // in motion.
924 - (void)tabDetachedWithContents:(TabContents*)contents 959 - (void)tabDetachedWithContents:(TabContents*)contents
925 atIndex:(NSInteger)modelIndex { 960 atIndex:(NSInteger)modelIndex {
926 // Take closing tabs into account. 961 // Take closing tabs into account.
927 NSInteger index = [self indexFromModelIndex:modelIndex]; 962 NSInteger index = [self indexFromModelIndex:modelIndex];
928 963
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 NSInteger index = [self indexFromModelIndex:modelIndex]; 1331 NSInteger index = [self indexFromModelIndex:modelIndex];
1297 BrowserWindowController* controller = 1332 BrowserWindowController* controller =
1298 (BrowserWindowController*)[[switchView_ window] windowController]; 1333 (BrowserWindowController*)[[switchView_ window] windowController];
1299 DCHECK(index >= 0); 1334 DCHECK(index >= 0);
1300 if (index >= 0) { 1335 if (index >= 0) {
1301 [controller setTab:[self viewAtIndex:index] isDraggable:YES]; 1336 [controller setTab:[self viewAtIndex:index] isDraggable:YES];
1302 } 1337 }
1303 } 1338 }
1304 1339
1305 @end 1340 @end
OLDNEW
« no previous file with comments | « chrome/browser/cocoa/download_shelf_controller.mm ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698