This is TreeView.m in view mode; [Download] [Up]
#import <foundation/foundation.h> #import <foundation/NSArchiver.h> #import "TreeView.h" #import "MiscDiagramTree.h" #import "MiscUserPath.h" #import "ScrollViewExtensions.h" #import "uwFoundationAdds.h" static const char *opSeparator = "\n----------------------------------------------------------------------\n"; static id createMiscTree(NXStream *stream); static int getNextNodeLabel(char *buffer, int n, NXStream *stream); @implementation TreeView - initFrame:(const NXRect *)frameRect { MiscLayoutTree *l, *r, *ll, *lr; [super initFrame:frameRect]; [self setFlipped:YES]; [window makeKeyAndOrderFront:nil]; treeDiagram = [[MiscDiagramTree alloc] init]; l = [MiscDiagramTree tree]; r = [MiscDiagramTree tree]; ll = [MiscDiagramTree tree]; lr = [MiscDiagramTree tree]; [l addBranch:ll]; [l addBranch:lr]; [treeDiagram addBranch:l]; [treeDiagram addBranch:r]; [treeDiagram setLayoutType:MiscVerticalTreeType]; [treeDiagram layout]; [self posTree]; linePath = [[MiscUserPath alloc] init]; [treeDiagram fillLines:linePath]; return self; } - free { [treeDiagram release]; [linePath release]; return [super free]; } - (void)posTree { NSRect r; NSPoint oldPos; NSPoint newPos; r = [treeDiagram branchBounds]; oldPos = [treeDiagram pos]; newPos.x = (bounds.size.width - r.size.width) / 2 + (oldPos.x - r.origin.x); newPos.y = (bounds.size.height - r.size.height) / 2 + (oldPos.y - r.origin.y); [treeDiagram setPos:newPos]; [linePath resetFill]; [treeDiagram fillLines:linePath]; } - sizeTo:(NXCoord)width :(NXCoord)height { [super sizeTo:width :height]; [self posTree]; return self; } - drawSelf:(const NXRect *)r :(int)count { PSsetgray(NX_WHITE); NXRectFill(&bounds); PSsetgray(NX_BLACK); if([treeDiagram needsUpdateLayout]){ [treeDiagram layout]; [linePath resetFill]; [treeDiagram fillLines:linePath]; } [linePath send:dps_ustroke cached:YES]; PSsetgray(NX_WHITE); [treeDiagram drawFill]; PSsetgray(NX_BLACK); [treeDiagram drawOutline]; [treeDiagram drawCellsInView:self attachments:NO]; return self; } - depthFirst:sender { NSEnumerator *enumerator; id node; [scrollView sprintf:opSeparator]; enumerator = [treeDiagram depthEnumerator]; while(node = [enumerator nextObject]) [scrollView sprintf:"%s\n",[[node label] cString]]; return self; } - breadthFirst:sender { NSEnumerator *enumerator; id node; [scrollView sprintf:opSeparator]; enumerator = [treeDiagram breadthEnumerator]; while(node = [enumerator nextObject]) [scrollView sprintf:"%s\n",[[node label] cString]]; return self; } - open:sender { const char *const *files; const char *directory; NSString *path; id unarchivedObject; const char *const allowedType[2] = {"owood", NULL}; id openpanel = [[OpenPanel new] allowMultipleFiles:NO]; BOOL result = NO; if([openpanel runModalForTypes:allowedType]){ files = [openpanel filenames]; directory = [openpanel directory]; if(files && *files){ path = [NSString stringWithFormat:@"%s/%s",directory,*files]; unarchivedObject = [NSUnarchiver unarchiveObjectWithFile:path]; if(unarchivedObject){ result = YES; [treeDiagram release]; treeDiagram = [unarchivedObject retain]; } } [scrollView sprintf:opSeparator]; if(result) [scrollView sprintf:"Unarchiving succesful\n"]; else [scrollView sprintf:"Unarchiving not succesful\n"]; } if(result) [self display]; return self; } - save:sender { id savepanel; NSString *path; BOOL result; savepanel = [SavePanel new]; [savepanel setRequiredFileType:"owood"]; if([savepanel runModal]){ path = [NSString stringWithCString:[savepanel filename]]; result = [NSArchiver archiveRootObject:treeDiagram toFile:path]; [scrollView sprintf:opSeparator]; if(result) [scrollView sprintf:"Archiving succesful\n"]; else [scrollView sprintf:"Archiving not succesful\n"]; } return self; } - openMMA:sender { const char *fileName; id openpanel = [OpenPanel new]; NXStream *aStream; const char *const fileTypes[] = {"tree", NULL}; id unarchivedObject; [openpanel allowMultipleFiles:NO]; if([openpanel runModalForTypes:fileTypes]){ fileName = [openpanel filename]; if((aStream = NXMapFile(fileName, NX_READONLY)) == NULL){ NXRunAlertPanel(NULL, "File %s could not be opened for reading.", NULL, NULL, NULL, fileName); return nil; } unarchivedObject = createMiscTree(aStream); NXCloseMemory(aStream, NX_FREEBUFFER); if(unarchivedObject){ [treeDiagram release]; treeDiagram = unarchivedObject; [self posTree]; [self display]; } return self; } return nil; } - vertical:sender { [treeDiagram setLayoutType:MiscVerticalTreeType]; [self posTree]; [self display]; return self; } - horizontal:sender { [treeDiagram setLayoutType:MiscHorizontalTreeType]; [self posTree]; [self display]; return self; } @end static int getNextNodeLabel(char *buffer, int n, NXStream *stream) { int c, i = 0, blanks = 0; int tnums = 0; while(((c = NXGetc(stream)) != EOF) && (i < n-1) && (c == ' ' || c == '\t')){ if(c == ' '){ blanks++; if(blanks == 3){ blanks = 0; tnums++; } } else tnums++; } buffer[i++] = c; while(((c = NXGetc(stream)) != EOF) && (i < n-1)){ if(c == '\n') break; else buffer[i++] = c; } if(c == EOF) tnums = -1; buffer[i] = 0; return tnums; } static id createMiscTree(NXStream *stream) { int tnums, lastTNums = 0, i, tags = -1; id lastNode, node; char labelBuffer[MAXPATHLEN]; tnums = getNextNodeLabel(labelBuffer,MAXPATHLEN,stream); lastNode = node = nil; tnums = getNextNodeLabel(labelBuffer,MAXPATHLEN,stream); while(tnums != -1){ if(labelBuffer){ node = [[MiscDiagramTree alloc] initWithLabel:[NSString stringWithCString:labelBuffer] shapeType:MiscRectangleShapeType]; [(MiscLayoutTree *)node setTag:++tags]; if(lastNode){ if(lastTNums >= tnums) for(i = 0; i <= lastTNums - tnums && [lastNode parent]; i++, lastNode = [lastNode parent]); [lastNode addBranch:node]; } lastNode = node; lastTNums = tnums; } tnums = getNextNodeLabel(labelBuffer,MAXPATHLEN,stream); } while([node parent]) node = [node parent]; return node; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.