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.