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.