This is ToyViewEvent.m in view mode; [Download] [Up]
#import "ToyView.h" #import <dpsclient/wraps.h> #import <dpsclient/event.h> #import <appkit/publicWraps.h> #import <appkit/NXImage.h> #import <appkit/NXBitmapImageRep.h> #import <appkit/Application.h> #import <appkit/NXCursor.h> #import <appkit/TextField.h> #import <stdlib.h> #import "PrefControl.h" #define CrossCursor "cross.tiff" static NXCursor *xCursor = nil; static BOOL originUpperLeft = NO; @implementation ToyView (EventHandling) + cursor { if (!xCursor) { NXPoint spot; xCursor = [NXCursor newFromImage:[NXImage newFromSection:CrossCursor]]; spot.x = 7.0; spot.y = 7.0; [xCursor setHotSpot:&spot]; } return xCursor; } + (BOOL)setOriginUpperLeft:(BOOL)flag { BOOL oldflag = originUpperLeft; originUpperLeft = flag; return oldflag; } - (BOOL)acceptsFirstResponder { return YES; } - (BOOL)acceptsFirstMouse { return YES; } - resetCursorRects { NXRect visible; if ([self getVisibleRect:&visible]) [self addCursorRect:&visible cursor:xCursor]; return self; } /* Local Method */ - drawDraggedLine: (NXCoord)x : (NXCoord)y : (int)dx : (int)dy { char buf[20], points[64]; int y1, y2; if (originUpperLeft) { y1 = curSize.height - y - dy; y2 = curSize.height - y - 1; }else { y1 = y, y2 = y + dy - 1; } sprintf(points, "%d x %d (%d, %d : %d, %d)", dx, dy, (int)x, y1, (int)x + dx - 1, y2); [commText setStringValue: points]; // already 'lockFocus'ed PSnewinstance(); PSsetinstance(YES); PSsetlinewidth(0.0); PSsetgray(0.1667); PSrectstroke(x, y+1, dx-1, dy-1); /* Why +1 ?? */ if ( dx >= 18 && dy >= 10 ) { sprintf(buf, "%d x %d", dx, dy); PSmoveto(x+1, y+2); PSselectfont("Times-Roman", 12.0); PSshow(buf); } PSsetinstance(NO); NXPing(); return self; } - clearDraggedLine { NXSize *sz = &selectRect.size; if (sz->width > 0.0 || sz->height > 0.0) { [self lockFocus]; PSnewinstance(); [self unlockFocus]; sz->width = 0.0; sz->height = 0.0; [commText setStringValue: comInfo->memo]; } return self; } - setDraggedLine: sender { NXSize *sz = &selectRect.size; if (sz->width > 0.0 && sz->height > 0.0) { [self lockFocus]; [self drawDraggedLine: selectRect.origin.x : selectRect.origin.y : sz->width : sz->height]; [self unlockFocus]; } return self; } - rewriteComment { [commText setStringValue: comInfo->memo]; return self; } #define DRAG_MASK (NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK) #define PRESS_MASK (NX_MOUSEUPMASK|NX_MOUSEDOWNMASK) /* Local Method */ - mousePress: (int)count { NXRect rect; if (!comInfo->alpha) return self; if (count <= 1) { if (backgray == 1.0) return self; backgray = 1.0; }else if (count > 3) backgray = 0.0; else backgray = (4 - count) / 3.0; // Double-click = Light Gray, Triple click = Dark Gray rect.origin.x = rect.origin.y = 0; rect.size = curSize; [self lockFocus]; [self drawSelf:&rect : 1]; [self unlockFocus]; [window flushWindow]; return self; } /* Code based on pCD.app (H. Danisch & D. Phillips) */ - mouseDown:(NXEvent *)event { NXPoint p, start, lowerleft; BOOL altDrag = NO, sftDrag = NO; int oldMask, cn; int xn = 0, yn = 0, xs, ys; [self mousePress: (cn = event->data.mouse.click)]; if (cn > 1) return self; oldMask = [window addToEventMask:DRAG_MASK]; p = event->location; [self convertPoint:&p fromView:nil]; /* View based point */ if (p.x < 0.0) p.x = 0.0; else if (p.x >= curSize.width) p.x = curSize.width - 1; p.y--; if (p.y < 0.0) p.y = 0.0; else if (p.y > curSize.height) p.y = curSize.height - 1; start.x = (int)p.x; start.y = (int)p.y; if (NX_ALTERNATEMASK & event->flags) altDrag = YES; [self lockFocus]; PSnewinstance(); PSsetinstance(YES); event = [NXApp getNextEvent:DRAG_MASK]; while( event->type != NX_MOUSEUP ) { if (NX_ALTERNATEMASK & event->flags) altDrag = YES; if (NX_SHIFTMASK & event->flags) sftDrag = YES; p = event->location; [self convertPoint:&p fromView:nil]; if (p.x < 0.0) p.x = 0.0; else if (p.x >= curSize.width) p.x = curSize.width - 1; p.y--; if (p.y < 0.0) p.y = 0.0; else if (p.y > curSize.height) p.y = curSize.height - 1; if (p.x > start.x) xn = (int)p.x - start.x + 1, xs = 1; else xn = start.x - (int)p.x + 1, xs = -1; if (p.y > start.y) yn = (int)p.y - start.y + 1, ys = 1; else yn = start.y - (int)p.y + 1, ys = -1; if (altDrag) { if (xn < yn) yn = xn; else xn = yn; } if (sftDrag) { xn = (xn + 1) & ~3; yn = (yn + 1) & ~3; } p.x = start.x + (xn-1)*xs; p.y = start.y + (yn-1)*ys; lowerleft.x = (start.x < p.x) ? start.x : p.x; lowerleft.y = (start.y < p.y) ? start.y : p.y; [self drawDraggedLine: lowerleft.x : lowerleft.y : xn : yn]; event = [NXApp getNextEvent:DRAG_MASK]; } [self unlockFocus]; selectRect.origin.x = lowerleft.x; selectRect.origin.y = lowerleft.y; selectRect.size.width = xn; selectRect.size.height = yn; if (xn == 0 && yn == 0) /* only click */ [commText setStringValue: comInfo->memo]; else if (xn < 3 && yn < 3) /* Too small area */ [self clearDraggedLine]; [window flushWindow]; [window setEventMask:oldMask]; return self; } - selectAll:sender { [self clearDraggedLine]; selectRect.size = curSize; selectRect.origin.x = selectRect.origin.y = 0.0; [self setDraggedLine: sender]; return self; } - copy:sender { NXStream *st; NXBitmapImageRep *bm; int i = 0; const char *types[2]; id pb = [Pasteboard new]; if (selectRect.size.width < 1.0 || selectRect.size.height < 1.0) { NXBeep(); return self; } // note that "owner:" in the following can not be "self", or the // id of anything else which might be freed inbetween "Copy" // operations. types[i++] = NXTIFFPboardType; [pb declareTypes:types num:i owner:NXApp]; [self lockFocus]; bm = [[NXBitmapImageRep alloc] initData:NULL fromRect:&selectRect]; [self unlockFocus]; st = NXOpenMemory(NULL, 0, NX_WRITEONLY); [bm writeTIFF:st]; [pb writeType:NXTIFFPboardType fromStream:st]; NXCloseMemory(st, NX_FREEBUFFER); [bm free]; return self; } - drawSelf:(NXRect *)r :(int) count { NXSize *sz; if (comInfo->alpha) { PSsetgray(backgray); NXRectFill(r); [image composite:NX_SOVER fromRect:r toPoint:&(r->origin)]; }else [image composite:NX_COPY fromRect:r toPoint:&(r->origin)]; sz = &selectRect.size; if (sz->width > 0.0 && sz->height > 0.0) [self perform:@selector(setDraggedLine:) with:self afterDelay:30 cancelPrevious:YES]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.