/**************************************************
 * SynthBuilder
 * Copyright 1993 Nick Porcaro All Rights Reserved
 **************************************************/


/* Generated by Interface Builder */

#import "EnvController.h"
#import "EnvelopeView.h"
#import "EnvDelegate.h"
#import <appkit/Application.h>
#import <appkit/Panel.h>
#import <appkit/Button.h>
#import <appkit/ButtonCell.h>
#import <appkit/Cell.h>
#import <appkit/ActionCell.h>
#import <appkit/Matrix.h>
#import <appkit/View.h>
#import <appkit/Form.h>
#import <appkit/Listener.h>
#import <appkit/PopUpList.h>
#import	<appkit/NXSplitView.h>
#import	<objc/List.h>
#import <stdlib.h>
#import <ctype.h>
#import <math.h>

extern NXDefaultsVector envelopeDefaults;

@implementation EnvController

//===================================================================
// Operations on Envelopes
//===================================================================

- free
{
  [theEnvelopeView free];
  return [super free];
}

- envelope
{
  return [theEnvelopeView envelope];
}

- setNewEnvelope:anEnv
{
  if (!theEnvelopeView)
    {
      [self addEnvelope:self];
    }

  [theEnvelopeView setNewEnvelope:anEnv];
  return self;
}

- envelopeDrawn
/* Do the right thing when the envelope has been drawn */
{
  [theDelegate sendEnvelope];
  return self;
}

- addEnvelope:sender
{
	id old;
	NXRect * theFrame;


	[theDelegate willAddEnvelope];
	theFrame = NXZoneMalloc([self zone], sizeof (NXRect));
	[theSplitView getFrame: theFrame];
	old=theEnvelopeView;
	if (old!=NULL) [old dim];
	theEnvelopeView=[[EnvelopeView alloc] initFrame: theFrame];
	[theEnvelopeView controllerIs: self];
	[theDelegate willSplitView];
	[theSplitView addSubview: theEnvelopeView];
	[theSplitView adjustSubviews];
	[theSplitView display];
	[theWindow makeFirstResponder: theEnvelopeView];
	if (old!=NULL && [theLinkX state]==1) 
		[self broadcastXLimitsOf: old];
	NXZoneFree([self zone], theFrame);

	[theDelegate envelopeAdded];
    return self;
}

- removeEnvelope:sender
{
	id views;
	unsigned int lastIndex;
	
	[theDelegate willRemoveEnvelope];
	if (theEnvelopeView!=NULL) {
		lastIndex=[[theSplitView subviews] 
			indexOf: theEnvelopeView];				// where is on the subview list?
		lastDeleted=[theEnvelopeView copy];			// remember last envelope...
		[theEnvelopeView removeFromSuperview];		// ...but delete it from the window!
		views=[theSplitView subviews];
		if ([views count]==0)					// define pointer to new envelope
			theEnvelopeView=NULL;
		else {
			if ((theEnvelopeView=[views objectAt: lastIndex])==NULL)
				theEnvelopeView=[views objectAt: 0];
		}
		if (theEnvelopeView!=NULL)
			[theWindow makeFirstResponder: theEnvelopeView];
		
		[theDelegate willSplitView];
		[theSplitView adjustSubviews];			// display new split view
		[theSplitView display];
	}
	[theDelegate envelopeRemoved];
	return self; 
}

- unRemoveEnvelope:sender
{
	id old;
	
	if (lastDeleted!=NULL) {					// only if previous delete
		[theSplitView addSubview: lastDeleted];
		old=theEnvelopeView;
		if (old!=NULL) [old dim];
		theEnvelopeView=lastDeleted;				// set new current envelope
		lastDeleted=NULL;
		[theWindow makeFirstResponder: theEnvelopeView];
		if (old!=NULL && [theLinkX state]==1) 
			[self broadcastXLimitsOf: old];
		[theDelegate willSplitView];
		[theSplitView adjustSubviews];
		[theSplitView display];
	}
    return self;
}

- update: sender
{
	int point;
	
	if (theEnvelopeView!=NULL && theEnvelopeView!=sender)
		[theEnvelopeView dim];
	if (theEnvelopeView!=sender) {
		theEnvelopeView=sender;
		[theEnvelopeView highlight];
		[theWindow makeFirstResponder: theEnvelopeView];
	}
	point=[sender getPoint];
	[thePoint setIntValue: point];
	[theXCoord setFloatValue: [sender getX: point]];
	[theYCoord setFloatValue: [sender getY: point]];
	[theYrCoord setFloatValue: [sender getYr: point]];
	[theSmoothing setFloatValue: [sender getSmoothing: point]];
	[theSmoothSlider setFloatValue: [sender getSmoothing: point]];
	[theXMinCoord setFloatValue: [sender getXMin]];
	[theXMaxCoord setFloatValue: [sender getXMax]];
	[theYMinCoord setFloatValue: [sender getYMin]];
	[theYMaxCoord setFloatValue: [sender getYMax]];
	[theXSnapCoord setFloatValue: [sender getXSnap]];
	[theYSnapCoord setFloatValue: [sender getYSnap]];
	[theStickyPoint setState: [sender getSticky: point]];
	[theGraphType setState: [sender getShowSmooth]];
	return self;
}

- updateCoords: sender at: (int)point
{
	[theXCoord setFloatValue: [sender getX: point]];
	[theYCoord setFloatValue: [sender getY: point]];
	[theYrCoord setFloatValue: [sender getYr: point]];
	return self;	
}

