Frameworks/AIUtilities Framework/Source/AIToolbarTabView.m
author Evan Schoenberg
Thu, 14 Nov 2019 16:22:42 -0500
changeset 5997 d88e6711d0e0
parent 3737 f06bf1a9d888
permissions -rw-r--r--
Fixed a triple handful of warnings
 * Adium is the legal property of its developers, whose names are listed in the copyright file included
 * with this source distribution.
 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
 * General Public License as published by the Free Software Foundation; either version 2 of the License,
 * or (at your option) any later version.
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
 * Public License for more details.
 * You should have received a copy of the GNU General Public License along with this program; if not,
 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

/* AIToolbarTabView

	This is a special tab view subclass that's useful in creating preference-type windows.  The tabview will
	automatically create a window toolbar and add an toolbar item for each tab it contains.  The tabview
	delegate will be asked for the toolbar images.

	This class also contains methods for auto-sizing the parent window based on the selected tab.  The delegate
	is asked for the window size, and this tabview takes care of the animation.

#import "AIToolbarTabView.h"
#import "AIToolbarUtilities.h"

@interface AIToolbarTabView ()
- (void)installToolbarItems;
- (IBAction)selectCategory:(id)sender;

@implementation AIToolbarTabView

- (void)awakeFromNib
    toolbarItems = [[NSMutableDictionary dictionary] retain];
	oldHeight = 100; //Height of the original tab view content
	//Create our toolbar
	NSToolbar *toolbar = [[[NSToolbar alloc] initWithIdentifier:@"ToolbarTabView"] autorelease];
    [toolbar setDelegate:self];
    [toolbar setAllowsUserCustomization:NO];
    [toolbar setAutosavesConfiguration:NO];
	[self installToolbarItems];
    [[self window] setToolbar:toolbar];

- (void)dealloc
	[toolbarItems release];
	[super dealloc];

//Toolbar --------------------------------------------------------------------------------------------------------------
#pragma mark Toolbar
//Install a toolbar item for each tab view item we contain
- (void)installToolbarItems
	if ([[self delegate] respondsToSelector:@selector(tabView:imageForTabViewItem:)]) {
		int	i;

		for (i = 0; i < [self numberOfTabViewItems]; i++) {
			NSTabViewItem	*tabViewItem = [self tabViewItemAtIndex:i];
			NSString 		*identifier = [NSString stringWithFormat:@"%i",i];
			NSString		*label = nil;
			if ([[self delegate] respondsToSelector:@selector(tabView:labelForTabViewItem:)]) {
				label = [(id<AIToolbarTabViewDelegate>)[self delegate] tabView:self labelForTabViewItem:tabViewItem];
			if (!label) label = [tabViewItem label];
			//We use the tab view item's index as identifier so we can easily sort our toolbar items into the same
			//ordering as the tabs.
			if (![toolbarItems objectForKey:identifier] && (tabViewItem != tabViewItem_loading)) {
				[AIToolbarUtilities addToolbarItemToDictionary:toolbarItems
												   itemContent:[(id<AIToolbarTabViewDelegate>)[self delegate] tabView:self
		[[[self window] toolbar] setConfigurationFromDictionary:toolbarItems];

//Select the category that invoked this method
//Select the corresponding tab view item
- (IBAction)selectCategory:(id)sender
    [self selectTabViewItemAtIndex:[[sender itemIdentifier] intValue]];

//Enable all categories
- (BOOL)validateToolbarItem:(NSToolbarItem *)theItem
    return YES;

//Access to our toolbar items
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier
    return [AIToolbarUtilities toolbarItemFromDictionary:toolbarItems withIdentifier:itemIdentifier];

//Default set (All items, sorted by name)
- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)toolbar
    return [[toolbarItems allKeys] sortedArrayUsingSelector:@selector(compare:)];

- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar
    return [self toolbarDefaultItemIdentifiers:toolbar];

- (NSArray *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar
    return [self toolbarDefaultItemIdentifiers:toolbar];

//Window Resizing ------------------------------------------------------------------------------------------------------
#pragma mark Window Resizing
//Resize our window when the tabview selection changes
- (void)selectTabViewItem:(NSTabViewItem *)tabViewItem
	//Update the selected toolbar item (10.3 or higher)
	if ([[[self window] toolbar] respondsToSelector:@selector(setSelectedItemIdentifier:)]) {
		[[[self window] toolbar] setSelectedItemIdentifier:[NSString stringWithFormat:@"%i",(int)[self indexOfTabViewItem:tabViewItem]]];

	if (tabViewItem != [self selectedTabViewItem]) {
		if (tabViewItem_loading) {
			//Start the spinning progress indicator
			[progressIndicator_loading setUsesThreadedAnimation:YES];
			[progressIndicator_loading startAnimation:self];
			//Select the loading tab view
			[super selectTabViewItem:tabViewItem_loading];
			if (![[self delegate] respondsToSelector:@selector(immediatelyShowLoadingIndicatorForTabView:willSelectTabViewItem:)] ||
			   [(id<AIToolbarTabViewDelegate>)[self delegate] immediatelyShowLoadingIndicatorForTabView:self willSelectTabViewItem:tabViewItem]) {
				[[self window] display];
			/* Now inform our delegate that we will be selecting the desired tab view 
			 * since after [super selectTabViewItem:tabViewItem_loading]; it thinks we are selecting tabViewItem_loading */
			if ([[self delegate] respondsToSelector:@selector(tabView:willSelectTabViewItem:)]) {
				[[self delegate] tabView:self willSelectTabViewItem:tabViewItem];
		} else if ([self respondsToSelector:@selector(setHidden:)]) {
			//If not, just hide
			[self setHidden:YES];
	if (!tabViewItem_loading) {
		//Select before resizing if we don't have a tab to show while loading
		[super selectTabViewItem:tabViewItem];
	//Resize the window
	if ([[self delegate] respondsToSelector:@selector(tabView:heightForTabViewItem:)]) {
		int		height = [(id<AIToolbarTabViewDelegate>)[self delegate] tabView:self heightForTabViewItem:tabViewItem];
		BOOL	isVisible = [[self window] isVisible];
		NSRect 	frame = [[self window] frame];
		//Factor out old view's height, factor in new view's height		
		frame.size.height += (height - oldHeight);
		frame.origin.y -= (height - oldHeight);
		oldHeight = height;
		[[self window] setFrame:frame display:isVisible animate:isVisible];		
	if (tabViewItem_loading) {
		//Select after resizing if we had a tab to show while loading
		[super selectTabViewItem:tabViewItem];
		//And stop the animation on the next run loop
		[progressIndicator_loading performSelector:@selector(stopAnimation:)
	} else if ([self respondsToSelector:@selector(setHidden:)]) {
		//Otherwise, we simply hid before, so unhide now
		[self setHidden:NO];