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 BOOL rebuildRequired = NO;
99 if ( [sender tag] == 1010) {
100 [self setLaunchesAtLogin:SENDER_STATE];
101 } else if ( [sender tag] == 1020) {
102 [df setBool:SENDER_STATE forKey:@"LaunchPlayerWithMT"];
103 } else if ( [sender tag] == 1030) {
104 [df setInteger:[sender intValue] forKey:@"SongsInAdvance"];
105 rebuildRequired = YES;
106 } else if ( [sender tag] == 1040) {
107 // This will not be executed. Song info always shows the title of the song.
108 // [df setBool:SENDER_STATE forKey:@"showName"];
109 // rebuildRequired = YES;
110 } else if ( [sender tag] == 1050) {
111 [df setBool:SENDER_STATE forKey:@"showArtist"];
112 rebuildRequired = YES;
113 } else if ( [sender tag] == 1060) {
114 [df setBool:SENDER_STATE forKey:@"showAlbum"];
115 rebuildRequired = YES;
116 } else if ( [sender tag] == 1070) {
117 [df setBool:SENDER_STATE forKey:@"showTime"];
118 rebuildRequired = YES;
119 } else if ( [sender tag] == 1080) {
120 [df setBool:SENDER_STATE forKey:@"showTrackNumber"];
121 rebuildRequired = YES;
122 } else if ( [sender tag] == 1090) {
123 [df setBool:SENDER_STATE forKey:@"showTrackRating"];
124 rebuildRequired = YES;
127 if ( rebuildRequired ) {
128 [controller rebuildMenu];
129 // redraw song info status window, or upcoming songs here
135 - (IBAction)changeStatusWindowSetting:(id)sender
137 if ( [sender tag] == 2010) {
138 [df setInteger:[sender selectedRow] forKey:@"statusWindowVerticalPosition"];
139 [df setInteger:[sender selectedColumn] forKey:@"statusWindowHorizontalPosition"];
140 // update the window's position here
141 } else if ( [sender tag] == 2020) {
142 // update screen selection
143 } else if ( [sender tag] == 2030) {
144 // Update appearance effect
145 } else if ( [sender tag] == 2040) {
146 // Update Vanish Effect
147 } else if ( [sender tag] == 2050) {
148 // Update appearance speed
149 } else if ( [sender tag] == 2060) {
150 // Update vanish speed
151 } else if ( [sender tag] == 2070) {
152 // Update vanish delay
153 } else if ( [sender tag] == 2080) {
154 // Update "Song Info window when song changes" setting.
158 - (IBAction)changeHotKey:(id)sender
160 switch ([sender tag])
163 [self setKeyCombo:playPauseCombo];
164 [self setHotKey:@"PlayPause"];
167 [self setKeyCombo:nextTrackCombo];
168 [self setHotKey:@"NextTrack"];
171 [self setKeyCombo:prevTrackCombo];
172 [self setHotKey:@"PrevTrack"];
175 [self setKeyCombo:toggleLoopCombo];
176 [self setHotKey:@"ToggleLoop"];
179 [self setKeyCombo:toggleShuffleCombo];
180 [self setHotKey:@"ToggleShuffle"];
183 [self setKeyCombo:trackInfoCombo];
184 [self setHotKey:@"TrackInfo"];
187 [self setKeyCombo:upcomingSongsCombo];
188 [self setHotKey:@"UpcomingSongs"];
191 [self setKeyCombo:volumeIncrementCombo];
192 [self setHotKey:@"IncrementVolume"];
195 [self setKeyCombo:volumeDecrementCombo];
196 [self setHotKey:@"DecrementVolume"];
199 [self setKeyCombo:ratingIncrementCombo];
200 [self setHotKey:@"IncrementRating"];
203 [self setKeyCombo:ratingDecrementCombo];
204 [self setHotKey:@"DecrementRating"];
209 - (void)registerDefaults
212 NSMutableDictionary *loginWindow;
213 NSMutableArray *loginArray;
214 NSEnumerator *loginEnum;
217 [df setObject:[NSArray arrayWithObjects:
232 @"Current Track Info",
233 nil] forKey:@"menu"];
235 [df setInteger:5 forKey:@"SongsInAdvance"];
236 // [df setBool:YES forKey:@"showName"]; // Song info will always show song title.
237 [df setBool:YES forKey:@"showArtist"];
238 [df setBool:NO forKey:@"showAlbum"];
239 [df setBool:NO forKey:@"showTime"];
243 loginWindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
244 loginArray = [loginWindow objectForKey:@"AutoLaunchedApplicationDictionary"];
245 loginEnum = [loginArray objectEnumerator];
247 while ( (anItem = [loginEnum nextObject]) ) {
248 if ( [[[anItem objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]] ) {
253 [loginWindow release];
256 // We must fix it so it is no longer suxy
258 if (NSRunInformationalAlertPanel(@"Auto-launch MenuTunes", @"Would you like MenuTunes to automatically launch at login?", @"Yes", @"No", nil) == NSOKButton) {
259 AEDesc scriptDesc, resultDesc;
260 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]];
261 ComponentInstance asComponent = OpenDefaultComponent(kOSAComponentType, kAppleScriptSubtype);
263 AECreateDesc(typeChar, [script cString], [script cStringLength],
266 OSADoScript(asComponent, &scriptDesc, kOSANullScript, typeChar, kOSAModeCanInteract, &resultDesc);
268 AEDisposeDesc(&scriptDesc);
269 AEDisposeDesc(&resultDesc);
271 CloseComponent(asComponent);
276 - (IBAction)cancelHotKey:(id)sender
278 [[NSNotificationCenter defaultCenter] removeObserver:self];
279 [NSApp endSheet:keyComboPanel];
280 [keyComboPanel orderOut:nil];
283 - (IBAction)clearHotKey:(id)sender
285 [self setKeyCombo:[KeyCombo clearKeyCombo]];
288 - (IBAction)okHotKey:(id)sender
290 NSString *string = [combo userDisplayRep];
295 if ([setHotKey isEqualToString:@"PlayPause"]) {
296 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
297 [combo isEqual:trackInfoCombo] || [combo isEqual:upcomingSongsCombo] ||
298 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
299 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
300 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
301 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
303 [window setLevel:NSNormalWindowLevel];
304 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
305 [window setLevel:NSStatusWindowLevel];
308 playPauseCombo = [combo copy];
309 [playPauseButton setTitle:string];
310 } else if ([setHotKey isEqualToString:@"NextTrack"]) {
311 if (([combo isEqual:playPauseCombo] || [combo isEqual:prevTrackCombo] ||
312 [combo isEqual:trackInfoCombo] || [combo isEqual:upcomingSongsCombo] ||
313 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
314 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
315 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
316 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
318 [window setLevel:NSNormalWindowLevel];
319 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
320 [window setLevel:NSStatusWindowLevel];
323 nextTrackCombo = [combo copy];
324 [nextTrackButton setTitle:string];
325 } else if ([setHotKey isEqualToString:@"PrevTrack"]) {
326 if (([combo isEqual:nextTrackCombo] || [combo isEqual:playPauseCombo] ||
327 [combo isEqual:trackInfoCombo] || [combo isEqual:upcomingSongsCombo] ||
328 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
329 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
330 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
331 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
333 [window setLevel:NSNormalWindowLevel];
334 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
335 [window setLevel:NSStatusWindowLevel];
338 prevTrackCombo = [combo copy];
339 [previousTrackButton setTitle:string];
340 } else if ([setHotKey isEqualToString:@"TrackInfo"]) {
341 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
342 [combo isEqual:playPauseCombo] || [combo isEqual:upcomingSongsCombo] ||
343 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
344 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
345 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
346 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
348 [window setLevel:NSNormalWindowLevel];
349 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
350 [window setLevel:NSStatusWindowLevel];
353 trackInfoCombo = [combo copy];
354 [trackInfoButton setTitle:string];
355 } else if ([setHotKey isEqualToString:@"UpcomingSongs"]) {
356 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
357 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
358 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
359 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
360 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
361 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
363 [window setLevel:NSNormalWindowLevel];
364 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
365 [window setLevel:NSStatusWindowLevel];
368 upcomingSongsCombo = [combo copy];
369 [upcomingSongsButton setTitle:string];
371 } else if ([setHotKey isEqualToString:@"IncrementVolume"]) {
372 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
373 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
374 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
375 [combo isEqual:upcomingSongsCombo] || [combo isEqual:volumeDecrementCombo] ||
376 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
377 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
379 [window setLevel:NSNormalWindowLevel];
380 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
381 [window setLevel:NSStatusWindowLevel];
384 volumeIncrementCombo = [combo copy];
385 [volumeIncrementButton setTitle:string];
386 } else if ([setHotKey isEqualToString:@"DecrementVolume"]) {
387 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
388 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
389 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
390 [combo isEqual:volumeIncrementCombo] || [combo isEqual:upcomingSongsCombo] ||
391 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
392 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
394 [window setLevel:NSNormalWindowLevel];
395 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
396 [window setLevel:NSStatusWindowLevel];
399 volumeDecrementCombo = [combo copy];
400 [volumeDecrementButton setTitle:string];
401 } else if ([setHotKey isEqualToString:@"IncrementRating"]) {
402 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
403 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
404 [combo isEqual:upcomingSongsCombo] || [combo isEqual:ratingDecrementCombo] ||
405 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
406 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
407 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
409 [window setLevel:NSNormalWindowLevel];
410 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
411 [window setLevel:NSStatusWindowLevel];
414 ratingIncrementCombo = [combo copy];
415 [ratingIncrementButton setTitle:string];
416 } else if ([setHotKey isEqualToString:@"DecrementRating"]) {
417 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
418 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
419 [combo isEqual:ratingIncrementCombo] || [combo isEqual:upcomingSongsCombo] ||
420 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
421 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
422 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
424 [window setLevel:NSNormalWindowLevel];
425 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
426 [window setLevel:NSStatusWindowLevel];
429 ratingDecrementCombo = [combo copy];
430 [ratingDecrementButton setTitle:string];
431 } else if ([setHotKey isEqualToString:@"ToggleLoop"]) {
432 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
433 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
434 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
435 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
436 [combo isEqual:upcomingSongsCombo] || [combo isEqual:toggleShuffleCombo]) &&
437 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
439 [window setLevel:NSNormalWindowLevel];
440 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
441 [window setLevel:NSStatusWindowLevel];
444 toggleLoopCombo = [combo copy];
445 [toggleLoopButton setTitle:string];
446 } else if ([setHotKey isEqualToString:@"ToggleShuffle"]) {
447 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
448 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
449 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
450 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
451 [combo isEqual:toggleLoopCombo] || [combo isEqual:upcomingSongsCombo]) &&
452 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
454 [window setLevel:NSNormalWindowLevel];
455 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
456 [window setLevel:NSStatusWindowLevel];
459 toggleShuffleCombo = [combo copy];
460 [toggleShuffleButton setTitle:string];
462 [df setKeyCombo:combo forKey:setHotKey];
463 [controller rebuildMenu];
464 [self cancelHotKey:sender];
469 /*************************************************************************/
471 #pragma mark HOTKEY SUPPORT METHODS
472 /*************************************************************************/
474 - (void)setHotKey:(NSString *)key
477 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyEvent:) name:@"KeyBroadcasterEvent" object:nil];
478 [NSApp beginSheet:keyComboPanel modalForWindow:window modalDelegate:self didEndSelector:nil contextInfo:nil];
481 - (void)keyEvent:(NSNotification *)note
483 NSDictionary *info = [note userInfo];
488 keyCode = [[info objectForKey:@"KeyCode"] shortValue];
489 modifiers = [[info objectForKey:@"Modifiers"] longValue];
491 newCombo = [[KeyCombo alloc] initWithKeyCode:keyCode andModifiers:modifiers];
492 [self setKeyCombo:newCombo];
495 - (void)setKeyCombo:(KeyCombo *)newCombo
499 combo = [newCombo copy];
501 string = [combo userDisplayRep];
505 [keyComboField setStringValue:string];
509 /*************************************************************************/
511 #pragma mark PRIVATE METHOD IMPLEMENTATIONS
512 /*************************************************************************/
516 if ( ! [NSBundle loadNibNamed:@"Preferences" owner:self] ) {
517 NSLog( @"Failed to load Preferences.nib" );
523 - (void)setupCustomizationTables
525 NSImageCell *imgCell = [[[NSImageCell alloc] initImageCell:nil] autorelease];
527 // Set the table view cells up
528 [imgCell setImageScaling:NSScaleNone];
529 [[menuTableView tableColumnWithIdentifier:@"submenu"] setDataCell:imgCell];
530 [[allTableView tableColumnWithIdentifier:@"submenu"] setDataCell:imgCell];
532 // Register for drag and drop
533 [menuTableView registerForDraggedTypes:[NSArray arrayWithObjects:
534 @"MenuTableViewPboardType",
535 @"AllTableViewPboardType",
537 [allTableView registerForDraggedTypes:[NSArray arrayWithObjects:
538 @"MenuTableViewPboardType",
539 @"AllTableViewPboardType",
543 - (void)setupMenuItems
545 NSEnumerator *itemEnum;
547 // Set the list of items you can have.
548 availableItems = [[NSMutableArray alloc] initWithObjects:
549 @"Current Track Info",
563 // Get our preferred menu
564 myItems = [[df arrayForKey:@"menu"] mutableCopy];
566 // Delete items in the availableItems array that are already part of the menu
567 itemEnum = [myItems objectEnumerator];
568 while ( (anItem = [itemEnum nextObject]) ) {
569 if ( ! [anItem isEqualToString:@"<separator>"] ) {
570 [availableItems removeObject:anItem];
574 // Items that show should a submenu image
575 submenuItems = [[NSArray alloc] initWithObjects:
585 NSMutableDictionary *loginwindow;
586 NSMutableArray *loginarray;
587 NSEnumerator *loginEnum;
590 // Fill in the number of songs in advance to show field
591 [songsInAdvance setIntValue:[df integerForKey:@"SongsInAdvance"]];
593 // Fill in hot key buttons
594 if ([df objectForKey:@"PlayPause"]){
595 playPauseCombo = [df keyComboForKey:@"PlayPause"];
596 [playPauseButton setTitle:[playPauseCombo userDisplayRep]];
598 playPauseCombo = [[KeyCombo alloc] init];
601 if ([df objectForKey:@"NextTrack"]) {
602 nextTrackCombo = [df keyComboForKey:@"NextTrack"];
603 [nextTrackButton setTitle:[nextTrackCombo userDisplayRep]];
605 nextTrackCombo = [[KeyCombo alloc] init];
608 if ([df objectForKey:@"PrevTrack"]) {
609 prevTrackCombo = [df keyComboForKey:@"PrevTrack"];
610 [previousTrackButton setTitle:[prevTrackCombo userDisplayRep]];
612 prevTrackCombo = [[KeyCombo alloc] init];
615 if ([df objectForKey:@"TrackInfo"]) {
616 trackInfoCombo = [df keyComboForKey:@"TrackInfo"];
617 [trackInfoButton setTitle:[trackInfoCombo userDisplayRep]];
619 trackInfoCombo = [[KeyCombo alloc] init];
622 if ([df objectForKey:@"UpcomingSongs"]) {
623 upcomingSongsCombo = [df keyComboForKey:@"UpcomingSongs"];
624 [upcomingSongsButton setTitle:[upcomingSongsCombo userDisplayRep]];
626 upcomingSongsCombo = [[KeyCombo alloc] init];
629 if ([df objectForKey:@"IncrementVolume"]) {
630 volumeIncrementCombo = [df keyComboForKey:@"IncrementVolume"];
631 [volumeIncrementButton setTitle:[volumeIncrementCombo userDisplayRep]];
633 volumeIncrementCombo = [[KeyCombo alloc] init];
636 if ([df objectForKey:@"DecrementVolume"]) {
637 volumeDecrementCombo = [df keyComboForKey:@"DecrementVolume"];
638 [volumeDecrementButton setTitle:[volumeDecrementCombo userDisplayRep]];
640 volumeDecrementCombo = [[KeyCombo alloc] init];
643 if ([df objectForKey:@"IncrementRating"]) {
644 ratingIncrementCombo = [df keyComboForKey:@"IncrementRating"];
645 [ratingIncrementButton setTitle:[ratingIncrementCombo userDisplayRep]];
647 ratingIncrementCombo = [[KeyCombo alloc] init];
650 if ([df objectForKey:@"DecrementRating"]) {
651 ratingDecrementCombo = [df keyComboForKey:@"DecrementRating"];
652 [ratingDecrementButton setTitle:[ratingDecrementCombo userDisplayRep]];
654 ratingDecrementCombo = [[KeyCombo alloc] init];
657 if ([df objectForKey:@"ToggleLoop"]) {
658 toggleLoopCombo = [df keyComboForKey:@"ToggleLoop"];
659 [toggleLoopButton setTitle:[toggleLoopCombo userDisplayRep]];
661 toggleLoopCombo = [[KeyCombo alloc] init];
664 if ([df objectForKey:@"ToggleShuffle"]) {
665 toggleShuffleCombo = [df keyComboForKey:@"ToggleShuffle"];
666 [toggleShuffleButton setTitle:[toggleShuffleCombo userDisplayRep]];
668 toggleShuffleCombo = [[KeyCombo alloc] init];
671 // Check current track info buttons
672 [albumCheckbox setState:[df boolForKey:@"showAlbum"] ? NSOnState : NSOffState];
673 [nameCheckbox setState:NSOnState]; // Song info will ALWAYS show song title.
674 [nameCheckbox setEnabled:NO]; // Song info will ALWAYS show song title.
675 [artistCheckbox setState:[df boolForKey:@"showArtist"] ? NSOnState : NSOffState];
676 [trackTimeCheckbox setState:[df boolForKey:@"showTime"] ? NSOnState : NSOffState];
678 // Set the launch at login checkbox state
680 loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
681 loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"];
683 loginEnum = [loginarray objectEnumerator];
684 while ( (anItem = [loginEnum nextObject]) ) {
685 if ([[[anItem objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) {
686 [launchAtLoginCheckbox setState:NSOnState];
691 - (IBAction)changeMenus:(id)sender
693 [df setObject:myItems forKey:@"menu"];
695 [controller rebuildMenu];
698 - (void)setLaunchesAtLogin:(BOOL)flag
701 NSMutableDictionary *loginwindow;
702 NSMutableArray *loginarray;
703 ComponentInstance temp = OpenDefaultComponent(kOSAComponentType, kAppleScriptSubtype);;
708 loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
709 loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"];
711 for (i = 0; i < [loginarray count]; i++) {
712 NSDictionary *tempDict = [loginarray objectAtIndex:i];
713 if ([[[tempDict objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) {
719 AEDesc scriptDesc, resultDesc;
720 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]];
722 AECreateDesc(typeChar, [script cString], [script cStringLength],
725 OSADoScript(temp, &scriptDesc, kOSANullScript, typeChar, kOSAModeCanInteract, &resultDesc);
727 AEDisposeDesc(&scriptDesc);
728 AEDisposeDesc(&resultDesc);
729 CloseComponent(temp);
733 NSMutableDictionary *loginwindow;
734 NSMutableArray *loginarray;
738 loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
739 loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"];
741 for (i = 0; i < [loginarray count]; i++) {
742 NSDictionary *tempDict = [loginarray objectAtIndex:i];
743 if ([[[tempDict objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) {
744 [loginarray removeObjectAtIndex:i];
745 [df setPersistentDomain:loginwindow forName:@"loginwindow"];
754 /*************************************************************************/
756 #pragma mark NSWindow DELEGATE METHODS
757 /*************************************************************************/
759 - (void)windowWillClose:(NSNotification *)note
761 [(MainController *)controller closePreferences];
765 /*************************************************************************/
767 #pragma mark NSTableView DATASOURCE METHODS
768 /*************************************************************************/
770 - (int)numberOfRowsInTableView:(NSTableView *)aTableView
772 if (aTableView == menuTableView) {
773 return [myItems count];
775 return [availableItems count];
779 - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
781 if (aTableView == menuTableView) {
782 if ([[aTableColumn identifier] isEqualToString:@"name"]) {
783 NSString *object = [myItems objectAtIndex:rowIndex];
784 if ([object isEqualToString:@"Show Player"]) {
785 return [NSString stringWithFormat:@"Show %@", [[controller currentRemote] playerSimpleName]];
789 if ([submenuItems containsObject:[myItems objectAtIndex:rowIndex]])
791 return [NSImage imageNamed:@"submenu"];
797 if ([[aTableColumn identifier] isEqualToString:@"name"]) {
798 return [availableItems objectAtIndex:rowIndex];
800 if ([submenuItems containsObject:[availableItems objectAtIndex:rowIndex]]) {
801 return [NSImage imageNamed:@"submenu"];
809 - (BOOL)tableView:(NSTableView *)tableView writeRows:(NSArray*)rows toPasteboard:(NSPasteboard*)pboard
811 if (tableView == menuTableView) {
812 [pboard declareTypes:[NSArray arrayWithObjects:@"MenuTableViewPboardType", nil] owner:self];
813 [pboard setString:[[rows objectAtIndex:0] stringValue] forType:@"MenuTableViewPboardType"];
817 if (tableView == allTableView) {
818 [pboard declareTypes:[NSArray arrayWithObjects:@"AllTableViewPboardType", nil] owner:self];
819 [pboard setString:[[rows objectAtIndex:0] stringValue] forType:@"AllTableViewPboardType"];
825 - (BOOL)tableView:(NSTableView*)tableView acceptDrop:(id <NSDraggingInfo>)info row:(int)row dropOperation:(NSTableViewDropOperation)operation
829 NSString *dragData, *temp;
831 pb = [info draggingPasteboard];
833 if ([[pb types] containsObject:@"MenuTableViewPboardType"]) {
834 dragData = [pb stringForType:@"MenuTableViewPboardType"];
835 dragRow = [dragData intValue];
836 temp = [myItems objectAtIndex:dragRow];
837 [myItems removeObjectAtIndex:dragRow];
839 if (tableView == menuTableView) {
841 [myItems insertObject:temp atIndex:row - 1];
843 [myItems insertObject:temp atIndex:row];
846 if (![temp isEqualToString:@"<separator>"]) {
847 [availableItems addObject:temp];
850 } else if ([[pb types] containsObject:@"AllTableViewPboardType"]) {
851 dragData = [pb stringForType:@"AllTableViewPboardType"];
852 dragRow = [dragData intValue];
853 temp = [availableItems objectAtIndex:dragRow];
855 if (![temp isEqualToString:@"<separator>"]) {
856 [availableItems removeObjectAtIndex:dragRow];
858 [myItems insertObject:temp atIndex:row];
861 [menuTableView reloadData];
862 [allTableView reloadData];
863 [self changeMenus:self];
867 - (NSDragOperation)tableView:(NSTableView*)tableView validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)operation
869 if (tableView == allTableView) {
870 if ([[[info draggingPasteboard] types] containsObject:@"AllTableViewPboardType"]) {
871 return NSDragOperationNone;
874 if ([[[info draggingPasteboard] types] containsObject:@"MenuTableViewPboardType"]) {
875 NSString *item = [myItems objectAtIndex:[[[info draggingPasteboard] stringForType:@"MenuTableViewPboardType"] intValue]];
876 if ([item isEqualToString:@"PreferencesÉ"] || [item isEqualToString:@"Quit"]) {
877 return NSDragOperationNone;
881 [tableView setDropRow:-1 dropOperation:NSTableViewDropOn];
882 return NSDragOperationGeneric;
885 if (operation == NSTableViewDropOn || row == -1)
887 return NSDragOperationNone;
890 return NSDragOperationGeneric;
894 /*************************************************************************/
896 #pragma mark DEALLOCATION METHODS
897 /*************************************************************************/
901 [self setKeyCombo:nil];
902 [playPauseCombo release];
903 [nextTrackCombo release];
904 [prevTrackCombo release];
905 [trackInfoCombo release];
906 [upcomingSongsCombo release];
907 [keyComboPanel release];
908 [menuTableView setDataSource:nil];
909 [allTableView setDataSource:nil];
910 [controller release];
911 [availableItems release];
912 [submenuItems release];