This is CircularSliderCell.m in view mode; [Download] [Up]
/* * 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
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.