Chromium Code Reviews| 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 |