|
|
Sample Programs from NeXSTEP 3.3
/* 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;
drawRect.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;
PShideinstance(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.
*/
{
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.