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

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

Issue 8921035: Lay out tabs to have integer widths. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 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) 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
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
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
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
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