#import "PieceView.h" @interface PieceView (Private) - (void)draw:(NSImage *)theImage; - (void)moveCluster:(NSEvent *)theEvent; - (void)joinCluster:(NSEvent *)theEvent; @end @implementation PieceView #define DIST ((float)2) #define CLOSE(_v1, _v2) \ ((_v1) > (_v2) ? \ ((_v1) - (_v2) < DIST) : ((_v2) - (_v1) < DIST)) static id checkResult[2]; + (id *)checkCluster:(BTree *)theCluster dimX:(int)dimx dimY:(int)dimy { NSMutableArray *allLeaves = [theCluster leaves]; PieceView *piece, *refpiece; BOOL fail; int curleaf, refx, refy; NSPoint reforigin, origin; refpiece = [allLeaves objectAtIndex:0]; refx = [refpiece x]; refy = [refpiece y]; reforigin = [refpiece frame].origin; fail = NO; for(curleaf=1; curleaf<[allLeaves count]; curleaf++){ piece = (PieceView *) [allLeaves objectAtIndex:curleaf]; origin = [piece frame].origin; if(!CLOSE(reforigin.x+([piece x]-refx)*dimx, origin.x) || !CLOSE(reforigin.y+([piece y]-refy)*dimy, origin.y)){ fail = YES; break; } } [allLeaves release]; if(fail==YES){ checkResult[0] = refpiece; checkResult[1] = piece; return checkResult; } return NULL; } + (BTree *)doJoin:(BTree *)cl1 and:(BTree *)cl2 all:(NSMutableArray *)allClusters { BTree *newCluster; newCluster = [[BTree alloc] initWithPairFirst:cl1 andSecond:cl2]; [allClusters removeObject:cl1]; [allClusters removeObject:cl2]; [allClusters addObject:newCluster]; // NSLog(@"clusters: %u\n", [allClusters count]); [newCluster inorderWithPointer:(void *)newCluster sel:@selector(setCluster:)]; return newCluster; } static int count; - (id)initWithImage:(NSImage *)theImage dimX:(int)dimx dimY:(int)dimy loc:(NSPoint)theLoc posX:(int)posx outOf:(int)pxval posY:(int)posy outOf:(int)pyval left:(BTYPE)bleft right:(BTYPE)bright upper:(BTYPE)bupper lower:(BTYPE)blower { piece_width = dimx; piece_height = dimy; NSSize size = [theImage size]; NSRect iframe; int padding, shift; NSCachedImageRep *rep; tag = count++; done = NO; padding = ((int)(size.width))%PIECE_WIDTH; if(padding){ padding = PIECE_WIDTH-padding; } padleft = padding/2; padright = padding-padleft; padding = ((int)(size.height))%PIECE_HEIGHT; if(padding){ padding = PIECE_HEIGHT-padding; } padlower = padding/2; padupper = padding-padlower; iframe.origin.x = theLoc.x; // -BOUNDARY; iframe.origin.y = theLoc.y; // -BOUNDARY; iframe.size.width = PIECE_WIDTH +2*BOUNDARY; iframe.size.height = PIECE_HEIGHT+2*BOUNDARY; [super initWithFrame:iframe]; image = [[NSImage alloc] initWithSize:iframe.size]; complete = [[NSImage alloc] initWithSize:iframe.size]; x = posx; y = posy; px = pxval; py = pyval; left = bleft; right = bright; upper = bupper; lower = blower; clip = [NSBezierPath bezierPath]; [clip moveToPoint:NSMakePoint(BOUNDARY, BOUNDARY)]; if(left!=BORDER){ [clip relativeLineToPoint: NSMakePoint(0, PIECE_HEIGHT/2-OFFS)]; shift = (left==INNER ? BOUNDARY : -BOUNDARY); [clip relativeCurveToPoint: NSMakePoint(0, 2*OFFS) controlPoint1:NSMakePoint(shift, -OFFS) controlPoint2:NSMakePoint(shift, 3*OFFS)]; } [clip lineToPoint: NSMakePoint(BOUNDARY, PIECE_HEIGHT+BOUNDARY)]; if(upper!=BORDER){ [clip relativeLineToPoint: NSMakePoint(PIECE_WIDTH/2-OFFS, 0)]; shift = (upper==INNER ? -BOUNDARY : BOUNDARY); [clip relativeCurveToPoint: NSMakePoint(2*OFFS, 0) controlPoint1:NSMakePoint(-OFFS, shift) controlPoint2:NSMakePoint(3*OFFS, shift)]; } [clip lineToPoint: NSMakePoint(PIECE_WIDTH+BOUNDARY, PIECE_HEIGHT+BOUNDARY)]; if(right!=BORDER){ [clip relativeLineToPoint: NSMakePoint(0, -(PIECE_HEIGHT/2-OFFS))]; shift = (right==INNER ? -BOUNDARY : BOUNDARY); [clip relativeCurveToPoint: NSMakePoint(0, -2*OFFS) controlPoint1:NSMakePoint(shift, OFFS) controlPoint2:NSMakePoint(shift, -3*OFFS)]; } [clip lineToPoint: NSMakePoint(BOUNDARY+PIECE_WIDTH, BOUNDARY)]; if(lower!=BORDER){ [clip relativeLineToPoint: NSMakePoint(-(PIECE_WIDTH/2-OFFS), 0)]; shift = (lower==INNER ? BOUNDARY : -BOUNDARY); [clip relativeCurveToPoint: NSMakePoint(-2*OFFS, 0) controlPoint1:NSMakePoint(OFFS, shift) controlPoint2:NSMakePoint(-3*OFFS, shift)]; } [clip closePath]; [clip retain]; boundary = [NSBezierPath bezierPath]; [boundary moveToPoint:NSMakePoint(BOUNDARY, BOUNDARY)]; if(left==BORDER){ [boundary lineToPoint: NSMakePoint(BOUNDARY, PIECE_HEIGHT+BOUNDARY)]; } else{ [boundary moveToPoint: NSMakePoint(BOUNDARY, PIECE_HEIGHT+BOUNDARY)]; } if(upper==BORDER){ [boundary lineToPoint: NSMakePoint(PIECE_WIDTH+BOUNDARY, PIECE_HEIGHT+BOUNDARY)]; } else{ [boundary moveToPoint: NSMakePoint(PIECE_WIDTH+BOUNDARY, PIECE_HEIGHT+BOUNDARY)]; } if(right==BORDER){ [boundary lineToPoint: NSMakePoint(BOUNDARY+PIECE_WIDTH, BOUNDARY)]; } else{ [boundary moveToPoint: NSMakePoint(BOUNDARY+PIECE_WIDTH, BOUNDARY)]; } if(lower==BORDER){ [boundary lineToPoint: NSMakePoint(BOUNDARY, BOUNDARY)]; } else{ [boundary moveToPoint: NSMakePoint(BOUNDARY, BOUNDARY)]; } // [boundary closePath]; [boundary retain]; [self draw:theImage]; return self; } - setCluster:(BTree *)theCluster { cluster = theCluster; return self; } - (BTree *)cluster { return cluster; } - setDocument:(Document *)theDocument { doc = theDocument; return self; } - (Document *)document { return doc; } - (int)setDone:(int)dflag { int prev = done; if(prev!=dflag){ done = dflag; } return prev; } - (void)drawRect:(NSRect)aRect { [clip addClip]; [(done==YES ? complete : image) compositeToPoint:aRect.origin fromRect:aRect operation:NSCompositeCopy]; } - (void)draw:(NSImage *)theImage { NSRect imageRect = {{ 0, 0 }, [theImage size] }; NSRect pieceRect = {{ -padleft+x*PIECE_WIDTH, -padlower+y*PIECE_HEIGHT }, { PIECE_WIDTH, PIECE_HEIGHT}}; NSPoint dest; NSImage *imgs[2] = { image, complete }; int idx; for(idx=0; idx<2; idx++){ [imgs[idx] lockFocus]; pieceRect.origin.x -= BOUNDARY; pieceRect.origin.y -= BOUNDARY; pieceRect.size.width += 2*BOUNDARY; pieceRect.size.height += 2*BOUNDARY; pieceRect = NSIntersectionRect(imageRect, pieceRect); [clip addClip]; dest.x = padleft +BOUNDARY+pieceRect.origin.x-x*PIECE_WIDTH; dest.y = padlower+BOUNDARY+pieceRect.origin.y-y*PIECE_HEIGHT; [theImage compositeToPoint:dest fromRect:pieceRect operation:NSCompositeCopy]; if(!x && padleft){ [[NSColor blueColor] set]; PSrectfill(BOUNDARY, 0, padleft, PIECE_BD_HEIGHT); } if(x==px-1 && padright){ [[NSColor blueColor] set]; PSrectfill(BOUNDARY+PIECE_WIDTH-padright, 0, padright, PIECE_BD_HEIGHT); } if(!y && padlower){ [[NSColor blueColor] set]; PSrectfill(0, BOUNDARY, PIECE_BD_WIDTH, padlower); } if(y==py-1 && padupper){ [[NSColor blueColor] set]; PSrectfill(0, BOUNDARY+PIECE_HEIGHT-padupper, PIECE_BD_WIDTH, padupper); } NSBezierPath *lim = (idx==1 ? boundary : clip); [[NSColor redColor] set]; [lim setLineWidth:4]; [lim stroke]; [[NSColor greenColor] set]; [lim setLineWidth:2]; [lim stroke]; [imgs[idx] unlockFocus]; } } - (void)outline:(float *)delta { NSRect frame = [self frame]; PSgsave(); PStranslate(frame.origin.x+delta[0], frame.origin.y+delta[1]); [[NSColor blackColor] set]; [clip setLineWidth:4]; [clip stroke]; [[NSColor whiteColor] set]; [clip setLineWidth:2]; [clip stroke]; PSgrestore(); } - (void)showInvalid { NSColor *red = [NSColor redColor], *green = [NSColor greenColor]; [self lockFocus]; [green set]; PSsetlinewidth(6.0); PSmoveto(BOUNDARY, BOUNDARY); PSlineto(BOUNDARY+PIECE_WIDTH, BOUNDARY+PIECE_HEIGHT); PSmoveto(BOUNDARY, BOUNDARY+PIECE_HEIGHT); PSlineto(BOUNDARY+PIECE_WIDTH, BOUNDARY); PSstroke(); [red set]; PSsetlinewidth(4.0); PSmoveto(BOUNDARY, BOUNDARY); PSlineto(BOUNDARY+PIECE_WIDTH, BOUNDARY+PIECE_HEIGHT); PSmoveto(BOUNDARY, BOUNDARY+PIECE_HEIGHT); PSlineto(BOUNDARY+PIECE_WIDTH, BOUNDARY); PSstroke(); [[self window] flushWindow]; [self unlockFocus]; } - (void)bbox:(NSRect *)bbox { *bbox = NSUnionRect(*bbox, [self frame]); } - (BTYPE)left { return left; } - (BTYPE)right { return right; } - (BTYPE)upper { return upper; } - (BTYPE)lower { return lower; } - (int)tag { return tag; } - (void)shiftView:(float *)delta { NSRect cframe = [self frame]; cframe.origin.x += delta[0]; cframe.origin.y += delta[1]; [self setFrame:cframe]; [self setNeedsDisplay:YES]; } - (int)x { return x; } - (int)y { return y; } - (PTYPE)classifyPoint:(NSPoint)pt { NSPoint leftout, leftin, rightout, rightin, lowerout, lowerin, upperout, upperin; leftout.x = BOUNDARY/2; leftout.y = BOUNDARY+PIECE_HEIGHT/2; leftin.x = 3*BOUNDARY/2; leftin.y = BOUNDARY+PIECE_HEIGHT/2; rightout.x = BOUNDARY+PIECE_WIDTH+BOUNDARY/2; rightout.y = BOUNDARY+PIECE_HEIGHT/2; rightin.x = BOUNDARY+PIECE_WIDTH-BOUNDARY/2; rightin.y = BOUNDARY+PIECE_HEIGHT/2; lowerout.x = BOUNDARY+PIECE_WIDTH/2; lowerout.y = BOUNDARY/2; lowerin.x = BOUNDARY+PIECE_WIDTH/2; lowerin.y = 3*BOUNDARY/2; upperout.x = BOUNDARY+PIECE_WIDTH/2; upperout.y = BOUNDARY+PIECE_HEIGHT+BOUNDARY/2; upperin.x = BOUNDARY+PIECE_WIDTH/2; upperin.y = BOUNDARY+PIECE_HEIGHT-BOUNDARY/2; #define DELTA(p1, p2) ((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)) if(DELTA(pt, leftout)