Prevent sending 0-byte files. Fixes #8711.
[adiumx.git] / Source / AIContactListRecentImagesWindowController.m
blob868fe64922bc78ad467e54977420b8ddf858e9db
1 //
2 //  AIContactListRecentImagesWindowController.m
3 //  Adium
4 //
5 //  Created by Evan Schoenberg on 12/19/05.
6 //
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
28 #define FADE_TIME               .3
30 @interface AIContactListRecentImagesWindowController (PRIVATE)
31 - (id)initWithWindowNibName:(NSString *)inWindowNibName
32                                 imagePicker:(AIContactListImagePicker *)inPicker
33           recentPictureSelector:(SEL)inRecentPictureSelector;
34 - (void)fadeOutAndClose;
35 @end
37 @implementation AIContactListRecentImagesWindowController
38 /*!
39  * @brief Show the window
40  *
41  * @param inPoint The bottom-right corner of our parent view
42  */
43 + (void)showWindowFromPoint:(NSPoint)inPoint
44                                 imagePicker:(AIContactListImagePicker *)inPicker
45           recentPictureSelector:(SEL)inRecentPictureSelector
47         AIContactListRecentImagesWindowController       *controller = [[self alloc] initWithWindowNibName:@"ContactListRecentImages"
48                                                                                                                                                                           imagePicker:inPicker
49                                                                                                                                                         recentPictureSelector:inRecentPictureSelector];
51         NSWindow                        *window = [controller window];
53         [controller positionFromPoint:inPoint];
54         [(AIBorderlessWindow *)window setMoveable:NO];
55         
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;
67                 
68                 [[NSNotificationCenter defaultCenter] addObserver:self
69                                                                                                  selector:@selector(parentWindowWillClose:)
70                                                                                                          name:NSWindowWillCloseNotification
71                                                                                                    object:[picker window]];
72         }
73         
74         return self;
77 - (void)dealloc
79         [[NSNotificationCenter defaultCenter] removeObserver:self];
80         [picker release];
81         
82         [super dealloc];
85 - (void)windowDidLoad
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];
101         
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;
107         }
108         
109         frame.origin.y = inPoint.y - frame.size.height;
110         if (frame.origin.y < screenFrame.origin.y) {
111                 frame.origin.y = screenFrame.origin.y;
112         }
113         
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];
117         }
118         
119         [window setFrame:frame display:NO animate:NO];  
122 - (int)numberOfImagesInImageGridView:(AIImageGridView *)imageGridView
124         return 10;
127 - (NSArray *)recentPictures
129         if ([NSApp isOnLeopardOrBetter]) {
130                 return [(IKPictureTakerRecentPictureRepository *)[NSClassFromString(@"IKPictureTakerRecentPictureRepository") recentRepository] recentPictures];
131                 
132         } else {
133                 return [NSClassFromString(@"NSIPRecentPicture") recentPictures];
134         }
137 - (NSArray *)recentSmallIcons
139         if ([NSApp isOnLeopardOrBetter]) {
140                 return [[(IKPictureTakerRecentPictureRepository *)[NSClassFromString(@"IKPictureTakerRecentPictureRepository") recentRepository] recentPictures] valueForKey:@"smallIcon"];
142         } else {
143                 return [NSClassFromString(@"NSIPRecentPicture") recentSmallIcons];
144         }
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];
156                 
157                 [displayImage setFlipped:YES];
158                 [displayImage lockFocus];
159                 
160                 if (index == currentHoveredIndex) {
161                         [[[NSColor blueColor] colorWithAlphaComponent:0.30] set];
162                         [fullPath fill];
163                         
164                         [[NSColor blueColor] set];
165                         [fullPath stroke];
166                         
167                 } else {
168                         [[NSColor whiteColor] set];
169                         [fullPath stroke];
170                 }
171                 
172                 [displayImage unlockFocus];
173         } else {
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];
179                 
180                 [[NSColor lightGrayColor] set];
181                 [fullPath fill];
182                 
183                 [displayImage unlockFocus];
184         }
185         
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];
216         }
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];
235         
236         [self fadeOutAndClose];
239 - (void)clearRecentPictures:(id)sender
241         if ([NSApp isOnLeopardOrBetter]) {
242                 [[NSClassFromString(@"IKPictureTakerRecentPictureRepository") recentRepository] clearRecents:nil];
244         } else {
245                 [NSClassFromString(@"NSIPRecentPicture") removeAllButCurrent];
246         }
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
263         [self close];
266 #pragma mark Fading
267 - (void)fadeOut:(NSTimer *)inTimer
269         float                           currentAlpha = [[self window] alphaValue];
270         currentAlpha -= 0.15;
271         
272         if (currentAlpha <= 0) {
273                 [self close];
274                 [inTimer invalidate];
276         } else {
277                 [[self window] setAlphaValue:currentAlpha];
278         }
281 - (void)fadeOutAndClose
283         [NSTimer scheduledTimerWithTimeInterval:.01
284                                                                          target:self 
285                                                                    selector:@selector(fadeOut:)
286                                                                    userInfo:nil
287                                                                         repeats:YES];
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];
302         
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);
308                 AIAccount        *account;
309                 NSEnumerator *enumerator;
311                 menuItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString(@"Change Icon For:", nil)
312                                                                                           target:nil
313                                                                                           action:nil
314                                                                            keyEquivalent:@""];
315                 [menuItem setEnabled:NO];
316                 [menu addItem:menuItem];
317                 [menuItem release];
318                 
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]
323                                                                                                   target:self
324                                                                                                   action:@selector(selectedAccount:)
325                                                                                    keyEquivalent:@""];
326                         [menuItem setRepresentedObject:account];
328                         if (activeAccount == account) {
329                                 [menuItem setState:NSOnState];
330                         }
331                         [menuItem setIndentationLevel:1];
332                         [menu addItem:menuItem];
333                         
334                         [menuItem release];
335                 }
336                 
337                 if (includeGlobal) {
338                         menuItem = [[NSMenuItem alloc] initWithTitle:ALL_OTHER_ACCOUNTS
339                                                                                                   target:self
340                                                                                                   action:@selector(selectedAccount:)
341                                                                                    keyEquivalent:@""];
342                         if (!activeAccount) {
343                                 [menuItem setState:NSOnState];
344                         }
345                         [menuItem setIndentationLevel:1];
347                         [menu addItem:menuItem];
348                         [menuItem release];
349                 }
350                 
351                 [menu addItem:[NSMenuItem separatorItem]];
353         } else {
354                 //All accounts are using the global preference
355         }
357         menuItem = [[NSMenuItem alloc] initWithTitle:[AILocalizedString(@"Choose Icon", nil) stringByAppendingEllipsis]
358                                                                                   target:self
359                                                                                   action:@selector(chooseIcon:)
360                                                                    keyEquivalent:@""];
361         [menu addItem:menuItem];
362         [menuItem release];
364         menuItem = [[NSMenuItem alloc] initWithTitle:AILocalizedString(@"Clear Recent Pictures", nil)
365                                                                                   target:self
366                                                                                   action:@selector(clearRecentPictures:)
367                                                                    keyEquivalent:@""];
368         [menu addItem:menuItem];
369         [menuItem release];
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];
384                 
385                 myFrame.size.height += heightDifference;
386                 myFrame.origin.y -= heightDifference;
387                 
388                 [[self window] setFrame:myFrame display:YES animate:NO];
389         }
393 @end