home *** CD-ROM | disk | FTP | other *** search
- /* 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>
-
- @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];
-
- 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:"Not a valid textlab 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;
- id curWin = [NXApp mainWindow];
-
- 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;
- id curWin;
-
- /* EXERCISE #4a *
- * Add code to respond to an saveInRequest *
- * Hint: Use a SavePanel to get the file name and *
- * directory where the document should be saved. *
- * You will note that the saveReq instance variable *
- * was initialized in the +new method of Controller *
- * to point to a SavePanel. SavePanels will automatically *
- * append an extension on the file name specified by the *
- * the user if you have previously sent it the *
- * setRequiredFileType: message passing it the appropriate *
- * extension. Once you have done this, you should send it a*
- * a method called runModalForDirectory:file: which *
- * makes theSavePanel visible and which make it *
- * a modal window. Once that method returns you can *
- * query the SavePanel for the file name *
- * selected (look in the spec sheets for SavePanel). *
- * Assuming you used setRequiredFileType: earlier the file *
- * name returned will have the appropriate extension *
- * Finally you should call the saveWindow:inPath: *
- * method of Controller which will actually save the *
- * document. Note the first argument to saveWindow is *
- * the id of the window containing the document to be *
- * saved. Look at the specSheets for the Application *
- * object to see what method to use to get the id of the *
- * current main window. In fact you will probably want to *
- * get the id of the main window first thing in here so *
- * you can use its title as the default file name for *
- * the file in which the window will be stored */
-
- 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];
-
- /* EXERCISE #4b *
- * Add code to store win and its contents *
- * in an file called name.Hint: you will want to *
- * use typedStreams to write out the window and its *
- * contents. The code to do this will look similar to the *
- * code in openFile: so be sure to look at that code. You *
- * will need to do 3 things. 1) Open a typedStream on a *
- * file named name using NXOpenTypedStreamForFile() *
- * 2) Write out the window to the typedStream using *
- * NXWriteRootObject(). 3) Close the 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
- {
- /* EXERCISE 5 *
- * Add code to assign curText to point to *
- * view which should be printed. Hint: it is the *
- * docView of the TextView in the application's *
- * mainWindow. Look at the spec sheets for the *
- * Application class to see how to get the id of *
- * the current main window */
-
- id curText = nil;
-
- if (curText == nil) [self showError:"No active window to print."];
- else {
- /* EXERCISE 5b *
- * Add code to print view *
- * *
- * */
- }
- 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
-