Annotation of Examples/AppKit/SortingInAction/SortView.m, revision 1.1

1.1     ! root        1: 
        !             2: /* SortView is a custom view class that displays a graphically animating sort.  
        !             3:  * Each sort creates a SortView to manage its display.  The SortView will draw 
        !             4:  * the necessary animation when a sort is moving or comparing elements.
        !             5:  *
        !             6:  * Author: Julie Zelenski, NeXT Developer Support
        !             7:  * You may freely copy, distribute and reuse the code in this example.  
        !             8:  * NeXT disclaims any warranty of any kind, expressed or implied, as to 
        !             9:  * its fitness for any particular use.
        !            10:  */
        !            11:  
        !            12:  
        !            13: #import "SortView.h"
        !            14: #import "GenericSort.h"
        !            15: #import "SortApp.h"
        !            16: #import <appkit/Font.h>
        !            17: #import <appkit/nextstd.h>
        !            18: #import <dpsclient/wraps.h>
        !            19: #import <math.h>
        !            20: #import "SortWraps.h"
        !            21: 
        !            22: extern BOOL Abort;             // global variable to signal abort 
        !            23: 
        !            24: 
        !            25: @implementation SortView:View
        !            26: 
        !            27: 
        !            28: - initSort:aSort 
        !            29: /* Each sort will create a new SortView for itself by calling initSort. 
        !            30:  * This init method sets a default size view, sets up a few instance 
        !            31:  * variables, grabs a few fonts and strings to be used later.  It also 
        !            32:  * allocates a gState for itself to improve performance, because the 
        !            33:  * sortviews are repeatedly lockFocus'ed on. 
        !            34:  */
        !            35: {      
        !            36: #define HORIZ_MARGIN 3.0
        !            37: #define VERT_MARGIN 13.0
        !            38: 
        !            39:     NXRect frameRect = {{2.0,2.0},{VIEW_WIDTH,VIEW_HEIGHT}};
        !            40: 
        !            41:     [self initFrame:&frameRect];
        !            42:     sort = aSort;
        !            43:     drawRect.size.width = bounds.size.width - 2*HORIZ_MARGIN;
        !            44:     drawRect.size.height = bounds.size.height - VERT_MARGIN;
        !            45:     drawRect.origin.x = bounds.origin.x + HORIZ_MARGIN;
        !            46:     drawRect.origin.y = bounds.origin.y;
        !            47:     numRows = 1;
        !            48:     numPixelsInRow = drawRect.size.width;
        !            49:     elementWidth = barWidth = 1.0;
        !            50:     rowHeight = drawRect.size.height;
        !            51:     numberFont = [Font newFont:"Helvetica" size:24 matrix:NX_IDENTITYMATRIX];
        !            52:     titleFont = [Font newFont:"Helvetica" size:12 matrix:NX_IDENTITYMATRIX];
        !            53:     [self setClipping:NO];     // I won't draw outside my bounds so don't clip
        !            54:     [self allocateGState];     // gstate will decrease lock/unlock focus time
        !            55:     return self;
        !            56: }    
        !            57:    
        !            58: 
        !            59: - setUpForSize:(int)numElements;
        !            60: /* This method is called by the sort when it knows how many elements are in 
        !            61:  * the current data set.  It will calculates the rowHeight and barWidth 
        !            62:  * that will allow all the elements to fit.  When there is a smaller data set,
        !            63:  * the bars are wider and there is a gap between bars. With larger data sets, 
        !            64:  * the sortView will layer the elements in more than one row 
        !            65:  */
        !            66: {
        !            67:     numRows = 1;
        !            68:     elementWidth = barWidth = floor(drawRect.size.width/numElements);
        !            69:     switch (barWidth) {
        !            70:         case 0: numRows = ceil((float)numElements/numPixelsInRow);
        !            71:                barWidth = 1.0;   
        !            72:                elementWidth = 1.0;
        !            73:                break;
        !            74:        case 1: break;
        !            75:        case 2: barWidth -= 1.0; 
        !            76:                break;
        !            77:        default: barWidth -= 2.0;
        !            78:                break;
        !            79:     }
        !            80:     rowHeight = floor(drawRect.size.height/(float)numRows);
        !            81:     return self;
        !            82: }
        !            83: 
        !            84: 
        !            85: - compare:(int)element1 value:(int)value1 with:(int)element2 value:(int)value2
        !            86: /* This method is called to show two values are being compared.  The 
        !            87:  * comparison is shown by highlighting the two bars in light gray.  This 
        !            88:  * highlighting is done with instance drawing, because I want it to be 
        !            89:  * transitory.  At each drawing request, the sortView will hide any previous 
        !            90:  * instance drawing.  This way I never have to erase the comparisons. They 
        !            91:  * will be "flushed" away in the next drawing.
        !            92:  * PSWcompareRects is a wrap which simply turns on instance drawing, sets 
        !            93:  * the gray, fills the two rectangles in gray and turns off instance drawing.
        !            94:  */
        !            95: {  
        !            96:     NXPoint pt1,pt2;
        !            97: 
        !            98:     [self lockFocus];
        !            99:     pt1.x = drawRect.origin.x + (element1%numPixelsInRow)*elementWidth;
        !           100:     pt1.y = (numRows - (element1/numPixelsInRow)-1)*rowHeight;
        !           101:     pt2.x = drawRect.origin.x + (element2%numPixelsInRow)*elementWidth;
        !           102:     pt2.y = (numRows - (element2/numPixelsInRow)-1)*rowHeight;
        !           103:     PShideinstance(0.0,0.0,bounds.size.width,bounds.size.height);
        !           104:     PSWcompareRects(pt1.x,pt1.y,barWidth,value1,pt2.x,pt2.y,value2);
        !           105:     [self unlockFocus];
        !           106:     return self;
        !           107: }
        !           108: 
        !           109: 
        !           110:  - swap:(int)element1 value:(int)value1 with:(int)element2 value:(int)value2
        !           111: /* This method is called to swap two elements.  It draws only the changed
        !           112:  * parts:  it adds height to the smaller bar (by drawing in black) and removes
        !           113:  * height from the larger bar (by drawing in white). 
        !           114:  * PSWswapRects is a wrap which sets the gray to white, fills the white 
        !           115:  * rectangle, sets the gray to black, fills the black rectangle, and flushes
        !           116:  * the drawing to the screen immediately.
        !           117:  */
        !           118: {  
        !           119:     NXPoint pt1,pt2;
        !           120: 
        !           121:     if ((value1 != value2) && !Abort) { // if values actually need to change
        !           122:         [self lockFocus];
        !           123:         pt1.x = drawRect.origin.x + (element1%numPixelsInRow)*elementWidth;
        !           124:         pt1.y = value1 + (numRows - (element1/numPixelsInRow)-1)*rowHeight;
        !           125:         pt2.x = drawRect.origin.x + (element2%numPixelsInRow)*elementWidth;
        !           126:         pt2.y = value1 + (numRows - (element2/numPixelsInRow)-1)*rowHeight;
        !           127:         PShideinstance(0.0,0.0,bounds.size.width,bounds.size.height);
        !           128:         PSWswapRects(pt1.x,pt1.y,pt2.x,pt2.y,barWidth,value2-value1);
        !           129:         [self unlockFocus];
        !           130:     }
        !           131:     return self;
        !           132: }
        !           133: 
        !           134: 
        !           135: - moveValue:(int)new to:(int)element oldValue:(int)old
        !           136: /* This method is called to change the value of an element. It draws only the 
        !           137:  * changed part:  it adds height (draws in black) if the value increased, or
        !           138:  * it removes height (draws in white) if the value decreased.
        !           139:  * PSWmoveRects is a wrap which sets the gray appropriately, fills the 
        !           140:  * rectangle, and flushes the drawing to the screen immediately.
        !           141:  */
        !           142: {
        !           143:     NXPoint p;
        !           144:     
        !           145:     if ((new != old) && !Abort) {      // if value actually needs to change
        !           146:         [self lockFocus];
        !           147:         p.x = drawRect.origin.x + (element%numPixelsInRow)*elementWidth;
        !           148:         p.y = MIN(old,new) + (numRows - (element/numPixelsInRow)-1)*rowHeight; 
        !           149:         PShideinstance(0.0,0.0,bounds.size.width,bounds.size.height);
        !           150:        PSWmoveRect(p.x,p.y,barWidth,ABS(old-new),((new>old)?NX_BLACK:NX_WHITE));
        !           151:         [self unlockFocus];
        !           152:     }
        !           153:     return self;
        !           154: }
        !           155: 
        !           156: 
        !           157: - drawSelf:(const NXRect *)rects :(int)rectCount;  
        !           158: /* In drawSelf, the sortView simple erases its background, draws the border and
        !           159:  * labels itself with the appropriate name.
        !           160:  */
        !           161: {         
        !           162:     NXEraseRect(&bounds);       
        !           163:     PSWdrawBorder(bounds.size.width,bounds.size.height);
        !           164:     [titleFont set];
        !           165:     PSWdrawName(drawRect.origin.x,drawRect.size.height,(char *)[sort getName]);
        !           166:     return self;
        !           167: }
        !           168:  
        !           169: 
        !           170: - drawStatistics;
        !           171: /* This methods displays the statistics when a sort finishes.  It fades the 
        !           172:  * sort background, and queries the sort for the necessary numbers to display 
        !           173:  * and title.  It looks up the strings for the titles in the SortApp's 
        !           174:  * NXStringTable.
        !           175:  */
        !           176: {    
        !           177:    char a[9],b[9],c[9],d[9];
        !           178:    id sTable;
        !           179:    
        !           180:     sprintf(a,"%8d",[sort totalTicks]);
        !           181:     sprintf(b,"%8d",[sort compares]);
        !           182:     sprintf(c,"%8d",[sort moves]);
        !           183:     sprintf(d,"%8d",[sort fcalls]);
        !           184:     [numberFont set];
        !           185:     PSWdrawStrings(a,b,c,d,35.0);
        !           186:     [titleFont set];
        !           187:     if (!tickString) {
        !           188:         sTable = [NXApp stringTable];
        !           189:         tickString = NXCopyStringBuffer([sTable valueForStringKey:"Ticks"]);
        !           190:         moveString = NXCopyStringBuffer([sTable valueForStringKey:"Moves"]);
        !           191:         compString = NXCopyStringBuffer([sTable valueForStringKey:"Compares"]);
        !           192:         fcallString = NXCopyStringBuffer([sTable valueForStringKey:"Fcalls"]);
        !           193:     }
        !           194:     PSWdrawStrings(tickString, compString, moveString, fcallString, 65.0);
        !           195:     return self;
        !           196: }
        !           197: 
        !           198: - displayFinished;
        !           199: /* This methods displays a sort when it finishes.  It fades the sort
        !           200:  * background, and if the sort finished normally (i.e. it wasn't canceled),
        !           201:  * it will call a method to display the sort's statistics.
        !           202:  */
        !           203: {
        !           204:     [self lockFocus];
        !           205:     PSWfade(bounds.size.width,bounds.size.height);
        !           206:     PSWdrawBorder(bounds.size.width,bounds.size.height);
        !           207:     [titleFont set];
        !           208:     PSWdrawName(drawRect.origin.x,drawRect.size.height,(char *)[sort getName]);
        !           209:     if (!Abort) 
        !           210:         [self drawStatistics];
        !           211:     [self unlockFocus];
        !           212:     [window flushWindow];
        !           213:     return self;
        !           214: }
        !           215: 
        !           216:    
        !           217: @end

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.