William Bowling is sharing code with you
Bitbucket is a code hosting site. Unlimited public and private repositories. Free for small teams.
Don't show this again1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | //
// AIServiceMenu.m
// Adium
//
// Created by Adam Iser on 5/19/05.
//
#import <Adium/AIServiceMenu.h>
#import <Adium/AIAccountControllerProtocol.h>
#import <Adium/AIService.h>
#import <Adium/AIServiceIcons.h>
#import <AIUtilities/AIMenuAdditions.h>
/*!
* @class AIServiceMenu
* @brief Class to provide a menu of services
*
* See menuOfServicesWithTarget:activeServicesOnly:longDescription:format:
*/
@implementation AIServiceMenu
/*!
* @brief Sort menu items by title
*/
NSInteger titleSort(NSMenuItem *itemA, NSMenuItem *itemB, void *context)
{
return [[itemA title] compare:[itemB title] options:NSLiteralSearch];
}
/*!
* @brief Returns a menu of services.
*
* Each menu item's represented object is the AIService it represents. Services are grouped by 'importance' and sorted alphabetically within groups.
*
* @param target Target on which \@selector(selectAccount:) is called when the user makes a selection
* @param activeServicesOnly If YES, only services for enabled accounts are included. If NO, all possible services are included.
* @param longDescription If YES, use the service's longer (more verbose) description -- for example, AOL Instant Messenger rather than AIM
* @param format Allows the description to be placed within a format string. If it is nil, the description alone will be used.
*/
+ (NSMenu *)menuOfServicesWithTarget:(id)target activeServicesOnly:(BOOL)activeServicesOnly
longDescription:(BOOL)longDescription format:(NSString *)format
{
id<AIAccountController> accountController = adium.accountController;
AIServiceImportance importance;
NSUInteger numberOfItems = 0;
id serviceArray;
BOOL targetRespondsToShouldIncludeService = [target respondsToSelector:@selector(serviceMenuShouldIncludeService:)];
//Prepare our menu
NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] init];
serviceArray = (activeServicesOnly ? (id)[accountController activeServicesIncludingCompatibleServices:YES] : (id)[accountController services]);
//Divide our menu into sections. This helps separate less important services from the others (sorry guys!)
for (importance = AIServicePrimary; importance <= AIServiceUnsupported; importance++) {
NSEnumerator *enumerator;
AIService *service;
NSMutableArray *menuItemArray = [[NSMutableArray alloc] init];
NSMenuItem *menuItem;
NSUInteger currentNumberOfItems;
BOOL addedDivider = NO;
//Divider
currentNumberOfItems = [menu numberOfItems];
if (currentNumberOfItems > numberOfItems) {
[menu addItem:[NSMenuItem separatorItem]];
numberOfItems = currentNumberOfItems + 1;
addedDivider = YES;
}
//Insert a menu item for each service of this importance
enumerator = [serviceArray objectEnumerator];
while ((service = [enumerator nextObject])) {
if (([service serviceImportance] == importance) &&
![service isHidden] &&
(!targetRespondsToShouldIncludeService || [target serviceMenuShouldIncludeService:service])) {
NSString *description = (longDescription ?
[service longDescription] :
[service shortDescription]);
menuItem = [[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:(format ?
[NSString stringWithFormat:format,description] :
description)
target:target
action:@selector(selectServiceType:)
keyEquivalent:@""];
[menuItem setRepresentedObject:service];
[menuItem setImage:[AIServiceIcons serviceIconForService:service
type:AIServiceIconSmall
direction:AIIconNormal]];
[menuItemArray addObject:menuItem];
[menuItem release];
}
}
[menuItemArray sortUsingFunction:titleSort context:NULL];
for (menuItem in menuItemArray) {
[menu addItem:menuItem];
}
[menuItemArray release];
//If we added a divider but didn't add any items, remove it
currentNumberOfItems = [menu numberOfItems];
if (addedDivider && (currentNumberOfItems <= numberOfItems) && (currentNumberOfItems > 0)) {
[menu removeItemAtIndex:(currentNumberOfItems-1)];
}
}
return [menu autorelease];
}
@end
|