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] == 101) {
98 [self setLaunchesAtLogin:SENDER_STATE];
99 } else if ( [sender tag] == 102) {
100 [df setBool:SENDER_STATE forKey:@"LaunchPlayerWithMT"];
101 } else if ( [sender tag] == 103) {
102 [df setInteger:[sender intValue] forKey:@"SongsInAdvance"];
103 } else if ( [sender tag] == 104) {
104 [df setBool:SENDER_STATE forKey:@"showAlbum"];
105 } else if ( [sender tag] == 105) {
106 [df setBool:SENDER_STATE forKey:@"showName"];
107 } else if ( [sender tag] == 106) {
108 [df setBool:SENDER_STATE forKey:@"showArtist"];
109 } else if ( [sender tag] == 107) {
110 [df setBool:SENDER_STATE forKey:@"showTime"];
111 } else if ( [sender tag] == 108) {
112 [df setBool:SENDER_STATE forKey:@"showTrackNumber"];
113 } else if ( [sender tag] == 109) {
114 [df setBool:SENDER_STATE forKey:@"showTrackRating"];
118 - (IBAction)changeStatusWindowSetting:(id)sender
120 if ( [sender tag] == 201) {
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] == 202) {
125 // update screen selection
126 } else if ( [sender tag] == 203) {
127 // Update appearance effect
128 } else if ( [sender tag] == 204) {
129 // Update Vanish Effect
130 } else if ( [sender tag] == 205) {
131 // Update appearance speed
132 } else if ( [sender tag] == 206) {
133 // Update vanish speed
134 } else if ( [sender tag] == 207) {
135 // Update vanish delay
136 } else if ( [sender tag] == 208) {
137 // Update "Song Info window when song changes" setting.
141 - (IBAction)apply:(id)sender
144 [df setKeyCombo:playPauseCombo forKey:@"PlayPause"];
145 [df setKeyCombo:nextTrackCombo forKey:@"NextTrack"];
146 [df setKeyCombo:prevTrackCombo forKey:@"PrevTrack"];
147 [df setKeyCombo:trackInfoCombo forKey:@"TrackInfo"];
148 [df setKeyCombo:upcomingSongsCombo forKey:@"UpcomingSongs"];
149 [df setKeyCombo:volumeIncrementCombo forKey:@"IncrementVolume"];
150 [df setKeyCombo:volumeDecrementCombo forKey:@"DecrementVolume"];
151 [df setKeyCombo:ratingIncrementCombo forKey:@"IncrementRating"];
152 [df setKeyCombo:ratingDecrementCombo forKey:@"DecrementRating"];
153 [df setKeyCombo:toggleLoopCombo forKey:@"ToggleLoop"];
154 [df setKeyCombo:toggleShuffleCombo forKey:@"ToggleShuffle"];
156 //Set info checkboxes
157 [df setBool:[albumCheckbox state] forKey:@"showAlbum"];
158 [df setBool:[nameCheckbox state] forKey:@"showName"];
159 [df setBool:[artistCheckbox state] forKey:@"showArtist"];
160 [df setBool:[trackTimeCheckbox state] forKey:@"showTime"];
162 //Here we set whether we will launch at login by modifying loginwindow.plist
164 //Set songs in advance
165 if ([songsInAdvance intValue]) {
166 [df setInteger:[songsInAdvance intValue] forKey:@"SongsInAdvance"];
168 [df setInteger:5 forKey:@"SongsInAdvance"];
172 NSArray *apps = [[NSWorkspace sharedWorkspace] launchedApplications];
175 for (i = 0; i < [apps count]; i++) {
176 if ([[[apps objectAtIndex:i] objectForKey:@"NSApplicationName"]
177 isEqualToString:@"iTunes"]) {
178 [controller rebuildMenu];
182 [controller clearHotKeys];
185 - (void)registerDefaults
188 NSMutableDictionary *loginWindow;
189 NSMutableArray *loginArray;
190 NSEnumerator *loginEnum;
193 [df setObject:[NSArray arrayWithObjects:
208 @"Current Track Info",
209 nil] forKey:@"menu"];
211 [df setInteger:5 forKey:@"SongsInAdvance"];
212 [df setBool:YES forKey:@"showName"];
213 [df setBool:YES forKey:@"showArtist"];
214 [df setBool:NO forKey:@"showAlbum"];
215 [df setBool:NO forKey:@"showTime"];
219 loginWindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
220 loginArray = [loginWindow objectForKey:@"AutoLaunchedApplicationDictionary"];
221 loginEnum = [loginArray objectEnumerator];
223 while ( (anItem = [loginEnum nextObject]) ) {
224 if ( [[[anItem objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]] ) {
229 [loginWindow release];
232 // We must fix it so it is no longer suxy
234 if (NSRunInformationalAlertPanel(@"Auto-launch MenuTunes", @"Would you like MenuTunes to automatically launch at login?", @"Yes", @"No", nil) == NSOKButton) {
235 AEDesc scriptDesc, resultDesc;
236 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]];
237 ComponentInstance asComponent = OpenDefaultComponent(kOSAComponentType, kAppleScriptSubtype);
239 AECreateDesc(typeChar, [script cString], [script cStringLength],
242 OSADoScript(asComponent, &scriptDesc, kOSANullScript, typeChar, kOSAModeCanInteract, &resultDesc);
244 AEDisposeDesc(&scriptDesc);
245 AEDisposeDesc(&resultDesc);
247 CloseComponent(asComponent);
252 - (IBAction)cancelHotKey:(id)sender
254 [[NSNotificationCenter defaultCenter] removeObserver:self];
255 [NSApp endSheet:keyComboPanel];
256 [keyComboPanel orderOut:nil];
259 - (IBAction)clearHotKey:(id)sender
261 [self setKeyCombo:[KeyCombo clearKeyCombo]];
264 - (IBAction)okHotKey:(id)sender
266 NSString *string = [combo userDisplayRep];
271 if ([setHotKey isEqualToString:@"PlayPause"]) {
272 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
273 [combo isEqual:trackInfoCombo] || [combo isEqual:upcomingSongsCombo] ||
274 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
275 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
276 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
277 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
279 [window setLevel:NSNormalWindowLevel];
280 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
281 [window setLevel:NSStatusWindowLevel];
284 playPauseCombo = [combo copy];
285 [playPauseButton setTitle:string];
286 } else if ([setHotKey isEqualToString:@"NextTrack"]) {
287 if (([combo isEqual:playPauseCombo] || [combo isEqual:prevTrackCombo] ||
288 [combo isEqual:trackInfoCombo] || [combo isEqual:upcomingSongsCombo] ||
289 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
290 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
291 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
292 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
294 [window setLevel:NSNormalWindowLevel];
295 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
296 [window setLevel:NSStatusWindowLevel];
299 nextTrackCombo = [combo copy];
300 [nextTrackButton setTitle:string];
301 } else if ([setHotKey isEqualToString:@"PrevTrack"]) {
302 if (([combo isEqual:nextTrackCombo] || [combo isEqual:playPauseCombo] ||
303 [combo isEqual:trackInfoCombo] || [combo isEqual:upcomingSongsCombo] ||
304 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
305 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
306 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
307 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
309 [window setLevel:NSNormalWindowLevel];
310 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
311 [window setLevel:NSStatusWindowLevel];
314 prevTrackCombo = [combo copy];
315 [previousTrackButton setTitle:string];
316 } else if ([setHotKey isEqualToString:@"TrackInfo"]) {
317 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
318 [combo isEqual:playPauseCombo] || [combo isEqual:upcomingSongsCombo] ||
319 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
320 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
321 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
322 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
324 [window setLevel:NSNormalWindowLevel];
325 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
326 [window setLevel:NSStatusWindowLevel];
329 trackInfoCombo = [combo copy];
330 [trackInfoButton setTitle:string];
331 } else if ([setHotKey isEqualToString:@"UpcomingSongs"]) {
332 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
333 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
334 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
335 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
336 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
337 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
339 [window setLevel:NSNormalWindowLevel];
340 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
341 [window setLevel:NSStatusWindowLevel];
344 upcomingSongsCombo = [combo copy];
345 [upcomingSongsButton setTitle:string];
347 } else if ([setHotKey isEqualToString:@"IncrementVolume"]) {
348 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
349 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
350 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
351 [combo isEqual:upcomingSongsCombo] || [combo isEqual:volumeDecrementCombo] ||
352 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
353 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
355 [window setLevel:NSNormalWindowLevel];
356 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
357 [window setLevel:NSStatusWindowLevel];
360 volumeIncrementCombo = [combo copy];
361 [volumeIncrementButton setTitle:string];
362 } else if ([setHotKey isEqualToString:@"DecrementVolume"]) {
363 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
364 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
365 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
366 [combo isEqual:volumeIncrementCombo] || [combo isEqual:upcomingSongsCombo] ||
367 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
368 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
370 [window setLevel:NSNormalWindowLevel];
371 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
372 [window setLevel:NSStatusWindowLevel];
375 volumeDecrementCombo = [combo copy];
376 [volumeDecrementButton setTitle:string];
377 } else if ([setHotKey isEqualToString:@"IncrementRating"]) {
378 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
379 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
380 [combo isEqual:upcomingSongsCombo] || [combo isEqual:ratingDecrementCombo] ||
381 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
382 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
383 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
385 [window setLevel:NSNormalWindowLevel];
386 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
387 [window setLevel:NSStatusWindowLevel];
390 ratingIncrementCombo = [combo copy];
391 [ratingIncrementButton setTitle:string];
392 } else if ([setHotKey isEqualToString:@"DecrementRating"]) {
393 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
394 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
395 [combo isEqual:ratingIncrementCombo] || [combo isEqual:upcomingSongsCombo] ||
396 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
397 [combo isEqual:toggleLoopCombo] || [combo isEqual:toggleShuffleCombo]) &&
398 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
400 [window setLevel:NSNormalWindowLevel];
401 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
402 [window setLevel:NSStatusWindowLevel];
405 ratingDecrementCombo = [combo copy];
406 [ratingDecrementButton setTitle:string];
407 } else if ([setHotKey isEqualToString:@"ToggleLoop"]) {
408 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
409 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
410 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
411 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
412 [combo isEqual:upcomingSongsCombo] || [combo isEqual:toggleShuffleCombo]) &&
413 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
415 [window setLevel:NSNormalWindowLevel];
416 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
417 [window setLevel:NSStatusWindowLevel];
420 toggleLoopCombo = [combo copy];
421 [toggleLoopButton setTitle:string];
422 } else if ([setHotKey isEqualToString:@"ToggleShuffle"]) {
423 if (([combo isEqual:nextTrackCombo] || [combo isEqual:prevTrackCombo] ||
424 [combo isEqual:trackInfoCombo] || [combo isEqual:playPauseCombo] ||
425 [combo isEqual:ratingIncrementCombo] || [combo isEqual:ratingDecrementCombo] ||
426 [combo isEqual:volumeIncrementCombo] || [combo isEqual:volumeDecrementCombo] ||
427 [combo isEqual:toggleLoopCombo] || [combo isEqual:upcomingSongsCombo]) &&
428 !(([combo modifiers] == -1) && ([combo keyCode] == -1))) {
430 [window setLevel:NSNormalWindowLevel];
431 NSRunAlertPanel(@"Duplicate Key Combo", @"Please choose a unique key combo.", @"OK", nil, nil, nil);
432 [window setLevel:NSStatusWindowLevel];
435 toggleShuffleCombo = [combo copy];
436 [toggleShuffleButton setTitle:string];
438 [self cancelHotKey:sender];
441 - (IBAction)setNewHotKey:(id)sender
443 switch ([sender tag])
446 [self setKeyCombo:playPauseCombo];
447 [self setHotKey:@"PlayPause"];
450 [self setKeyCombo:nextTrackCombo];
451 [self setHotKey:@"NextTrack"];
454 [self setKeyCombo:prevTrackCombo];
455 [self setHotKey:@"PrevTrack"];
458 [self setKeyCombo:toggleLoopCombo];
459 [self setHotKey:@"ToggleLoop"];
462 [self setKeyCombo:toggleShuffleCombo];
463 [self setHotKey:@"ToggleShuffle"];
466 [self setKeyCombo:trackInfoCombo];
467 [self setHotKey:@"TrackInfo"];
470 [self setKeyCombo:upcomingSongsCombo];
471 [self setHotKey:@"UpcomingSongs"];
474 [self setKeyCombo:volumeIncrementCombo];
475 [self setHotKey:@"IncrementVolume"];
478 [self setKeyCombo:volumeDecrementCombo];
479 [self setHotKey:@"DecrementVolume"];
482 [self setKeyCombo:ratingIncrementCombo];
483 [self setHotKey:@"IncrementRating"];
486 [self setKeyCombo:ratingDecrementCombo];
487 [self setHotKey:@"DecrementRating"];
493 /*************************************************************************/
495 #pragma mark HOTKEY SUPPORT METHODS
496 /*************************************************************************/
498 - (void)setHotKey:(NSString *)key
501 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyEvent:) name:@"KeyBroadcasterEvent" object:nil];
502 [NSApp beginSheet:keyComboPanel modalForWindow:window modalDelegate:self didEndSelector:nil contextInfo:nil];
505 - (void)keyEvent:(NSNotification *)note
507 NSDictionary *info = [note userInfo];
512 keyCode = [[info objectForKey:@"KeyCode"] shortValue];
513 modifiers = [[info objectForKey:@"Modifiers"] longValue];
515 newCombo = [[KeyCombo alloc] initWithKeyCode:keyCode andModifiers:modifiers];
516 [self setKeyCombo:newCombo];
519 - (void)setKeyCombo:(KeyCombo *)newCombo
523 combo = [newCombo copy];
525 string = [combo userDisplayRep];
529 [keyComboField setStringValue:string];
533 /*************************************************************************/
535 #pragma mark PRIVATE METHOD IMPLEMENTATIONS
536 /*************************************************************************/
540 if ( ! [NSBundle loadNibNamed:@"Preferences" owner:self] ) {
541 NSLog( @"Failed to load Preferences.nib" );
547 - (void)setupCustomizationTables
549 NSImageCell *imgCell = [[[NSImageCell alloc] initImageCell:nil] autorelease];
551 // Set the table view cells up
552 [imgCell setImageScaling:NSScaleNone];
553 [[menuTableView tableColumnWithIdentifier:@"submenu"] setDataCell:imgCell];
554 [[allTableView tableColumnWithIdentifier:@"submenu"] setDataCell:imgCell];
556 // Register for drag and drop
557 [menuTableView registerForDraggedTypes:[NSArray arrayWithObjects:
558 @"MenuTableViewPboardType",
559 @"AllTableViewPboardType",
561 [allTableView registerForDraggedTypes:[NSArray arrayWithObjects:
562 @"MenuTableViewPboardType",
563 @"AllTableViewPboardType",
567 - (void)setupMenuItems
569 NSEnumerator *itemEnum;
571 // Set the list of items you can have.
572 availableItems = [[NSMutableArray alloc] initWithObjects:
573 @"Current Track Info",
587 // Get our preferred menu
588 myItems = [[df arrayForKey:@"menu"] mutableCopy];
590 // Delete items in the availableItems array that are already part of the menu
591 itemEnum = [myItems objectEnumerator];
592 while ( (anItem = [itemEnum nextObject]) ) {
593 if ( ! [anItem isEqualToString:@"<separator>"] ) {
594 [availableItems removeObject:anItem];
598 // Items that show should a submenu image
599 submenuItems = [[NSArray alloc] initWithObjects:
609 NSMutableDictionary *loginwindow;
610 NSMutableArray *loginarray;
611 NSEnumerator *loginEnum;
614 // Fill in the number of songs in advance to show field
615 [songsInAdvance setIntValue:[df integerForKey:@"SongsInAdvance"]];
617 // Fill in hot key buttons
618 if ([df objectForKey:@"PlayPause"]){
619 playPauseCombo = [df keyComboForKey:@"PlayPause"];
620 [playPauseButton setTitle:[playPauseCombo userDisplayRep]];
622 playPauseCombo = [[KeyCombo alloc] init];
625 if ([df objectForKey:@"NextTrack"]) {
626 nextTrackCombo = [df keyComboForKey:@"NextTrack"];
627 [nextTrackButton setTitle:[nextTrackCombo userDisplayRep]];
629 nextTrackCombo = [[KeyCombo alloc] init];
632 if ([df objectForKey:@"PrevTrack"]) {
633 prevTrackCombo = [df keyComboForKey:@"PrevTrack"];
634 [previousTrackButton setTitle:[prevTrackCombo userDisplayRep]];
636 prevTrackCombo = [[KeyCombo alloc] init];
639 if ([df objectForKey:@"TrackInfo"]) {
640 trackInfoCombo = [df keyComboForKey:@"TrackInfo"];
641 [trackInfoButton setTitle:[trackInfoCombo userDisplayRep]];
643 trackInfoCombo = [[KeyCombo alloc] init];
646 if ([df objectForKey:@"UpcomingSongs"]) {
647 upcomingSongsCombo = [df keyComboForKey:@"UpcomingSongs"];
648 [upcomingSongsButton setTitle:[upcomingSongsCombo userDisplayRep]];
650 upcomingSongsCombo = [[KeyCombo alloc] init];
653 if ([df objectForKey:@"IncrementVolume"]) {
654 volumeIncrementCombo = [df keyComboForKey:@"IncrementVolume"];
655 [volumeIncrementButton setTitle:[volumeIncrementCombo userDisplayRep]];
657 volumeIncrementCombo = [[KeyCombo alloc] init];
660 if ([df objectForKey:@"DecrementVolume"]) {
661 volumeDecrementCombo = [df keyComboForKey:@"DecrementVolume"];
662 [volumeDecrementButton setTitle:[volumeDecrementCombo userDisplayRep]];
664 volumeDecrementCombo = [[KeyCombo alloc] init];
667 if ([df objectForKey:@"IncrementRating"]) {
668 ratingIncrementCombo = [df keyComboForKey:@"IncrementRating"];
669 [ratingIncrementButton setTitle:[ratingIncrementCombo userDisplayRep]];
671 ratingIncrementCombo = [[KeyCombo alloc] init];
674 if ([df objectForKey:@"DecrementRating"]) {
675 ratingDecrementCombo = [df keyComboForKey:@"DecrementRating"];
676 [ratingDecrementButton setTitle:[ratingDecrementCombo userDisplayRep]];
678 ratingDecrementCombo = [[KeyCombo alloc] init];
681 if ([df objectForKey:@"ToggleLoop"]) {
682 toggleLoopCombo = [df keyComboForKey:@"ToggleLoop"];
683 [toggleLoopButton setTitle:[toggleLoopCombo userDisplayRep]];
685 toggleLoopCombo = [[KeyCombo alloc] init];
688 if ([df objectForKey:@"ToggleShuffle"]) {
689 toggleShuffleCombo = [df keyComboForKey:@"ToggleShuffle"];
690 [toggleShuffleButton setTitle:[toggleShuffleCombo userDisplayRep]];
692 toggleShuffleCombo = [[KeyCombo alloc] init];
695 // Check current track info buttons
696 [albumCheckbox setState:[df boolForKey:@"showAlbum"] ? NSOnState : NSOffState];
697 [nameCheckbox setState:[df boolForKey:@"showName"] ? NSOnState : NSOffState];
698 [artistCheckbox setState:[df boolForKey:@"showArtist"] ? NSOnState : NSOffState];
699 [trackTimeCheckbox setState:[df boolForKey:@"showTime"] ? NSOnState : NSOffState];
701 // Set the launch at login checkbox state
703 loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
704 loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"];
706 loginEnum = [loginarray objectEnumerator];
707 while ( (anItem = [loginEnum nextObject]) ) {
708 if ([[[anItem objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) {
709 [launchAtLoginCheckbox setState:NSOnState];
714 - (IBAction)changeMenus:(id)sender
716 [df setObject:myItems forKey:@"menu"];
718 [controller rebuildMenu];
721 - (void)setLaunchesAtLogin:(BOOL)flag
724 NSMutableDictionary *loginwindow;
725 NSMutableArray *loginarray;
726 ComponentInstance temp = OpenDefaultComponent(kOSAComponentType, kAppleScriptSubtype);;
731 loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
732 loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"];
734 for (i = 0; i < [loginarray count]; i++) {
735 NSDictionary *tempDict = [loginarray objectAtIndex:i];
736 if ([[[tempDict objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) {
742 AEDesc scriptDesc, resultDesc;
743 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]];
745 AECreateDesc(typeChar, [script cString], [script cStringLength],
748 OSADoScript(temp, &scriptDesc, kOSANullScript, typeChar, kOSAModeCanInteract, &resultDesc);
750 AEDisposeDesc(&scriptDesc);
751 AEDisposeDesc(&resultDesc);
752 CloseComponent(temp);
756 NSMutableDictionary *loginwindow;
757 NSMutableArray *loginarray;
761 loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
762 loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"];
764 for (i = 0; i < [loginarray count]; i++) {
765 NSDictionary *tempDict = [loginarray objectAtIndex:i];
766 if ([[[tempDict objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) {
767 [loginarray removeObjectAtIndex:i];
768 [df setPersistentDomain:loginwindow forName:@"loginwindow"];
777 /*************************************************************************/
779 #pragma mark NSWindow DELEGATE METHODS
780 /*************************************************************************/
782 - (void)windowWillClose:(NSNotification *)note
784 [(MainController *)controller closePreferences];
788 /*************************************************************************/
790 #pragma mark NSTableView DATASOURCE METHODS
791 /*************************************************************************/
793 - (int)numberOfRowsInTableView:(NSTableView *)aTableView
795 if (aTableView == menuTableView) {
796 return [myItems count];
798 return [availableItems count];
802 - (id)tableView:(NSTableView *)aTableView objectValueForTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex
804 if (aTableView == menuTableView) {
805 if ([[aTableColumn identifier] isEqualToString:@"name"]) {
806 return [myItems objectAtIndex:rowIndex];
808 if ([submenuItems containsObject:[myItems objectAtIndex:rowIndex]])
810 return [NSImage imageNamed:@"submenu"];
816 if ([[aTableColumn identifier] isEqualToString:@"name"]) {
817 return [availableItems objectAtIndex:rowIndex];
819 if ([submenuItems containsObject:[availableItems objectAtIndex:rowIndex]]) {
820 return [NSImage imageNamed:@"submenu"];
828 - (BOOL)tableView:(NSTableView *)tableView writeRows:(NSArray*)rows toPasteboard:(NSPasteboard*)pboard
830 if (tableView == menuTableView) {
831 [pboard declareTypes:[NSArray arrayWithObjects:@"MenuTableViewPboardType", nil] owner:self];
832 [pboard setString:[[rows objectAtIndex:0] stringValue] forType:@"MenuTableViewPboardType"];
836 if (tableView == allTableView) {
837 [pboard declareTypes:[NSArray arrayWithObjects:@"AllTableViewPboardType", nil] owner:self];
838 [pboard setString:[[rows objectAtIndex:0] stringValue] forType:@"AllTableViewPboardType"];
844 - (BOOL)tableView:(NSTableView*)tableView acceptDrop:(id <NSDraggingInfo>)info row:(int)row dropOperation:(NSTableViewDropOperation)operation
848 NSString *dragData, *temp;
850 pb = [info draggingPasteboard];
852 if ([[pb types] containsObject:@"MenuTableViewPboardType"]) {
853 dragData = [pb stringForType:@"MenuTableViewPboardType"];
854 dragRow = [dragData intValue];
855 temp = [myItems objectAtIndex:dragRow];
856 [myItems removeObjectAtIndex:dragRow];
858 if (tableView == menuTableView) {
860 [myItems insertObject:temp atIndex:row - 1];
862 [myItems insertObject:temp atIndex:row];
865 if (![temp isEqualToString:@"<separator>"]) {
866 [availableItems addObject:temp];
869 } else if ([[pb types] containsObject:@"AllTableViewPboardType"]) {
870 dragData = [pb stringForType:@"AllTableViewPboardType"];
871 dragRow = [dragData intValue];
872 temp = [availableItems objectAtIndex:dragRow];
874 if (![temp isEqualToString:@"<separator>"]) {
875 [availableItems removeObjectAtIndex:dragRow];
877 [myItems insertObject:temp atIndex:row];
880 [menuTableView reloadData];
881 [allTableView reloadData];
882 [self changeMenus:self];
886 - (NSDragOperation)tableView:(NSTableView*)tableView validateDrop:(id <NSDraggingInfo>)info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)operation
888 if (tableView == allTableView) {
889 if ([[[info draggingPasteboard] types] containsObject:@"AllTableViewPboardType"]) {
890 return NSDragOperationNone;
893 if ([[[info draggingPasteboard] types] containsObject:@"MenuTableViewPboardType"]) {
894 NSString *item = [myItems objectAtIndex:[[[info draggingPasteboard] stringForType:@"MenuTableViewPboardType"] intValue]];
895 if ([item isEqualToString:@"PreferencesÉ"] || [item isEqualToString:@"Quit"]) {
896 return NSDragOperationNone;
900 [tableView setDropRow:-1 dropOperation:NSTableViewDropOn];
901 return NSDragOperationGeneric;
904 if (operation == NSTableViewDropOn || row == -1)
906 return NSDragOperationNone;
909 return NSDragOperationGeneric;
913 /*************************************************************************/
915 #pragma mark DEALLOCATION METHODS
916 /*************************************************************************/
920 [self setKeyCombo:nil];
921 [playPauseCombo release];
922 [nextTrackCombo release];
923 [prevTrackCombo release];
924 [trackInfoCombo release];
925 [upcomingSongsCombo release];
926 [keyComboPanel release];
927 [menuTableView setDataSource:nil];
928 [allTableView setDataSource:nil];
929 [controller release];
930 [availableItems release];
931 [submenuItems release];