2 // AIContactListRecentImagesWindowController.m
5 // Created by Evan Schoenberg on 12/19/05.
8 #import "AIContactListRecentImagesWindowController.h"
9 #import <Adium/AIAccountControllerProtocol.h>
10 #import <Adium/AIContactControllerProtocol.h>
11 #import <Adium/AIPreferenceControllerProtocol.h>
12 #import "AIStandardListWindowController.h"
13 #import "AIContactListImagePicker.h"
14 #import "AIMenuItemView.h"
15 #import <Adium/AIAccount.h>
16 #import <AIUtilities/AIApplicationAdditions.h>
17 #import <AIUtilities/AIBorderlessWindow.h>
18 #import <AIUtilities/AIColoredBoxView.h>
19 #import <AIUtilities/AIImageGridView.h>
20 #import <AIUtilities/AIImageAdditions.h>
21 #import <AIUtilities/AIMenuAdditions.h>
22 #import <AIUtilities/AIStringAdditions.h>
24 #import "NSIPRecentPicture.h" //10.4, private
25 #import "IKRecentPicture.h" //10.5+, private
27 #define FADE_INCREMENT 0.3
30 @interface AIContactListRecentImagesWindowController (PRIVATE)
31 - (id)initWithWindowNibName:(NSString *)inWindowNibName
32 imagePicker:(AIContactListImagePicker *)inPicker
33 recentPictureSelector:(SEL)inRecentPictureSelector;
34 - (void)fadeOutAndClose;
37 @implementation AIContactListRecentImagesWindowController
39 * @brief Show the window
41 * @param inPoint The bottom-right corner of our parent view
43 + (void)showWindowFromPoint:(NSPoint)inPoint
44 imagePicker:(AIContactListImagePicker *)inPicker
45 recentPictureSelector:(SEL)inRecentPictureSelector
47 AIContactListRecentImagesWindowController *controller = [[self alloc] initWithWindowNibName:@"ContactListRecentImages"
49 recentPictureSelector:inRecentPictureSelector];
51 NSWindow *window = [controller window];
53 [controller positionFromPoint:inPoint];
54 [(AIBorderlessWindow *)window setMoveable:NO];
56 [controller showWindow:nil];
57 [window makeKeyAndOrderFront:nil];
60 - (id)initWithWindowNibName:(NSString *)inWindowNibName
61 imagePicker:(AIContactListImagePicker *)inPicker
62 recentPictureSelector:(SEL)inRecentPictureSelector
64 if ((self = [super initWithWindowNibName:inWindowNibName])) {
65 picker = [inPicker retain];
66 recentPictureSelector = inRecentPictureSelector;
68 [[NSNotificationCenter defaultCenter] addObserver:self
69 selector:@selector(parentWindowWillClose:)
70 name:NSWindowWillCloseNotification
71 object:[picker window]];
79 [[NSNotificationCenter defaultCenter] removeObserver:self];
87 [imageGridView setImageSize:NSMakeSize(30, 30)];
88 [coloredBox setColor:[NSColor windowBackgroundColor]];
89 [label_recentIcons setLocalizedString:AILocalizedString(@"Recent Icons:", "Label at the top of the recent icons picker shown in the contact list")];
91 [picker setMaxSize:NSMakeSize(256, 256)];
93 currentHoveredIndex = -1;
96 - (void)positionFromPoint:(NSPoint)inPoint
98 NSWindow *window = [self window];
99 NSRect frame = [window frame];
100 NSRect screenFrame = [[window screen] visibleFrame];
102 frame.origin.x = inPoint.x - frame.size.width;
103 if (frame.origin.x < screenFrame.origin.x) {
104 frame.origin.x = screenFrame.origin.x;
105 } else if (frame.origin.x + frame.size.width > screenFrame.origin.x + screenFrame.size.width) {
106 frame.origin.x = screenFrame.origin.x + screenFrame.size.width - frame.size.width;
109 frame.origin.y = inPoint.y - frame.size.height;
110 if (frame.origin.y < screenFrame.origin.y) {
111 frame.origin.y = screenFrame.origin.y;
114 //Ensure our window is visible above the window of the imagePicker that created us
115 if ([window level] < [[picker window] level]) {
116 [window setLevel:[[picker window] level] + 1];
119 [window setFrame:frame display:NO animate:NO];
122 - (int)numberOfImagesInImageGridView:(AIImageGridView *)imageGridView
127 - (NSArray *)recentPictures
129 if ([NSApp isOnLeopardOrBetter]) {
130 return [(IKPictureTakerRecentPictureRepository *)[NSClassFromString(@"IKPictureTakerRecentPictureRepository") recentRepository] recentPictures];
133 return [NSClassFromString(@"NSIPRecentPicture") recentPictures];
137 - (NSArray *)recentSmallIcons
139 if ([NSApp isOnLeopardOrBetter]) {
140 return [[(IKPictureTakerRecentPictureRepository *)[NSClassFromString(@"IKPictureTakerRecentPictureRepository") recentRepository] recentPictures] valueForKey:@"smallIcon"];
143 return [NSClassFromString(@"NSIPRecentPicture") recentSmallIcons];
147 - (NSImage *)imageGridView:(AIImageGridView *)imageGridView imageAtIndex:(int)index
149 NSImage *displayImage;
150 NSArray *recentSmallIcons = [self recentSmallIcons];
151 if (index < [recentSmallIcons count]) {
152 NSImage *image = [recentSmallIcons objectAtIndex:index];
153 NSSize size = [image size];
154 NSBezierPath *fullPath = [NSBezierPath bezierPathWithRect:NSMakeRect(0, 0, size.width, size.height)];
155 displayImage = [image copy];
157 [displayImage setFlipped:YES];
158 [displayImage lockFocus];
160 if (index == currentHoveredIndex) {
161 [[[NSColor blueColor] colorWithAlphaComponent:0.30] set];
164 [[NSColor blueColor] set];
168 [[NSColor whiteColor] set];
172 [displayImage unlockFocus];
174 NSSize size = NSMakeSize(32, 32);
175 NSBezierPath *fullPath = [NSBezierPath bezierPathWithRect:NSMakeRect(0, 0, size.width, size.height)];
177 displayImage = [[NSImage alloc] initWithSize:size];
178 [displayImage lockFocus];
180 [[NSColor lightGrayColor] set];
183 [displayImage unlockFocus];
186 return [displayImage autorelease];
189 - (void)imageGridView:(AIImageGridView *)inImageGridView cursorIsHoveringImageAtIndex:(int)index
191 //Update our hovered index and redisplay the image
192 currentHoveredIndex = index;
193 [imageGridView setNeedsDisplayOfImageAtIndex:index];
196 - (void)imageGridViewSelectionDidChange:(NSNotification *)notification
198 int selectedIndex = [imageGridView selectedIndex];
199 NSArray *recentPictures = [self recentPictures];
200 if (selectedIndex < [recentPictures count]) {
201 id recentPicture = [recentPictures objectAtIndex:selectedIndex];
202 NSData *imageData = nil;
203 if ([recentPicture respondsToSelector:@selector(editedImage)])
204 imageData = [[recentPicture editedImage] PNGRepresentation];
205 else if ([recentPicture respondsToSelector:@selector(croppedImage)])
206 imageData = [[recentPicture croppedImage] PNGRepresentation];
207 else if ([recentPicture respondsToSelector:@selector(originalImagePath)])
208 imageData = [NSData dataWithContentsOfFile:[recentPicture originalImagePath]];
210 //Notify as if the image had been selected in the picker
211 [[picker delegate] imageViewWithImagePicker:picker
212 didChangeToImageData:imageData];
214 //Now pass on the actual recent picture for use if possible
215 [picker setRecentPictureAsImageInput:recentPicture];
217 [self fadeOutAndClose];
220 - (void)selectedAccount:(id)sender
222 AIAccount *activeAccount = [sender representedObject];
224 //Change the active account
225 [[adium preferenceController] setPreference:(activeAccount ? [activeAccount internalObjectID] : nil)
226 forKey:@"Active Icon Selection Account"
227 group:GROUP_ACCOUNT_STATUS];
229 [menuItemView setMenu:[self menuForMenuItemView:menuItemView]];
232 - (void)chooseIcon:(id)sender
234 [picker showImagePicker:nil];
236 [self fadeOutAndClose];
239 - (void)clearRecentPictures:(id)sender
241 if ([NSApp isOnLeopardOrBetter]) {
242 [[NSClassFromString(@"IKPictureTakerRecentPictureRepository") recentRepository] clearRecents:nil];
245 [NSClassFromString(@"NSIPRecentPicture") removeAllButCurrent];
247 [imageGridView reloadData];
250 - (void)windowDidResignMain:(NSNotification *)aNotification
252 [self fadeOutAndClose];
255 - (void)windowDidResignKey:(NSNotification *)aNotification
257 [self fadeOutAndClose];
260 - (void)parentWindowWillClose:(NSNotification *)aNotification
262 //Close, no fade, when our parent window closes
267 - (void)fadeOut:(NSTimer *)inTimer
269 float currentAlpha = [[self window] alphaValue];
270 currentAlpha -= 0.15;
272 if (currentAlpha <= 0) {
274 [inTimer invalidate];
277 [[self window] setAlphaValue:currentAlpha];
281 - (void)fadeOutAndClose
283 [NSTimer scheduledTimerWithTimeInterval:.01
285 selector:@selector(fadeOut:)
290 #pragma mark AIMenuItemView delegate
292 - (NSMenu *)menuForMenuItemView:(AIMenuItemView *)inMenuItemView
294 NSMenu *menu = [[NSMenu alloc] init];
295 NSMutableSet *onlineAccounts = [NSMutableSet set];
296 NSMutableSet *ownIconAccounts = [NSMutableSet set];
297 AIAccount *activeAccount = nil;
298 NSMenuItem *menuItem;
300 activeAccount = [AIStandardListWindowController activeAccountForIconsGettingOnlineAccounts:onlineAccounts
301 ownIconAccounts:ownIconAccounts];
303 int ownIconAccountsCount = [ownIconAccounts count];
304 int onlineAccountsCount = [onlineAccounts count];
305 if (ownIconAccountsCount && ((ownIconAccountsCount > 1) || (onlineAccountsCount > 1))) {
306 //There are at least some accounts using the global preference if the counts differ
307 BOOL includeGlobal = (onlineAccountsCount != ownIconAccountsCount);
309 NSEnumerator *enumerator;
311 menuItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString(@"Change Icon For:", nil)
315 [menuItem setEnabled:NO];
316 [menu addItem:menuItem];
319 enumerator = [ownIconAccounts objectEnumerator];
320 while ((account = [enumerator nextObject])) {
321 //Put a check before the account if it is the active account
322 menuItem = [[NSMenuItem alloc] initWithTitle:[account formattedUID]
324 action:@selector(selectedAccount:)
326 [menuItem setRepresentedObject:account];
328 if (activeAccount == account) {
329 [menuItem setState:NSOnState];
331 [menuItem setIndentationLevel:1];
332 [menu addItem:menuItem];
338 menuItem = [[NSMenuItem alloc] initWithTitle:ALL_OTHER_ACCOUNTS
340 action:@selector(selectedAccount:)
342 if (!activeAccount) {
343 [menuItem setState:NSOnState];
345 [menuItem setIndentationLevel:1];
347 [menu addItem:menuItem];
351 [menu addItem:[NSMenuItem separatorItem]];
354 //All accounts are using the global preference
357 menuItem = [[NSMenuItem alloc] initWithTitle:[AILocalizedString(@"Choose Icon", nil) stringByAppendingEllipsis]
359 action:@selector(chooseIcon:)
361 [menu addItem:menuItem];
364 menuItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString(@"Clear Recent Pictures", nil)
366 action:@selector(clearRecentPictures:)
368 [menu addItem:menuItem];
371 return [menu autorelease];
374 - (void)menuItemViewDidChangeMenu:(AIMenuItemView *)inMenuItemView
376 NSRect oldFrame = [inMenuItemView frame];
377 [inMenuItemView sizeToFit];
378 NSRect newFrame = [inMenuItemView frame];
380 float heightDifference = newFrame.size.height - oldFrame.size.height;
382 if (heightDifference != 0) {
383 NSRect myFrame = [[self window] frame];
385 myFrame.size.height += heightDifference;
386 myFrame.origin.y -= heightDifference;
388 [[self window] setFrame:myFrame display:YES animate:NO];