
/* Generated by Interface Builder */

#import "ChaosView.h"
#import <appkit/Application.h>
#import <appkit/Slider.h>
#import <appkit/Form.h>
#import <math.h>
#import <dpsclient/psops.h>
#import <dpsclient/wraps.h>
#import <stdlib.h>
#import "UserPath.h"

#define	TRUE	1
#define	FALSE	0

@implementation ChaosView


static NXCoord	fixedWidth, fixedHeight;

- initFrame:(const NXRect *)frameRect
{
	
// Initialize the View and the variables describing the boundaries

	[super initFrame:frameRect];
	[self setOpaque:YES];
	
	userPath = newUserPath();
	
	fixedWidth = bounds.size.width;
	fixedHeight = bounds.size.height;
	
	xSize = (float)fixedWidth;
	ySize = (float)fixedHeight;
	
	printWidth = (NXCoord)480.0;
	printHeight = (NXCoord)480.0;
	
	PRINTINVERSE = TRUE;
	
	return self;
}

- drawSelf:(const NXRect *)rects :(int)rectCount
// This is the routine where everything really happens
// The background of the view is drawn and then the function itself
// is calculated.  The parameters used are global to this class, so
// the sliders can change them at any time.
{	
	int	i;

	if(rects == NULL) return self;
		

	if((NXDrawingStatus != NX_DRAWING)&&(PRINTINVERSE!=FALSE)){
		[self sizeTo:printWidth :printHeight];
		PSsetgray(NX_WHITE);
		NXRectFill(&bounds);
		PSsetgray(NX_BLACK);
		NXFrameRect(&bounds);
	}
	else{
		PSsetgray(NX_BLACK);
		NXRectFill(&bounds);
		PSsetgray(NX_WHITE);
		NXFrameRect(&bounds);
	}
	
	beginUserPath(userPath,NO);
	
	UPmoveto(userPath,0,0);
	
	// Calculate and draw the function x(t+1)=rx(t)(1-x(t))
	
	for(x=0;x<=1.1;x+=stepValue){
		y=x;
		for(i=0;i<iterationValue;i++){
			y = parameterValue*y*(1-y);
		}
		UPlineto(userPath,x*xSize,y*ySize);
	}
	
	PSsetgray(NX_DKGRAY);
	UPmoveto(userPath,0,0);
	UPlineto(userPath,xSize,ySize);
	PSsetgray(NX_WHITE);
	
	closePath(userPath);
    
	/* draw it */
	endUserPath(userPath, dps_ustroke);
	sendUserPath(userPath);
	return self;
}

- sizeTo:(NXCoord)width :(NXCoord)height
// Allow resizing
{
	
	[super sizeTo:width :height];

	[self setDrawSize	:fixedWidth
				:fixedHeight];
				
	[self setDrawOrigin: (0) :(0)];
	
	return self;
}


// This next set of routines takes care of adjusting the parameter calues
// whenever a slider is changed.  It also updates the value in the form next
// to the slider.

- iterationSliderChanged:sender
{
	iterationValue=[sender floatValue];
	[iterationFormOutlet setFloatValue:iterationValue at:0];

	[self display];
	return self;
}

- setIterationSliderOutlet:sender
{
	iterationSliderOutlet = sender;
	iterationValue = [iterationSliderOutlet floatValue];
	return self;
}

- setIterationFormOutlet:sender
{
	iterationFormOutlet = sender;
	[iterationFormOutlet setFloatValue:iterationValue at:0];
	return self;
}

- parameterSliderChanged:sender
{
	parameterValue=[sender doubleValue];
	[parameterFormOutlet setDoubleValue:parameterValue at:0];

	[self display];
	return self;
}

- setParameterSliderOutlet:sender
{
	parameterSliderOutlet = sender;
	parameterValue = [parameterSliderOutlet doubleValue];
	return self;
}
- setParameterFormOutlet:sender
{
	parameterFormOutlet = sender;
	[parameterFormOutlet setDoubleValue:parameterValue at:0];
	return self;
}

- stepSliderChanged:sender
{
	stepValue= [sender floatValue];
	[stepFormOutlet setFloatValue:stepValue at:0];

	[self display];
	return self;
}

- setStepSliderOutlet:sender
{
	stepSliderOutlet = sender;
	stepValue = [stepSliderOutlet floatValue];
	return self;
}
- setStepFormOutlet:sender
{
	stepFormOutlet = sender;
	[stepFormOutlet setFloatValue:stepValue at:0];
	return self;
}

@end

