home *** CD-ROM | disk | FTP | other *** search
-
- /* SortView is a custom view class that displays a graphically animating sort.
- * Each sort creates a SortView to manage its display. The SortView will draw
- * the necessary animation when a sort is moving or comparing elements.
- *
- * Author: Julie Zelenski, NeXT Developer Support
- * You may freely copy, distribute and reuse the code in this example.
- * NeXT disclaims any warranty of any kind, expressed or implied, as to
- * its fitness for any particular use.
- */
-
-
- #import "SortView.h"
- #import "GenericSort.h"
- #import "SortApp.h"
- #import <appkit/Font.h>
- #import <appkit/nextstd.h>
- #import <dpsclient/wraps.h>
- #import <math.h>
- #import "SortWraps.h"
-
- extern BOOL Abort; // global variable to signal abort
-
-
- @implementation SortView:View
-
-
- - initSort:aSort
- /* Each sort will create a new SortView for itself by calling initSort.
- * This init method sets a default size view, sets up a few instance
- * variables, grabs a few fonts and strings to be used later. It also
- * allocates a gState for itself to improve performance, because the
- * sortviews are repeatedly lockFocus'ed on.
- */
- {
- #define HORIZ_MARGIN 3.0
- #define VERT_MARGIN 13.0
-
- NXRect frameRect = {{2.0,2.0},{VIEW_WIDTH,VIEW_HEIGHT}};
-
- [self initFrame:&frameRect];
- sort = aSort;
- drawRect.size.width = bounds.size.width - 2*HORIZ_MARGIN;
- drawRect.size.height = bounds.size.height - VERT_MARGIN;
- UfawRect.origin.x = bounds.origin.x + HORIZ_MARGIN;
- drawRect.origin.y = bounds.origin.y;
- numRows = 1;
- numPixelsInRow = drawRect.size.width;
- elementWidth = barWidth = 1.0;
- rowHeight = drawRect.size.height;
- numberFont = [Font newFont:"Helvetica" size:24 matrix:NX_IDENTITYMATRIX];
- titleFont = [Font newFont:"Helvetica" size:12 matrix:NX_IDENTITYMATRIX];
- [self setClipping:NO]; // I won't draw outside my bounds so don't clip
- [self allocateGState]; // gstate will decrease lock/unlock focus time
- return self;
- }
-
-
- - setUpForSize:(int)numElements;
- /* This method is called by the sort when it knows how many elements are in
- * the current data set. It will calculates the rowHeight and barWidth
- * that will allow all the elements to fit. When there is a smaller data set,
- * the bars are wider and there is a gap between bars. With larger data sets,
- * the sortView will layer the elements in more than one row
- */
- {
- numRows = 1;
- elementWidth = barWidth = floor(drawRect.size.width/numElements);
- switch (barWidth) {
- case 0: numRows = ceil((float)numElements/numPixelsInRow);
- barWidth = 1.0;
- elementWidth = 1.0;
- break;
- case 1: break;
- case 2: barWidth -= 1.0;
- break;
- default: barWidth -= 2.0;
- break;
- }
- rowHeight = floor(drawRect.size.height/(float)numRows);
- return self;
- }
-
-
- - compare:(int)element1 value:(int)value1 with:(int)element2 value:(int)value2
- /* This method is called to show two values are being compared. The
- * comparison is shown by highlighting the two bars in light gray. This
- * highlighting is done with instance drawing, because I want it to be
- * transitory. At each drawing request, the sortView will hide any previous
- * instance drawing. This way I never have to erase the comparisons. They
- * will be "flushed" away in the next drawing.
- * PSWcompareRects is a wrap which simply turns on instance drawing, sets
- * the gray, fills the two rectangles in gray and turns off instance drawing.
- */
- {
- NXPoint pt1,pt2;
-
- [self lockFocus];
- pt1.x = drawRect.origin.x + (element1%numPixelsInRow)*elementWidth;
- pt1.y = (numRows - (element1/numPixelsInRow)-1)*rowHeight;
- pt2.x = drawRect.origin.x + (element2%numPixelsInRow)*elementWidth;
- pt2.y = (numRows - (element2/numPixelsInRow)-1)*rowHeight;
- Ugdeinstance(0.0,0.0,bounds.size.width,bounds.size.height);
- PSWcompareRects(pt1.x,pt1.y,barWidth,value1,pt2.x,pt2.y,value2);
- [self unlockFocus];
- return self;
- }
-
-
- - swap:(int)element1 value:(int)value1 with:(int)element2 value:(int)value2
- /* This method is called to swap two elements. It draws only the changed
- * parts: it adds height to the smaller bar (by drawing in black) and removes
- * height from the larger bar (by drawing in white).
- * PSWswapRects is a wrap which sets the gray to white, fills the white
- * rectangle, sets the gray to black, fills the black rectangle, and flushes
- * the drawing to the screen immediately.
- */
- {
- NXPoint pt1,pt2;
-
- if ((value1 != value2) && !Abort) { // if values actually need to change
- [self lockFocus];
- pt1.x = drawRect.origin.x + (element1%numPixelsInRow)*elementWidth;
- pt1.y = value1 + (numRows - (element1/numPixelsInRow)-1)*rowHeight;
- pt2.x = drawRect.origin.x + (element2%numPixelsInRow)*elementWidth;
- pt2.y = value1 + (numRows - (element2/numPixelsInRow)-1)*rowHeight;
- PShideinstance(0.0,0.0,bounds.size.width,bounds.size.height);
- PSWswapRects(pt1.x,pt1.y,pt2.x,pt2.y,barWidth,value2-value1);
- [self unlockFocus];
- }
- return self;
- }
-
-
- - moveValue:(int)new to:(int)element oldValue:(int)old
- /* This method is called to change the value of an element. It draws only the
- * changed part: it adds height (draws in black) if the value increased, or
- * it removes height (draws in white) if the value decreased.
- * PSWmoveRects is a wrap which sets the gray appropriately, fills the
- * rectangle, and flushes the drawing to the screen immediately.
- */
- {
- NXPoint p;
-
- if ((new != old) && !Abort) { // if value actually needs to change
- [self lockFocus];
- p.x = drawRect.origin.x + (element%numPixelsInRow)*elementWidth;
- p.y = MIN(old,new) + (numRows - (element/numPixelsInRow)-1)*rowHeight;
- PShideinstance(0.0,0.0,bounds.size.width,bounds.size.height);
- PSWmoveRect(p.x,p.y,barWidth,ABS(old-new),((new>old)?NX_BLACK:NX_WHITE));
- [self unlockFocus];
- }
- return self;
- }
-
-
- - drawSelf:(const NXRect *)rects :(int)rectCount;
- /* In drawSelf, the sortView simple erases its background, draws the border and
- * labels itself with the appropriate name.
- */
- { Uh
- NXEraseRect(&bounds);
- PSWdrawBorder(bounds.size.width,bounds.size.height);
- [titleFont set];
- PSWdrawName(drawRect.origin.x,drawRect.size.height,(char *)[sort getName]);
- return self;
- }
-
-
- - drawStatistics;
- /* This methods displays the statistics when a sort finishes. It fades the
- * sort background, and queries the sort for the necessary numbers to display
- * and title. It looks up the strings for the titles in the SortApp's
- * NXStringTable.
- */
- {
- char a[9],b[9],c[9],d[9];
- id sTable;
-
- sprintf(a,"%8d",[sort totalTicks]);
- sprintf(b,"%8d",[sort compares]);
- sprintf(c,"%8d",[sort moves]);
- sprintf(d,"%8d",[sort fcalls]);
- [numberFont set];
- PSWdrawStrings(a,b,c,d,35.0);
- [titleFont set];
- if (!tickString) {
- sTable = [NXApp stringTable];
- tickString = NXCopyStringBuffer([sTable valueForStringKey:"Ticks"]);
- moveString = NXCopyStringBuffer([sTable valueForStringKey:"Moves"]);
- compString = NXCopyStringBuffer([sTable valueForStringKey:"Compares"]);
- fcallString = NXCopyStringBuffer([sTable valueForStringKey:"Fcalls"]);
- }
- PSWdrawStrings(tickString, compString, moveString, fcallString, 65.0);
- return self;
- }
-
- - displayFinished;
- /* This methods displays a sort when it finishes. It fades the sort
- * background, and if the sort finished normally (i.e. it wasn't canceled),
- * it will call a method to display the sort's statistics.
- */
- {
- [self lockFocus];
- PSWfade(bounds.size.width,bounds.size.height);
- PSWdrawBorder(bounds.size.width,bounds.size.height);
- [titleFont set];
- PSWdrawName(drawRect.origin.x,drawRect.size.height,(char *)[sort getName]);
- if (!Abort)
- [self drawStatistics];
- [self unlockFocus];
- [window flushWindow];
- return self;
- }
-
-
- @end