
#import <gamekit/gamekit.h>


@implementation GKHighScorePanel

- initContent:(const NXRect *)contentRect style:(int)aStyle
		backing:(int)bufferingType buttonMask:(int)mask defer:(BOOL)flag;
{
	[super initContent:contentRect style:aStyle backing:bufferingType
			buttonMask:mask defer:flag];
	tableNum = 0;
	numSlots = GK_HS_DEFAULT_SLOTS;	// assume that .nib is set up for this
	wantSlot = GK_HS_NO_SLOT;
	return self;
}

- keyDown:(NXEvent *)myevent	// handle keyDown events (want to trap 'n')
{ // sent if no one else in the panel wants keys.
	if (myevent->data.key.charSet == NX_ASCIISET &&
		(myevent->flags&(NX_CONTROLMASK|NX_ALTERNATEMASK|NX_COMMANDMASK)) == 0)
	{	
		if (GKKEYCODE == 'n') { // allow new game
			[[NXApp delegate] startNewGame:self]; // re-start the game
			// returns nil if user changes mind...
			return self; // so we don't beep, since we got the keypress
		}
	}
	return [super keyDown:myevent];
}

- setTable:(int)num { tableNum = num; return self; } // you have to refresh
- changeTable:sender
{	// sent by pop up list to display a new table;
	// Note that which row you use determines the table's tag!
	tableNum = [sender selectedRow]; // row should correspond to table number
			// that the controller object is using.
	[self refresh];
    return self;
}

- nameEntered:sender
{	// sent when player enters their name; need to send name to delegate
	id theCell;
	if (wantSlot == GK_HS_NO_SLOT) return self;
	theCell = [playerNameMatrix findCellWithTag:wantSlot];
	if ([delegate respondsTo:@selector(nameForSlot:inTable:is:)]) 
		[delegate nameForSlot:wantSlot inTable:wantTable
				is:[theCell stringValue]]; // if improper delegate, oh well.
	[theCell setBackgroundGray:NX_LTGRAY];
	[theCell setBezeled:NO];
	[theCell setEditable:NO];
	wantSlot = GK_HS_NO_SLOT;
    return self;
}

- ok:sender
{	// ok button was hit, so enter the name and then get rid of the panel 
	[self nameEntered:self];
	[self orderOut:self];
    return self;
}

- resizeMatrixTo:(int)num
{	// resize all matrices so that they have num cells.  This only works
	// well if the matrices are in a ScrollView; if the numberMatrix is
	// connected to something, then we assume that we're in a ScrollView
	// since that matrix isn't needed otherwise.  Returns nil if can't
	// resize *****This isn't working quite right.  Doesn't erase xtra junk!
	// I've worked around it by forcing the table to be at least 10 slots
	// in size.*****
	int i;
	char *tempString = malloc(num/10 + 2); // won't be any longer than this
	if (num == numSlots) return self;	// we're already the right size
	if (!numberMatrix) return nil;		// don't have a number matrix-no resize
	if (num < 10) return nil;			// won't resize to smaller than 10
	numSlots = num;
	// add empty cells to all the matrices as needed
	[numberMatrix notifyAncestorWhenFrameChanged:YES];
	[[elapsedTimeMatrix renewRows:numSlots cols:1] sizeToCells];
	[[endLevelMatrix renewRows:numSlots cols:1] sizeToCells];
	[[endTimeMatrix renewRows:numSlots cols:1] sizeToCells];
	[[finalScoreMatrix renewRows:numSlots cols:1] sizeToCells];
	[[machineNameMatrix renewRows:numSlots cols:1] sizeToCells];
	[[playerNameMatrix renewRows:numSlots cols:1] sizeToCells];
	[[startLevelMatrix renewRows:numSlots cols:1] sizeToCells];
	[[startTimeMatrix renewRows:numSlots cols:1] sizeToCells];
	[[userNameMatrix renewRows:numSlots cols:1] sizeToCells];
	[[numberMatrix renewRows:numSlots cols:1] sizeToCells];
	for (i=1; i<=numSlots; i++) { // number the slots from 1 to numSlots
		sprintf(tempString, "%d.", i); // note that value is copied by
				// the -setStringValue so that overwriting it is OK to do.
		[[numberMatrix cellAt:0 :(i-1)] setStringValue:tempString];
	}
	return self;
}

