OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/tabs/tab_strip_controller.h" | 5 #import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h" |
6 | 6 |
7 #import <QuartzCore/QuartzCore.h> | 7 #import <QuartzCore/QuartzCore.h> |
8 | 8 |
9 #include <cmath> | |
9 #include <limits> | 10 #include <limits> |
10 #include <string> | 11 #include <string> |
11 | 12 |
12 #include "base/command_line.h" | 13 #include "base/command_line.h" |
13 #include "base/mac/mac_util.h" | 14 #include "base/mac/mac_util.h" |
14 #include "base/sys_string_conversions.h" | 15 #include "base/sys_string_conversions.h" |
15 #include "chrome/app/chrome_command_ids.h" | 16 #include "chrome/app/chrome_command_ids.h" |
16 #include "chrome/browser/autocomplete/autocomplete.h" | 17 #include "chrome/browser/autocomplete/autocomplete.h" |
17 #include "chrome/browser/autocomplete/autocomplete_classifier.h" | 18 #include "chrome/browser/autocomplete/autocomplete_classifier.h" |
18 #include "chrome/browser/autocomplete/autocomplete_match.h" | 19 #include "chrome/browser/autocomplete/autocomplete_match.h" |
(...skipping 825 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
844 // This may be negative, but that's okay (taken care of by |MAX()| when | 845 // This may be negative, but that's okay (taken care of by |MAX()| when |
845 // calculating tab sizes). "mini" tabs in horizontal mode just get a special | 846 // calculating tab sizes). "mini" tabs in horizontal mode just get a special |
846 // section, they don't change size. | 847 // section, they don't change size. |
847 CGFloat availableSpaceForNonMini = availableSpace; | 848 CGFloat availableSpaceForNonMini = availableSpace; |
848 availableSpaceForNonMini -= | 849 availableSpaceForNonMini -= |
849 [self numberOfOpenMiniTabs] * (kMiniTabWidth - kTabOverlap); | 850 [self numberOfOpenMiniTabs] * (kMiniTabWidth - kTabOverlap); |
850 | 851 |
851 // Initialize |nonMiniTabWidth| in case there aren't any non-mini-tabs; this | 852 // Initialize |nonMiniTabWidth| in case there aren't any non-mini-tabs; this |
852 // value shouldn't actually be used. | 853 // value shouldn't actually be used. |
853 CGFloat nonMiniTabWidth = kMaxTabWidth; | 854 CGFloat nonMiniTabWidth = kMaxTabWidth; |
855 CGFloat nonMiniTabWidthFraction = 0; | |
854 const NSInteger numberOfOpenNonMiniTabs = [self numberOfOpenNonMiniTabs]; | 856 const NSInteger numberOfOpenNonMiniTabs = [self numberOfOpenNonMiniTabs]; |
855 if (numberOfOpenNonMiniTabs) { | 857 if (numberOfOpenNonMiniTabs) { |
856 // Find the width of a non-mini-tab. This only applies to horizontal | 858 // Find the width of a non-mini-tab. This only applies to horizontal |
857 // mode. Add in the amount we "get back" from the tabs overlapping. | 859 // mode. Add in the amount we "get back" from the tabs overlapping. |
858 availableSpaceForNonMini += (numberOfOpenNonMiniTabs - 1) * kTabOverlap; | 860 availableSpaceForNonMini += (numberOfOpenNonMiniTabs - 1) * kTabOverlap; |
859 | 861 |
860 // Divide up the space between the non-mini-tabs. | 862 // Divide up the space between the non-mini-tabs. |
861 nonMiniTabWidth = availableSpaceForNonMini / numberOfOpenNonMiniTabs; | 863 nonMiniTabWidth = availableSpaceForNonMini / numberOfOpenNonMiniTabs; |
862 | 864 |
863 // Clamp the width between the max and min. | 865 // Clamp the width between the max and min. |
864 nonMiniTabWidth = MAX(MIN(nonMiniTabWidth, kMaxTabWidth), kMinTabWidth); | 866 nonMiniTabWidth = MAX(MIN(nonMiniTabWidth, kMaxTabWidth), kMinTabWidth); |
867 | |
868 // Separate integral and fractional parts. | |
869 CGFloat integralPart = std::floor(nonMiniTabWidth); | |
870 nonMiniTabWidthFraction = nonMiniTabWidth - integralPart; | |
871 nonMiniTabWidth = integralPart; | |
865 } | 872 } |
866 | 873 |
867 BOOL visible = [[tabStripView_ window] isVisible]; | 874 BOOL visible = [[tabStripView_ window] isVisible]; |
868 | 875 |
869 CGFloat offset = [self leftIndentForControls]; | 876 CGFloat offset = [self leftIndentForControls]; |
870 bool hasPlaceholderGap = false; | 877 bool hasPlaceholderGap = false; |
871 // Whether or not the last tab processed by the loop was a mini tab. | 878 // Whether or not the last tab processed by the loop was a mini tab. |
872 BOOL isLastTabMini = NO; | 879 BOOL isLastTabMini = NO; |
880 CGFloat tabWidthAccumulatedFraction = 0; | |
881 NSInteger laidOutNonMiniTabs = 0; | |
873 for (TabController* tab in tabArray_.get()) { | 882 for (TabController* tab in tabArray_.get()) { |
874 // Ignore a tab that is going through a close animation. | 883 // Ignore a tab that is going through a close animation. |
875 if ([closingControllers_ containsObject:tab]) | 884 if ([closingControllers_ containsObject:tab]) |
876 continue; | 885 continue; |
877 | 886 |
878 BOOL isPlaceholder = [[tab view] isEqual:placeholderTab_]; | 887 BOOL isPlaceholder = [[tab view] isEqual:placeholderTab_]; |
879 NSRect tabFrame = [[tab view] frame]; | 888 NSRect tabFrame = [[tab view] frame]; |
880 tabFrame.size.height = [[self class] defaultTabHeight] + 1; | 889 tabFrame.size.height = [[self class] defaultTabHeight] + 1; |
881 tabFrame.origin.y = 0; | 890 tabFrame.origin.y = 0; |
882 tabFrame.origin.x = offset; | 891 tabFrame.origin.x = offset; |
(...skipping 30 matching lines...) Expand all Loading... | |
913 hasPlaceholderGap = true; | 922 hasPlaceholderGap = true; |
914 offset += NSWidth(placeholderFrame_); | 923 offset += NSWidth(placeholderFrame_); |
915 offset -= kTabOverlap; | 924 offset -= kTabOverlap; |
916 tabFrame.origin.x = offset; | 925 tabFrame.origin.x = offset; |
917 } | 926 } |
918 } | 927 } |
919 | 928 |
920 // Set the width. Selected tabs are slightly wider when things get really | 929 // Set the width. Selected tabs are slightly wider when things get really |
921 // small and thus we enforce a different minimum width. | 930 // small and thus we enforce a different minimum width. |
922 BOOL isMini = [tab mini]; | 931 BOOL isMini = [tab mini]; |
923 tabFrame.size.width = isMini ? | 932 if (isMini) { |
924 ([tab app] ? kAppTabWidth : kMiniTabWidth) : nonMiniTabWidth; | 933 tabFrame.size.width = [tab app] ? kAppTabWidth : kMiniTabWidth; |
934 } else { | |
935 tabFrame.size.width = nonMiniTabWidth; | |
936 tabWidthAccumulatedFraction += nonMiniTabWidthFraction; | |
937 | |
938 if (tabWidthAccumulatedFraction >= 1.0) { | |
Robert Sesek
2011/12/13 18:46:38
I'd maybe name and discuss the algorithm you're us
| |
939 ++tabFrame.size.width; | |
940 --tabWidthAccumulatedFraction; | |
941 } | |
942 | |
943 // In case of rounding error, give any left over pixels to the last tab. | |
Robert Sesek
2011/12/13 18:46:38
Why is this a "rounding error"?
Avi (use Gerrit)
2011/12/13 19:15:01
Assume that we have 181px to distribute across thr
Robert Sesek
2011/12/13 19:49:56
Got to love floating point math.
| |
944 if (laidOutNonMiniTabs == numberOfOpenNonMiniTabs - 1 && | |
945 tabWidthAccumulatedFraction > 0.5) { | |
946 ++tabFrame.size.width; | |
947 } | |
948 | |
949 ++laidOutNonMiniTabs; | |
950 } | |
951 | |
925 if ([tab selected]) | 952 if ([tab selected]) |
926 tabFrame.size.width = MAX(tabFrame.size.width, kMinSelectedTabWidth); | 953 tabFrame.size.width = MAX(tabFrame.size.width, kMinSelectedTabWidth); |
927 | 954 |
928 // If this is the first non-mini tab, then add a bit of spacing between this | 955 // If this is the first non-mini tab, then add a bit of spacing between this |
929 // and the last mini tab. | 956 // and the last mini tab. |
930 if (!isMini && isLastTabMini) { | 957 if (!isMini && isLastTabMini) { |
931 offset += kLastMiniTabSpacing; | 958 offset += kLastMiniTabSpacing; |
932 tabFrame.origin.x = offset; | 959 tabFrame.origin.x = offset; |
933 } | 960 } |
934 isLastTabMini = isMini; | 961 isLastTabMini = isMini; |
(...skipping 1082 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2017 NSInteger index = [self indexFromModelIndex:modelIndex]; | 2044 NSInteger index = [self indexFromModelIndex:modelIndex]; |
2018 BrowserWindowController* controller = | 2045 BrowserWindowController* controller = |
2019 (BrowserWindowController*)[[switchView_ window] windowController]; | 2046 (BrowserWindowController*)[[switchView_ window] windowController]; |
2020 DCHECK(index >= 0); | 2047 DCHECK(index >= 0); |
2021 if (index >= 0) { | 2048 if (index >= 0) { |
2022 [controller setTab:[self viewAtIndex:index] isDraggable:YES]; | 2049 [controller setTab:[self viewAtIndex:index] isDraggable:YES]; |
2023 } | 2050 } |
2024 } | 2051 } |
2025 | 2052 |
2026 @end | 2053 @end |
OLD | NEW |