diff options
Diffstat (limited to 'chrome/browser/ui/cocoa/tab_view_picker_table.mm')
-rw-r--r-- | chrome/browser/ui/cocoa/tab_view_picker_table.mm | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/chrome/browser/ui/cocoa/tab_view_picker_table.mm b/chrome/browser/ui/cocoa/tab_view_picker_table.mm new file mode 100644 index 0000000..95dec3b --- /dev/null +++ b/chrome/browser/ui/cocoa/tab_view_picker_table.mm @@ -0,0 +1,193 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "tab_view_picker_table.h" + +#include "base/logging.h" + +@interface TabViewPickerTable (Private) +// If a heading is shown, the indices between the tab items and the table rows +// are shifted by one. These functions convert between tab indices and table +// indices. +- (NSInteger)tabIndexFromTableIndex:(NSInteger)tableIndex; +- (NSInteger)tableIndexFromTabIndex:(NSInteger)tabIndex; + +// Returns if |item| is the item shown as heading. If |heading_| is nil, this +// always returns |NO|. +- (BOOL)isHeadingItem:(id)item; + +// Reloads the outline view and sets the selection to the row corresponding to +// the currently selected tab. +- (void)reloadDataWhileKeepingCurrentTabSelected; +@end + +@implementation TabViewPickerTable + +- (id)initWithFrame:(NSRect)frame { + if ((self = [super initWithFrame:frame])) { + [self setDelegate:self]; + [self setDataSource:self]; + } + return self; +} + +- (id)initWithCoder:(NSCoder*)coder { + if ((self = [super initWithCoder:coder])) { + [self setDelegate:self]; + [self setDataSource:self]; + } + return self; +} + +- (void)awakeFromNib { + DCHECK(tabView_); + DCHECK_EQ([self delegate], self); + DCHECK_EQ([self dataSource], self); + DCHECK(![self allowsEmptySelection]); + DCHECK(![self allowsMultipleSelection]); + + // Suppress the "Selection changed" message that's sent while the table is + // being built for the first time (this causes a selection change to index 0 + // and back to the prior index). + id oldTabViewDelegate = [tabView_ delegate]; + [tabView_ setDelegate:nil]; + + [self reloadDataWhileKeepingCurrentTabSelected]; + + oldTabViewDelegate_ = oldTabViewDelegate; + [tabView_ setDelegate:self]; +} + +- (NSString*)heading { + return heading_.get(); +} + +- (void)setHeading:(NSString*)str { + heading_.reset([str copy]); + [self reloadDataWhileKeepingCurrentTabSelected]; +} + +- (void)reloadDataWhileKeepingCurrentTabSelected { + NSInteger index = + [tabView_ indexOfTabViewItem:[tabView_ selectedTabViewItem]]; + [self reloadData]; + if (heading_) + [self expandItem:[self outlineView:self child:0 ofItem:nil]]; + NSIndexSet* indexSet = + [NSIndexSet indexSetWithIndex:[self tableIndexFromTabIndex:index]]; + [self selectRowIndexes:indexSet byExtendingSelection:NO]; +} + +// NSTabViewDelegate methods. +- (void) tabView:(NSTabView*)tabView + didSelectTabViewItem:(NSTabViewItem*)tabViewItem { + DCHECK_EQ(tabView_, tabView); + NSInteger index = + [tabView_ indexOfTabViewItem:[tabView_ selectedTabViewItem]]; + NSIndexSet* indexSet = + [NSIndexSet indexSetWithIndex:[self tableIndexFromTabIndex:index]]; + [self selectRowIndexes:indexSet byExtendingSelection:NO]; + if ([oldTabViewDelegate_ + respondsToSelector:@selector(tabView:didSelectTabViewItem:)]) { + [oldTabViewDelegate_ tabView:tabView didSelectTabViewItem:tabViewItem]; + } +} + +- (BOOL) tabView:(NSTabView*)tabView + shouldSelectTabViewItem:(NSTabViewItem*)tabViewItem { + if ([oldTabViewDelegate_ + respondsToSelector:@selector(tabView:shouldSelectTabViewItem:)]) { + return [oldTabViewDelegate_ tabView:tabView + shouldSelectTabViewItem:tabViewItem]; + } + return YES; +} + +- (void) tabView:(NSTabView*)tabView + willSelectTabViewItem:(NSTabViewItem*)tabViewItem { + if ([oldTabViewDelegate_ + respondsToSelector:@selector(tabView:willSelectTabViewItem:)]) { + [oldTabViewDelegate_ tabView:tabView willSelectTabViewItem:tabViewItem]; + } +} + +- (NSInteger)tabIndexFromTableIndex:(NSInteger)tableIndex { + if (!heading_) + return tableIndex; + DCHECK(tableIndex > 0); + return tableIndex - 1; +} + +- (NSInteger)tableIndexFromTabIndex:(NSInteger)tabIndex { + DCHECK_GE(tabIndex, 0); + DCHECK_LT(tabIndex, [tabView_ numberOfTabViewItems]); + if (!heading_) + return tabIndex; + return tabIndex + 1; +} + +- (BOOL)isHeadingItem:(id)item { + return item && item == heading_.get(); +} + +// NSOutlineViewDataSource methods. +- (NSInteger) outlineView:(NSOutlineView*)outlineView + numberOfChildrenOfItem:(id)item { + if (!item) + return heading_ ? 1 : [tabView_ numberOfTabViewItems]; + return (item == heading_.get()) ? [tabView_ numberOfTabViewItems] : 0; +} + +- (BOOL)outlineView:(NSOutlineView*)outlineView isItemExpandable:(id)item { + return [self isHeadingItem:item]; +} + +- (id)outlineView:(NSOutlineView*)outlineView + child:(NSInteger)index + ofItem:(id)item { + if (!item) { + return heading_.get() ? + heading_.get() : static_cast<id>([tabView_ tabViewItemAtIndex:index]); + } + return (item == heading_.get()) ? [tabView_ tabViewItemAtIndex:index] : nil; +} + +- (id) outlineView:(NSOutlineView*)outlineView + objectValueForTableColumn:(NSTableColumn*)tableColumn + byItem:(id)item { + if ([item isKindOfClass:[NSTabViewItem class]]) + return [static_cast<NSTabViewItem*>(item) label]; + if ([self isHeadingItem:item]) + return [item uppercaseString]; + return nil; +} + +// NSOutlineViewDelegate methods. +- (void)outlineViewSelectionDidChange:(NSNotification*)notification { + int row = [self selectedRow]; + [tabView_ selectTabViewItemAtIndex:[self tabIndexFromTableIndex:row]]; +} + +- (BOOL)outlineView:(NSOutlineView *)sender isGroupItem:(id)item { + return [self isHeadingItem:item]; +} + +- (BOOL)outlineView:(NSOutlineView*)outlineView shouldExpandItem:(id)item { + return [self isHeadingItem:item]; +} + +- (BOOL)outlineView:(NSOutlineView*)outlineView shouldCollapseItem:(id)item { + return NO; +} + +- (BOOL)outlineView:(NSOutlineView *)outlineView shouldSelectItem:(id)item { + return ![self isHeadingItem:item]; +} + +// -outlineView:shouldShowOutlineCellForItem: is 10.6-only. +- (NSRect)frameOfOutlineCellAtRow:(NSInteger)row { + return NSZeroRect; +} + +@end |