/* InspectFunc.h		by Paul Kunz	May 1992
 * Controls list of user added functions.
 *
 * Copyright (C)  1991  The Board of Trustees of
 * The Leland Stanford Junior University.  All Rights Reserved.
 */

#import "HGraphicView.h"
#import "InspectFunc.h"

const char InspectFunc_h_rcsid[] = INSPECTFUNC_H_ID;
const char InspectFunc_m_rcsid[] = "$Id: InspectFunc.m,v 2.25 1993/08/16 16:35:55 pfkeb Exp $";

#import "HAddColFunction.h"
#import "HDrawApp.h"
#import "HTuple.h"
#import "InspectTuple.h"
#import "NewInspector.h"
#import "Plot.h"

@interface InspectFunc(PrivateMethods)
- showMessagesFrom:(HAddColFunction *)funcObj;
 /*
  * Displays the messages from the compiling, linking or other messages
  * from the function funcObj.
  */
- removeFunc:funcObj;
 /*
  * Removes the function funcObj from the function list.
  */

- updateFuncList;
 /*
  * Updates function browser and selected current tuple
  * in tuple browser.
  */
- updatePlots:(ntuple) ntuple;
 /*
  * Marks as dirty and plots that used the current n-tuple
  */
- updateTupleList;
 /*
  * Updates tupleBrowser if needed.
  */
@end

@implementation InspectFunc

- initInspFor:aDraw
{    
    NXBundle	*bundle;
    char	buffer[MAXPATHLEN+1];
    
    [super initInspFor:aDraw];
    
    bundle = [NXBundle bundleForClass:[self class]];
    if ( [bundle getPath:buffer forResource:"InspectFunc" ofType:"nib"] ) {
    	[NXApp loadNibFile:buffer owner:self
                 withNames:NO  fromZone:[self zone]];
    }
    [theInspector addView:[contentBox contentView]
                  withName:"Tuple Functions" withSupervisor:self];
    [statusText setStringValue:""];
    [statusText display];
    NXPing();
    return self;
}

- newFunction:sender
{
    HAddColFunction	*funcObj;
    Matrix		*browserMatrix;
    const char		*name;
    int			irc, row;
    List *currentList = [[hDraw inspectTuple] tupleList];
    
    browserMatrix = [tupleBrowser matrixInColumn:0];
    row = [browserMatrix selectedRow];
    hTuple = [currentList objectAt:row];
    if ( !hTuple ) {
        return self;
    }
    [funcNamePanel makeKeyAndOrderFront:self];
    [funcNameForm selectTextAt:0];
    irc = [NXApp runModalFor:funcNamePanel];
    [funcNamePanel orderOut:self];
    if ( irc ) {
        return self;
    }
    name = [funcNameForm stringValueAt:0];
    funcObj = [[HAddColFunction allocFromZone:[hTuple zone]]
                          initSource:ANSI_C for:hTuple withName:name];
    irc = [funcObj saveToTmpFile];
    if ( irc != 0 ) {
        NXRunAlertPanel("Error", "Unable to save template function"
		" to /tmp", "OK", NULL, NULL );
	[funcObj free];
	return self;
    }
    [statusText setStringValue:"Editing"];
    [statusText display];
    NXPing();
    [[Application workspace] openFile:[funcObj filename]];
    funcList = [hTuple functionList];
    [funcList addObject:funcObj];
    [funcBrowser reloadColumn:0];
    irc = [funcList indexOf:funcObj];
    [[funcBrowser matrixInColumn:0] selectCellAt:irc :0];
    return self;
}
- newColumnFunction:sender
{
    id			inspectTuple;
    id			funcObj;
    const char		*name;
    int			irc;
    
    inspectTuple = [hDraw inspectTuple];
    hTuple = [inspectTuple currentHTuple];
    if ( !hTuple ) {
        return self;
    }
	
	//hTuple = sender;
    [funcNamePanel makeKeyAndOrderFront:self];
    irc = [NXApp runModalFor:funcNamePanel];
    [funcNamePanel orderOut:self];
    if ( irc ) {
        return self;
    }
    name = [funcNameForm stringValueAt:0];
    funcObj = [[HAddColFunction allocFromZone:[self zone]] 
                          initSource:ANSI_C for:hTuple withName:name];
    irc = [funcObj saveToTmpFile];
    if ( irc != 0 ) {
        NXRunAlertPanel("Error", "Unable to save template function"
		" to /tmp", "OK", NULL, NULL );
	[funcObj free];
	return self;
    }
    [statusText setStringValue:"Editing"];
    [statusText display];
    NXPing();
    [[Application workspace] openFile:[funcObj filename]];
    funcList = [hTuple functionList];
    [funcList addObject:funcObj];
    [funcBrowser reloadColumn:0];
    return self;
}

