This is RZBrowserCell.m in view mode; [Download] [Up]
/* * RZBrowserCell * * A subclass of BrowserCell supporting fixed and variable position tabs, * multi-font text and inline graphics. * * Here is an example of setting up a Browser to use a RZBrowserCell: * * // create a prototype cell for the browser * id cellPrototype = [[RZBrowserCell alloc] init]; * * // initialize the tab stops * // fixed tab at 10 pixels * [cellPrototype addFixedTab:10.0]; * * // proportional tab at 20% with min at 30 and max at 600 pixels * [cellPrototype addProportionalTab:0.2 min:30 max:600]; * * // fixed tab 60 pixels from right side * [cellPrototype addFixedTab:-60.0]; * * // make sure to set the prototype before we've loaded any columns * [browser setCellPrototype:cellPrototype]; * [browser loadColumnZero]; * [[browser window] makeKeyAndOrderFront:self]; * * * You may freely copy, distribute and reuse the code in this example. * This code is provided AS IS without warranty of any kind, expressed * or implied, as to its fitness for any particular use. * * Copyright 1995 Ralph Zazula (rzazula@next.com). All Rights Reserved. * */ #import "RZBrowserCell.h" #import "RZSortedList.h" #import "RZTextToken.h" #import "RZTabStop.h" #import "RZSimpleString.h" #import "RZRefCountedList.h" #import <appkit/appkit.h> #define BORDER 1 @interface RZBrowserCell(Private) - _addTab:(RZTabStop *)aTab; - _addText:(RZTextToken *)aText; - _drawToken:(RZTextToken *)token inside:(const NXRect *)cellFrame inView:controlView; @end @implementation RZBrowserCell - copyFromZone:(NXZone *)zone { if(self = [super copyFromZone:zone]) { if(tabStops) { [tabStops addReference]; } if(textTokens) { [textTokens addReference]; } } return self; } - free { if(tabStops) { tabStops = [[tabStops freeObjects] free]; } if(textTokens) { textTokens = [[textTokens freeObjects] free]; } return [super free]; } - setFont:fontObj { [super setFont:fontObj]; /* * save this info so we don't have to look it up every time we draw * Note: support for a TextCell is a font object */ NXTextFontInfo(support, &ascender, &descender, &lineHeight); return self; } - calcCellSize:(NXSize *)theSize inRect:(const NXRect *)aRect { NXRect b; [super calcCellSize:theSize inRect:aRect]; [[self controlView] getBounds:&b]; theSize->width = b.size.width; return self; } - drawInside:(const NXRect *)cellFrame inView:controlView { int i, count; if([[self font] screenFont]) { [[[self font] screenFont] set]; } else { [[self font] set]; } /* erase the cell */ PSsetgray((cFlags1.state || cFlags1.highlighted) ? NX_WHITE : NX_LTGRAY); NXRectFill(cellFrame); /* draw the individual tokens */ count = [textTokens count]; for(i=0; i<count; i++) { [self _drawToken:(RZTextToken *)[textTokens objectAt:i] inside:cellFrame inView:controlView]; } #if BORDER /* all drawing from now on will be in dark gray */ PSsetgray(NX_DKGRAY); /* draw the two dark gray lines above and below the cell */ if (cFlags1.state || cFlags1.highlighted) { NXRect rectArray[2]; /* * draw 1-pixel tall rectangles instead of lines (this is faster than * PSmoveto(); PSlineto()). */ NXSetRect(&(rectArray[0]), NX_X(cellFrame), NX_Y(cellFrame), NX_WIDTH(cellFrame), 1.0); NXSetRect(&(rectArray[1]), NX_X(cellFrame), NX_MAXY(cellFrame) - 1.0, NX_WIDTH(cellFrame), 1.0); /* using NXRectFillList is faster than separate calls to NXRectFill */ NXRectFillList(rectArray, 2); } #endif return self; } - highlight:(const NXRect *)cellFrame inView:controlView lit:(BOOL)flag { if (cFlags1.highlighted != flag) { cFlags1.highlighted = flag; [self drawInside:cellFrame inView:controlView]; } return self; } /*** manipulating tabs ***/ - addProportionalTab:(float)position { return [self addProportionalTab:position min:0.0 max:0.0]; } - addProportionalTab:(float)position min:(float)minPos max:(float)maxPos { id aTab = [[RZTabStop alloc] initProportional:position min:minPos max:maxPos]; [self _addTab:aTab]; return self; } - addFixedTab:(float)position { id aTab = [[RZTabStop alloc] initFixed:position]; [self _addTab:aTab]; return self; } - clearTabs { if(tabStops) { [tabStops freeObjects]; } return self; } /*** manipulating text tokens ***/ - setText:(const char *)format at:(unsigned)index font:(char)font color:(char)color, ... { va_list args; static char buf[1024]; va_start(args, format); vsprintf(buf, format, args); [self _addText:[[RZTextToken alloc] initText:buf at:index font:font color:color]]; return self; } - setText:(const char *)format at:(unsigned)index, ... { va_list args; static char buf[1024]; va_start(args, format); vsprintf(buf, format, args); [self _addText:[[RZTextToken alloc] initText:buf at:index]]; return self; } - setText:(const char *)format at:(unsigned)index font:(char)font, ... { va_list args; static char buf[1024]; va_start(args, format); vsprintf(buf, format, args); [self _addText:[[RZTextToken alloc] initText:buf at:index font:font color:0]]; return self; } - setText:(const char *)format at:(unsigned)index color:(char)color, ... { va_list args; static char buf[1024]; va_start(args, format); vsprintf(buf, format, args); [self _addText:[[RZTextToken alloc] initText:buf at:index font:0 color:color]]; return self; } - clearText { if(textTokens) { [textTokens freeObjects]; } return self; } /*** manipulating icons ***/ - setImageNamed:(const char *)name at:(unsigned)index { [self _addText:[[RZTextToken alloc] initImage:name at:index]]; return self; } /*** archiving ***/ - write:(NXTypedStream *)ts { [super write:ts]; NXWriteTypes(ts, "fff@@", &ascender, &descender, &lineHeight, &tabStops, &textTokens); return self; } - read:(NXTypedStream *)ts { [super read:ts]; NXReadTypes(ts, "fff@@", &ascender, &descender, &lineHeight, &tabStops, &textTokens); return self; } @end @implementation RZBrowserCell(Private) - _addTab:(RZTabStop *)aTab { if(!tabStops) { tabStops = [[RZRefCountedList alloc] init]; } [tabStops addObject:aTab]; return self; } - _addText:(RZTextToken *)aText { int i; if(!textTokens) { textTokens = [[RZSortedList alloc] init]; } /* remove any tokens at the same index */ for(i=0; i<[textTokens count]; i++) { if([(RZTextToken *)[textTokens objectAt:i] position] == [aText position]) { [[textTokens removeObjectAt:i] free]; } } [textTokens addObject:aText]; return self; } - _drawToken:(RZTextToken *)token inside:(const NXRect *)cellFrame inView:controlView { static id textCell = nil; switch([token isText]) { case YES : { // text NXRect rect = *cellFrame; RZTabStop *thisStop, *nextStop; float thisStopPos, nextStopPos; if(!textCell) { textCell = [[TextFieldCell alloc] init]; [textCell setWrap:NO]; } [textCell setFont:[self font]]; thisStop = [tabStops objectAt:[token position]]; nextStop = [tabStops objectAt:([token position] + 1)]; if([thisStop fixed]) { thisStopPos = [thisStop position]; if(thisStopPos < 0.0) { thisStopPos += NX_WIDTH(cellFrame); } } else { thisStopPos = [thisStop position] * NX_WIDTH(cellFrame); if(([thisStop max] > 0.0) && (thisStopPos > [thisStop max])) { thisStopPos = [thisStop max]; } if(thisStopPos < [thisStop min]) { thisStopPos = [thisStop min]; } } if(nextStop) { if([nextStop fixed] ) { nextStopPos = [nextStop position]; if(nextStopPos < 0.0) { nextStopPos += NX_WIDTH(cellFrame); } } else { nextStopPos = [nextStop position] * NX_WIDTH(cellFrame); if(([nextStop max] > 0.0) && (nextStopPos > [nextStop max])) { nextStopPos = [nextStop max]; } if(nextStopPos < [nextStop min]) { nextStopPos = [nextStop min]; } } } else { nextStopPos = 0.0; } /* move to the correct tab position */ if(nextStopPos > 0.0) { NX_WIDTH(&rect) = nextStopPos - thisStopPos; } else { NX_WIDTH(&rect) -= thisStopPos; } NX_X(&rect) = thisStopPos; // NX_Y(&rect) += descender - 1; /* set the gray level */ switch([token color]) { default : case 0 : [textCell setTextGray:NX_BLACK]; break; case 1 : [textCell setTextGray:NX_DKGRAY]; break; case 2 : case 3 : if(cFlags1.state || cFlags1.highlighted) { [textCell setTextGray:NX_LTGRAY]; } else { [textCell setTextGray:NX_WHITE]; } break; } /* set the font */ { id newFont; char buf[128]; switch([token font]) { default : case 0 : sprintf(buf, "%s", [[self font] familyName]); newFont = [[Font newFont:buf size:[[self font] pointSize]] screenFont]; break; case 1 : sprintf(buf, "%s-Bold", [[self font] familyName]); newFont = [[Font newFont:buf size:[[self font] pointSize]] screenFont]; break; case 2 : sprintf(buf, "%s-Oblique", [[self font] familyName]); newFont = [[Font newFont:buf size:[[self font] pointSize]] screenFont]; break; case 3 : sprintf(buf, "%s-BoldOblique", [[self font] familyName]); newFont = [[Font newFont:buf size:[[self font] pointSize]] screenFont]; break; } [textCell setFont:newFont]; } [textCell setStringValue:(char *)[[token data] string]]; [textCell drawInside:&rect inView:controlView]; break; } case NO : { // icon float thisStopPos; RZTabStop *thisStop = [tabStops objectAt:[token position]]; NXPoint p = cellFrame->origin; NXSize imageSize; if([thisStop fixed]) { thisStopPos = [thisStop position]; if(thisStopPos < 0.0) { thisStopPos += NX_WIDTH(cellFrame); } } else { thisStopPos = [thisStop position] * NX_WIDTH(cellFrame); if(([thisStop max] > 0.0) && (thisStopPos > [thisStop max])) { thisStopPos = [thisStop max]; } if(thisStopPos < [thisStop min]) { thisStopPos = [thisStop min]; } } [[token data] getSize:&imageSize]; p.x += thisStopPos; p.y += NX_HEIGHT(cellFrame) - (NX_HEIGHT(cellFrame) - imageSize.height) / 2.0; [[token data] composite:NX_SOVER toPoint:&p]; break; } } return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.