Added `-[NSArray validateAsPropertyList]` and `-[NSDictionary validateAsPropertyList...
[adiumx.git] / Source / AIMenuBarIcons.m
blob1938cbc402e549e633c88bda93f1d58f19643203
1 /* 
2  * Adium is the legal property of its developers, whose names are listed in the copyright file included
3  * with this source distribution.
4  * 
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.
8  * 
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.
12  * 
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.
15  */
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;
27 @end
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];
37         }
38         return self;
41 - (NSImage *)imageOfType:(NSString *)imageType alternate:(BOOL)alternate
43         NSImage *image;
45         // Default to Online if key not found.
46         if (![self keyOfTypeExists:imageType]) {
47                 imageType = @"Online";
48         }
50         image = [(alternate ? alternateImageStates : imageStates) objectForKey:imageType];
51         if (!image) { // Image not already stored.
52                 if (alternate) {
53                         NSImage *normalImage = [self imageOfType:imageType alternate:NO];
54                         image = [self alternateImageForImage:normalImage];
55                         [alternateImageStates setObject:image forKey:imageType];
56                 } else {
57                         image = [self imageForKey:imageType];
58                         if (image) { // Make sure the image exists.
59                                 [imageStates setObject:image forKey:imageType];
60                         }
61                 }
62         }
63         return image;
66 - (NSImage *)imageForKey:(NSString *)keyName
68         NSString *imagePath;
69         
70         // This set doesn't contain an Icons dictionary entry. It's invalid.
71         if (!iconInfo) {
72                 return nil;
73         }
74         
75         imagePath = [xtraBundle pathForImageResource:[iconInfo objectForKey:keyName]];
76         return [[[NSImage alloc] initWithContentsOfFile:imagePath] autorelease];
79 - (BOOL)keyOfTypeExists:(NSString *)keyName
81         if (!iconInfo || ![iconInfo objectForKey:keyName]) {
82                 return NO;
83         }
84         return YES;
87 - (void)dealloc
89         [imageStates release];
90         [alternateImageStates release];
91         [super dealloc];
94 #define PREVIEW_MENU_IMAGE_SIZE         18
95 #define PREVIEW_MENU_IMAGE_MARGIN       2
97 + (NSImage *)previewMenuImageForIconPackAtPath:(NSString *)inPath
99         NSImage                 *image;
100         NSBundle                *menuIconsBundle = [[NSBundle alloc] initWithPath:inPath];
101         NSDictionary    *imageInfo;
102         
103         if (!menuIconsBundle) {
104                 return nil;
105         }
106         
107         imageInfo = [menuIconsBundle objectForInfoDictionaryKey:KEY_ICONS_DICT];
108         
109         if (!imageInfo) {
110                 [menuIconsBundle release];
111                 return nil;
112         }
114         image = [[NSImage alloc] initWithSize:NSMakeSize((PREVIEW_MENU_IMAGE_SIZE + PREVIEW_MENU_IMAGE_MARGIN) * 2,
115                                                                                                          PREVIEW_MENU_IMAGE_SIZE)];
116                                                                                                          
118         if ([[menuIconsBundle objectForInfoDictionaryKey:@"XtraBundleVersion"] intValue] == 1) {
119                 NSEnumerator    *enumerator = [[NSArray arrayWithObjects:@"Online",@"Offline",nil] objectEnumerator];
120                 NSString                *iconID;
121                 int                             xOrigin = 0;
123                 [image lockFocus];
124                 while ((iconID = [enumerator nextObject])) {
125                         NSString        *anIconPath = [menuIconsBundle pathForImageResource:[imageInfo objectForKey:iconID]];
126                         NSImage         *anIcon;
128                         if ((anIcon = [[[NSImage alloc] initWithContentsOfFile:anIconPath] autorelease])) {
129                                 NSSize  anIconSize = [anIcon size];
130                                 NSRect  targetRect = NSMakeRect(xOrigin, 0, PREVIEW_MENU_IMAGE_SIZE, PREVIEW_MENU_IMAGE_SIZE);
132                                 if (anIconSize.width < targetRect.size.width) {
133                                         float difference = (targetRect.size.width - anIconSize.width)/2;
135                                         targetRect.size.width -= difference;
136                                         targetRect.origin.x += difference;
137                                 }
139                                 if (anIconSize.height < targetRect.size.height) {
140                                         float difference = (targetRect.size.height - anIconSize.height)/2;
142                                         targetRect.size.height -= difference;
143                                         targetRect.origin.y += difference;
144                                 }
146                                 [anIcon drawInRect:targetRect
147                                                         fromRect:NSMakeRect(0,0,anIconSize.width,anIconSize.height)
148                                                    operation:NSCompositeCopy
149                                                         fraction:1.0];
151                                 //Shift right in preparation for next image
152                                 xOrigin += PREVIEW_MENU_IMAGE_SIZE + PREVIEW_MENU_IMAGE_MARGIN;
153                         }
154                 }
155                 [image unlockFocus];
156                 [menuIconsBundle release];
157         }
159         return [image autorelease];
162 // Returns an inverted image.
163 - (NSImage *)alternateImageForImage:(NSImage *)inImage
165         NSImage                         *altImage = [[NSImage alloc] initWithSize:[inImage size]];
166         NSBitmapImageRep        *srcImageRep = [inImage bitmapRep];
168         id monochromeFilter, invertFilter, alphaFilter;
169         
170         monochromeFilter = [CIFilter filterWithName:@"CIColorMonochrome"];
171         [monochromeFilter setValue:[[[CIImage alloc] initWithBitmapImageRep:srcImageRep] autorelease]
172                                                 forKey:@"inputImage"]; 
173         [monochromeFilter setValue:[NSNumber numberWithFloat:1.0]
174                                                 forKey:@"inputIntensity"];
175         [monochromeFilter setValue:[[[CIColor alloc] initWithColor:[NSColor blackColor]] autorelease]
176                                                 forKey:@"inputColor"];
177         
178         //Now invert our greyscale image
179         invertFilter = [CIFilter filterWithName:@"CIColorInvert"];
180         [invertFilter setValue:[monochromeFilter valueForKey:@"outputImage"]
181                                         forKey:@"inputImage"]; 
182         
183         //And turn the parts that were previously white (are now black) into transparent
184         alphaFilter = [CIFilter filterWithName:@"CIMaskToAlpha"];
185         [alphaFilter setValue:[invertFilter valueForKey:@"outputImage"]
186                                    forKey:@"inputImage"]; 
187         
188         [altImage lockFocus];
189         id context = [CIContext contextWithCGContext:[[NSGraphicsContext currentContext] graphicsPort] 
190                                                                            options:nil];
191         id result = [alphaFilter valueForKey:@"outputImage"];
192         [context drawImage:result
193                            atPoint:CGPointZero
194                           fromRect:[result extent]];
195         [altImage unlockFocus];
196         
197         return [altImage autorelease];
200 @end