- funcNameOK:sender
{
    List		*flist;
    id			funcObj;
    const char		*name;
    int			irc;
    int	i;
    
    if (!hTuple) return self;
    
    name = [funcNameForm stringValueAt:0];
    flist = [hTuple functionList];
    if (!flist) return self;
    
    i = [flist count];
    while (i--) {
	funcObj = [flist objectAt:i];
	if ( !strcmp( name, [funcObj functionName] ) ) {
	    irc = NXRunAlertPanel("Warning",
			          "Function name already in use. "
			          "Reuse same name?",
					"OK", "Cancel", NULL);
	    if ( irc != NX_ALERTDEFAULT ) {
		[NXApp stopModal:1];
		return self;
	    }
	}
    }
    [NXApp stopModal:0];
    return self;
}
- funcNameCancel:sender
{
    [NXApp stopModal:1];
    return self;
}
- performCompile:sender
{
    List	*tupleList;
    id		inspectTuple;
    id		matrix;
    int		row;
    int		irc;
    
    matrix = [funcBrowser matrixInColumn:0];
    row = [matrix selectedRow];
    if ( row < 0 ) {
        return self;
    }
    curFuncObj = [funcList objectAt:row];
    
    matrix = [tupleBrowser matrixInColumn:0];
    row = [matrix selectedRow];
    inspectTuple = [hDraw inspectTuple];
    tupleList = [inspectTuple tupleList];
    hTuple = [tupleList objectAt:row];
    if ( hTuple != [curFuncObj hTuple] ) {
        irc = NXRunAlertPanel("Warning",
	        "Function was compiled with different n-tuple",
		"Proceed", "Cancel", NULL);
	if ( irc != NX_ALERTDEFAULT ) {
	    return self;
	}
    }
    if ( [self performFunction:curFuncObj with:[hTuple ntuple]] ) {
        return self;
    }
    [self updatePlots:[hTuple ntuple]];
    [[hDraw inspectTuple] updateColBrowser];
    return self;
}
- performEdit:sender
{
    Matrix	*matrix;
    int		row;
        
    matrix = [funcBrowser matrixInColumn:0];
    row = [matrix selectedRow];
    if ( row < 0 ) {
        return self;
    }
    curFuncObj = [funcList objectAt:row];
    [[Application workspace] openFile:[curFuncObj filename]];
    return self;
}
- (int) performFunction:(HAddColFunction *)funcObj with:(ntuple)nt
{
    [statusText setStringValue:"Compiling"];
    [statusText display];
    NXPing();
    
    if ( [funcObj compile] ) {
        [self showMessagesFrom:funcObj];
	return (-1);
    }
        
    [statusText setStringValue:"Linking"];
    [statusText display];
    NXPing();
    if ( [funcObj link] ) {
        [self showMessagesFrom:funcObj];
	[self removeFunc:funcObj];
	return (-1);
    }
        
    [statusText setStringValue:"Executing"];
    [statusText display];
    NXPing();
    if ( [funcObj executeWith:nt] ) {
        NXRunAlertPanel("Error", "Error executing tuple function",
		"OK", NULL, NULL );
	[self removeFunc:funcObj];
	return (-1);
    }
    if ( [funcObj unload] ) {
        [self showMessagesFrom:funcObj];
    }
    [statusText setStringValue:""];
    [statusText display];
    NXPing();
    return 0;
}
- closeMessageWindow:sender
{
    if ( [[sender selectedCell] tag] == 1 ) {
	[[Application workspace] openFile:[curFuncObj filename]];
    } else {
    	[self removeFunc:curFuncObj];
    }
    NXClose(msgStream);
    return self;
}
- tupleBrowserSelected:sender
{
    id		browserMatrix;
    int		row;
    List *currentList = [[hDraw inspectTuple] tupleList];
    
    [graphicView deselectAll:self];
    browserMatrix = [tupleBrowser matrixInColumn:0];
    row = [browserMatrix selectedRow];
    hTuple = [currentList objectAt:row];
    [self updateFuncList];
    return self;
}

