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 "AIDockController.h"
18 #import "AIDockIconSelectionSheet.h"
19 #import "AIAppearancePreferencesPlugin.h"
20 #import <Adium/AIPreferenceControllerProtocol.h>
21 #import <AIUtilities/AIFileManagerAdditions.h>
22 #import <AIUtilities/AIImageGridView.h>
23 #import <Adium/AIIconState.h>
25 #define PREF_GROUP_DOCK_ICON @"Dock Icon"
26 #define DEFAULT_DOCK_ICON_NAME @"Adiumy Green"
28 @interface AIDockIconSelectionSheet (PRIVATE)
29 - (void)selectIconWithName:(NSString *)selectName;
30 - (void)xtrasChanged:(NSNotification *)notification;
31 - (void)selectIconWithName:(NSString *)selectName;
34 @implementation AIDockIconSelectionSheet
36 + (void)showDockIconSelectorOnWindow:(NSWindow *)parentWindow
38 AIDockIconSelectionSheet *controller;
40 controller = [[self alloc] initWithWindowNibName:@"DockIconSelectionSheet"];
43 [NSApp beginSheet:[controller window]
44 modalForWindow:parentWindow
45 modalDelegate:controller
46 didEndSelector:@selector(sheetDidEnd:returnCode:contextInfo:)
49 [controller showWindow:nil];
50 [[controller window] makeKeyAndOrderFront:nil];
51 [NSApp activateIgnoringOtherApps:YES];
56 * Invoked as the sheet closes, dismiss the sheet
58 - (void)sheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo
62 [self setAnimatedDockIconAtIndex:-1];
66 //Setup our preference view
73 //Setup our image grid
74 [imageGridView_icons setImageSize:NSMakeSize(64,64)];
76 //Observe xtras changes
77 [[adium notificationCenter] addObserver:self
78 selector:@selector(xtrasChanged:)
79 name:Adium_Xtras_Changed
81 [self xtrasChanged:nil];
83 [button_OK setLocalizedString:AILocalizedStringFromTable(@"Close", @"Buttons", nil)];
85 [super windowDidLoad];
90 [[adium notificationCenter] removeObserver:self];
91 [iconArray release]; iconArray = nil;
96 //Preference view is closing
97 - (void)windowWillClose:(id)sender
99 [super windowWillClose:sender];
101 [self setAnimatedDockIconAtIndex:-1];
105 //When the xtras are changed, update our icons
106 - (void)xtrasChanged:(NSNotification *)notification
108 if (!notification || [[notification object] caseInsensitiveCompare:@"AdiumIcon"] == 0) {
110 iconArray = [[NSMutableArray alloc] init];
112 //Fetch the pack previews
113 NSEnumerator *enumerator = [[[adium dockController] availableDockIconPacks] objectEnumerator];
116 while ((path = [enumerator nextObject])) {
117 AIIconState *previewState = [[adium dockController] previewStateForIconPackAtPath:path];
118 [iconArray addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:path, @"Path", previewState, @"State", nil]];
121 [imageGridView_icons reloadData];
122 [self selectIconWithName:[[adium preferenceController] preferenceForKey:KEY_ACTIVE_DOCK_ICON
123 group:PREF_GROUP_APPEARANCE]];
131 //Build an array of available icon packs
135 //- (void)_buildIconArray
137 // NSDirectoryEnumerator *fileEnumerator;
138 // NSString *iconPath;
139 // NSString *filePath;
140 // NSEnumerator *enumerator;
142 // //Create a fresh icon array
143 // [iconArray release]; iconArray = [[NSMutableArray alloc] init];
144 // enumerator = [[adium resourcePathsForName:FOLDER_DOCK_ICONS] objectEnumerator];
146 // while ((iconPath = [enumerator nextObject])) {
147 // fileEnumerator = [[NSFileManager defaultManager] enumeratorAtPath:iconPath];
149 // //Find all the .AdiumIcon's
150 // while ((filePath = [fileEnumerator nextObject])) {
151 // if ([[filePath pathExtension] caseInsensitiveCompare:@"AdiumIcon"] == NSOrderedSame) {
152 // NSString *fullPath;
153 // AIIconState *previewState;
155 // //Get the icon pack's full path and preview state
156 // fullPath = [iconPath stringByAppendingPathComponent:filePath];
157 // previewState = [[adium dockController] previewStateForIconPackAtPath:fullPath];
159 // //Add this icon to our icon array
160 // [iconArray addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:fullPath, @"Path", previewState, @"State", previewState, @"Original State", nil]];
165 // //Update our view and re-select the correct icon
166 // [imageGridView_icons reloadData];
167 // [self selectIconWithName:[[adium preferenceController] preferenceForKey:KEY_ACTIVE_DOCK_ICON group:PREF_GROUP_APPEARANCE]];
170 //Set the selected icon by name
171 - (void)selectIconWithName:(NSString *)selectName
173 NSEnumerator *enumerator = [iconArray objectEnumerator];
174 NSDictionary *iconDict;
177 while ((iconDict = [enumerator nextObject])) {
178 NSString *iconName = [[[iconDict objectForKey:@"Path"] lastPathComponent] stringByDeletingPathExtension] ;
179 if ([iconName isEqualToString:selectName]) {
180 [imageGridView_icons selectIndex:index];
181 break; //we can exit early
188 //Animation ------------------------------------------------------------------------------------------------------------
189 #pragma mark Animation
190 //Start animating an icon in our grid by index (pass -1 to stop animation)
191 - (void)setAnimatedDockIconAtIndex:(int)index
193 //Schedule the old and new animating images for redraw
194 [imageGridView_icons setNeedsDisplayOfImageAtIndex:animatedIndex];
195 [imageGridView_icons setNeedsDisplayOfImageAtIndex:index];
197 //Stop the current animation
198 if (animationTimer) {
199 [animationTimer invalidate];
200 [animationTimer release];
201 animationTimer = nil;
203 [animatedIconState release]; animatedIconState = nil;
206 //Start the new animation
208 NSString *path = [[iconArray objectAtIndex:index] objectForKey:@"Path"];
210 animatedIconState = [[self animatedStateForDockIconAtPath:path] retain];
211 animatedIndex = index;
212 animationTimer = [[NSTimer scheduledTimerWithTimeInterval:[animatedIconState animationDelay]
214 selector:@selector(animate:)
216 repeats:YES] retain];
220 //Returns an animated AIIconState for the dock icon pack at the specified path
221 - (AIIconState *)animatedStateForDockIconAtPath:(NSString *)path
223 NSDictionary *iconPackDict = [[adium dockController] iconPackAtPath:path];
224 NSDictionary *stateDict = [iconPackDict objectForKey:@"State"];
226 return [[[AIIconState alloc] initByCompositingStates:[NSArray arrayWithObjects:
227 [stateDict objectForKey:@"Base"],
228 [stateDict objectForKey:@"Online"],
229 [stateDict objectForKey:@"Alert"], nil]] autorelease];
232 //Animate the hovered icon
233 - (void)animate:(NSTimer *)timer
235 [animatedIconState nextFrame];
236 [imageGridView_icons setNeedsDisplayOfImageAtIndex:animatedIndex];
239 //ImageGridView Delegate -----------------------------------------------------------------------------------------------
240 #pragma mark ImageGridView Delegate
241 - (int)numberOfImagesInImageGridView:(AIImageGridView *)imageGridView
243 return [iconArray count];
246 - (NSImage *)imageGridView:(AIImageGridView *)imageGridView imageAtIndex:(int)index
248 if (index == animatedIndex) {
249 return [animatedIconState image];
251 return [[[iconArray objectAtIndex:index] objectForKey:@"State"] image];
255 - (void)imageGridViewSelectionDidChange:(NSNotification *)notification
257 NSDictionary *iconDict = [iconArray objectAtIndex:[imageGridView_icons selectedIndex]];
258 NSString *iconName = [[[iconDict objectForKey:@"Path"] lastPathComponent] stringByDeletingPathExtension];
260 [[adium preferenceController] setPreference:iconName forKey:KEY_ACTIVE_DOCK_ICON group:PREF_GROUP_APPEARANCE];
263 - (void)imageGridView:(AIImageGridView *)imageGridView cursorIsHoveringImageAtIndex:(int)index
265 [self setAnimatedDockIconAtIndex:index];
269 //Deleting dock xtras --------------------------------------------------------------------------------------------------
270 #pragma mark Deleting dock xtras
271 //Delete the selected dock icon
272 - (void)imageGridViewDeleteSelectedImage:(AIImageGridView *)imageGridView
274 NSString *selectedIconPath = [[iconArray objectAtIndex:[imageGridView selectedIndex]] valueForKey:@"Path"];
275 NSString *name = [[selectedIconPath lastPathComponent] stringByDeletingPathExtension];
277 //We need atleast one icon installed, so prevent the user from deleting the default icon
278 if (![name isEqualToString:DEFAULT_DOCK_ICON_NAME]) {
279 NSBeginAlertSheet(AILocalizedString(@"Delete Dock Icon",nil),
280 AILocalizedString(@"Delete",nil),
281 AILocalizedString(@"Cancel",nil),
285 @selector(trashConfirmSheetDidEnd:returnCode:contextInfo:),
288 AILocalizedString(@"Are you sure you want to delete the %@ Dock Icon? It will be moved to the Trash.",nil), name);
291 - (void)trashConfirmSheetDidEnd:(NSWindow *)sheet returnCode:(int)returnCode contextInfo:(NSString *)selectedIconPath
293 if (returnCode == NSOKButton) {
294 int deletedIndex = [imageGridView_icons selectedIndex];
296 //Deselect and stop animating
297 [self setAnimatedDockIconAtIndex:-1];
298 [imageGridView_icons selectIndex:-1];
300 //Trash the file & Rebuild our icons
301 [[NSFileManager defaultManager] trashFileAtPath:selectedIconPath];
303 //Select the next available icon
304 [imageGridView_icons selectIndex:deletedIndex];