/* Overlay.m	by Paul Kunz	March 1991
 * Group of Plot graphics that overlay each other.
 *
 * Copyright (C)  1992  The Board of Trustees of
 * The Leland Stanford Junior University.  All Rights Reserved.
 */
 
#import "Overlay.h"

const char Overlay_h_rcsid[] = OVERLAY_H_ID;
const char Overlay_m_rcsid[] = "$Id: Overlay.m,v 1.5 1992/04/22 00:44:20 pfkeb Rel $";

#import <appkit/nextstd.h>
#import <objc/List.h>

#import "DrawDocument.h"
#import "HGraphicView.h"
#import "Plot.h"

@implementation Overlay

- initList:list with:plot
{
    id			g;
    unsigned int	i;
    int			flag = 0;
    int 		logX, logY;
    
    [super initList:list];
    
    [self getExtendedBounds:&initialRect];
    firstPlot = plot;
    [self checkBounds];
    logX = [firstPlot isLogScaleX];
    logY = [firstPlot isLogScaleY];
    [firstPlot setAutoScaleX:&flag];
    [firstPlot setAutoScaleY:&flag];
    lastRect = bounds;
    i = [components count];
    while ( i-- ) {
        g = [components objectAt:i];
	if ( g != firstPlot ) {
	    [g setRangesFrom:firstPlot];
	    [g setTitlesFlag:&flag];
	    [g setAxesFlag:&flag];
	    [g setLogScaleX:&logX];
	    [g setLogScaleY:&logY];
	    [g setBounds:&bounds];
	}
    }
    
    return self;
}
- checkBounds
{
    NXRect	frameRect;
    NXCoord	edge;
    
    [firstPlot getBounds:&bounds];
    [[[[firstPlot graphicView] window] delegate] getPageFrame:&frameRect];
    if ( NXContainsRect( &frameRect, &bounds) ) {
        return self;
    }
    edge = NX_MAXX(&frameRect);
    if ( NX_MAXX(&bounds) > edge ) {
        [firstPlot moveRightEdgeTo:&edge];
    }
    edge = NX_MAXY(&frameRect);
    if ( NX_MAXY(&bounds) > edge ) {
        [firstPlot moveTopEdgeTo:&edge ];
    }
    edge = NX_X(&frameRect);
    if ( NX_X(&bounds) < edge ) {
	[firstPlot moveLeftEdgeTo:&edge];
    }
    edge = NX_Y(&frameRect);
    if ( NX_Y(&bounds) < edge ) {
        [firstPlot moveBottomEdgeTo:&edge ];
    }
    [firstPlot getBounds:&bounds];
    NXUnionRect(&bounds, &initialRect);
    return self;
}
- (NXRect *) getInitialBounds:(NXRect *)initBounds
{
    *initBounds = initialRect;
    return initBounds;
}
- transferSubGraphicsTo:list at:(int)position
{
    id		g;
    NXRect	b;
    int		i, flag = 1;

    b = bounds;
    i = [components count];
    while ( i-- ) {
	g = [components objectAt:i];
        if ( [g isKindOf:[Plot class]] ) {
	    [g setTitlesFlag:&flag];
	    [g setAxesFlag:&flag];
	    [g setBounds:&b];
	    b.origin.x += 10.0;
	    b.origin.y -= 10.0;
	}
    }
    [super transferSubGraphicsTo:list at:position];
    return self;
}

- firstPlot
{
    return firstPlot;
}
- NameAxisX:(const char *) stringValue
{
    [firstPlot NameAxisX:stringValue];
    return self;
}
- NameAxisY:(const char *) stringValue
{
    [firstPlot NameAxisY:stringValue];
    return self;
}
- setAutoScaleX:(const int *) value
{
    id			plot;
    NXPoint		range, max_range;
    unsigned int	i, count;
    int			state;
    
    state = *value;
    if ( state ) {
        [self makeGraphicsPerform:@selector(setAutoScaleX:) with:&state];
	state = 0;
	max_range.x = +1.0;
	max_range.y = -1.0;
	count = [components count];
	for ( i = 0; i < count; i++ ) {
	    plot = [components objectAt:i];
	    if ( [plot isKindOf:[Plot class]] ) {
		[plot getRangeForAxisX: &range];
		max_range.x = MIN( max_range.x, range.x);
		max_range.y = MAX( max_range.y, range.y);
		[plot setAutoScaleX:&state];
	    }
	}
        [self makeGraphicsPerform:@selector(setRangeForAxisX:)
			     with:&max_range];
    }
    return self;
}
- setAutoScaleY:(const int *) value
{
    id			plot, save_plot;
    NXPoint		range, max_range;
    graphtype_t		plot_t;
    unsigned int	i, count;
    int			state;
    
    state = *value;
    if ( state ) {
        [self makeGraphicsPerform:@selector(setAutoScaleY:) with:&state];
	state = 0;
	save_plot = nil;
	[firstPlot getRangeForAxisY:&max_range];
	[firstPlot setAutoScaleY:&state];
	count = [components count];
	for ( i = 0; i < count; i++ ) {
	    plot = [components objectAt:i];
	    if ( (plot != firstPlot) && [plot isKindOf:[Plot class]] ) {
		[plot getRangeForAxisY: &range normalizedTo:firstPlot];
		max_range.x = MIN( max_range.x, range.x);
		max_range.y = MAX( max_range.y, range.y);
		[plot setAutoScaleY:&state];
	    }
	}
	[firstPlot setRangeForAxisY:&max_range];
	[firstPlot getDispType:&plot_t];
	if ( plot_t == HISTOGRAM ) {
	    for ( i = 0; i < count; i++ ) {
		plot = [components objectAt:i];
		if ( plot != firstPlot ) {
		    [plot setRangesFrom:firstPlot];
		}
	    }
	} else {
            [self makeGraphicsPerform:@selector(setRangeForAxisY:)
		    		 with:&max_range];
	}
    }
    return self;
}
- setRangeForAxisY:(NXPoint *) value
{
    unsigned int	i;
    
    [firstPlot setRangeForAxisY:value];
    i = [components count];
    while ( i-- ) {
        [[components objectAt:i] setRangesFrom:firstPlot];
    }
    return self;
}
- setTitle:(const char *) stringValue
{
    [firstPlot setTitle:stringValue];
    return self;
}
- setTitlesFlag:(const int *) value
{
    [firstPlot setTitlesFlag:value];
    return self;
}

/* Methods supporting archiving and de-archiving */
- write:(NXTypedStream *) ts
{
    [super write:ts];
    NXWriteObjectReference( ts, firstPlot );
    return self;
}
- read:(NXTypedStream *)ts
{
    [super read:ts];
    firstPlot = NXReadObject( ts );
    return self;
}
@end
