home *** CD-ROM | disk | FTP | other *** search
- //
- // MiscMatrix.m -- a class to implement variable-sized matrices
- // Written by Mike Ferris Copyright (c) 1994 by Mike Ferris.
- // Modified from original MOKit "MOMatrix" class by Don Yacktman.
- // Version 1.0. All rights reserved.
- //
- // This notice may not be removed from this source code.
- //
- // This object is included in the MiscKit by permission from the author
- // and its use is governed by the MiscKit license, found in the file
- // "LICENSE.rtf" in the MiscKit distribution. Please refer to that file
- // for a list of all applicable permissions and restrictions.
- //
-
- // MiscMatrix is a subclass of Matrix that allows independantly sizable
- // rows and columns. Each row can have a different height and each column
- // can have a different width.
- /*
- * Revision History:
- * July 1994: Steve Quirk steveq@telerate.com
- * - implemented sizeToFit method
- * - fixed bugs in addRow, addCol methods
- * - fixed bugs in initFrame:&etc&etc methods
- * - improved performance when changing row/column size
- * Aug 1994: Steve Quirk
- * - improved drawing performance
- * - improved getRow:andCol:forPoint: performance
- * Sep 1994: Scott Violet
- * - improved drawing performance; Scott's note:
- * In the code for drawSelf:: Mike chose to call drawCellAt::
- * which is very expensive, this will result in needless
- * lockFocus: and unlockFocus: calls, and this will make it
- * so that when the matrix is sent printPSCode: it won't work
- * (it tries to print it flipped).
- */
-
- #import <misckit/MiscMatrix.h>
- #import <objc/List.h>
- #import <objc/objc-runtime.h>
-
- #define CLASS_VERSION 0
- #define CLASS_NAME "MiscMatrix"
-
- // These are the private methods we use in MiscMatrix
- @interface MiscMatrix(private)
-
- - _Misc_copyRowSizes:rs andColSizes:cs zone:(NXZone *)zone;
- - _Misc_moveColumnsRightBy:(NXCoord)difference startingAt:(int)col;
- - _Misc_moveRowsDownBy:(NXCoord)difference startingAt:(int)row;
-
- @end
-
- @implementation MiscMatrix
-
- + initialize
- // Set the class version
- {
- if (self == objc_lookUpClass(CLASS_NAME)) {
- [self setVersion:CLASS_VERSION];
- }
- return self;
- }
-
- - setupStorage:(int)rowsHigh :(int)colsWide
- // Set up our storage objects
- {
- int i;
- MiscColumnSize newCSize;
- MiscRowSize newRSize;
-
- columnSizes = [[Storage allocFromZone:[self zone]] initCount:0
- elementSize:sizeof(MiscColumnSize)
- description:MISC_COLUMNSIZE_DESC];
- [columnSizes setAvailableCapacity:(colsWide > 2) ? colsWide : 2];
- rowSizes = [[Storage allocFromZone:[self zone]] initCount:0
- elementSize:sizeof(MiscRowSize)
- description:MISC_ROWSIZE_DESC];
- [rowSizes setAvailableCapacity:(rowsHigh > 2) ? rowsHigh : 2];
-
- newCSize.width = cellSize.width;
- newRSize.height = cellSize.height;
- for (i=0; i<colsWide; i++) {
- newCSize.x = bounds.origin.x + i * (cellSize.width + intercell.width);
- [columnSizes addElement:&newCSize];
- }
- for (i=0; i<rowsHigh; i++) {
- newRSize.y = bounds.origin.y + i * (cellSize.height + intercell.height);
- [rowSizes addElement:&newRSize];
- }
-
- return self;
- }
-
- - initFrame:(const NXRect *)frm mode:(int)aMode prototype:cellId
- numRows:(int)rowsHigh numCols:(int)colsWide
- // Designated initializer override from Matrix. Sets up our storage stuff.
- {
- [super initFrame:frm mode:aMode prototype:cellId numRows:rowsHigh
- numCols:colsWide];
-
- [self setupStorage:rowsHigh :colsWide];
-
- return self;
- }
-
- - initFrame:(const NXRect *)frm mode:(int)aMode cellClass:factoryId
- numRows:(int)rowsHigh numCols:(int)colsWide
- // Designated initializer override from Matrix. Sets up our storage stuff.
- {
- [super initFrame:frm mode:aMode cellClass:factoryId numRows:rowsHigh
- numCols:colsWide];
-
- [self setupStorage:rowsHigh :colsWide];
-
- return self;
- }
-
- - _Misc_copyRowSizes:rs andColSizes:cs zone:(NXZone *)zone
- {
- rowSizes = [rs copyFromZone:zone];
- columnSizes = [cs copyFromZone:zone];
- return self;
- }
-
- - copyFromZone:(NXZone *)zone
- {
- id obj = [super copyFromZone:zone];
- [obj _Misc_copyRowSizes:rowSizes andColSizes:columnSizes zone:zone];
- return obj;
- }
-
- - free
- // free the storage
- {
- [columnSizes free];
- [rowSizes free];
- return [super free];
- }
-
- - _Misc_moveColumnsRightBy:(NXCoord)difference startingAt:(int)col
- // A private method used by the methods which cause sizing stuff to change
- {
- MiscColumnSize *cSize;
- int i;
-
- if ((col < 0) || (col >= numCols)) {
- return nil;
- }
-
- cSize = (MiscColumnSize *)[columnSizes elementAt:col];
- for (i=col; i<numCols; i++, cSize++)
- cSize->x += difference;
-
- return self;
- }
-
- - _Misc_moveRowsDownBy:(NXCoord)difference startingAt:(int)row
- // A private method used by the methods which cause sizing stuff to change
- {
- MiscRowSize *rSize;
- int i;
-
- if ((row < 0) || (row >= numRows)) {
- return nil;
- }
-
- rSize = (MiscRowSize *)[rowSizes elementAt:row];
- for (i=row; i<numRows; i++, rSize++)
- rSize->y += difference;
-
- return self;
- }
-
- - setWidth:(NXCoord)newWidth ofCol:(int)col
- // This method allows the setting of column widths
- {
- NXCoord diff;
- MiscColumnSize *cSize;
-
- if ((col < 0) || (col >= numCols)) {
- return nil;
- }
-
- cSize = (MiscColumnSize *)[columnSizes elementAt:col];
- diff = newWidth - cSize->width;
- cSize->width = newWidth;
-
- return [self _Misc_moveColumnsRightBy:diff startingAt:col+1];
- }
-
- - setHeight:(NXCoord)newHeight ofRow:(int)row
- // This method allows the setting of row heights
- {
- NXCoord diff;
- MiscRowSize *rSize;
-
- if ((row < 0) || (row >= numRows)) {
- return nil;
- }
-
- rSize = (MiscRowSize *)[rowSizes elementAt:row];
- diff = newHeight - rSize->height;
- rSize->height = newHeight;
-
- return [self _Misc_moveRowsDownBy:diff startingAt:row+1];
- }
-
- - sizeToCells
- // Resize the matrix to the proper size to fit all our cells.
- {
- NXRect rect;
- MiscColumnSize *cSize;
- MiscRowSize *rSize;
-
- [self getFrame:&rect];
-
- if (numCols == 0) {
- rect.size.width = 0.0;
- } else {
- cSize = (MiscColumnSize *)[columnSizes lastElement];
- rect.size.width = cSize->x + cSize->width - bounds.origin.x;
- }
-
- if (numRows == 0) {
- rect.size.height = 0.0;
- } else {
- rSize = (MiscRowSize *)[rowSizes lastElement];
- rect.size.height = rSize->y + rSize->height - bounds.origin.y;
- }
-
- /* Or do we want to just hit the instance variable directly--see the
- * version at the end of -sizeRowsToFitCells where you _cannot_ use
- * the -setFrame: method. If you have troubles with this implementation,
- * let the maintainer of the class know to change this so it will
- * work right for everybody.
- */
- [self setFrame:&rect]; // I think we want self here, not super... -DAY
-
- return self;
- }
-
-
- - sizeToFit
- /*
- * resize row heights and column widths to accommodate the largest cell in each
- * then resize self to fit the cells.
- */
- {
- int row,col;
- NXSize thisCellSize;
- MiscRowSize *rSize;
- MiscColumnSize *cSize;
- NXCoord *maxWidth, *mW, maxHeight;
- NXZone *myZone;
- id *cellAt;
- /*
- * This method is a pig. Try to improve preformance by removing method calls
- * by using the method implementation ptr...
- */
- id (*cellCalcCellSize)(id, SEL, NXSize*);
-
- myZone = [super zone];
-
- // space to record the largest size of the columns
- maxWidth = NXZoneCalloc(myZone, numCols, sizeof(NXCoord));
-
- /*
- * this monkey business is to speed up execution of this pig
- */
- cellCalcCellSize = (id(*)(id, SEL, NXSize*))
- [protoCell methodFor:@selector(calcCellSize:)];
- cellAt = ((List *)(cellList))->dataPtr; // peek at Lists' data
-
- rSize = (MiscRowSize *)[rowSizes elementAt:0];
- for (row = 0; row < numRows; row++,rSize++) {
- maxHeight = rSize->height; /* init max = height of cell 0 */
-
- for (col = 0, mW = maxWidth; col < numCols; col++, mW++) {
- // [[super cellAt:row:col] calcCellSize:&thisCellSize];
- // replace above with....
- cellCalcCellSize(*cellAt,@selector(calcCellSize:),&thisCellSize);
-
- if (thisCellSize.height > maxHeight)
- maxHeight = thisCellSize.height;
- if (thisCellSize.width > *mW)
- *mW = thisCellSize.width;
- cellAt++; /* next column... */
- }
- /*
- * change the height of this row if one of the columns needs more headroom
- */
- if (maxHeight > rSize->height)
- [self setHeight:maxHeight ofRow:row];
- }
-
- /*
- * now adjust the column widths if needed...
- */
- cSize = (MiscColumnSize *)[columnSizes elementAt:0];
- for (col = 0, mW = maxWidth; col < numCols; col++,cSize++, mW++)
- if (*mW != cSize->width) {
- NXCoord diff;
- diff = *mW - cSize->width;
- cSize->width = *mW;
- [self _Misc_moveColumnsRightBy:diff startingAt:col+1];
- }
-
- if (maxWidth)
- NXZoneFree(myZone,maxWidth);
-
- return [self sizeToCells];
- }
-
- - renewRows:(int)newRows cols:(int)newCols
- // Makes sure to keep our storage objects in synch with everything else.
- {
- MiscColumnSize newCSize, *cSize;
- MiscRowSize newRSize, *rSize;
- int i;
-
- // Remove any storage elements past the new number of cols
- for (i=numCols-1; i>=newCols; i--) {
- [columnSizes removeLastElement];
- }
- // Add any needed new storage elements to get up to the new number of cols
- for (i=numCols; i<newCols; i++) {
- if (i==0) {
- newCSize.x = bounds.origin.x;
- } else {
- cSize = (MiscColumnSize *)[columnSizes lastElement];
- newCSize.x = cSize->x + cSize->width + intercell.width;
- }
- newCSize.width = cellSize.width;
- [columnSizes addElement:&newCSize];
- }
-
- // Remove any storage elements past the new number of rows
- for (i=numRows-1; i>=newRows; i--) { // Was ++ but -- makes more sense
- [rowSizes removeLastElement];
- }
- // Add any needed new storage elements to get up to the new number of rows
- for (i=numRows; i<newRows; i++) {
- if (i==0) {
- newRSize.y = bounds.origin.y;
- } else {
- rSize = (MiscRowSize *)[rowSizes lastElement];
- newRSize.y = rSize->y + rSize->height + intercell.height;
- }
- newRSize.height = cellSize.height;
- [rowSizes addElement:&newRSize];
- }
-
- [super renewRows:newRows cols:newCols];
-
- return self;
- }
-
- - addCol
- /*
- * addCol is implemented by the Matrix superclass as [self insertColAt:numCols]
- * so doing all this work here is redundant (and wrong). Changed this to simply
- * call super.
- */
- {
- int n = [columnSizes count]; /* copy just to prove a point... */
-
- [super addCol];
- // to prove my point, look how everything still checks out...
- if (([columnSizes count] != (n+1)) || ((n+1) != numCols))
- [self error:"Assertion failed in [MiscMatrix addCol]. Re-implement!"];
-
- return self;
- }
-
- - addRow
- /*
- * addRow is implemented by the Matrix superclass as [self insertRowAt:numRows]
- * so doing all this work here is redundant (and wrong). Changed this to simply
- * call super.
- */
- {
- int n = [rowSizes count]; /* copy just to prove a point... */
-
- [super addRow];
- // to prove my point, look how everything still checks out...
- if (([rowSizes count] != (n+1)) || ((n+1) != numRows))
- [self error:"Assertion failed in [MiscMatrix addRow]. Re-implement!"];
-
- return self;
- }
-
- - insertColAt:(int)col
- // Keep the storage in synch
- {
- MiscColumnSize newCSize, *cSize;
-
- if ((col < 0) || (col > numCols))
- return nil;
-
- newCSize.width = cellSize.width;
- if (col == 0) /* adding first cell ? */
- newCSize.x = bounds.origin.x;
- else
- if (col == numCols) { /* adding new last element? */
- cSize = (MiscColumnSize *)[columnSizes lastElement];
- newCSize.x = cSize->x + cSize->width + intercell.width;
- } else { /* must be in the middle somewhere... */
- cSize = (MiscColumnSize *)[columnSizes elementAt:col];
- newCSize.x = cSize->x;
- }
-
-
- if (col == numCols)
- [columnSizes addElement:&newCSize];
- else {
- [columnSizes insertElement:&newCSize at:col];
- [self _Misc_moveColumnsRightBy:newCSize.width + intercell.width
- startingAt:col+1];
- }
-
- [super insertColAt:col];
-
- return self;
- }
-
- - insertRowAt:(int)row
- // Keep the storage in synch
- {
- MiscRowSize newRSize, *rSize;
-
- if ((row < 0) || (row > numRows))
- return nil;
-
- newRSize.height = cellSize.height;
- if (row == 0) /* adding first row? */
- newRSize.y = bounds.origin.y;
- else
- if (row == numRows) { /* adding new last row? */
- rSize = (MiscRowSize *)[rowSizes lastElement];
- newRSize.y = rSize->y + rSize->height + intercell.height;
- } else { /* must be in the middle somewhere... */
- rSize = (MiscRowSize *)[rowSizes elementAt:row];
- newRSize.y = rSize->y;
- }
-
-
- if (row == numRows)
- [rowSizes addElement:&newRSize];
- else {
- [rowSizes insertElement:&newRSize at:row]; // changed from row+1 (sq)
- [self _Misc_moveRowsDownBy:newRSize.height + intercell.height
- startingAt:row+1];
- }
-
- [super insertRowAt:row];
-
- return self;
- }
-
- - removeColAt:(int)col andFree:(BOOL)flag
- // Keep the storage in synch
- {
- MiscColumnSize *cSize;
- NXCoord diff;
-
- if ((col >= numCols) || (col < 0)) {
- return nil;
- }
-
- [super removeColAt:col andFree:flag];
-
- cSize = (MiscColumnSize *)[columnSizes elementAt:col];
- diff = cSize->width;
- [columnSizes removeElementAt:col];
- [self _Misc_moveColumnsRightBy:0.0 - diff - intercell.width startingAt:col];
-
- return self;
- }
-
- - removeRowAt:(int)row andFree:(BOOL)flag
- // Keep the storage in synch
- {
- MiscRowSize *rSize;
- NXCoord diff;
-
- if ((row >= numRows) || (row < 0)) {
- return nil;
- }
-
- [super removeRowAt:row andFree:flag];
-
- rSize = (MiscRowSize *)[rowSizes elementAt:row];
- diff = rSize->height;
- [rowSizes removeElementAt:row];
- [self _Misc_moveRowsDownBy:0.0 - diff - intercell.height startingAt:row];
-
- return self;
- }
-
- - drawSelf:(const NXRect *)rects:(int)rectCount
- // We do our own drawing because we need to draw our cells in diverse
- // rectangles
- {
- int row, col;
- int rMin,cMin,rMax,cMax;
- NXPoint lowerRt;
- NXRect cFrm;
- MiscColumnSize *cSize;
- MiscRowSize *rSize;
-
- // Scott Violet removed the window flushing stuff; his change in the
- // cell rendering should make these unnecessary, so removing them will
- // remove flicker when the MiscMatrix is in a SplitView. I simply
- // commented it out for now; --DAY
- // [window disableFlushWindow];
-
- // the background (if any)
- if (backgroundGray != -1.0) {
- PSsetgray(backgroundGray);
- if (rectCount==1) {
- NXRectFill(&(rects[0]));
- } else {
- NXRectFill(&(rects[1]));
- NXRectFill(&(rects[2]));
- }
- }
-
- /*
- * calculate the cells that need to be redrawn & iterate through them only...
- */
- [self getRow:&rMin andCol:&cMin forPoint:&(rects->origin)];
- if (rMin == -1) rMin = 0;
- if (cMin == -1) cMin = 0;
-
- lowerRt.x = rects->origin.x + rects->size.width;
- lowerRt.y = rects->origin.y + rects->size.height;
- [self getRow:&rMax andCol:&cMax forPoint:&lowerRt];
- if (rMax == -1) rMax = numRows-1;
- if (cMax == -1) cMax = numCols-1;
-
- rSize = (MiscRowSize *)[rowSizes elementAt:rMin];
- for (row=rMin; row<=rMax; row++,rSize++) {
- cSize = (MiscColumnSize *)[columnSizes elementAt:cMin];
- for (col=cMin; col<=cMax; col++,cSize++) {
- cFrm.origin.x = cSize->x;
- cFrm.origin.y = rSize->y;
- cFrm.size.width = cSize->width;
- cFrm.size.height = rSize->height;
- if (rectCount == 1) {
- if (NXIntersectsRect(&(rects[0]), &cFrm))
- // old way: [self drawCellAt:row:col];
- [self getCellFrame:&cFrm at:row:col];
- [[self cellAt:row:col] drawInside:&cFrm inView:self];
- } else {
- if ((NXIntersectsRect(&(rects[1]), &cFrm)) ||
- (NXIntersectsRect(&(rects[2]), &cFrm)))
- // old way: [self drawCellAt:row:col];
- [self getCellFrame:&cFrm at:row:col];
- [[self cellAt:row:col] drawInside:&cFrm inView:self];
- }
- }
- }
-
- // [window reenableFlushWindow];
- // [window flushWindow];
-
- return self;
- }
-
- - getCellFrame:(NXRect *)theRect at:(int)row:(int)col
- // Calculate and return the rect used to display the cell at the given
- // row and column
- {
- MiscColumnSize *cSize;
- MiscRowSize *rSize;
-
- if (col < numCols) {
- cSize = (MiscColumnSize *)[columnSizes elementAt:col];
- theRect->origin.x = cSize->x;
- theRect->size.width = cSize->width;
- } else {
- int num = col - numCols;
-
- cSize = (MiscColumnSize *)[columnSizes lastElement];
- theRect->origin.x = cSize->x +
- (num * (cellSize.width + intercell.width));
- theRect->size.width = cellSize.width;
- }
-
- if (row < numRows) {
- rSize = (MiscRowSize *)[rowSizes elementAt:row];
- theRect->origin.y = rSize->y;
- theRect->size.height = rSize->height;
- } else {
- int num = row - numRows;
-
- rSize = (MiscRowSize *)[rowSizes lastElement];
- theRect->origin.y = rSize->y +
- (num * (cellSize.height + intercell.height));
- theRect->size.height = cellSize.height;
- }
-
- return self;
- }
-
- - getRow:(int *)row andCol:(int *)col forPoint:(const NXPoint *)aPoint
- // Calculate the row and column of the cell which contains the given point
- // changed to use a bsearch instead of iterative... - sq
- {
- MiscColumnSize *cSize;
- MiscRowSize *rSize;
- int index, upper, lower;
-
- *row = -1;
- *col = -1;
- if ((aPoint->x < bounds.origin.x) ||
- (aPoint->x > bounds.origin.x + bounds.size.width) ||
- (aPoint->y < bounds.origin.y) ||
- (aPoint->y > bounds.origin.y + bounds.size.height)) {
- return nil;
- }
- cSize = (MiscColumnSize *)[columnSizes elementAt:0];
- lower = 0;
- upper = [columnSizes count];
- while (lower < upper) {
- index = (lower + upper) / 2;
- if (aPoint->x < cSize[index].x)
- upper = index; // lower, look to the left...
- else if (aPoint->x > (cSize[index].x + cSize[index].width))
- lower = index + 1; // higher, look to the right...
- else {
- *col = index; // hit it...
- break;
- }
- }
- rSize = (MiscRowSize *)[rowSizes elementAt:0];
- lower = 0;
- upper = [rowSizes count];
- while (lower < upper) {
- index = (lower + upper) / 2;
- if (aPoint->y < rSize[index].y)
- upper = index; // lower, look to the left...
- else if (aPoint->y > (rSize[index].y + rSize[index].height))
- lower = index + 1; // higher, look to the right...
- else {
- *row = index; // hit it...
- break;
- }
- }
- return ((*row == -1) || (*col == -1)) ? nil : self;
- }
-
- - setIntercell:(const NXSize *)aSize
- // Keep the storage in synch
- {
- NXCoord xDiff = aSize->width - intercell.width;
- NXCoord yDiff = aSize->height - intercell.height;
- MiscRowSize *rSize;
- MiscColumnSize *cSize;
- int i;
-
- for (i=1; i<numRows; i++) {
- rSize = (MiscRowSize *)[rowSizes elementAt:i];
- rSize->y += (yDiff * i);
- }
- for (i=1; i<numCols; i++) {
- cSize = (MiscColumnSize *)[columnSizes elementAt:i];
- cSize->x += (xDiff * i);
- }
-
- return [super setIntercell:aSize];
- }
-
-
- - write:(NXTypedStream *)typedStream
- // Write our ivars
- {
- [super write:typedStream];
- NXWriteObject(typedStream, columnSizes);
- NXWriteObject(typedStream, rowSizes);
- return self;
- }
-
- - read:(NXTypedStream *)typedStream
- // Read our ivars
- {
- int classVersion;
-
- [super read:typedStream];
-
- classVersion = NXTypedStreamClassVersion(typedStream, CLASS_NAME);
-
- switch (classVersion) {
- case 0: // First version.
- columnSizes = NXReadObject(typedStream);
- rowSizes = NXReadObject(typedStream);
- break;
- default:
- NXLogError("[%s read:] class version %d cannot read "
- "instances archived with version %d",
- CLASS_NAME, CLASS_VERSION, classVersion);
- [self setupStorage:numRows :numCols];
- break;
- }
- return self;
- }
-
-
- // ********************Overridden private methods***********************
- // *****************that I'm going to hell for using********************
-
- // These methods are used by Matrix's mouseDown:. Doing the whole
- // mouseDown: method over would have been a royal pain in the butt,
- // so I cheated.
-
-
- - (BOOL)_mouseHit:(const NXPoint *)forpoint row:(int *)row col:(int *)col
- {
- NXPoint point;
- id ret;
-
- point = *forpoint;
- [self convertPoint:&point fromView:nil];
- ret = [self getRow:row andCol:col forPoint:&point];
-
- if (ret == nil)
- return NO;
- return YES;
- }
-
- - (BOOL)_loopHit:(const NXPoint *)forpoint row:(int *)row col:(int *)col
- {
- NXPoint point;
- id ret;
-
- point = *forpoint;
- [self convertPoint:&point fromView:nil];
- ret = [self getRow:row andCol:col forPoint:&point];
-
- if (ret == nil)
- return NO;
- return YES;
- }
-
- - (BOOL)_radioHit:(const NXPoint *)forpoint row:(int *)row col:(int *)col
- {
- NXPoint point;
- id ret;
-
- point = *forpoint;
- [self convertPoint:&point fromView:nil];
- ret = [self getRow:row andCol:col forPoint:&point];
-
- if (ret == nil)
- return NO;
- return YES;
- }
-
- - sizeRowsToFitCells
- {
- NXRect veryBig;
- NXSize size;
- NXRect myFrame;
- NXCoord maxHeight;
- NXCoord offset = 0.0;
- MiscRowSize *rSize;
- int i,j;
-
- veryBig.size.width = cellSize.width;
- veryBig.size.height = MAXFLOAT;
-
- [self getFrame:&myFrame];
- for (i = 0; i < numRows; i++)
- {
- maxHeight = 0.0;
- rSize = (MiscRowSize *)[rowSizes elementAt:i];
- rSize->y = offset;
- for (j = 0; j < numCols; j++)
- {
- [[self cellAt:i :j] calcCellSize:&size inRect:&veryBig];
- if (size.height > maxHeight)
- maxHeight = size.height;
- }
- rSize->height = maxHeight;
- offset += maxHeight + intercell.height;
- }
-
- myFrame.size.height = offset;
- // This can't be used: [self setFrame:&myFrame];
- /*
- * We can't call setFrame: here because it will call sizeTo::
- * which will try to modify cellFrame and the column/row sizes.
- * So we just copy into the instance variable.
- *
- * And we'll probably be sent to the deepest corners of hell for doing it.
- */
- // frame = myFrame;
- // This has been suggested as a perhaps safer way to do the same thing,
- // so we'll use it instead of the above line, but I'm keeping the above
- // until we are sure that it is doing the right thing... -DAY
- /*
- * We use super here to avoid re-adjusting the row
- * and column sizes.
- */
- [super sizeTo:myFrame.size.width :myFrame.size.height];
-
- return self;
- }
-
-
- - sizeTo:(NXCoord)width :(NXCoord)height
- {
- NXRect oldFrame;
- NXCoord dx, dy;
- float sx, sy;
-
- [self getFrame:&oldFrame];
-
- [super sizeTo:width :height];
-
- dx = width - oldFrame.size.width;
- dy = height - oldFrame.size.height;
-
- if ([self doesAutosizeCells] && (numRows > 0) && (numCols > 0))
- {
- NXCoord offset;
- int i;
- MiscRowSize *rSize;
- MiscColumnSize *cSize;
-
- sx = 1 + (dx/(oldFrame.size.width - (numRows - 1)*intercell.width));
- sy = 1 + (dy/(oldFrame.size.height - (numCols - 1)*intercell.height));
-
- for (i=0, offset = 0.0; i < numRows; i++)
- {
- rSize = (MiscRowSize *)[rowSizes elementAt:i];
- rSize->y = offset;
- rSize->height *= floor(sy+0.5);
- offset += rSize->height + intercell.height;
- }
-
- for (i=0, offset = 0.0; i < numCols; i++)
- {
- cSize = (MiscColumnSize *)[columnSizes elementAt:i];
- cSize->x = offset;
- cSize->width *= sx;
- offset += cSize->width + intercell.width;
- }
- }
- return self;
- }
-
- @end
-
- @implementation Storage(MiscLastElementCategory)
-
- - (void *)lastElement
- // A little shortcut
- {
- void *theLastOne;
- theLastOne = (numElements) ? (char *)dataPtr + (elementSize*(numElements-1)) : NULL;
- return theLastOne;
- }
-
- @end
-
-