home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.0 / NeXTSTEP3.0.iso / NextDeveloper / Examples / AppKit / SortingInAction / SortView.m < prev    next >
Encoding:
Text File  |  1992-02-18  |  7.8 KB  |  217 lines

  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.   UfawRect.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.     Ugdeinstance(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. { Uh    
  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