This is DialView.m in view mode; [Download] [Up]
/*
* (a) (C) 1990 by Adobe Systems Incorporated. All rights reserved.
*
* (b) If this Sample Code is distributed as part of the Display PostScript
* System Software Development Kit from Adobe Systems Incorporated,
* then this copy is designated as Development Software and its use is
* subject to the terms of the License Agreement attached to such Kit.
*
* (c) If this Sample Code is distributed independently, then the following
* terms apply:
*
* (d) This file may be freely copied and redistributed as long as:
* 1) Parts (a), (d), (e) and (f) continue to be included in the file,
* 2) If the file has been modified in any way, a notice of such
* modification is conspicuously indicated.
*
* (e) PostScript, Display PostScript, and Adobe are registered trademarks of
* Adobe Systems Incorporated.
*
* (f) 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 NONINFRINGEMENT
* OF THIRD PARTY RIGHTS.
*/
/*
* DialView.m
* Created by Ken Fromm
*
* This application draws hash marks on a dial in several ways. The first way
* draws using wraps and the rotate operator. The second draws with wraps
* but calculates the trig for the beginning and ending points of the line segments.
* The third calculates the trig and sends the line segments to the server with
* user paths. This is the fastest drawing approach and is recommended
* for all but the simplest drawing. The last method stores the user path in the
* server instead of calculating the points anew. This is may be useful in a few
* cases where the paths are large, imaged frequently and do not change.
* In most cases, though, the overhead of managing paths in the server
* overrides any savings.
*
* Version: 2.0
* Author: Ken Fromm
* History:
* 03-07-91 Added this comment.
* 05-10-91 Simplified the application from six methods to
* four. (The two taken out were variations of
* user path drawing and tended to cloud the
* message of the application.)
*/
#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 setupUpaths];
drawFlags.field = 0x80;
return self;
}
/* Free the arrays upon quitting. */
- free
{
if (pts)
NX_FREE(pts);
if (ops)
NX_FREE(ops);
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 setupUpathTrig (pts, ops, x, y, startlen, endlen, deg, upathname, bbox)
float pts[];
char ops[];
float x, y, startlen, endlen, deg;
char *upathname;
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;
}
PSWPlaceName(upathname);
DPSDoUserPath(pts, i, dps_float, ops, j, bbox, dps_def);
}
- setupUpaths
{
float bbox[4];
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;
setupUpathTrig(pts, ops, viewcenter.x, viewcenter.y,
maxdim * LEN1, maxdim, DEG1, upath1, bbox);
setupUpathTrig(pts, ops, viewcenter.x, viewcenter.y,
maxdim * LEN10, maxdim, DEG10, upath10, bbox);
setupUpathTrig(pts, ops, viewcenter.x, viewcenter.y,
maxdim * LEN45, maxdim, DEG45, upath45, bbox);
setupUpathTrig(pts, ops, viewcenter.x, viewcenter.y,
maxdim * LEN90, maxdim, DEG90, upath90, bbox);
return self;
}
/*
* This method changes the title of the menu cell according to the
* value of the trace variable.
*/
-trace:sender
{
if (trace == NO)
[[sender selectedCell] setTitle:"Trace On"];
else
[[sender selectedCell] setTitle:"Trace Off"];
trace = !trace;
return self;
}
- eraseTimes:sender
{
int i;
for (i = 0; i < [matrixDisplayTimes cellCount]; i++)
[[matrixDisplayTimes cellAt:i :0] setStringValue:""];
return self;
}
-drawViewOne:sender
{
drawFlags.field = 0x80 >> [sender selectedRow];
[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 drawWrapsRotate (clr, wid, startlen, endlen, deg)
float clr, wid, startlen, endlen, deg;
{
int angle;
PSWSetColorWidth(clr, wid);
for (angle = 0; angle < 360; angle += deg)
PSWRotate_MakeLine(deg, startlen, 0, endlen, 0);
PSstroke();
}
- drawWrapsRotate:(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 (trace)
DPSTraceContext(DPSGetCurrentContext(), YES);
PSgsave();
PStranslate(viewcenter.x, viewcenter.y);
if ([[matrixDegreeTypes cellAt:1 :1] state]) drawWrapsRotate(CLR1, WID1, maxdim * LEN1, maxdim, DEG1);
if ([[matrixDegreeTypes cellAt:0 :1] state]) drawWrapsRotate(CLR10, WID10, maxdim * LEN10, maxdim, DEG10);
if ([[matrixDegreeTypes cellAt:1 :0] state]) drawWrapsRotate(CLR45, WID45, maxdim * LEN45, maxdim, DEG45);
if ([[matrixDegreeTypes cellAt:0 :0] state]) drawWrapsRotate(CLR90, WID90, maxdim * LEN90, maxdim, DEG90);
PSgrestore();
if (trace)
DPSTraceContext(DPSGetCurrentContext(), NO);
PSWReturnTime (&ElapsedTime);
PSWSetColorWidth(CLRCIRCBRD, WIDCIRCBRD);
PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
PSstroke();
[[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 drawWrapsTrig (clr, wid, x, y, startlen, endlen, deg)
float clr, wid, x, y, startlen, endlen, deg;
{
int angle;
PSWSetColorWidth(clr, wid);
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);
PSstroke();
}
- drawWrapsTrig:(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 (trace)
DPSTraceContext(DPSGetCurrentContext(), YES);
if ([[matrixDegreeTypes cellAt:1 :1] state]) drawWrapsTrig(CLR1, WID1, viewcenter.x, viewcenter.y,
maxdim * LEN1, maxdim, DEG1);
if ([[matrixDegreeTypes cellAt:0 :1] state]) drawWrapsTrig(CLR10, WID10, viewcenter.x, viewcenter.y,
maxdim * LEN10, maxdim, DEG10);
if ([[matrixDegreeTypes cellAt:1 :0] state]) drawWrapsTrig(CLR45, WID45, viewcenter.x, viewcenter.y,
maxdim * LEN45, maxdim, DEG45);
if ([[matrixDegreeTypes cellAt:0 :0] state]) drawWrapsTrig(CLR90, WID90, viewcenter.x, viewcenter.y,
maxdim * LEN90, maxdim, DEG90);
if (trace)
DPSTraceContext(DPSGetCurrentContext(), NO);
PSWReturnTime (&ElapsedTime);
PSWSetColorWidth(CLRCIRCBRD, WIDCIRCBRD);
PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
PSstroke();
[[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 drawUpathsTrig (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;
}
PSWSetColorWidth(clr, wid);
DPSDoUserPath(pts, i, dps_float, ops, j, bbox, dps_ustroke);
}
- drawUpathsTrig:(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 (trace)
DPSTraceContext(DPSGetCurrentContext(), YES);
if ([[matrixDegreeTypes cellAt:1 :1] state]) drawUpathsTrig(pts, ops, CLR1, WID1, viewcenter.x, viewcenter.y,
maxdim * LEN1, maxdim, DEG1, bbox);
if ([[matrixDegreeTypes cellAt:0 :1] state]) drawUpathsTrig(pts, ops, CLR10, WID10, viewcenter.x, viewcenter.y,
maxdim * LEN10, maxdim, DEG10, bbox);
if ([[matrixDegreeTypes cellAt:1 :0] state]) drawUpathsTrig(pts, ops, CLR45, WID45, viewcenter.x, viewcenter.y,
maxdim * LEN45, maxdim, DEG45, bbox);
if ([[matrixDegreeTypes cellAt:0 :0] state]) drawUpathsTrig(pts, ops, CLR90, WID90, viewcenter.x, viewcenter.y,
maxdim * LEN90, maxdim, DEG90, bbox);
if (trace)
DPSTraceContext(DPSGetCurrentContext(), NO);
PSWReturnTime (&ElapsedTime);
PSWSetColorWidth(CLRCIRCBRD, WIDCIRCBRD);
PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
PSstroke();
[[matrixDisplayTimes cellAt:cell :0] setIntValue:ElapsedTime];
return self;
}
- drawUpathsServer:(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 (trace)
DPSTraceContext(DPSGetCurrentContext(), YES);
if ([[matrixDegreeTypes cellAt:1 :1] state]) {
PSWSetColorWidth(CLR1, WID1);
PSWDrawUserPath(upath1);
}
if ([[matrixDegreeTypes cellAt:0 :1] state]) {
PSWSetColorWidth(CLR10, WID10);
PSWDrawUserPath(upath10);
}
if ([[matrixDegreeTypes cellAt:1 :0] state]) {
PSWSetColorWidth(CLR45, WID45);
PSWDrawUserPath(upath45);
}
if ([[matrixDegreeTypes cellAt:0 :0] state])
{
PSWSetColorWidth(CLR90, WID90);
PSWDrawUserPath(upath90);
}
if (trace)
DPSTraceContext(DPSGetCurrentContext(), NO);
PSWReturnTime (&ElapsedTime);
PSWSetColorWidth(CLRCIRCBRD, WIDCIRCBRD);
PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
PSstroke();
[[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.wrapsrotate)
[self drawWrapsRotate:0];
if (drawFlags.flags.wrapstrig)
[self drawWrapsTrig:1];
if (drawFlags.flags.upathstrig)
[self drawUpathsTrig:2];
if (drawFlags.flags.upathsserver)
[self drawUpathsServer:3];
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.