
/*
   MiscAppManager.m 
*/

// RCS identification information

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

#import <AppKit/AppKit.h>

#import "MiscWindowManager.h"
#import "MiscInfoWindowManager.h"

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


@implementation MiscAppManager

/*"
   MiscAppManager is sort of an abstract superclass. You can use it
   as is, but it is recommended that you create a subclass in order
   to override #appVersion and return your app's current version. 
   With this you'll have the benefit of the version being displayed 
   in the generic info panel (if you don't supply an info panel of 
   your own). 
   
   MiscAppManager makes it easy to supply your own info panel by 
   either specifying a new info window manager class 	
   (#setInfoWindowManagerClass:) or specifying an info bundle
   that should be used (override #infoBundleName to return your
   bundle name). The info bundle's principal class needs to be a 
   subclass of MiscInfoWindowManager.
   
   Some other benefits you get for free when using this class in
   cooperation with the MiscWindowManager class is when the app is
   terminated we close all the open windows one by one allowing the
   user to save their contents if they are dirty.
   
   In the future I'll be adding code so that you can load inspectors
   and preferences much the same way that the info panel is handled.
   Some of the code for the inspectors is already in the 
   AdderAppManager and just needs to be moved here.
"*/

//-------------------------------------------------------------------
// 	Initialization/deallocation
//-------------------------------------------------------------------

- (id) init
/*"
   Sets our info window manager class to be MiscInfoWindowManager.
   That way if you don't do anything you'll still get a default
   info panel with the app's name, icon, version and copyright info
"*/
{
    BOOL error = ([super init] == nil);

    if (!error) {
        // By default we should use an info panel that has the app name,
        // icon, version and copyright.
        [self setInfoWindowManagerClass:[MiscInfoWindowManager class]];
    }

    return error ? nil : self;
}


//-------------------------------------------------------------------
// 	Getting the application version
//-------------------------------------------------------------------

- (NSString*) appVersion
/*"
   Returns a string describing the version of the application.  The
   default implementation just returns an empty string. 
"*/
{
    return @"";
}


//-------------------------------------------------------------------
// 	InfoWindowManager by class
//-------------------------------------------------------------------

- (Class) infoWindowManagerClass
/*"
   Returns the info window manager class that'll be created when
   the user wants to see the info panel (unless it is using an
   info bundle). The default is MiscInfoWindowManager.
"*/
{
	return _infoWindowManagerClass;
}


- (void) setInfoWindowManagerClass:(Class)newInfoWindowManagerClass
/*"
   Sets our info window manager class we should use to get the
   info panel displayed. The default is MiscInfoWindowManager.
   The class you pass should be a subclass of MiscInfoWindowManager,
   though in a later release I'll probably just create a protocol
   to conform to.
   This method has no effect if #infoBundleName has been
   overridden and doesn't return nil. In that case we try to
   load the info window manager from the bundle.
"*/
{
	_infoWindowManagerClass = newInfoWindowManagerClass;
}


//-------------------------------------------------------------------
// 	InfoWindowManager by bundle
//-------------------------------------------------------------------

- (NSString*) infoBundleName
/*"
	By default we return nil. If subclasses are going to use an info
	bundle then override this class to return the bundle's name. The
	principal class in the bundle has to be a subclass of MiscInfoWindowManger.
	The infoBundleName that you return can include or omit the .bundle 
	extension (I think :-).
"*/
{
	return nil;
}


//-------------------------------------------------------------------
// 	Showing the info panel
//-------------------------------------------------------------------

- (void) showInfoPanel:(id)sender
/*"
   Trys first to find an info window manager that already exists.
   If one cannot be found then we either create one by looking for
   an info bundle (if #infoBundleName returns something other than
   nil) or by asking the class returned by our #infoWindowManagerClass 
   for their default info window manager. 
"*/
{
    MiscInfoWindowManager* ourInfoWindowManager = nil;

    // Check to see if we already have one since we don't need
    // more than one info panel being displayed. This should work
    // whether we used a bundle or a class to get the info panel.
    ourInfoWindowManager = (MiscInfoWindowManager*)
        [MiscWindowManager windowManagerOfClass:[self infoWindowManagerClass]];
    
    if (ourInfoWindowManager == nil) {
        // Check to see if there is an infoBundleName.
        if ([self infoBundleName] != nil) {
            NSBundle* infoBundle = [self _findInfoBundle];

            if (infoBundle != nil) {
                ourInfoWindowManager = 
					[[infoBundle principalClass] defaultInfoWindowManager];

                // Make sure it is a subclass of something we expect. Actually
                // this might not be necessary if we create an
				// InfoWindowManager protocol and just check that. 
				// Then others won't have to subclass from 
				// MiscInfoWindowManager if they don't want.
                if (![ourInfoWindowManager isKindOfClass:[MiscInfoWindowManager class]]) {
                    [ourInfoWindowManager release];
                    ourInfoWindowManager = nil;
                }
            }
        }

        // If not then use our infoWindowManagerClass. This is an else statement
        // because if we do have a info bundle to find and it fails we
        // shouldn't just load the default info panel (or should we?)
        else {
            ourInfoWindowManager = 
				[[self infoWindowManagerClass] defaultInfoWindowManager];
        }
    }
    
    [ourInfoWindowManager makeKeyConditionallyAndOrderFront:nil];    
}	

@end