//===================================================================
// Pasteboard interface methods
//===================================================================

- copy:sender
{
	if (theEnvelopeView!=NULL)
		return [theEnvelopeView copy: sender];
	return self;
}

- paste:sender
{
	if (theEnvelopeView!=NULL)
		return [theEnvelopeView paste: sender];
	return self;
}

//===================================================================
// Messages received from panel buttons and fields to update parameters
//===================================================================

- nextPoint:sender
{
	if (theEnvelopeView!=NULL) [theEnvelopeView nextPoint];
	return self;
}

- previousPoint:sender
{
	if (theEnvelopeView!=NULL) [theEnvelopeView previousPoint];
	return self;
}

- setPoint:sender
{
	if (theEnvelopeView!=NULL) [theEnvelopeView setPointTo: [sender intValue]];
	return self;
}

- setXValue:sender
{
	if (theEnvelopeView!=NULL) 
		[theEnvelopeView setXAt: [thePoint intValue] to: [sender floatValue]];
	return self;
}

- setYValue:sender
{
	if (theEnvelopeView!=NULL) 
		[theEnvelopeView setYAt: [thePoint intValue] to: [sender floatValue]];
	return self;
}

- setYrValue:sender
{
	if (theEnvelopeView!=NULL) 
		[theEnvelopeView setYrAt: [thePoint intValue] to: [sender floatValue]];
	return self;
}

- setSmoothValue:sender
{
	float smooth;
	
	smooth=[sender floatValue];
	smooth=rint(smooth*1000)/1000;
	[theSmoothSlider setFloatValue: smooth];
	if (theEnvelopeView!=NULL) 
		[theEnvelopeView setSmoothAt: [thePoint intValue] to: smooth];
	return self;
}

- setSmoothFromSlider:sender
{
	float smooth;
	
	smooth=[sender floatValue];
	smooth=rint(smooth*1000)/1000;
	[theSmoothing setFloatValue: smooth];
	if (theEnvelopeView!=NULL) 
		[theEnvelopeView setSmoothAt: [thePoint intValue] to: smooth];
	return self;
}

- broadcastXLimitsOf:envelope
{
	unsigned int i;
	List * envelopes;
	double max, min;
	
	min=[envelope getXMin];
	max=[envelope getXMax];
	envelopes=[theSplitView subviews];
	for (i=0; i<[envelopes count]; i++)
		[[envelopes objectAt: i] setXLimitsTo:min :max];
	return self;
}

- setXMinValue:sender
{
  [self makeXMinValue: [sender floatValue]];
  return self;
}

- makeXMinValue:(double) val
{
	if (theEnvelopeView!=NULL) {
		[theEnvelopeView setXMinTo: val];
		if ([theLinkX state]==1) 
			[self broadcastXLimitsOf: theEnvelopeView];
	}
	return self;
}

- setXMaxValue:sender
{
  [self makeXMaxValue: [sender floatValue]];
  return self;
}

- makeXMaxValue:(double) val
{
	if (theEnvelopeView!=NULL) {
		[theEnvelopeView setXMaxTo: val];
		if ([theLinkX state]==1) 
			[self broadcastXLimitsOf: theEnvelopeView];
	}
	return self;
}

- setYMinValue:sender
{
  [self makeYMinValue: [sender floatValue]];
  return self;
}

- makeYMinValue:(double) val
{
	if (theEnvelopeView!=NULL) {
		[theEnvelopeView setYMinTo:val];
	}
	return self;
}

- setYMaxValue:sender
{
  [self makeYMaxValue: [sender floatValue]];
  return self;
}

- makeYMaxValue:(double) val
{
	if (theEnvelopeView!=NULL) {
		[theEnvelopeView setYMaxTo:val];
	}
	return self;
}

- setXSnapValue:sender
{
	if (theEnvelopeView!=NULL) {
		[theEnvelopeView setXSnapTo: [sender floatValue]];
	}
	return self;
}

- setYSnapValue:sender
{
	if (theEnvelopeView!=NULL) {
		[theEnvelopeView setYSnapTo: [sender floatValue]];
	}
	return self;
}

- setStickyPoint:sender
{
	if (theEnvelopeView!=NULL) 
		[theEnvelopeView setStickyAt: [thePoint intValue] To: [sender state]];
	return self;
}

- makeGraphType:(int) val
{
  if (theEnvelopeView!=NULL) 
    [theEnvelopeView setShowSmooth: val];
  return self;

}

- setGraphType:sender
{
  [self makeGraphType:(int) [sender state]];
  return self;
}

- setDrawSegmentsState:sender
{
	if (theEnvelopeView!=NULL) {
	    if ([theEnvelopeView getDrawSegments]==-1)
		[theEnvelopeView setDrawSegments: 0];
	    else
	    	[theEnvelopeView setDrawSegments: -1];
	}
	return self;
}

- setLinkX:sender
{
	if (theEnvelopeView!=NULL && [sender state]==1) 
		[self broadcastXLimitsOf: theEnvelopeView];
	return self;
}

- reScaleLimits:sender;
{
	if (theEnvelopeView!=NULL) {
		[theEnvelopeView scaleLimits];
		if ([theLinkX state]==1) 
			[self broadcastXLimitsOf: theEnvelopeView];
	}
	return self;
}

//===================================================================
// Messages received from the envelope to query for parameters
//===================================================================

- (const char *)getStyle
{
	return [[[theOutputTypes cell] target] selectedItem];
}

@end
