home *** CD-ROM | disk | FTP | other *** search
- /*
- * Filename: CircularSliderCell.m
- * Created : Sun Oct 18 16:56:38 1992
- * Author : Vince DeMarco
- * <vince@whatnxt.cuc.ab.ca>
- * LastEditDate was "Wed Feb 3 17:30:28 1993"
- */
-
-
- #import "CircularSliderCell.h"
- #import <appkit/Control.h>
- #import <appkit/Application.h>
- #import <math.h>
- #import <dpsclient/psops.h>
- #import "wraps.h"
-
- /* Calculate the Absolute value of y safely */
- #define ABS(y) \
- ({typeof (y) __x = (y); \
- (__x < 0) ? (-(__x)) : (__x); })
-
- @implementation CircularSliderCell
-
- /* Given a x,y point on a cart coordinate system this function returns the angle (in degrees) from
- * the positive side of the Y- axis
- * ^
- * |
- * |\
- * <____|_|__>
- * | |
- * |<-
- * |
- */
-
- inline static float angle(float x, float y)
- {
- float result;
-
- if (y >= 0){ /* Quadrants 1,4 */
- if ( x >= 0){ /* Quadrant 1 */
- result = atan(ABS(x/y));
- result *= (180/M_PI);
- return(ABS(result));
- }else{ /* Quadrant 4 */
- result = atan(ABS(y/x));
- result *= (180/M_PI);
- return(ABS(result+270.0));
- }
- }else{ /* Quadrants 2,3 */
- if ( x >= 0){ /* Quadrant 2 */
- result = atan(ABS(y/x));
- result *= (180/M_PI);
- return(ABS(result+90.0));
- }else{ /* Quadrant 3 */
- result = atan(ABS(x/y));
- result *= (180/M_PI);
- return(ABS(result+180.0));
- }
- }
- }
-
- /*
- * xycoord does the opposite of angle,
- * given an angle and a radius, xycoord returns the x,y position of
- * a point on the radius
- * ^
- * |
- * |\
- * | \ angle in degrees
- * <____|__\___>
- * |\ |
- * | \<-
- * | \ (x,y)
- */
- inline static void xycoord(float angle, float radius,float *x, float *y)
- {
- *x = (radius - 3.0)*(float)sin((M_PI/180)*angle);
- *y = (radius - 3.0)*(float)cos((M_PI/180)*angle);
- }
-
- + (BOOL)prefersTrackingUntilMouseUp
- {
- return YES;
- }
-
- - init
- {
- self = [super init];
- minValue = value = currentang = 0.0;
- maxValue = 360.0;
- scale_value = 360.0/(ABS(maxValue-minValue));
- pieChart = hidden = jumpToMousePoint = NO;
- return self;
- }
-
- - drawSelf:(const NXRect *)cellFrame inView:controlView
- {
- center.x = cellFrame->size.width/2;
- center.y = cellFrame->size.height/2;
- radius = ( center.x < center.y ? center.x : center.y) - 4;
- scalex = cellFrame->size.height/ cellFrame->size.width;
- scaley = cellFrame->size.width / cellFrame->size.height;
-
- if ([controlView isFlipped]){
- imFlipped = YES;
- }
- if (hidden == YES){
- [controlView lockFocus];
- /* PSsetgray(0.66666); */
- NXSetColor(NX_COLORLTGRAY);
- PSrectfill(cellFrame->origin.x,cellFrame->origin.y,cellFrame->size.width,cellFrame->size.height);
- [controlView unlockFocus];
- return self;
- }
- [controlView lockFocus];
- PSgsave();
- if (imFlipped) {
- PSscale(1.0, -1.0);
- }
- if (cFlags1.bezeled == 1){
- NXDrawButton(cellFrame,cellFrame);
- }else{
- if (cFlags1.bordered == 1){
- /* PSsetgray(0.0); */
- NXSetColor(NX_COLORBLACK);
- NXFrameRect(cellFrame);
- }
- }
-
- if (pieChart == NO){
- PSDrawBackground(cellFrame->size.height,cellFrame->size.width, center.x,center.y,radius);
- }else{
- if (cFlags1.disabled == 0)
- PSDrawBackground(cellFrame->size.height,cellFrame->size.width, center.x,center.y,radius);
- }
- PSgrestore();
- [controlView unlockFocus];
-
- [self drawInside:cellFrame inView:controlView];
- return self;
- }
-
- - drawInside:(const NXRect *)cellFrame inView:aView /* Draws only control portion not bezzel */
- {
- float x,y;
-
-
- if (jumpToMousePoint == NO){
- currentang += deltaAngle;
- if (currentang > 360.0)
- currentang -= 360.0;
- if (currentang < 0.0)
- currentang += 360.0;
- }
-
- [aView lockFocus];
- PSgsave();
- if (imFlipped) {
- PSscale(1.0, -1.0);
- }
-
- if (pieChart){
- if (cFlags1.disabled == 0){
- PSPieChart(cellFrame->size.height,cellFrame->size.width,
- center.x,center.y,radius,currentang);
- }else{
- PSPieChartDisabled(cellFrame->size.height,cellFrame->size.width,
- center.x,center.y,radius,currentang);
- }
- }else{
- if (cFlags1.disabled == 0){
- xycoord(currentang,radius,&x,&y);
- PSControlKnob(cellFrame->size.height,cellFrame->size.width, center.x,center.y,radius,x,y);
- }else{
- PSControlKnobDisabled(cellFrame->size.height,cellFrame->size.width, center.x,center.y,radius);
- }
- }
- PSgrestore();
- [aView unlockFocus];
- return self;
- }
-
- - (BOOL)startTrackingAt:(const NXPoint *)startPoint inView:aView
- {
- return YES;
- }
-
- - (BOOL)trackMouse:(NXEvent *)theEvent inRect:(const NXRect *)cellFrame ofView:aView
- {
- int looping; /* Flag for while in modal loop */
- int oldMask; /* Old event mask */
- NXPoint startPoint; /* Location of mouseDown */
- NXPoint currentPoint; /* Location of mouseDragged/mouseUp */
- float newangle = 0.0;
- float startangle = 0.0;
-
- if ((cFlags1.disabled == 0) && (hidden == NO)){
- /* Allow mouseDragged events */
- oldMask = [[aView window] addToEventMask:NX_MOUSEDRAGGEDMASK];
-
- /* Get the location of the mouseDown in view coordinates */
- startPoint = theEvent->location;
- [aView convertPoint:&startPoint fromView:nil];
-
- if ([self startTrackingAt:&startPoint inView:aView]){
-
- /* Adjust the mouseDown event's location if the Slider has been
- * scaled in either the x or y direction
- */
-
- if (scalex > scaley ){
- startangle = angle(scalex*(startPoint.x-(center.x)),startPoint.y-(center.y));
- }else
- if (scalex < scaley ){
- startangle = angle(startPoint.x-(center.x),scaley*(startPoint.y-(center.y)));
- }else
- startangle = angle(startPoint.x-(center.x),startPoint.y-(center.y));
-
- if (jumpToMousePoint == YES){
- currentang = startangle;
- [self drawInside:cellFrame inView:aView];
- [[aView window] flushWindow];
- }
-
- /* Run modal loop until mouse up */
- looping = YES;
- while (looping) {
- /* Get the next mouseDragged/mouseUp event */
- theEvent=[NXApp getNextEvent:NX_MOUSEUPMASK|NX_MOUSEDRAGGEDMASK];
-
- /* Convert location to view coordinates */
- currentPoint = theEvent->location;
- [aView convertPoint:¤tPoint fromView:nil];
-
- /* Handle the event */
- if (theEvent->type == NX_MOUSEDRAGGED) {
-
- /* Adjust the mouseDown event's location if the Slider has been
- * scaled in either the x or y direction
- */
-
- if (scalex > scaley ){
- newangle = angle(scalex*(currentPoint.x-(center.x)),currentPoint.y-(center.y));
- }else
- if (scalex < scaley ){
- newangle = angle(currentPoint.x-(center.x),scaley*(currentPoint.y-(center.y)));
- }else
- if (scalex = scaley ){
- newangle = angle(currentPoint.x-(center.x),currentPoint.y-(center.y));
- }
- if (jumpToMousePoint == NO){
- deltaAngle = newangle - startangle;
- startangle = newangle;
- }else{
- currentang = newangle;
- }
- if (!finite(currentang)){
- currentang = 0.0;
- }
- if (!finite(deltaAngle)){
- deltaAngle = 0.0;
- }
- #if 0
- if (currentang != currentang){ /* If this occurs, ie this test is true then
- * currentang == NAN */
- currentang = 0.0;
- }
- if (deltaAngle != deltaAngle){ /* If this occurs, ie this test is true then
- * deltaAngle == NAN */
- deltaAngle = 0.0;
- }
- #endif
- [self drawInside:cellFrame inView:aView];
- [[aView window] flushWindow];
- if ([self continueTracking:&startPoint at:¤tPoint inView:aView]){
- [aView sendAction: action to: target];
- }
- }else{
- looping = NO;
- [[aView window] flushWindow];
- [aView sendAction: action to: target];
- }
- startPoint.x = currentPoint.x;
- startPoint.y = currentPoint.y;
- }
- [aView sendAction: action to: target];
- }
- [[aView window] setEventMask:oldMask];
- return YES;
- }
- return NO;
- }
-
- - highlight:(const NXRect *)cellFrame inView:aView lit:(BOOL)flag
- {
- return self;
- }
-
- - (float)floatValue
- {
- value = (currentang/scale_value) + minValue;
-
- return(value);
- }
-
- - (double)doubleValue
- {
- return((double)[self floatValue]);
- }
-
- - (int)intValue
- {
- return((int)[self floatValue]);
- }
-
- - setDoubleValue:(double)aDouble
- {
- [self setFloatValue:(float)aDouble];
- return self;
- }
-
- - setFloatValue:(float)aFloat
- {
- if (aFloat < minValue){
- value = minValue;
- currentang = 0;
- }else
- if (aFloat > maxValue){
- value = maxValue;
- currentang = 360.0;
- }else{
- value = aFloat;
- currentang = (value - minValue)*scale_value;
- }
-
- return self;
- }
-
- - setIntValue:(int)aInt
- {
- [self setFloatValue:(float)aInt];
- return self;
- }
-
- - (float)minValue
- {
- return minValue;
- }
-
- - setMinValue:(float)aFloat
- {
- float scale = ABS(aFloat-minValue);
- if (scale != 0.0){
- minValue = aFloat;
- scale_value = 360.0/(ABS(maxValue-minValue));
- }
- return self;
- }
-
- - (float)maxValue
- {
- return maxValue;
- }
-
- - setMaxValue:(float)aFloat
- {
- float scale = ABS(aFloat-minValue);
- if (scale != 0.0){
- maxValue = aFloat;
- scale_value = 360.0/scale;
- }
- return self;
- }
-
- - setDrawAsPieChart:(BOOL)aBOOL
- {
- pieChart = aBOOL;
- return self;
- }
-
- - (BOOL)drawAsPieChart
- {
- return pieChart;
- }
-
- - setJumpToMousePoint:(BOOL)aBOOL
- {
- jumpToMousePoint = aBOOL;
- return self;
- }
-
- - (BOOL)jumpToMousePoint
- {
- return jumpToMousePoint;
- }
-
- - setHidden:(BOOL)flag
- {
- hidden = flag;
- return self;
- }
-
- - (BOOL)hidden
- {
- return hidden;
- }
-
- - read:(NXTypedStream *)stream
- {
- [super read:stream];
- NXReadTypes(stream,"fff",&value,&maxValue,&minValue);
- NXReadTypes(stream,"ccc",&pieChart,&jumpToMousePoint,&hidden);
- NXReadTypes(stream,"ff",¤tang,&radius);
- NXReadPoint(stream,¢er);
- NXReadTypes(stream,"ffff",&deltaAngle,&scale_value,&scalex,&scaley);
- return self;
- }
-
- - write:(NXTypedStream *)stream
- {
- [super write:stream];
- NXWriteTypes(stream,"fff",&value,&maxValue,&minValue);
- NXWriteTypes(stream,"ccc",&pieChart,&jumpToMousePoint,&hidden);
- NXWriteTypes(stream,"ff",¤tang,&radius);
- NXWritePoint(stream,¢er);
- NXWriteTypes(stream,"ffff",&deltaAngle,&scale_value,&scalex,&scaley);
- return self;
- }
-
- @end
-
-