This is SketchView.m in view mode; [Download] [Up]
/*****************************************************************************/
/* SketchView.m */
/* implementation file for SketchView class of the SketchDemo application */
/* August 1989 Carl F. Sutter */
/*****************************************************************************/
#import "SketchView.h"
#import <appkit/appkit.h>
@implementation SketchView
/*****************************************************************************/
/* newFrame - create an instance of SketchView, and initialize it */
/*****************************************************************************/
+ newFrame:(NXRect *)rect
{
int i;
NXPoint nxpHotSpot;
/* make a new view, and initialize some flags */
self = [super newFrame:rect];
nTool = TOOL_RECT;
bOpenedWithFile = FALSE;
nCurPage = 1;
/* make the open and save-as panels */
openReq = [OpenPanel new];
saveReq = [SavePanel new];
[saveReq setRequiredFileType:"sketchD"];
/* create the bitmaps */
for (i=0; i<MAXPAGES; i++)
{
bmpPage[i] = [Bitmap newSize:bounds.size.width :bounds.size.height
type:NX_ALPHABITMAP];
[bmpPage[i] setFlip:NO];
}
/* get the drawing cursor and set it's hot spot */
curDraw = [Cursor newFromMachO:"DrawCursor.tiff"];
nxpHotSpot.x = 7.0; nxpHotSpot.y = 7.0;
[curDraw setHotSpot:&nxpHotSpot];
return( self );
} /* newFrame 8/16/89 CFS */
/*****************************************************************************/
/* outlet initialization methods */
/*****************************************************************************/
- setNewAlpha:anObject { newAlpha = anObject; return( self ); }
- setPageNum:anObject { pageNum = anObject; return( self ); }
- setNumToDraw:anObject { numToDraw = anObject; return( self ); }
/*****************************************************************************/
/* appDidInit - delegate message sent after application is set up */
/* this is the time for setting fields etc. */
/*****************************************************************************/
- appDidInit:(id)sender
{
/* clear the pages, unless a file was just loaded in to start the App */
if (!bOpenedWithFile) [self clearPages:self];
return( self );
} /* appDidInit 8/16/89 CFS */
/*****************************************************************************/
/* appAcceptsAnotherFile is an application delegate method which */
/* returns whether it is OK for the application to try to open more files */
/* with the appOpenFile:type: */
/*****************************************************************************/
- (BOOL)appAcceptsAnotherFile:sender;
{
return( YES );
} /* appAcceptsAnotherFile 11/2/89 CFS */
/*****************************************************************************/
/* appOpenFile:type: - delegate message sent to open the specified file. */
/* It is normally called by the Application object in response to open */
/* requests from the Workspace. */
/*****************************************************************************/
- (int)appOpenFile:(const char *)filename type:(const char *)aType;
{
/* set the app icon as the Miniwindow icon */
[window setMiniwindowIcon:"app"];
/* bOpenedWithFile only used for initialization, since if the user double */
/* clicks a file in the workspace to start the App, appOpenFile arrives */
/* BEFORE appDidInit! (due to Listener weirdness) */
bOpenedWithFile = TRUE;
return( [self openSketchPad:filename] );
} /* appOpenFile 9/11/89 CFS */
/*****************************************************************************/
/* newPage - flip to the page entered by the user */
/*****************************************************************************/
- newPage:sender
{
nCurPage = MAX( 1, MIN( MAXPAGES, [pageNum intValueAt:0] ) );
[pageNum setIntValue:nCurPage at:0];
[pageNum selectTextAt:0];
[self display];
return( self );
} /* newPage 8/16/89 CFS */
/*****************************************************************************/
/* clearPages - erase all the pages, and reset tablet */
/*****************************************************************************/
- clearPages:sender
{
float flNewAlpha;
int i;
strcpy( szFileName, UNTITLED );
[self setTitle];
/* get the new alpha value */
[newAlpha selectTextAt:0];
flNewAlpha = [newAlpha floatValueAt:0];
/* white out the pages */
for (i=0; i<MAXPAGES; i++)
{
[bmpPage[i] lockFocus];
PSsetalpha( flNewAlpha );
PSsetgray( NX_WHITE );
NXRectFill( &bounds );
[bmpPage[i] unlockFocus];
}
/* set the new page number, and redraw the sheets */
nCurPage = 1;
[pageNum setIntValue:nCurPage at:0];
[self display];
return( self );
} /* clearPages 8/16/89 CFS */
/*****************************************************************************/
/* setTool - set the current drawing tool */
/*****************************************************************************/
- setTool:sender
{
nTool = [[sender selectedCell] tag];
return( self );
} /* setTool 8/16/89 CFS */
/*****************************************************************************/
/* flipUp - flip up one page */
/*****************************************************************************/
- flipUp:sender
{
if (nCurPage > 1) nCurPage--;
[pageNum setIntValue:nCurPage at:0];
[self display];
return( self );
} /* flipUp 8/16/89 CFS */
/*****************************************************************************/
/* flipDown - flip down one page */
/*****************************************************************************/
- flipDown:sender
{
if (nCurPage < MAXPAGES) nCurPage++;
[pageNum setIntValue:nCurPage at:0];
[self display];
return( self );
} /* flipDown 8/16/89 CFS */
/*****************************************************************************/
/* drawSelf - draw the pages in order up to the current page */
/*****************************************************************************/
- drawSelf:(NXRect *)r :(int) count
{
int i;
int nStartPage;
nStartPage = MAX( 0, nCurPage - [numToDraw intValue] );
PSsetgray( NX_WHITE );
NXRectFill( &bounds );
for (i=nStartPage; i<nCurPage; i++)
[bmpPage[i] composite:NX_SOVER toPoint:&bounds.origin];
return( self );
} /* drawSelf 8/16/89 CFS */
/*****************************************************************************/
/* animate - draw the frames back in sequence */
/*****************************************************************************/
- animate:sender;
{
int i;
[self lockFocus];
PSsetgray( NX_WHITE );
NXRectFill( &bounds );
for (i=0; i<nCurPage; i++)
{
[bmpPage[i] composite:NX_COPY toPoint:&bounds.origin];
[[self window] flushWindow];
}
[self unlockFocus];
[self display];
return( self );
} /* animate 8/16/89 CFS */
/*****************************************************************************/
/* mouseDown - trap mouse movements, and draw new graphics */
/* the drawing is very crude here, no pswraps or anything */
/*****************************************************************************/
- mouseDown:(NXEvent *)e
{
BOOL bLooping = YES;
int nOldMask;
NXPoint pA, pB;
/* use standard instance drawing to rubber-band or draw a graphic */
nOldMask = [window addToEventMask:NX_MOUSEDRAGGEDMASK];
pA = e->location;
[self convertPoint:&pA fromView:nil];
[self lockFocus];
while (bLooping)
{
e = [NXApp getNextEvent:NX_MOUSEUPMASK | NX_MOUSEDRAGGEDMASK];
pB = e->location;
[self convertPoint:&pB fromView:nil];
PSnewinstance();
if (bLooping = (e->type == NX_MOUSEDRAGGED))
switch (nTool)
{
case TOOL_RECT: /* rubber band a rectangle */
PSsetinstance( YES );
PSsetgray( NX_BLACK );
PSrectstroke( pA.x, pA.y, pB.x - pA.x, pB.y - pA.y );
PSsetinstance( NO );
break;
case TOOL_LINE: /* rubber band a line */
PSsetinstance( YES );
PSsetgray( NX_BLACK );
PSmoveto( pA.x, pA.y );
PSlineto( pB.x, pB.y );
PSstroke();
PSsetinstance( NO );
break;
case TOOL_PENCIL: /* draw a line right on the current bitmap */
PSsetgray( NX_BLACK );
PSmoveto( pA.x, pA.y );
PSlineto( pB.x, pB.y );
PSstroke();
[window flushWindow];
[bmpPage[nCurPage - 1] lockFocus];
PSsetgray( NX_BLACK );
PSmoveto( pA.x, pA.y );
PSlineto( pB.x, pB.y );
PSstroke();
[bmpPage[nCurPage - 1] unlockFocus];
pA = pB;
break;
} /* nTool switch */
}
[self unlockFocus];
[window setEventMask:nOldMask];
/* draw the rubber banded rectangle or line on the current bitmap */
[bmpPage[nCurPage - 1] lockFocus];
PSsetgray( NX_BLACK );
if (nTool == TOOL_RECT)
PSrectstroke( pA.x, pA.y, pB.x - pA.x, pB.y - pA.y );
if (nTool == TOOL_LINE)
{
PSmoveto( pA.x, pA.y );
PSlineto( pB.x, pB.y );
PSstroke();
}
[bmpPage[nCurPage - 1] unlockFocus];
[self display];
return( self );
} /* mouseDown 8/12/89 CFS */
/*****************************************************************************/
/* showError - display an error message in an alert panel */
/*****************************************************************************/
- showError:(char *)errorMessage
{
NXRunAlertPanel( "SketchDemo Error", errorMessage, "OK", NULL, NULL );
} /* showError 9/11/89 CFS */
/*****************************************************************************/
/* openRequest - opens a new file using the open panel */
/*****************************************************************************/
- openRequest:sender
{
const char *fileName;
const char *const types[2] = {"sketchD", NULL};
if ([openReq runModalForTypes:types] && (fileName = [openReq filename]))
[self openSketchPad:fileName];
return( self );
} /* openRequest 9/11/89 CFS */
/*****************************************************************************/
/* openSketchPad - read the file and load the bitmaps */
/*****************************************************************************/
- (BOOL)openSketchPad:(const char *)fileName
{
NXTypedStream *ts;
int i;
if (!(ts = NXOpenTypedStreamForFile( fileName, NX_READONLY )))
{
[self showError:"Couldn't open file."];
return( NO );
}
/* file opened OK, load in the bitmaps and set the new filename */
[NXWait push];
for (i=0; i<MAXPAGES; i++)
{
/*[bmpPage[i] free];*/
/*bmpPage[i] = [Bitmap newFromStream:ts];*/
bmpPage[i] = NXReadObject( ts );
}
NXCloseTypedStream( ts );
strcpy( szFileName, fileName );
[self setTitle];
[self display];
[NXWait pop];
return( YES );
} /* openSketchPad 9/11/89 CFS */
/*****************************************************************************/
/* saveRequest - saves the current window under its default name */
/* if the current szFileName is "Untitled" then use saveAsRequest */
/*****************************************************************************/
- saveRequest:sender
{
if (strcmp( szFileName, UNTITLED ))
[self saveSketchPad:szFileName];
else [self saveAsRequest:sender];
return( self );
} /* saveRequest 9/11/89 CFS */
/*****************************************************************************/
/* saveAsRequest - gives the user a chance to save under a new name. */
/*****************************************************************************/
- saveAsRequest:sender
{
const char *fileName;
char *name;
char path[120];
/* split the filename into path and name */
strcpy( path, szFileName );
name = strrchr( path, '/' );
if (name) *name++ = '\0';
else
{
strcpy( path, "." );
name = szFileName;
}
/* bring up the save panel */
if (([saveReq runModalForDirectory:path file:name]) &&
(fileName = [saveReq filename]))
[self saveSketchPad:fileName];
return( self );
} /* saveAsRequest 9/11/89 CFS */
/*****************************************************************************/
/* saveSketchPad - save the current bitmaps in the named file */
/*****************************************************************************/
- (BOOL)saveSketchPad:(const char *)fileName
{
NXTypedStream *ts;
int i;
if (!(ts = NXOpenTypedStreamForFile( fileName, NX_WRITEONLY )))
{
[self showError:"Couldn't open file."];
return( NO );
}
/* file opened OK, save the bitmaps */
[NXWait push];
for (i=0; i<MAXPAGES; i++)
NXWriteObject( ts, bmpPage[i] );
NXCloseTypedStream( ts );
strcpy( szFileName, fileName );
[self setTitle];
[NXWait pop];
return( YES );
} /* saveSketchPad 9/11/89 CFS */
/*****************************************************************************/
/* resetCursorRects - override the View's method to add our drawing cursor */
/*****************************************************************************/
- resetCursorRects
{
[self addCursorRect:&bounds cursor:curDraw];
return( self );
} /* resetCursorRects 11/2/89 CFS */
/*****************************************************************************/
/* setTitle - set the window's title with the current file name */
/* don't be confused by the name of this method - a Window has a setTitle */
/* method, while a View (this code) does NOT. This is just an internal one. */
/*****************************************************************************/
- setTitle
{
const char *first;
char szTitle[80];
/* get rid of any path info, if there is any */
first = strrchr( szFileName, '/' );
if (first == NULL) first = szFileName;
else first++; /* character after last forward slash */
sprintf( szTitle, "Animation Sketch Pad - %s", first );
[window setTitle:szTitle];
} /* setTitle 11/9/89 CFS */
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.