This is Controller.m in view mode; [Download] [Up]
/* Controller.m --- Main controller object for the TextLab program.
** Authors: Bruce Blumberg and Ali Ozer, NeXT Developer Support Group
*/
// Controller object is the central object in TextLab. It manages the
// windows, open/save panels, and menu commands.
#import "Controller.h"
#import "TextView.h"
#import <appkit/Application.h>
#import <objc/typedstream.h>
#import <appkit/FontManager.h>
// Extension for TextLab archive files and length of the extension
#define EXTENSION ".tl"
#define EXTENSIONLEN 3
@implementation Controller
// We subclass the Controller "new" so that we can set the application's
// delegate to point to the Controller object. This way open file
// requests from the Workspace get routed to the Controller's
// appOpenFile:type: and appAcceptsAnotherFile methods.
+ new
{
self = [super new];
[NXApp setDelegate:self];
// create instances of support objects
openReq = [OpenPanel new];
saveReq = [SavePanel new];
fontReq = [FontManager new];
return self;
}
- showError: (char *)errorMessage
{
NXRunAlertPanel (NULL,errorMessage,"OK",NULL,NULL);
}
// newTextView: is invoked in response to a new empty window request. It
// creates a new window containing a TextView. Note that we want new windows
// to be offset from each other by some amount; hence the use of wRect.
#define ORIGX 100.0
#define ORIGY 100.0
static NXRect wRect = {{ORIGX, ORIGY},{500.0,400.0}};
- newTextView:sender
{
id newTextView;
NXOffsetRect(&wRect, 20.0, -20.0);
if (wRect.origin.y < 0) {wRect.origin.y = ORIGY; wRect.origin.x = ORIGX;}
newTextView = [TextView newFrame:&wRect];
[[newTextView window] setDelegate:self];
return self;
}
// 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: method. TextLab can indeed open multiple
// windows, so we return YES.
-(BOOL) appAcceptsAnotherFile:sender
{
return (YES);
}
// appOpenFile:type: is called to open the specified file. It is normally
// called by the Application object in response to open requests from the
// Workspace. Here we also route the open requests from the OpenPanel
// to this method (see openRequest:).
-(int) appOpenFile:(char *)fileName type:(char *)fileType
{
return [self openFile:fileName];
}
// openRequest: opens a new file. It puts up a open panel, and, if the user
// doesn't cancel, it reads the specified archive file. If the selected file
// is not a proper archive file, then openRequest: will complain.
- openRequest:sender
{
const char *fileName;
const char *const types[2] = {"tl",NULL};
int ok;
if ([openReq runModalForTypes:types] && (fileName =[openReq filename])) {
[self openFile:fileName];
}
else
[self showError:"No file chosen or could not open file"];
return self;
}
-(int) openFile:(const char *)fileName
{
id win;
NXTypedStream *typedStream;
if(!(typedStream = NXOpenTypedStreamForFile(fileName,NX_READONLY))){
[self showError:"error on opening file"];
return NO;
}
else {
win = NXReadObject(typedStream);
NXCloseTypedStream(typedStream);
[win setTitle:fileName];
[[win display] makeKeyAndOrderFront:self];
return YES;
}
}
// saveRequest: saves the current window under its default name (found in
// the title bar). Note that if the title bar is empty or the default title
// is "Untitled" then saveRequest: will put up a save panel, giving the user
// a chance to specify a real title.
- saveRequest:sender
{
const char *fileName;
const char *const types[2] = {"tl",NULL};
id curWin = [NXApp mainWindow];
[saveReq setRequiredFileType:types[0]];
if (curWin == nil)
[self showError:"No active window to save."];
else {
// Check to see if the current window is titled and the title is not
// "Untitled". If so, save the file, else put up a save panel...
fileName = [curWin title];
if (strcmp (fileName, "Untitled"))
[self saveWindow:curWin inPath:fileName];
else [self saveInRequest:sender];
}
return self;
}
// saveInRequest: gives the user a chance to save the current window
// under a new name.
- saveInRequest:sender
{
const char *fileName;
const char *const types[2] = {"tl",NULL};
id curWin = [NXApp mainWindow];
[saveReq setRequiredFileType:types[0]];
if (curWin == nil)
[self showError:"No active window to save."];
else {
// Get a file name from the user; use title of the window as default.
if (([saveReq runModalForDirectory:"." file:[curWin title]]) &&
(fileName = [saveReq filename]))
[self saveWindow:curWin inPath:fileName];
}
return self;
}
// saveWindow writes a window out the archive file whose name is specified
// by the second argument. The title of the current window is also set
// accordingly.
- saveWindow:(id)win inPath:(const char *)name
{
NXTypedStream *typedStream;
[win setTitle:name];
typedStream = NXOpenTypedStreamForFile(name,NX_WRITEONLY);
NXWriteRootObject(typedStream,win);
NXCloseTypedStream(typedStream);
return self;
}
// 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.
- printRequest:sender
{
id curText = [[[NXApp mainWindow] contentView] docView];
if (curText == nil) [self showError:"No active window to print."];
else {
[[[NXApp printInfo] setHorizCentered:NO] setVertCentered:NO];
[curText printPSCode:self];
}
return self;
}
// closeRequest closes the current window by simulating a click on the
// closebutton. A check should probably be added to give the user the
// option of saving the window before closing
- closeRequest:sender
{
[[NXApp mainWindow] performClose:sender];
return self;
}
// This method will get called before a window is closed and
// will give the user an opportunity to save their file. It then returns
// self indicating that the window may be closed.
- windowWillClose:(id)whichWin
{
return self;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.