This is Glyph.m in view mode; [Download] [Up]
#pragma .h #import <objc/Object.h> #pragma .h #import <appkit/graphics.h> #pragma .h struct gFlags #pragma .h { unsigned isRoot: 1 ; #pragma .h unsigned isTarget: 1 ; #pragma .h unsigned noDraw: 1 ; } ; #import "Glyph.h" #import "Terminator.h" #import <dpsclient/psops.h> #import <appkit/Application.h> @implementation Glyph: Object { @public NXRect frame ; Glyph *is, *then, *ancestor ; // these belong as a bitstructure struct gFlags flags ; char iam[20] ; } - ancestor ; { return ancestor ; } - ancestor: aGlyph ; { return ancestor = aGlyph ; } -convertFromAncestor: (NXPoint *) aPnt ; // Convert aPnt from my ancestor's coord system to // my own. Does nothing if I am the root { if(!flags.isRoot) { aPnt->x -= frame.origin.x ; aPnt->y -= frame.origin.y ; } return self ; } -convertFromRootGlyph: (NXPoint *) aPnt ; // Convert aPnt from rootGlyph's coord system // to my coord system. { Glyph *aGlyph ; aGlyph = self ; while(!aGlyph->flags.isRoot) { aPnt->x -= aGlyph->frame.origin.x ; aPnt->y -= aGlyph->frame.origin.y ; aGlyph = aGlyph->ancestor ; if([aGlyph isTerminator]) { [NXApp printf: "from oops\n"] ; return self ; } } return self ; } -convertToAncestor: (NXPoint *) aPnt ; // Convert aPnt from my coord system to that // of my ancestor. Does nothing if I am the // rootGlyph { if(!flags.isRoot) { aPnt->x += frame.origin.x ; aPnt->y += frame.origin.y ; } return self ; } -convertToRootGlyph: (NXPoint *) aPnt ; // Convert aPnt from my coord system // to that of the rootGlyph. { Glyph *aGlyph ; aGlyph = self ; while(!aGlyph->flags.isRoot) { aPnt->x += aGlyph->frame.origin.x ; aPnt->y += aGlyph->frame.origin.y ; aGlyph = aGlyph->ancestor ; if([aGlyph isTerminator]) { [NXApp printf: "to oops\n"] ; return self ; } } return self ; } - display: (const NXRect *) aRect ; { // I traverses a glist recursively, // translating coord systems and calling // drawself as needed. I only draw if // my frame intersects visRect, which // must be in my ancestor's coord system. // If I am the target: I don't translate... // the target's origin is 0.0 with // respect to the ground view // it is drawing into. // If noDraw, then I don't draw myself or // any of my subGlyphs. This is used to prevent // the target glyph from drawing into the bGrnd. if(NXIntersectsRect(aRect,&frame)) { NXRect bRect, bounds ; bRect.size.width = aRect->size.width ; bRect.size.height = aRect->size.height ; bounds.origin.x = bounds.origin.y = 0.0 ; bounds.size.width = frame.size.width ; bounds.size.height = frame.size.height ; PSgsave() ; if(!flags.isTarget) { PStranslate(frame.origin.x, frame.origin.y) ; bRect.origin.x = aRect->origin.x - frame.origin.x ; bRect.origin.y = aRect->origin.y - frame.origin.y ; } else bRect.origin.x = bRect.origin.y = 0.0 ; NXIntersectionRect(&bounds,&bRect) ; // don't allow drawing NXRectClip(&bRect) ; // outside of my frame or interRect if(!flags.noDraw) { [self drawSelf: &bRect] ; [is display: &bRect] ; } PSgrestore() ; } [then display: aRect] ; return self ; } - drawSelf: (NXRect *) aRect ; { // draw my image into whatever is // currently focused. Only that part // of the image intersecting aRect, in // my coord system, needs to be drawn. if(flags.isRoot) { PSsetgray(0.8) ; PSrectfill(aRect->origin.x,aRect->origin.y, aRect->size.width,aRect->size.height) ; return self ; } PSsetgray(0.0) ; PSmoveto(0.0,0.0) ; PSlineto(0.0,frame.size.height) ; PSlineto(frame.size.width,frame.size.height); PSlineto(frame.size.width,0.0) ; PSlineto(0.0,0.0) ; PSlineto(frame.size.width,frame.size.height) ; PSstroke() ; return self ; } - enlist: (Glyph *) aGlyt ; { // I am a Glist ; link aGlyt into myself, // return the head of the list aGlyt->ancestor = ancestor ; if([aGlyt precedes: self]) // link before me { aGlyt->then = self ; return aGlyt ; } then = [then enlist: aGlyt] ;// ask my neighbour to enlist it return self ; } - hitTest: (NXPoint *) aPnt ; // return id of deepest, leftmost glyph in hierarchy // which contains aPnt. aPnt is in my superview's coordinate // system. Returns nil if no appropriate glyph can be // found (i.e. not in my frame, nor any of my // Glist's frames). { if(NXPointInRect(aPnt,&frame)) { id deeperHit ; NXPoint thePnt ; thePnt.x = aPnt->x - frame.origin.x ; // thePnt = aPnt thePnt.y = aPnt->y - frame.origin.y ; // in my coord system if(deeperHit = [is hitTest: &thePnt]) return deeperHit ; else return self ; } return [then hitTest: aPnt] ; } - (char *) iam ; { return iam ; } - iam: (char *) str ; { strcpy(iam,str) ; } - init ; { // make sure we are terminated [super init]; is = then = ancestor = [Terminator new] ; // cook up a temporary frame frame.origin.x = frame.origin.y = 0.0 ; frame.size.width = frame.size.height = 50.0 ; return self; } - is ; { return is ; } - is: aGlyph ; { return is = aGlyph ; } - (BOOL) isTerminator ; { return NO ; } - moveTo:(float) x :(float)y ; { // move my origin to aPnt in my ancestor's // coord system. frame.origin.x = x ; frame.origin.y = y ; return self ; } - plant: (Glyph *) aGlyt ; { // link aGlyt as a subGlyph of myself, i.e. // "plant" it as a branch of my subtree aGlyt->ancestor = self ; if([is isTerminator]) is = aGlyt ; else is = [is enlist: aGlyt] ; return self ; } - (BOOL) precedes: (Glyph *) aGlyph ; { // answer YES iff aGlyph should come before // me in my Glist. Defaults to left-to-right order if([aGlyph isTerminator] || (aGlyph->frame.origin.x > frame.origin.x)) return YES ; else return NO ; } - sizeTo: (float)width : (float)height ; { // changes my size, but does nothing about // redisplaying it! frame.size.width = width ; frame.size.height = height ; return self ; } - then ; { return then ; } - then: aGlyph ; { return then = aGlyph ; } - test: (int) anInt ; { // remove when you are satisfied... char *name = "none" ; if(iam[0] != '\0') name = iam ; [NXApp printf: "(%d %s %s %s %s)\n",anInt,name,[is iam], [then iam], [ancestor iam]] ; [is test: anInt + 1] ; [then test: anInt] ; return self ; } - unlink ; { // unlink myself (as a Glyt) from the TTree I am a part of. // Note: I must be part of a TTree, else bomb! if(flags.isRoot) // can't unlink the root glyph! return self ; if(ancestor->is == self) // the simple case... ancestor->is = then ; else { Glyph *cursor = ancestor->is ; while(cursor->then != self) // find predecessor cursor = cursor->then ; cursor->then = then ; } ancestor = then = [Terminator new] ; return self ; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.