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 ;
}
@endThese are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.