When loading a service icon from service ID and the pack doesn't specify one, ask the first service with that ID for it.
This also will return 'nil' instead of a dead path for service icons which are not supported by an icon pack, but which a service specifies as a default. Refs #12697. (We don't know the paths of default service icons, yet)
2 * Adium is the legal property of its developers, whose names are listed in the copyright file included
3 * with this source distribution.
5 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU
6 * General Public License as published by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
10 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
11 * Public License for more details.
13 * You should have received a copy of the GNU General Public License along with this program; if not,
14 * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 #import <Adium/AIListObject.h>
18 #import <Adium/AIService.h>
19 #import <Adium/AIServiceIcons.h>
20 #import <Adium/AIAccountControllerProtocol.h>
22 static NSMutableDictionary *serviceIcons[NUMBER_OF_SERVICE_ICON_TYPES][NUMBER_OF_ICON_DIRECTIONS];
24 static NSString *serviceIconBasePath = nil;
25 static NSDictionary *serviceIconNames[NUMBER_OF_SERVICE_ICON_TYPES];
27 @interface AIServiceIcons ()
28 + (NSImage *)defaultServiceIconForType:(AIServiceIconType)type serviceID:(NSString *)serviceID;
31 @implementation AIServiceIcons
35 if (self == [AIServiceIcons class]) {
38 //Allocate our service icon cache
39 for (i = 0; i < NUMBER_OF_SERVICE_ICON_TYPES; i++) {
40 for (j = 0; j < NUMBER_OF_ICON_DIRECTIONS; j++) {
41 serviceIcons[i][j] = [[NSMutableDictionary alloc] init];
47 //Retrive the correct service icon for a contact
48 + (NSImage *)serviceIconForObject:(AIListObject *)inObject type:(AIServiceIconType)iconType direction:(AIIconDirection)iconDirection
50 return [self serviceIconForService:inObject.service type:iconType direction:iconDirection];
53 //Retrieve the correct service icon for a service
54 + (NSImage *)serviceIconForService:(AIService *)service type:(AIServiceIconType)iconType direction:(AIIconDirection)iconDirection
56 NSImage *serviceIcon = [self serviceIconForServiceID:service.serviceID type:iconType direction:iconDirection];
58 if (!serviceIcon && service) {
59 //If the icon pack doesn't supply a service icon, query the service itself
60 serviceIcon = [service defaultServiceIconOfType:iconType];
63 if (iconDirection == AIIconFlipped) [serviceIcon setFlipped:YES];
64 [serviceIcons[iconType][iconDirection] setObject:serviceIcon forKey:service.serviceID];
70 + (NSString *)pathForServiceIconForServiceID:(NSString *)serviceID type:(AIServiceIconType)iconType
72 NSString *iconName = [serviceIconNames[iconType] objectForKey:serviceID];
75 return [serviceIconBasePath stringByAppendingPathComponent:iconName];
81 //Retrieve the correct service icon for a service by ID
82 + (NSImage *)serviceIconForServiceID:(NSString *)serviceID type:(AIServiceIconType)iconType direction:(AIIconDirection)iconDirection
86 //Retrieve the service icon from our cache
87 serviceIcon = [serviceIcons[iconType][iconDirection] objectForKey:serviceID];
89 //Load the service icon if necessary
91 NSString *path = [self pathForServiceIconForServiceID:serviceID type:iconType];
94 serviceIcon = [[NSImage alloc] initWithContentsOfFile:path];
96 AIService *service = [adium.accountController firstServiceWithServiceID:serviceID];
98 serviceIcon = [service defaultServiceIconOfType:iconType];
103 if (iconDirection == AIIconFlipped) [serviceIcon setFlipped:YES];
104 [serviceIcons[iconType][iconDirection] setObject:serviceIcon forKey:serviceID];
105 [serviceIcon release];
107 //Attempt to load the default service icon
108 serviceIcon = [self defaultServiceIconForType:iconType serviceID:serviceID];
110 //Cache the default service icon (until the pack is changed) so we have it immediately next time
111 if (iconDirection == AIIconFlipped) [serviceIcon setFlipped:YES];
112 [serviceIcons[iconType][iconDirection] setObject:serviceIcon forKey:serviceID];
120 //Set the active service icon pack
121 + (BOOL)setActiveServiceIconsFromPath:(NSString *)inPath
123 NSDictionary *serviceIconDict = [NSDictionary dictionaryWithContentsOfFile:[inPath stringByAppendingPathComponent:@"Icons.plist"]];
125 if (serviceIconDict && [[serviceIconDict objectForKey:@"AdiumSetVersion"] intValue] == 1) {
126 [serviceIconBasePath release];
127 serviceIconBasePath = [inPath retain];
129 [serviceIconNames[AIServiceIconSmall] release];
130 serviceIconNames[AIServiceIconSmall] = [[serviceIconDict objectForKey:@"Interface-Small"] retain];
132 [serviceIconNames[AIServiceIconLarge] release];
133 serviceIconNames[AIServiceIconLarge] = [[serviceIconDict objectForKey:@"Interface-Large"] retain];
135 [serviceIconNames[AIServiceIconList] release];
136 serviceIconNames[AIServiceIconList] = [[serviceIconDict objectForKey:@"List"] retain];
138 //Clear out the service icon cache
141 for (i = 0; i < NUMBER_OF_SERVICE_ICON_TYPES; i++) {
142 for (j = 0; j < NUMBER_OF_ICON_DIRECTIONS; j++) {
143 [serviceIcons[i][j] removeAllObjects];
147 [[NSNotificationCenter defaultCenter] postNotificationName:AIServiceIconSetDidChangeNotification
156 #define PREVIEW_MENU_IMAGE_SIZE 13
157 #define PREVIEW_MENU_IMAGE_MARGIN 2
159 + (NSImage *)previewMenuImageForIconPackAtPath:(NSString *)inPath
162 NSDictionary *iconDict;
164 image = [[NSImage alloc] initWithSize:NSMakeSize((PREVIEW_MENU_IMAGE_SIZE + PREVIEW_MENU_IMAGE_MARGIN) * 4,
165 PREVIEW_MENU_IMAGE_SIZE)];
167 iconDict = [NSDictionary dictionaryWithContentsOfFile:[inPath stringByAppendingPathComponent:@"Icons.plist"]];
169 if (iconDict && [[iconDict objectForKey:@"AdiumSetVersion"] intValue] == 1) {
170 NSDictionary *previewIconNames = [iconDict objectForKey:@"List"];
171 NSEnumerator *enumerator = [[NSArray arrayWithObjects:@"AIM",@"Jabber",@"MSN",@"Yahoo!",nil] objectEnumerator];
176 while ((iconID = [enumerator nextObject])) {
177 NSString *anIconPath = [inPath stringByAppendingPathComponent:[previewIconNames objectForKey:iconID]];
180 if ((anIcon = [[[NSImage alloc] initWithContentsOfFile:anIconPath] autorelease])) {
181 NSSize anIconSize = [anIcon size];
182 NSRect targetRect = NSMakeRect(xOrigin, 0, PREVIEW_MENU_IMAGE_SIZE, PREVIEW_MENU_IMAGE_SIZE);
184 if (anIconSize.width < targetRect.size.width) {
185 float difference = (targetRect.size.width - anIconSize.width)/2;
187 targetRect.size.width -= difference;
188 targetRect.origin.x += difference;
191 if (anIconSize.height < targetRect.size.height) {
192 float difference = (targetRect.size.height - anIconSize.height)/2;
194 targetRect.size.height -= difference;
195 targetRect.origin.y += difference;
198 [anIcon drawInRect:targetRect
199 fromRect:NSMakeRect(0,0,anIconSize.width,anIconSize.height)
200 operation:NSCompositeCopy
203 //Shift right in preparation for next image
204 xOrigin += PREVIEW_MENU_IMAGE_SIZE + PREVIEW_MENU_IMAGE_MARGIN;
210 return [image autorelease];
213 #pragma mark Default loading
215 #define PREF_GROUP_APPEARANCE @"Appearance"
216 #define KEY_SERVICE_ICON_PACK @"Service Icon Pack"
218 + (NSImage *)defaultServiceIconForType:(AIServiceIconType)type serviceID:(NSString *)serviceID
220 NSString *defaultName, *defaultPath;
221 NSDictionary *serviceIconDict;
222 NSImage *defaultServiceIcon = nil;
224 defaultName = [adium.preferenceController defaultPreferenceForKey:KEY_SERVICE_ICON_PACK
225 group:PREF_GROUP_APPEARANCE
227 defaultPath = [adium pathOfPackWithName:defaultName
228 extension:@"AdiumServiceIcons"
229 resourceFolderName:@"Service Icons"];
231 serviceIconDict = [NSDictionary dictionaryWithContentsOfFile:[defaultPath stringByAppendingPathComponent:@"Icons.plist"]];
232 if (serviceIconDict && [[serviceIconDict objectForKey:@"AdiumSetVersion"] intValue] == 1) {
233 NSString *nameKey = nil;
236 case AIServiceIconSmall:
237 nameKey = @"Interface-Small";
239 case AIServiceIconLarge:
240 nameKey = @"Interface-Large";
242 case AIServiceIconList:
248 NSDictionary *defaultServiceIconNames;
249 NSString *thisServiceIconImageName;
251 defaultServiceIconNames = [serviceIconDict objectForKey:nameKey];
252 if ((thisServiceIconImageName = [defaultServiceIconNames objectForKey:serviceID])) {
253 NSString *iconPath = [defaultPath stringByAppendingPathComponent:thisServiceIconImageName];
255 defaultServiceIcon = [[[NSImage alloc] initWithContentsOfFile:iconPath] autorelease];
260 return defaultServiceIcon;