home *** CD-ROM | disk | FTP | other *** search
- /* CEAppManager.m
- *
- * This is the basic controller of the App. It manages all big abstraction
- * tasks for the panels, documents and connections to the outside.
- *
- * For interface-info see the header file. The comments in this file mostly
- * cover only the real implementation details.
- *
- * Written by: Thomas Engel
- * Created: 23.10.1993 (Copyleft)
- * Last modified: 07.05.1994
- */
-
- #import "CEAppManager.h"
- #import "CEClassEditor.h"
- #import "CEListener.h"
- #import "Text_MiscExtensions.h"
- #import "MiscCompletionText.h"
-
- #import <misckit/MiscString.h>
-
-
- @implementation CEAppManager
-
- - appWillInit:sender
- {
- // This is the init part we need to pass before we get the messages that
- // we have to open some files.
- // To be able to init a class we need the have the Preferences,
-
- // preferences = [CEPreferencesManager new];
-
- // Now lets load the docu templates
-
- NXStream * aStream;
- id aPath;
- id ourListener;
-
- // Setup out own Listener...this is really nasty..anyway.
-
- [[NXApp appListener] free];
-
- ourListener = [[CEListener alloc] init];
- [ourListener setDelegate:self];
- [ourListener checkInAs:[NXApp appName]];
- [ourListener addPort];
-
- [NXApp setAppListener:ourListener];
-
- // Well now this is a litle rough....maybe we should search for those files
- // inside the ~/AppInfo or even *Library/ClassEditor sections..anyway.
-
- aPath = [MiscString newWithString:
- [(NXBundle *)[NXBundle mainBundle] directory]];
- [aPath cat:"/CEClassDocuTemplate.rtf"];
- if( [aPath doesExistInFileSystem] )
- {
- aStream = NXMapFile( [aPath stringValue], NX_READONLY );
- [classDocTemplateView readRichText:aStream];
- NXCloseMemory( aStream, NX_FREEBUFFER );
- }
- [aPath free];
-
- aPath = [MiscString newWithString:
- [(NXBundle *)[NXBundle mainBundle] directory]];
- [aPath cat:"/CEMethodDocuTemplate.rtf"];
- if( [aPath doesExistInFileSystem] )
- {
- aStream = NXMapFile( [aPath stringValue], NX_READONLY );
- [methodDocuTemplateView readRichText:aStream];
- NXCloseMemory( aStream, NX_FREEBUFFER );
- }
- [aPath free];
-
- // Here comes teh hack...
-
- [MiscCompletionText poseAs:[Text class]];
-
- return self;
- }
-
- - appDidInit:sender
- {
- // This is some kind of late init. These object are need for working but
- // not for reading the classes or having a class initialized.
-
-
- return self;
- }
-
- - (int)app:sender openFile:(const char *)path type:(const char *)type
- {
- // This method is performed whenever a user opens a document from the
- // Workspace Manager.
- // We use our default file open method with some default params.
-
- return [self openFile:path onHost:"*" atTrueLine:0];
- }
-
- - (BOOL)appAcceptsAnotherFile:sender
- {
- // Inform the workspace that we can open multiple files.
- return YES;
- }
-
- - appDidBecomeActive:sender
- {
- return self;
- }
-
- - appWillTerminate:sender
- {
- // Now lets see what we have...ask every window what is going on.
-
- BOOL ready;
- int i;
- id windowList;
- int count;
- int result;
-
- windowList = [NXApp windowList];
- count = 0;
-
- for( i=0; i<[windowList count]; i++ )
- if( [[windowList objectAt:i] isDocEdited] ) count++;
-
- // Well if there are windows with unsaved contents we should tell the
- // user about it.
- // We won't leave until the user has decided what to do on the top level.
-
- if( count == 0 ) return self;
-
- ready = NO;
- while( !ready )
- {
- result = NXRunAlertPanel( "Quit", "There are edited windows.",
- "Review Unsaved", "Quit Anyway", "Cancel" );
-
- if( result == NX_ALERTOTHER )
- return nil;
-
- else if( result == NX_ALERTDEFAULT )
- ready = [self _closeAllWindows];
-
- else ready = YES;
- }
- return self;
- }
-
- - (BOOL)_closeAllWindows
- {
- // We will try to close all windows and if we succeed we will let the app
- // know. YES = all closed
- // NOTE: Well this is kind of ugly because the app should maintain a list
- // of all the controllers that are responsible for some data. But I
- // don't want to hack down another list access stuff. So we do it
- // this way. Maybe in the future I will change that.
-
- id delegateList;
- id aDelegate;
- int i;
- id windowList;
- BOOL success;
-
- windowList = [NXApp windowList];
- delegateList = [List new];
-
- // Lets find all the delegates first.
-
- for( i=0; i<[windowList count]; i++ )
- {
- aDelegate = [[windowList objectAt:i] delegate];
- if( aDelegate != nil &&
- [aDelegate isKindOf:[CEClassEditor class]] )
- [delegateList addObjectIfAbsent:aDelegate];
- }
- success = YES;
-
- for( i=0; i<[delegateList count]; i++ )
- {
- if( [[delegateList objectAt:i] close:self] == nil )
- {
- success = NO;
- break;
- }
- }
-
- return success;
- }
-
- - addToReleasePool:anObject
- {
- return [NXApp delayedFree:anObject];
- }
-
- - (int)openFile:(char *)path onHost:(char *)host atTrueLine:(int *)line;
- {
- // This method is performed whenever a user opens a document.
- // It takes care that every file is only opened once.
-
- id newEditor;
- id aString;
- id basename;
- id filetype;
- id thePath;
- id windowList;
- id aDelegate;
- int i;
- BOOL loadIt;
-
- // First we have to check if we already know this file !
- // Some window delegate should have the same filename (without .h or .m)
- // Using the window list might not be the safest way..but I guess it
- // will work.
-
- aString = [MiscString newWithString:path];
- filetype = [aString fileExtension];
-
- if( [filetype cmp:"m"] != 0 &&
- [filetype cmp:"h"] != 0 &&
- [filetype cmp:"rtf"] != 0 )
- {
- // Looks like this is no valid file !
-
- [aString free];
- [filetype free];
- return -1;
- }
- // Now that it is clear that this is a valid file...
-
- [NXApp activateSelf:NO];
-
- windowList = [NXApp windowList];
- basename = [aString fileBasename];
- thePath = [aString pathName];
- [thePath addChar:[MiscString pathSeparator]];
- [thePath concatenate:basename];
- [basename free];
- [aString free];
- loadIt = YES;
-
- for( i=0; i<[windowList count]; i++ )
- {
- aDelegate = [[windowList objectAt:i] delegate];
-
- if( [aDelegate respondsTo:@selector(filename)] &&
- aDelegate != nil )
- {
- if( [thePath cmp:[aDelegate filename]] == 0 )
- {
- // Looks like we have found a delegate that belongs to exactly
- // the same path.
- // We must to ask this delegate now what window we should top.
-
- [[aDelegate window] makeKeyAndOrderFront:self];
- loadIt = NO;
- }
- }
- }
- [thePath free];
-
- // If we really have a new editor...let the world know about it.
-
- if( loadIt )
- {
- newEditor = [[CEClassEditor alloc] initFromFile:path];
- if( newEditor ) return YES;
- }
- return 0;
- }
-
- - showInfo:sender
- {
- // if( !info ) info = [BBInfo new];
-
- // [info makeKeyAndOrderFront:self];
- return self;
- }
-
- - showPreferences:sender
- {
- // if( preferences ) [preferences makeKeyAndOrderFront:self];
- return self;
- }
-
- - preferences
- {
- return self;
- }
-
- - open:sender
- {
- id openPanel;
- char fullName[MAXPATHLEN];
- const char *const *files;
- const char *const fileType[6] = { "m",
- "h",
- NULL};
-
- openPanel = [[OpenPanel new] allowMultipleFiles:YES];
-
- // Run the open panel, filtering for our type of documents
- // We try to open every file the panel returns.
-
- if( [openPanel runModalForTypes:fileType] )
- {
- files = [openPanel filenames];
- for( files = [openPanel filenames]; files && *files; files++)
- {
- // Now lets merge the fullFilename from the directory and the
- // current filename and try to init a editor from this file.
- // We use the default open method with some default params.
-
- sprintf( fullName, "%s/%s",
- [(OpenPanel *)openPanel directory], *files );
- [self openFile:fullName onHost:"*" atTrueLine:0];
- }
- }
- return self;
- }
-
- - new:sender
- {
- [CEClassEditor new];
- return self;
- }
-
- - save:sender
- {
- // [[NXApp keyWindow] save:sender];
- //
- // This is a posible solution
- // But we currently work with a firstResponder solution
-
- return self;
- }
-
- - saveAs:sender
- {
- return self;
- }
-
- - saveTo:sender
- {
- return self;
- }
-
- - saveAll:sender
- {
- return self;
- }
-
- - revert:sender
- {
- return self;
- }
-
- - close:sender
- {
- return self;
- }
-
- - print:sender
- {
- return self;
- }
-
- - setTextFontStyle:sender
- {
- [self _setSelectionFont:textFontField andColor:textFontColorWell];
- return self;
- }
-
- - setMethodNameFontStyle:sender
- {
- [self _setSelectionFont:methodNameField andColor:methodNameColorWell];
- return self;
- }
-
- - setParameterFontStyle:sender
- {
- id firstResponder = [[NXApp mainWindow] firstResponder];
-
- if( [firstResponder respondsTo:@selector(setSelFont:)] )
- [firstResponder setSelFont:[Font newFont:"Times-Italic" size:14]];
- return self;
- }
-
- - setMathSymbolFontStyle:sender
- {
- id firstResponder = [[NXApp mainWindow] firstResponder];
-
- if( [firstResponder respondsTo:@selector(setSelFont:)] )
- [firstResponder setSelFont:[Font newFont:"Symbol" size:14]];
- return self;
- }
-
- - setHeadlinesFontStyle:sender
- {
- [self _setSelectionFont:headlinesFontField
- andColor:headlinesFontColorWell];
- return self;
- }
-
- - setExampleCodeFontStyle:sender
- {
- [self _setSelectionFont:exampleCodeFontField
- andColor:exampleCodeFontColorWell];
- return self;
- }
-
- - setBlankLinesFontStyle:sender
- {
- [self _setSelectionFont:blankLinesFontField
- andColor:blankLinesFontColorWell];
- return self;
- }
-
- - setSourceFontStyle:sender
- {
- [self _setSelectionFont:sourceFontField andColor:sourceFontColorWell];
- return self;
- }
-
- - setKeywordsFontStyle:sender
- {
- [self _setSelectionFont:keywordsFontField andColor:keywordsFontColorWell];
- return self;
- }
-
- - setTypecastFontStyle:sender
- {
- [self _setSelectionFont:typecastFontField andColor:typecastFontColorWell];
- return self;
- }
-
- - setRemarkFontStyle:sender
- {
- [self _setSelectionFont:remarkFontField andColor:remarkFontColorWell];
- return self;
- }
-
- - setBugNoteFontStyle:sender
- {
- [self _setSelectionFont:bugNoteFontField andColor:bugNoteFontColorWell];
- return self;
- }
-
- - _setSelectionFont:aFont andColor:aColor
- {
- // Well this is a lie...we don't get the font but the TextField that has
- // the right font set !!
-
- id firstResponder = [[NXApp mainWindow] firstResponder];
-
- if( [firstResponder respondsTo:@selector(setSelFont:)] &&
- aFont != nil )
- [firstResponder setSelFont:[aFont font]];
- if( [firstResponder respondsTo:@selector(setSelColor:)] &&
- aColor != nil )
- [firstResponder setSelColor:[aColor color]];
-
- // This is for letting the delegates know about the changes to
- // be able to track document modification.
- // The first responder must know about the window because the
- // textDidChange might require it.
-
- if( [firstResponder respondsTo:@selector(window)] )
- [[[NXApp mainWindow] delegate] textDidChange:firstResponder];
-
- return self;
- }
-
- - copyClassDocuTemplate
- {
- // All we do here is to copy the docu template to the pasteboard.
-
- [classDocTemplateView selectAll:self];
- [classDocTemplateView copyTo:[Pasteboard newName:"CETempPb"]];
- return self;
- }
-
- - copyMethodDocuTemplate
- {
- // All we do here is to copy the method template to the pasteboard.
-
- [methodDocuTemplateView selectAll:self];
- [methodDocuTemplateView copyTo:[Pasteboard newName:"CETempPb"]];
- return self;
- }
-
- - windowDidBecomeKey:sender
- {
- // now if our Docu window will become key...we should load the text into
- // it if we havn't yet.
-
- NXStream * aStream;
- id aPath;
-
- if( sender != docuTemplateWindow ) return self;
-
- if( [docuTemplateTextView textLength] < 10 )
- {
- aPath = [MiscString newWithString:
- [(NXBundle *)[NXBundle mainBundle] directory]];
- [aPath cat:"/DocuTemplate.rtf"];
- if( [aPath doesExistInFileSystem] )
- {
- aStream = NXMapFile( [aPath stringValue], NX_READONLY );
- [docuTemplateTextView readRichText:aStream];
- NXCloseMemory( aStream, NX_FREEBUFFER );
- }
- [aPath free];
- }
- return self;
- }
-
- @end
-
- /*
- * History: 13.01.95 Bla.
- *
- *
- * Bugs: No bugs and birds seen....
- */