+
+/*************************************************************************/
+#pragma mark -
+#pragma mark PRIVATE METHOD IMPLEMENTATIONS
+/*************************************************************************/
+
+- (void)setupWindow
+{
+ if ( ! [NSBundle loadNibNamed:@"Preferences" owner:self] ) {
+ NSLog( @"Failed to load Preferences.nib" );
+ NSBeep();
+ return;
+ }
+}
+
+- (void)setupCustomizationTables
+{
+ NSImageCell *imgCell = [[[NSImageCell alloc] initImageCell:nil] autorelease];
+
+ // Set the table view cells up
+ [imgCell setImageScaling:NSScaleNone];
+ [[menuTableView tableColumnWithIdentifier:@"submenu"] setDataCell:imgCell];
+ [[allTableView tableColumnWithIdentifier:@"submenu"] setDataCell:imgCell];
+
+ // Register for drag and drop
+ [menuTableView registerForDraggedTypes:[NSArray arrayWithObjects:
+ @"MenuTableViewPboardType",
+ @"AllTableViewPboardType",
+ nil]];
+ [allTableView registerForDraggedTypes:[NSArray arrayWithObjects:
+ @"MenuTableViewPboardType",
+ @"AllTableViewPboardType",
+ nil]];
+}
+
+- (void)setupMenuItems
+{
+ NSEnumerator *itemEnum;
+ id anItem;
+ // Set the list of items you can have.
+ availableItems = [[NSMutableArray alloc] initWithObjects:
+ @"Current Track Info",
+ @"Upcoming Songs",
+ @"Playlists",
+ @"EQ Presets",
+ @"Song Rating",
+ @"Play/Pause",
+ @"Next Track",
+ @"Previous Track",
+ @"Fast Forward",
+ @"Rewind",
+ @"Show Player",
+ @"<separator>",
+ nil];
+
+ // Get our preferred menu
+ myItems = [[df arrayForKey:@"menu"] mutableCopy];
+
+ // Delete items in the availableItems array that are already part of the menu
+ itemEnum = [myItems objectEnumerator];
+ while ( (anItem = [itemEnum nextObject]) ) {
+ if ( ! [anItem isEqualToString:@"<separator>"] ) {
+ [availableItems removeObject:anItem];
+ }
+ }
+
+ // Items that show should a submenu image
+ submenuItems = [[NSArray alloc] initWithObjects:
+ @"Upcoming Songs",
+ @"Playlists",
+ @"EQ Presets",
+ @"Song Rating",
+ nil];
+}
+
+- (void)setupUI
+{
+ NSMutableDictionary *loginwindow;
+ NSMutableArray *loginarray;
+ NSEnumerator *loginEnum;
+ id anItem;
+
+ // Fill in the number of songs in advance to show field
+ [songsInAdvance setIntValue:[df integerForKey:@"SongsInAdvance"]];
+
+ // Fill in hot key buttons
+ if ([df objectForKey:@"PlayPause"]){
+ playPauseCombo = [df keyComboForKey:@"PlayPause"];
+ [playPauseButton setTitle:[playPauseCombo userDisplayRep]];
+ } else {
+ playPauseCombo = [[KeyCombo alloc] init];
+ }
+
+ if ([df objectForKey:@"NextTrack"]) {
+ nextTrackCombo = [df keyComboForKey:@"NextTrack"];
+ [nextTrackButton setTitle:[nextTrackCombo userDisplayRep]];
+ } else {
+ nextTrackCombo = [[KeyCombo alloc] init];
+ }
+
+ if ([df objectForKey:@"PrevTrack"]) {
+ prevTrackCombo = [df keyComboForKey:@"PrevTrack"];
+ [previousTrackButton setTitle:[prevTrackCombo userDisplayRep]];
+ } else {
+ prevTrackCombo = [[KeyCombo alloc] init];
+ }
+
+ if ([df objectForKey:@"TrackInfo"]) {
+ trackInfoCombo = [df keyComboForKey:@"TrackInfo"];
+ [trackInfoButton setTitle:[trackInfoCombo userDisplayRep]];
+ } else {
+ trackInfoCombo = [[KeyCombo alloc] init];
+ }
+
+ if ([df objectForKey:@"UpcomingSongs"]) {
+ upcomingSongsCombo = [df keyComboForKey:@"UpcomingSongs"];
+ [upcomingSongsButton setTitle:[upcomingSongsCombo userDisplayRep]];
+ } else {
+ upcomingSongsCombo = [[KeyCombo alloc] init];
+ }
+
+ if ([df objectForKey:@"IncrementVolume"]) {
+ volumeIncrementCombo = [df keyComboForKey:@"IncrementVolume"];
+ [volumeIncrementButton setTitle:[volumeIncrementCombo userDisplayRep]];
+ } else {
+ volumeIncrementCombo = [[KeyCombo alloc] init];
+ }
+
+ if ([df objectForKey:@"DecrementVolume"]) {
+ volumeDecrementCombo = [df keyComboForKey:@"DecrementVolume"];
+ [volumeDecrementButton setTitle:[volumeDecrementCombo userDisplayRep]];
+ } else {
+ volumeDecrementCombo = [[KeyCombo alloc] init];
+ }
+
+ if ([df objectForKey:@"IncrementRating"]) {
+ ratingIncrementCombo = [df keyComboForKey:@"IncrementRating"];
+ [ratingIncrementButton setTitle:[ratingIncrementCombo userDisplayRep]];
+ } else {
+ ratingIncrementCombo = [[KeyCombo alloc] init];
+ }
+
+ if ([df objectForKey:@"DecrementRating"]) {
+ ratingDecrementCombo = [df keyComboForKey:@"DecrementRating"];
+ [ratingDecrementButton setTitle:[ratingDecrementCombo userDisplayRep]];
+ } else {
+ ratingDecrementCombo = [[KeyCombo alloc] init];
+ }
+
+ if ([df objectForKey:@"ToggleLoop"]) {
+ toggleLoopCombo = [df keyComboForKey:@"ToggleLoop"];
+ [toggleLoopButton setTitle:[toggleLoopCombo userDisplayRep]];
+ } else {
+ toggleLoopCombo = [[KeyCombo alloc] init];
+ }
+
+ if ([df objectForKey:@"ToggleShuffle"]) {
+ toggleShuffleCombo = [df keyComboForKey:@"ToggleShuffle"];
+ [toggleShuffleButton setTitle:[toggleShuffleCombo userDisplayRep]];
+ } else {
+ toggleShuffleCombo = [[KeyCombo alloc] init];
+ }
+
+ // Check current track info buttons
+ [albumCheckbox setState:[df boolForKey:@"showAlbum"] ? NSOnState : NSOffState];
+ [nameCheckbox setState:NSOnState]; // Song info will ALWAYS show song title.
+ [nameCheckbox setEnabled:NO]; // Song info will ALWAYS show song title.
+ [artistCheckbox setState:[df boolForKey:@"showArtist"] ? NSOnState : NSOffState];
+ [trackTimeCheckbox setState:[df boolForKey:@"showTime"] ? NSOnState : NSOffState];
+
+ // Set the launch at login checkbox state
+ [df synchronize];
+ loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
+ loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"];
+
+ loginEnum = [loginarray objectEnumerator];
+ while ( (anItem = [loginEnum nextObject]) ) {
+ if ([[[anItem objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) {
+ [launchAtLoginCheckbox setState:NSOnState];
+ }
+ }
+}
+
+- (IBAction)changeMenus:(id)sender
+{
+ [df setObject:myItems forKey:@"menu"];
+ [df synchronize];
+ [controller rebuildMenu];
+}
+
+- (void)setLaunchesAtLogin:(BOOL)flag
+{
+ if ( flag ) {
+ NSMutableDictionary *loginwindow;
+ NSMutableArray *loginarray;
+ ComponentInstance temp = OpenDefaultComponent(kOSAComponentType, kAppleScriptSubtype);;
+ int i;
+ BOOL skip = NO;
+
+ [df synchronize];
+ loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
+ loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"];
+
+ for (i = 0; i < [loginarray count]; i++) {
+ NSDictionary *tempDict = [loginarray objectAtIndex:i];
+ if ([[[tempDict objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) {
+ skip = YES;
+ }
+ }
+
+ if (!skip) {
+ AEDesc scriptDesc, resultDesc;
+ 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]];
+
+ AECreateDesc(typeChar, [script cString], [script cStringLength],
+ &scriptDesc);
+
+ OSADoScript(temp, &scriptDesc, kOSANullScript, typeChar, kOSAModeCanInteract, &resultDesc);
+
+ AEDisposeDesc(&scriptDesc);
+ AEDisposeDesc(&resultDesc);
+ CloseComponent(temp);
+ }
+
+ } else {
+ NSMutableDictionary *loginwindow;
+ NSMutableArray *loginarray;
+ int i;
+
+ [df synchronize];
+ loginwindow = [[df persistentDomainForName:@"loginwindow"] mutableCopy];
+ loginarray = [loginwindow objectForKey:@"AutoLaunchedApplicationDictionary"];
+
+ for (i = 0; i < [loginarray count]; i++) {
+ NSDictionary *tempDict = [loginarray objectAtIndex:i];
+ if ([[[tempDict objectForKey:@"Path"] lastPathComponent] isEqualToString:[[[NSBundle mainBundle] bundlePath] lastPathComponent]]) {
+ [loginarray removeObjectAtIndex:i];
+ [df setPersistentDomain:loginwindow forName:@"loginwindow"];
+ [df synchronize];
+ break;
+ }
+ }
+ }
+}
+
+
+/*************************************************************************/
+#pragma mark -
+#pragma mark NSWindow DELEGATE METHODS
+/*************************************************************************/
+
+- (void)windowWillClose:(NSNotification *)note
+{
+ [(MainController *)controller closePreferences];
+}
+
+
+/*************************************************************************/
+#pragma mark -
+#pragma mark NSTableView DATASOURCE METHODS
+/*************************************************************************/