home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1994 June / NEBULA_SE.ISO / SourceCode / AdobeExamples / NX_Dial / DialView.m < prev    next >
Encoding:
Text File  |  1993-01-19  |  13.5 KB  |  463 lines

  1.  
  2. /*
  3.  * (a)  (C) 1990 by Adobe Systems Incorporated. All rights reserved.
  4.  *
  5.  * (b)  If this Sample Code is distributed as part of the Display PostScript
  6.  *    System Software Development Kit from Adobe Systems Incorporated,
  7.  *    then this copy is designated as Development Software and its use is
  8.  *    subject to the terms of the License Agreement attached to such Kit.
  9.  *
  10.  * (c)  If this Sample Code is distributed independently, then the following
  11.  *    terms apply:
  12.  *
  13.  * (d)  This file may be freely copied and redistributed as long as:
  14.  *    1) Parts (a), (d), (e) and (f) continue to be included in the file,
  15.  *    2) If the file has been modified in any way, a notice of such
  16.  *      modification is conspicuously indicated.
  17.  *
  18.  * (e)  PostScript, Display PostScript, and Adobe are registered trademarks of
  19.  *    Adobe Systems Incorporated.
  20.  * 
  21.  * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
  22.  *    CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
  23.  *    AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
  24.  *    ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
  25.  *    OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
  26.  *    WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
  27.  *    WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
  28.  *    DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY, 
  29.  *    FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
  30.  *    OF THIRD PARTY RIGHTS.
  31.  */
  32.  
  33. /*
  34.  *    DialView.m
  35.  *    Created by Ken Fromm
  36.  *
  37.  *    This application draws hash marks on a dial in several ways. The first way
  38.  *    draws using wraps and the rotate operator. The second draws with wraps
  39.  *    but calculates the trig for the beginning and ending points of the line segments.
  40.  *    The third calculates the trig and sends the line segments to the server with
  41.  *    user paths. This is the fastest drawing approach and is recommended
  42.  *    for all but the simplest drawing. The last method stores the user path in the
  43.  *    server instead of calculating the points anew. This is may be useful in a few
  44.  *    cases where the paths are large, imaged frequently and do not change.
  45.  *    In most cases, though, the overhead of managing paths in the server
  46.  *    overrides any savings.
  47.  *
  48.  *    Version:    2.0
  49.  *    Author:    Ken Fromm
  50.  *    History:
  51.  *            03-07-91        Added this comment.
  52.  *            05-10-91        Simplified the application from six methods to
  53.  *                        four. (The two taken out were variations of 
  54.  *                        user path drawing and tended to cloud the
  55.  *                        message of the application.)
  56.  */
  57.  
  58. #import "DialView.h"
  59. #import "DialViewWraps.h"
  60. #import <appkit/Button.h>
  61. #import <appkit/Control.h>
  62. #import <appkit/Matrix.h>
  63. #import <appkit/TextField.h>
  64. #import <appkit/nextstd.h>
  65. #import <math.h>
  66. #import <dpsclient/wraps.h>
  67.  
  68. @implementation DialView
  69.  
  70. /*
  71. *    These definitions are for the names of the user path arrays in the server.  Providing
  72. *    names like this is only to simplify the example. An optimized solution would probably use
  73. *    user objects and forego names altogether.
  74. */
  75. static char *upath1 = "upath1";
  76. static char *upath10 = "upath10";
  77. static char *upath45 = "upath45";
  78. static char *upath90 = "upath90";
  79.  
  80. /*
  81. *    Allocate a gstate and set clipping to NO.  The gstate is allocated because we do not
  82. *    want to reset the individual drawing variables when the context is switched back to this
  83. *    view.  The clipping is set to NO because the drawing methods do not need clipping so
  84. *    its a way to save display time.
  85. *
  86. *    The dimensions of the dial are calculated. The bounds of the DialView is the starting
  87. *    point. Arrays to hold user path point and operator values are allocated.
  88. *
  89. *    The PSWDefs() call sends some definitions used in the wraps to the interpreter.  They
  90. *    will be available in the interpreter when the wraps call them. 
  91. */
  92.  
  93. + newFrame:(NXRect *) frm
  94. {
  95.     self = [super newFrame:frm]; 
  96.     [self allocateGState]; 
  97.     [self setClipping:NO];
  98.  
  99.     viewcenter.x =  bounds.size.width/2;
  100.     viewcenter.y = bounds.size.height/2;
  101.     if (viewcenter.x > viewcenter.y)
  102.         maxdim = viewcenter.y - WIDCIRCBRD/2 - CIRCFF ;
  103.     else
  104.         maxdim = viewcenter.x - WIDCIRCBRD/2 -CIRCFF;
  105.     viewcenter.x += bounds.origin.x;
  106.     viewcenter.y += bounds.origin.y;
  107.  
  108.     NX_MALLOC(pts, float, MAX_PTS); 
  109.     NX_MALLOC(ops, char, MAX_OPS);
  110.     
  111.     PSWDefs ();
  112.     [self setupUpaths];
  113.  
  114.     drawFlags.field = 0x80;
  115.  
  116.     return self;
  117. }
  118.  
  119. /* Free the arrays upon quitting. */
  120. - free
  121. {
  122.     if (pts)
  123.         NX_FREE(pts);
  124.     if (ops)
  125.         NX_FREE(ops);
  126.   
  127.        return [super free];
  128. }
  129.  
  130. /*  Created by interface.  Used to obtain the id's of objects that will be messaged. */
  131. - setMatrixDegreeTypes:anObject
  132. {
  133.     matrixDegreeTypes = anObject;
  134.     return self;
  135. }
  136.  
  137. - setMatrixDisplayTimes:anObject
  138. {
  139.     matrixDisplayTimes = anObject;
  140.     return self;
  141. }
  142.  
  143. /*
  144. *    Calculate the start and end points and place in user path format.
  145. *    Send the user path to the server and define it in the server. Execute
  146. *    the user path for drawing.
  147. */
  148. static void setupUpathTrig (pts, ops, x, y, startlen, endlen, deg, upathname, bbox)
  149.     float        pts[];
  150.     char        ops[];
  151.     float     x, y, startlen, endlen, deg;
  152.     char        *upathname;
  153.     float        bbox[4];
  154. {
  155.     int        i , j, angle;
  156.     
  157.     i = j = 0;
  158.     for (angle = 0; angle < 360; angle += deg)
  159.     {
  160.         pts[i++] = x + (float) cos(angle * RADIANS) * startlen;
  161.         pts[i++] = y + (float) sin(angle * RADIANS) * startlen;
  162.         ops[j++] = dps_moveto;
  163.         
  164.         pts[i++] = x + (float) cos(angle * RADIANS) * endlen;
  165.         pts[i++] = y + (float) sin(angle * RADIANS) * endlen;
  166.         ops[j++] = dps_lineto;
  167.     }
  168.  
  169.     PSWPlaceName(upathname);
  170.     DPSDoUserPath(pts, i, dps_float, ops, j, bbox, dps_def);
  171. }
  172.  
  173. - setupUpaths
  174. {
  175.     float        bbox[4];
  176.     
  177.     bbox[0] = bounds.origin.x;
  178.     bbox[1] = bounds.origin.y;
  179.     bbox[2] = bounds.origin.x + bounds.size.width;
  180.     bbox[3] = bounds.origin.y + bounds.size.height;
  181.         
  182.     setupUpathTrig(pts, ops, viewcenter.x, viewcenter.y,
  183.                 maxdim * LEN1, maxdim, DEG1, upath1, bbox);
  184.     setupUpathTrig(pts, ops, viewcenter.x, viewcenter.y,
  185.                 maxdim * LEN10, maxdim, DEG10, upath10, bbox);
  186.     setupUpathTrig(pts, ops, viewcenter.x, viewcenter.y,
  187.                 maxdim * LEN45, maxdim, DEG45, upath45, bbox);
  188.     setupUpathTrig(pts, ops, viewcenter.x, viewcenter.y,
  189.                 maxdim * LEN90, maxdim, DEG90, upath90, bbox);
  190.  
  191.     return self;
  192. }
  193.  
  194. /*
  195. *    This method changes the title of the menu cell according to the
  196. *     value of the trace variable.
  197. */
  198. -trace:sender
  199. {
  200.     if (trace == NO)
  201.         [[sender selectedCell] setTitle:"Trace On"];
  202.     else
  203.         [[sender selectedCell] setTitle:"Trace Off"];
  204.     trace = !trace;
  205.     
  206.     return self;
  207. }
  208.  
  209. - eraseTimes:sender
  210. {
  211.     int        i;
  212.     
  213.     for (i = 0; i < [matrixDisplayTimes cellCount]; i++)
  214.         [[matrixDisplayTimes cellAt:i :0] setStringValue:""];
  215.  
  216.     return self;
  217. }
  218.  
  219. -drawViewOne:sender
  220. {
  221.     drawFlags.field = 0x80 >> [sender  selectedRow];
  222.     [self display];
  223.  
  224.     return self;
  225. }
  226.  
  227. -drawViewAll:sender
  228. {
  229.     drawFlags.field = DRAWALL;
  230.     [self display];
  231.  
  232.     return self;
  233. }
  234.  
  235. /* Use the same line dimensions except rotate the graphics state before each line. */
  236. static void drawWrapsRotate (clr, wid, startlen, endlen, deg)
  237.     float     clr, wid, startlen, endlen, deg;
  238. {
  239.     int        angle;
  240.     
  241.     PSWSetColorWidth(clr, wid);
  242.     for (angle = 0; angle < 360; angle += deg)
  243.         PSWRotate_MakeLine(deg, startlen, 0, endlen, 0);
  244.     PSstroke();
  245. }
  246.  
  247. - drawWrapsRotate:(int) cell 
  248. {
  249.     int            ElapsedTime;
  250.  
  251.     [[matrixDisplayTimes cellAt:cell :0] setStringValue:""];
  252.     PSWEraseView (CLRVIEW, bounds.origin.x, bounds.origin.y,
  253.                     bounds.size.width, bounds.size.height);
  254.     PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
  255.     PSWFillPath(CLRCIRC);
  256.  
  257.     PSWMarkTime (); NXPing ();    
  258.         if (trace)
  259.             DPSTraceContext(DPSGetCurrentContext(), YES);
  260.         PSgsave();
  261.             PStranslate(viewcenter.x, viewcenter.y);            
  262.             if ([[matrixDegreeTypes cellAt:1 :1] state])                drawWrapsRotate(CLR1, WID1, maxdim * LEN1, maxdim, DEG1);
  263.             if ([[matrixDegreeTypes cellAt:0 :1] state])                drawWrapsRotate(CLR10, WID10, maxdim * LEN10, maxdim, DEG10);
  264.             if ([[matrixDegreeTypes cellAt:1 :0] state])                drawWrapsRotate(CLR45, WID45, maxdim * LEN45, maxdim, DEG45);
  265.             if ([[matrixDegreeTypes cellAt:0 :0] state])                drawWrapsRotate(CLR90, WID90, maxdim * LEN90, maxdim, DEG90);
  266.         PSgrestore();
  267.         if (trace)
  268.             DPSTraceContext(DPSGetCurrentContext(), NO);
  269.     PSWReturnTime (&ElapsedTime);
  270.  
  271.     PSWSetColorWidth(CLRCIRCBRD, WIDCIRCBRD);
  272.     PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
  273.     PSstroke();
  274.             
  275.     [[matrixDisplayTimes cellAt:cell :0] setIntValue:ElapsedTime];
  276.  
  277.     return self;
  278. }
  279.  
  280. /*
  281. *    Calculate the position of the start and end points and add the line to the
  282. *    current path.  Not bad for this particular object but the calculations could
  283. *    become ugly for something more complex.
  284. */
  285. static void drawWrapsTrig (clr, wid, x, y, startlen, endlen, deg)
  286.     float     clr, wid, x, y, startlen, endlen, deg;
  287. {
  288.     int        angle;
  289.     
  290.     PSWSetColorWidth(clr, wid);
  291.     for (angle = 0; angle < 360; angle += deg)
  292.         PSWMakeLine(x + (float) cos(angle * RADIANS) * startlen,
  293.                 y + (float) sin(angle * RADIANS) * startlen,
  294.                 x + (float) cos(angle * RADIANS) * endlen,
  295.                 y + (float) sin(angle * RADIANS) * endlen);
  296.     PSstroke();
  297. }
  298.  
  299. - drawWrapsTrig:(int) cell
  300. {
  301.     int            ElapsedTime;
  302.  
  303.     [[matrixDisplayTimes cellAt:cell :0] setStringValue:""];
  304.     PSWEraseView (CLRVIEW, bounds.origin.x, bounds.origin.y,
  305.                     bounds.size.width, bounds.size.height);
  306.     PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
  307.     PSWFillPath(CLRCIRC);
  308.  
  309.     PSWMarkTime ();  NXPing ();    
  310.         if (trace)
  311.             DPSTraceContext(DPSGetCurrentContext(), YES);
  312.         if ([[matrixDegreeTypes cellAt:1 :1] state])            drawWrapsTrig(CLR1, WID1, viewcenter.x, viewcenter.y, 
  313.                 maxdim * LEN1, maxdim, DEG1);
  314.         if ([[matrixDegreeTypes cellAt:0 :1] state])            drawWrapsTrig(CLR10, WID10, viewcenter.x, viewcenter.y, 
  315.                 maxdim * LEN10, maxdim, DEG10);
  316.         if ([[matrixDegreeTypes cellAt:1 :0] state])            drawWrapsTrig(CLR45, WID45, viewcenter.x, viewcenter.y, 
  317.                 maxdim * LEN45, maxdim, DEG45);
  318.         if ([[matrixDegreeTypes cellAt:0 :0] state])            drawWrapsTrig(CLR90, WID90, viewcenter.x, viewcenter.y, 
  319.                 maxdim * LEN90, maxdim, DEG90);
  320.         if (trace)
  321.             DPSTraceContext(DPSGetCurrentContext(), NO);
  322.     PSWReturnTime (&ElapsedTime);
  323.  
  324.     PSWSetColorWidth(CLRCIRCBRD, WIDCIRCBRD);
  325.     PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
  326.     PSstroke();
  327.                     
  328.     [[matrixDisplayTimes cellAt:cell :0] setIntValue:ElapsedTime];
  329.  
  330.     return self;
  331. }
  332.  
  333. /*
  334. *    Calculate the start and end points and place in user path format.
  335. *    Send the entire user path at once using the DPSDoUserPath() call.
  336. */
  337. static void drawUpathsTrig (pts, ops, clr, wid, x, y, startlen, endlen, deg, bbox)
  338.     float        pts[];
  339.     char        ops[];
  340.     float     clr, wid, x, y, startlen, endlen, deg;
  341.     float        bbox[4];
  342. {
  343.     int        i , j, angle;
  344.     
  345.     i = j = 0;
  346.     for (angle = 0; angle < 360; angle += deg)
  347.     {
  348.         pts[i++] = x + (float) cos(angle * RADIANS) * startlen;
  349.         pts[i++] = y + (float) sin(angle * RADIANS) * startlen;
  350.         ops[j++] = dps_moveto;
  351.         
  352.         pts[i++] = x + (float) cos(angle * RADIANS) * endlen;
  353.         pts[i++] = y + (float) sin(angle * RADIANS) * endlen;
  354.         ops[j++] = dps_lineto;
  355.     }
  356.  
  357.     PSWSetColorWidth(clr, wid);
  358.     DPSDoUserPath(pts, i, dps_float, ops, j, bbox, dps_ustroke);
  359. }
  360.  
  361. - drawUpathsTrig:(int) cell;
  362. {
  363.     int            ElapsedTime;
  364.  
  365.     float        bbox[4];
  366.  
  367.     [[matrixDisplayTimes cellAt:cell :0] setStringValue:""];
  368.     PSWEraseView (CLRVIEW, bounds.origin.x, bounds.origin.y,
  369.                     bounds.size.width, bounds.size.height);
  370.     PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
  371.     PSWFillPath(CLRCIRC);
  372.         
  373.     PSWMarkTime (); NXPing ();        
  374.         bbox[0] = bounds.origin.x;
  375.         bbox[1] = bounds.origin.y;
  376.         bbox[2] = bounds.origin.x + bounds.size.width;
  377.         bbox[3] = bounds.origin.y + bounds.size.height;
  378.  
  379.         if (trace)
  380.             DPSTraceContext(DPSGetCurrentContext(), YES);
  381.         if ([[matrixDegreeTypes cellAt:1 :1] state])            drawUpathsTrig(pts, ops, CLR1, WID1, viewcenter.x, viewcenter.y,
  382.                 maxdim * LEN1, maxdim, DEG1, bbox);
  383.         if ([[matrixDegreeTypes cellAt:0 :1] state])            drawUpathsTrig(pts, ops, CLR10, WID10, viewcenter.x, viewcenter.y,
  384.                 maxdim * LEN10, maxdim, DEG10, bbox);
  385.         if ([[matrixDegreeTypes cellAt:1 :0] state])            drawUpathsTrig(pts, ops, CLR45, WID45, viewcenter.x, viewcenter.y,
  386.                 maxdim * LEN45, maxdim, DEG45, bbox);
  387.         if ([[matrixDegreeTypes cellAt:0 :0] state])            drawUpathsTrig(pts, ops, CLR90, WID90, viewcenter.x, viewcenter.y,
  388.                 maxdim * LEN90, maxdim, DEG90, bbox);
  389.         if (trace)
  390.             DPSTraceContext(DPSGetCurrentContext(), NO);
  391.     PSWReturnTime (&ElapsedTime);
  392.  
  393.     PSWSetColorWidth(CLRCIRCBRD, WIDCIRCBRD);
  394.     PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
  395.     PSstroke();
  396.         
  397.     [[matrixDisplayTimes cellAt:cell  :0] setIntValue:ElapsedTime];
  398.  
  399.     return self;
  400. }
  401.  
  402. - drawUpathsServer:(int) cell
  403. {
  404.     int            ElapsedTime;
  405.  
  406.     [[matrixDisplayTimes cellAt:cell :0] setStringValue:""];
  407.     PSWEraseView (CLRVIEW, bounds.origin.x, bounds.origin.y,
  408.                     bounds.size.width, bounds.size.height);
  409.     PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
  410.     PSWFillPath(CLRCIRC);
  411.         
  412.     PSWMarkTime (); NXPing ();        
  413.         if (trace)
  414.             DPSTraceContext(DPSGetCurrentContext(), YES);
  415.         if ([[matrixDegreeTypes cellAt:1 :1] state])        {
  416.             PSWSetColorWidth(CLR1, WID1);
  417.             PSWDrawUserPath(upath1);
  418.         }
  419.         if ([[matrixDegreeTypes cellAt:0 :1] state])        {
  420.             PSWSetColorWidth(CLR10, WID10);
  421.             PSWDrawUserPath(upath10);
  422.         }
  423.         if ([[matrixDegreeTypes cellAt:1 :0] state])        {
  424.             PSWSetColorWidth(CLR45, WID45);
  425.             PSWDrawUserPath(upath45);
  426.         }
  427.         if ([[matrixDegreeTypes cellAt:0 :0] state])
  428.         {
  429.             PSWSetColorWidth(CLR90, WID90);
  430.             PSWDrawUserPath(upath90);
  431.         }
  432.         if (trace)
  433.             DPSTraceContext(DPSGetCurrentContext(), NO);
  434.     PSWReturnTime (&ElapsedTime);
  435.  
  436.     PSWSetColorWidth(CLRCIRCBRD, WIDCIRCBRD);
  437.     PSWMakeCircle(viewcenter.x, viewcenter.y, maxdim);
  438.     PSstroke();
  439.         
  440.     [[matrixDisplayTimes cellAt:cell  :0] setIntValue:ElapsedTime];
  441.  
  442.     return self;
  443. }
  444.  
  445. - drawSelf:(NXRect *)r :(int) count
  446. {
  447.     PSWEraseView (CLRVIEW, bounds.origin.x, bounds.origin.y,
  448.                     bounds.size.width, bounds.size.height);
  449.  
  450.     if (drawFlags.flags.wrapsrotate)
  451.         [self drawWrapsRotate:0];
  452.     if (drawFlags.flags.wrapstrig)
  453.         [self drawWrapsTrig:1];
  454.     if (drawFlags.flags.upathstrig)
  455.         [self drawUpathsTrig:2];
  456.     if (drawFlags.flags.upathsserver)
  457.         [self drawUpathsServer:3];
  458.  
  459.     return self;
  460. }
  461.  
  462. @end
  463.