|
|
1.1 ! root 1: /* ! 2: * BarChart, A simple multi source loadable class. ! 3: * ! 4: * Written by: Joe Freeman 7/92 ! 5: * ! 6: * HSB color sweep stolen from some of Randy Nelson's code ! 7: * should use NXEqualColor() for duplicates ! 8: * ! 9: */ ! 10: ! 11: ! 12: #import "ChartOfMatrix.h" ! 13: #import <dpsclient/psops.h> ! 14: #import <c.h> ! 15: #import <stdio.h> ! 16: ! 17: #define NUM_BOGUS 8 /* number of bars to draw when no data */ ! 18: #define COM_VERSION 3.3 /* version 3 ported to 3.0 */ ! 19: ! 20: @implementation ChartOfMatrix ! 21: ! 22: ! 23: /*============================================================ ! 24: *factory ! 25: *============================================================*/ ! 26: ! 27: ! 28: + initialize ! 29: { ! 30: [super initialize]; ! 31: [ChartOfMatrix setVersion:2]; ! 32: return self; ! 33: } ! 34: ! 35: - (const char *)getInspectorClassName ! 36: { ! 37: return "ChartOfMatrixInspector"; } ! 38: ! 39: - initFrame:(NXRect *)r ! 40: { ! 41: self = [super initFrame:r]; ! 42: minSheetSet = 0.0; ! 43: maxSheetSet = 1.0; ! 44: COM_Flags.autoScale = YES; ! 45: COM_Flags.drawType = DRAW_V_BAR; ! 46: backgroundColor = NX_COLORWHITE; ! 47: highlightColor = NX_COLORBLACK; ! 48: highlightIndex = MAXINT; /* don't show on default */ ! 49: COM_Flags.drawFrame = YES; ! 50: hMargin = vMargin = 15.0; ! 51: hMargin = vMargin = 5.0; ! 52: numPrototypes = 5; ! 53: COM_Flags.randomBarColors = YES; ! 54: return self; ! 55: } ! 56: ! 57: - awake ! 58: { ! 59: [super awake]; ! 60: highlightIndex = MAXINT; ! 61: [self registerForDraggedTypes:&NXColorPboardType count:1]; ! 62: return self; ! 63: } ! 64: ! 65: /*============================================================ ! 66: * color dragging support ! 67: *============================================================*/ ! 68: ! 69: - (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender ! 70: { ! 71: if ([sender draggingSourceOperationMask] & NX_DragOperationGeneric) { ! 72: return NX_DragOperationGeneric; ! 73: } else { ! 74: return NX_DragOperationNone; ! 75: } ! 76: } ! 77: ! 78: - (BOOL)performDragOperation:(id <NXDraggingInfo>)sender ! 79: { ! 80: NXColor c = NXReadColorFromPasteboard([sender draggingPasteboard]); ! 81: [self setBackgroundColor: c]; ! 82: return YES; ! 83: } ! 84: /*============================================================ ! 85: * instance set / query methods ! 86: *============================================================*/ ! 87: ! 88: - setDataSrc:anObject ! 89: { ! 90: dataSrc = anObject; ! 91: return self; ! 92: } ! 93: ! 94: - setGraphType:(int)drawCode ! 95: { COM_Flags.drawType = drawCode; [self update]; return self; } ! 96: - (int)graphType ! 97: { return COM_Flags.drawType; } ! 98: ! 99: - takeRandomColorStateFrom:sender ! 100: { [self setRandomBarColorEnabled:[sender state]]; return self; } ! 101: - setRandomBarColorEnabled:(BOOL)flag ! 102: { COM_Flags.randomBarColors = flag; [self update]; return self; } ! 103: - (BOOL)isRandomBarColorEnabled ! 104: { return COM_Flags.randomBarColors; } ! 105: ! 106: - takeBackgroundColorFrom:sender ! 107: { [self setBackgroundColor: [sender color]]; return self; } ! 108: - setBackgroundColor:(NXColor)aColor ! 109: { backgroundColor = aColor; [self update]; return self; } ! 110: - (NXColor)backgroundColor ! 111: { return backgroundColor; } ! 112: ! 113: - takeHighlightColorFrom:sender ! 114: { [self setHighlightColor: [sender color]]; return self; } ! 115: - setHighlightColor:(NXColor)aColor ! 116: { highlightColor = aColor; [self update]; return self; } ! 117: - (NXColor)highlightColor ! 118: { return highlightColor; } ! 119: ! 120: ! 121: /* set and query the size for the margins (in points) */ ! 122: - takeHMarginFrom:sender ! 123: { hMargin = [sender floatValue]; [self update]; return self; } ! 124: - takeVMarginFrom:sender ! 125: { vMargin = [sender floatValue]; [self update]; return self; } ! 126: - (float)hMargin ! 127: { return hMargin; } ! 128: - (float)vMargin ! 129: { return vMargin; } ! 130: ! 131: - takeAutoScaleStateFrom:sender ! 132: { COM_Flags.autoScale = [sender floatValue]; return self; } ! 133: - setAutoScale:(BOOL)flag ! 134: { COM_Flags.autoScale = flag; [self update]; return self; } ! 135: - (BOOL)autoScale ! 136: { return COM_Flags.autoScale; } ! 137: ! 138: /* fancy controls */ ! 139: - takeFrameStateFrom:sender ! 140: { COM_Flags.drawFrame = [sender state]; [self update]; return self; } ! 141: - (BOOL)frameState ! 142: { return COM_Flags.drawFrame; } ! 143: ! 144: - takeNumProtosFrom:sender ! 145: { numPrototypes= [sender intValue]; [self update]; return self; } ! 146: - (int)numProtos ! 147: { return numPrototypes; } ! 148: ! 149: - takeBorderTypeFrom:sender ! 150: { borderType = [sender tag]; [self update]; return self; } ! 151: - (int)borderType ! 152: { return borderType; } ! 153: ! 154: /* when autoscale is off, set the min and max for the sheet */ ! 155: - takeMinValueFrom:sender ! 156: { minSheetSet = [sender floatValue]; return self; } ! 157: - takeMaxValueFrom:sender ! 158: { maxSheetSet = [sender floatValue]; return self; } ! 159: - (double)minValue ! 160: { return minSheetSet; } ! 161: - (double)maxValue ! 162: { return maxSheetSet; } ! 163: ! 164: ! 165: /*============================================================ ! 166: * target/action ! 167: *============================================================*/ ! 168: ! 169: - (BOOL)acceptsFirstResponder { return YES; } ! 170: ! 171: - copy:sender ! 172: { ! 173: id pb = [Pasteboard new]; /* global pasteboard object */ ! 174: NXStream *st; /* stream to collect data in */ ! 175: char *data; /* actual data buffer */ ! 176: int length; /* length of data */ ! 177: int maxLength; /* (not used here) */ ! 178: ! 179: /* declare that we will supply a single type of data, eps */ ! 180: [pb declareTypes:&NXPostScriptPboard num:1 owner:self]; ! 181: ! 182: /* get a stream which writes to memory */ ! 183: st = NXOpenMemory (NULL, 0, NX_WRITEONLY); ! 184: ! 185: /* find bounding box and then write it to the stream */ ! 186: [self copyPSCodeInside:&bounds to:st]; ! 187: ! 188: /* get actuall data buffer form stream */ ! 189: NXGetMemoryBuffer (st, &data, &length, &maxLength); ! 190: ! 191: /* write data to pasteboard */ ! 192: [pb writeType:NXPostScriptPboard data:data length:length ]; ! 193: ! 194: /* dealocate stream including it's buffer */ ! 195: NXCloseMemory (st, NX_FREEBUFFER ); ! 196: ! 197: ! 198: return self; ! 199: } ! 200: ! 201: /*============================================================ ! 202: * do real work ! 203: *============================================================*/ ! 204: ! 205: - (int)numLocations ! 206: { ! 207: int numRows,numCols; ! 208: ! 209: if ([dataSrc respondsTo:@selector(getValue:forProperty:at:)]){ ! 210: return [dataSrc count]; ! 211: } else if ([dataSrc respondsTo:@selector(selectedCell)]){ ! 212: [dataSrc getNumRows:&numRows numCols:&numCols]; ! 213: return MAX(numRows,numCols); ! 214: } else if (!dataSrc) { ! 215: /* put up some dummy graph on palette */ ! 216: return NUM_BOGUS; ! 217: } ! 218: return 0; ! 219: } ! 220: ! 221: - (float)valueOfLocation:(int)n ! 222: { ! 223: static float data[NUM_BOGUS] = {.1, .3, .2, .7, .4, .8, .5, .98}; ! 224: int numRows,numCols; ! 225: float theValue; ! 226: id mrValue = [[DBValue alloc] init]; ! 227: ! 228: if ([dataSrc respondsTo:@selector(getValue:forProperty:at:)]){ ! 229: [dataSrc getValue:mrValue forProperty:mrExpression at:n]; ! 230: theValue = [mrValue floatValue]; ! 231: [mrValue free]; ! 232: return theValue; ! 233: } else if ([dataSrc respondsTo:@selector(selectedCell)]){ ! 234: [dataSrc getNumRows:&numRows numCols:&numCols]; ! 235: if (numCols == 1) { ! 236: return [[dataSrc cellAt:n :0] floatValue]; ! 237: } else { /* numRows == 1 */ ! 238: return [[dataSrc cellAt:0 :n] floatValue]; ! 239: } ! 240: } else if (!dataSrc) { ! 241: return data[n]; ! 242: } ! 243: ! 244: return 0.0; ! 245: } ! 246: ! 247: /*============================================================ ! 248: * target action loading ! 249: *============================================================*/ ! 250: ! 251: - plotFromMatrix:sender ! 252: { ! 253: if (!dataSrc && [sender respondsTo:@selector(selectedCell)]){ ! 254: [self setDataSrc:sender]; ! 255: } ! 256: [self update]; ! 257: return self; ! 258: } ! 259: ! 260: /*============================================================ ! 261: * dbKit support ! 262: *============================================================*/ ! 263: ! 264: - associationContentsDidChange:association ! 265: { ! 266: mrFetchGroup = [association fetchGroup]; ! 267: dataSrc = [mrFetchGroup recordList]; ! 268: highlightIndex = [mrFetchGroup currentRecord]; ! 269: mrExpression = [association expression]; ! 270: [self update]; ! 271: return self; ! 272: } ! 273: ! 274: /* ! 275: ** adh 7/27/92 ! 276: ** Do this so we redraw when values are updated in the UI ! 277: */ ! 278: - association:association setValue:(DBValue *)value ! 279: { ! 280: return [self update]; ! 281: } ! 282: ! 283: - associationSelectionDidChange:association ! 284: { ! 285: /* assume fetchgroup doesn't change so don't update mrFetchGroup */ ! 286: highlightIndex = [[association fetchGroup] currentRecord]; ! 287: return [self update]; ! 288: } ! 289: ! 290: - associationCurrentRecordDidDelete:association ! 291: { ! 292: /* assumes record list is the same */ ! 293: return [self update]; ! 294: return self; ! 295: } ! 296: ! 297: /*============================================================ ! 298: * do a selection with the mouse ! 299: *============================================================*/ ! 300: ! 301: - mouseDown:(NXEvent *)theEvent ! 302: { ! 303: NXEvent lastEvent; ! 304: NXRect rectOfBar; ! 305: NXRect drawRect; ! 306: int longSize = [self numLocations]; ! 307: int index; ! 308: ! 309: ! 310: if ((COM_Flags.drawType != DRAW_H_BAR && ! 311: COM_Flags.drawType != DRAW_V_BAR ) || ! 312: ![dataSrc respondsTo:@selector(getValue:forProperty:at:)]) { ! 313: NXBeep(); ! 314: return nil; ! 315: } ! 316: ! 317: lastEvent = *theEvent; ! 318: [self convertPoint: &lastEvent.location fromView:nil]; ! 319: /* modify the mouse position to be in psuedo drawing area coords */ ! 320: lastEvent.location.x -= hMargin; ! 321: lastEvent.location.y -= vMargin; ! 322: ! 323: /* allow for the margins when calc'ing the bar moused down on */ ! 324: drawRect = bounds; ! 325: drawRect.origin.x += hMargin; ! 326: drawRect.origin.y += vMargin; ! 327: drawRect.size.width -= (2*hMargin); ! 328: drawRect.size.height -= (2*vMargin); ! 329: ! 330: for ( index = 0 ; index < longSize; index++){ ! 331: if (COM_Flags.drawType == DRAW_V_BAR) { ! 332: [self calcRect:&rectOfBar ofBar:index ! 333: insideRect:&drawRect ! 334: usingMin:NX_Y(&bounds) ]; ! 335: rectOfBar.origin.y = bounds.origin.y; ! 336: rectOfBar.size.height = bounds.size.height; ! 337: } else if (COM_Flags.drawType == DRAW_H_BAR) { ! 338: [self calcRect:&rectOfBar ofBar:index ! 339: insideRect:&drawRect ! 340: usingMin:NX_X(&bounds) ]; ! 341: rectOfBar.origin.x = bounds.origin.x; ! 342: rectOfBar.size.width = bounds.size.width; ! 343: } else { ! 344: return nil; ! 345: } ! 346: if ([self mouse:&lastEvent.location inRect:&rectOfBar]){ ! 347: [mrFetchGroup setCurrentRecord:index]; ! 348: break; ! 349: } ! 350: } ! 351: return self; ! 352: } ! 353: ! 354: /*============================================================ ! 355: * target/action ! 356: *============================================================*/ ! 357: ! 358: - read:(NXTypedStream *)stream ! 359: { ! 360: int tmpScale, tmpDrawFrame, tmpDrawType; ! 361: [super read:stream]; ! 362: dataSrc = NXReadObject(stream); ! 363: minField = NXReadObject(stream); ! 364: maxField = NXReadObject(stream); ! 365: meanField = NXReadObject(stream); ! 366: /* the first demo palette went out as version 1 */ ! 367: if (NXTypedStreamClassVersion(stream, "ChartOfMatrix")<2) { ! 368: NXReadTypes(stream,"ffffiii", ! 369: &minSheetSet,&maxSheetSet, ! 370: &vMargin,&hMargin, ! 371: &tmpScale, ! 372: &tmpDrawType, ! 373: &tmpDrawFrame); ! 374: COM_Flags.autoScale = tmpScale; ! 375: COM_Flags.drawType = tmpDrawType; ! 376: COM_Flags.drawFrame = tmpDrawFrame; ! 377: COM_Flags.randomBarColors = YES; ! 378: } else { ! 379: NXReadTypes(stream,"ffffi", ! 380: &minSheetSet,&maxSheetSet, ! 381: &vMargin,&hMargin, ! 382: &COM_Flags); ! 383: } ! 384: ! 385: backgroundColor = NXReadColor(stream); ! 386: highlightColor = NXReadColor(stream); ! 387: NXReadTypes(stream,"ii", ! 388: &numPrototypes, ! 389: &borderType); ! 390: return self; ! 391: } ! 392: ! 393: - write:(NXTypedStream *)stream ! 394: { ! 395: [super write:stream]; ! 396: NXWriteObjectReference(stream, dataSrc); ! 397: NXWriteObjectReference(stream, minField); ! 398: NXWriteObjectReference(stream, maxField); ! 399: NXWriteObjectReference(stream, meanField); ! 400: NXWriteTypes(stream,"ffffi", ! 401: &minSheetSet,&maxSheetSet, ! 402: &vMargin,&hMargin, ! 403: &COM_Flags); ! 404: NXWriteColor(stream, backgroundColor); ! 405: NXWriteColor(stream, highlightColor); ! 406: NXWriteTypes(stream,"ii", ! 407: &numPrototypes, ! 408: &borderType); ! 409: return self; ! 410: } ! 411: ! 412: /*============================================================ ! 413: *display ! 414: *============================================================*/ ! 415: ! 416: - calcMin:(float *)rMin andMax:(float *)rMax andMean:(float *)rMean; ! 417: { ! 418: int index; ! 419: int longSize; ! 420: float thisVal; ! 421: float sumAll = 0; ! 422: ! 423: *rMin = *rMax = [self valueOfLocation:0]; ! 424: longSize = [self numLocations]; ! 425: ! 426: /* first figure out what the maxs and mins are */ ! 427: for ( index = 0 ; index < longSize; index++){ ! 428: thisVal = [self valueOfLocation:index]; ! 429: if (*rMin > thisVal) *rMin = thisVal; ! 430: if (*rMax < thisVal) *rMax = thisVal; ! 431: sumAll += thisVal; ! 432: } ! 433: *rMean = sumAll / longSize; ! 434: ! 435: [minField setFloatValue:*rMin]; ! 436: [maxField setFloatValue:*rMax]; ! 437: [meanField setFloatValue:*rMean]; ! 438: return self; ! 439: } ! 440: ! 441: - renderVLines:(NXRect *)r min:(float )minSheetVal max:(float )maxSheetVal ! 442: { ! 443: int longSize; /* numRows or numCols, whichever is the long side */ ! 444: int index; ! 445: float thisVal; ! 446: float cellWidth; /* the width of a unit (N) to plot */ ! 447: ! 448: /* scale the plot */ ! 449: PSscale(1.0, r->size.height / ( maxSheetVal - minSheetVal) ); ! 450: PStranslate(0.0, -minSheetVal); ! 451: ! 452: longSize = [self numLocations]; ! 453: cellWidth = r->size.width / (longSize); ! 454: ! 455: /* now plot each square */ ! 456: PSsetgray(NX_BLACK); ! 457: thisVal = [self valueOfLocation:0]; ! 458: PSmoveto(cellWidth/2.0, thisVal); ! 459: for ( index = 0 ; index < longSize; index++){ ! 460: thisVal = [self valueOfLocation:index]; ! 461: PSlineto(cellWidth*index+ cellWidth/2.0, thisVal); ! 462: } ! 463: PSstroke(); ! 464: return self; ! 465: } ! 466: ! 467: /* we can position the bars anywhere inside the view by changing the ! 468: * insideRect parameter ! 469: */ ! 470: - calcRect:(NXRect *)r ! 471: ofBar:(int)n ! 472: insideRect:(NXRect *)boundingRect ! 473: usingMin:(float)minSheetVal ! 474: { ! 475: float thisVal; ! 476: float cellWidth; /* width of a unit (N) to plot */ ! 477: ! 478: thisVal = [self valueOfLocation:n]; ! 479: if (COM_Flags.drawType == DRAW_V_BAR){ ! 480: cellWidth = boundingRect->size.width / (3 * [self numLocations] + 1); ! 481: r->origin.x = n * 3 * cellWidth + cellWidth; ! 482: if (thisVal < 0.0){ ! 483: r->origin.y = thisVal; ! 484: r->size.height = -thisVal; ! 485: }else{ ! 486: r->origin.y = MAX(minSheetVal, 0.0); ! 487: r->size.height= thisVal-r->origin.y; ! 488: } ! 489: r->size.width = 2 * cellWidth; ! 490: } else /* assume h bar */ { ! 491: cellWidth = boundingRect->size.height / (3 * [self numLocations] + 1); ! 492: r->origin.y = n * 3 * cellWidth + cellWidth; ! 493: if (thisVal < 0.0){ ! 494: r->origin.x = thisVal; ! 495: r->size.width = -thisVal; ! 496: }else{ ! 497: r->origin.x = MAX(minSheetVal, 0.0); ! 498: r->size.width= thisVal - r->origin.x; ! 499: } ! 500: r->size.height = 2 * cellWidth; ! 501: } ! 502: ! 503: return self; ! 504: } ! 505: ! 506: /* this should probably be empty but because Kris asked for a bar/lines switch ! 507: * in the inspectorwe have the abillity to draw bars (vertical). Of course ! 508: * this makes the vertical bar drawing object almost codeless ! 509: */ ! 510: - renderBars:(NXRect *)r min:(float )minSheetVal max:(float )maxSheetVal ! 511: { ! 512: int longSize; /* numRows/numCols, whichever is long side */ ! 513: int index; ! 514: NXRect barRect; /* bounding rectangle for bar in the chart */ ! 515: NXColor HSBColor; /* in case randomBarColors */ ! 516: ! 517: longSize = [self numLocations]; ! 518: if (COM_Flags.drawType == DRAW_V_BAR){ ! 519: /* scale the plot */ ! 520: PSscale(1.0, r->size.height / ( maxSheetVal - minSheetVal) ); ! 521: PStranslate(0.0, -minSheetVal); ! 522: } else /* assume h bar */ { ! 523: /* scale the plot */ ! 524: PSscale(r->size.width / ( maxSheetVal - minSheetVal), 1.0 ); ! 525: PStranslate( -minSheetVal, 0.0); ! 526: } ! 527: ! 528: /* now plot each square */ ! 529: for ( index = 0 ; index < longSize; index++){ ! 530: if (index == highlightIndex) ! 531: NXSetColor(highlightColor); ! 532: else if (!COM_Flags.randomBarColors) { ! 533: PSsetgray ((1.0 / (longSize+2.0)) * (index +1)); ! 534: } else { ! 535: HSBColor = NXConvertHSBToColor( ! 536: ((float)index / (float)longSize), ! 537: 1.0, 1.0); ! 538: NXSetColor(HSBColor); ! 539: } ! 540: [self calcRect:&barRect ofBar:index ! 541: insideRect:(NXRect *)r ! 542: usingMin:minSheetVal]; ! 543: NXRectFill(&barRect); ! 544: } ! 545: return self; ! 546: } ! 547: ! 548: ! 549: /* spacing: Each plot is a width of 2N and each gap is a width of 1N ! 550: * total width is m*(2N+N) + N = 3mN+N = where m = number of bars ! 551: * Thus N = width / (3m+1) ! 552: * ! 553: * scaling: The scaling can make some stuff look pretty funny. ! 554: */ ! 555: - drawSelf:(NXRect *)r :(int)c ! 556: { ! 557: float minCellVal, maxCellVal; /* min & max of values to be plotted */ ! 558: float meanCellVal; /* mean of the plotted values */ ! 559: float minSheetVal,maxSheetVal;/* RangeOfNumbers will plot in graph */ ! 560: NXRect rectOfPlot; /* bounds of rect that will hold plot */ ! 561: NXSetColor(backgroundColor); ! 562: NXRectFill(&bounds); ! 563: PSsetgray(NX_BLACK); ! 564: switch (borderType) { ! 565: case NX_LINE: ! 566: NXFrameRect(&bounds); ! 567: break; ! 568: case NX_BEZEL: ! 569: NXDrawWhiteBezel(&bounds,&bounds); ! 570: break; ! 571: case NX_GROOVE: ! 572: NXDrawGroove(&bounds, &bounds); ! 573: break; ! 574: default: break; ! 575: } ! 576: rectOfPlot= bounds; ! 577: rectOfPlot.origin.x += hMargin; ! 578: rectOfPlot.origin.y += vMargin; ! 579: rectOfPlot.size.width -=2*hMargin; ! 580: rectOfPlot.size.height -=2*vMargin; ! 581: if ( NX_WIDTH(&bounds) < (2*hMargin) || ! 582: NX_HEIGHT(&bounds) < (2*vMargin) ) ! 583: return self; ! 584: ! 585: ! 586: [window disableFlushWindow]; ! 587: PSgsave(); ! 588: PSsetlinewidth(0.0); ! 589: PStranslate (hMargin, vMargin); ! 590: ! 591: if (YES){ ! 592: /* great we only have a single axis to work on */ ! 593: [self calcMin:&minCellVal andMax:&maxCellVal andMean:&meanCellVal]; ! 594: ! 595: if (COM_Flags.autoScale){ ! 596: /* give us a plot if they are all the same (but not 0.0) */ ! 597: if (minCellVal == maxCellVal){ ! 598: if (minCellVal > 0.0) minCellVal = 0.0; ! 599: else if (maxCellVal < 0.0) maxCellVal = 0.0; ! 600: } ! 601: ! 602: /* figure out what min and the max should be on the sheet */ ! 603: if (minCellVal == 0.0) minSheetVal= 0.0; ! 604: else minSheetVal= minCellVal - ((maxCellVal - minCellVal)*0.2); ! 605: /* we shouldn't have pushed this across the origin */ ! 606: if (minSheetVal < 0.0 && minCellVal > 0.0) minSheetVal = 0.0; ! 607: ! 608: if (maxCellVal == 0.0) maxSheetVal = 0.0; ! 609: else maxSheetVal= maxCellVal +((maxCellVal - minCellVal)* 0.2); ! 610: /* make sure we didn't go across the origin */ ! 611: if (maxSheetVal > 0.0 && maxCellVal < 0.0) maxSheetVal = 0.0; ! 612: } else { ! 613: minSheetVal = minSheetSet; ! 614: maxSheetVal = maxSheetSet; ! 615: } ! 616: ! 617: switch(COM_Flags.drawType){ ! 618: case DRAW_H_BAR: ! 619: case DRAW_V_BAR: ! 620: [self renderBars:&rectOfPlot min:minSheetVal max:maxSheetVal]; ! 621: break; ! 622: case DRAW_H_LINE: ! 623: break; ! 624: case DRAW_V_LINE: ! 625: [self renderVLines:&rectOfPlot min:minSheetVal max:maxSheetVal ]; ! 626: break; ! 627: default: ! 628: break; ! 629: } ! 630: ! 631: PSgrestore(); ! 632: if (COM_Flags.drawFrame){ ! 633: PSsetgray(NX_BLACK); ! 634: NXFrameRect(&rectOfPlot); ! 635: } ! 636: } ! 637: [window reenableFlushWindow]; ! 638: return self; ! 639: } ! 640: ! 641: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.