This is ColumnSelectionHandler.m in view mode; [Download] [Up]
/* Generated by Interface Builder */ #import "ColumnSelectionHandler.h" #import "Plot.h" #import "defs.h" #import <appkit/Font.h> #import <appkit/Panel.h> #import <appkit/Window.h> #import <appkit/Matrix.h> #import <appkit/View.h> #import <appkit/ButtonCell.h> #import <dpsclient/wraps.h> #import <appkit/color.h> /* only for "blanking out" parts of a matrix */ #import <appkit/graphics.h> /* ditto */ /* * The job of this object is to keep the appearance of the Column Selection panel * in accord with the state of the program. We do not update the Column Selection * panel every time a file is read in, since it is expected that this option will * not be heavily used. */ @implementation ColumnSelectionHandler - init { /* * This global variable keeps track of whether the column selection window * has ever been displayed. We can avoid updating after the selective * file removal if we have never been displayed. */ everVisible = NO; return self; } /* * Arrange to blank out the disabled buttons. The "right" way to do this * is probably to have a "RaggedMatrix" class which allows a different * number of columns in each row, but there are too many other issues * raised by that to deal with right now. Note that having such a class * would allow us to correctly deal with the problem of correctly * redisplaying the matrix after a resize operation on the window. * (We currently get around that problem by making ourself the window's delegate * and defining windowDidResize:, and in that method calling * perform:with:afterDelay:cancelPrevious, but this is highly suboptimal.) */ - eraseDisabledCells:sender { int n, j, numrows, numcols, ncurves; NXRect r; [columnMatrix getNumRows:&numrows numCols:&numcols]; [columnMatrix lockFocus]; NXSetColor([columnMatrix backgroundColor]); /* The NXSetColor call has to come after the lockFocus; otherwise, when * this method is called by fixPanel, the color always comes out black * even if something else is specifically requested. The weird part is, * when this method is called by fixRow, the color is correct when the * NXSetColor call is outside the lockFocus. */ for (n=0; n<[plotParam nFiles]; n++) { ncurves = [plotParam nCurves:n]; if (ncurves < numcols-1) { for (j=ncurves; j<numcols; j++) { [columnMatrix getCellFrame:&r at:n :j+1]; /* note the j+1 */ NXRectFill(&r); } } } [columnMatrix unlockFocus]; NXPing(); return self; } - removeAll:sender /* This method is called by the "remove all files" method of the Plot object. */ { int n, j; int numrows, numcols; NXSize cellsize, intercell; NXCoord dy; /* Do something only if the window has ever been displayed */ if (everVisible) { [columnMatrix getNumRows:&numrows numCols:&numcols]; [columnMatrix getCellSize:&cellsize]; [columnMatrix getIntercell:&intercell]; /* * Wipe out everything. */ dy = (NXCoord)(numrows - 1) * (cellsize.height + intercell.height); [columnMatrix moveBy:0.0 :dy]; /* * Before doing renewRows, set the state of all the cells to 0; this is * because the renewRows method just recycles the cells, and later on * we may find ourselves using a cell which has state=1 when we don't * want such a beast. Also enable all cells (paranoia strikes). */ for (n=0; n<numrows; n++) { for (j=0; j<numcols; j++) { [[columnMatrix cellAt:n :j] setState:0]; [[columnMatrix cellAt:n :j] setEnabled:YES]; } } [columnMatrix renewRows:1 cols:1]; [columnMatrix sizeToCells]; [[columnMatrix cellAt:0 :0] setEnabled:YES]; [[columnMatrix cellAt:0 :0] setType:NX_TOGGLE]; [[columnMatrix cellAt:0 :0] setState:1]; [filenameMatrix moveBy:0.0 :dy]; [filenameMatrix renewRows:1 cols:1]; [[filenameMatrix cellAt:0 :0] setStringValue:"filename"]; [filenameMatrix sizeToCells]; [columnText renewRows:1 cols:1]; [columnText sizeToCells]; /* Do some drawing now. Display the view. */ [[columnMatrix window] display]; NXPing(); /* needed??? */ } return self; } - fixPanel:sender /* * The select column button activates this method; it is also called from * windowDidResize, from Plot.m in postludeToReading, and by the update * button on the panel. We have to fix up the column selection panel * so that it's correct. */ { int n, j; int nfilestotal = [plotParam nFiles], maxcols = 0, ncurves; char title[80]; int numrows, numcols; BOOL one_on; NXSize cellsize, intercell; NXCoord dy; int * turned_on; if (everVisible == NO) everVisible = YES; [columnMatrix getNumRows:&numrows numCols:&numcols]; [columnMatrix getCellSize:&cellsize]; [columnMatrix getIntercell:&intercell]; /* * We have to create some additional rows and perhaps some additional columns. */ // First figure out how many rows and columns the matrices should have for (n=0; n<nfilestotal; n++) { maxcols = MAX(maxcols, [plotParam nCurves:n]); } maxcols++; /* this is the number of columns needed */ if (numrows != nfilestotal || numcols != maxcols) { /* The renewRows:cols: message might have the side effect of setting * the state of all the cells of the matrix back to 0; this is undesired, * so before changing the number of rows and/or columns in the matrix, * make sure we remember which cells in each row were turned on. */ turned_on = (int *)malloc(numrows * sizeof(int)); /* should do error check */ for (n=0; n<numrows; n++) { turned_on[n] = 0; /* cautious initialization */ for (j=0; j<numcols; j++) { if ([[columnMatrix cellAt:n :j] state] == 1) { turned_on[n] = j; break; } } } [columnMatrix renewRows:nfilestotal cols:maxcols]; for (n=numrows; n<nfilestotal; n++) { [[columnMatrix cellAt:n :0] setState:1]; for (j=1; j<maxcols; j++) { [[columnMatrix cellAt:n :j] setState:0]; } } /* And now turn cells back on. */ for (n=0; n<numrows; n++) { for (j=0; j<numcols; j++) { [[columnMatrix cellAt:n :j] setState:0]; } [[columnMatrix cellAt:n :turned_on[n]] setState:1]; } free((void *)turned_on); } [columnMatrix sizeToCells]; dy = (float)(nfilestotal - numrows) * (cellsize.height + intercell.height); [columnMatrix moveBy:0.0 :-dy]; // Some of the cells may come in with type NULLCELL; fix them here for (n=0; n<nfilestotal; n++) { for (j=0; j<maxcols; j++) { [[columnMatrix cellAt:n :j] setEnabled:YES]; [[columnMatrix cellAt:n :j] setType:NX_TOGGLE]; } } // Make sure exactly one button is turned on in each row for (n=0; n<nfilestotal; n++) { one_on = NO; for (j=0; j<maxcols; j++) { if ([[columnMatrix cellAt:n :j] state] == 1) { one_on = YES; break; } } if (!one_on) [[columnMatrix cellAt:n :0] setState:1]; } // We surround the [columnMatrix display] and [self eraseDisabledCells] // calls with the disableFlushWindow, reenableFlushWindow, and flushWindow // calls to prevent the disabled matrix cells from being visible for a long // time while they're drawn and then erased. [columnPanel disableFlushWindow]; [columnMatrix display]; // Disable cells that shouldn't appear. for (n=0; n<nfilestotal; n++) { ncurves = [plotParam nCurves:n]; if (ncurves < maxcols-1) { for (j=ncurves; j<maxcols; j++) { [[columnMatrix cellAt:n :j+1] setType:NX_NULLCELL]; /* note the j+1 */ [[columnMatrix cellAt:n :j+1] setEnabled:NO]; /* again j+1 */ } } } // We have to put the makeKeyAndOrderFront before the eraseDisabledCells // method, because eraseDisabledCells does a lockFocus and lockFocus needs // a real window to draw into. We put the makeKeyAndOrderFront here rather // than at the beginning of this method because this way the disabled cells // of the matrix are visible for a shorter period of time. [columnPanel makeKeyAndOrderFront:self]; // Now erase those disabled cells. [self eraseDisabledCells:self]; [columnPanel reenableFlushWindow]; [columnPanel flushWindowIfNeeded]; NXPing(); /* needed? */ // That finishes with the columnMatrix; now for the filename Matrix. [filenameMatrix renewRows:nfilestotal cols:1]; for (n=0; n<nfilestotal; n++) { if (!strncmp([plotParam filename:(unsigned)n], "pasteboard", 10)) sprintf(title, "pasteboard"); else sprintf(title, strrchr([plotParam filename:(unsigned)n], '/') + 1); [[filenameMatrix cellAt:n :0] setStringValue:title]; } [filenameMatrix sizeToCells]; [filenameMatrix moveBy:0.0 :-dy]; [filenameMatrix display]; // And now for the columnText matrix. [columnText renewRows:1 cols:maxcols]; for (j=1; j<=maxcols; j++) { sprintf(title, "%d", j); [[columnText cellAt:0 :(j-1)] setStringValue:title]; } [columnText sizeToCells]; [columnText display]; return self; } - fixRow:sender /* The sender is columnMatrix in the column selection panel; we want to * turn off some buttons in the matrix row. */ { int row, col, i, prev_col=0, numrows, numcols; row = [sender selectedRow]; col = [sender selectedCol]; [sender getNumRows:&numrows numCols:&numcols]; // Find out what column was previously highlighted: for (i=0; i<numcols; i++) { if ( [[sender cellAt:row :i] state] == 1 && i != col) { prev_col = i; break; } } // adjust the matrix for (i=0; i<numcols; i++) { [ [sender cellAt:row :i] setState:0]; } [ [sender cellAt:row :col] setState:1]; // The disableFlushWindow, reenableFlushWindow, and flushWindow methods // bracket the [sender display] and [self eraseDisabledCells] methods, with // the result that the disabled cells are not visibly drawn on the screen. // This is the way it should be. [columnPanel disableFlushWindow]; [sender display]; [self eraseDisabledCells:self]; [columnPanel reenableFlushWindow]; [columnPanel flushWindowIfNeeded]; // swap the pointers as requested [plotParam swapColumns:prev_col :col forFileNumber:row]; return self; } /* * We call fixPanel here, rather than eraseDisabledCells (which is more * logical), because for some reason eraseDisableCells doesn't seem to work * properly! The method fixPanel: does a lot more work than is really * needed. Sigh... This should all be cleaned up. */ - windowDidResize:sender { [self perform:@selector(fixPanel:) with:self afterDelay:1 /* wait 0.001 second */ cancelPrevious:YES]; return self; } /* * This is called by the selective file removal code in Plot.m. */ - update:sender { int n, nfilestotal = [plotParam nFiles], num_removed = 0; NXSize cellsize, intercell; NXCoord dy; /* Do something only if the window has ever been displayed */ if (everVisible) { [columnMatrix getCellSize:&cellsize]; [columnMatrix getIntercell:&intercell]; /* * Count down the file removal panel, removing rows as needed. */ for (n = nfilestotal-1; n>=0; n--) { if ([[fileRemovalButtons cellAt:n :0] state] == 1) { /* This file is to be removed. */ num_removed++; [columnMatrix removeRowAt:n andFree:YES]; [filenameMatrix removeRowAt:n andFree:YES]; } } [columnMatrix sizeToCells]; [filenameMatrix sizeToCells]; if (num_removed > 0) { dy = (NXCoord)(num_removed) * (cellsize.height + intercell.height); [columnMatrix moveBy:0.0 :dy]; [filenameMatrix moveBy:0.0 :dy]; } /* Do some drawing now. Display the view. */ [[columnMatrix window] display]; NXPing(); /* needed??? */ } return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.