# PSMTabBarControl

Inherits from | NSControl : NSView : NSResponder : NSObject
Conforms to | NSCoding (NSResponder) NSObject (NSObject)
Declared in | PSMTabBarControl.h

## Class Description

PSMTabBarControl provides a user interface for the management of tabbed views that has an appearance similar to Apple's Safari web browser.

Internally, PSMTabBarControl uses a custom cell class and supporting style objects to implement its user interface.

Currently, this object supports "Aqua" and "Metal" tab styles to present an appearance consistent with the rest of your application. Numerous configuration options exist to customize behavior, as outlined below. PSMTabBarControl instances require a few specific connections with other application objects to perform properly at runtime:

- The control's "tabView" outlet must be connected to the desired NSTabView instance in Interface Builder, or set programmatically with the setTabView: method.
- The "delegate" outlet of the NSTabView being controlled must be connected to the instance of PSMTabBarControl, either programmatically or in IB.
- Optionally, you may connect the control's "partnerView" outlet to a view that will be resized to compensate when PSMTabBarControl changes size due to hide/show behavior. If no connection is made, PSMTabBarControl will resize the window in response to hide/show messages.

A PSMTabBarControl instance should occupy the width of the window, and should be precisely 22 pixels in height. It should be resizable in width, but not height. It can be placed at the top or botton of the window (or anywhere in between, if desired).

Outside of configuring it, your application should have little interaction with this class. The presented tabs will change in conjunction with changes your application makes in the NSTabView being controlled.

## A Usage Pattern

PSMTabBarControl becomes even more powerful if your application design matches an expected pattern: the control attempts to bind a number of tab attributes to the NSTabViewItem's identifier object if possible. These visible attributes include a progress indicator, an icon, and an object counter. Additionally, the control binds each tab's title to the label of the represented NSTabViewItem.

Taking advantage of these features requires no glue code on your part, but it does require providing a particular object graph. Here's the basics...

- For each tab that is created, your application should have a model object that keeps the state of model attributes: isProcessing (a BOOL), objectCount (an int), and icon (an NSImage). You can pick and choose any number of these to support, or none, at your option.
- Your application should create an NSObjectController to control your model (the model object is the "content" of the NSObjectController instance).
- When you create new tabs (via the NSTabView interface), you should set the object controller instance to be the identifier object of the newly created NSTabViewItem object.

The demo application included with this project illustrates a very quick way to accomplish these goals. If this pattern is followed, PSMTabBarControl will take care of the rest.

## Methods by Task

### Setting needed connections

`– setTabView:`

  Specifies the instance of NSTabView to be controlled.

`– tabView`

  Returns the instance of NSTabView being controlled.

### Setting optional connections

`– setPartnerView:`

  Specifies a view that will resize to compensate for control size changes in response to hide and show messages.

`– partnerView`

  Returns the instance of a view that will resize to compensate for control size changes in response to hide and show messages.

`– setDelegate:`

  Specifies an object that will receive delegate messages as passed through from the NSTabView instance.

`– delegate:`

  Returns the specified delegate object.

### Control configuration

`– canCloseOnlyTab`

  Returns YES if the user is allowed to close a tab when it is the only tab left, NO otherwise.

`– setCanCloseOnlyTab:`

  Controls whether the receiver will present a close button for a single tab in a tab bar.

`– styleName`

  Returns the name of the current drawing style. "Aqua", "Metal", and "Unified" are the currently supported options.

`– setStyleNamed:`

  Specifies the style in which the tabs and control are drawn. "Aqua", "Metal", and "Unified" are the currently supported options.

`– hideForSingleTab`

  Returns YES if the control will hide if there is only one tab left, NO otherwise.

`– setHideForSingleTab:`

  Controls whether the receiver will hide when the user closes all but a single tab in a tab bar.

`– showAddTabButton`

  Returns YES if the control will display a small "add tab" button at the rightmost end of the tabs, NO otherwise.

