home *** CD-ROM | disk | FTP | other *** search
/ Nebula / nebula.bin / SourceCode / Palettes / CircularSliderPalette / CircularSlider.m < prev    next >
Text File  |  1992-10-01  |  7KB  |  313 lines

  1. /*
  2.  *    Filename:    CircularSlider.m 
  3.  *    Created :    Sat 24 21:25:44 1991
  4.  *    Author  :    Vince DeMarco
  5.  *        <vince@whatnxt.cuc.ab.ca>
  6.  * 
  7.  *    Version 1.0.1
  8.  */
  9.  
  10. /* Generated by Interface Builder */
  11.  
  12. #import "CircularSlider.h"
  13. #include <math.h>
  14. #import <appkit/Application.h>
  15. #import <appkit/Panel.h>
  16. #import <dpsclient/event.h>
  17. #import <dpsclient/wraps.h>
  18. #import <appkit/graphics.h>
  19.  
  20. #import "wraps.h"
  21.  
  22. inline static float angle(float x, float y);
  23.  
  24. @implementation CircularSlider
  25.  
  26. // Given a x,y point on a cart coordinate system this function returns the angle from
  27. // the positive side of the Y- axis
  28. //        ^
  29. //        |
  30. //        |\
  31. //   <____|_|__>
  32. //        | |
  33. //        |<-
  34. //        |
  35.  
  36. inline static float angle(float x, float y)
  37. {
  38.     float result;
  39.  
  40.     if (y >= 0){                       /* Quadrants 1,4 */
  41.     if ( x >= 0){              /* Quadrant 1 */
  42.         result  = fabs(atan(fabs(x/y)));
  43.         result *= (180/M_PI);
  44.         return(result);
  45.     }else{                     /* Quadrant 4 */
  46.         result  = fabs(atan(fabs(y/x)));
  47.         result *= (180/M_PI);
  48.         return(result+270.0);
  49.     }
  50.     }else{                             /* Quadrants 2,3 */
  51.     if ( x >= 0){              /* Quadrant 2 */
  52.         result  = fabs(atan(fabs(y/x)));
  53.         result *= (180/M_PI);
  54.         return(result+90.0);
  55.     }else{                     /* Quadrant 3 */
  56.         result  = fabs(atan(fabs(x/y)));
  57.         result *= (180/M_PI);
  58.         return(result+180.0);
  59.     }
  60.     }
  61. }
  62.  
  63. - initFrame:(NXRect *)nf
  64. {
  65.     self = [super initFrame:nf];
  66.     [self allocateGState];
  67.     x = nf->size.width/2;          
  68.     y = nf->size.height/2;         
  69.     radius = ( x < y ? x : y) - 4;
  70.     currentang = 0.0;
  71.     maxang = 360.0;
  72.     CircFlags.continuous = 1;  // By Default messages are continuously sent
  73.     return(self);
  74. }
  75.  
  76. - setContinuous:(BOOL)flag
  77. {
  78.     if (flag == NO)
  79.     CircFlags.continuous = 0;
  80.     else
  81.     CircFlags.continuous = 1;
  82.     return(self);
  83. }
  84.  
  85. - (BOOL)isContinuous
  86. {
  87.     if (CircFlags.continuous == 1)
  88.     return YES;
  89.     else
  90.     return NO;
  91. }
  92.  
  93. - (float)floatValue
  94. {
  95.     return(currentang);
  96. }
  97.  
  98. - (double)doubleValue
  99. {
  100.     return((double)currentang);
  101. }
  102.  
  103. - (int)intValue
  104. {
  105.     return((int)currentang);
  106. }
  107.  
  108. - setDoubleValue:(double)value
  109. {
  110.     [self setFloatValue:(float)value];
  111.     return(self);
  112. }
  113.  
  114. - setFloatValue:(float)value
  115. {
  116.     if (value <= maxang){
  117.     currentang = value;
  118.     }else{
  119.     currentang = maxang;
  120.     }
  121.     [self display];
  122.     return(self);
  123. }
  124.  
  125. - setIntValue:(int)value
  126. {
  127.     [self setFloatValue:(float)value];
  128.     return(self);
  129. }
  130.  
  131. - setTheMaxValue:(float)afloat
  132. {
  133.     maxang = afloat;
  134.     return(self);
  135. }
  136.  
  137. - (float)theMaxValue
  138. {
  139.     return(maxang);
  140. }
  141.  
  142. - takeDoubleValueFrom:sender
  143. {
  144.     float newValue;
  145.  
  146.     newValue = [sender floatValue];
  147.     if ((newValue != currentang) && (newValue <= maxang)){
  148.     currentang = newValue;
  149.     [self display];
  150.     }
  151.     return(self);
  152. }
  153.  
  154. - takeFloatValueFrom:sender
  155. {
  156.     return([self takeDoubleValueFrom:sender]);
  157. }
  158.  
  159. - takeIntValueFrom:sender
  160. {
  161.     return([self takeDoubleValueFrom:sender]);
  162. }
  163.  
  164. - setAction:(SEL)aSelector
  165. {
  166.     _action = aSelector;
  167.     return(self);
  168. }
  169.  
  170. - setTarget:anObject
  171. {
  172.     _target = anObject;
  173.     return(self);
  174. }
  175.  
  176. - target
  177. {
  178.     return( _target);
  179. }
  180.  
  181. - (SEL)action
  182. {
  183.     return( _action);
  184. }
  185.  
  186. - drawSelf:(const NXRect *)rects : (int)count
  187. {
  188.     x = bounds.size.width/2;         
  189.     y = bounds.size.height/2;
  190.     radius = ( x < y ? x : y) - 4;
  191.     if (conFlags.enabled == 1){  /* Draw the 3D raised box first if it has been enabled */
  192.     //PSdrawRectangle(bounds.origin.x,bounds.origin.y,bounds.size.width - 2,bounds.size.height);
  193.     NXDrawButton(&bounds, &bounds);
  194.     }
  195.     PSdrawCircSlider(bounds.size.height,bounds.size.width,x,y,radius,currentang);   // Draw the actual slider
  196.     return(self);
  197. }
  198.  
  199. - mouseDown:(NXEvent *)theEvent
  200. {
  201.     int            looping;        /* Flag for while in modal loop     */
  202.     int            oldMask;        /* Old event mask                   */
  203.     NXPoint            startPoint;        /* Location of mouseDown            */
  204.     NXPoint            currentPoint;        /* Location of mouseDragged/mouseUp */
  205.     float           newangle = 0;           /* angle of current mouseDown/mouseDragged/mouseUp point */
  206.     float           scalex = bounds.size.height / bounds.size.width;
  207.     float           scaley = bounds.size.width / bounds.size.height;
  208.  
  209.     if (conFlags.enabled == 1){  /* If CircularSlider is disabled don't allow any 
  210.                                       * mouseDown events, just ignore them.
  211.                       */
  212.  
  213.         /* Allow mouseDragged events */
  214.         oldMask = [window addToEventMask:NX_MOUSEDRAGGEDMASK];
  215.         
  216.         /* Get the location of the mouseDown in view coordinates */
  217.         startPoint = theEvent->location;
  218.         [self convertPoint:&startPoint fromView:nil];
  219.         
  220.         /* Initialize the drawing context */
  221.         [self lockFocus];
  222.  
  223.         // Adjust the mouseDown event's location if the Slider has been
  224.             // scaled in either the x or y direction
  225.  
  226.         if (scalex > scaley ){
  227.         newangle = angle(scalex*(startPoint.x-(x)),startPoint.y-(y));
  228.         }else
  229.         if (scalex < scaley ){
  230.             newangle = angle(startPoint.x-(x),scaley*(startPoint.y-(y)));
  231.         }else
  232.             if (scalex = scaley ){
  233.             newangle = angle(startPoint.x-(x),startPoint.y-(y));
  234.             }
  235.             if (newangle <= maxang)
  236.         currentang = newangle;
  237.         else
  238.         currentang = maxang;
  239.         //PSdrawRectangle(bounds.origin.x,bounds.origin.y,bounds.size.width - 2,bounds.size.height);
  240.         NXDrawButton(&bounds, &bounds);
  241.         PSdrawCircSlider(bounds.size.height,bounds.size.width,x,y,radius,currentang);
  242.         [window flushWindow];
  243.         
  244.         /* Run modal loop until mouse up */
  245.         looping = YES;
  246.         while (looping) {
  247.         
  248.         /* Get the next mouseDragged/mouseUp event */
  249.         theEvent=[NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
  250.         
  251.         /* Convert location to view coordinates */
  252.         currentPoint = theEvent->location;
  253.         [self convertPoint:¤tPoint fromView:nil];
  254.         
  255.         /* Handle the event */
  256.         if (theEvent->type == NX_MOUSEDRAGGED) {
  257.  
  258.                 // Adjust the mouseDown event's location if the Slider has been
  259.                     // scaled in either the x or y direction
  260.  
  261.             if (scalex > scaley ){
  262.             newangle = angle(scalex*(currentPoint.x-(x)),currentPoint.y-(y));
  263.             }else
  264.             if (scalex < scaley ){
  265.                 newangle = angle(currentPoint.x-(x),scaley*(currentPoint.y-(y)));
  266.             }else
  267.                 if (scalex = scaley ){
  268.                 newangle = angle(currentPoint.x-(x),currentPoint.y-(y));
  269.                 }
  270.  
  271.             if (newangle <= maxang)
  272.             currentang = newangle;
  273.             else
  274.             currentang = maxang;
  275.  
  276.             PSdrawCircSlider(bounds.size.height,bounds.size.width,x,y,radius,currentang);
  277.             [window flushWindow];
  278.             if (CircFlags.continuous == 1)
  279.             [self sendAction: _action to: _target];
  280.         }else{
  281.             looping = NO;
  282.             [window flushWindow];
  283.             [self sendAction: _action to: _target];
  284.         }
  285.         }
  286.     
  287.         /* Release the drawing context and restore the event mask */
  288.         [self unlockFocus];
  289.         [window setEventMask:oldMask];
  290.     }
  291.     return self;
  292. }
  293.  
  294. - read:(NXTypedStream *)stream
  295. {
  296.     [super read:stream];
  297.     NXReadTypes(stream,"fffffi@:",¤tang,&maxang,&radius,&x,&y,&CircFlags,&_target,&_action);
  298.     return(self);
  299. }
  300.  
  301. - write:(NXTypedStream *)stream
  302. {
  303.     [super write:stream];
  304.     NXWriteTypes(stream,"fffffi@:",¤tang,&maxang,&radius,&x,&y,&CircFlags,&_target,&_action);
  305.     return(self);
  306. }
  307.  
  308. - (const char *)getInspectorClassName
  309. {
  310.     return "CircularSliderInspector";
  311. }
  312. @end
  313.