home *** CD-ROM | disk | FTP | other *** search
/ Nebula / nebula.bin / SourceCode / Classes / Gauges / Gauge.m < prev    next >
Text File  |  1993-01-19  |  11KB  |  463 lines

  1.  
  2. /* Generated by Interface Builder */
  3.  
  4. #import "Gauge.h"
  5. #import <appkit/graphics.h>
  6. #import <appkit/Window.h>
  7.  
  8. #define GAUGEQUANTTICS \
  9.     if (GaugeDat.ticQuanta){ \
  10.         GaugeDat.ticSize = \
  11.             (((int)(GaugeDat.ticSize/GaugeDat.ticQuanta))+1) \
  12.             *GaugeDat.ticQuanta; \
  13.         GaugeDat.startValue = \
  14.             (((int)(GaugeDat.startValue/GaugeDat.ticSize))-1) \
  15.             *GaugeDat.ticSize; \
  16.     }
  17.  
  18. @implementation Gauge
  19.  
  20. /**********************************************************************/
  21. /* Factory Methods 
  22. /**********************************************************************/
  23.  
  24. + newFrame: (NXRect *) r
  25. {
  26.     self = [super newFrame:r];
  27.     GaugeDat.backGray = NX_LTGRAY;
  28.     GaugeDat.faceGray = NX_WHITE;
  29.     GaugeDat.ticGray = NX_BLACK;
  30.     GaugeDat.textGray = NX_BLACK;
  31.     GaugeDat.ptGray = NX_DKGRAY;
  32.     [self changeBMSize];
  33.     GaugeDat.startValue = 0.0;
  34.     GaugeDat.ticSize = 0.1;
  35.     GaugeDat.value = 0.5;
  36.     GaugeDat.numMajor = 11;
  37.     GaugeDat.numMinor = 1;
  38.     GaugeDat.ticQuanta = 0.0;    /* tic can be any size */
  39.     GaugeDat.aThreshHi = 0.9;
  40.     GaugeDat.aThreshLo =0.1; 
  41.     GaugeDat.labelTicPat = "%1.1f";    /* one sig dig on each side */
  42.     GaugeDat.ticFontName = "Helvetica";
  43.     GaugeDat.titleFontName = "Helvetica";
  44.     GaugeFlags.titleOn = NO;
  45.     GaugeFlags.ticsOn = YES;
  46.     GaugeFlags.labelTicsOn = NO;
  47.     GaugeFlags.autoScaleOn = YES;
  48.     GaugeFlags.jumpChange = YES;
  49.     GaugeFlags.overFlow = NO;
  50.     GaugeFlags.autoRenderBit = YES;    /*always re render on changes */
  51.     GaugeFlags.borderType =    NX_NOBORDER;
  52.     return self;
  53. }
  54. /**********************************************************************/
  55. /* Private Methods 
  56. /**********************************************************************/
  57. - reScaleGauge:sender
  58. /* return self if overrun or rescale
  59. /*    else return nil;
  60. /* This gets called if value is out of thresholds and auto scale is on.
  61. /*
  62. /* Autoscaling with no labels will cause the number of tics to change
  63. /*    when blowing up or shrinking tic mark values otherwise ...
  64. /*
  65. /* This will rescale the tic marks or start values under thse rules
  66. /* Underrun:
  67. /*    if .aThreshLo > 0.0 
  68. /*    then move low point so we are centered
  69. /*    else if aThreshHi < 1.0 
  70. /*    then rescale tic marks to blow up
  71. /*    
  72. /* Overrun
  73. /*    if .aThreshHi < 1.0
  74. /*    then move the tic marks to shrink
  75. /*    else if .aThreshLo > 0.0
  76. /*    then move up low so this is centered
  77. /*
  78. /* Bugs
  79. /*    no way to tell it fixed increment scaling 
  80. /*    no wayt to autoscale and cap 
  81. /*
  82. /*                             */
  83. {
  84.     double tStart;
  85.     double tSize;
  86.     
  87.     GaugeFlags.overFlow = NO;
  88.     if ((GaugeDat.value < GAUGEHI) && (GaugeDat.value > GAUGELO))
  89.         return nil;
  90.     /* if not autoscaling or both bounds locked then ... */
  91.     if (!GaugeFlags.autoScaleOn ||
  92.             ((GaugeDat.aThreshLo <= 0.0) && (GaugeDat.aThreshHi >= 1.0))){
  93.         if ((GaugeDat.value < GAUGELO) || (GaugeDat.value > GAUGEHI)){
  94.             GaugeFlags.overFlow = YES;
  95.             if (GaugeDat.value > GAUGEMAX)     GaugeDat.value = GAUGEMAX;
  96.             else if (GaugeDat.value < GaugeDat.startValue)
  97.                 GaugeDat.value = GaugeDat.startValue;
  98.             [self sendAction:action to:target];
  99.             return self;
  100.         } else return nil;
  101.     }
  102.     /* we know we have at least one valid threshold if we got this far */
  103.     /* and we have an overrun or underrun condition */
  104.     if (GaugeDat.value > GAUGEHI){ /* overrun */
  105.         if (!GaugeFlags.labelTicsOn){
  106.             GaugeDat.numMajor += GaugeDat.numMajor -1 ;
  107.         }else if (GaugeDat.aThreshHi < 1.0){ /* scale tics */
  108.             GaugeDat.ticSize = GAUGESIZE*2 / (GaugeDat.numMajor-1);
  109.         }else{    /* move start */
  110.             GaugeDat.startValue += GAUGESIZE / 2;
  111.         }
  112.     }else{         /* underrun */
  113.         if (!GaugeFlags.labelTicsOn ){
  114.             if (GaugeDat.numMajor > 2)
  115.                 GaugeDat.numMajor=((GaugeDat.numMajor-1)/2)+1;
  116.         }else if (GaugeDat.aThreshLo > 0.0){ /*move the start down */
  117.             GaugeDat.startValue -= GAUGESIZE / 2;
  118.         }else{     /* change tic size */
  119.             GaugeDat.ticSize = GAUGESIZE/2 / (GaugeDat.numMajor-1);
  120.         }
  121.     }
  122.     GAUGEQUANTTICS
  123.  
  124.     return self;
  125. }
  126.  
  127. /**********************************************************************/
  128. /* Public Methods 
  129. /**********************************************************************/
  130. - changeBMSize
  131. {
  132.     NXRect    r;
  133.     
  134.     [self getBounds:&r];
  135.     if (GaugeDat.bm) [GaugeDat.bm free];
  136.     // Create offscreen window for face. Note that the defer: argument
  137.     // has to be NO for windows which will remain offscreen. Deferred
  138.     // windows only get created on a orderFront: (or any other method
  139.     // that causes them to come on screen).
  140.  
  141.     GaugeDat.bm = [Window newContent:&r 
  142.             style:NX_PLAINSTYLE
  143.             backing:NX_RETAINED 
  144.             buttonMask:0 
  145.             defer:NO];  
  146.     GaugeDat.bmgState = (int)[GaugeDat.bm gState];  
  147.     CONDITIONAL_REFRESH;
  148.     return self;
  149. }
  150. - sizeTo:(NXCoord)tW :(NXCoord)tH
  151. {
  152.     fprintf(stderr,"in sizeTo\n");
  153.     [self changeBMSize];
  154.     return self;
  155. }
  156. - refreshBackground:sender;
  157. /* redraw the bitmap - subclasses should override */
  158. /* Subclasses should re image the bitmap and then do [self display] */
  159. {
  160.     [self display];
  161.     return self;
  162. }
  163.  
  164. /*____________________________________________________________________*/
  165.  
  166. - setBackGray:(float)bg Face:(float)fg Tic:(float)tg Text:(float)teg 
  167.             Point:(float)pg
  168. {
  169.     GaugeFlags.autoRenderBit = NO;
  170.     [self setBackgroundGray:bg];
  171.     [self setFaceGray:fg];
  172.     [self setTicGray:tg];
  173.     [self setTextGray:teg];
  174.     GaugeFlags.autoRenderBit = YES;
  175.     CONDITIONAL_REFRESH;
  176.     [self setPointerGray:pg];
  177.     return self;
  178. }
  179. - setBackgroundGray:(float)tC
  180. {
  181.     if ((tC > 1.0) || (tC < 0.0)) return nil;
  182.     GaugeDat.backGray = tC;
  183.     CONDITIONAL_REFRESH;
  184.     return self;
  185. }
  186. - setFaceGray:(float)tC
  187. {
  188.     if ((tC > 1.0) || (tC < 0.0)) return nil;
  189.     GaugeDat.faceGray = tC;
  190.     CONDITIONAL_REFRESH;
  191.     return self;
  192. }
  193. - setTicGray:(float)tC
  194. {
  195.     if ((tC > 1.0) || (tC < 0.0)) return nil;
  196.     GaugeDat.ticGray = tC;
  197.     if (GaugeFlags.ticsOn)     CONDITIONAL_REFRESH;
  198.     return self;
  199. }
  200. - setTextGray:(float)tC
  201. {
  202.     if ((tC > 1.0) || (tC < 0.0)) return nil;
  203.     GaugeDat.textGray = tC;
  204.     if (GaugeFlags.labelTicsOn || GaugeFlags.titleOn) 
  205.         CONDITIONAL_REFRESH;
  206.     return self;
  207. }
  208. - setPointerGray:(float)tC
  209. {
  210.     if ((tC > 1.0) || (tC < 0.0)) return nil;
  211.     GaugeDat.ptGray = tC;
  212.     [self display];
  213.     return self;
  214. }
  215. - (float)backgroundGray
  216. {
  217.     return GaugeDat.backGray;
  218. }
  219. - (float)faceGray
  220. {
  221.     return GaugeDat.faceGray;
  222. }
  223. - (float)ticGray
  224. {
  225.     return GaugeDat.ticGray;
  226. }
  227. - (float)textGray
  228. {
  229.     return GaugeDat.textGray;
  230. }
  231. - (float)pointerGray
  232. {
  233.     return GaugeDat.ptGray;
  234. }
  235.  
  236. /*____________________________________________________________________*/
  237.  
  238.  
  239. - setLowThresh:(double)lT HighThresh:(double)hT AndQuanta:(double)qT
  240. {
  241.     if ((lT < 1.0) && (lT >= 0.0)) GaugeDat.aThreshLo = lT;
  242.     if ((hT > 0.0) && (hT <= 1.0)) GaugeDat.aThreshHi = hT;
  243.     GaugeDat.ticQuanta = qT;
  244.     return self;
  245. }
  246. - setTic:(double)sTic AndStart:(double)aStart;
  247. /* this is so we can do auto scale with only one bitmap redraw */
  248. {
  249.     if (sTic <= 0.0) return nil;
  250.     GaugeDat.ticSize = sTic;
  251.     GaugeDat.startValue = aStart;
  252.     GAUGEQUANTTICS
  253.     if ((GaugeDat.value > GAUGEHI) || (GaugeDat.value < GAUGELO)){
  254.             [self reScaleGauge:self];
  255.     } else GaugeFlags.overFlow = NO;
  256.     CONDITIONAL_REFRESH;
  257.     return self;
  258. }
  259. - setTicSize:(double)sTic
  260. {
  261.     [self setTic:sTic AndStart:GaugeDat.startValue];
  262.     return self;
  263. }
  264. - setStartValue:(double)aStart
  265. {
  266.     [self setTic:GaugeDat.ticSize AndStart:aStart];
  267.     return self;
  268. }    
  269. - setDoubleValue:(double)aD
  270. /* if autoscale and out of range then do it ... else load value and display */
  271. {
  272.     GaugeDat.value = aD;
  273.     if ((aD <= GAUGELO) || (aD >= GAUGEHI)){
  274.         if ([self reScaleGauge:self] != nil)
  275.             CONDITIONAL_REFRESH;
  276.         else [self display];
  277.     }else{
  278.         GaugeFlags.overFlow = NO;
  279.         [self display];
  280.     }
  281.     return self;
  282. }
  283. - setFloatValue:(float)aF
  284. {
  285.     [self setDoubleValue:(double)aF];
  286.     return self;
  287. }
  288. - takeDoubleValueFrom:sender;
  289. {
  290.     [self setDoubleValue:[sender doubleValue]];
  291.     return self;
  292. }
  293. - takeFloatValueFrom:sender;
  294. {
  295.     [self setDoubleValue:(double)[sender floatValue]];
  296.     return self;
  297. }
  298. - (double)maxValue
  299. {
  300.     return GAUGEMAX;
  301. }
  302. - (double)ticSize
  303. {
  304.     return GaugeDat.ticSize;
  305. }
  306. - (double)startValue
  307. {
  308.     return GaugeDat.startValue;
  309. }
  310. - (double)doubleValue
  311. {
  312.     return GaugeDat.value;
  313. }
  314. - (float)floatValue
  315. {
  316.     return (float)GaugeDat.value;
  317. }
  318. - (BOOL)overFlowDetected
  319. {
  320.     return GaugeFlags.overFlow;
  321. }
  322.  
  323. /*____________________________________________________________________*/
  324.  
  325. - setMajorTics:(int)nTic
  326. {
  327.     if (nTic <= 1) return nil;
  328.     GaugeDat.numMajor = nTic;
  329.     CONDITIONAL_REFRESH;
  330.     return self;
  331. }
  332. - setMinorTics:(int)nTic
  333. {
  334.     if (nTic < 0) return nil;
  335.     GaugeDat.numMinor = nTic;
  336.     CONDITIONAL_REFRESH;
  337.     return self;
  338. }
  339. - setTitle:(char *)nTitle
  340. {
  341.     GaugeDat.title = nTitle;
  342.     CONDITIONAL_REFRESH;
  343.     return self;
  344. }
  345. - (int)majorTics
  346. {
  347.     return GaugeDat.numMajor;
  348. }
  349. - (int)minorTics
  350. {
  351.     return GaugeDat.numMinor;
  352. }
  353. - (char *)title
  354. {
  355.     return GaugeDat.title;
  356. }
  357.  
  358. /*____________________________________________________________________*/
  359.  
  360. - setTitleEnable:(BOOL)aFlag
  361. {
  362.     if (aFlag == GaugeFlags.titleOn) return nil;
  363.     GaugeFlags.titleOn = aFlag;
  364.     CONDITIONAL_REFRESH;
  365.     return self;
  366. }
  367. - setTicsEnable:(BOOL)aFlag
  368. {
  369.     if (aFlag == GaugeFlags.ticsOn) return nil;
  370.     GaugeFlags.ticsOn = aFlag;
  371.     CONDITIONAL_REFRESH;
  372.     return self;
  373. }
  374. - setLabelTicsEnable:(BOOL)aFlag
  375. {
  376.     if (aFlag == GaugeFlags.labelTicsOn) return nil;
  377.     GaugeFlags.labelTicsOn = aFlag;
  378.     CONDITIONAL_REFRESH;
  379.     return self;
  380. }
  381. - setAutoScaleEnable:(BOOL)aFlag
  382. {
  383.     GaugeFlags.autoScaleOn = aFlag;
  384.     return self;
  385. }
  386. - setJumpChangeEnable:(BOOL)aFlag
  387. {
  388.     GaugeFlags.jumpChange = aFlag;
  389.     return self;
  390. }
  391. - setBorderType:(int)aType
  392. {
  393.     if (    (aType == NX_NOBORDER) || (aType == NX_LINE) ||
  394.         (aType == NX_BEZEL)    || (aType == NX_RIDGE)){
  395.         GaugeFlags.borderType = aType;
  396.         CONDITIONAL_REFRESH;
  397.     }
  398.     return self;
  399. }
  400. - (BOOL)titleEnabled;
  401. {
  402.     return GaugeFlags.titleOn;
  403. }
  404. - (BOOL)ticsEnabled
  405. {
  406.     return GaugeFlags.ticsOn;
  407. }
  408. - (BOOL)labelTicsEnabled
  409. {
  410.     return GaugeFlags.labelTicsOn;
  411. }
  412. - (BOOL)autoScaleEnabled
  413. {
  414.     return GaugeFlags.autoScaleOn;
  415. }
  416. - (BOOL)jumpChangeEnabled
  417. {
  418.     return GaugeFlags.jumpChange;
  419. }
  420. - (int)borderType
  421. {
  422.     return GaugeFlags.borderType;
  423. }
  424.  
  425.  
  426. /*____________________________________________________________________*/
  427.  
  428. - awake
  429. {
  430.     NXRect r;
  431.     
  432.     [self getBounds:&r];
  433.     return [self changeBMSize];
  434. }
  435.  
  436. - read:(NXTypedStream*)aStream
  437. {
  438.     fprintf(stderr,"Gauge.m read:\n");
  439.     [super read:aStream];
  440.     NXReadTypes(aStream,"{ii}",&GaugeFlags);
  441.     NXReadTypes(aStream,"{fffff@idddiiddd****}",&GaugeDat);
  442.     NXReadTypes(aStream,"@:",&target,&action);
  443.     return self;
  444. }
  445.  
  446. - write:(NXTypedStream*)aStream
  447. {
  448.     fprintf(stderr,"Gauge.m: write:\n");
  449.     [super write:aStream];
  450.     NXWriteTypes(aStream,"{ii}",&GaugeFlags);
  451.     NXWriteTypes(aStream,"{fffff@idddiiddd****}",&GaugeDat);
  452.     NXWriteTypes(aStream,"@:",&target,&action);
  453.     return self;
  454. }
  455.  
  456.  
  457. /* I wish the control class would do this automaticlly */
  458. - setTarget:aTarget                { target = aTarget; return self; }
  459. - setAction:(SEL)anAction        { action = anAction; return self; }
  460.  
  461.  
  462. @end
  463.