`– setShowAddTabButton:`

  Controls whether the receiver will will display a small "add tab" button at the rightmost end of the tabs.

`– cellMinWidth`

  Returns the minimum width (in pixels) that a tab will be allowed to occupy.

`– setCellMinWidth:`

  Specifies the maximum width (in pixels) that a tab will be allowed to occupy.

`– cellMaxWidth`

  Returns the maximum width (in pixels) that a tab will be allowed to occupy.

`– setCellMaxWidth:`

  Specifies the maximum width (in pixels) that a tab will be allowed to occupy.

`– cellOptimumWidth`

  Returns the default width (in pixels) that a tab will be allowed to occupy when tabs are drawn with uniform size.

`– setCellMaxWidth:`

  Specifies the default width (in pixels) that a tab will be allowed to occupy when tabs are drawn with uniform size.

`– sizeCellsToFit`

  Returns YES if the control will make the tabs sized to fit the content of the tab, NO otherwise.

`– setSizeCellsToFit:`

  Controls whether the receiver will make the tabs sized to fit the content of the tab.

`– allowsDragBetweenWindows`

  Returns YES if the control allows a user to drag a tab to another instance of this control, NO otherwise.

`– setAllowsDragBetweenWindows:`

  Controls whether the receiver will allow a user to drag a tab to another instance of this control.

### Internal UI components

`– addTabButton`

  Returns an instance of an NSButton subclass that is used to present the "add tab" button. If "showAddTabButton" is YES, developers must use this method to access the button and specify a target and action for the button.

`– overflowPopUpButton`

  Returns an instance of an NSPopUpButton subclass that is used to present the overflow menu (which shows when there are more tabs than can fit across the control).

`– representedTabViewItems`

  Returns an array of the NSTabViewItems represented by the tabs in the control. Useful if you want to archive the order of the tabs between runs of your program.

### Visibility

`– hideTabBar:animate:`

  If desired, obejcts can tell the tab bar to hide (reduce in size to a single pixel line spanning the window) or show, and optionally whether to animate this effect or not.

## Instance Methods

### addTabButton

Returns an instance of an NSButton subclass that is used to present the "add tab" button. If "showAddTabButton" is YES, developers must use this method to access the button and specify a target and action for the button.

- (PSMRolloverButton *)addTabButton;

##### Discussion

If you have configured the control to show the add tab button, you must use this method to access the button and set the target and action for it. Example:

`[[tabBar addTabButton] setTarget:self];
[[tabBar addTabButton] setAction:@selector(addNewTab:)];`

##### See Also

- `– setShowAddTabButton:`
- `– showAddTabButton`

### allowsDragBetweenWindows

Returns `YES` if the control allows a user to drag a tab to another instance of this control, NO otherwise.

- (BOOL)allowsDragBetweenWindows

##### Discussion

The default is `YES`.

##### See Also

- `– setAllowsDragBetweenWindows:`

### canCloseOnlyTab

Returns `YES` if the receiver has been configured to allow users to close a single remaining tab.

- (BOOL)canCloseOnlyTab

##### Discussion

The default is `NO`.

##### See Also

- `– setCanCloseOnlyTab:`

### cellMaxWidth

Returns the maximum width (in pixels) that a tab will be allowed to occupy.

- (int)cellMaxWidth

##### Discussion

The cellMaxWidth value applies to both uniformly sized tabs, and tabs that are sized to fit. No tab will be drawn wider than the specified value.

##### See Also

- `– setCellMaxWidth:`
- `– cellMinWidth`
- `– cellOptimumWidth`

### cellMinWidth

Returns the minimum width (in pixels) that a tab will be allowed to occupy.

- (int)cellMinWidth

##### Discussion

The cellMinWidth value applies only to uniformly sized tabs. No tab will be drawn smaller than the specified value. Size-to-fit tabs ignore this value, and are made just small enough to fit their content.

##### See Also

- `– setCellMinWidth:`
- `– cellMaxWidth`
- `– cellOptimumWidth`

