1 #import "PreferencesController.h"
2 #import "MainController.h"
3 #import "HotKeyCenter.h"
4 #import <ITKit/ITWindowPositioning.h>
6 #define SENDER_STATE (([sender state] == NSOnState) ? YES : NO)
8 /*************************************************************************/
10 #pragma mark PRIVATE INTERFACE
11 /*************************************************************************/
13 @interface PreferencesController (Private)
15 - (void)setupCustomizationTables;
16 - (void)setupMenuItems;
18 - (IBAction)changeMenus:(id)sender;
19 - (void)setLaunchesAtLogin:(BOOL)flag;
23 @implementation PreferencesController
26 /*************************************************************************/
28 #pragma mark STATIC VARIABLES
29 /*************************************************************************/
31 static PreferencesController *prefs = nil;
34 /*************************************************************************/
36 #pragma mark INITIALIZATION METHODS
37 /*************************************************************************/
39 + (PreferencesController *)sharedPrefs;
42 prefs = [[self alloc] init];
49 if ( (self = [super init]) ) {
50 df = [[NSUserDefaults standardUserDefaults] retain];
57 /*************************************************************************/
59 #pragma mark ACCESSOR METHODS
60 /*************************************************************************/
67 - (void)setController:(id)object
69 [controller autorelease];
70 controller = [object retain];
74 /*************************************************************************/
76 #pragma mark INSTANCE METHODS
77 /*************************************************************************/
79 - (IBAction)showPrefsWindow:(id)sender
81 if (! window) { // If window does not exist yet, then the nib hasn't been loaded.
82 [self setupWindow]; // Load in the nib, and perform any initial setup.
83 [self setupCustomizationTables]; // Setup the DnD manu config tables.
84 [self setupMenuItems]; // Setup the arrays of menu items
85 [self setupUI]; // Sets up additional UI
86 [window setDelegate:self];
89 [window setLevel:NSStatusWindowLevel];
91 [window makeKeyAndOrderFront:self];
92 [NSApp activateIgnoringOtherApps:YES];
95 - (IBAction)changeGeneralSetting:(id)sender
97 if ( [sender tag] == 1010) {
98 [self setLaunchesAtLogin:SENDER_STATE];
99 } else if ( [sender tag] == 1020) {
100 [df setBool:SENDER_STATE forKey:@"LaunchPlayerWithMT"];
101 } else if ( [sender tag] == 1030) {
102 [df setInteger:[sender intValue] forKey:@"SongsInAdvance"];
103 } else if ( [sender tag] == 1040) {
104 [df setBool:SENDER_STATE forKey:@"showAlbum"];
105 } else if ( [sender tag] == 1050) {
106 [df setBool:SENDER_STATE forKey:@"showName"];
107 } else if ( [sender tag] == 1060) {
108 [df setBool:SENDER_STATE forKey:@"showArtist"];
109 } else if ( [sender tag] == 1070) {
110 [df setBool:SENDER_STATE forKey:@"showTime"];
111 } else if ( [sender tag] == 1080) {
112 [df setBool:SENDER_STATE forKey:@"showTrackNumber"];
113 } else if ( [sender tag] == 1090) {
114 [df setBool:SENDER_STATE forKey:@"showTrackRating"];
118 - (IBAction)changeStatusWindowSetting:(id)sender
120 if ( [sender tag] == 2010) {
121 [df setInteger:[sender selectedRow] forKey:@"statusWindowVerticalPosition"];
122 [df setInteger:[sender selectedColumn] forKey:@"statusWindowHorizontalPosition"];
123 // update the window's position here
124 } else if ( [sender tag] == 2020) {
125 // update screen selection
126 } else if ( [sender tag] == 2030) {
127 // Update appearance effect
128 } else if ( [sender tag] == 2040) {
129 // Update Vanish Effect
130 } else if ( [sender tag] == 2050) {
131 // Update appearance speed
132 } else if ( [sender tag] == 2060) {
133 // Update vanish speed
134 } else if ( [sender tag] == 2070) {
135 // Update vanish delay
136 } else if ( [sender tag] == 2080) {
137 // Update "Song Info window when song changes" setting.
141 - (IBAction)changeHotKey:(id)sender
143 switch ([sender tag])
146 [self setKeyCombo:playPauseCombo];
147 [self setHotKey:@"PlayPause"];
150 [self setKeyCombo:nextTrackCombo];
151 [self setHotKey:@"NextTrack"];
154 [self setKeyCombo:prevTrackCombo];
155 [self setHotKey:@"PrevTrack"];
158 [self setKeyCombo:toggleLoopCombo];
159 [self setHotKey:@"ToggleLoop"];
162 [self setKeyCombo:toggleShuffleCombo];
163 [self setHotKey:@"ToggleShuffle"];
166 [self setKeyCombo:trackInfoCombo];
167 [self setHotKey:@"TrackInfo"];
170 [self setKeyCombo:upcomingSongsCombo];
171 [self setHotKey:@"UpcomingSongs"];
174 [self setKeyCombo:volumeIncrementCombo];
175 [self setHotKey:@"IncrementVolume"];
178 [self setKeyCombo:volumeDecrementCombo];
179 [self setHotKey:@"DecrementVolume"];
182 [self setKeyCombo:ratingIncrementCombo];
183 [self setHotKey:@"IncrementRating"];
186 [self setKeyCombo:ratingDecrementCombo];
187 [self setHotKey:@"DecrementRating"];
192 - (void)registerDefaults
195 NSMutableDictionary *loginWindow;
196 NSMutableArray *loginArray;
197 NSEnumerator *loginEnum;
200 [df setObject:[NSArray arrayWithObjects:
215 @"Current Track Info",
216 nil] forKey:@"menu"];
218 [df setInteger:5 forKey:@"SongsInAdvance"];
219 [df setBool:YES forKey:@"showName"];
220 [df setBool:YES forKey:@"showArtist"];
221 [df setBool:NO forKey:@"showAlbum"];
222 [df setBool:NO forKey:@"showTime"];
226 loginWindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
227 loginArray = [loginWindow objectForKey:@"AutoLaunchedApplicationDictionary"];
228 loginEnum = [loginArray objectEnumerator];
230 while ( (anItem = [loginEnum nextObject]) ) {
231 if ( [[[anItem objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]] ) {
236 [loginWindow release];
239 // We must fix it so it is no longer suxy
241 if (NSRunInformationalAlertPanel(@"Auto-launch MenuTunes", @"Would you like MenuTunes to automatically launch at login?", @"Yes", @"No", nil) == NSOKButton) {
242 AEDesc scriptDesc, resultDesc;
243 NSString *script = [NSString stringWithFormat:@"tell application \"System Events\"\nmake new login item at end of login items with properties {path:\"%@\", kind:\"APPLICATION\"}\nend tell", [[NSBundle mainBundle] bundlePath]];
244 ComponentInstance asComponent = OpenDefaultComponent(kOSAComponentType, kAppleScriptSubtype);
246 AECreateDesc(typeChar, [script cString], [script cStringLength],
249 OSADoScript(asComponent, &scriptDesc, kOSANullScript, typeChar, kOSAModeCanInteract, &resultDesc);
251 AEDisposeDesc(&scriptDesc);
252 AEDisposeDesc(&resultDesc);
254 CloseComponent(asComponent);
259 - (IBAction)cancelHotKey:(id)sender
261 [[NSNotificationCenter defaultCenter] removeObserver:self];
262 [NSApp endSheet:keyComboPanel];
263 [keyComboPanel orderOut:nil];
266 - (IBAction)clearHotKey:(id)sender
268 [self setKeyCombo:[KeyCombo clearKeyCombo]];
271 - (IBAction)okHotKey:(id)sender
273 NSString *string = [combo userDisplayRep];
278 if ([setHotKey isEqualToString:@"PlayPause"]) {
279 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
280 [combo isEqual:trackInfoCombo] || [combo isEqual:upcomingSongsCombo] ||
281 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
282 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
283 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
284 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
286 [window setLevel:NSNormalWindowLevel];
287 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
288 [window setLevel:NSStatusWindowLevel];
291 playPauseCombo = [combo copy];
292 [playPauseButton setTitle:string];
293 } else if ([setHotKey isEqualToString:@"NextTrack"]) {
294 if (([combo isEqual:playPauseCombo] || [combo isEqual:prevTrackCombo] ||
295 [combo isEqual:trackInfoCombo] || [combo isEqual:upcomingSongsCombo] ||
296 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
297 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
298 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
299 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
301 [window setLevel:NSNormalWindowLevel];
302 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
303 [window setLevel:NSStatusWindowLevel];
306 nextTrackCombo = [combo copy];
307 [nextTrackButton setTitle:string];
308 } else if ([setHotKey isEqualToString:@"PrevTrack"]) {
309 if (([combo isEqual:nextTrackCombo] || [combo isEqual:playPauseCombo] ||
310 [combo isEqual:trackInfoCombo] || [combo isEqual:upcomingSongsCombo] ||
311 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
312 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
313 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
314 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
316 [window setLevel:NSNormalWindowLevel];
317 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
318 [window setLevel:NSStatusWindowLevel];
321 prevTrackCombo = [combo copy];
322 [previousTrackButton setTitle:string];
323 } else if ([setHotKey isEqualToString:@"TrackInfo"]) {
324 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
325 [combo isEqual:playPauseCombo] || [combo isEqual:upcomingSongsCombo] ||
326 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
327 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
328 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
329 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
331 [window setLevel:NSNormalWindowLevel];
332 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
333 [window setLevel:NSStatusWindowLevel];
336 trackInfoCombo = [combo copy];
337 [trackInfoButton setTitle:string];
338 } else if ([setHotKey isEqualToString:@"UpcomingSongs"]) {
339 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
340 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
341 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
342 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
343 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
344 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
346 [window setLevel:NSNormalWindowLevel];
347 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
348 [window setLevel:NSStatusWindowLevel];
351 upcomingSongsCombo = [combo copy];
352 [upcomingSongsButton setTitle:string];
354 } else if ([setHotKey isEqualToString:@"IncrementVolume"]) {
355 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
356 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
357 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
358 [combo isEqual:upcomingSongsCombo] || [combo isEqual:volumeDecrementCombo] ||
359 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
360 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
362 [window setLevel:NSNormalWindowLevel];
363 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
364 [window setLevel:NSStatusWindowLevel];
367 volumeIncrementCombo = [combo copy];
368 [volumeIncrementButton setTitle:string];
369 } else if ([setHotKey isEqualToString:@"DecrementVolume"]) {
370 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
371 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
372 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
373 [combo isEqual:volumeIncrementCombo] || [combo isEqual:upcomingSongsCombo] ||
374 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
375 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
377 [window setLevel:NSNormalWindowLevel];
378 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
379 [window setLevel:NSStatusWindowLevel];
382 volumeDecrementCombo = [combo copy];
383 [volumeDecrementButton setTitle:string];
384 } else if ([setHotKey isEqualToString:@"IncrementRating"]) {
385 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
386 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
387 [combo isEqual:upcomingSongsCombo] || [combo isEqual:ratingDecrementCombo] ||
388 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
389 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
390 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
392 [window setLevel:NSNormalWindowLevel];
393 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
394 [window setLevel:NSStatusWindowLevel];
397 ratingIncrementCombo = [combo copy];
398 [ratingIncrementButton setTitle:string];
399 } else if ([setHotKey isEqualToString:@"DecrementRating"]) {
400 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
401 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
402 [combo isEqual:ratingIncrementCombo] || [combo isEqual:upcomingSongsCombo] ||
403 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
404 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
405 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
407 [window setLevel:NSNormalWindowLevel];
408 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
409 [window setLevel:NSStatusWindowLevel];
412 ratingDecrementCombo = [combo copy];
413 [ratingDecrementButton setTitle:string];
414 } else if ([setHotKey isEqualToString:@"ToggleLoop"]) {
415 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
416 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
417 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
418 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
419 [combo isEqual:upcomingSongsCombo] || [combo isEqual:toggleShuffleCombo]) &&
420 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
422 [window setLevel:NSNormalWindowLevel];
423 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
424 [window setLevel:NSStatusWindowLevel];
427 toggleLoopCombo = [combo copy];
428 [toggleLoopButton setTitle:string];
429 } else if ([setHotKey isEqualToString:@"ToggleShuffle"]) {
430 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
431 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
432 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
433 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
434 [combo isEqual:toggleLoopCombo] || [combo isEqual:upcomingSongsCombo]) &&
435 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
437 [window setLevel:NSNormalWindowLevel];
438 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
439 [window setLevel:NSStatusWindowLevel];
442 toggleShuffleCombo = [combo copy];
443 [toggleShuffleButton setTitle:string];
445 [self cancelHotKey:sender];
450 /*************************************************************************/
452 #pragma mark HOTKEY SUPPORT METHODS
453 /*************************************************************************/
455 - (void)setHotKey:(NSString *)key
458 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyEvent:) name:@"KeyBroadcasterEvent" object:nil];
459 [NSApp beginSheet:keyComboPanel modalForWindow:window modalDelegate:self didEndSelector:nil contextInfo:nil];
462 - (void)keyEvent:(NSNotification *)note
464 NSDictionary *info = [note userInfo];
469 keyCode = [[info objectForKey:@"KeyCode"] shortValue];
470 modifiers = [[info objectForKey:@"Modifiers"] longValue];
472 newCombo = [[KeyCombo alloc] initWithKeyCode:keyCode andModifiers:modifiers];
473 [self setKeyCombo:newCombo];
476 - (void)setKeyCombo:(KeyCombo *)newCombo
480 combo = [newCombo copy];
482 string = [combo userDisplayRep];
486 [keyComboField setStringValue:string];
490 /*************************************************************************/
492 #pragma mark PRIVATE METHOD IMPLEMENTATIONS
493 /*************************************************************************/
497 if ( ! [NSBundle loadNibNamed:@"Preferences" owner:self] ) {
498 NSLog( @"Failed to load Preferences.nib" );
504 - (void)setupCustomizationTables
506 NSImageCell *imgCell = [[[NSImageCell alloc] initImageCell:nil] autorelease];
508 // Set the table view cells up
509 [imgCell setImageScaling:NSScaleNone];
510 [[menuTableView tableColumnWithIdentifier:@"submenu"] setDataCell:imgCell];
511 [[allTableView tableColumnWithIdentifier:@"submenu"] setDataCell:imgCell];
513 // Register for drag and drop
514 [menuTableView registerForDraggedTypes:[NSArray arrayWithObjects:
515 @"MenuTableViewPboardType",
516 @"AllTableViewPboardType",
518 [allTableView registerForDraggedTypes:[NSArray arrayWithObjects:
519 @"MenuTableViewPboardType",
520 @"AllTableViewPboardType",
524 - (void)setupMenuItems
526 NSEnumerator *itemEnum;
528 // Set the list of items you can have.
529 availableItems = [[NSMutableArray alloc] initWithObjects:
530 @"Current Track Info",
544 // Get our preferred menu
545 myItems = [[df arrayForKey:@"menu"] mutableCopy];
547 // Delete items in the availableItems array that are already part of the menu
548 itemEnum = [myItems objectEnumerator];
549 while ( (anItem = [itemEnum nextObject]) ) {
550 if ( ! [anItem isEqualToString:@"<separator>"] ) {
551 [availableItems removeObject:anItem];
555 // Items that show should a submenu image
556 submenuItems = [[NSArray alloc] initWithObjects:
566 NSMutableDictionary *loginwindow;
567 NSMutableArray *loginarray;
568 NSEnumerator *loginEnum;
571 // Fill in the number of songs in advance to show field
572 [songsInAdvance setIntValue:[df integerForKey:@"SongsInAdvance"]];
574 // Fill in hot key buttons
575 if ([df objectForKey:@"PlayPause"]){
576 playPauseCombo = [df keyComboForKey:@"PlayPause"];
577 [playPauseButton setTitle:[playPauseCombo userDisplayRep]];
579 playPauseCombo = [[KeyCombo alloc] init];
582 if ([df objectForKey:@"NextTrack"]) {
583 nextTrackCombo = [df keyComboForKey:@"NextTrack"];
584 [nextTrackButton setTitle:[nextTrackCombo userDisplayRep]];
586 nextTrackCombo = [[KeyCombo alloc] init];
589 if ([df objectForKey:@"PrevTrack"]) {
590 prevTrackCombo = [df keyComboForKey:@"PrevTrack"];
591 [previousTrackButton setTitle:[prevTrackCombo userDisplayRep]];
593 prevTrackCombo = [[KeyCombo alloc] init];
596 if ([df objectForKey:@"TrackInfo"]) {
597 trackInfoCombo = [df keyComboForKey:@"TrackInfo"];
598 [trackInfoButton setTitle:[trackInfoCombo userDisplayRep]];
600 trackInfoCombo = [[KeyCombo alloc] init];
603 if ([df objectForKey:@"UpcomingSongs"]) {
604 upcomingSongsCombo = [df keyComboForKey:@"UpcomingSongs"];
605 [upcomingSongsButton setTitle:[upcomingSongsCombo userDisplayRep]];
607 upcomingSongsCombo = [[KeyCombo alloc] init];
610 if ([df objectForKey:@"IncrementVolume"]) {
611 volumeIncrementCombo = [df keyComboForKey:@"IncrementVolume"];
612 [volumeIncrementButton setTitle:[volumeIncrementCombo userDisplayRep]];
614 volumeIncrementCombo = [[KeyCombo alloc] init];
617 if ([df objectForKey:@"DecrementVolume"]) {
618 volumeDecrementCombo = [df keyComboForKey:@"DecrementVolume"];
619 [volumeDecrementButton setTitle:[volumeDecrementCombo userDisplayRep]];
621 volumeDecrementCombo = [[KeyCombo alloc] init];
624 if ([df objectForKey:@"IncrementRating"]) {
625 ratingIncrementCombo = [df keyComboForKey:@"IncrementRating"];
626 [ratingIncrementButton setTitle:[ratingIncrementCombo userDisplayRep]];
628 ratingIncrementCombo = [[KeyCombo alloc] init];
631 if ([df objectForKey:@"DecrementRating"]) {
632 ratingDecrementCombo = [df keyComboForKey:@"DecrementRating"];
633 [ratingDecrementButton setTitle:[ratingDecrementCombo userDisplayRep]];
635 ratingDecrementCombo = [[KeyCombo alloc] init];
638 if ([df objectForKey:@"ToggleLoop"]) {
639 toggleLoopCombo = [df keyComboForKey:@"ToggleLoop"];
640 [toggleLoopButton setTitle:[toggleLoopCombo userDisplayRep]];
642 toggleLoopCombo = [[KeyCombo alloc] init];
645 if ([df objectForKey:@"ToggleShuffle"]) {
646 toggleShuffleCombo = [df keyComboForKey:@"ToggleShuffle"];
647 [toggleShuffleButton setTitle:[toggleShuffleCombo userDisplayRep]];
649 toggleShuffleCombo = [[KeyCombo alloc] init];
652 // Check current track info buttons
653 [albumCheckbox setState:[df boolForKey:@"showAlbum"] ? NSOnState : NSOffState];
654 [nameCheckbox setState:[df boolForKey:@"showName"] ? NSOnState : NSOffState];
655 [artistCheckbox setState:[df boolForKey:@"showArtist"] ? NSOnState : NSOffState];
656 [trackTimeCheckbox setState:[df boolForKey:@"showTime"] ? NSOnState : NSOffState];
658 // Set the launch at login checkbox state
660 loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
661 loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"];
663 loginEnum = [loginarray objectEnumerator];
664 while ( (anItem = [loginEnum nextObject]) ) {
665 if ([[[anItem objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) {
666 [launchAtLoginCheckbox setState:NSOnState];
671 - (IBAction)changeMenus:(id)sender
673 [df setObject:myItems forKey:@"menu"];
675 [controller rebuildMenu];
678 - (void)setLaunchesAtLogin:(BOOL)flag
681 NSMutableDictionary *loginwindow;
682 NSMutableArray *loginarray;
683 ComponentInstance temp = OpenDefaultComponent(kOSAComponentType, kAppleScriptSubtype);;
688 loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
689 loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"];
691 for (i = 0; i < [loginarray count]; i++) {
692 NSDictionary *tempDict = [loginarray objectAtIndex:i];
693 if ([[[tempDict objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) {
699 AEDesc scriptDesc, resultDesc;
700 NSString *script = [NSString stringWithFormat:@"tell application \"System Events\"\nmake new login item at end of login items with properties {path:\"%@\", kind:\"APPLICATION\"}\nend tell", [[NSBundle mainBundle] bundlePath]];
702 AECreateDesc(typeChar, [script cString], [script cStringLength],
705 OSADoScript(temp, &scriptDesc, kOSANullScript, typeChar, kOSAModeCanInteract, &resultDesc);
707 AEDisposeDesc(&scriptDesc);
708 AEDisposeDesc(&resultDesc);
709 CloseComponent(temp);
713 NSMutableDictionary *loginwindow;
714 NSMutableArray *loginarray;
718 loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
719 loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"];
721 for (i = 0; i < [loginarray count]; i++) {
722 NSDictionary *tempDict = [loginarray objectAtIndex:i];
723 if ([[[tempDict objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) {
724 [loginarray removeObjectAtIndex:i];
725 [df setPersistentDomain:loginwindow forName:@"loginwindow"];
734 /*************************************************************************/
736 #pragma mark NSWindow DELEGATE METHODS
737 /*************************************************************************/
739 - (void)windowWillClose:(NSNotification *)note
741 [(MainController *)controller closePreferences];
745 /*************************************************************************/
747 #pragma mark NSTableView DATASOURCE METHODS
748 /*************************************************************************/
750 - (int)numberOfRowsInTableView:(NSTableView *)aTableView
752 if (aTableView == menuTableView) {
753 return [myItems count];
755 return [availableItems count];
759 - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
761 if (aTableView == menuTableView) {
762 if ([[aTableColumn identifier] isEqualToString:@"name"]) {
763 return [myItems objectAtIndex:rowIndex];
765 if ([submenuItems containsObject:[myItems objectAtIndex:rowIndex]])
767 return [NSImage imageNamed:@"submenu"];
773 if ([[aTableColumn identifier] isEqualToString:@"name"]) {
774 return [availableItems objectAtIndex:rowIndex];
776 if ([submenuItems containsObject:[availableItems objectAtIndex:rowIndex]]) {
777 return [NSImage imageNamed:@"submenu"];
785 - (BOOL)tableView:(NSTableView *)tableView writeRows:(NSArray*)rows toPasteboard:(NSPasteboard*)pboard
787 if (tableView == menuTableView) {
788 [pboard declareTypes:[NSArray arrayWithObjects:@"MenuTableViewPboardType", nil] owner:self];
789 [pboard setString:[[rows objectAtIndex:0] stringValue] forType:@"MenuTableViewPboardType"];
793 if (tableView == allTableView) {
794 [pboard declareTypes:[NSArray arrayWithObjects:@"AllTableViewPboardType", nil] owner:self];
795 [pboard setString:[[rows objectAtIndex:0] stringValue] forType:@"AllTableViewPboardType"];
801 - (BOOL)tableView:(NSTableView*)tableView acceptDrop:(id <NSDraggingInfo>)info row:(int)row dropOperation:(NSTableViewDropOperation)operation
805 NSString *dragData, *temp;
807 pb = [info draggingPasteboard];
809 if ([[pb types] containsObject:@"MenuTableViewPboardType"]) {
810 dragData = [pb stringForType:@"MenuTableViewPboardType"];
811 dragRow = [dragData intValue];
812 temp = [myItems objectAtIndex:dragRow];
813 [myItems removeObjectAtIndex:dragRow];
815 if (tableView == menuTableView) {
817 [myItems insertObject:temp atIndex:row - 1];
819 [myItems insertObject:temp atIndex:row];
822 if (![temp isEqualToString:@"<separator>"]) {
823 [availableItems addObject:temp];
826 } else if ([[pb types] containsObject:@"AllTableViewPboardType"]) {
827 dragData = [pb stringForType:@"AllTableViewPboardType"];
828 dragRow = [dragData intValue];
829 temp = [availableItems objectAtIndex:dragRow];
831 if (![temp isEqualToString:@"<separator>"]) {
832 [availableItems removeObjectAtIndex:dragRow];
834 [myItems insertObject:temp atIndex:row];
837 [menuTableView reloadData];
838 [allTableView reloadData];
839 [self changeMenus:self];
843 - (NSDragOperation)tableView:(NSTableView*)tableView validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)operation
845 if (tableView == allTableView) {
846 if ([[[info draggingPasteboard] types] containsObject:@"AllTableViewPboardType"]) {
847 return NSDragOperationNone;
850 if ([[[info draggingPasteboard] types] containsObject:@"MenuTableViewPboardType"]) {
851 NSString *item = [myItems objectAtIndex:[[[info draggingPasteboard] stringForType:@"MenuTableViewPboardType"] intValue]];
852 if ([item isEqualToString:@"PreferencesÉ"] || [item isEqualToString:@"Quit"]) {
853 return NSDragOperationNone;
857 [tableView setDropRow:-1 dropOperation:NSTableViewDropOn];
858 return NSDragOperationGeneric;
861 if (operation == NSTableViewDropOn || row == -1)
863 return NSDragOperationNone;
866 return NSDragOperationGeneric;
870 /*************************************************************************/
872 #pragma mark DEALLOCATION METHODS
873 /*************************************************************************/
877 [self setKeyCombo:nil];
878 [playPauseCombo release];
879 [nextTrackCombo release];
880 [prevTrackCombo release];
881 [trackInfoCombo release];
882 [upcomingSongsCombo release];
883 [keyComboPanel release];
884 [menuTableView setDataSource:nil];
885 [allTableView setDataSource:nil];
886 [controller release];
887 [availableItems release];
888 [submenuItems release];