// BWBorkPadPrefController.h -- the controller for BorkPad preferences.  Basically
//				a stripped-down font picker

// Copyright (C) 2003 Borkware
// We use the BSD License.  Check out http://borkware.com/license

#import "BWBorkPadPrefController.h"

// name of the notification we broadcast on font/size changes

NSString *BWBorkPadPrefControllerFontChangeNotification
   = @"BWBorkPadPrefController Font Change Notification";


// the user info of the broadcast is a dictionary with these keys

NSString *BWBorkPadPrefFontKey = @"Font";
NSString *BWBorkPadPrefPermanentKey = @"IsPermanent";



@implementation BWBorkPadPrefController


// load the pref window from the nib file.
// other initialization stuffage happens when we awake from
// the nib

- (id) init
{
    if (self = [super init]) {
	[NSBundle loadNibNamed: @"Preferences.nib"  owner: self];
    }

    return (self);

} // init



// There are two popup menus, one with font names an the other with
// sizes.  choose the correct item based on the currently selected
// font

- (void) updateMenus
{
    if (font) {
	// update the menus
	int index;
	
	index = [sizeMenuButton indexOfItemWithTag: (int)[font pointSize]];
	[sizeMenuButton selectItemAtIndex: index];

	index = [fontMenuButton indexOfItemWithTitle: [font familyName]];
	[fontMenuButton selectItemAtIndex: index];
    }

} // updateMenus



// turn on context help.  Discovered this little goody in Bill Cheeseman's
// Vermont Recipes book. 

- (void) setupContextHelp
{
    NSHelpManager *helpManager;
    helpManager = [NSHelpManager sharedHelpManager];

    // use the same help for the entire window.  Set it for all the controls
    // therein

    [helpManager 
	setContextHelp: [[NSBundle mainBundle] 
			    contextHelpForKey: @"prefwindowContextHelp.rtfd"]
	forObject: fontMenuButton];
    
    [helpManager 
	setContextHelp: [[NSBundle mainBundle] 
			    contextHelpForKey: @"prefwindowContextHelp.rtfd"]
	forObject: sizeMenuButton];
    
    [helpManager 
	setContextHelp: [[NSBundle mainBundle] 
			    contextHelpForKey: @"prefwindowContextHelp.rtfd"]
	forObject: window];
    
    [helpManager 
	setContextHelp: [[NSBundle mainBundle] 
			    contextHelpForKey: @"prefwindowContextHelp.rtfd"]
	forObject: cancelButton];
    
    [helpManager 
	setContextHelp: [[NSBundle mainBundle] 
			    contextHelpForKey: @"prefwindowContextHelp.rtfd"]
	forObject: okButton];

} // setupContextHelp



// do any post-nib-loading initialization and setup

- (void) awakeFromNib
{
    // the names of the font family, sorted.
    NSArray *fontNames;
    fontNames = [[NSFontManager sharedFontManager] availableFontFamilies];
    fontNames = [fontNames sortedArrayUsingSelector: @selector(compare:)];

    // get the menu that belongs to the font button
    NSMenu *fontMenu;
    fontMenu = [fontMenuButton menu];

    // out with the old
    while ([fontMenu numberOfItems] > 0) {
	[fontMenu removeItemAtIndex: 0];
    }

    // in with the new
    NSEnumerator *enumerator;
    NSString *name;

    enumerator = [fontNames objectEnumerator];
    while (name = [enumerator nextObject]) {

	// there are some 'noise' fonts that end with TT or LET which apps
	// like mail.app don't show.  So filter those out, as well as those
	// that have a leading dot in the name
	if ([name characterAtIndex: 0] == '.') {
	    continue;
	}

	NSRange range;
	range = [name rangeOfString: @"TT" 
		      options: NSBackwardsSearch | NSAnchoredSearch];
	if (range.location != NSNotFound) {
	    continue;
	}

	range = [name rangeOfString: @"LET" 
		      options: NSBackwardsSearch | NSAnchoredSearch];
	if (range.location != NSNotFound) {
	    continue;
	}

	// if we survived down to here, we have a worthwhile font
	[fontMenu addItemWithTitle: name  action: nil  keyEquivalent: @""];
    }

    [self setupContextHelp];

} // awakeFromNib



// display the pref window

- (void) showWindow: (id) sender
{
    [window makeKeyAndOrderFront: nil];
} // showWindow