### cellOptimumWidth

Returns the width (in pixels) that a tab will be made to occupy if the tabs are uniformly sized.

- (int)cellOptimumWidth

##### Discussion

The cellOptimumWidth value applies only to uniformly sized tabs. All tabs will be drawn at the specified value. Size-to-fit tabs ignore this value, and are made just small enough to fit their content.

##### See Also

- `– setCellOptimumWidth:`
- `– cellMaxWidth`
- `– cellMinWidth`

### delegate

Returns the object that will be sent passed-through NSTabView delegate messages.

- (id)delegate

##### See Also

- `– setDelegate:`

### hideForSingleTab

Returns `YES` if the receiver has been configured to hide if there is a single remaining tab.

- (BOOL)hideForSingleTab

##### Discussion

The default is `NO`.

##### See Also

- `– setHideForSingleTab:`

### hideTabBar:animate:

If desired, obejcts can tell the tab bar to hide (reduce in size to a single pixel line spanning the window) or show, and optionally whether to animate this effect or not.

- (void)hideTabBar:(BOOL)hide animate:(BOOL)animate

##### Discussion

If hide is `YES` the control will shrink to a single pixel line spanning the window; otherwise the control will expand to its normal appearance. If animate is `YES`, the shrinking and expanding will happen in a visible animation; otherwise the transition will be instant. There is no effect if the control is already in the specified state.

### overflowPopUpButton

Returns an instance of an NSPopUpButton subclass that is used to present the overflow menu.

- (PSMOverflowPopUpButton *)overflowPopUpButton;

##### Discussion

This method could be used to modify the button or menu if desired.

### partnerView

Returns the object that will be resized to compensate for the changing size of the control during hide/show behavior.

- (id)partnerView

##### Discussion

If a partnerView has not been specified, the window will be resized during hide/show.

##### See Also

- `– setPartnerView:`

### representedTabViewItems

Returns an array of NSTabViewItems, ordered according to the display order of the tabs in the control.

- (NSMutableArray *)representedTabViewItems;

##### Discussion

This method could be used archive the order of the tabs between application runs. When the user reorders tabs via drag and drop, the represented NSTabView does not change order.

### setAllowsDragBetweenWindows

If set to `YES`, the receiver is configured to allow users to drag a tab to an instance of PSMTabBarControl in another window.

- (void)setAllowsDragBetweenWindows:(BOOL)value

##### Discussion

The default is `YES`.

##### See Also

- `– allowsDragBetweenWindows:`

### setCanCloseOnlyTab:

If set to `YES`, the receiver is configured to allow users to close a single remaining tab.

- (void)setCanCloseOnlyTab:(BOOL)value

##### Discussion

The default is `NO`.

##### See Also

- `– canCloseOnlyTab:`

### setCellMaxWidth:

Specifies the maximum width (in pixels) that a tab will be allowed to occupy.

- (void)setCellMaxWidth:(int)value

##### Discussion

No tab will be drawn any wider than the specified value.

##### See Also

- `– cellMaxWidth`

### setCellMinWidth:

Specifies the minimum width (in pixels) that a tab will be allowed to occupy.

- (void)setCellMinWidth:(int)value

##### Discussion

No tab will be drawn any smaller than the specified value. This value is ignored when drawing in size-to-fit; tabs are made just small enough to fit their content.

##### See Also

- `– cellMinWidth`

### setCellOptimumWidth:

Specifies the width (in pixels) that a tab will occupy when tabs are uniformly sized.

- (void)setCellOptimumWidth:(int)value

##### Discussion

This value is ignored when drawing in size-to-fit; tabs are made just small enough to fit their content.

##### See Also

- `– cellOptimumWidth`

### setDelegate:

Specifies an object that will receive delegate messages as passed through from the NSTabView instance.

- (void)setDelegate:(id)object

##### See Also

- `– delegate:`

### setHideForSingleTab:

If set to `YES`, the receiver is configured to hide when there is a single remaining tab.