/* Methods for updating Inspector */
- updateView
{
    [self updateTupleList];
    hTuple = [firstPlot hTuple];
    [self updateFuncList];
    return self;
}
- updateEmptySelection
{
    [self updateTupleList];
    [self updateFuncList];
    return self;
}
/* Delegate Method for NXBrowsers */
- (int) browser: sender fillMatrix: matrix inColumn: (int) column
{
    id		inspectTuple;
    id		funcObj, aCell;
    const char	*name;
    int         i, count = 0;

    if ( sender == tupleBrowser ) {
        inspectTuple = [hDraw inspectTuple];
	count = [inspectTuple fillTupleMatrix:matrix];
    } 
    else if (funcList) {
	count = [funcList count];
	for (i = 0; i < count; i++) {
	    [matrix insertRowAt:i];
	    aCell = [matrix cellAt:i :0];
	    funcObj = [funcList objectAt:i];
	    name = [funcObj functionName];
	    if (name && strcmp(name, "")) {
		[aCell setStringValue:name];
	    } else {
		[aCell setStringValue:"<none>"];
	    }
	    [aCell setLeaf:YES];
	    [aCell setLoaded:YES];
	}
    }

    [matrix setEmptySelectionEnabled:NO];
    return count;
}

@end

@implementation InspectFunc(PrivateMetods)

- showMessagesFrom:(HAddColFunction *)funcObj
{
    
    msgStream = [funcObj openMessages];
    [[msgScrollView docView] readText:msgStream];
    [msgWindow makeKeyAndOrderFront:self];
    return self;
}
- removeFunc:funcObj
{
    
    [funcList removeObject:funcObj];
    [funcBrowser reloadColumn:0];
    return self;
}
    
- updateFuncList
{
    Matrix             *browserMatrix;
    int        i;
    List               *currentList = [[hDraw inspectTuple] tupleList];

    i = [currentList indexOf:hTuple];
    if (i >= 0) {
	browserMatrix = [tupleBrowser matrixInColumn:0];
	[browserMatrix selectCellAt:i :0];
	if (funcList != [hTuple functionList]) {
	    funcList = [hTuple functionList];
	}
    } else {
    	hTuple = nil;
	funcList = nil;
    }
    [funcBrowser reloadColumn:0];
    
    return self;
}
    
- updatePlots:(ntuple) nt
{
    List	*plist;
    Plot	*plot;
    display	disp;
    int		i, index;
    
    index = [curFuncObj colIndex];
    plist = [graphicView plotList];
    i = [plist count];
    while ( i-- ) {
        plot = [plist objectAt:i];
	if ( [plot ntuple] == nt ) {
	    disp = [plot histDisplay];
	    h_setDirty(disp);
	    [graphicView graphicsPerformNOP:plot];
	}
    }   
    [[[graphicView window] flushWindow] makeKeyWindow];
    return self;
}
- updateTupleList
{
    List               *currentList = [[hDraw inspectTuple] tupleList];
    int                 count = [currentList count];

    if (count != numTuples) {
	[tupleBrowser reloadColumn:0];
    }
    numTuples = count;

    return self;
}
@end
