This is InspectTuple.m in view mode; [Download] [Up]
/* InspectTuple by Paul Kunz October 1991
* The supervisor for the tuple inspection panel
*
* Copyright (C) 1991 The Board of Trustees of
* The Leland Stanford Junior University. All Rights Reserved.
*/
#import "Draw.subproj/draw.h"
#import "HGraphicView.h"
#import "InspectTuple.h"
const char InspectTuple_h_rcsid[] = INSPECTTUPLE_H_ID;
const char InspectTuple_m_rcsid[] = "$Id: InspectTuple.m,v 2.35.2.3 1994/02/08 20:29:50 rensing Exp $";
#import "HDrawApp.h"
#import "HTuple.h"
#import "NewInspector.h"
#import "Plot.h"
#define FN_INDEX 0
#define BY_INDEX 1
#define COL_INDEX 2
#define ROW_INDEX 3
#define MB_INDEX 4
#define LOW_RANGE 0
#define HIGH_RANGE 1
#define LOW_X 0
#define LOW_Y 1
#define HIGH_X 2
#define HIGH_Y 3
#define MAX_VALUE 0
#define MIN_VALUE 1
#define SUM_VALUE 2
#define AX_X 0
#define AX_Y 1
#define AX_Z 2
#define AX_W 2
#define AX_XE 3
#define AX_YE 4
@interface InspectTuple(PrivateMethods)
- hTupleForTuple:(ntuple) nt;
/*
* Returns the HTuple object managing the ntuple nt, or
* nil if none found.
*/
- (BOOL) isNewTupleFile:(const char *)filename;
/* return YES if tuple file with filename is not in list of
* currently opened files, otherwise returns NO.
*/
- (BOOL) isReplaceOK:(List *)list with:(HTuple *)tuple;
/*
* Checks to see if tuple can be used as replacement for list of Plots
* in list. Checks all binding axes of displays and plot and
* cut binding if any.
*/
- openTupleFile;
/*
* Opens the tuple file selected by the OpenPanel. This method
* does not run the OpenPanel, rather it is called after it has been run.
*/
- openTupleFromFile:(const char *)filename by:(BOOL)refFlag;
/*
* Opens ntuple file filename and returns a List of
* HTuple objects created or nil if file could not be opened.
* The refFlag is passed to each HTuple object.
*/
- (int) openAltTupleFile:(const char *)filename;
/*
* Runs the OpenPanel to select a file to replace filename and
* opens the selected n-tuple file. The altfilename of the
* opened Tuples is set to filename. This method is used
* when opening a document with tuples by reference, and the
* ntuple file has changed it's path or doesn't exists
*/
- closeTupleFile:(const char *)filename;
/*
* Close an n-tuple file after informing each DrawDocument's View
* that file is about to close.
*/
- (int) runModelForTypes;
/*
* Runs the openPanel to select tuple binary file with suffix .hippo.
* Returns HD_OK on success, HD_CANCEL if user canceled.
*/
- showPanel;
/*
* Orders the NewInspector panel to show the Tuple List and brings
* Panel front
*/
- replaceWithCuts:hTuple;
/*
* Replaces the HTuple of selected Plots, their cuts, and
* all plots dependent on those cuts.
*/
- setButtonsAndTitles;
/*
* Enables appropriate axis buttons and titles
*/
- setDisable:(int) axisIndex;
/*
* Disables axis button and clears Form for specified Axis index.
*/
- setEnable:(int) axisIndex;
/*
* Enables axis button and sets label for specified Axis index.
*/
- showBinding;
/*
* Updates inspector view to show bindings of selected plot
*/
- updateFileForm;
/*
* Updates the information Form and copyButton.
*/
@end
@implementation InspectTuple
- initInspFor:aDraw
{
PopUpList *popUpList;
NXBundle *bundle;
char buffer[MAXPATHLEN+1];
[super initInspFor:aDraw];
bundle = [NXBundle bundleForClass:[self class]];
if ( [bundle getPath:buffer forResource:"InspectTuple" ofType:"nib"] ) {
[NXApp loadNibFile:buffer owner:self
withNames:NO fromZone:[self zone]];
}
[theInspector addView:[contentBox contentView]
withName:"Data Selection"
withSupervisor:self];
[colBrowser setDoubleAction:@selector(colBrowserDoubleClicked:)];
openPanel = [OpenPanel new];
/* the following avoids getting "/private/Net/..." as default */
[openPanel setDirectory:NXHomeDirectory()];
tupleList = [[ List allocFromZone:[self zone]] init];
popUpList = [popUpButton target];
[popUpList setTarget:self];
[popUpList setAction:@selector(formChange:)];
graphtype = HISTOGRAM;
tpAxisIndex[0] = 0;
tpAxisIndex[1] = 0;
tpAxisIndex[2] = -1;
tpAxisIndex[3] = -1;
tpAxisIndex[4] = -1;
return self;
}
/* Action methods */
- axisMatrixClick:sender
{
Matrix *colBrowserCells;
int currentButton;
currentButton = [tpAxisButtons selectedRow];
colBrowserCells = [colBrowser matrixInColumn:0];
[colBrowserCells selectCellAt:tpAxisIndex[currentButton] :0 ];
[colBrowserCells scrollCellToVisible:tpAxisIndex[currentButton] :0];
return self;
}
- colBrowserSingleClicked:sender
{
Matrix *colBrowserCells;
int tpColSelected, currentButton;
static int previousTupleN = -1, previousButton = -1;
colBrowserCells = [colBrowser matrixInColumn:0];
tpColSelected = [colBrowserCells selectedRow ];
currentButton = [tpAxisButtons selectedRow];
if ( popUpRow == 0 ) {
[infoForm setStringValue:
[[colBrowserCells cellAt:tpColSelected :0] stringValue]
at:currentButton];
}
switch( currentButton ) {
case AX_X:
tpAxisIndex[0] = tpColSelected;
break;
case AX_Y:
tpAxisIndex[1] = tpColSelected;
break;
case AX_W: /* or AX_Z */
if (graphtype == THREEDSCATTER) {
/* case AX_Z: */
tpAxisIndex[2] = tpColSelected;
break;
} else {
/* case AX_W: */
if (tpColSelected == previousTupleN &&
currentButton == previousButton ) {
tpColSelected = -1;
if ( popUpRow == 0 ) {
[infoForm setStringValue:"" at:AX_W];
}
}
tpAxisIndex[2] = tpColSelected;
previousTupleN = tpColSelected;
previousButton = currentButton;
break;
}
case AX_XE:
if (graphtype == XYPLOT || graphtype == STRIPCHART) {
if (tpColSelected == previousTupleN &&
currentButton == previousButton) {
tpColSelected = -1;
if ( popUpRow == 0 ) {
[infoForm setStringValue:"" at:AX_XE];
}
}
tpAxisIndex[3] = tpColSelected;
}
previousTupleN = tpColSelected;
previousButton = currentButton;
break;
case AX_YE:
if ( tpColSelected == previousTupleN &&
currentButton == previousButton ) {
tpColSelected = -1;
if ( popUpRow == 0 ) {
[infoForm setStringValue:"" at:AX_YE];
}
}
tpAxisIndex[4] = tpColSelected;
previousTupleN = tpColSelected;
previousButton = currentButton;
break;
}
return self;
}
- colBrowserDoubleClicked:sender
{
Matrix *colBrowserCells;
int tpColSelected, currentButton;
static int previousTupleN = -1, previousButton = -1;
colBrowserCells = [colBrowser matrixInColumn:0];
tpColSelected = [colBrowserCells selectedRow ];
currentButton = [tpAxisButtons selectedRow];
if ( popUpRow == 0 ) {
[infoForm setStringValue:
[[colBrowserCells cellAt:tpColSelected :0] stringValue]
at:currentButton];
}
switch( currentButton ) {
case AX_X:
[graphicView graphicsPerform:@selector(bindAxisX:)
with :(id)&tpColSelected andDraw:YES];
tpAxisIndex[0] = tpColSelected;
break;
case AX_Y:
[graphicView graphicsPerform:@selector(bindAxisY:)
with :(id)&tpColSelected andDraw:YES];
tpAxisIndex[1] = tpColSelected;
break;
case AX_W: /* or AX_Z */
if (graphtype == THREEDSCATTER) {
/* case AX_Z: */
[graphicView graphicsPerform:@selector(bindAxisZ:)
with :(id)&tpColSelected andDraw:YES];
tpAxisIndex[2] = tpColSelected;
break;
} else {
/* case AX_W: */
if (tpColSelected == previousTupleN &&
currentButton == previousButton ) {
tpColSelected = -1;
if ( popUpRow == 0 ) {
[infoForm setStringValue:"" at:AX_W];
}
}
[graphicView graphicsPerform:@selector(bindAxisW:)
with :(id)&tpColSelected andDraw:YES];
tpAxisIndex[2] = tpColSelected;
previousTupleN = tpColSelected;
previousButton = currentButton;
break;
}
case AX_XE:
if (graphtype == XYPLOT || graphtype == STRIPCHART) {
if (tpColSelected == previousTupleN &&
currentButton == previousButton) {
tpColSelected = -1;
if ( popUpRow == 0 ) {
[infoForm setStringValue:"" at:AX_XE];
}
}
[graphicView graphicsPerform:@selector(bindAxisXE:)
with :(id)&tpColSelected andDraw:YES];
tpAxisIndex[3] = tpColSelected;
}
previousTupleN = tpColSelected;
previousButton = currentButton;
break;
case AX_YE:
if ( tpColSelected == previousTupleN &&
currentButton == previousButton ) {
tpColSelected = -1;
if ( popUpRow == 0 ) {
[infoForm setStringValue:"" at:AX_YE];
}
}
[graphicView graphicsPerform:@selector(bindAxisYE:)
with :(id)&tpColSelected andDraw:YES];
tpAxisIndex[4] = tpColSelected;
previousTupleN = tpColSelected;
previousButton = currentButton;
break;
}
[[[graphicView window] flushWindow] makeKeyWindow];
return self;
}
- graphOption:sender
{
int color;
drawtype_t dt;
if ( [selectedPlot hasFunction] ) {
NXRunAlertPanel( "Alert", "Can not change plot with function attached",
NULL, NULL, NULL );
return self;
}
graphtype = [[graphTypMatrix selectedCell] tag];
color = 0;
if ((abs(graphtype) == COLORPLOT) && graphtype > 0)
color = 1;
graphtype = abs(graphtype);
if (graphtype == XYPLOT || graphtype == STRIPCHART) {
[selectedPlot getDrawType: &dt];
if (!(dt & (LINE+POINT+ERRBAR))) {
dt += POINT;
[graphicView graphicsPerform:@selector(setDrawType:)
with :(id)&dt andDraw:NO];
}
}
if (graphtype == THREEDSCATTER)
{
if (tpAxisIndex[2] == -1)
tpAxisIndex[2] = 0;
}
[graphicView graphicsPerform:@selector(setDispType:)
with :(id)&graphtype andDraw:NO];
[graphicView graphicsPerform:@selector(setColorType:)
with :(id)&color andDraw:YES];
[[[graphicView window] flushWindow] makeKeyWindow];
lastPlot = nil;
if(!selectedPlot && !firstPlot)
[self setButtonsAndTitles];
return self;
}
- addPlot:sender
{
Matrix *colCells;
Cell *aCell;
Plot *plot = nil;
graphtype_t plotType;
int i, count;
int color, curAxis;
if ( !selectedTuple ) {
return self;
}
colCells = [colBrowser matrixInColumn:0];
count = [colCells cellCount];
if ( !count ) return self;
[graphicView deselectAll:self];
plotType = [[graphTypMatrix selectedCell] tag];
color = 0;
if ( ( abs(plotType) == COLORPLOT) && plotType > 0 ) {
color = 1;
}
plotType = abs(plotType);
curAxis = [tpAxisButtons selectedRow];
for ( i = 0; i < count; i++ ) {
aCell = [colCells cellAt:i :0];
if ( [aCell isHighlighted] ) {
tpAxisIndex[curAxis] = i;
plot = [self addPlotOfType:plotType];
if ( color ) {
[plot setColorType:&color];
}
[graphicView addPlot:plot andSelect:NO];
}
}
[plot select];
[graphicView getSelection];
[graphicView recacheSelection];
[[[graphicView window] flushWindow] makeKeyWindow];
return self;
}
- openTuple:sender
{
[openPanel setAccessoryView:nil];
if ( [self runModelForTypes] != HD_CANCEL ) {
[self openTupleFile];
}
return self;
}
- openTupleAsText:sender
{
[openPanel setAccessoryView:nil];
if ( ![openPanel runModal] ) {
return self;
}
[self openTupleFile];
return self;
}
- tupleBrowserClick:sender
{
List *slist;
id browserMatrix;
id doc;
id hTuple;
int irc, index;
BOOL ok;
browserMatrix = [tupleBrowser matrixInColumn:0];
index = [browserMatrix selectedRow];
if ( index < 0 ) {
[self setTuple: NULL];
return self;
}
hTuple = [tupleList objectAt:index];
selectedTuple = [hTuple ntuple];
[self updateColBrowser];
[self updateFileForm];
doc = [drawInstance currentDocument];
if ( !doc ) return self;
graphicView = [doc view];
if ( [graphicView hasCutsSelected] ) {
irc = NXRunAlertPanel( "Alert", "Selected Plot(s) contain cuts,"
" replacing ntuple will effect multiple plots.",
"OK", "Cancel", NULL);
if ( irc == NX_ALERTDEFAULT ) {
[self replaceWithCuts:hTuple];
}
} else {
slist = [graphicView selectedGraphics];
ok = [self isReplaceOK:slist with:hTuple];
if ( !ok ) return self;
[graphicView graphicsPerform:@selector(replaceTupleWith:)
with: hTuple andDraw:YES ];
[[graphicView window] flushWindow];
}
return self;
}
- closeTuple:sender
{
id windowList;
id window, document, view;
id usedTupleList;
id hTuple;
id browserMatrix;
int wcount;
int i, irc, index;
browserMatrix = [tupleBrowser matrixInColumn:0];
index = [browserMatrix selectedRow];
if ( index < 0 ) return self;
hTuple = [tupleList objectAt:index];
windowList = [NXApp windowList];
wcount = [windowList count];
while ( wcount-- ) {
window = [windowList objectAt:wcount];
document = [window delegate];
if ( [document isKindOf:[DrawDocument class]] ) {
view = [document view];
usedTupleList = [view tupleList];
i = [usedTupleList indexOf:hTuple];
if ( i != NX_NOT_IN_LIST ) {
irc = NXRunAlertPanel( "Close", "Tuple in use",
"OK", NULL, NULL);
return self;
}
}
}
[self closeTupleFile:[hTuple filename]];
// since this tuple is not in use, there must be no plot selected.
// make sure selectedPlot == nil in case it has not been updated.
selectedPlot = nil;
firstPlot = nil;
[self tupleBrowserClick: self];
/*
* force an update.
* make sure to get the current view. it may have been freed.
*/
[self load:[[drawInstance currentDocument] view]];
return self;
}
- changeImportMode:sender
{
id hTuple;
hTuple = [self currentHTuple];
if ( [hTuple isRef ] ) {
[hTuple setIsRef:NO];
} else {
[hTuple setIsRef:YES];
}
[self updateFileForm];
return self;
}
- formChange:sender
{
popUpRow = [sender selectedRow];
switch (popUpRow ) {
case 0 :
[self setButtonsAndTitles];
break;
case 1 :
[self updateFileForm];
break;
default :
; /* should never happen */
}
return self;
}
/* Methods invoked by other objects */
- hTupleForFile:(const char *)filename index:(int)iValue
{
const char *altfile;
id hTuple;
int i;
i = [tupleList count];
while ( i-- ) {
hTuple = [tupleList objectAt:i];
if ( [hTuple index] == iValue ) {
if ( strcmp( [hTuple filename], filename ) == 0 ) {
return hTuple;
}
altfile = [hTuple altfilename];
if ( altfile && (strcmp(altfile, filename) == 0 ) ) {
return hTuple;
}
}
}
return nil;
}
- openTuple:pasteBoard userData:(const char *)args error:(char **)errorMsg
{
id hTuple;
FILE *infile;
ntuple *ntlist;
const char *const *ptypes;
const char *data;
char filename[25];
char *outbuffer;
int i, irc, length;
BOOL binFlag;
ptypes = [pasteBoard types];
for ( i = 0; ptypes[i]; i++ ) {
if ( !strcmp(ptypes[i], NXAsciiPboardType) ) {
[pasteBoard readType:ptypes[i] data:&data length:&length];
NX_ZONEMALLOC([self zone], outbuffer, char, (length+2) );
strncpy( outbuffer, data, length);
outbuffer[length] = '\n';
outbuffer[length+1] = '\0';
strcpy(filename,"/tmp/file000000Selection" );
NXGetTempFilename(filename,9);
infile=fopen(filename,"w");
fprintf(infile,outbuffer);
fclose(infile);
NXZoneFree([self zone], outbuffer);
if ( (infile = fopen(filename, "r") ) == NULL ) {
*errorMsg = "Couldn't open /tmp file";
return nil;
}
binFlag = NO;
NX_ZONEMALLOC( [self zone], ntlist, ntuple, 2 );
if ( !(ntlist[0] = h_fileParse( infile, NULL, 0) ) ) {
NXZoneFree([self zone], ntlist);
*errorMsg = "Couldn't interpret data as n-tuple";
return nil;
}
ntlist[1] = NULL;
irc = fclose( infile );
unlink(filename);
hTuple = [[HTuple allocFromZone:[self zone]]
initTuple:ntlist[0] file:"From Pasteboard"
by:NO mode:NO index:0];
[hTuple setFakeFilename:YES];
[tupleList addObject:hTuple];
[tupleBrowser loadColumnZero];
[self setTuple:ntlist[0] ];
[self showPanel];
}
}
return self;
}
- addTuple:(ntuple) nt
{
id hTuple;
hTuple = [[HTuple allocFromZone:[self zone]]
initTuple:nt file:"none"
by:NO mode:YES index:0];
[hTuple setFakeFilename:YES];
[tupleList addObject:hTuple];
[tupleBrowser loadColumnZero];
[ self setTuple:nt];
return hTuple;
}
- addPlotOfType:(graphtype_t) plotType
{
HTuple *hTuple;
Plot *plot;
drawtype_t drawtype;
int saveAxisIndex[5];
int i, max;
if ( !selectedTuple ) {
ntuple nt = [self currentTuple];
if ( !nt ) return nil;
[self setTuple:nt];
}
if ( (plotType !=HISTOGRAM) && (h_getNtDim(selectedTuple) < 2) ) {
return nil;
}
if ( !graphicView ) {
return nil;
}
[self load:graphicView]; /* force an update */
hTuple = [self currentHTuple];
plot = [[Plot allocFromZone:[graphicView zone]]
initPlotWithTuple:hTuple Type:plotType];
max = h_getNtDim(selectedTuple) - 1;
for ( i = 0; i < 5; i++ ) {
saveAxisIndex[i] = MIN( tpAxisIndex[i], max );
}
/* do bindings as neccessary */
[plot bindAxisX:&saveAxisIndex[0]];
if (plotType != HISTOGRAM) {
saveAxisIndex[1] = MAX(0, saveAxisIndex[1]);
[plot bindAxisY:&saveAxisIndex[1]];
}
if (plotType == XYPLOT) {
if ( saveAxisIndex[3] >= 0 || saveAxisIndex[4] >= 0 ) {
drawtype = POINT + ERRBAR;
} else {
drawtype = POINT;
}
[plot setDrawType:&drawtype];
[plot bindAxisXE:&saveAxisIndex[3]];
[plot bindAxisYE:&saveAxisIndex[4]];
} else {
if (plotType == THREEDSCATTER) {
saveAxisIndex[2] = MAX(0, saveAxisIndex[2]);
[plot bindAxisZ:&saveAxisIndex[2]];
} else {
[plot bindAxisW:&saveAxisIndex[2]];
}
}
/* bindings done */
[self setInspectorFor:plot];
return plot;
}
- (ntuple) currentTuple
{
id browserMatrix;
id hTuple;
ntuple nt;
int index;
browserMatrix = [tupleBrowser matrixInColumn:0];
index = [browserMatrix selectedRow];
if ( index >= 0 ) {
hTuple = [tupleList objectAt:index];
nt = [hTuple ntuple];
} else {
nt = NULL;
}
return nt;
}
- currentHTuple
{
id browserMatrix;
id hTuple;
int index;
browserMatrix = [tupleBrowser matrixInColumn:0];
index = [browserMatrix selectedRow];
if ( index >= 0 ) {
hTuple = [tupleList objectAt:index];
} else {
hTuple = nil;
}
return hTuple;
}
- bindDisplays
{
id windowList;
id window, document, view;
int wcount;
windowList = [NXApp windowList];
wcount = [windowList count];
while ( wcount-- ) {
window = [windowList objectAt:wcount];
document = [window delegate];
if ( [document isKindOf:[DrawDocument class]] ) {
view = [document view];
[view bindDisplays];
[view reDrawPlot];
}
}
return self;
}
- (int) addTuplesIfAbsent:newList
{
id newTuple, hTuple;
int newCount, count;
int i, j, irc;
BOOL isNew;
graphicView = nil; /* to keep open methods from messaging the view */
newCount = [newList count];
for ( i = 0; i < newCount; i++ ) {
newTuple = [newList objectAt:i];
isNew = YES;
count = [tupleList count];
for ( j = 0; j < count; j++ ) {
hTuple = [tupleList objectAt:j];
if ( [hTuple isSameTupleAs:newTuple] ) {
isNew = NO;
[newList replaceObjectAt:i with:hTuple];
[newTuple free];
break;
}
}
if ( isNew ) {
if ( [newTuple isRef ] ) {
irc = [self openTupleFile:[newTuple filename] by:YES];
if ( irc == HD_NOTEXIST ) {
irc = [ self openAltTupleFile:[newTuple filename]];
if (irc != HD_OK) return irc;
}
j = [tupleList count];
while ( j-- ) {
hTuple = [tupleList objectAt:j];
if ( [hTuple isSameTupleAs:newTuple] ) {
[hTuple takeFunctionList:[newTuple functionList]];
[newList replaceObjectAt:i with:hTuple];
[newTuple free];
break;
}
}
} else {
[tupleList addObject:newTuple];
[tupleBrowser loadColumnZero];
[ self setTuple:[newTuple ntuple]];
}
}
}
[self showPanel];
return HD_OK;
}
- (int) openTupleFile:(const char *)filename by:(BOOL) refFlag
{
id newTupleList;
struct stat statbuf;
int irc, rvalue;
if ( stat(filename, &statbuf) ) {
return HD_NOTEXIST;
}
rvalue = HD_OK;
if( ![self isNewTupleFile:filename] ) {
irc = NXRunAlertPanel( "Open", "Tuple file already open",
"Replace", "Cancel", NULL);
if ( irc != NX_ALERTDEFAULT ) {
return HD_CANCEL;
}
[self closeTupleFile:filename];
rvalue = HD_REPLACE;
}
if ( !(newTupleList = [self openTupleFromFile:filename by:refFlag]) ) {
irc = NXRunAlertPanel("Open", "Couldn't open file",
"OK", NULL, NULL);
return HD_CANCEL;
}
[newTupleList free];
return rvalue;
}
- saveAsExportFile:(const char *)filename
{
HTuple *htuple;
ntuple nt;
display disp;
display *dispList;
const char *ntFilename;
int i, irc;
BOOL refFlag;
dispList = [graphicView displayList];
if ( dispList == NULL ) {
return self;
}
/* update the ntuple filename for referenced tuples before saving */
for ( i = 0; (disp = dispList[i]) != NULL; i++) {
h_setNtByRef( disp, NO, filename );
}
if ( h_write( filename, dispList, NULL ) ) {
irc = NXRunAlertPanel("Alert", "Couldn't save export file",
"OK", NULL, NULL);
}
for ( i = 0; (disp = dispList[i]) != NULL; i++) {
nt = h_getNtuple( disp );
htuple = [self hTupleForTuple:nt];
refFlag = [htuple isRef];
ntFilename = [htuple filename];
h_setNtByRef( disp, refFlag, ntFilename );
}
return self;
}
- tupleList
{
return tupleList;
}
- tupleListForFile:(const char *) filename
{
id hTuple;
int i, count;
if ( tmpTupleList ) {
[tmpTupleList empty];
} else {
tmpTupleList = [[List allocFromZone:[self zone]] initCount: 0];
}
count = [tupleList count];
for ( i = 0; i < count; i++ ) {
hTuple = [tupleList objectAt:i];
if ( strcmp( [hTuple filename], filename ) == 0 ) {
[tmpTupleList addObject:hTuple];
}
}
return tmpTupleList;
}
- replaceNtuple:(ntuple)oldnt with:(ntuple)newnt andFree:(BOOL)flag
{
id oldTuple, newTuple;
id document;
List *windowList;
id view;
Window *window;
int i, j;
i = [tupleList count];
while (i--) {
oldTuple = [tupleList objectAt:i];
if ( oldnt == [oldTuple ntuple] ) {
newTuple = [self addTuple:newnt];
[newTuple takeFunctionList:[oldTuple functionList]];
windowList = [NXApp windowList];
j = [windowList count];
while (j-- ) {
window = [windowList objectAt:j];
document = [window delegate];
if ( [document isKindOf:[DrawDocument class]] ) {
view = [document view];
[view replace:oldTuple with:newTuple];
}
}
if ( flag ) {
[tupleList removeObject:oldTuple];
[oldTuple free];
}
}
break;
}
[tupleBrowser reloadColumn:0];
[self updateFileForm];
return self;
}
- setInspectorFor:(Plot *)plot
{
display disp;
graphtype_t type;
disp = [plot histDisplay];
type = h_getDispType(disp);
if ([plot isCutPlot])
[plot setInspector : [hDraw inspectCut]];
else
[plot setInspector:[hDraw inspectAxes]];
return self;
}
- updateView
{
if ( lastPlot == firstPlot &&
selectedTuple == [firstPlot ntuple] ) {
return self;
}
if ( firstPlot ) {
[self setTuple:[firstPlot ntuple] ];
[self showBinding];
lastPlot = firstPlot;
} else {
lastPlot = nil;
}
return self;
}
- updateEmptySelection
{
unsigned int i;
lastPlot = nil;
if ( popUpRow != 0 ) return self;
for ( i = 0; i < 5; i++ ) {
[[tpAxisButtons cellAt:i :0] setEnabled:YES];
}
if (comingForward) {
[self setButtonsAndTitles];
}
if (!selectedTuple) [self updateColBrowser];
return self;
}
- setTuple:(ntuple) atuple
{
id browserMatrix;
id hTuple;
display disp;
unsigned int i, count;
if (selectedTuple == atuple)
return self;
selectedTuple = atuple;
[self updateColBrowser];
if (selectedTuple == NULL) return self;
browserMatrix = [tupleBrowser matrixInColumn:0];
count = [tupleList count];
for ( i = 0; i < count; i++ ) {
hTuple = [tupleList objectAt:i];
if ( selectedTuple == [hTuple ntuple] ) {
[ browserMatrix selectCellAt:i :0];
[ self updateFileForm];
break;
}
}
if ( firstPlot && graphicView ) {
disp = [firstPlot histDisplay];
graphtype = h_getDispType( disp );
if ( graphtype == XYPLOT ) {
[tpAxisButtons selectCellAt:AX_Y :0];
}
}
return self;
}
- updateColBrowser
{
[colBrowser loadColumnZero];
[self showBinding];
return self;
}
- startUnarchivingFrom:(const char *)directory
{
return self;
}
/* Delegate Methods for NXBrowsers */
- (BOOL)browser:sender columnIsValid:(int)column;
{
return YES;
}
- (BOOL)browser:sender selectCell:(const char *)title inColumn:(int)column
{
return YES;
}
- (int) browser: sender fillMatrix: matrix inColumn: (int) column
{
int nrows = 0;
if ( sender == tupleBrowser ) {
nrows = [self fillTupleMatrix: matrix];
}
else if ( sender == colBrowser ) {
nrows = [self fillColumnMatrix: matrix];
}
return nrows;
}
- (int) fillTupleMatrix:matrix
{
NXBrowserCell *aCell;
HTuple *hTuple;
const char *title;
int i, nrows = 0;
nrows = [tupleList count];
for (i = 0; i < nrows; i++) {
[matrix insertRowAt:i];
aCell = [matrix cellAt:i :0];
hTuple = [tupleList objectAt:i];
title = [hTuple title];
if ( title && strcmp(title, "") ) {
[aCell setStringValue:title];
} else {
[aCell setStringValue:"<none>"];
}
[aCell setLeaf:YES];
[aCell setLoaded:YES];
}
[matrix setEmptySelectionEnabled:NO];
return nrows;
}
- (int) fillColumnMatrix:matrix
{
NXBrowserCell *aCell;
int i, nrows = 0;
if ( selectedTuple ) {
nrows = h_getNtDim(selectedTuple);
} else {
nrows = 0;
}
for (i = 0; i < nrows; i++) {
[matrix insertRowAt:i];
aCell = [matrix cellAt:i :0];
[aCell setStringValue:h_getNtLabel(selectedTuple, i)];
[aCell setLeaf:YES];
[aCell setLoaded:YES];
}
return nrows;
}
- setMsgMatrix:anObject
{
float gray;
int i, rows, cols;
msgMatrix = anObject;
gray = [msgMatrix backgroundGray ];
[msgMatrix getNumRows:&rows numCols:&cols];
for ( i = 0; i < rows; i++ ) {
[[msgMatrix cellAt:i :0] setTextGray:gray];
}
return self;
}
/* Obsolete methods, maintained for backward compatibility */
- newTuple:(ntuple) nt
{
[self addTuple:nt];
return self;
}
@end
@implementation InspectTuple(PrivateMethods)
- hTupleForTuple:(ntuple) nt
{
HTuple *hTuple;
int i;
i = [tupleList count];
while ( i-- ) {
hTuple = [tupleList objectAt:i];
if ( nt == [hTuple ntuple] ) {
return hTuple;
}
}
return nil;
}
- (BOOL) isNewTupleFile:(const char *)filename
{
HTuple *hTuple;
int i;
i = [tupleList count];
while ( i-- ) {
hTuple = [tupleList objectAt:i];
if ( strcmp( [hTuple filename], filename ) == 0 ) {
return NO;
}
}
return YES;
}
- (BOOL) isReplaceOK:(List *)list with:(HTuple *)tuple
{
Plot *plot;
ntuple nt;
display disp;
func_id cut = NULL;
int i, j, ndim;
BOOL ok = YES;
nt = [tuple ntuple];
ndim = h_getNtDim(nt);
i = [list count];
while( i-- ) {
plot = [list objectAt:i];
disp = [plot histDisplay];
for ( j = 0; j < 5; j++ ) {
if ( h_getBinding( disp, j) >= ndim ) {
ok = NO;
break;
}
}
if ( !ok ) break;
if ( [plot hasCut] ) {
cut = NULL;
while ( (cut = h_nextCut( disp, cut ) ) != NULL ) {
if ( (int)cut->paramBlk[0] >= ndim ) {
ok = NO;
break;
}
}
}
if ( !ok ) break;
}
if ( !ok ) {
NXRunAlertPanel( "Alert", "Replacement n-tuple does not have"
" enough columns to be used on effected plots."
" No replacement made",
"OK", NULL, NULL);
selectedTuple = NULL;
[self updateView];
}
return ok;
}
- openTupleFile
{
const char *filename;
int irc;
BOOL refFlag;
filename = [openPanel filename];
refFlag = YES;
irc = [self openTupleFile:filename by:refFlag];
if ( irc == HD_REPLACE ) {
[self bindDisplays];
}
[self showPanel];
return self;
}
- openTupleFromFile:(const char *)filename by:(BOOL)refFlag
{
List *newTupleList;
HTuple *hTuple;
FILE *infile;
ntuple *ntlist = NULL;
display *dlist = NULL;
int i;
BOOL binFlag;
if (h_isHippoFile(filename)) {
binFlag = YES;
if (h_read(filename, &dlist, &ntlist) != 0) {
return nil;
}
} else {
if ((infile = fopen(filename, "r")) == NULL) {
NXRunAlertPanel("Reason Alert", "Couldn't open file",
"OK", NULL, NULL);
return nil;
}
binFlag = NO;
NX_ZONEMALLOC([self zone], ntlist, ntuple, 2);
if (!(ntlist[0] = h_fileParse(infile, NULL, 0))) {
NXZoneFree([self zone], ntlist);
return nil;
}
ntlist[1] = NULL;
fclose(infile);
}
newTupleList = [[List allocFromZone:[self zone]] initCount:0];
for (i = 0; ntlist[i] != NULL; i++) {
hTuple = [[HTuple allocFromZone:[self zone]]
initTuple:ntlist[i] file:filename
by:refFlag mode:binFlag index:i];
[tupleList addObject:hTuple];
[newTupleList addObject:hTuple];
}
/* update graphicView because old one could have been freed */
graphicView = [[drawInstance currentDocument] view];
[graphicView deselectAll:self];
firstPlot = nil;
lastPlot = nil;
[tupleBrowser loadColumnZero];
[self setTuple:ntlist[0]];
return newTupleList;
}
- (int) openAltTupleFile:(const char *)filename
{
List *newTupleList;
HTuple *hTuple;
const char *newfilename;
char *suffix;
float gray;
int i, count;
int rows, cols;
int irc;
BOOL refFlag;
[msgMatrix getNumRows:&rows numCols:&cols];
for (i = 0; i < rows; i++) {
[[msgMatrix cellAt:i :0] setTextGray:0.];
}
[[msgMatrix cellAt:1 :0] setStringValue:filename];
[openPanel setAccessoryView:accessoryView];
suffix = rindex(filename, '.');
if (suffix && !strcmp(suffix, ".hippo") ) {
irc = [self runModelForTypes];
} else {
if ( ![openPanel runModal] ) {
irc = HD_CANCEL;
} else {
irc = HD_OK;
}
}
gray = [msgMatrix backgroundGray];
for (i = 0; i < rows; i++) {
[[msgMatrix cellAt:i :0] setTextGray:gray];
}
if ( irc == HD_CANCEL ) {
return irc;
}
newfilename = [openPanel filename];
if ( ![self isNewTupleFile:newfilename] ) {
newTupleList = [self tupleListForFile:newfilename];
count = [newTupleList count];
for ( i = 0; i < count; i++ ) {
hTuple = [newTupleList objectAt:i];
[hTuple setAltFilename:filename];
}
return HD_OK;
}
refFlag = YES;
if ( !(newTupleList = [self openTupleFromFile:newfilename by:refFlag]) ) {
irc = NXRunAlertPanel("Open", "Couldn't open file",
"OK", NULL, NULL);
return HD_CANCEL;
}
count = [newTupleList count];
for ( i = 0; i < count; i++ ) {
hTuple = [newTupleList objectAt:i];
[hTuple setAltFilename:filename];
}
return HD_OK;
}
- closeTupleFile:(const char *)filename
{
List *windowList;
Window *window;
DrawDocument *document;
HGraphicView *view;
HTuple *hTuple;
int count;
windowList = [NXApp windowList];
count = [windowList count];
while ( count-- ) {
window = [windowList objectAt:count];
document = [window delegate];
if ( [document isKindOf:[DrawDocument class]] ) {
view = [document view];
[view closeTupleFile:filename];
}
}
tmpTupleList = [self tupleListForFile:filename];
count = [tmpTupleList count];
while ( count-- ) {
hTuple = [tmpTupleList objectAt:count];
[tupleList removeObject:hTuple];
}
[tupleBrowser reloadColumn:0];
[self updateFileForm];
[tmpTupleList freeObjects];
return self;
}
- (int) runModelForTypes
{
static const char *const filetype[2] = {"hippo", NULL};
if ( ![openPanel runModalForTypes:filetype] ) {
return HD_CANCEL;
}
return HD_OK;
}
- replaceWithCuts:hTuple
{
List *plotList, *slist;
List *list, *cutList;
List *depList;
Plot *cut, *plot;
int i, j;
BOOL ok;
/* make plotList list of Plots amongst selected graphics */
slist = [graphicView selectedGraphics];
plotList = [[List allocFromZone:[self zone]] initCount:0];
[slist makeObjectsPerform:@selector(addPlotToList:) with:plotList];
[graphicView deselectAll:self];
slist = [graphicView selectedGraphics];
/* add to plotList and Plots dependent on cuts amongst selected graphics */
depList = [[plotList copyFromZone:[self zone]] initCount:0];
i = [depList count];
while (i--) {
cut = [depList objectAt:i];
if ( [cut isCutPlot] ) {
list = [cut dependList];
j = [list count];
while (j--) {
plot = [list objectAt:i];
[plotList addObjectIfAbsent:plot];
}
}
}
[depList free];
/* find the complete list of cuts and updated slist from plotList */
cutList = [[List allocFromZone:[self zone]] initCount:0];
i = [plotList count];
while (i--) {
plot = [plotList objectAt:i];
[slist addObjectIfAbsent:plot];
list = [plot cutList];
j = [list count];
while (j--) {
cut = [list objectAt:j];
[cutList addObjectIfAbsent:cut];
}
}
[plotList free];
/* update slist with cutList and each cut's depend list */
i = [cutList count];
while (i--) {
cut = [cutList objectAt:i];
[slist addObjectIfAbsent:cut];
list = [cut dependList];
j = [list count];
while ( j-- ) {
plot = [list objectAt:j];
[slist addObjectIfAbsent:plot];
}
}
[cutList free];
ok = [self isReplaceOK:slist with:hTuple];
if ( !ok ) {
return self;
}
[graphicView recacheSelection];
[graphicView graphicsPerform:@selector(replaceTupleWith:)
with: hTuple andDraw:YES ];
[[graphicView window] flushWindow];
return self;
}
- showPanel
{
[theInspector showPanelWithName:"Data Selection"];
[theInspector orderFrontPanel:self];
[[graphicView window] orderFront:self];
return self;
}
- setDisable:(int) axisIndex
{
if ( popUpRow != 0 ) return self;
[[tpAxisButtons cellAt:axisIndex :0] setTitle:""];
[[tpAxisButtons cellAt:axisIndex :0] setEnabled:NO];
[infoForm setStringValue:"" at:axisIndex];
[infoForm drawCellAt:axisIndex :0];
return self;
}
- setEnable:(int) axisIndex
{
char *titles[5] = {"x-axis", "y-axis", "weight", "x-error", "y-error"};
if ( popUpRow != 0 ) return self;
[[tpAxisButtons cellAt:axisIndex :0] setTitle:titles[axisIndex]];
if ((graphtype == THREEDSCATTER) && (axisIndex == AX_Z))
[[tpAxisButtons cellAt:axisIndex :0] setTitle:"z-axis"];
[[tpAxisButtons cellAt:axisIndex :0] setEnabled:YES];
/* add tuple column name if anything selected, else blank */
if (tpAxisIndex[axisIndex] >= 0)
[infoForm setStringValue:h_getNtLabel(selectedTuple,
tpAxisIndex[axisIndex]) at:axisIndex];
else
[infoForm setStringValue:"" at:axisIndex];
[infoForm drawCellAt:axisIndex :0];
return self;
}
- setButtonsAndTitles
{
if (!selectedTuple) {
[self setDisable:AX_X]; /* disable everything if no tuple */
[self setDisable:AX_Y];
[self setDisable:AX_W];
[self setDisable:AX_XE];
[self setDisable:AX_YE];
return self;
}
switch (graphtype) {
case HISTOGRAM:
[self setEnable:AX_X];
[self setDisable:AX_Y];
[self setEnable:AX_W];
[self setDisable:AX_XE];
[self setDisable:AX_YE];
break;
case XYPLOT:
case STRIPCHART:
[self setEnable:AX_X];
[self setEnable:AX_Y];
[self setDisable:AX_W];
[self setEnable:AX_XE];
[self setEnable:AX_YE];
break;
case SCATTERPLOT:
[self setEnable:AX_X];
[self setEnable:AX_Y];
[self setDisable:AX_W];
[self setDisable:AX_XE];
[self setDisable:AX_YE];
break;
case COLORPLOT:
case LEGOPLOT:
[self setEnable:AX_X];
[self setEnable:AX_Y];
[self setEnable:AX_W];
[self setDisable:AX_XE];
[self setDisable:AX_YE];
break;
case THREEDSCATTER:
[self setEnable:AX_X];
[self setEnable:AX_Y];
[self setEnable:AX_Z];
[self setDisable:AX_XE];
[self setDisable:AX_YE];
break;
}
return self;
}
- showBinding
/*
* called when we click on a different plot -
* load up the options panel to correspond to the selected plot
*/
{
int pos;
int neg;
int row;
display adisplay;
drawtype_t drawtype;
if ( !firstPlot ) return self;
adisplay = [firstPlot histDisplay];
if ( !adisplay ) return self;
graphtype = h_getDispType(adisplay);
pos = graphtype;
neg = -pos;
if ( graphtype != COLORPLOT ) {
[graphTypMatrix selectCellWithTag:pos];
} else {
[selectedPlot getDrawType:(drawtype_t *) &drawtype];
if ( drawtype & COLOR ) {
[graphTypMatrix selectCellWithTag:pos];
} else {
[graphTypMatrix selectCellWithTag:neg];
}
}
if ( [selectedPlot isCutPlot] ) {
[graphTypMatrix setEnabled:NO];
} else {
[graphTypMatrix setEnabled:YES];
}
[graphTypMatrix display];
/*
* get the current bindings
*/
tpAxisIndex[0] = h_getBinding(adisplay, XAXIS);
tpAxisIndex[1] = h_getBinding(adisplay, YAXIS);
tpAxisIndex[2] = h_getBinding(adisplay, WEIGHT);
if (graphtype == THREEDSCATTER) {
tpAxisIndex[2] = h_getBinding(adisplay, ZAXIS);
} else {
tpAxisIndex[2] = h_getBinding(adisplay, WEIGHT);
};
tpAxisIndex[3] = h_getBinding(adisplay, XERROR);
tpAxisIndex[4] = h_getBinding(adisplay, YERROR);
/*
* enable buttons and show titles
*/
[self setButtonsAndTitles];
/*
* click on the X Axis button as a starting default
*/
row = [ tpAxisButtons selectedRow ];
if ( row < 0 ) {
[tpAxisButtons selectCellAt:AX_X :0];
}
if ( ![[tpAxisButtons cellAt:row :0] isEnabled] ) {
[tpAxisButtons selectCellAt:AX_X :0];
}
[self axisMatrixClick:self];
return self;
}
- updateFileForm
{
Matrix *browserMatrix;
HTuple *hTuple;
id cell;
ntuple nt;
char filename[FILENAME_MAX];
float mb;
int i, index, rows, cols;
char *titles[5] = {"file", "mode", "cols", "rows", "size"};
if ( popUpRow != 1 ) return self;
for ( i = 0; i < 5; i++ ) {
cell = [tpAxisButtons cellAt:i :0];
[cell setTitle:titles[i]];
[cell setEnabled:YES];
}
browserMatrix = [tupleBrowser matrixInColumn:0];
index = [browserMatrix selectedRow];
if ( index < 0 ) {
for ( i = 0; i < 5; i ++ ) {
[infoForm setStringValue:"" at:i];
[infoForm display];
}
[copyButton setEnabled:NO];
return self;
}
hTuple = [tupleList objectAt:index];
nt = [hTuple ntuple];
rows = h_getNtNdata(nt);
cols = h_getNtDim(nt);
mb = (4*rows*cols)/1000000.;
strcpy( filename, NXHomeDirectory() );
index = strspn( [hTuple filename], filename );
if ( index != (strlen(filename) + 1) ) {
strcpy( filename, [hTuple filename]); /* not in home directory */
} else {
strcpy( filename, "~"); /* file in home directory */
strcat( filename, [hTuple filename]+(index-1) );
}
if ( [hTuple isFakeFilename] ) {
[copyButton setEnabled:NO];
} else {
[copyButton setEnabled:YES];
}
[ infoForm setStringValue:filename at:FN_INDEX];
if ( [hTuple isRef ] ) {
[infoForm setStringValue:"Imported by reference" at:BY_INDEX];
} else {
[infoForm setStringValue:"Imported by copy" at:BY_INDEX];
}
[ infoForm setIntValue:cols at:COL_INDEX];
[ infoForm setIntValue:rows at:ROW_INDEX];
[ infoForm setFloatValue:mb at:MB_INDEX];
[ infoForm display];
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.