// Copyright 1997-1999 Omni Development, Inc.  All rights reserved.
//
// This software may only be used and reproduced according to the
// terms in the file OmniSourceLicense.html, which should be
// distributed with this project and can also be found at
// http://www.omnigroup.com/DeveloperResources/OmniSourceLicense.html.

#import "OAFindController.h"

#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#import <OmniBase/OmniBase.h>
#import <OmniFoundation/OmniFoundation.h>

#import "NSBundle-OAExtensions.h"

RCS_ID("$Header: /Network/Developer/Source/CVS/OmniGroup/OmniAppKit/OAFindController.m,v 1.12 1999/03/30 21:25:53 kc Exp $")

static NSString *OAFindPanelTitle = @"Find";

@interface OAFindController (Private)
- (void)loadInterface;
- (void)findStringWithBackwardsFlag:(BOOL)backwardsFlag;
- (NSString *)enterSelectionString;
- (unsigned int)enterSelectionStringLength;
- (NSText *)enterSelectionTarget;
@end

@implementation OAFindController

// Init and dealloc

- init;
{
    if (![super init])
        return nil;

    [self loadInterface];

    return self;
}

- (void)dealloc;
{
    [findPanel release];
    [super dealloc];
}


// Menu Actions

- (IBAction)showFindPanel:(id)sender;
{
    [[searchTextForm cellAtIndex:0] setStringValue:[self restoreFindText]];
    [findPanel makeKeyAndOrderFront:NULL];
    [searchTextForm selectTextAtIndex:0];
}

- (IBAction)findNext:(id)sender;
{
    [findNextButton performClick:nil];
}

- (IBAction)findPrevious:(id)sender;
{
    [findPreviousButton performClick:nil];
}

- (IBAction)enterSelection:(id)sender;
{
    NSString *selectionString;

    selectionString = [self enterSelectionString];
    if (!selectionString)
        return;

    [self saveFindText:selectionString];
    [[searchTextForm cellAtIndex:0] setStringValue:selectionString];
    [searchTextForm selectTextAtIndex:0];
}

// Called internally by the Find Panel

- (IBAction)_findNext:(id)sender;
{
    [self findStringWithBackwardsFlag:NO];
}

- (IBAction)_findPrevious:(id)sender;
{
    [self findStringWithBackwardsFlag:YES];
}

- (IBAction)_findNextAndClosePanel:(id)sender;
{
    [findNextButton performClick:nil];
    [findPanel orderOut:nil];
}

// Utility methods

- (void)saveFindText:(NSString *)string;
{
    NSPasteboard *findPasteboard;

    if ([string length] == 0)
	return;
    NS_DURING {
	findPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard];
	[findPasteboard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
	[findPasteboard setString:string forType:NSStringPboardType];
    } NS_HANDLER {
    } NS_ENDHANDLER;
}

- (NSString *)restoreFindText;
{
    NSString *findText = nil;
    
    NS_DURING {
	NSPasteboard *findPasteboard;

	findPasteboard = [NSPasteboard pasteboardWithName:NSFindPboard];
	if ([findPasteboard availableTypeFromArray:[NSArray arrayWithObject:NSStringPboardType]])
	    findText = [findPasteboard stringForType:NSStringPboardType];
    } NS_HANDLER {
    } NS_ENDHANDLER;
    return findText ? findText : @"";
}

- (id <OAFindControllerTarget>)target;
{
    return [[[NSApp mainWindow] delegate] omniFindControllerTarget];
}


// NSMenuActionResponder informal protocol

- (BOOL)validateMenuItem:(NSMenuItem *)item
{
    if ([item action] == @selector(enterSelection:)) {
        return [self enterSelectionStringLength] > 0;
    }
    return YES;
}

@end

@implementation OAFindController (Private)

// Load our interface

- (void)loadInterface;
{
    [[NSBundle bundleForClass:[self class]] loadNibNamed:@"OAFindPanel.nib" owner:self];
    [findPanel setFrameUsingName:OAFindPanelTitle];
    [findPanel setFrameAutosaveName:OAFindPanelTitle];
}

// This is the real find method

- (void)findStringWithBackwardsFlag:(BOOL)backwardsFlag;
{
    id <OAFindControllerTarget> target;
    NSString *findString;

    target = [self target];
    if (!target) {
        NSBeep();
        return;
    }

    if ([findPanel isVisible])
        findString = [[searchTextForm cellAtIndex:0] stringValue];
    else
        findString = [self restoreFindText];

    if ([findString length] == 0) {
        NSBeep();
        return;
    }

    if (![target findString:findString ignoreCase:[ignoreCaseButton state] backwards:backwardsFlag wrap:YES])
        NSBeep();

    [self saveFindText:findString];
    [searchTextForm selectTextAtIndex:0];
}

- (NSString *)enterSelectionString;
{
    id enterSelectionTarget;

    enterSelectionTarget = [self enterSelectionTarget];
    if (!enterSelectionTarget)
        return nil;
    
    if ([enterSelectionTarget respondsToSelector:@selector(selectedString)])
        return [enterSelectionTarget selectedString];
    else {
        NSRange selectedRange;

        selectedRange = [enterSelectionTarget selectedRange];
        if (selectedRange.length == 0)
            return @"";
        else
            return [[enterSelectionTarget string] substringWithRange:selectedRange];
    }
}

- (unsigned int)enterSelectionStringLength;
{
    id enterSelectionTarget;

    enterSelectionTarget = [self enterSelectionTarget];
    if (!enterSelectionTarget)
        return 0;
    
    if ([enterSelectionTarget respondsToSelector:@selector(selectedString)])
        return [[enterSelectionTarget selectedString] length];
    else
        return [enterSelectionTarget selectedRange].length;
}

- (NSText *)enterSelectionTarget;
{
    NSWindow *selectionWindow;
    NSText *enterSelectionTarget;

    selectionWindow = [NSApp keyWindow];
    if (selectionWindow == findPanel)
        selectionWindow = [NSApp mainWindow];
    enterSelectionTarget = (id)[selectionWindow firstResponder];
    
    if ([enterSelectionTarget respondsToSelector:@selector(selectedString)])
        return enterSelectionTarget;
    if ([enterSelectionTarget respondsToSelector:@selector(string)] &&
        [enterSelectionTarget respondsToSelector:@selector(selectedRange)])
        return enterSelectionTarget;

    return nil;
}

@end

@implementation NSObject (OAFindControllerAware)

- (id <OAFindControllerTarget>)omniFindControllerTarget;
{
    return nil;
}

@end

@implementation NSObject (OAOptionalSearchableCellProtocol)

- (NSView <OASearchableContent> *)searchableContentView;
{
    return nil;
}

@end
