This is DrawView.m in view mode; [Download] [Up]
/*
This class was created to control the drawing from within logo for the NeXT.
Created by :
Gary F. Desrochers (garyd@slate.mines.colorado.edu)
Sean Kerstiens (skerstie@slate.mines.colorado.edu)
Created For:
Colorado School of Mines.
Last edited:
June 25,1992
*/
#import "DrawView.h"
#import <zone.h>
#import <appkit/Matrix.h>
#import <dpsclient/wraps.h>
#import <appkit/NXImage.h>
#import <appkit/NXEPSImageRep.h>
#import <appkit/Control.h>
#import <appkit/OpenPanel.h>
#import <appkit/color.h>
#import "pslogo.h"
#import <stdlib.h>
#import <mach.h>
#import <appkit/Application.h>
#import <appkit/OpenPanel.h>
#import <appkit/SavePanel.h>
@interface DrawView(DrawViewPrivate)
// Declare methods static to this class.
- _write:(const char *)filename;
- _open:sender _newDrawing:(BOOL)doClear;
- _read:(const char *)filename _newDrawing:(BOOL)doClear;
- _doSaveWithNewName:(BOOL)doNewName retainName:(BOOL)doRetain;
- _drawTurtleImage;
@end
@implementation DrawView
- drawTurtleWith:(double)angle :(double)tox :(double)toy :(int)hide
// This routine draws the Turtle when asked to by setting the boolean to YES,
// setting the coordinates and then asking for a display.
// should be combined with clearTurtle later.
{
// First check on whether to display the turtle or not.
if(hide == 0)
{
//recache in a sense clears the NXImage.
[idTurtle recache];
drawTurtle = YES;
}
else
{
drawTurtle = NO;
}
// Set angle and Coordinates.
turtleAngle = -angle;
sRect.origin.x = tox -22.7;
sRect.origin.y = toy -32.5;
return [self display];
}
- initFrame:(const NXRect *)tF
{
[super initFrame:tF];
// Setup permanent for use later.
// See the .h file for explanation of permanent variables.
sRect.origin.x = bounds.size.width/2.0-22.7;
sRect.origin.y = bounds.size.height/2.0-32.5;
sRect.size.width = 45.4;
sRect.size.height = 65.0;
rRect = bounds;
bbox[0] = rRect.origin.x;
bbox[1] = rRect.origin.y;
bbox[2] = rRect.size.width;
bbox[3] = rRect.size.height;
thisStruct = &firstStruct;
thisStruct->nextStruct = NULL;
drawTurtle = YES;
// Make the Background a NXImage. Makes it so that for alot of the
// things that need to be done (like clearing the turtle and showing the
// turtle) easier.
[(idBackground = [[NXImage allocFromZone:[self zone]] initSize:&rRect.size]) useDrawMethod:@selector(drawBack:) inObject:self];
// Now the turtle will be easier as a NXImage also.
turtleAngle = 0.0;
idTurtle=[[NXImage allocFromZone:[self zone]] initSize:&sRect.size];
// So that they are easier to Composite, set each background to clear.
[idBackground setBackgroundColor:NX_COLORWHITE];
[idTurtle setBackgroundColor:NX_COLORCLEAR];
// We want the Turtle scalable. Just makes it easier to draw.
[idTurtle setScalable:YES];
return self;
}
-drawSelf:(NXRect *)r: (int)count
{
// Always composite copy the background.
[idBackground composite:NX_COPY toPoint:&rRect.origin];
// Draw the turtle only if drawTurtle is set to YES.
if (drawTurtle) {
[self _drawTurtleImage];
[idTurtle composite:NX_SOVER toPoint:&sRect.origin];
}
return self;
}
- drawLine:(double)type :(double)fromx :(double)fromy :(double)tox: (double)toy;
{
// Lock the focus for our drawing of the line.
[idBackground lockFocus];
// Make sure the Color is set to black.
NXSetColor(NX_COLORBLACK);
// Drawing the line is easy. Mix the Postscript commands into one command.
PSWline (fromx,fromy,tox,toy);
NXSetColor(NX_COLORWHITE);
// Now unlock our focus.
[idBackground unlockFocus];
// Now for the hard part. What if our drawing needs to be created from
// scratch. This needs to be done when printing for instance.
// Save the data for the lines into a linked list.
// Later on the option may be added to remove the previous line drawn.
// Wouldn't be to hard to do.
// Fill up the two arrays.
thisStruct->cArray[0] = dps_ucache;
thisStruct->cArray[1] = dps_setbbox;
thisStruct->oArray[0] = (float)fromx;
thisStruct->oArray[1] = (float)fromy;
thisStruct->cArray[2] = dps_moveto;
thisStruct->oArray[2] = (float)tox;
thisStruct->oArray[3] = (float)toy;
thisStruct->cArray[3] = dps_lineto;
thisStruct->nextStruct = (struct prStruct *)malloc(sizeof(struct prStruct));
thisStruct = thisStruct->nextStruct;
thisStruct->nextStruct = NULL;
// O.K. Everything set up for later.
return [self display];
}
-clearScreen;
// A clear screen needs to remove everything in the link list except the
// first element and then redraw the background.
{
struct prStruct *oldStruct = &firstStruct,*tempStruct = &firstStruct;
// Free our old background.
[idBackground free];
// Loop through the link lists and delete all the old lines.
tempStruct = tempStruct->nextStruct;
while(tempStruct != NULL)
{
oldStruct = tempStruct;
tempStruct = tempStruct->nextStruct;
free(oldStruct);
}
thisStruct = &firstStruct;
thisStruct->nextStruct = NULL;
// Now set get a new Background.
[(idBackground = [[NXImage allocFromZone:[self zone]]
initSize:&rRect.size])
useDrawMethod:@selector(drawBack:)
inObject:self];
// Set background Attribute
[idBackground setBackgroundColor:NX_COLORCLEAR];
return [self display];
}
- drawBack: image
// This routine will redraw the background if needed. It is called for
// routines like the printing routine.
{
struct prStruct *tempStruct = &firstStruct;
// Here is the big secret as how to get it to draw alot of lines real fast.
// I guess you could also loop through the link list and calculate all the
// values needed for one DPSDoUserPath. Never tried it.
// Another way would be to make a typed memory stream. That way the linked
// list could be gotten rid of. (Who knows? The Shadow knows!)
while(tempStruct->nextStruct != NULL)
{
DPSDoUserPath(tempStruct->oArray,4,dps_float,tempStruct->cArray,
4,bbox,dps_ustroke);
tempStruct = tempStruct->nextStruct;
}
return self;
}
- _drawTurtleImage
// This routine calls the post script to draw the turtle image.
{
[idTurtle lockFocus];
PSWTurtle(turtleAngle);
[idTurtle unlockFocus];
return self;
}
- print;
{
// Printing is rather simple; just send printPSCode: to the text view
// you wish to print. The print panel will automatically pop up and unless
// the user cancels the printout the text view will be printed.
// This routine prints out the screen minus the turtle in postscript.
// Need to save the old turtle type.
BOOL save = drawTurtle;
// First turn of compositing the turtle.
drawTurtle = NO;
// Find out stuff about printing.
[NXApp printInfo];
// Print it out. It is that simple.
[self printPSCode:self];
// Put the turtle compositing back the way it was
drawTurtle = save;
return self;
}
- save:sender
// Called when Save is picked from the menu.
{
return [self _doSaveWithNewName:NO retainName:YES];
}
- saveAs:sender
// Called when Save As... is picked from the menu.
{
return [self _doSaveWithNewName:YES retainName:YES];
}
- saveTo:sender
// Called when Save To... is picked from the menu.
{
return [self _doSaveWithNewName:YES retainName:NO];
}
- add:sender
// Action method, called when the user chooses add in the menu.
{
return [self _open:sender _newDrawing:NO];
}
- open:sender
// Action method, called when the user chooses open in the menu.
{
return [self _open:sender _newDrawing:YES];
}
- _open:sender _newDrawing:(BOOL)doClear
// This is used for both open and add.
// The doClear variable says whether to add to or clear the drawing.
{
const char *const *file;
static const char *const fileType[2] = {"logo", NULL};
id openPanel;
char fullName[MAXPATHLEN];
// Run the open panel, filtering for out type of document
openPanel = [OpenPanel new];
if ([openPanel runModalForTypes:fileType])
{
// Open the file returned by the open panel
file = [openPanel filenames];
// Need to piece together the name from filenames and directory calls.
strcpy(fullName, [openPanel directory]);
strcat(fullName, "/");
strcat(fullName, *file);
if(doClear)
name = fullName;
[self _read:fullName _newDrawing:doClear];
}
return self;
}
- _doSaveWithNewName:(BOOL)doNewName retainName:(BOOL)doRetain
{
id savePanel;
// filename to save into
const char *saveName;
NXZone *zone;
// If the file is untitled or we are saving under a different name,
// run the save panel to get a new name.
zone = [self zone];
if (!name || doNewName) {
savePanel = [SavePanel new];
[savePanel setRequiredFileType:"logo"];
if ([savePanel runModalForDirectory:NULL file:name]) {
// If we want to keep this name, replace any old name.
if (doRetain) {
NXZoneFree(zone, name);
name = NXCopyStringBufferFromZone([savePanel filename], zone);
}
saveName = [savePanel filename];
} else
return self;
} else
// if we didn't run the Save Panel, save using the existing name.
saveName = name;
// Now do a _write routine.
[self _write:saveName];
return self;
}
- _write:(const char *)filename
// Writes a document to the given file using typedstreams.
{
NXTypedStream *ts;
float realVal;
struct prStruct *tempStruct = &firstStruct;
int howMany = 0;
// Open the typed stream to a file for writing.
ts = NXOpenTypedStreamForFile(filename, NX_WRITEONLY);
if (ts)
{
// Version of this write's data.
realVal = 1.0;
NXWriteType(ts, "f", &realVal);
// Figure out how many lines there are.
while(tempStruct->nextStruct != NULL)
{
howMany++;
tempStruct = tempStruct->nextStruct;
}
// Now save that number for the reading in of the file.
/* NXWriteType(ts, "i", &howMany); */
tempStruct = &firstStruct;
// Continue by writing out all the lines.
for(NXWriteType(ts,"i", &howMany);howMany >= 0;howMany--)
{
NXWriteArray(ts, "f", 4, tempStruct->oArray);
NXWriteArray(ts, "c", 4, tempStruct->cArray);
tempStruct = tempStruct->nextStruct;
}
// Close the stream. All done.
NXCloseTypedStream(ts);
}
return self;
}
- _read:(const char *)filename _newDrawing:(BOOL)doClear
// Reads a document from the given file using typedstreams.
{
NXTypedStream *ts;
float realVal;
int howMany = 0;
// Open the typed stream as a file.
ts = NXOpenTypedStreamForFile(filename, NX_READONLY);
if (ts)
{
// If this is an open the drawing needs to be cleared.
if(doClear)
[self clearScreen];
// The version number is not used as of this version
// but it needs to be retrieved anyway.
NXReadType(ts, "f", &realVal);
// This next variable is used to find out how many lines
// need to be added.
NXReadType(ts, "i", &howMany);
// Get howMany lines and add them into the drawing link list.
for(;howMany >= 1;howMany--)
{
NXReadArray(ts, "f", 4, thisStruct->oArray);
NXReadArray(ts, "c", 4, thisStruct->cArray);
thisStruct->nextStruct =
(struct prStruct *)malloc(sizeof(struct prStruct));
thisStruct = thisStruct->nextStruct;
thisStruct->nextStruct = NULL;
}
// Close the typed stream (file)
NXCloseTypedStream(ts);
// Tell the image to clear the image and that we want to
// redraw it when the next composite is called.
[idBackground recache];
}
return [self display];
}
- new:sender
{
// All we need to do is clear the screen for a new.
return [self clearScreen];
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.