- (void)setHideForSingleTab:(BOOL)value

##### Discussion

The default is `NO`.

##### See Also

- `– hideForSingleTab`

### setPartnerView:

Specifies a view that will resize to compensate for control size changes in response to hide and show messages.

- (void)setPartnerView:(id)view

##### Discussion

if nil, the control will resize the window in response to hide/show messages.

##### See Also

- `– partnerView`

### setStyleNamed:

Specifies the style in which the tabs and control are drawn.

- (void)setStyleNamed:(NSString *)name

##### Discussion

"Aqua" and "Metal" are the currently supported options.

##### See Also

- `– styleName`

### setShowAddTabButton:

Controls whether the receiver will will display a small "add tab" button at the rightmost end of the tabs.

- (void)setShowAddTabButton:(BOOL)value

##### Discussion

Default is `NO`.

##### See Also

- `– showAddTabButton`

### setSizeCellsToFit:

Controls whether the receiver will make the tabs sized to fit the content of the tab.

- (void)setSizeCellsToFit:(BOOL)value

##### Discussion

Default is `NO`.

##### See Also

- `– sizeCellsToFit`

### setTabView:

Specifies the instance of NSTabView to be controlled.

- (void)setTabView:(NSTabView *)view

##### Discussion

This class will not function properly without this outlet being set.

##### See Also

- `– tabView`

### sizeCellsToFit

Returns YES if the control will make the tabs sized to fit the content of the tab, NO otherwise.

##### Discussion

The default is `NO`.

##### See Also

- `– setSizeCellsToFit:`

### styleName:

Returns the name of the current drawing style.

- (NSString *)styleName

##### Discussion

"Aqua" and "Metal" are the currently supported options.

##### See Also

- `– setStyleNamed:`

### tabView:

Returns the instance of NSTabView being controlled.

- (NSTabView *)tabView

##### Discussion

This class will not function properly if this object is nil.

##### See Also

- `– setTabView`

## Delegate Methods

You application controller can keep track of activity from the tab view and the user via the following delegate methods.

### tabView:shouldCloseTabViewItem:

Sent when a user clicks the close button on a tab.

- (BOOL)tabView:(NSTabView *)tabView shouldCloseTabViewItem:(NSTabViewItem *)tabViewItem

##### Discussion

If you return `NO`, the tab will not be closed. Please make sure to alert the user as to why with a sheet or dialog.

### tabView:willCloseTabViewItem:

Sent when tab is about to be closed.

- (void)tabView:(NSTabView *)tabView willCloseTabViewItem:(NSTabViewItem *)tabViewItem

##### Discussion

This presents you with an opportunity to clean up the application objects/events/sessions represented by the tab.

### tabView:didCloseTabViewItem:

Sent after a tab has been closed.

- (void)tabView:(NSTabView *)tabView didCloseTabViewItem:(NSTabViewItem *)tabViewItem

##### Discussion

This presents you with an opportunity to clean up the application objects/events/sessions represented by the tab. Don't go trying to modify the tabViewItem - it is about to be released, and has already been removed from the tabView!

### tabView:didSelectTabViewItem:

Informs the delegate that tabView has selected tabViewItem.

- (void)tabView:(NSTabView *)tabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem

### tabView:shouldSelectTabViewItem:

Invoked just before tabViewItem in tabView is selected.

- (BOOL)tabView:(NSTabView *)tabView shouldSelectTabViewItem:(NSTabViewItem *)tabViewItem

##### Discussion

The delegate can return `NO` to prevent selection of specific tabs.

### tabView:willSelectTabViewItem:

Informs the delegate that tabView is about to select tabViewItem.

- (void)tabView:(NSTabView *)tabView willSelectTabViewItem:(NSTabViewItem *)tabViewItem

### tabViewDidChangeNumberOfTabViewItems:

Informs the delegate that the number of tab view items in tabView has changed.

- (void)tabViewDidChangeNumberOfTabViewItems:(NSTabView *)tabView