mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 13:07:02 +00:00
All classes (excluding the ones prefixed with underscores) in Foundation and AppKit can now be loaded individually except CPOpenPanel and CPSavePanel. These two classes have some sort of dependency cycle that seems impossible to resolve without forward declarations (which we don't have).
445 lines
12 KiB
Plaintext
445 lines
12 KiB
Plaintext
@import <AppKit/CPBox.j>
|
|
@import <AppKit/CPSegmentedControl.j>
|
|
@import <AppKit/CPTabViewItem.j>
|
|
@import <AppKit/CPView.j>
|
|
|
|
/*
|
|
Places tabs on top with a bezeled border.
|
|
@global
|
|
@group CPTabViewType
|
|
*/
|
|
CPTopTabsBezelBorder = 0;
|
|
//CPLeftTabsBezelBorder = 1;
|
|
CPBottomTabsBezelBorder = 2;
|
|
//CPRightTabsBezelBorder = 3;
|
|
/*
|
|
Displays no tabs and has a bezeled border.
|
|
@global
|
|
@group CPTabViewType
|
|
*/
|
|
CPNoTabsBezelBorder = 4;
|
|
/*
|
|
Has no tabs and displays a line border.
|
|
@global
|
|
@group CPTabViewType
|
|
*/
|
|
CPNoTabsLineBorder = 5;
|
|
/*
|
|
Displays no tabs and no border.
|
|
@global
|
|
@group CPTabViewType
|
|
*/
|
|
CPNoTabsNoBorder = 6;
|
|
|
|
var CPTabViewDidSelectTabViewItemSelector = 1,
|
|
CPTabViewShouldSelectTabViewItemSelector = 2,
|
|
CPTabViewWillSelectTabViewItemSelector = 4,
|
|
CPTabViewDidChangeNumberOfTabViewItemsSelector = 8;
|
|
|
|
var HEIGHT_OF_SEGMENTED_CONTROL = 24;
|
|
|
|
@implementation CPTabView : CPView
|
|
{
|
|
CPArray items;
|
|
|
|
CPSegmentedControl tabs;
|
|
CPBox box;
|
|
|
|
CPNumber selectedIndex;
|
|
|
|
CPTabViewType type;
|
|
|
|
id delegate;
|
|
unsigned delegateSelectors;
|
|
}
|
|
|
|
- (id)initWithFrame:(CGRect)aFrame
|
|
{
|
|
self = [super initWithFrame:aFrame];
|
|
if (self)
|
|
{
|
|
items = [CPArray array];
|
|
|
|
tabs = [[CPSegmentedControl alloc] initWithFrame:CGRectMake(0, 0, 0, HEIGHT_OF_SEGMENTED_CONTROL)];
|
|
[tabs setHitTests:NO];
|
|
|
|
box = [[CPBox alloc] initWithFrame:CGRectMake(0, HEIGHT_OF_SEGMENTED_CONTROL / 2, CGRectGetWidth(aFrame),
|
|
CGRectGetHeight(aFrame) - HEIGHT_OF_SEGMENTED_CONTROL)];
|
|
|
|
selectedIndex = CPNotFound;
|
|
|
|
[self setTabViewType:CPTopTabsBezelBorder];
|
|
[self setBackgroundColor:[CPColor colorWithCalibratedWhite:0.95 alpha:1.0]];
|
|
|
|
[self addSubview:box];
|
|
[self addSubview:tabs];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
// Adding and Removing Tabs
|
|
/*!
|
|
Adds a CPTabViewItem to the tab view.
|
|
@param aTabViewItem the item to add
|
|
*/
|
|
- (void)addTabViewItem:(CPTabViewItem)aTabViewItem
|
|
{
|
|
[self insertTabViewItem:aTabViewItem atIndex:[items count]];
|
|
}
|
|
|
|
/*!
|
|
Inserts a CPTabViewItem into the tab view
|
|
at the specified index.
|
|
@param aTabViewItem the item to insert
|
|
@param anIndex the index for the item
|
|
*/
|
|
- (void)insertTabViewItem:(CPTabViewItem)aTabViewItem atIndex:(unsigned)anIndex
|
|
{
|
|
[items insertObject:aTabViewItem atIndex:anIndex];
|
|
|
|
[self _updateItems];
|
|
[self _repositionTabs];
|
|
|
|
if (delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
|
|
[delegate tabViewDidChangeNumberOfTabViewItems:self];
|
|
}
|
|
|
|
/*!
|
|
Removes the specified tab view item from the tab view.
|
|
@param aTabViewItem the item to remove
|
|
*/
|
|
- (void)removeTabViewItem:(CPTabViewItem)aTabViewItem
|
|
{
|
|
for (var i = 0; i < [items count]; i++)
|
|
{
|
|
if ([items objectAtIndex:i] === aTabViewItem)
|
|
{
|
|
[items removeObjectAtIndex:i];
|
|
}
|
|
}
|
|
|
|
[self _updateItems];
|
|
[self _repositionTabs];
|
|
|
|
if (delegateSelectors & CPTabViewDidChangeNumberOfTabViewItemsSelector)
|
|
[delegate tabViewDidChangeNumberOfTabViewItems:self];
|
|
}
|
|
|
|
// Accessing Tabs
|
|
/*!
|
|
Returns the index of the specified item
|
|
@param aTabViewItem the item to find the index for
|
|
*/
|
|
- (int)indexOfTabViewItem:(CPTabViewItem)aTabViewItem
|
|
{
|
|
return [items indexOfObjectIdenticalTo:aTabViewItem];
|
|
}
|
|
|
|
/*!
|
|
Returns the index of the CPTabViewItem with the specified identifier.
|
|
@param anIdentifier the identifier of the item
|
|
*/
|
|
- (int)indexOfTabViewItemWithIdentifier:(CPString)anIdentifier
|
|
{
|
|
for (var index = [items count]; index >= 0; index--)
|
|
if ([[items[index] identifier] isEqual:anIdentifier])
|
|
return index;
|
|
|
|
return CPNotFound;
|
|
}
|
|
|
|
/*!
|
|
Returns the number of items in the tab view.
|
|
*/
|
|
- (unsigned)numberOfTabViewItems
|
|
{
|
|
return [items count];
|
|
}
|
|
|
|
/*!
|
|
Returns the CPTabViewItem at the specified index.
|
|
*/
|
|
- (CPTabViewItem)tabViewItemAtIndex:(unsigned)anIndex
|
|
{
|
|
return [items objectAtIndex:anIndex];
|
|
}
|
|
|
|
/*!
|
|
Returns the array of items that backs this tab view.
|
|
*/
|
|
- (CPArray)tabViewItems
|
|
{
|
|
return [items copy]; // Copy?
|
|
}
|
|
|
|
// Selecting a Tab
|
|
/*!
|
|
Sets the first tab view item in the array to be displayed to the user.
|
|
@param aSender the object making this request
|
|
*/
|
|
- (void)selectFirstTabViewItem:(id)aSender
|
|
{
|
|
if ([items count] === 0)
|
|
return; // throw?
|
|
|
|
[self selectTabViewItemAtIndex:0];
|
|
}
|
|
|
|
/*!
|
|
Sets the last tab view item in the array to be displayed to the user.
|
|
@param aSender the object making this request
|
|
*/
|
|
- (void)selectLastTabViewItem:(id)aSender
|
|
{
|
|
if ([items count] === 0)
|
|
return; // throw?
|
|
|
|
[self selectTabViewItemAtIndex:[items count] - 1];
|
|
}
|
|
|
|
/*!
|
|
Sets the next tab item in the array to be displayed.
|
|
@param aSender the object making this request
|
|
*/
|
|
- (void)selectNextTabViewItem:(id)aSender
|
|
{
|
|
if (selectedIndex === CPNotFound)
|
|
return;
|
|
|
|
var nextIndex = selectedIndex + 1;
|
|
|
|
if (nextIndex === [items count])
|
|
return; // does nothing. According to spec at (http://developer.apple.com/mac/library/DOCUMENTATION/Cocoa/Reference/ApplicationKit/Classes/NSTabView_Class/Reference/Reference.html#//apple_ref/occ/instm/NSTabView/selectNextTabViewItem:)
|
|
|
|
[self selectTabViewItemAtIndex:nextIndex];
|
|
}
|
|
|
|
/*!
|
|
Selects the previous item in the array for display.
|
|
@param aSender the object making this request
|
|
*/
|
|
- (void)selectPreviousTabViewItem:(id)aSender
|
|
{
|
|
if (selectedIndex === CPNotFound)
|
|
return;
|
|
|
|
var previousIndex = selectedIndex - 1;
|
|
|
|
if (previousIndex < 0)
|
|
return; // does nothing. See above.
|
|
|
|
[self selectTabViewItemAtIndex:previousIndex];
|
|
}
|
|
|
|
/*!
|
|
Displays the specified item in the tab view.
|
|
@param aTabViewItem the item to display
|
|
*/
|
|
- (void)selectTabViewItem:(CPTabViewItem)aTabViewItem
|
|
{
|
|
[self selectTabViewItemAtIndex:[self indexOfTabViewItem:aTabViewItem]];
|
|
}
|
|
|
|
/*!
|
|
Selects the item at the specified index.
|
|
@param anIndex the index of the item to display.
|
|
*/
|
|
- (void)selectTabViewItemAtIndex:(unsigned)anIndex
|
|
{
|
|
var aTabViewItem = [items objectAtIndex:anIndex];
|
|
|
|
if (anIndex === selectedIndex)
|
|
return;
|
|
|
|
if ((delegateSelectors & CPTabViewShouldSelectTabViewItemSelector) && ![delegate tabView:self shouldSelectTabViewItem:aTabViewItem])
|
|
return;
|
|
|
|
if (delegateSelectors & CPTabViewWillSelectTabViewItemSelector)
|
|
[delegate tabView:self willSelectTabViewItem:aTabViewItem];
|
|
|
|
[tabs selectSegmentWithTag:anIndex];
|
|
[self _setSelectedIndex:anIndex];
|
|
|
|
if (delegateSelectors & CPTabViewDidSelectTabViewItemSelector)
|
|
[delegate tabView:self didSelectTabViewItem:aTabViewItem];
|
|
}
|
|
|
|
/*!
|
|
Returns the current item being displayed.
|
|
*/
|
|
- (CPTabViewItem)selectedTabViewItem
|
|
{
|
|
return [items objectAtIndex:selectedIndex];
|
|
}
|
|
|
|
//
|
|
/*!
|
|
Sets the tab view type.
|
|
@param aTabViewType the view type
|
|
*/
|
|
- (void)setTabViewType:(CPTabViewType)aTabViewType
|
|
{
|
|
if (type === aTabViewType)
|
|
return;
|
|
|
|
if ((type === CPTopTabsBezelBorder || type === CPBottomTabsBezelBorder)
|
|
&& (aTabViewType !== CPTopTabsBezelBorder && aTabViewType !== CPBottomTabsBezelBorder))
|
|
[tabs removeFromSuperview];
|
|
|
|
if ((type === CPNoTabsBezelBorder || type === CPNoTabsLineBorder || type === CPNoTabsNoBorder)
|
|
&& (aTabViewType !== CPNoTabsBezelBorder && aTabViewType !== CPNoTabsBezelBorder && aTabViewType !== CPNoTabsNoBorder))
|
|
[self addSubview:tabs];
|
|
|
|
type = aTabViewType;
|
|
|
|
switch (type) {
|
|
case CPTopTabsBezelBorder:
|
|
case CPBottomTabsBezelBorder:
|
|
case CPNoTabsBezelBorder:
|
|
[box setBorderType:CPBezelBorder];
|
|
break;
|
|
case CPNoTabsLineBorder:
|
|
[box setBorderType:CPLineBorder];
|
|
break;
|
|
case CPNoTabsNoBorder:
|
|
[box setBorderType:CPNoBorder];
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Returns the tab view type.
|
|
*/
|
|
- (CPTabViewType)tabViewType
|
|
{
|
|
return type;
|
|
}
|
|
|
|
/*!
|
|
Returns the receiver's delegate.
|
|
*/
|
|
- (id)delegate
|
|
{
|
|
return delegate;
|
|
}
|
|
|
|
/*!
|
|
Sets the delegate for this tab view.
|
|
@param aDelegate the tab view's delegate
|
|
*/
|
|
- (void)setDelegate:(id)aDelegate
|
|
{
|
|
if (delegate == aDelegate)
|
|
return;
|
|
|
|
delegate = aDelegate;
|
|
|
|
delegateSelectors = 0;
|
|
|
|
if ([delegate respondsToSelector:@selector(tabView:shouldSelectTabViewItem:)])
|
|
delegateSelectors |= CPTabViewShouldSelectTabViewItemSelector;
|
|
|
|
if ([delegate respondsToSelector:@selector(tabView:willSelectTabViewItem:)])
|
|
delegateSelectors |= CPTabViewWillSelectTabViewItemSelector;
|
|
|
|
if ([delegate respondsToSelector:@selector(tabView:didSelectTabViewItem:)])
|
|
delegateSelectors |= CPTabViewDidSelectTabViewItemSelector;
|
|
|
|
if ([delegate respondsToSelector:@selector(tabViewDidChangeNumberOfTabViewItems:)])
|
|
delegateSelectors |= CPTabViewDidChangeNumberOfTabViewItemsSelector;
|
|
}
|
|
|
|
- (void)setBackgroundColor:(CPColor)aColor
|
|
{
|
|
[box setBackgroundColor:aColor];
|
|
}
|
|
|
|
- (void)mouseDown:(CPEvent)anEvent
|
|
{
|
|
var segmentIndex = [tabs testSegment:[tabs convertPoint:[anEvent locationInWindow] fromView:nil]];
|
|
|
|
if (segmentIndex != CPNotFound)
|
|
{
|
|
[self selectTabViewItemAtIndex:segmentIndex];
|
|
[tabs trackSegment:anEvent];
|
|
}
|
|
}
|
|
|
|
- (void)_repositionTabs
|
|
{
|
|
var horizontalCenterOfSelf = CGRectGetWidth([self bounds]) / 2,
|
|
verticalCenterOfTabs = CGRectGetHeight([tabs bounds]) / 2;
|
|
|
|
if (type === CPBottomTabsBezelBorder)
|
|
[tabs setCenter:CGPointMake(horizontalCenterOfSelf, CGRectGetHeight([self bounds]) - verticalCenterOfTabs)];
|
|
else
|
|
[tabs setCenter:CGPointMake(horizontalCenterOfSelf, verticalCenterOfTabs)];
|
|
}
|
|
|
|
- (void)_setSelectedIndex:(CPNumber)index
|
|
{
|
|
selectedIndex = index;
|
|
|
|
[box setContentView:[[items objectAtIndex:selectedIndex] view]];
|
|
}
|
|
|
|
- (void)_updateItems
|
|
{
|
|
[tabs setSegmentCount:[items count]];
|
|
|
|
for (var i = 0; i < [items count]; i++)
|
|
{
|
|
[tabs setLabel:[[items objectAtIndex:i] label] forSegment:i];
|
|
[tabs setTag:i forSegment:i];
|
|
}
|
|
|
|
if (selectedIndex === CPNotFound)
|
|
{
|
|
[self selectFirstTabViewItem:self];
|
|
}
|
|
}
|
|
|
|
@end
|
|
|
|
var CPTabViewItemsKey = "CPTabViewItemsKey",
|
|
CPTabViewSelectedItemKey = "CPTabViewSelectedItemKey",
|
|
CPTabViewTypeKey = "CPTabViewTypeKey",
|
|
CPTabViewDelegateKey = "CPTabViewDelegateKey";
|
|
|
|
@implementation CPTabView (CPCoding)
|
|
|
|
- (id)initWithCoder:(CPCoder)aCoder
|
|
{
|
|
if (self = [super initWithCoder:aCoder])
|
|
{
|
|
type = [aCoder decodeIntForKey:CPTabViewTypeKey];
|
|
items = [];
|
|
|
|
var encodedItems = [aCoder decodeObjectForKey:CPTabViewItemsKey];
|
|
for (var i = 0; encodedItems && i < encodedItems.length; i++)
|
|
[self insertTabViewItem:encodedItems[i] atIndex:i];
|
|
|
|
var selected = [aCoder decodeObjectForKey:CPTabViewSelectedItemKey];
|
|
if (selected)
|
|
[self selectTabViewItem:selected];
|
|
|
|
[self setDelegate:[aCoder decodeObjectForKey:CPTabViewDelegateKey]];
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
- (void)encodeWithCoder:(CPCoder)aCoder
|
|
{
|
|
[super encodeWithCoder:aCoder];
|
|
|
|
[aCoder encodeObject:items forKey:CPTabViewItemsKey];;
|
|
[aCoder encodeObject:[self selectedTabViewItem] forKey:CPTabViewSelectedItemKey];
|
|
|
|
[aCoder encodeInt:type forKey:CPTabViewTypeKey];
|
|
|
|
[aCoder encodeConditionalObject:delegate forKey:CPTabViewDelegateKey];
|
|
}
|
|
|
|
@end
|