This is Gauge.m in view mode; [Download] [Up]
/* Generated by Interface Builder */ #import "Gauge.h" #import <appkit/graphics.h> #import <appkit/Window.h> #define GAUGEQUANTTICS \ if (GaugeDat.ticQuanta){ \ GaugeDat.ticSize = \ (((int)(GaugeDat.ticSize/GaugeDat.ticQuanta))+1) \ *GaugeDat.ticQuanta; \ GaugeDat.startValue = \ (((int)(GaugeDat.startValue/GaugeDat.ticSize))-1) \ *GaugeDat.ticSize; \ } @implementation Gauge /**********************************************************************/ /* Factory Methods /**********************************************************************/ -initFrame: (const NXRect *) r { self = [super initFrame:r]; if(self!=0){ GaugeDat.backGray = NX_LTGRAY; GaugeDat.faceGray = NX_WHITE; GaugeDat.ticGray = NX_BLACK; GaugeDat.textGray = NX_BLACK; GaugeDat.ptGray = NX_DKGRAY; [self changeBMSize]; GaugeDat.startValue = 0.0; GaugeDat.ticSize = 0.1; GaugeDat.value = 0.5; GaugeDat.numMajor = 11; GaugeDat.numMinor = 1; GaugeDat.ticQuanta = 0.0; /* tic can be any size */ GaugeDat.aThreshHi = 0.9; GaugeDat.aThreshLo =0.1; GaugeDat.labelTicPat = "%1.1f"; /* one sig dig on each side */ GaugeDat.ticFontName = "Helvetica"; GaugeDat.titleFontName = "Helvetica"; GaugeFlags.titleOn = NO; GaugeFlags.ticsOn = YES; GaugeFlags.labelTicsOn = NO; GaugeFlags.autoScaleOn = YES; GaugeFlags.jumpChange = YES; GaugeFlags.overFlow = NO; GaugeFlags.autoRenderBit = YES; /*always re render on changes */ GaugeFlags.borderType = NX_NOBORDER; } return self; } /**********************************************************************/ /* Private Methods /**********************************************************************/ - reScaleGauge:sender /* return self if overrun or rescale /* else return nil; /* This gets called if value is out of thresholds and auto scale is on. /* /* Autoscaling with no labels will cause the number of tics to change /* when blowing up or shrinking tic mark values otherwise ... /* /* This will rescale the tic marks or start values under thse rules /* Underrun: /* if .aThreshLo > 0.0 /* then move low point so we are centered /* else if aThreshHi < 1.0 /* then rescale tic marks to blow up /* /* Overrun /* if .aThreshHi < 1.0 /* then move the tic marks to shrink /* else if .aThreshLo > 0.0 /* then move up low so this is centered /* /* Bugs /* no way to tell it fixed increment scaling /* no wayt to autoscale and cap /* /* */ { GaugeFlags.overFlow = NO; if ((GaugeDat.value < GAUGEHI) && (GaugeDat.value > GAUGELO)) return nil; /* if not autoscaling or both bounds locked then ... */ if (!GaugeFlags.autoScaleOn || ((GaugeDat.aThreshLo <= 0.0) && (GaugeDat.aThreshHi >= 1.0))){ if ((GaugeDat.value < GAUGELO) || (GaugeDat.value > GAUGEHI)){ GaugeFlags.overFlow = YES; if (GaugeDat.value > GAUGEMAX) GaugeDat.value = GAUGEMAX; else if (GaugeDat.value < GaugeDat.startValue) GaugeDat.value = GaugeDat.startValue; [self sendAction:action to:target]; return self; } else return nil; } /* we know we have at least one valid threshold if we got this far */ /* and we have an overrun or underrun condition */ if (GaugeDat.value > GAUGEHI){ /* overrun */ if (!GaugeFlags.labelTicsOn){ GaugeDat.numMajor += GaugeDat.numMajor -1 ; }else if (GaugeDat.aThreshHi < 1.0){ /* scale tics */ GaugeDat.ticSize = GAUGESIZE*2 / (GaugeDat.numMajor-1); }else{ /* move start */ GaugeDat.startValue += GAUGESIZE / 2; } }else{ /* underrun */ if (!GaugeFlags.labelTicsOn ){ if (GaugeDat.numMajor > 2) GaugeDat.numMajor=((GaugeDat.numMajor-1)/2)+1; }else if (GaugeDat.aThreshLo > 0.0){ /*move the start down */ GaugeDat.startValue -= GAUGESIZE / 2; }else{ /* change tic size */ GaugeDat.ticSize = GAUGESIZE/2 / (GaugeDat.numMajor-1); } } GAUGEQUANTTICS return self; } /**********************************************************************/ /* Public Methods /**********************************************************************/ - changeBMSize { NXRect r; [self getBounds:&r]; if (GaugeDat.bm) [GaugeDat.bm free]; // Create offscreen window for face. Note that the defer: argument // has to be NO for windows which will remain offscreen. Deferred // windows only get created on a orderFront: (or any other method // that causes them to come on screen). GaugeDat.bm = [Window newContent:&r style:NX_PLAINSTYLE backing:NX_RETAINED buttonMask:0 defer:NO]; GaugeDat.bmgState = (int)[GaugeDat.bm gState]; CONDITIONAL_REFRESH; return self; } - sizeTo:(NXCoord)tW :(NXCoord)tH { fprintf(stderr,"in sizeTo\n"); [self changeBMSize]; return self; } - refreshBackground:sender; /* redraw the bitmap - subclasses should override */ /* Subclasses should re image the bitmap and then do [self display] */ { [self display]; return self; } /*____________________________________________________________________*/ - setBackGray:(float)bg Face:(float)fg Tic:(float)tg text:(float)teg Point:(float)pg { GaugeFlags.autoRenderBit = NO; [self setBackgroundGray:bg]; [self setFaceGray:fg]; [self setTicGray:tg]; [self setTextGray:teg]; GaugeFlags.autoRenderBit = YES; CONDITIONAL_REFRESH; [self setPointerGray:pg]; return self; } - setBackgroundGray:(float)tC { if ((tC > 1.0) || (tC < 0.0)) return nil; GaugeDat.backGray = tC; CONDITIONAL_REFRESH; return self; } - setFaceGray:(float)tC { if ((tC > 1.0) || (tC < 0.0)) return nil; GaugeDat.faceGray = tC; CONDITIONAL_REFRESH; return self; } - setTicGray:(float)tC { if ((tC > 1.0) || (tC < 0.0)) return nil; GaugeDat.ticGray = tC; if (GaugeFlags.ticsOn) CONDITIONAL_REFRESH; return self; } - setTextGray:(float)tC { if ((tC > 1.0) || (tC < 0.0)) return nil; GaugeDat.textGray = tC; if (GaugeFlags.labelTicsOn || GaugeFlags.titleOn) CONDITIONAL_REFRESH; return self; } - setPointerGray:(float)tC { if ((tC > 1.0) || (tC < 0.0)) return nil; GaugeDat.ptGray = tC; [self display]; return self; } - (float)backgroundGray { return GaugeDat.backGray; } - (float)faceGray { return GaugeDat.faceGray; } - (float)ticGray { return GaugeDat.ticGray; } - (float)textGray { return GaugeDat.textGray; } - (float)pointerGray { return GaugeDat.ptGray; } /*____________________________________________________________________*/ - setLowThresh:(double)lT HighThresh:(double)hT AndQuanta:(double)qT { if ((lT < 1.0) && (lT >= 0.0)) GaugeDat.aThreshLo = lT; if ((hT > 0.0) && (hT <= 1.0)) GaugeDat.aThreshHi = hT; GaugeDat.ticQuanta = qT; return self; } - setTic:(double)sTic AndStart:(double)aStart; /* this is so we can do auto scale with only one bitmap redraw */ { if (sTic <= 0.0) return nil; GaugeDat.ticSize = sTic; GaugeDat.startValue = aStart; GAUGEQUANTTICS if ((GaugeDat.value > GAUGEHI) || (GaugeDat.value < GAUGELO)){ [self reScaleGauge:self]; } else GaugeFlags.overFlow = NO; CONDITIONAL_REFRESH; return self; } - setTicSize:(double)sTic { [self setTic:sTic AndStart:GaugeDat.startValue]; return self; } - setStartValue:(double)aStart { [self setTic:GaugeDat.ticSize AndStart:aStart]; return self; } - setDoubleValue:(double)aD /* if autoscale and out of range then do it ... else load value and display */ { GaugeDat.value = aD; if ((aD <= GAUGELO) || (aD >= GAUGEHI)){ if ([self reScaleGauge:self] != nil) CONDITIONAL_REFRESH; else [self display]; }else{ GaugeFlags.overFlow = NO; [self display]; } return self; } - setFloatValue:(float)aF { [self setDoubleValue:(double)aF]; return self; } - takeDoubleValueFrom:sender; { [self setDoubleValue:[sender doubleValue]]; return self; } - takeFloatValueFrom:sender; { [self setDoubleValue:(double)[sender floatValue]]; return self; } - (double)maxValue { return GAUGEMAX; } - (double)ticSize { return GaugeDat.ticSize; } - (double)startValue { return GaugeDat.startValue; } - (double)doubleValue { return GaugeDat.value; } - (float)floatValue { return (float)GaugeDat.value; } - (BOOL)overFlowDetected { return GaugeFlags.overFlow; } /*____________________________________________________________________*/ - setMajorTics:(int)nTic { if (nTic <= 1) return nil; GaugeDat.numMajor = nTic; CONDITIONAL_REFRESH; return self; } - setMinorTics:(int)nTic { if (nTic < 0) return nil; GaugeDat.numMinor = nTic; CONDITIONAL_REFRESH; return self; } - setTitle:(char *)nTitle { GaugeDat.title = nTitle; CONDITIONAL_REFRESH; return self; } - (int)majorTics { return GaugeDat.numMajor; } - (int)minorTics { return GaugeDat.numMinor; } - (char *)title { return GaugeDat.title; } /*____________________________________________________________________*/ - setTitleEnable:(BOOL)aFlag { if (aFlag == GaugeFlags.titleOn) return nil; GaugeFlags.titleOn = aFlag; CONDITIONAL_REFRESH; return self; } - setTicsEnable:(BOOL)aFlag { if (aFlag == GaugeFlags.ticsOn) return nil; GaugeFlags.ticsOn = aFlag; CONDITIONAL_REFRESH; return self; } - setLabelTicsEnable:(BOOL)aFlag { if (aFlag == GaugeFlags.labelTicsOn) return nil; GaugeFlags.labelTicsOn = aFlag; CONDITIONAL_REFRESH; return self; } - setAutoScaleEnable:(BOOL)aFlag { GaugeFlags.autoScaleOn = aFlag; return self; } - setJumpChangeEnable:(BOOL)aFlag { GaugeFlags.jumpChange = aFlag; return self; } - setBorderType:(int)aType { if ( (aType == NX_NOBORDER) || (aType == NX_LINE) || (aType == NX_BEZEL) || (aType == NX_RIDGE)){ GaugeFlags.borderType = aType; CONDITIONAL_REFRESH; } return self; } - (BOOL)titleEnabled; { return GaugeFlags.titleOn; } - (BOOL)ticsEnabled { return GaugeFlags.ticsOn; } - (BOOL)labelTicsEnabled { return GaugeFlags.labelTicsOn; } - (BOOL)autoScaleEnabled { return GaugeFlags.autoScaleOn; } - (BOOL)jumpChangeEnabled { return GaugeFlags.jumpChange; } - (int)borderType { return GaugeFlags.borderType; } /*____________________________________________________________________*/ - awake { NXRect r; [self getBounds:&r]; return [self changeBMSize]; } - read:(NXTypedStream*)aStream { fprintf(stderr,"Gauge.m read:\n"); [super read:aStream]; NXReadTypes(aStream,"{ii}",&GaugeFlags); NXReadTypes(aStream,"{fffff@idddiiddd****}",&GaugeDat); NXReadTypes(aStream,"@:",&target,&action); return self; } - write:(NXTypedStream*)aStream { fprintf(stderr,"Gauge.m: write:\n"); [super write:aStream]; NXWriteTypes(aStream,"{ii}",&GaugeFlags); NXWriteTypes(aStream,"{fffff@idddiiddd****}",&GaugeDat); NXWriteTypes(aStream,"@:",&target,&action); return self; } /* I wish the control class would do this automaticlly */ - setTarget:aTarget { target = aTarget; return self; } - setAction:(SEL)anAction { action = anAction; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.