- refresh
{	// get data from delegate and put it into the matrix and re-display
	id theTable; int i, slotsInTable;
	if ([delegate respondsTo:@selector(table:)])
		theTable = [delegate table:tableNum];
	else return self; // may as well bail if the delegate won't give us info!
	slotsInTable = [theTable count];
	// try to resize matrix to #slots in the table.
	[[self disableFlushWindow] disableDisplay]; // hold off on the graphics...
	[self resizeMatrixTo:slotsInTable];
	for (i=0; i<numSlots; i++) { // now fill the matrices w/slot data
		[[playerNameMatrix findCellWithTag:i]
				setStringValue:[[theTable objectAt:i] playerName]];
		[[machineNameMatrix findCellWithTag:i]
				setStringValue:[[theTable objectAt:i] machineName]];
		[[userNameMatrix findCellWithTag:i]
				setStringValue:[[theTable objectAt:i] userName]];
				
		[[startTimeMatrix findCellWithTag:i]
				setStringValue:[[[theTable objectAt:i] startTime]
				stringValue]];
		[[endTimeMatrix findCellWithTag:i]
				setStringValue:[[[theTable objectAt:i] endTime] stringValue]];
		[[elapsedTimeMatrix findCellWithTag:i]
				setStringValue:[[[theTable objectAt:i] elapsedTime]
				stringValue]];
		[[startLevelMatrix findCellWithTag:i]
				setIntValue:[[theTable objectAt:i] startLevel]];
		[[endLevelMatrix findCellWithTag:i]
				setIntValue:[[theTable objectAt:i] endLevel]];
		[[finalScoreMatrix findCellWithTag:i]
				setIntValue:[[theTable objectAt:i] finalScore]];
	}
	[[self reenableDisplay] displayIfNeeded]; // do all drawing at once
	[[self reenableFlushWindow] flushWindowIfNeeded]; // flush it out once
	return self;
}

- getPlayerName:(int)index table:(int)table
{	// sent by HighScoreController to allow player to enter name
	id tempCell;
	// if already looking to fill the name in a slot...
	// user lost chance to enter name; send default name back to
	// the delegate and then make it uneditable to allow next slot
	// to be entered in by the user.  Done by telling self user just
	// entered name, which, indirectly, has just happened.
	[self nameEntered:self];
	// now can set up to enter a new name.
	if (table != tableNum) { // wants to put in a different table than the
		// one currently displayed.
		// so we update pop up list and then get the new table
		// 1. select a new cell in the matrix and then
		// 2. reset the title of the trigger button
		[[[selectPopUp target] itemList] selectCellAt:tableNum :0]; // 1.
		[selectPopUp setTitle:[[selectPopUp target] selectedItem]]; // 2.
		tableNum = table; // set up to load in new table
	}
	[self refresh]; // with new slot in there, we need a refresh
	wantSlot = index;
	tempCell = [playerNameMatrix findCellWithTag:wantSlot];
	[tempCell setBackgroundGray:NX_WHITE];
	[tempCell setEditable:YES];
	[tempCell setBezeled:YES];
	// ***** users have suggested pausing before this part since there's an
	// ***** annoying tendency to "keep playing" and thereby trashing the
	// ***** name by hitting a key which comes here rather than to the game
	// ***** view where the user thought it would go.  This is needs fixing.
	// ***** maybe a complete event queue flush _and_ a short delay (such as
	// ***** a kind of ending sequence would be in order.  I'm not so sure
	// ***** that this object should worry about it, however.
	[self makeKeyAndOrderFront:self];  // want user to enter name, so bring
	[self makeFirstResponder:playerNameMatrix]; // up new first responder
	[playerNameMatrix selectCell:tempCell]; // and select entry field
	return self;
}

@end