// make the pref window reflect the font currently inuse

- (void) setFont: (NSFont *) inFont
{
    // keep it as the current font

    [inFont retain];
    [font release];
    font = inFont;

    // also keep it as the original font so we can restore it
    // in face of the user cancelling

    [inFont retain];
    [originalFont release];
    originalFont = inFont;

    // tell the two menu pop up button thingies to reflect the
    // current value

    [self updateMenus];

} // setFont



// the the world the user has chosen a new font

- (void) broadcastFontChange: (NSFont *) newFont  permanent: (BOOL) isPermanent
{
    NSDictionary *dict;
    dict = [NSDictionary dictionaryWithObjectsAndKeys: newFont, BWBorkPadPrefFontKey,
			 [NSNumber numberWithBool: isPermanent], BWBorkPadPrefPermanentKey,
			 nil];

    [[NSNotificationCenter defaultCenter]
	postNotificationName: BWBorkPadPrefControllerFontChangeNotification
	object: self
	userInfo: dict];

} // broadcastFontChange



// look at the menus in the pref window, and build a font with
// the indicated family name and size

- (void) buildFont
{
    NSString *familyName;
    familyName = [fontMenuButton titleOfSelectedItem];

    int fontSize;
    fontSize = [[sizeMenuButton selectedItem] tag];

    [font release];
    font = [[NSFontManager sharedFontManager] fontWithFamily: familyName
					      traits: 0
					      weight: 5
					      size: fontSize];
    [font retain];
    
} // buildFont



/*
 * ----- Actions
 */


// the user cancelled.  Close the window and broadcast the original font
// so that the UI can revert to its original state

- (IBAction) cancelAction: (id) sender
{
    // permanent is 'NO' because the receiver shouldn't have stored
    // any font values in permanent storage.  This will avoid an
    // an unnecessary disk access

    [self broadcastFontChange: originalFont  permanent: NO];

    [window close];

} // cancelAction



// the user picked a new font or size.  Got build the chosen font
// and broadcast the news

- (IBAction) applyAction: (id) sender
{
    [self buildFont];
    [self broadcastFontChange: font  permanent: NO];

} // applyAction



// the user likes it!  They really do!  Make this font stick now.

- (IBAction) okAction: (id) sender
{
    [self buildFont];
    [self broadcastFontChange: font  permanent: YES];

    [window close];

} // okAction


// If the user tries closing the window without choosing OK or Cancel,
// ask the user if they want the font change to stick, or else cancel
// the window closing

- (void) prefCloseSheetDidEnd: (NSWindow *) sheet
		   returnCode: (int) returnCode
		  contextInfo: (void *) contextInfo
{
    switch (returnCode) {

    case NSAlertDefaultReturn:
	[self okAction: nil]; // this closes the window
	break;

    case NSAlertAlternateReturn: 
	// cancel of the sheet, so go back to the sheet with state unchanged
	// actually, don't do anything
	break;

    case NSAlertOtherReturn:
	// no button, meaning to revert to the pre-pref-change version
	[self cancelAction: nil]; // this closes the window too
	break;
    }

} // prefCloseSheetDidEnd



// this is a window delegate method that's invoked when the user tries
// to close the window.  if they've changed the font, we don't know if
// they want to keep it ("This is nice. I'm done") or forget it
// ("blech!  make it go away")  So put up an alert sheet with yes, no, or cancel
// buttons, and defer the decision to actually close the window

- (BOOL) windowShouldClose: (id) sender

{
    BOOL result = YES;

    if (font != originalFont) {
	NSBeginAlertSheet (NSLocalizedString(@"Make font changes permanent?", 
					     @"pref alert make changes permanent"),
			   NSLocalizedString(@"Yes", 
					     @"Yes button label"),
			   NSLocalizedString(@"Cancel", 
					     @"Cancel button label"), 
			   NSLocalizedString(@"No", 
					     @"No button label"),
			   window,
			   self,
			   @selector(prefCloseSheetDidEnd: returnCode: contextInfo:),
			   NULL, // didDismissSelector
			   NULL, // contextInfo
			   NSLocalizedString(@"pref close explanation",
					     @"pref close explanation"));
	result = NO;
    }

    return (result);

} // windowShouldClose


@end // BWBorkPadPrefController


/* $Id: BWBorkPadPrefController.m,v 1.6 2003/01/02 21:29:20 markd Exp $ */
