
/*
   MiscAppManager_Protected.m
*/

// RCS identification information
static char *rcsID = "$Id:$";
static void __AvoidCompilerWarning(void) {if(!rcsID)__AvoidCompilerWarning();}

// NeXT Headers
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>

#import "MiscWindowManager.h"

// Superclass/Class Headers
#import "MiscAppManager.h"


@implementation MiscAppManager (Protected)

/*"
   These methods are only available for subclasses to use, extend,
   or override. Most of them are hooks for subclasses.
"*/


- (BOOL) _shouldAllowTermination
/*"
   May be overridden by subclasses. This default implementation
   returns NO if there are any MiscWindowManagers with visible
   Windows. Subclasses can assume that all open Windows have been
   sent a #performClose: method before this method is invoked, but
   cannot assume that all Windows are actually closed since a Window
   delegate may have intervened. 
"*/
{
    BOOL 		shouldAllowTermination = YES;
    NSEnumerator* 	windowManagerEnumerator;
    MiscWindowManager* 	aWindowManager;

    windowManagerEnumerator =
        [[MiscWindowManager allWindowManagers] objectEnumerator];

    while ((aWindowManager = [windowManagerEnumerator nextObject]) != nil) {
        if ([[aWindowManager window] isVisible]) {
            shouldAllowTermination = NO;
            break;
        }
    }

    return shouldAllowTermination;
}


//-------------------------------------------------------------------
//	Default registration for all apps.
//-------------------------------------------------------------------

- (void) _registerApplicationDefaults
/*"
   Currently does nothing. Hook for subclasses.
"*/
{
}


//-------------------------------------------------------------------
// 	Saving and restoring application state between sessions
//-------------------------------------------------------------------

- (void) _saveApplicationState 
/*"
	Stores the application state to be recreated for the next session.  We 
	should probably add some code here to forward this method to all the 
	active window managers so they can save their own state.
"*/
{
}


- (void) _restoreApplicationState 
/*"
**	Restores the application state for the current session. 
"*/
{
}


//-------------------------------------------------------------------
// 	Searching for the info bundle
//-------------------------------------------------------------------

- (NSBundle*) _findInfoBundle
/*"
   Returns our info bundle if it was found or nil if it wasn't. We
   check the main bundle (app wrapper) first. If it wasn't found then
   we try our class's bundle if it is different from the app wrapper.
"*/
{
    NSBundle* ourInfoBundle = nil;
    BOOL error = NO;

    // Is the bundle name even there?
    if (!error) {
        error = ([self infoBundleName] == nil);
    }

    // Check our bundles for the info bundle.
    if (!error) {
        NSBundle* mainBundle = [NSBundle mainBundle];
        NSBundle* classBundle = [NSBundle bundleForClass:[self class]];
        NSString* infoBundleName = [self infoBundleName];
        NSString* infoBundlePath;

        // Main bundle first. This way if the info bundle is also in a
        // framework (if this class gets into a framework) then it'll
        // default to the one in the main bundle. We use a type of nil
        // because the infoBundleName should have the extension.
        infoBundlePath = [mainBundle pathForResource:infoBundleName ofType:nil];

        // If it wasn't in the main bundle check our class's bundle.
        if (infoBundlePath == nil && mainBundle != classBundle) {
            infoBundlePath = [classBundle pathForResource:infoBundleName ofType:nil];
        }

        // If we found a suitable bundle path then create the bundle object
        // for it.
        if (infoBundlePath != nil) {
            ourInfoBundle = [NSBundle bundleWithPath:infoBundlePath];
        }
    }

    return error ? nil : ourInfoBundle;
}

@end


@implementation MiscAppManager (ApplicationDelegate)

- (void) applicationWillFinishLaunching:(NSNotification *)notification
/*"
	Currently empty. 
"*/
{
}

- (void) applicationDidFinishLaunching:(NSNotification *)notification
/*"
   This method is full of hooks for app manager subclasses to make use of.
"*/
{
    // Register any application wide defaults.
    [self _registerApplicationDefaults];

    // Restore any application state that was stored when the last
    // application session was terminated.
    [self _restoreApplicationState];
}


- (BOOL) applicationShouldTerminate:(id)sender
/*"
   Cleanup just before the application (possibly) dies. It sends all the
   application's manager windows a #performClose: message, then sends a
   #_shouldAllowTermination message to see whether or not the application
   should be terminated.
"*/
{
    BOOL shouldAllowTermination = YES;

    // This should be done before the Window close stuff happens below,
    // because we're actually recording the fact if those Windows are
    // open or not in #_saveApplicationState.
    if (shouldAllowTermination) {
        [self _saveApplicationState];
    }

    if (shouldAllowTermination) {
        NSArray* windowManagers = [MiscWindowManager allWindowManagers];

        // Send every open Window Manager a -performClose: message. It's the
        // responsibility of each Window's delegate to prevent the
        // close from happening if it would be inappropriate.
        [windowManagers makeObjectsPerform:@selector(performClose:)
                                                     withObject:self];

        // The default implementation of -shouldAllowTermination
        // just checks for open Windows; this would imply that some
        // Window's delegate aborted the close operation and that
        // the entire termination should be aborted.
        shouldAllowTermination = [self _shouldAllowTermination];
    }

    return shouldAllowTermination;
}

@end

