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 "AIAppearancePreferences.h"
18 #import "AIAppearancePreferencesPlugin.h"
19 #import "AIDockController.h"
20 #import "AIDockIconSelectionSheet.h"
21 #import "AIEmoticonPack.h"
22 #import "AIEmoticonPreferences.h"
23 #import "AIListLayoutWindowController.h"
24 #import "AIListThemeWindowController.h"
25 #import <AIUtilities/AIMenuAdditions.h>
26 #import <AIUtilities/ESImageAdditions.h>
27 #import <AIUtilities/AIPopUpButtonAdditions.h>
28 #import <Adium/AIEmoticonController.h>
29 #import <Adium/AIIconState.h>
30 #import <Adium/AIServiceIcons.h>
31 #import <Adium/AIStatusIcons.h>
32 #import <Adium/ESPresetManagementController.h>
33 #import <Adium/ESPresetNameSheetController.h>
36 #import "AISCLViewPlugin.h"
39 AIEmoticonMenuNone = 1,
40 AIEmoticonMenuMultiple
43 @interface AIAppearancePreferences (PRIVATE)
44 - (NSMenu *)_windowStyleMenu;
45 - (NSMenu *)_dockIconMenu;
46 - (NSMenu *)_emoticonPackMenu;
47 - (NSMenu *)_statusIconsMenu;
48 - (NSMenu *)_serviceIconsMenu;
49 - (NSMenu *)_listLayoutMenu;
50 - (NSMenu *)_colorThemeMenu;
51 - (void)_rebuildEmoticonMenuAndSelectActivePack;
52 - (NSMenu *)_iconPackMenuForPacks:(NSArray *)packs class:(Class)iconClass;
53 - (void)_addWindowStyleOption:(NSString *)option withTag:(int)tag toMenu:(NSMenu *)menu;
54 - (void)_updateSliderValues;
57 @implementation AIAppearancePreferences
60 * @brief Preference pane properties
62 - (PREFERENCE_CATEGORY)category{
63 return(AIPref_Appearance);
66 return(AILocalizedString(@"Appearance","Appearance preferences label"));
68 - (NSString *)nibName{
69 return(@"AppearancePrefs");
73 * @brief Configure the preference view
77 NSDictionary *prefDict = [[adium preferenceController] preferencesForGroup:PREF_GROUP_APPEARANCE];
80 [popUp_windowStyle setMenu:[self _windowStyleMenu]];
81 [popUp_windowStyle compatibleSelectItemWithTag:[[prefDict objectForKey:KEY_LIST_LAYOUT_WINDOW_STYLE] intValue]];
82 [checkBox_verticalAutosizing setState:[[prefDict objectForKey:KEY_LIST_LAYOUT_VERTICAL_AUTOSIZE] boolValue]];
83 [checkBox_horizontalAutosizing setState:[[prefDict objectForKey:KEY_LIST_LAYOUT_HORIZONTAL_AUTOSIZE] boolValue]];
84 [slider_windowOpacity setFloatValue:([[prefDict objectForKey:KEY_LIST_LAYOUT_WINDOW_OPACITY] floatValue] * 100.0)];
85 [slider_horizontalWidth setIntValue:[[prefDict objectForKey:KEY_LIST_LAYOUT_HORIZONTAL_WIDTH] intValue]];
86 [self _updateSliderValues];
89 [label_serviceIcons setLocalizedString:AILocalizedString(@"Service icons:","Label for preference to select the icon pack to used for service (AIM, MSN, etc.)")];
90 [label_statusIcons setLocalizedString:AILocalizedString(@"Status icons:","Label for preference to select status icon pack")];
91 [label_dockIcons setLocalizedString:AILocalizedString(@"Dock icons:","Label for preference to select dock icon")];
93 //Observe preference changes
94 [[adium preferenceController] registerPreferenceObserver:self forGroup:PREF_GROUP_EMOTICONS];
95 [[adium preferenceController] registerPreferenceObserver:self forGroup:PREF_GROUP_APPEARANCE];
97 //Observe xtras changes
98 [[adium notificationCenter] addObserver:self
99 selector:@selector(xtrasChanged:)
100 name:Adium_Xtras_Changed
102 [self xtrasChanged:nil];
106 * @brief View will close
108 - (void)viewWillClose
110 [[adium preferenceController] unregisterPreferenceObserver:self];
112 [[adium notificationCenter] removeObserver:self];
116 * @brief Xtras changed, update our menus to reflect the new Xtras
118 - (void)xtrasChanged:(NSNotification *)notification
120 NSString *type = [[notification object] lowercaseString];
121 NSDictionary *prefDict = [[adium preferenceController] preferencesForGroup:PREF_GROUP_APPEARANCE];
123 if(!type || [type isEqualToString:@"adiumemoticonset"]){
124 [self _rebuildEmoticonMenuAndSelectActivePack];
127 if(!type || [type isEqualToString:@"adiumicon"]){
128 [popUp_dockIcon setMenu:[self _dockIconMenu]];
129 [popUp_dockIcon selectItemWithTitle:[prefDict objectForKey:KEY_ACTIVE_DOCK_ICON]];
132 if(!type || [type isEqualToString:@"adiumserviceicons"]){
133 [popUp_serviceIcons setMenu:[self _serviceIconsMenu]];
134 [popUp_serviceIcons selectItemWithTitle:[prefDict objectForKey:KEY_SERVICE_ICON_PACK]];
137 if(!type || [type isEqualToString:@"adiumstatusicons"]){
138 [popUp_statusIcons setMenu:[self _statusIconsMenu]];
139 [popUp_statusIcons selectItemWithTitle:[prefDict objectForKey:KEY_STATUS_ICON_PACK]];
142 if(!type || [type isEqualToString:@"listtheme"]){
143 [popUp_colorTheme setMenu:[self _colorThemeMenu]];
144 [popUp_colorTheme selectItemWithRepresentedObject:[prefDict objectForKey:KEY_LIST_THEME_NAME]];
147 if(!type || [type isEqualToString:@"listlayout"]){
148 [popUp_listLayout setMenu:[self _listLayoutMenu]];
149 [popUp_listLayout selectItemWithRepresentedObject:[prefDict objectForKey:KEY_LIST_LAYOUT_NAME]];
154 * @brief Preferences changed
156 * Update controls in our view to reflect the changed preferences
158 - (void)preferencesChangedForGroup:(NSString *)group key:(NSString *)key object:(AIListObject *)object
159 preferenceDict:(NSDictionary *)prefDict firstTime:(BOOL)firstTime
162 if([group isEqualToString:PREF_GROUP_EMOTICONS]){
163 [self _rebuildEmoticonMenuAndSelectActivePack];
167 if([group isEqualToString:PREF_GROUP_APPEARANCE]){
169 //Horizontal resizing label
171 [key isEqualToString:KEY_LIST_LAYOUT_WINDOW_STYLE] ||
172 [key isEqualToString:KEY_LIST_LAYOUT_HORIZONTAL_AUTOSIZE]){
174 int windowMode = [[prefDict objectForKey:KEY_LIST_LAYOUT_WINDOW_STYLE] intValue];
175 BOOL horizontalAutosize = [[prefDict objectForKey:KEY_LIST_LAYOUT_HORIZONTAL_AUTOSIZE] boolValue];
177 if(windowMode == WINDOW_STYLE_STANDARD){
178 //In standard mode, disable the horizontal autosizing slider if horiztonal autosizing is off
179 [textField_horizontalWidthText setLocalizedString:AILocalizedString(@"Maximum width:",nil)];
180 [slider_horizontalWidth setEnabled:horizontalAutosize];
183 //In all the borderless transparent modes, the horizontal autosizing slider becomes the
184 //horizontal sizing slider when autosizing is off
185 if(horizontalAutosize){
186 [textField_horizontalWidthText setLocalizedString:AILocalizedString(@"Maximum width:",nil)];
188 [textField_horizontalWidthText setLocalizedString:AILocalizedString(@"Width:",nil)];
190 [slider_horizontalWidth setEnabled:YES];
195 //Selected menu items
196 if(firstTime || [key isEqualToString:KEY_STATUS_ICON_PACK]){
197 [popUp_statusIcons selectItemWithTitle:[prefDict objectForKey:KEY_STATUS_ICON_PACK]];
199 //If the prefDict's item isn't present, we're using the default, so select that one
200 if(![popUp_serviceIcons selectedItem]){
201 [popUp_serviceIcons selectItemWithTitle:[[adium preferenceController] defaultPreferenceForKey:KEY_STATUS_ICON_PACK
202 group:PREF_GROUP_APPEARANCE
206 if(firstTime || [key isEqualToString:KEY_SERVICE_ICON_PACK]){
207 [popUp_serviceIcons selectItemWithTitle:[prefDict objectForKey:KEY_SERVICE_ICON_PACK]];
209 //If the prefDict's item isn't present, we're using the default, so select that one
210 if(![popUp_serviceIcons selectedItem]){
211 [popUp_serviceIcons selectItemWithTitle:[[adium preferenceController] defaultPreferenceForKey:KEY_SERVICE_ICON_PACK
212 group:PREF_GROUP_APPEARANCE
216 if(firstTime || [key isEqualToString:KEY_LIST_LAYOUT_NAME]){
217 [popUp_listLayout selectItemWithRepresentedObject:[prefDict objectForKey:KEY_LIST_LAYOUT_NAME]];
219 if(firstTime || [key isEqualToString:KEY_LIST_THEME_NAME]){
220 [popUp_colorTheme selectItemWithRepresentedObject:[prefDict objectForKey:KEY_LIST_THEME_NAME]];
222 if(firstTime || [key isEqualToString:KEY_ACTIVE_DOCK_ICON]){
223 [popUp_dockIcon selectItemWithTitle:[prefDict objectForKey:KEY_ACTIVE_DOCK_ICON]];
229 * @brief Rebuild the emoticon menu
231 - (void)_rebuildEmoticonMenuAndSelectActivePack
233 [popUp_emoticons setMenu:[self _emoticonPackMenu]];
235 //Update the selected pack
236 NSArray *activeEmoticonPacks = [[adium emoticonController] activeEmoticonPacks];
237 int numActivePacks = [activeEmoticonPacks count];
239 if(numActivePacks == 0){
240 [popUp_emoticons compatibleSelectItemWithTag:AIEmoticonMenuNone];
241 }else if(numActivePacks > 1){
242 [popUp_emoticons compatibleSelectItemWithTag:AIEmoticonMenuMultiple];
244 [popUp_emoticons selectItemWithRepresentedObject:[activeEmoticonPacks objectAtIndex:0]];
249 * @brief Save changed preferences
251 - (IBAction)changePreference:(id)sender
253 if(sender == popUp_statusIcons){
254 [[adium preferenceController] setPreference:[[sender selectedItem] title]
255 forKey:KEY_STATUS_ICON_PACK
256 group:PREF_GROUP_APPEARANCE];
258 }else if(sender == popUp_serviceIcons){
259 [[adium preferenceController] setPreference:[[sender selectedItem] title]
260 forKey:KEY_SERVICE_ICON_PACK
261 group:PREF_GROUP_APPEARANCE];
263 }else if(sender == popUp_dockIcon){
264 [[adium preferenceController] setPreference:[[sender selectedItem] title]
265 forKey:KEY_ACTIVE_DOCK_ICON
266 group:PREF_GROUP_APPEARANCE];
268 }else if(sender == popUp_listLayout){
269 [[adium preferenceController] setPreference:[[sender selectedItem] title]
270 forKey:KEY_LIST_LAYOUT_NAME
271 group:PREF_GROUP_APPEARANCE];
273 }else if(sender == popUp_colorTheme){
274 [[adium preferenceController] setPreference:[[sender selectedItem] title]
275 forKey:KEY_LIST_THEME_NAME
276 group:PREF_GROUP_APPEARANCE];
278 }else if(sender == popUp_windowStyle){
279 [[adium preferenceController] setPreference:[NSNumber numberWithInt:[[sender selectedItem] tag]]
280 forKey:KEY_LIST_LAYOUT_WINDOW_STYLE
281 group:PREF_GROUP_APPEARANCE];
283 }else if(sender == checkBox_verticalAutosizing){
284 [[adium preferenceController] setPreference:[NSNumber numberWithBool:[sender state]]
285 forKey:KEY_LIST_LAYOUT_VERTICAL_AUTOSIZE
286 group:PREF_GROUP_APPEARANCE];
288 }else if(sender == checkBox_horizontalAutosizing){
289 [[adium preferenceController] setPreference:[NSNumber numberWithBool:[sender state]]
290 forKey:KEY_LIST_LAYOUT_HORIZONTAL_AUTOSIZE
291 group:PREF_GROUP_APPEARANCE];
293 }else if(sender == slider_windowOpacity){
294 [[adium preferenceController] setPreference:[NSNumber numberWithFloat:([sender floatValue] / 100.0)]
295 forKey:KEY_LIST_LAYOUT_WINDOW_OPACITY
296 group:PREF_GROUP_APPEARANCE];
297 [self _updateSliderValues];
299 }else if(sender == slider_horizontalWidth){
300 int newValue = [sender intValue];
301 int oldValue = [[[adium preferenceController] preferenceForKey:KEY_LIST_LAYOUT_HORIZONTAL_WIDTH
302 group:PREF_GROUP_APPEARANCE] intValue];
303 if(newValue != oldValue){
304 [[adium preferenceController] setPreference:[NSNumber numberWithInt:newValue]
305 forKey:KEY_LIST_LAYOUT_HORIZONTAL_WIDTH
306 group:PREF_GROUP_APPEARANCE];
307 [self _updateSliderValues];
310 }else if(sender == popUp_emoticons){
311 if([sender tag] != AIEmoticonMenuMultiple){
312 //Disable all active emoticons
313 NSArray *activePacks = [[[[adium emoticonController] activeEmoticonPacks] mutableCopy] autorelease];
314 NSEnumerator *enumerator = [activePacks objectEnumerator];
315 AIEmoticonPack *pack, *selectedPack;
317 selectedPack = [[sender selectedItem] representedObject];
319 [[adium preferenceController] delayPreferenceChangedNotifications:YES];
321 while(pack = [enumerator nextObject]){
322 [[adium emoticonController] setEmoticonPack:pack enabled:NO];
325 //Enable the selected pack
326 if(selectedPack) [[adium emoticonController] setEmoticonPack:selectedPack enabled:YES];
328 [[adium preferenceController] delayPreferenceChangedNotifications:NO];
336 - (void)_updateSliderValues
338 [textField_windowOpacity setStringValue:[NSString stringWithFormat:@"%i%%", (int)[slider_windowOpacity floatValue]]];
339 [textField_horizontalWidthIndicator setStringValue:[NSString stringWithFormat:@"%ipx",[slider_horizontalWidth intValue]]];
343 //Emoticons ------------------------------------------------------------------------------------------------------------
344 #pragma mark Emoticons
348 - (IBAction)customizeEmoticons:(id)sender
350 [AIEmoticonPreferences showEmoticionCustomizationOnWindow:[[self view] window]];
356 - (NSMenu *)_emoticonPackMenu
358 NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] init];
359 NSEnumerator *enumerator = [[[adium emoticonController] availableEmoticonPacks] objectEnumerator];
360 AIEmoticonPack *pack;
361 NSMenuItem *menuItem;
363 //Add the "No Emoticons" option
364 menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:AILocalizedString(@"None",nil)
367 keyEquivalent:@""] autorelease];
368 [menuItem setImage:[NSImage imageNamed:@"emoticonBlank" forClass:[self class]]];
369 [menuItem setTag:AIEmoticonMenuNone];
370 [menu addItem:menuItem];
372 //Add the "Multiple packs selected" option
373 if([[[adium emoticonController] activeEmoticonPacks] count] > 1){
374 menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:AILocalizedString(@"Multiple Packs Selected",nil)
377 keyEquivalent:@""] autorelease];
378 [menuItem setImage:[NSImage imageNamed:@"emoticonBlank" forClass:[self class]]];
379 [menuItem setTag:AIEmoticonMenuMultiple];
380 [menu addItem:menuItem];
384 [menu addItem:[NSMenuItem separatorItem]];
387 while(pack = [enumerator nextObject]){
388 menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:[pack name]
391 keyEquivalent:@""] autorelease];
392 [menuItem setRepresentedObject:pack];
393 [menuItem setImage:[[[[pack emoticons] objectAtIndex:0] image] imageByScalingToSize:NSMakeSize(16,16)]];
394 [menu addItem:menuItem];
398 return([menu autorelease]);
402 //Contact list options -------------------------------------------------------------------------------------------------
403 #pragma mark Contact list options
407 - (NSMenu *)_windowStyleMenu
409 NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] init];
411 [self _addWindowStyleOption:AILocalizedString(@"Regular Window",nil)
412 withTag:WINDOW_STYLE_STANDARD
414 [menu addItem:[NSMenuItem separatorItem]];
415 [self _addWindowStyleOption:AILocalizedString(@"Borderless Window",nil)
416 withTag:WINDOW_STYLE_BORDERLESS
418 [self _addWindowStyleOption:AILocalizedString(@"Group Bubbles",nil)
419 withTag:WINDOW_STYLE_MOCKIE
421 [self _addWindowStyleOption:AILocalizedString(@"Contact Bubbles",nil)
422 withTag:WINDOW_STYLE_PILLOWS
424 [self _addWindowStyleOption:AILocalizedString(@"Contact Bubbles (To Fit)",nil)
425 withTag:WINDOW_STYLE_PILLOWS_FITTED
428 return([menu autorelease]);
430 - (void)_addWindowStyleOption:(NSString *)option withTag:(int)tag toMenu:(NSMenu *)menu{
431 NSMenuItem *menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:option
434 keyEquivalent:@""] autorelease];
435 [menuItem setTag:tag];
436 [menu addItem:menuItem];
440 //Contact list layout & theme ----------------------------------------------------------------------------------------
441 #pragma mark Contact list layout & theme
443 * @brief Create a new theme
445 - (IBAction)createListTheme:(id)sender
447 NSString *theme = [[adium preferenceController] preferenceForKey:KEY_LIST_THEME_NAME group:PREF_GROUP_APPEARANCE];
449 [ESPresetNameSheetController showPresetNameSheetWithDefaultName:[theme stringByAppendingString:@" Copy"]
450 explanatoryText:AILocalizedString(@"Enter a unique name for this new theme.",nil)
451 onWindow:[[self view] window]
457 * @brief Customize the active theme
459 - (IBAction)customizeListTheme:(id)sender
461 NSString *theme = [[adium preferenceController] preferenceForKey:KEY_LIST_THEME_NAME group:PREF_GROUP_APPEARANCE];
463 [AIListThemeWindowController editListThemeWithName:theme
464 onWindow:[[self view] window]
465 notifyingTarget:self];
469 * @brief Save (or revert) changes made when editing a theme
471 - (void)listThemeEditorWillCloseWithChanges:(BOOL)saveChanges forThemeNamed:(NSString *)name
474 //Update the modified theme
475 if([AISCLViewPlugin createSetFromPreferenceGroup:PREF_GROUP_LIST_THEME
477 extension:LIST_THEME_EXTENSION
478 inFolder:LIST_THEME_FOLDER]){
480 [[adium preferenceController] setPreference:name
481 forKey:KEY_LIST_THEME_NAME
482 group:PREF_GROUP_APPEARANCE];
486 //Revert back to selected theme
487 NSString *theme = [[adium preferenceController] preferenceForKey:KEY_LIST_THEME_NAME group:PREF_GROUP_APPEARANCE];
489 [AISCLViewPlugin applySetWithName:theme
490 extension:LIST_THEME_EXTENSION
491 inFolder:LIST_THEME_FOLDER
492 toPreferenceGroup:PREF_GROUP_LIST_THEME];
497 * @brief Manage available themes
499 - (void)manageListThemes:(id)sender
501 _listThemes = [AISCLViewPlugin availableThemeSets];
502 [ESPresetManagementController managePresets:_listThemes
504 onWindow:[[self view] window]
507 [popUp_colorTheme selectItemWithRepresentedObject:[[adium preferenceController] preferenceForKey:KEY_LIST_THEME_NAME
508 group:PREF_GROUP_APPEARANCE]];
512 * @brief Create a new layout
514 - (IBAction)createListLayout:(id)sender
516 NSString *layout = [[adium preferenceController] preferenceForKey:KEY_LIST_LAYOUT_NAME group:PREF_GROUP_APPEARANCE];
518 [ESPresetNameSheetController showPresetNameSheetWithDefaultName:[layout stringByAppendingString:@" Copy"]
519 explanatoryText:AILocalizedString(@"Enter a unique name for this new layout.",nil)
520 onWindow:[[self view] window]
526 * @brief Customize the active layout
528 - (IBAction)customizeListLayout:(id)sender
530 NSString *theme = [[adium preferenceController] preferenceForKey:KEY_LIST_LAYOUT_NAME group:PREF_GROUP_APPEARANCE];
532 [AIListLayoutWindowController editListLayoutWithName:theme
533 onWindow:[[self view] window]
534 notifyingTarget:self];
538 * @brief Save (or revert) changes made when editing a layout
540 - (void)listLayoutEditorWillCloseWithChanges:(BOOL)saveChanges forLayoutNamed:(NSString *)name
543 //Update the modified layout
544 if([AISCLViewPlugin createSetFromPreferenceGroup:PREF_GROUP_LIST_LAYOUT
546 extension:LIST_LAYOUT_EXTENSION
547 inFolder:LIST_LAYOUT_FOLDER]){
549 [[adium preferenceController] setPreference:name
550 forKey:KEY_LIST_LAYOUT_NAME
551 group:PREF_GROUP_APPEARANCE];
555 //Revert back to selected layout
556 NSString *layout = [[adium preferenceController] preferenceForKey:KEY_LIST_LAYOUT_NAME group:PREF_GROUP_APPEARANCE];
558 [AISCLViewPlugin applySetWithName:layout
559 extension:LIST_LAYOUT_EXTENSION
560 inFolder:LIST_LAYOUT_FOLDER
561 toPreferenceGroup:PREF_GROUP_LIST_LAYOUT];
566 * @brief Manage available layouts
568 - (void)manageListLayouts:(id)sender
570 _listLayouts = [AISCLViewPlugin availableLayoutSets];
571 [ESPresetManagementController managePresets:_listLayouts
573 onWindow:[[self view] window]
576 [popUp_listLayout selectItemWithRepresentedObject:[[adium preferenceController] preferenceForKey:KEY_LIST_LAYOUT_NAME
577 group:PREF_GROUP_APPEARANCE]];
581 * @brief Validate a layout or theme name to ensure it is unique
583 - (BOOL)presetNameSheetController:(ESPresetNameSheetController *)controller
584 shouldAcceptNewName:(NSString *)newName
585 userInfo:(id)userInfo
587 NSEnumerator *enumerator;
588 NSDictionary *presetDict;
590 //Scan the correct presets to ensure this name doesn't already exist
591 if([userInfo isEqualToString:@"theme"]){
592 enumerator = [[AISCLViewPlugin availableThemeSets] objectEnumerator];
594 enumerator = [[AISCLViewPlugin availableLayoutSets] objectEnumerator];
597 while(presetDict = [enumerator nextObject]){
598 if([newName isEqualToString:[presetDict objectForKey:@"name"]]) return(NO);
605 * @brief Create a new theme with the user supplied name, activate and edit it
607 - (void)presetNameSheetControllerDidEnd:(ESPresetNameSheetController *)controller
608 returnCode:(ESPresetNameSheetReturnCode)returnCode
609 newName:(NSString *)newName
610 userInfo:(id)userInfo
613 case ESPresetNameSheetOkayReturn:
614 if([userInfo isEqualToString:@"theme"]){
615 [self performSelector:@selector(_editListThemeWithName:) withObject:newName afterDelay:0.00001];
617 [self performSelector:@selector(_editListLayoutWithName:) withObject:newName afterDelay:0.00001];
621 case ESPresetNameSheetCancelReturn:
626 - (void)_editListThemeWithName:(NSString *)name{
627 [AIListThemeWindowController editListThemeWithName:name
628 onWindow:[[self view] window]
629 notifyingTarget:self];
631 - (void)_editListLayoutWithName:(NSString *)name{
632 [AIListLayoutWindowController editListLayoutWithName:name
633 onWindow:[[self view] window]
634 notifyingTarget:self];
640 - (NSArray *)renamePreset:(NSDictionary *)preset toName:(NSString *)newName inPresets:(NSArray *)presets renamedPreset:(id *)renamedPreset
644 if(presets == _listLayouts){
645 [AISCLViewPlugin renameSetWithName:[preset objectForKey:@"name"]
646 extension:LIST_LAYOUT_EXTENSION
647 inFolder:LIST_LAYOUT_FOLDER
649 _listLayouts = [AISCLViewPlugin availableLayoutSets];
650 newPresets = _listLayouts;
652 }else if(presets == _listThemes){
653 [AISCLViewPlugin renameSetWithName:[preset objectForKey:@"name"]
654 extension:LIST_THEME_EXTENSION
655 inFolder:LIST_THEME_FOLDER
657 _listThemes = [AISCLViewPlugin availableThemeSets];
658 newPresets = _listThemes;
664 //Return the new duplicate by reference for the preset controller
666 NSEnumerator *enumerator = [newPresets objectEnumerator];
667 NSDictionary *aPreset;
669 while(aPreset = [enumerator nextObject]){
670 if([newName isEqualToString:[aPreset objectForKey:@"name"]]){
671 *renamedPreset = aPreset;
683 - (NSArray *)duplicatePreset:(NSDictionary *)preset inPresets:(NSArray *)presets createdDuplicate:(id *)duplicatePreset
685 NSString *newName = [NSString stringWithFormat:@"%@ (%@)", [preset objectForKey:@"name"], AILocalizedString(@"Copy",nil)];
686 NSArray *newPresets = nil;
688 if(presets == _listLayouts){
689 [AISCLViewPlugin duplicateSetWithName:[preset objectForKey:@"name"]
690 extension:LIST_LAYOUT_EXTENSION
691 inFolder:LIST_LAYOUT_FOLDER
693 _listLayouts = [AISCLViewPlugin availableLayoutSets];
694 newPresets = _listLayouts;
696 }else if(presets == _listThemes){
697 [AISCLViewPlugin duplicateSetWithName:[preset objectForKey:@"name"]
698 extension:LIST_THEME_EXTENSION
699 inFolder:LIST_THEME_FOLDER
701 _listThemes = [AISCLViewPlugin availableThemeSets];
702 newPresets = _listThemes;
705 //Return the new duplicate by reference for the preset controller
707 NSEnumerator *enumerator = [newPresets objectEnumerator];
708 NSDictionary *aPreset;
710 while(aPreset = [enumerator nextObject]){
711 if([newName isEqualToString:[aPreset objectForKey:@"name"]]){
712 *duplicatePreset = aPreset;
724 - (NSArray *)deletePreset:(NSDictionary *)preset inPresets:(NSArray *)presets
726 if(presets == _listLayouts){
727 [AISCLViewPlugin deleteSetWithName:[preset objectForKey:@"name"]
728 extension:LIST_LAYOUT_EXTENSION
729 inFolder:LIST_LAYOUT_FOLDER];
730 _listLayouts = [AISCLViewPlugin availableLayoutSets];
732 return(_listLayouts);
734 }else if(presets == _listThemes){
735 [AISCLViewPlugin deleteSetWithName:[preset objectForKey:@"name"]
736 extension:LIST_THEME_EXTENSION
737 inFolder:LIST_THEME_FOLDER];
738 _listThemes = [AISCLViewPlugin availableThemeSets];
750 - (NSMenu *)_listLayoutMenu
752 NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] init];
753 NSEnumerator *enumerator = [[AISCLViewPlugin availableLayoutSets] objectEnumerator];
755 NSMenuItem *menuItem;
759 while(set = [enumerator nextObject]){
760 name = [set objectForKey:@"name"];
761 menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:name
764 keyEquivalent:@""] autorelease];
765 [menuItem setRepresentedObject:name];
766 [menu addItem:menuItem];
770 [menu addItem:[NSMenuItem separatorItem]];
773 menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:AILocalizedString(@"Add New Layout...",nil)
775 action:@selector(createListLayout:)
776 keyEquivalent:@""] autorelease];
777 [menu addItem:menuItem];
779 menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:AILocalizedString(@"Edit Layouts...",nil)
781 action:@selector(manageListLayouts:)
782 keyEquivalent:@""] autorelease];
783 [menu addItem:menuItem];
791 - (NSMenu *)_colorThemeMenu
793 NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] init];
794 NSEnumerator *enumerator = [[AISCLViewPlugin availableThemeSets] objectEnumerator];
796 NSMenuItem *menuItem;
800 while(set = [enumerator nextObject]){
801 name = [set objectForKey:@"name"];
802 menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:name
805 keyEquivalent:@""] autorelease];
806 [menuItem setRepresentedObject:name];
807 [menu addItem:menuItem];
811 [menu addItem:[NSMenuItem separatorItem]];
814 menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:AILocalizedString(@"Add New Theme...",nil)
816 action:@selector(createListTheme:)
817 keyEquivalent:@""] autorelease];
818 [menu addItem:menuItem];
820 menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:AILocalizedString(@"Edit Themes...",nil)
822 action:@selector(manageListThemes:)
823 keyEquivalent:@""] autorelease];
824 [menu addItem:menuItem];
830 //Dock icons -----------------------------------------------------------------------------------------------------------
831 #pragma mark Dock icons
835 - (IBAction)showAllDockIcons:(id)sender
837 [AIDockIconSelectionSheet showDockIconSelectorOnWindow:[[self view] window]];
841 * @brief Returns a menu of dock icon packs
843 - (NSMenu *)_dockIconMenu
845 NSMenu *menu = [[NSMenu allocWithZone:[NSMenu menuZone]] init];
846 NSEnumerator *enumerator = [[[adium dockController] availableDockIconPacks] objectEnumerator];
849 while(packPath = [enumerator nextObject]){
850 NSString *name = [[packPath lastPathComponent] stringByDeletingPathExtension];
851 AIIconState *preview = [[adium dockController] previewStateForIconPackAtPath:packPath];
853 NSMenuItem *menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:name
856 keyEquivalent:@""] autorelease];
857 [menuItem setRepresentedObject:name];
858 [menuItem setImage:[[preview image] imageByScalingToSize:NSMakeSize(18,18)]];
859 [menu addItem:menuItem];
866 //Status and Service icons ---------------------------------------------------------------------------------------------
867 #pragma mark Status and service icons
869 * @brief Returns a menu of status icon packs
871 - (NSMenu *)_statusIconsMenu
873 return([self _iconPackMenuForPacks:[adium allResourcesForName:@"Status Icons" withExtensions:@"AdiumStatusIcons"] class:[AIStatusIcons class]]);
877 * @brief Returns a menu of service icon packs
879 - (NSMenu *)_serviceIconsMenu
881 return([self _iconPackMenuForPacks:[adium allResourcesForName:@"Service Icons" withExtensions:@"AdiumServiceIcons"] class:[AIServiceIcons class]]);
885 * @brief Builds and returns an icon pack menu
887 * @param packs NSArray of icon pack file paths
888 * @param iconClass The controller class (AIStatusIcons, AIServiceIcons) for icon pack previews
890 - (NSMenu *)_iconPackMenuForPacks:(NSArray *)packs class:(Class)iconClass
892 NSMenu *serviceIconsMenu = [[NSMenu allocWithZone:[NSMenu menuZone]] init];
893 NSEnumerator *enumerator = [packs objectEnumerator];
896 while(packPath = [enumerator nextObject]){
897 NSString *name = [[packPath lastPathComponent] stringByDeletingPathExtension];
898 NSMenuItem *menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:name
901 keyEquivalent:@""] autorelease];
902 [menuItem setRepresentedObject:name];
903 [menuItem setImage:[iconClass previewMenuImageForIconPackAtPath:packPath]];
904 [serviceIconsMenu addItem:menuItem];
907 return(serviceIconsMenu);