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.