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 "AIMenuBarIcons.h"
18 #import <AIXtraInfo.h>
19 #import <AIUtilities/AIImageAdditions.h>
20 #import <QuartzCore/CoreImage.h>
22 #define KEY_ICONS_DICT @"Icons"
24 @interface AIMenuBarIcons (PRIVATE)
25 - (NSImage *)imageForKey:(NSString *)keyName;
26 - (BOOL)keyOfTypeExists:(NSString *)keyName;
29 @implementation AIMenuBarIcons
31 - (id)initWithURL:(NSURL *)url
33 if ((self = [super initWithURL:url])) {
34 imageStates = [[NSMutableDictionary alloc] init];
35 alternateImageStates = [[NSMutableDictionary alloc] init];
36 iconInfo = [xtraBundle objectForInfoDictionaryKey:KEY_ICONS_DICT];
43 return [[xtraBundle objectForInfoDictionaryKey:@"Show Badge"] boolValue];
46 - (NSImage *)imageOfType:(NSString *)imageType alternate:(BOOL)alternate
50 // Default to Online if key not found.
51 if (![self keyOfTypeExists:imageType]) {
52 imageType = @"Online";
55 image = [(alternate ? alternateImageStates : imageStates) objectForKey:imageType];
56 if (!image) { // Image not already stored.
58 NSImage *normalImage = [self imageOfType:imageType alternate:NO];
59 image = [self alternateImageForImage:normalImage];
60 [alternateImageStates setObject:image forKey:imageType];
62 image = [self imageForKey:imageType];
63 if (image) { // Make sure the image exists.
64 [imageStates setObject:image forKey:imageType];
71 - (NSImage *)imageForKey:(NSString *)keyName
75 // This set doesn't contain an Icons dictionary entry. It's invalid.
80 imagePath = [xtraBundle pathForImageResource:[iconInfo objectForKey:keyName]];
81 return [[[NSImage alloc] initWithContentsOfFile:imagePath] autorelease];
84 - (BOOL)keyOfTypeExists:(NSString *)keyName
86 if (!iconInfo || ![iconInfo objectForKey:keyName]) {
94 [imageStates release];
95 [alternateImageStates release];
99 #define PREVIEW_MENU_IMAGE_SIZE 18
100 #define PREVIEW_MENU_IMAGE_MARGIN 2
102 + (NSImage *)previewMenuImageForIconPackAtPath:(NSString *)inPath
105 NSBundle *menuIconsBundle = [[NSBundle alloc] initWithPath:inPath];
106 NSDictionary *imageInfo;
108 if (!menuIconsBundle) {
112 imageInfo = [menuIconsBundle objectForInfoDictionaryKey:KEY_ICONS_DICT];
115 [menuIconsBundle release];
119 image = [[NSImage alloc] initWithSize:NSMakeSize((PREVIEW_MENU_IMAGE_SIZE + PREVIEW_MENU_IMAGE_MARGIN) * 2,
120 PREVIEW_MENU_IMAGE_SIZE)];
123 if ([[menuIconsBundle objectForInfoDictionaryKey:@"XtraBundleVersion"] intValue] == 1) {
124 NSEnumerator *enumerator = [[NSArray arrayWithObjects:@"Online",@"Offline",nil] objectEnumerator];
129 while ((iconID = [enumerator nextObject])) {
130 NSString *anIconPath = [menuIconsBundle pathForImageResource:[imageInfo objectForKey:iconID]];
133 if ((anIcon = [[[NSImage alloc] initWithContentsOfFile:anIconPath] autorelease])) {
134 NSSize anIconSize = [anIcon size];
135 NSRect targetRect = NSMakeRect(xOrigin, 0, PREVIEW_MENU_IMAGE_SIZE, PREVIEW_MENU_IMAGE_SIZE);
137 if (anIconSize.width < targetRect.size.width) {
138 float difference = (targetRect.size.width - anIconSize.width)/2;
140 targetRect.size.width -= difference;
141 targetRect.origin.x += difference;
144 if (anIconSize.height < targetRect.size.height) {
145 float difference = (targetRect.size.height - anIconSize.height)/2;
147 targetRect.size.height -= difference;
148 targetRect.origin.y += difference;
151 [anIcon drawInRect:targetRect
152 fromRect:NSMakeRect(0,0,anIconSize.width,anIconSize.height)
153 operation:NSCompositeCopy
156 //Shift right in preparation for next image
157 xOrigin += PREVIEW_MENU_IMAGE_SIZE + PREVIEW_MENU_IMAGE_MARGIN;
161 [menuIconsBundle release];
164 return [image autorelease];
167 // Returns an inverted image.
168 - (NSImage *)alternateImageForImage:(NSImage *)inImage
170 NSImage *altImage = [[NSImage alloc] initWithSize:[inImage size]];
171 NSBitmapImageRep *srcImageRep = [inImage bitmapRep];
173 id monochromeFilter, invertFilter, alphaFilter;
175 monochromeFilter = [CIFilter filterWithName:@"CIColorMonochrome"];
176 [monochromeFilter setValue:[[[CIImage alloc] initWithBitmapImageRep:srcImageRep] autorelease]
177 forKey:@"inputImage"];
178 [monochromeFilter setValue:[NSNumber numberWithFloat:1.0]
179 forKey:@"inputIntensity"];
180 [monochromeFilter setValue:[[[CIColor alloc] initWithColor:[NSColor blackColor]] autorelease]
181 forKey:@"inputColor"];
183 //Now invert our greyscale image
184 invertFilter = [CIFilter filterWithName:@"CIColorInvert"];
185 [invertFilter setValue:[monochromeFilter valueForKey:@"outputImage"]
186 forKey:@"inputImage"];
188 //And turn the parts that were previously white (are now black) into transparent
189 alphaFilter = [CIFilter filterWithName:@"CIMaskToAlpha"];
190 [alphaFilter setValue:[invertFilter valueForKey:@"outputImage"]
191 forKey:@"inputImage"];
193 [altImage lockFocus];
194 id context = [CIContext contextWithCGContext:[[NSGraphicsContext currentContext] graphicsPort]
196 id result = [alphaFilter valueForKey:@"outputImage"];
197 [context drawImage:result
199 fromRect:[result extent]];
200 [altImage unlockFocus];
202 return [altImage autorelease];