Annotation of Examples/AppKit/SortingInAction/SortView.m, revision 1.1.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.