Re: Varying Row Heights
Re: Varying Row Heights
- Subject: Re: Varying Row Heights
- From: Drew McCormack <email@hidden>
- Date: Thu, 25 Apr 2002 08:06:49 +0200
On Thursday, April 25, 2002, at 12:36 AM, Paul A. Seligman wrote:
I am looking to implement a TableView in which different rows have
different heights depending on the data corresponding to each row. If
it helps, I only need two different row heights. There seems to be
absolutely nothing in the docs about this, and I
fear it may be impossible. Does anyone have any knowledge about this?
I spent some time trying to do this about 6 months ago. You might check
out the archives for what was said then. I think a search for "varying
row heights" would find it.
My conclusion was that it was probably possible, but not trivial. I got
to the stage that I could have rows with different heights, but when I
edited a cell, I couldn't get the field editor to resize properly (the
rows themselves do resize properly).
The code I made is slow (I just wanted to see if it worked first), and
not that long, so I will include it here. Maybe someone can see what is
wrong with it. I have played with it a lot to try to get the correct
behavior, so I don't know if it will work straight out of the box. At
least it will show you which methods you need to override.
First, here is the header and implementation file for a subclass of
NSCell which can be used to set attributes of the cells:
#import <AppKit/AppKit.h>
@interface TextCell : NSTextFieldCell {
NSText *currentFieldEditor;
}
- (void)dealloc;
- (NSText *)setUpFieldEditorAttributes:(NSText *)textObj;
- (NSText *)currentFieldEditor;
- (void)setCurrentFieldEditor:(NSText *)editor;
@end
@implementation TextCell
- (NSText *)setUpFieldEditorAttributes:(NSText *)textObj {
NSTextContainer *container = [textObj textContainer];
//[self setCurrentFieldEditor:textObj];
//textObj = [super setUpFieldEditorAttributes:textObj];
[textObj setFieldEditor:NO];
//[textObj setHorizontallyResizable:NO];
[textObj setVerticallyResizable:YES];
[container setHeightTracksTextView:YES];
//[container setWidthTracksTextView:NO];
//[container setContainerSize:NSMakeSize([container
containerSize].width, 10000000.0)];
//[textObj setBackgroundColor: [NSColor redColor]];
//[textObj setDrawsBackground:YES];
//[textObj setAutoresizingMask: NSViewHeightSizable];
return textObj;
}
- (void)editWithFrame:(NSRect)aRect inView:(NSView *)controlView
editor:(NSText *)textObj delegate:(id)anObject event:(NSEvent
*)theEvent {
// aRect.size.height = aRect.size.height + 50.0;
[super editWithFrame:aRect inView:controlView editor:textObj
delegate:anObject event:theEvent];
}
@end
Here is the ".h" file of my table view:
#import <Cocoa/Cocoa.h>
@class TextCell;
@interface RowIrregTableView : NSTableView
{
BOOL textHasChanged;
}
- (void)editColumn:(int)columnIndex row:(int)rowIndex withEvent:(NSEvent
*)theEvent select:(BOOL)flag;
- (TextCell *)textCellForRow:(int)row column:(int)col;
- (NSRect)rectOfRow:(int)row;
- (NSRect)rectOfColumn:(int)col;
- (NSRect)frameOfCellAtColumn:(int)column row:(int)row;
-(NSRect)frame;
@end
Here is the ".m" file:
#import "RowIrregTableView.h"
#import "TextCell.h"
@interface RowIrregTableView(PrivateMethods)
-(NSRange)rangeOfRow:(int)row;
- (int)maxHeightInRow:(int)row;
@end
@implementation RowIrregTableView
-(id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if ( self ) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(TextDidChange:)
name:@"NSControlTextDidChangeNotification"
object:self];
}
return self;
}
- (void)awakeFromNib {
NSArray *cols = [self tableColumns];
NSTableColumn *col;
int i;
NSCell *dataCell;
NSTextView *fe;
for ( i = 0; i < [cols count]; i++ ) {
col = [cols objectAtIndex:i];
dataCell = [[[TextCell alloc] initTextCell:@""] autorelease ];
[dataCell setEditable:YES];
[col setDataCell:dataCell];
}
}
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
-(void)textDidChange:(NSNotification *)notif {
TextCell *cell;
NSRect frame;
cell = [self textCellForRow:[self editedRow] column:[self
editedColumn]];
textHasChanged = YES;
frame = [self frameOfCellAtColumn:[self editedColumn] row:[self
editedRow]];
[self setRowHeight:frame.size.height];
}
-(NSRange)rangeOfRow:(int)row {
NSRange range;
int rowIndex;
float spacing = [self intercellSpacing].height;
range.location = 0;
for ( rowIndex = 0; rowIndex < row; rowIndex++ ) {
range.location += [self maxHeightInRow:rowIndex] + spacing;
}
range.length = [self maxHeightInRow:row];
return range;
}
- (TextCell *)textCellForRow:(int)row column:(int)col {
NSTableColumn *tabCol;
NSArray *tableCols = [self tableColumns];
tabCol = [tableCols objectAtIndex:col];
return [tabCol dataCellForRow:row];
}
// Determine maximum height of any cell in 'row'
- (int)maxHeightInRow:(int)row {
float maxHeight;
int colIndex;
id obj;
id <NSCopying> initObjVal;
BOOL releaseObj;
NSTableColumn *tabCol;
TextCell *dataCell;
NSArray *tableCols = [self tableColumns];
maxHeight = [self rowHeight];
for ( colIndex = 0; colIndex < [self numberOfColumns]; colIndex++ ) {
tabCol = [tableCols objectAtIndex:colIndex];
dataCell = [self textCellForRow:row column:colIndex];
initObjVal = [dataCell objectValue];
if ( nil == initObjVal ) continue;
releaseObj = NO;
[initObjVal retain];
obj = [[self dataSource] tableView:self
objectValueForTableColumn:tabCol row:row];
if ( textHasChanged && ( row == [self editedRow] ) &&
( colIndex == [self editedColumn] ) ) {
obj = [[[self window] fieldEditor:YES forObject:dataCell]
string];
releaseObj = NO;
}
[dataCell setObjectValue:obj];
maxHeight = MAX(maxHeight, [dataCell cellSize].height);
if ( releaseObj ) [obj release];
[dataCell setObjectValue:initObjVal];
[initObjVal release];
}
return maxHeight;
}
- (NSRect)rectOfRow:(int)row {
NSRect rect = [super rectOfRow:row];
NSRange rowRange = [self rangeOfRow:row];
rect.origin.y = rowRange.location;
rect.size.height = rowRange.length;
return rect;
}
- (NSRect)rectOfColumn:(int)col {
NSRect rect = [super rectOfColumn:col];
NSRange rowRange = [self rangeOfRow:([self numberOfRows]-1) ];
rect.size.height = rowRange.location + rowRange.length - 1;
return rect;
}
- (NSRect)frameOfCellAtColumn:(int)column row:(int)row {
NSRect rect = [super frameOfCellAtColumn:column row:row];
NSRect rowRect = [self rectOfRow:row];
rect.size.height = rowRect.size.height;
rect.origin.y = rowRect.origin.y;
return rect;
}
-(void)calcAndSetFrame {
NSRect frameRect = [super frame];
NSRect tempRect;
if ( [self numberOfColumns] == 0 || [self numberOfRows] == 0 )
return frameRect;
tempRect = [self rectOfColumn:0];
frameRect.size.height = tempRect.size.height;
tempRect = [self rectOfRow:0];
frameRect.size.width = tempRect.size.width;
[self setFrame: frameRect];
}
-(void)calcAndSetBounds {
NSRect boundsRect = [super bounds];
NSRect tempRect;
if ( [self numberOfColumns] == 0 || [self numberOfRows] == 0 )
return boundsRect;
tempRect = [self rectOfColumn:0];
boundsRect.size.height = tempRect.size.height;
tempRect = [self rectOfRow:0];
boundsRect.size.width = tempRect.size.width;
[self setBounds:boundsRect];
}
- (int)rowAtPoint:(NSPoint)point {
int result;
int i;
NSRect rowRect;
BOOL rowNotFound = YES;
i = -1;
result = -1;
while ( ++i < [self numberOfRows] && rowNotFound ) {
rowRect = [self rectOfRow:i];
if ( ( point.y >= rowRect.origin.y ) && ( point.y <=
rowRect.origin.y + rowRect.size.height - 1 ) &&
( point.x >= rowRect.origin.x ) && ( point.x <=
rowRect.origin.x + rowRect.size.width - 1 ) ) {
rowNotFound = NO;
result = i;
}
}
return result;
}
- (int)columnAtPoint:(NSPoint)point {
int result;
int i;
NSRect colRect;
BOOL colNotFound = YES;
i = -1;
result = -1;
while ( ++i < [self numberOfColumns] && colNotFound ) {
colRect = [self rectOfColumn:i];
if ( ( point.y >= colRect.origin.y ) && ( point.y <=
colRect.origin.y + colRect.size.height - 1 ) &&
( point.x >= colRect.origin.x ) && ( point.x <=
colRect.origin.x + colRect.size.width - 1 ) ) {
colNotFound = NO;
result = i;
}
}
return result;
}
- (NSRange)columnsInRect:(NSRect)rect {
NSRange result;
NSPoint point;
NSRect lastCol, lastRow, firstCol, firstRow;
float left, right, top, bottom;
int leftCol, rightCol, topRow, bottomRow;
firstCol = [self rectOfColumn:0 ];
firstRow = [self rectOfRow:0 ];
lastCol = [self rectOfColumn:([self numberOfColumns] - 1) ];
lastRow = [self rectOfRow:([self numberOfRows] - 1) ];
left = rect.origin.x;
right = rect.origin.x + rect.size.width;
top = rect.origin.y;
bottom = rect.origin.y + rect.size.height;
// Check non-overlapping case
if ( ( left > lastCol.origin.x + lastCol.size.width ) ||
( right < firstCol.origin.x ) ||
( top > lastRow.origin.y + lastRow.size.height ) ||
( bottom < firstRow.origin.x ) ) {
result.length = 0.0;
return result;
}
point.x = left;
point.y = 0.0;
leftCol = [self columnAtPoint:point];
if ( leftCol == -1 ) leftCol = 0;
point.x = right;
point.y = 0;
rightCol = [self columnAtPoint:point];
if ( rightCol == -1 ) rightCol = [self numberOfColumns] - 1;
result.location = leftCol;
result.length = (rightCol - leftCol + 1);
return result;
}
- (NSRange)rowsInRect:(NSRect)rect {
NSRange result;
NSPoint point;
NSRect lastCol, lastRow, firstCol, firstRow;
float left, right, top, bottom;
int topRow, bottomRow;
firstCol = [self rectOfColumn:0 ];
firstRow = [self rectOfRow:0 ];
lastCol = [self rectOfColumn:([self numberOfColumns] - 1) ];
lastRow = [self rectOfRow:([self numberOfRows] - 1) ];
left = rect.origin.x;
right = rect.origin.x + rect.size.width;
top = rect.origin.y;
bottom = rect.origin.y + rect.size.height;
// Check non-overlapping case
if ( ( left > lastCol.origin.x + lastCol.size.width ) ||
( right < firstCol.origin.x ) ||
( top > lastRow.origin.y + lastRow.size.height ) ||
( bottom < firstRow.origin.x ) ) {
result.length = 0.0;
return result;
}
point.x = 0.0;
point.y = top;
topRow = [self rowAtPoint:point];
if ( topRow == -1 ) topRow = 0;
point.x = 0.0;
point.y = bottom;
bottomRow = [self rowAtPoint:point];
if ( bottomRow == -1 ) bottomRow = [self numberOfRows] - 1;
result.location = topRow;
result.length = (bottomRow - topRow + 1);
return result;
}
@end
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
... ... ... ... ... ... ... ...
Dr. Drew McCormack
Trade Strategist (www.trade-strategist.com)
Trading simulation software for Mac OS X
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.