This is DialView.m in view mode; [Download] [Up]
/*
* (C) 1990 by Adobe Systems Incorporated. All rights reserved.
*
* This file may be freely copied and redistributed as long as:
* 1) This entire notice continues to be included in the file,
* 2) If the file has been modified in any way, a notice of such
* modification is conspicuously indicated.
*
* PostScript, Display PostScript, and Adobe are registered trademarks of
* Adobe Systems Incorporated.
*
* ************************************************************************
* THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO CHANGE WITHOUT
* NOTICE, AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY ADOBE SYSTEMS
* INCORPORATED. ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY OR
* LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO WARRANTY OF ANY
* KIND (EXPRESS, IMPLIED OR STATUTORY) WITH RESPECT TO THIS INFORMATION,
* AND EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR PARTICULAR PURPOSES AND NONINFINGEMENT OF THIRD PARTY RIGHTS.
* ************************************************************************
*/
/*
* DialView.m
* Created by Ken Fromm
*
* This application draws an object in several ways. The first way draws
* with the help of the matrix operation rotate. The second draws with
* rotate and user paths. The third draws with basic wraps performing
* the calculations on the client side. The fourth draws with the
* calculated user paths placed in a buffer and sent to the server a
* single request. The fifth follows the same procedure as the previous
* method except that the user path is stored in the server and not
* resent each time.
*/
#import "DialView.h"
#import "DialViewWraps.h"
#import <appkit/Button.h>
#import <appkit/Control.h>
#import <appkit/Matrix.h>
#import <appkit/TextField.h>
#import <appkit/nextstd.h>
#import <math.h>
#import <dpsclient/wraps.h>
@implementation DialView
/* These definitions are for the names of the user path arrays in the
* server. Providing names like this is only to simplify the example. An
* optimized solution would probably use user objects and forego names
* altogether.
*/
static char *upath1 = {"upath1"};
static char *upath10 = {"upath10"};
static char *upath45 = {"upath45"};
static char *upath90 = {"upath90"};
/* Allocate a gstate and set clipping to NO. The gstate is allocated
* because we do not want to reset the individual drawing variables when
* the context is switched back to this view. The clipping is set to NO
* because the drawing methods do not need clipping so its a way to save
* display time.
*
* The dimensions of the dial are calculated. The bounds of the DialView
* is the starting point. Arrays to hold user path point and operator
* values are allocated.
*
* The PSWDefs() call sends some definitions used in the wraps to the
* interpreter. They will be available in the interpreter when the wraps
* call them.
*/
+ newFrame:(NXRect *) frm
{
self = [super newFrame:frm];
[self allocateGState];
[self setClipping:NO];
viewcenter.x = bounds.size.width/2;
viewcenter.y = bounds.size.height/2;
if (viewcenter.x > viewcenter.y)
maxdim = viewcenter.y - WIDCIRCBRD/2 - CIRCFF ;
else
maxdim = viewcenter.x - WIDCIRCBRD/2 -CIRCFF;
viewcenter.x += bounds.origin.x;
viewcenter.y += bounds.origin.y;
NX_MALLOC(pts, float, MAX_PTS);
NX_MALLOC(ops, char, MAX_OPS);
PSWDefs ();
[self setupUserPaths];
drawFlags.field = 0x80;
return self;
}
/* Free the gstate upon quitting. */
- free
{
if (pts)
NX_FREE(pts);
if (ops)
NX_FREE(ops);
[self freeGState];
return [super free];
}
/* Created by interface. Used to obtain the id's of objects that will
* be messaged. */
- setMatrixDegreeTypes:anObject
{
matrixDegreeTypes = anObject;
return self;
}
- setMatrixDisplayTimes:anObject
{
matrixDisplayTimes = anObject;
return self;
}
/* Calculate the start and end points and place in user path format. Send
* the user path to the server and define it in the server. Execute the
* user path for drawing. */
static void setupTrigUserPath(
pts, ops, x, y, startlen, endlen, deg, upathname)
float pts[];
char ops[];
float x, y, startlen, endlen, deg;
char *upathname;
{
int i , j, angle;
i = 4; j = 1;
for (angle = 0; angle < 360; angle += deg)
{
pts[i++] = x + (float) cos(angle * RADIANS) * startlen;
pts[i++] = y + (float) sin(angle * RADIANS) * startlen;
ops[j++] = dps_moveto;
pts[i++] = x + (float) cos(angle * RADIANS) * endlen;
pts[i++] = y + (float) sin(angle * RADIANS) * endlen;
ops[j++] = dps_lineto;
}
PSWDefineUserPath(pts, i, ops, j, upathname );
}
- setupUserPaths
{
pts[0] = bounds.origin.x;
pts[1] = bounds.origin.y;
pts[2] = bounds.origin.x + bounds.size.width;
pts[3] = bounds.origin.y + bounds.size.height;
ops[0] = dps_setbbox;
setupTrigUserPath(pts, ops, viewcenter.x, viewcenter.y,
maxdim * LEN1, maxdim, DEG1, upath1);
setupTrigUserPath(pts, ops, viewcenter.x, viewcenter.y,
maxdim * LEN10, maxdim, DEG10, upath10);
setupTrigUserPath(pts, ops, viewcenter.x, viewcenter.y,
maxdim * LEN45, maxdim, DEG45, upath45);
setupTrigUserPath(pts, ops, viewcenter.x, viewcenter.y,
maxdim * LEN90, maxdim, DEG90, upath90);
return self;
}
- eraseTimes:sender
{
int i;
for (i = 0; i < [matrixDisplayTimes cellCount]; i++)
[[matrixDisplayTimes cellAt:i :0] setStringValue:""];
return self;
}
-drawViewOne:sender
{
int i, row;
row = [sender selectedRow];
drawFlags.field = 0x80 >> row;
[self display];
return self;
}
-drawViewAll:sender
{
drawFlags.field = DRAWALL;
[self display];
return self;
}
/* Use the same line dimensions except rotate the graphics state before
* each line. */
static void drawRotateLines (clr, wid, startlen, endlen, deg)
float clr, wid, startlen, endlen, deg;
{
int angle;
for (angle = 0; angle < 360; angle += deg)
PSWRotate_MakeLine(deg, startlen, 0, endlen, 0);
PSWStrokePath(clr, wid);
}
- drawRotate:(int) cell
{
int ElapsedTime;
[[matrixDisplayTimes cellAt:cell :0] setStringValue:""];
PSWEraseView (CLRVIEW, bounds.origin.x, bounds.origin.y,
bounds.size.width, bounds.size.height);
PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
PSWFillPath(CLRCIRC);
PSWMarkTime (); NXPing ();
PSgsave();
PStranslate(viewcenter.x, viewcenter.y);
if ([[matrixDegreeTypes cellAt:1 :1] state])
drawRotateLines(CLR1, WID1, maxdim * LEN1, maxdim, DEG1);
if ([[matrixDegreeTypes cellAt:0 :1] state])
drawRotateLines(CLR10, WID10, maxdim * LEN10, maxdim, DEG10);
if ([[matrixDegreeTypes cellAt:1 :0] state])
drawRotateLines(CLR45, WID45, maxdim * LEN45, maxdim, DEG45);
if ([[matrixDegreeTypes cellAt:0 :0] state])
drawRotateLines(CLR90, WID90, maxdim * LEN90, maxdim, DEG90);
PSgrestore();
PSWReturnTime (&ElapsedTime);
PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
PSWStrokePath(CLRCIRCBRD, WIDCIRCBRD);
[[matrixDisplayTimes cellAt:cell :0] setIntValue:ElapsedTime];
return self;
}
/* Put the line description in a user path and then rotate and uappend.
* Not a good way to do it. (In other words, don't try this at home.) */
static void drawRotateUserPathLines(pts, ops, clr, wid, startlen, endlen, deg)
float pts[];
char ops[];
float clr, wid, startlen, endlen, deg;
{
int angle;
pts[0] = pts[4] = startlen;
pts[2] = pts[6] = endlen;
pts[1] = -wid/2;
pts[3] = -pts[1];
pts[5] = pts[7] = 0;
PSsetgray(clr);
PSsetlinewidth(wid);
for (angle = 0; angle < 360; angle += deg)
PSWRotate_UAppend(deg, pts, 8, ops, 3);
PSstroke();
}
- drawRotateUserPaths:(int) cell
{
int ElapsedTime;
[[matrixDisplayTimes cellAt:cell :0] setStringValue:""];
PSWEraseView (CLRVIEW, bounds.origin.x, bounds.origin.y,
bounds.size.width, bounds.size.height);
PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
PSWFillPath(CLRCIRC);
PSWMarkTime (); NXPing ();
ops[0] = dps_setbbox;
ops[1] = dps_moveto;
ops[2] = dps_lineto;
PSgsave();
PStranslate(viewcenter.x, viewcenter.y);
if ([[matrixDegreeTypes cellAt:1 :1] state])
drawRotateUserPathLines(pts, ops, CLR1, WID1, maxdim * LEN1,
maxdim, DEG1);
if ([[matrixDegreeTypes cellAt:0 :1] state])
drawRotateUserPathLines(pts, ops, CLR10, WID10, maxdim * LEN10,
maxdim, DEG10);
if ([[matrixDegreeTypes cellAt:1 :0] state])
drawRotateUserPathLines(pts, ops, CLR45, WID45, maxdim * LEN45,
maxdim, DEG45);
if ([[matrixDegreeTypes cellAt:0 :0] state])
drawRotateUserPathLines(pts, ops, CLR90, WID90, maxdim * LEN90,
maxdim, DEG90);
PSgrestore();
PSWReturnTime (&ElapsedTime);
PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
PSWStrokePath(CLRCIRCBRD, WIDCIRCBRD);
[[matrixDisplayTimes cellAt:cell :0] setIntValue:ElapsedTime];
return self;
}
/* Calculate the position of the start and end points and add the line to
* the current path. Not bad for this particular object but the
* calculations could become ugly for something more complex. */
static void drawTrigLines (clr, wid, x, y, startlen, endlen, deg)
float clr, wid, x, y, startlen, endlen, deg;
{
int angle;
for (angle = 0; angle < 360; angle += deg)
PSWMakeLine(x + (float) cos(angle * RADIANS) * startlen,
y + (float) sin(angle * RADIANS) * startlen,
x + (float) cos(angle * RADIANS) * endlen,
y + (float) sin(angle * RADIANS) * endlen);
PSWStrokePath(clr, wid);
}
- drawTrig:(int) cell
{
int ElapsedTime;
[[matrixDisplayTimes cellAt:cell :0] setStringValue:""];
PSWEraseView (CLRVIEW, bounds.origin.x, bounds.origin.y,
bounds.size.width, bounds.size.height);
PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
PSWFillPath(CLRCIRC);
PSWMarkTime (); NXPing ();
if ([[matrixDegreeTypes cellAt:1 :1] state])
drawTrigLines(CLR1, WID1, viewcenter.x, viewcenter.y,
maxdim * LEN1, maxdim, DEG1);
if ([[matrixDegreeTypes cellAt:0 :1] state])
drawTrigLines(CLR10, WID10, viewcenter.x, viewcenter.y,
maxdim * LEN10, maxdim, DEG10);
if ([[matrixDegreeTypes cellAt:1 :0] state])
drawTrigLines(CLR45, WID45, viewcenter.x, viewcenter.y,
maxdim * LEN45, maxdim, DEG45);
if ([[matrixDegreeTypes cellAt:0 :0] state])
drawTrigLines(CLR90, WID90, viewcenter.x, viewcenter.y,
maxdim * LEN90, maxdim, DEG90);
PSWReturnTime (&ElapsedTime);
PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
PSWStrokePath(CLRCIRCBRD, WIDCIRCBRD);
[[matrixDisplayTimes cellAt:cell :0] setIntValue:ElapsedTime];
return self;
}
/* Calculate the start and end points and place in user path format. Send
* the entire user path at once. */
static void drawTrigUserPathLines(
pts, ops, clr, wid, x, y, startlen, endlen, deg)
float pts[];
char ops[];
float clr, wid, x, y, startlen, endlen, deg;
{
int i , j, angle;
i = 4; j = 1;
for (angle = 0; angle < 360; angle += deg)
{
pts[i++] = x + (float) cos(angle * RADIANS) * startlen;
pts[i++] = y + (float) sin(angle * RADIANS) * startlen;
ops[j++] = dps_moveto;
pts[i++] = x + (float) cos(angle * RADIANS) * endlen;
pts[i++] = y + (float) sin(angle * RADIANS) * endlen;
ops[j++] = dps_lineto;
}
PSWUStroke(clr, wid, pts, i, ops, j);
}
- drawTrigUserPaths:(int) cell
{
int ElapsedTime;
[[matrixDisplayTimes cellAt:cell :0] setStringValue:""];
PSWEraseView (CLRVIEW, bounds.origin.x, bounds.origin.y,
bounds.size.width, bounds.size.height);
PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
PSWFillPath(CLRCIRC);
PSWMarkTime (); NXPing ();
pts[0] = bounds.origin.x;
pts[1] = bounds.origin.y;
pts[2] = bounds.origin.x + bounds.size.width;
pts[3] = bounds.origin.y + bounds.size.height;
ops[0] = dps_setbbox;
if ([[matrixDegreeTypes cellAt:1 :1] state])
drawTrigUserPathLines(pts, ops, CLR1, WID1, viewcenter.x, viewcenter.y,
maxdim * LEN1, maxdim, DEG1);
if ([[matrixDegreeTypes cellAt:0 :1] state])
drawTrigUserPathLines(pts, ops, CLR10, WID10, viewcenter.x, viewcenter.y,
maxdim * LEN10, maxdim, DEG10);
if ([[matrixDegreeTypes cellAt:1 :0] state])
drawTrigUserPathLines(pts, ops, CLR45, WID45, viewcenter.x, viewcenter.y,
maxdim * LEN45, maxdim, DEG45);
if ([[matrixDegreeTypes cellAt:0 :0] state])
drawTrigUserPathLines(pts, ops, CLR90, WID90, viewcenter.x, viewcenter.y,
maxdim * LEN90, maxdim, DEG90);
PSWReturnTime (&ElapsedTime);
PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
PSWStrokePath(CLRCIRCBRD, WIDCIRCBRD);
[[matrixDisplayTimes cellAt:cell:0] setIntValue:ElapsedTime];
return self;
}
- drawTrigUserPathsServer:(int) cell
{
int ElapsedTime;
[[matrixDisplayTimes cellAt:cell :0] setStringValue:""];
PSWEraseView (CLRVIEW, bounds.origin.x, bounds.origin.y,
bounds.size.width, bounds.size.height);
PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
PSWFillPath(CLRCIRC);
PSWMarkTime (); NXPing ();
if ([[matrixDegreeTypes cellAt:1 :1] state])
PSWDrawUserPath(CLR1, WID1, upath1);
if ([[matrixDegreeTypes cellAt:0 :1] state])
PSWDrawUserPath(CLR10, WID10, upath10);
if ([[matrixDegreeTypes cellAt:1 :0] state])
PSWDrawUserPath(CLR45, WID45, upath45);
if ([[matrixDegreeTypes cellAt:0 :0] state])
PSWDrawUserPath(CLR90, WID90, upath90);
PSWReturnTime (&ElapsedTime);
PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
PSWStrokePath(CLRCIRCBRD, WIDCIRCBRD);
[[matrixDisplayTimes cellAt:cell:0] setIntValue:ElapsedTime];
return self;
}
/* Calculate the start and end points and place in user path format. Send
* the entire user path at once using the DPSDoUserPath() call. */
static void drawDPSUserPathLines(
pts, ops, clr, wid, x, y, startlen, endlen, deg, bbox)
float pts[];
char ops[];
float clr, wid, x, y, startlen, endlen, deg;
float bbox[4];
{
int i , j, angle;
i = j = 0;
for (angle = 0; angle < 360; angle += deg)
{
pts[i++] = x + (float) cos(angle * RADIANS) * startlen;
pts[i++] = y + (float) sin(angle * RADIANS) * startlen;
ops[j++] = dps_moveto;
pts[i++] = x + (float) cos(angle * RADIANS) * endlen;
pts[i++] = y + (float) sin(angle * RADIANS) * endlen;
ops[j++] = dps_lineto;
}
PSsetgray(clr);
PSsetlinewidth(wid);
DPSDoUserPath(pts, i, dps_float, ops, j, bbox, dps_ustroke);
}
- drawDPSUserPaths:(int) cell;
{
int ElapsedTime;
float bbox[4];
[[matrixDisplayTimes cellAt:cell :0] setStringValue:""];
PSWEraseView (CLRVIEW, bounds.origin.x, bounds.origin.y,
bounds.size.width, bounds.size.height);
PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
PSWFillPath(CLRCIRC);
PSWMarkTime (); NXPing ();
bbox[0] = bounds.origin.x;
bbox[1] = bounds.origin.y;
bbox[2] = bounds.origin.x + bounds.size.width;
bbox[3] = bounds.origin.y + bounds.size.height;
if ([[matrixDegreeTypes cellAt:1 :1] state])
drawDPSUserPathLines(pts, ops, CLR1, WID1, viewcenter.x, viewcenter.y,
maxdim * LEN1, maxdim, DEG1, bbox);
if ([[matrixDegreeTypes cellAt:0 :1] state])
drawDPSUserPathLines(pts, ops, CLR10, WID10, viewcenter.x, viewcenter.y,
maxdim * LEN10, maxdim, DEG10, bbox);
if ([[matrixDegreeTypes cellAt:1 :0] state])
drawDPSUserPathLines(pts, ops, CLR45, WID45, viewcenter.x, viewcenter.y,
maxdim * LEN45, maxdim, DEG45, bbox);
if ([[matrixDegreeTypes cellAt:0 :0] state])
drawDPSUserPathLines(pts, ops, CLR90, WID90, viewcenter.x, viewcenter.y,
maxdim * LEN90, maxdim, DEG90, bbox);
PSWReturnTime (&ElapsedTime);
PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
PSWStrokePath(CLRCIRCBRD, WIDCIRCBRD);
[[matrixDisplayTimes cellAt:cell:0] setIntValue:ElapsedTime];
return self;
}
- drawSelf:(NXRect *)r :(int) count
{
PSWEraseView (CLRVIEW, bounds.origin.x, bounds.origin.y,
bounds.size.width, bounds.size.height);
if (drawFlags.flags.rotate)
[self drawRotate:0];
if (drawFlags.flags.uappend)
[self drawRotateUserPaths:1];
if (drawFlags.flags.trig)
[self drawTrig:2];
if (drawFlags.flags.userpaths)
[self drawTrigUserPaths:3];
if (drawFlags.flags.server)
[self drawTrigUserPathsServer:4];
if (drawFlags.flags.dpsuserpath)
[self drawDPSUserPaths:5];
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.