Bug 418359 - Start drag of background tabs with one click. Patch by Stuart Morgan <stuart.morgan+bugzilla@gmail.com>, r=murph, sr=pink

git-svn-id: svn://10.0.0.236/trunk@255533 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
alqahira%ardisson.org 2008-12-16 03:39:25 +00:00
parent 701218f5df
commit 3ca4e997f1
5 changed files with 81 additions and 41 deletions

View File

@ -80,8 +80,11 @@
NSMutableArray* mCurrentlySlidingTabs; // strong
}
// destroy the tab bar and recreate it from the tabview
-(void)rebuildTabBar;
// Should be called when the number, order, or visible range of tabs is changed.
- (void)tabStructureChanged;
// Should be called when only the selected tab has changed.
- (void)tabSelectionChanged;
// return the height the tab bar should be
-(float)tabBarHeight;
-(BrowserTabViewItem*)tabViewItemAtPoint:(NSPoint)location;

View File

@ -56,9 +56,17 @@
#import "NSView+Utils.h"
#import "CHSlidingViewAnimation.h"
enum ETabRebuildReason {
kTabRebuildForSelectionChange,
kTabRebuildForStructureChange
};
@interface BrowserTabBarView(TabBarViewPrivate)
-(void)layoutButtonsPreservingVisibility:(BOOL)preserveVisibility;
-(void)rebuildTabBar:(ETabRebuildReason)reason;
-(void)layoutButtonsPreservingVisibility:(BOOL)preserveVisibility
forChange:(ETabRebuildReason)reason;
-(void)loadImages;
-(void)drawTabBarBackgroundInRect:(NSRect)rect withActiveTabRect:(NSRect)tabRect;
-(void)drawTabBarBackgroundHiliteRectInRect:(NSRect)rect;
@ -113,7 +121,7 @@ const int kEscapeKeyCode = 53;
if (self) {
mOverflowTabs = NO;
// this will not likely have any result here
[self rebuildTabBar];
[self tabStructureChanged];
[self registerForDraggedTypes:[NSArray arrayWithObjects: kCaminoBookmarkListPBoardType,
kWebURLsWithTitlesPboardType,
NSStringPboardType,
@ -133,7 +141,7 @@ const int kEscapeKeyCode = 53;
// start off with the tabs hidden, and allow our controller to show or hide as appropriate.
[self setVisible:NO];
// this needs to be called again since our tabview should be non-nil now
[self rebuildTabBar];
[self tabStructureChanged];
// When background tabs are finished sliding around the dragging one, we need to perform
// certain actions like updating the divider images.
[[NSNotificationCenter defaultCenter] addObserver:self
@ -199,7 +207,7 @@ const int kEscapeKeyCode = 53;
[super setFrame:frameRect];
// tab buttons probably need to be resized if the frame changes
[self unregisterTabButtonsForTracking];
[self layoutButtonsPreservingVisibility:YES];
[self layoutButtonsPreservingVisibility:YES forChange:kTabRebuildForStructureChange];
[self registerTabButtonsForTracking];
}
@ -384,9 +392,19 @@ const int kEscapeKeyCode = 53;
mButtonDividerImage = [[NSImage imageNamed:@"tab_button_divider"] retain];
}
- (void)tabStructureChanged
{
[self rebuildTabBar:kTabRebuildForStructureChange];
}
- (void)tabSelectionChanged
{
[self rebuildTabBar:kTabRebuildForSelectionChange];
}
// construct the tab bar based on the current state of mTabView;
// should be called when tabs are first shown.
-(void)rebuildTabBar
-(void)rebuildTabBar:(ETabRebuildReason)reason;
{
if ([self tabIsCurrentlyDragging])
return;
@ -394,7 +412,7 @@ const int kEscapeKeyCode = 53;
[self loadImages];
[self unregisterTabButtonsForTracking];
[self layoutButtonsPreservingVisibility:NO];
[self layoutButtonsPreservingVisibility:NO forChange:reason];
[self registerTabButtonsForTracking];
[self updateKeyViewLoop];
}
@ -506,11 +524,13 @@ const int kEscapeKeyCode = 53;
// remain visible in the new layout if it was previously. If it is NO, then the
// tab may or may not stay visible in the new layout.
-(void)layoutButtonsPreservingVisibility:(BOOL)preserveVisibility
forChange:(ETabRebuildReason)reason
{
// before changing anything, get information about the current state
BrowserTabViewItem* selectedTab = (BrowserTabViewItem*)[mTabView selectedTabViewItem];
int selectedTabIndex = selectedTab ? [mTabView indexOfTabViewItem:selectedTab]
: -1;
int oldLeftmostTabIndex = mLeftMostVisibleTabIndex;
// if we aren't currently overflowing, or we were asked to preserve the
// visibility of the current tab, make sure the current tab stays visible.
BOOL keepCurrentTabVisible = !mOverflowTabs ||
@ -527,7 +547,7 @@ const int kEscapeKeyCode = 53;
mNumberOfVisibleTabs = (int)floor(widthOfTabBar / kMinTabWidth);
widthOfATab = floor(widthOfTabBar / mNumberOfVisibleTabs);
if (mNumberOfVisibleTabs + mLeftMostVisibleTabIndex > numberOfTabs)
[self setLeftmostVisibleTabIndex:(numberOfTabs - mNumberOfVisibleTabs)];
[self scrollTabIndexToVisible:(numberOfTabs - mNumberOfVisibleTabs)];
if (keepCurrentTabVisible && selectedTab)
[self scrollTabIndexToVisible:selectedTabIndex];
}
@ -537,14 +557,23 @@ const int kEscapeKeyCode = 53;
widthOfATab = (widthOfATab > kMaxTabWidth ? kMaxTabWidth : widthOfATab);
}
[self removeAllSubviews];
[self setOverflowButtonsVisible:mOverflowTabs];
// If we are doing nothing but changing the selection (without changing the
// visible tabs as a result), we don't need to do a full reconstruction.
BOOL needsFullRebuild = (reason == kTabRebuildForStructureChange) ||
(mLeftMostVisibleTabIndex != oldLeftmostTabIndex);
NSRect tabsRect = [self tabsRect];
float extraWidth = 0.0;
if (widthOfATab < kMaxTabWidth)
extraWidth = NSWidth(tabsRect) - widthOfATab * mNumberOfVisibleTabs;
float nextTabXOrigin = NSMinX(tabsRect);
float nextTabXOrigin = 0.0;
if (needsFullRebuild) {
[self removeAllSubviews];
[self setOverflowButtonsVisible:mOverflowTabs];
NSRect tabsRect = [self tabsRect];
if (widthOfATab < kMaxTabWidth)
extraWidth = NSWidth(tabsRect) - widthOfATab * mNumberOfVisibleTabs;
nextTabXOrigin = NSMinX(tabsRect);
}
for (int i = 0; i < numberOfTabs; i++) {
TabButtonView* tabButton = [(BrowserTabViewItem*)[mTabView tabViewItemAtIndex:i] buttonView];
@ -552,17 +581,23 @@ const int kEscapeKeyCode = 53;
if (i < mLeftMostVisibleTabIndex || i >= mLeftMostVisibleTabIndex + mNumberOfVisibleTabs)
continue;
[self addSubview:tabButton];
NSRect tabRect = NSMakeRect(nextTabXOrigin, 0, widthOfATab, [self tabBarHeight]);
// spread the extra width from rounding tab sizes over the leftmost tabs.
if (extraWidth > 0.5) {
extraWidth -= 1.0;
tabRect.size.width += 1.0;
if (needsFullRebuild) {
[self addSubview:tabButton];
NSRect tabRect = NSMakeRect(nextTabXOrigin, 0, widthOfATab, [self tabBarHeight]);
// spread the extra width from rounding tab sizes over the leftmost tabs.
if (extraWidth > 0.5) {
extraWidth -= 1.0;
tabRect.size.width += 1.0;
}
[tabButton setFrame:tabRect];
nextTabXOrigin += NSWidth(tabRect);
} else {
// Tab buttons expect setFrame: to be called whenever their selection
// state changes, so call it even when it's not otherwise necessary.
[tabButton setFrame:[tabButton frame]];
}
[tabButton setFrame:tabRect];
[tabButton setDrawsLeftDivider:NO];
[tabButton setDrawsRightDivider:YES];
nextTabXOrigin += NSWidth(tabRect);
}
if (selectedTab) {
@ -727,7 +762,7 @@ const int kEscapeKeyCode = 53;
{
if (index != mLeftMostVisibleTabIndex) {
mLeftMostVisibleTabIndex = index;
[self rebuildTabBar];
[self tabStructureChanged];
}
}
@ -780,7 +815,7 @@ const int kEscapeKeyCode = 53;
// only change anything if the new state is different from the current state
if (show && [self isHidden]) {
[self setHidden:NO];
[self rebuildTabBar];
[self tabStructureChanged];
// set up tracking rects
[self registerTabButtonsForTracking];
} else if (!show && ![self isHidden]) { // being hidden
@ -1164,7 +1199,7 @@ const int kEscapeKeyCode = 53;
[animatedTab setDrawsLeftDivider:NO];
if ([mCurrentlySlidingTabs count] == 0 && ![self tabIsCurrentlyDragging])
[self performSelectorOnMainThread:@selector(rebuildTabBar) withObject:nil waitUntilDone:YES];
[self performSelectorOnMainThread:@selector(tabStructureChanged) withObject:nil waitUntilDone:YES];
}
// Called when the dragging tab has been released and is finished animating into its
@ -1181,7 +1216,7 @@ const int kEscapeKeyCode = 53;
[self addSubview:mDraggingTab];
}
else {
[self rebuildTabBar];
[self tabStructureChanged];
}
[[self window] removeChildWindow:mDraggingTabWindow];
@ -1234,7 +1269,7 @@ const int kEscapeKeyCode = 53;
[mDraggingTabWindow release];
mDraggingTabWindow = nil;
[self performSelector:@selector(rebuildTabBar) withObject:nil afterDelay:0.0];
[self performSelector:@selector(tabStructureChanged) withObject:nil afterDelay:0.0];
}
-(void)tabViewClosedTabViewItem:(BrowserTabViewItem*)closedTabViewItem atIndex:(int)indexOfClosedItem

View File

@ -63,6 +63,10 @@ extern NSString* const kTabBarBackgroundDoubleClickedNotification;
- (BOOL)barAlwaysVisible;
- (void)setBarAlwaysVisible:(BOOL)newSetting;
// Notification that the tab state has changed.
- (void)numberOfTabsChanged;
- (void)selectedTabChanged;
- (void)addTabForURL:(NSString*)aURL referrer:(NSString*)aReferrer inBackground:(BOOL)inBackground;
- (BOOL)tabsVisible;
@ -70,7 +74,6 @@ extern NSString* const kTabBarBackgroundDoubleClickedNotification;
- (int)numberOfBookmarkableTabViewItems;
- (int)indexOfTabViewItemWithURL:(NSString*)aURL;
- (BrowserTabViewItem*)itemWithTag:(int)tag;
- (void)refreshTabBar:(BOOL)rebuild;
- (BOOL)isVisible;
// inform the view that it will be shown or hidden; e.g. prior to showing or hiding the bookmarks
- (void)setVisible:(BOOL)show;

View File

@ -215,17 +215,16 @@ NSString* const kTabBarBackgroundDoubleClickedNotification = @"kTabBarBackground
/*** Instance Methods ***/
/******************************************/
// redraws the tab bar, rebuilding it if instructed
- (void)refreshTabBar:(BOOL)rebuild
- (void)numberOfTabsChanged
{
// don't bother if it's not even visible
if ([self tabsVisible]) {
if (rebuild) {
[mTabBar rebuildTabBar];
} else {
[mTabBar setNeedsDisplay:YES];
}
}
if ([self tabsVisible])
[mTabBar tabStructureChanged];
}
- (void)selectedTabChanged
{
if ([self tabsVisible])
[mTabBar tabSelectionChanged];
}
// Only to be used with the 2 types of tab view which we use in Camino.

View File

@ -3616,7 +3616,7 @@ public:
// Connect up the new view
mBrowserView = [aTabViewItem view];
[mTabBrowser refreshTabBar:YES];
[mTabBrowser selectedTabChanged];
// Make the new view the primary content area.
[mBrowserView setDelegate:self];
@ -3642,7 +3642,7 @@ public:
- (void)tabViewDidChangeNumberOfTabViewItems:(NSTabView *)aTabView
{
[[NSApp delegate] delayedFixCloseMenuItemKeyEquivalents];
[mTabBrowser refreshTabBar:YES];
[mTabBrowser numberOfTabsChanged];
// paranoia, to avoid stale mBrowserView pointer (since we don't own it)
if ([aTabView numberOfTabViewItems] == 0)
mBrowserView = nil;