/* 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 2.10.2.2 1993/10/26 00:09:46 rensing Exp $";

#import "Plot.h"

@implementation Overlay

- initList:list with:plot
{
    Plot		*g;
    binding_t		xaxis = XAXIS, yaxis = YAXIS;
    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 setAutoScale:&xaxis to:&flag];
    [firstPlot setAutoScale:&yaxis to:&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 setLogScale:&xaxis to:&logX];
	    [g setLogScale:&yaxis to:&logY];
	    [g setBounds:&bounds];
	}
    }
    
    return self;
}
- checkBounds
{
    NXRect	frameRect;
    NXCoord	edge;
    
    [firstPlot getBounds:&bounds];
    [[firstPlot graphicView] getFrame:&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];
    [components empty];
    return self;
}

- firstPlot
{
    return firstPlot;
}
- NameAxisX:(const char *) stringValue
{
    [firstPlot NameAxisX:stringValue];
    return self;
}
- NameAxisY:(const char *) stringValue
{
    [firstPlot NameAxisY:stringValue];
    return self;
}
- setAutoScale:(binding_t *) axis to:(const int *) value
{
    Plot               *plot;
    NXPoint             range, max_range;
    display             disp;
    unsigned int        i, count;


    [firstPlot setAutoScale:axis to:value];

    if (!*value) return self;

    disp = [firstPlot histDisplay];
    h_autoScale(disp);
    h_getRange(disp, *axis, &max_range.x, &max_range.y );
    count = [components count];
    for (i = 0; i < count; i++) {
	plot = [components objectAt:i];
	if ((plot != firstPlot) && [plot isKindOf:[Plot class]]) {
	    [plot setAutoScale:axis to:value];
	    disp = [plot histDisplay];
	    h_autoScale(disp);
	    switch (*axis) {
	    case XAXIS:
		h_getRange(disp, XAXIS, &range.x, &range.y );
		break;
	    case YAXIS:
		[plot getRangeForAxisY:&range normalizedTo:firstPlot];
		break;
	    default:
		break;
	    }
	    if (range.x < max_range.x) max_range.x = range.x;
	    if (range.y > max_range.y) max_range.y = range.y;
	}
    }
    [self makeGraphicsPerform:@selector(setRange:to:)
                 with :axis with:&max_range];

    return self;
}
- setRange:(binding_t* ) axis to:(const NXPoint *)p
{
    [firstPlot setRange:axis to:p];
    [components makeObjectsPerform:@selector(setRangesAndBinsFrom:) with:firstPlot];
    return self;
}

- setNumBins:(binding_t *) axis to:(const int *) value
{
    [firstPlot setNumBins:axis to:value];
    [components makeObjectsPerform:@selector(setRangesAndBinsFrom:) with: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
