This is PolyView.m in view mode; [Download] [Up]
/*****************************************************************************/ /* PolyView.m */ /* interface file for PolyView class of RandPoly application */ /* Carl F. Sutter September 1989 */ /* RandPoly draws polygons continuously in the view. */ /* Use of the Alpha channel is accomplished by drawing first in a bitmap, */ /* and then compositing to the screen. Drawing in the icon and limiting */ /* window resizing are also shown. DPSDoUserPath is used for polygons. */ /*****************************************************************************/ #import "PolyView.h" #import "Animator.h" #import <appkit/appkit.h> @implementation PolyView // newFrame - create an instance of PolyView, and initialize it + newFrame:(NXRect *)rect { self = [super newFrame:rect]; nNumCorners = 5; [self createOpsArray]; bAlpha = YES; flAlpha = 1.0; bDrawInIcon = NO; nFill = FILL_FILL; nBorder = BORDER_YES; srandom( time( 0 ) ); /* randomize the random number generator */ timer = [Animator newChronon:0.0 adaptation:0.0 target:self action:(SEL)"drawPolygons:" autoStart:YES eventMask:NX_ALLEVENTS]; bmpPoly = [Bitmap newSize:bounds.size.width :bounds.size.height type:NX_UNIQUEBITMAP]; return( self ); } /* newFrame 8/16/89 CFS */ // appDidInit - Delegate message sent after application is set up. // The Views's window instance variable is now set, so it's size can be // found. Now find the minimum window size for a view of 1x1, since the // bounds instance variable is used to size each polygon. - appDidInit:(id)sender { NXRect nxrWinFrame; [window getFrame:&nxrWinFrame]; minWindowSize.width = nxrWinFrame.size.width - bounds.size.width + 1.0; minWindowSize.height = nxrWinFrame.size.height - bounds.size.height + 1.0; return( self ); } /* appDidInit 8/16/89 CFS */ // windowWillResize - Delegate message sent from main window. // Prevent window from getting so small that the view size is zero. - windowWillResize:sender toSize:(NXSize *)frameSize { frameSize->width = MAX( frameSize->width, minWindowSize.width ); frameSize->height = MAX( frameSize->height, minWindowSize.height ); return( self ); } /* windowWillResize 9/14/89 CFS */ // windowDidResize - Delegate message sent from main window. // After sizing, free and re-allocate image storage bitmap. - windowDidResize:sender; { [bmpPoly resize:bounds.size.width :bounds.size.height]; return( self ); } /* windowDidResize 9/14/89 CFS */ // These are the outlet initialization methods made by the IB - setCornersDisplay:anObject { cornersDisplay = anObject; return( self ); } - setAlphaDisplay:anObject; { alphaDisplay = anObject; return( self ); } - setDelayDisplay:anObject; { delayDisplay = anObject; return( self ); } // setCorners - set the number of corners for the following polygons - setCorners:sender { nNumCorners = MIN( MAXCORNERS, MAX( 2, [sender intValue]) ); /* limit value */ [cornersDisplay setIntValue:nNumCorners]; [self createOpsArray]; return( self ); } // setAlpha - set the alpha value for the next and following polygons - setAlpha:sender { flAlpha = [sender floatValue]; [alphaDisplay setFloatValue:flAlpha]; return( self ); } /* setAlpha 9/14/89 CFS */ // setDelay - set the delay time between polygons // to do this, free the current Animator instance and make a new one - setDelay:sender; { double dDelay; [timer free]; dDelay = [sender doubleValue]; [delayDisplay setDoubleValue:dDelay]; timer = [Animator newChronon:dDelay adaptation:0.0 target:self action:(SEL)"drawPolygons:" autoStart:YES eventMask:NX_ALLEVENTS]; return( self ); } /* setDelay 9/14/89 CFS */ // setBAlpha - set whether or not to use the bitmap and compositing - setBAlpha:sender; { bAlpha = !bAlpha; return( self ); } /* setBAlpha 9/15/89 CFS */ // drawInTheIcon - set whether to draw polygons in the icon too - drawInTheIcon:sender { bDrawInIcon = !bDrawInIcon; return( self ); } // setFill - set the fill type - setFill:sender { nFill = [[sender selectedCell] tag]; } /* setFill 9/28/89 CFS */ // setBorder - set whether to draw a border or not - setBorder:sender; { nBorder = [[sender selectedCell] tag]; } /* setFill 9/28/89 CFS */ // drawPolygons - draw polygons until any other events occur - drawPolygons:(id)sender { Window *winIcon; // window of Applications icon NXRect nxrIcon; // frame of icon window [self lockFocus]; /* this do loop prevents locking and unlocking the view focus while */ /* there are no pending events. This saves time, since locking is slow */ /* Note that turning alpha off, and icon-drawing off is fastest. */ do { if (bAlpha) { /* clear and draw a new polygon in the off-screen bitmap */ [bmpPoly lockFocus]; PScompositerect (0.0, 0.0, bounds.size.width, bounds.size.height, NX_CLEAR); [self drawOnePolygon:bounds]; [bmpPoly unlockFocus]; /* composite the polygon to the screen - the only way to use alpha */ [bmpPoly composite:NX_SOVER toPoint:&bounds.origin]; } else [self drawOnePolygon:bounds]; /* just draw one poly. to the screen */ if (bDrawInIcon) { /* get the icon window, it's size, and draw a poly in it's view */ winIcon = [NXApp appIcon]; [winIcon getFrame:&nxrIcon]; [[winIcon contentView] lockFocus]; [self drawOnePolygon:nxrIcon]; [winIcon flushWindow]; [[winIcon contentView] unlockFocus]; } [window flushWindow]; /* send main view buffer to the screen */ /* repeat if delay is zero, and no events are in the queue */ } while(([delayDisplay floatValue] == 0.0) && ![timer shouldBreak]); [self unlockFocus]; return( self ); } /* drawPolygons 9/20/89 CFS */ // Draw one polygon in the current focus // note: even when not compositing, the alpha value does have an effect on color - drawOnePolygon:(NXRect)nxrBounds { short bbox[4]; // bounding box short data[MAXCORNERS*2]; // Array of data points for user path int i; /* set up the bounding box array */ bbox[0] = nxrBounds.origin.x; bbox[1] = nxrBounds.origin.y; bbox[2] = nxrBounds.origin.x + nxrBounds.size.width; bbox[3] = nxrBounds.origin.y + nxrBounds.size.height; /* put random x and y coordinates in the data array */ for (i=0; i<nNumCorners; i++) { data[i * 2] = random() % (int)nxrBounds.size.width;; data[i * 2 + 1] = random() % (int)nxrBounds.size.height; } /* draw the new polygon */ PSsetgray( (float)random() / (float)RAND_MAX ); PSsetalpha( flAlpha ); if (nFill == FILL_FILL) DPSDoUserPath( data, nNumCorners*2, dps_short, ops, nNumCorners+1, bbox, dps_ufill ); if (nFill == FILL_EOFILL) DPSDoUserPath( data, nNumCorners*2, dps_short, ops, nNumCorners+1, bbox, dps_ueofill ); if (nBorder == BORDER_YES) { PSsetgray( NX_BLACK ); PSsetalpha( 1.0 ); /* opaque */ DPSDoUserPath( data, nNumCorners*2, dps_short, ops, nNumCorners+1, bbox, dps_ustroke ); } return( self ); } /* drawOnePolygon 9/28/89 CFS */ // createOpsArray - Create an ops[] array that has moveto as the first element and // a lineto per edge and finally a closepath. Everytime we change the number // of edges we need to fix this array. This array gets passed into // DPSDoUserPath as the array of PS operators... - createOpsArray { int i; ops[0] = dps_moveto; for (i=1; i<nNumCorners; i++) ops[i] = dps_lineto; ops[nNumCorners] = dps_closepath; } /* createOpsArray 9/28/89 CFS */ @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.