1 #import "PreferencesController.h"
2 #import "MainController.h"
3 #import "HotKeyCenter.h"
5 /*************************************************************************/
7 #pragma mark PRIVATE INTERFACE
8 /*************************************************************************/
10 @interface PreferencesController (Private)
12 - (void)setupCustomizationTables;
13 - (void)setupMenuItems;
18 @implementation PreferencesController
21 /*************************************************************************/
23 #pragma mark STATIC VARIABLES
24 /*************************************************************************/
26 static PreferencesController *prefs = nil;
29 /*************************************************************************/
31 #pragma mark INITIALIZATION METHODS
32 /*************************************************************************/
34 + (PreferencesController *)sharedPrefs;
37 prefs = [[self alloc] init];
44 if ( (self = [super init]) ) {
45 df = [[NSUserDefaults standardUserDefaults] retain];
52 /*************************************************************************/
54 #pragma mark ACCESSOR METHODS
55 /*************************************************************************/
62 - (void)setController:(id)object
64 [controller autorelease];
65 controller = [object retain];
69 /*************************************************************************/
71 #pragma mark INSTANCE METHODS
72 /*************************************************************************/
74 - (IBAction)showPrefsWindow:(id)sender
76 if (! window) { // If window does not exist yet, then the nib hasn't been loaded.
77 [self setupWindow]; // Load in the nib, and perform any initial setup.
78 [self setupCustomizationTables]; // Setup the DnD manu config tables.
79 [self setupMenuItems]; // Setup the arrays of menu items
80 [self setupUI]; // Sets up additional UI
81 [window setDelegate:self];
84 [window setLevel:NSStatusWindowLevel];
86 [window makeKeyAndOrderFront:self];
87 [NSApp activateIgnoringOtherApps:YES];
90 - (IBAction)apply:(id)sender
92 [df setObject:myItems forKey:@"menu"];
95 [df setKeyCombo:playPauseCombo forKey:@"PlayPause"];
96 [df setKeyCombo:nextTrackCombo forKey:@"NextTrack"];
97 [df setKeyCombo:prevTrackCombo forKey:@"PrevTrack"];
98 [df setKeyCombo:trackInfoCombo forKey:@"TrackInfo"];
99 [df setKeyCombo:upcomingSongsCombo forKey:@"UpcomingSongs"];
100 [df setKeyCombo:volumeIncrementCombo forKey:@"IncrementVolume"];
101 [df setKeyCombo:volumeDecrementCombo forKey:@"DecrementVolume"];
102 [df setKeyCombo:ratingIncrementCombo forKey:@"IncrementRating"];
103 [df setKeyCombo:ratingDecrementCombo forKey:@"DecrementRating"];
104 [df setKeyCombo:toggleLoopCombo forKey:@"ToggleLoop"];
105 [df setKeyCombo:toggleShuffleCombo forKey:@"ToggleShuffle"];
107 //Set info checkboxes
108 [df setBool:[albumCheckbox state] forKey:@"showAlbum"];
109 [df setBool:[nameCheckbox state] forKey:@"showName"];
110 [df setBool:[artistCheckbox state] forKey:@"showArtist"];
111 [df setBool:[trackTimeCheckbox state] forKey:@"showTime"];
113 //Here we set whether we will launch at login by modifying loginwindow.plist
114 if ([launchAtLoginCheckbox state] == NSOnState) {
115 NSMutableDictionary *loginwindow;
116 NSMutableArray *loginarray;
117 ComponentInstance temp = OpenDefaultComponent(kOSAComponentType, kAppleScriptSubtype);;
122 loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
123 loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"];
125 for (i = 0; i < [loginarray count]; i++) {
126 NSDictionary *tempDict = [loginarray objectAtIndex:i];
127 if ([[[tempDict objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) {
133 AEDesc scriptDesc, resultDesc;
134 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]];
136 AECreateDesc(typeChar, [script cString], [script cStringLength],
139 OSADoScript(temp, &scriptDesc, kOSANullScript, typeChar, kOSAModeCanInteract, &resultDesc);
141 AEDisposeDesc(&scriptDesc);
142 AEDisposeDesc(&resultDesc);
143 CloseComponent(temp);
146 NSMutableDictionary *loginwindow;
147 NSMutableArray *loginarray;
151 loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
152 loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"];
154 for (i = 0; i < [loginarray count]; i++) {
155 NSDictionary *tempDict = [loginarray objectAtIndex:i];
156 if ([[[tempDict objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) {
157 [loginarray removeObjectAtIndex:i];
158 [df setPersistentDomain:loginwindow forName:@"loginwindow"];
165 //Set songs in advance
166 if ([songsInAdvance intValue]) {
167 [df setInteger:[songsInAdvance intValue] forKey:@"SongsInAdvance"];
169 [df setInteger:5 forKey:@"SongsInAdvance"];
173 NSArray *apps = [[NSWorkspace sharedWorkspace] launchedApplications];
176 for (i = 0; i < [apps count]; i++) {
177 if ([[[apps objectAtIndex:i] objectForKey:@"NSApplicationName"]
178 isEqualToString:@"iTunes"]) {
179 [controller rebuildMenu];
183 [controller clearHotKeys];
186 - (void)registerDefaults
189 NSMutableDictionary *loginWindow;
190 NSMutableArray *loginArray;
191 NSEnumerator *loginEnum;
194 [df setObject:[NSArray arrayWithObjects:
209 @"Current Track Info",
210 nil] forKey:@"menu"];
212 [df setInteger:5 forKey:@"SongsInAdvance"];
213 [df setBool:YES forKey:@"showName"];
214 [df setBool:YES forKey:@"showArtist"];
215 [df setBool:NO forKey:@"showAlbum"];
216 [df setBool:NO forKey:@"showTime"];
220 loginWindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
221 loginArray = [loginWindow objectForKey:@"AutoLaunchedApplicationDictionary"];
222 loginEnum = [loginArray objectEnumerator];
224 while ( (anItem = [loginEnum nextObject]) ) {
225 if ( [[[anItem objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]] ) {
230 [loginWindow release];
233 // We must fix it so it is no longer suxy
235 if (NSRunInformationalAlertPanel(@"Auto-launch MenuTunes", @"Would you like MenuTunes to automatically launch at login?", @"Yes", @"No", nil) == NSOKButton) {
236 AEDesc scriptDesc, resultDesc;
237 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]];
238 ComponentInstance asComponent = OpenDefaultComponent(kOSAComponentType, kAppleScriptSubtype);
240 AECreateDesc(typeChar, [script cString], [script cStringLength],
243 OSADoScript(asComponent, &scriptDesc, kOSANullScript, typeChar, kOSAModeCanInteract, &resultDesc);
245 AEDisposeDesc(&scriptDesc);
246 AEDisposeDesc(&resultDesc);
248 CloseComponent(asComponent);
253 - (IBAction)cancelHotKey:(id)sender
255 [[NSNotificationCenter defaultCenter] removeObserver:self];
256 [NSApp endSheet:keyComboPanel];
257 [keyComboPanel orderOut:nil];
260 - (IBAction)clearHotKey:(id)sender
262 [self setKeyCombo:[KeyCombo clearKeyCombo]];
265 - (IBAction)okHotKey:(id)sender
267 NSString *string = [combo userDisplayRep];
272 if ([setHotKey isEqualToString:@"PlayPause"]) {
273 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
274 [combo isEqual:trackInfoCombo] || [combo isEqual:upcomingSongsCombo] ||
275 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
276 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
277 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
278 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
280 [window setLevel:NSNormalWindowLevel];
281 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
282 [window setLevel:NSStatusWindowLevel];
285 playPauseCombo = [combo copy];
286 [playPauseButton setTitle:string];
287 } else if ([setHotKey isEqualToString:@"NextTrack"]) {
288 if (([combo isEqual:playPauseCombo] || [combo isEqual:prevTrackCombo] ||
289 [combo isEqual:trackInfoCombo] || [combo isEqual:upcomingSongsCombo] ||
290 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
291 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
292 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
293 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
295 [window setLevel:NSNormalWindowLevel];
296 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
297 [window setLevel:NSStatusWindowLevel];
300 nextTrackCombo = [combo copy];
301 [nextTrackButton setTitle:string];
302 } else if ([setHotKey isEqualToString:@"PrevTrack"]) {
303 if (([combo isEqual:nextTrackCombo] || [combo isEqual:playPauseCombo] ||
304 [combo isEqual:trackInfoCombo] || [combo isEqual:upcomingSongsCombo] ||
305 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
306 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
307 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
308 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
310 [window setLevel:NSNormalWindowLevel];
311 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
312 [window setLevel:NSStatusWindowLevel];
315 prevTrackCombo = [combo copy];
316 [previousTrackButton setTitle:string];
317 } else if ([setHotKey isEqualToString:@"TrackInfo"]) {
318 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
319 [combo isEqual:playPauseCombo] || [combo isEqual:upcomingSongsCombo] ||
320 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
321 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
322 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
323 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
325 [window setLevel:NSNormalWindowLevel];
326 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
327 [window setLevel:NSStatusWindowLevel];
330 trackInfoCombo = [combo copy];
331 [trackInfoButton setTitle:string];
332 } else if ([setHotKey isEqualToString:@"UpcomingSongs"]) {
333 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
334 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
335 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
336 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
337 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
338 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
340 [window setLevel:NSNormalWindowLevel];
341 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
342 [window setLevel:NSStatusWindowLevel];
345 upcomingSongsCombo = [combo copy];
346 [upcomingSongsButton setTitle:string];
348 } else if ([setHotKey isEqualToString:@"IncrementVolume"]) {
349 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
350 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
351 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
352 [combo isEqual:upcomingSongsCombo] || [combo isEqual:volumeDecrementCombo] ||
353 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
354 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
356 [window setLevel:NSNormalWindowLevel];
357 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
358 [window setLevel:NSStatusWindowLevel];
361 volumeIncrementCombo = [combo copy];
362 [volumeIncrementButton setTitle:string];
363 } else if ([setHotKey isEqualToString:@"DecrementVolume"]) {
364 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
365 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
366 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
367 [combo isEqual:volumeIncrementCombo] || [combo isEqual:upcomingSongsCombo] ||
368 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
369 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
371 [window setLevel:NSNormalWindowLevel];
372 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
373 [window setLevel:NSStatusWindowLevel];
376 volumeDecrementCombo = [combo copy];
377 [volumeDecrementButton setTitle:string];
378 } else if ([setHotKey isEqualToString:@"IncrementRating"]) {
379 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
380 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
381 [combo isEqual:upcomingSongsCombo] || [combo isEqual:ratingDecrementCombo] ||
382 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
383 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
384 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
386 [window setLevel:NSNormalWindowLevel];
387 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
388 [window setLevel:NSStatusWindowLevel];
391 ratingIncrementCombo = [combo copy];
392 [ratingIncrementButton setTitle:string];
393 } else if ([setHotKey isEqualToString:@"DecrementRating"]) {
394 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
395 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
396 [combo isEqual:ratingIncrementCombo] || [combo isEqual:upcomingSongsCombo] ||
397 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
398 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
399 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
401 [window setLevel:NSNormalWindowLevel];
402 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
403 [window setLevel:NSStatusWindowLevel];
406 ratingDecrementCombo = [combo copy];
407 [ratingDecrementButton setTitle:string];
408 } else if ([setHotKey isEqualToString:@"ToggleLoop"]) {
409 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
410 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
411 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
412 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
413 [combo isEqual:upcomingSongsCombo] || [combo isEqual:toggleShuffleCombo]) &&
414 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
416 [window setLevel:NSNormalWindowLevel];
417 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
418 [window setLevel:NSStatusWindowLevel];
421 toggleLoopCombo = [combo copy];
422 [toggleLoopButton setTitle:string];
423 } else if ([setHotKey isEqualToString:@"ToggleShuffle"]) {
424 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
425 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
426 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
427 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
428 [combo isEqual:toggleLoopCombo] || [combo isEqual:upcomingSongsCombo]) &&
429 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
431 [window setLevel:NSNormalWindowLevel];
432 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
433 [window setLevel:NSStatusWindowLevel];
436 toggleShuffleCombo = [combo copy];
437 [toggleShuffleButton setTitle:string];
439 [self cancelHotKey:sender];
442 - (IBAction)setNewHotKey:(id)sender
444 switch ([sender tag])
447 [self setKeyCombo:playPauseCombo];
448 [self setHotKey:@"PlayPause"];
451 [self setKeyCombo:nextTrackCombo];
452 [self setHotKey:@"NextTrack"];
455 [self setKeyCombo:prevTrackCombo];
456 [self setHotKey:@"PrevTrack"];
459 [self setKeyCombo:toggleLoopCombo];
460 [self setHotKey:@"ToggleLoop"];
463 [self setKeyCombo:toggleShuffleCombo];
464 [self setHotKey:@"ToggleShuffle"];
467 [self setKeyCombo:trackInfoCombo];
468 [self setHotKey:@"TrackInfo"];
471 [self setKeyCombo:upcomingSongsCombo];
472 [self setHotKey:@"UpcomingSongs"];
475 [self setKeyCombo:volumeIncrementCombo];
476 [self setHotKey:@"IncrementVolume"];
479 [self setKeyCombo:volumeDecrementCombo];
480 [self setHotKey:@"DecrementVolume"];
483 [self setKeyCombo:ratingIncrementCombo];
484 [self setHotKey:@"IncrementRating"];
487 [self setKeyCombo:ratingDecrementCombo];
488 [self setHotKey:@"DecrementRating"];
494 /*************************************************************************/
496 #pragma mark HOTKEY SUPPORT METHODS
497 /*************************************************************************/
499 - (void)setHotKey:(NSString *)key
502 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyEvent:) name:@"KeyBroadcasterEvent" object:nil];
503 [NSApp beginSheet:keyComboPanel modalForWindow:window modalDelegate:self didEndSelector:nil contextInfo:nil];
506 - (void)keyEvent:(NSNotification *)note
508 NSDictionary *info = [note userInfo];
513 keyCode = [[info objectForKey:@"KeyCode"] shortValue];
514 modifiers = [[info objectForKey:@"Modifiers"] longValue];
516 newCombo = [[KeyCombo alloc] initWithKeyCode:keyCode andModifiers:modifiers];
517 [self setKeyCombo:newCombo];
520 - (void)setKeyCombo:(KeyCombo *)newCombo
524 combo = [newCombo copy];
526 string = [combo userDisplayRep];
530 [keyComboField setStringValue:string];
534 /*************************************************************************/
536 #pragma mark PRIVATE METHOD IMPLEMENTATIONS
537 /*************************************************************************/
541 if ( ! [NSBundle loadNibNamed:@"Preferences" owner:self] ) {
542 NSLog( @"Failed to load Preferences.nib" );
548 - (void)setupCustomizationTables
550 NSImageCell *imgCell = [[[NSImageCell alloc] initImageCell:nil] autorelease];
552 // Set the table view cells up
553 [imgCell setImageScaling:NSScaleNone];
554 [[menuTableView tableColumnWithIdentifier:@"submenu"] setDataCell:imgCell];
555 [[allTableView tableColumnWithIdentifier:@"submenu"] setDataCell:imgCell];
557 // Register for drag and drop
558 [menuTableView registerForDraggedTypes:[NSArray arrayWithObjects:
559 @"MenuTableViewPboardType",
560 @"AllTableViewPboardType",
562 [allTableView registerForDraggedTypes:[NSArray arrayWithObjects:
563 @"MenuTableViewPboardType",
564 @"AllTableViewPboardType",
568 - (void)setupMenuItems
570 NSEnumerator *itemEnum;
572 // Set the list of items you can have.
573 availableItems = [[NSMutableArray alloc] initWithObjects:
574 @"Current Track Info",
588 // Get our preferred menu
589 myItems = [[df arrayForKey:@"menu"] mutableCopy];
591 // Delete items in the availableItems array that are already part of the menu
592 itemEnum = [myItems objectEnumerator];
593 while ( (anItem = [itemEnum nextObject]) ) {
594 if ( ! [anItem isEqualToString:@"<separator>"] ) {
595 [availableItems removeObject:anItem];
599 // Items that show should a submenu image
600 submenuItems = [[NSArray alloc] initWithObjects:
610 NSMutableDictionary *loginwindow;
611 NSMutableArray *loginarray;
612 NSEnumerator *loginEnum;
615 // Fill in the number of songs in advance to show field
616 [songsInAdvance setIntValue:[df integerForKey:@"SongsInAdvance"]];
618 // Fill in hot key buttons
619 if ([df objectForKey:@"PlayPause"]){
620 playPauseCombo = [df keyComboForKey:@"PlayPause"];
621 [playPauseButton setTitle:[playPauseCombo userDisplayRep]];
623 playPauseCombo = [[KeyCombo alloc] init];
626 if ([df objectForKey:@"NextTrack"]) {
627 nextTrackCombo = [df keyComboForKey:@"NextTrack"];
628 [nextTrackButton setTitle:[nextTrackCombo userDisplayRep]];
630 nextTrackCombo = [[KeyCombo alloc] init];
633 if ([df objectForKey:@"PrevTrack"]) {
634 prevTrackCombo = [df keyComboForKey:@"PrevTrack"];
635 [previousTrackButton setTitle:[prevTrackCombo userDisplayRep]];
637 prevTrackCombo = [[KeyCombo alloc] init];
640 if ([df objectForKey:@"TrackInfo"]) {
641 trackInfoCombo = [df keyComboForKey:@"TrackInfo"];
642 [trackInfoButton setTitle:[trackInfoCombo userDisplayRep]];
644 trackInfoCombo = [[KeyCombo alloc] init];
647 if ([df objectForKey:@"UpcomingSongs"]) {
648 upcomingSongsCombo = [df keyComboForKey:@"UpcomingSongs"];
649 [upcomingSongsButton setTitle:[upcomingSongsCombo userDisplayRep]];
651 upcomingSongsCombo = [[KeyCombo alloc] init];
654 if ([df objectForKey:@"IncrementVolume"]) {
655 volumeIncrementCombo = [df keyComboForKey:@"IncrementVolume"];
656 [volumeIncrementButton setTitle:[volumeIncrementCombo userDisplayRep]];
658 volumeIncrementCombo = [[KeyCombo alloc] init];
661 if ([df objectForKey:@"DecrementVolume"]) {
662 volumeDecrementCombo = [df keyComboForKey:@"DecrementVolume"];
663 [volumeDecrementButton setTitle:[volumeDecrementCombo userDisplayRep]];
665 volumeDecrementCombo = [[KeyCombo alloc] init];
668 if ([df objectForKey:@"IncrementRating"]) {
669 ratingIncrementCombo = [df keyComboForKey:@"IncrementRating"];
670 [ratingIncrementButton setTitle:[ratingIncrementCombo userDisplayRep]];
672 ratingIncrementCombo = [[KeyCombo alloc] init];
675 if ([df objectForKey:@"DecrementRating"]) {
676 ratingDecrementCombo = [df keyComboForKey:@"DecrementRating"];
677 [ratingDecrementButton setTitle:[ratingDecrementCombo userDisplayRep]];
679 ratingDecrementCombo = [[KeyCombo alloc] init];
682 if ([df objectForKey:@"ToggleLoop"]) {
683 toggleLoopCombo = [df keyComboForKey:@"ToggleLoop"];
684 [toggleLoopButton setTitle:[toggleLoopCombo userDisplayRep]];
686 toggleLoopCombo = [[KeyCombo alloc] init];
689 if ([df objectForKey:@"ToggleShuffle"]) {
690 toggleShuffleCombo = [df keyComboForKey:@"ToggleShuffle"];
691 [toggleShuffleButton setTitle:[toggleShuffleCombo userDisplayRep]];
693 toggleShuffleCombo = [[KeyCombo alloc] init];
696 // Check current track info buttons
697 [albumCheckbox setState:[df boolForKey:@"showAlbum"] ? NSOnState : NSOffState];
698 [nameCheckbox setState:[df boolForKey:@"showName"] ? NSOnState : NSOffState];
699 [artistCheckbox setState:[df boolForKey:@"showArtist"] ? NSOnState : NSOffState];
700 [trackTimeCheckbox setState:[df boolForKey:@"showTime"] ? NSOnState : NSOffState];
702 // Set the launch at login checkbox state
704 loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
705 loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"];
707 loginEnum = [loginarray objectEnumerator];
708 while ( (anItem = [loginEnum nextObject]) ) {
709 if ([[[anItem objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) {
710 [launchAtLoginCheckbox setState:NSOnState];
716 /*************************************************************************/
718 #pragma mark NSWindow DELEGATE METHODS
719 /*************************************************************************/
721 - (void)windowWillClose:(NSNotification *)note
723 [(MainController *)controller closePreferences];
727 /*************************************************************************/
729 #pragma mark NSTableView DATASOURCE METHODS
730 /*************************************************************************/
732 - (int)numberOfRowsInTableView:(NSTableView *)aTableView
734 if (aTableView == menuTableView) {
735 return [myItems count];
737 return [availableItems count];
741 - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
743 if (aTableView == menuTableView) {
744 if ([[aTableColumn identifier] isEqualToString:@"name"]) {
745 return [myItems objectAtIndex:rowIndex];
747 if ([submenuItems containsObject:[myItems objectAtIndex:rowIndex]])
749 return [NSImage imageNamed:@"submenu"];
755 if ([[aTableColumn identifier] isEqualToString:@"name"]) {
756 return [availableItems objectAtIndex:rowIndex];
758 if ([submenuItems containsObject:[availableItems objectAtIndex:rowIndex]]) {
759 return [NSImage imageNamed:@"submenu"];
767 - (BOOL)tableView:(NSTableView *)tableView writeRows:(NSArray*)rows toPasteboard:(NSPasteboard*)pboard
769 if (tableView == menuTableView) {
770 [pboard declareTypes:[NSArray arrayWithObjects:@"MenuTableViewPboardType", nil] owner:self];
771 [pboard setString:[[rows objectAtIndex:0] stringValue] forType:@"MenuTableViewPboardType"];
775 if (tableView == allTableView) {
776 [pboard declareTypes:[NSArray arrayWithObjects:@"AllTableViewPboardType", nil] owner:self];
777 [pboard setString:[[rows objectAtIndex:0] stringValue] forType:@"AllTableViewPboardType"];
783 - (BOOL)tableView:(NSTableView*)tableView acceptDrop:(id <NSDraggingInfo>)info row:(int)row dropOperation:(NSTableViewDropOperation)operation
787 NSString *dragData, *temp;
789 pb = [info draggingPasteboard];
791 if ([[pb types] containsObject:@"MenuTableViewPboardType"]) {
792 dragData = [pb stringForType:@"MenuTableViewPboardType"];
793 dragRow = [dragData intValue];
794 temp = [myItems objectAtIndex:dragRow];
795 [myItems removeObjectAtIndex:dragRow];
797 if (tableView == menuTableView) {
799 [myItems insertObject:temp atIndex:row - 1];
801 [myItems insertObject:temp atIndex:row];
804 if (![temp isEqualToString:@"<separator>"]) {
805 [availableItems addObject:temp];
808 } else if ([[pb types] containsObject:@"AllTableViewPboardType"]) {
809 dragData = [pb stringForType:@"AllTableViewPboardType"];
810 dragRow = [dragData intValue];
811 temp = [availableItems objectAtIndex:dragRow];
813 if (![temp isEqualToString:@"<separator>"]) {
814 [availableItems removeObjectAtIndex:dragRow];
816 [myItems insertObject:temp atIndex:row];
819 [menuTableView reloadData];
820 [allTableView reloadData];
824 - (NSDragOperation)tableView:(NSTableView*)tableView validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)operation
826 if (tableView == allTableView) {
827 if ([[[info draggingPasteboard] types] containsObject:@"AllTableViewPboardType"]) {
828 return NSDragOperationNone;
831 if ([[[info draggingPasteboard] types] containsObject:@"MenuTableViewPboardType"]) {
832 NSString *item = [myItems objectAtIndex:[[[info draggingPasteboard] stringForType:@"MenuTableViewPboardType"] intValue]];
833 if ([item isEqualToString:@"PreferencesÉ"] || [item isEqualToString:@"Quit"]) {
834 return NSDragOperationNone;
838 [tableView setDropRow:-1 dropOperation:NSTableViewDropOn];
839 return NSDragOperationGeneric;
842 if (operation == NSTableViewDropOn || row == -1)
844 return NSDragOperationNone;
847 return NSDragOperationGeneric;
851 /*************************************************************************/
853 #pragma mark DEALLOCATION METHODS
854 /*************************************************************************/
858 [self setKeyCombo:nil];
859 [playPauseCombo release];
860 [nextTrackCombo release];
861 [prevTrackCombo release];
862 [trackInfoCombo release];
863 [upcomingSongsCombo release];
864 [keyComboPanel release];
865 [menuTableView setDataSource:nil];
866 [allTableView setDataSource:nil];
867 [controller release];
868 [availableItems release];
869 [submenuItems release];