// Suppress compiler warning about rcsid being unused, yet prevent assembler
// code for this function from being produced.
inline extern const char *suppressCompilerWarning(void)
{
	static const char *rcsid = "$Id$ cc: "__FILE__" "__DATE__" "__TIME__;

	return rcsid;
}

//
// ---------- MiscSwitchViewConnectInspector Class Implementation -------------
//
// IB MiscSwitchView Connection inspector.
//
// Written by Art Isbell.
// Copyright 1996 by Art Isbell.
// Version 1.0.  All rights reserved.
//
// This notice may not be removed from this source code.
//
// This object is included in the MiscKit by permission from the author
// and its use is governed by the MiscKit license, found in the file
// "License.rtf" in the MiscKit distribution.  Please refer to that file
// for a list of all applicable permissions and restrictions.
//	
// ----------------------------------------------------------------------------
//

// ----------------------------- Header Files ---------------------------------

#import <AppKit/AppKit.h>
#import <InterfaceBuilder/InterfaceBuilder.h>

#ifndef NOMISC
#import <misckit/MiscSwitchViewConnectInspector.h>
#import <misckit/MiscSwitchView.h>
#import <misckit/MiscDraggableCellMatrix.h>

#else NOMISC

#import "MiscSwitchViewConnectInspector.h"
#import "MiscSwitchView.h"
#import "MiscDraggableCellMatrix.h"
#endif NOMISC

// ---------------- Typedef, Struct, and Union Declarations -------------------

// --------------------- Constant and Enum Definitions ------------------------

enum
{
    MiscConnect = 1,
    MiscDisconnect
};

// Button labels
static NSString *MiscConnectLabel = @"Connect";
static NSString *MiscDisconnectLabel = @"Disconnect";

// ------------------------- Function Declarations ----------------------------

@interface MiscSwitchViewConnectInspector(Private)
// ---------------------- Private Method Declarations -------------------------

- (void)_replaceBrowser;
- (void)_setOkButtonTag:(int)aTag isEnabled:(BOOL)yesNo;
- (void)_deselectBrowser;
- (NSString *)_contentsOfCellAtIndex:(unsigned)aRow;

@end

@implementation MiscSwitchViewConnectInspector
// ---------------------- Factory Method Definitions --------------------------

// ---------------- Overridden Instance Method Definitions --------------------

- (id)init
{
    self = [super init];

    // If self in not nil and inspector nib can't be loaded, autorelease self.
    if ((self != nil) &&
        ![NSBundle loadNibNamed:@"MiscSwitchViewConnectInspector" owner:self])
    {
        [self autorelease];
        self = nil;
    }
    return self;
}

- (void)ok:(id)aSender
{
    MiscSwitchView *switchViewL = [self object];

    // If aSender is "Connect" button, add view.
    if ([aSender tag] == MiscConnect)
    {
        id connectDestinationL = [NSApp connectDestination];

        // If connectDestination is a view, add it to switchView's views.
        if ([connectDestinationL isKindOfClass:[NSView class]])
        {
            [switchViewL addView:connectDestinationL];
            [browser reloadColumn:0];
            [browser selectRow:[[browser matrixInColumn:0] numberOfRows] - 1
                      inColumn:0];
            [self _setOkButtonTag:MiscDisconnect isEnabled:YES];
        }
        // connectDestination isn't a view, so open Alert panel.
        else
        {
            NSRunInformationalAlertPanel(@"Error",
                                         @"Connection to non-NSView objects not supported.",
                                         nil, nil, nil);
            [NSApp stopConnecting];
        }
    }
    // aSender is "Disconnect" button, so remove view.
    else
    {
        int selectedRowL = [browser selectedRowInColumn:0];

        // If selectedRow is less that the number of switchView views, remove
        // the indicated view.
        if (selectedRowL < [switchViewL count])
        {
            [switchViewL removeViewAtIndex:selectedRowL];
            [browser reloadColumn:0];

            // If the last view was removed, deselect browser.
            [self _deselectBrowser];
            [self _setOkButtonTag:MiscConnect isEnabled:YES];
        }
    }
    [super ok:aSender];
}

- (void)revert:(id)sender
{
    // If this isn't the first time revert: is sent, list the switchView's
    // views.
    if (!_isFirstConnectingRevert)
    {
        // If the browser has already been loaded, reload it.
        if ([browser isLoaded])
        {
            [browser reloadColumn:0];
        }
        // browser hasn't been loaded, so load it and add self as an observer
        // for MiscMatrixRowDidMove notifications.
        else
        {
            [browser loadColumnZero];
            [[NSNotificationCenter defaultCenter] addObserver:self selector:
                @selector(rowDidMove:) name:MiscMatrixRowDidMove
                object:[browser matrixInColumn:0]];
        }
        // If a connection is being made, update browser selection.
        if ([NSApp isConnecting])
        {
            unsigned rowNumberL = [[self object] indexOfView:[NSApp
                connectDestination]];

            // If the connected view is already a switchView view, select the
            // browser entry for that view and enable the "Disconnect" button.
            if (rowNumberL != NSNotFound)
            {
                if ([browser selectedRowInColumn:0] != rowNumberL)
                {
                    [browser selectRow:rowNumberL inColumn:0];
                }
                [self _setOkButtonTag:MiscDisconnect isEnabled:YES];
            }
            // The connected view isn't a switchView view, so deselect the
            // browser cell and enable the "Connect" button.
            else
            {
                [self _deselectBrowser];
                [self _setOkButtonTag:MiscConnect isEnabled:YES];
            }
        }
        // No connection is being made, so deselect the browser cell and
        // disable the "Connect" button.
        else
        {
            [self _deselectBrowser];
            [self _setOkButtonTag:MiscConnect isEnabled:NO];
        }
        [[self window] displayIfNeeded];
        [super revert:sender];
    }
    // During the first revert: message, set up ok and revert buttons.  These
    // buttons haven't been assigned in awakeFromNib,
    else
    {
        [self _setOkButtonTag:MiscConnect isEnabled:NO];
        _isFirstConnectingRevert = NO;
    }
}

- (BOOL)wantsButtons
{
    return YES;
}

// -------------------- New Instance Method Definitions -----------------------

- (void)awakeFromNib
{
    _isFirstConnectingRevert = YES;

    // In OS/Mach 4.0 PR2 IB, an installed browser already has column 0 loaded,
    // so browser must be replaced to use MiscDraggableCellMatrix.  Maybe this
    // will change with later releases.
    [self _replaceBrowser];
}

- (void)selectConnection:(id)aSender
{
    int selectedRowL = [aSender selectedRowInColumn:0];

    if (selectedRowL != -1)
    {
        MiscSwitchView *switchViewL = [self object];
        unsigned maxRowL = [switchViewL count] - 1;

        if (maxRowL < selectedRowL)
        {
            selectedRowL = maxRowL;
        }
        // Draw the connection.
        [NSApp displayConnectionBetween:switchViewL and:[switchViewL
            viewAtIndex:selectedRowL]];
        _isFirstConnectingRevert = YES;
        [self _setOkButtonTag:MiscDisconnect isEnabled:YES];
    }
    else
    {
        [self _setOkButtonTag:MiscConnect isEnabled:NO];
    }
}

- (void)clickConnectButton:(id)aSender
{
    [[self okButton] performClick:aSender];
}

- (void)rowDidMove:(NSNotification *)aNotification
{
    NSDictionary *userInfoL = [aNotification userInfo];
    MiscSwitchView *switchViewL = [self object];
    int oldRowL = [[userInfoL objectForKey:@"OldRow"] intValue];

    // Prevent possible release of view when it's removed from its superview.
    NSView *movedView = [[switchViewL viewAtIndex:oldRowL] retain];

    [switchViewL removeViewAtIndex:oldRowL];
    [switchViewL addView:movedView atIndex:[[userInfoL objectForKey:@"NewRow"]
        intValue]];
    [movedView release];
    [[NSApp activeDocument] touch];
    [browser reloadColumn:0];
}

// ----------------- Delegate Instance Method Definitions ---------------------

- (int)browser:(NSBrowser *)aBrowser numberOfRowsInColumn:(int)aColumn
{
    return [[self object] count];
}

- (void)browser:(NSBrowser *)aBrowser willDisplayCell:(id)aCell atRow:(int)aRow
         column:(int)aColumn
{
    if (aRow < [[self object] count])
    {
        [aCell setStringValue:[self _contentsOfCellAtIndex:aRow]];
    }
    else
    {
        [aCell setStringValue:@""];
    }
    [aCell setLeaf:YES];
}

@end

@implementation MiscSwitchViewConnectInspector(Private)
// ---------------------- Private Method Definitions --------------------------

- (void)_replaceBrowser
{
    NSBrowser *newBrowserL = [[NSBrowser allocWithZone:[self zone]]
        initWithFrame:[browser frame]];

    [newBrowserL setAction:[browser action]];
    [newBrowserL setTarget:[browser target]];
    [newBrowserL setDelegate:[browser delegate]];
    [newBrowserL setAllowsBranchSelection:[browser allowsBranchSelection]];
    [newBrowserL setAllowsEmptySelection:[browser allowsEmptySelection]];
    [newBrowserL setAllowsMultipleSelection:[browser allowsMultipleSelection]];
    [newBrowserL setHasHorizontalScroller:[browser hasHorizontalScroller]];
    [newBrowserL setMaxVisibleColumns:1];
    [newBrowserL setSeparatesColumns:[browser separatesColumns]];
    [newBrowserL setTitled:[browser isTitled]];
    [newBrowserL setTitle:[browser titleOfColumn:0] ofColumn:0];
    [newBrowserL setDoubleAction:@selector(clickConnectButton:)];
    [newBrowserL setMatrixClass:[MiscDraggableCellMatrix class]];
    [[browser superview] addSubview:newBrowserL];
    [newBrowserL release];
    [browser removeFromSuperview];
    browser = newBrowserL;
}

- (void)_setOkButtonTag:(int)aTag isEnabled:(BOOL)yesNo
{
    NSButton *revertButtonL;
    NSButton *okButtonL = [self okButton];

    // If aTag differs from okButton's tag, change button label.
    if ([okButtonL tag] != aTag)
    {
        [okButtonL setTag:aTag];

        if (aTag == MiscConnect)
        {
            [okButtonL setTitle:MiscConnectLabel];
        }
        else
        {
            [okButtonL setTitle:MiscDisconnectLabel];
        }
    }
    // Set button's enabled state, if necessary.
    if (yesNo != [okButtonL isEnabled])
    {
        [okButtonL setEnabled:yesNo];
    }
    // Ensure that revertButton is disabled, if necessary.
    revertButtonL = [self revertButton];
    if ([revertButtonL isEnabled])
    {
        [revertButtonL setEnabled:NO];
    }
}

- (void)_deselectBrowser
{
    if ([browser selectedColumn] == 0)
    {
        [[browser matrixInColumn:0] deselectAllCells];
    }
}

- (NSString *)_contentsOfCellAtIndex:(unsigned)aRow
{
    NSString *contentsL;
    MiscSwitchView *switchViewL = [self object];
    id objectL = [switchViewL viewAtIndex:aRow];

    if ([objectL isKindOfClass:[NSMatrix class]])
    {
        NSCell *cellL = [objectL selectedCell];

        if (cellL != nil)
        {
            objectL = cellL;
        }
        else
        {
            objectL = [objectL cellAtRow:0 column:0];
        }
    }
    // NSBox, NSButton, NSSlider, ...
    if ([objectL respondsToSelector:@selector(title)])
    {
        contentsL = [objectL title];
    }
    // NSControl, NSPopUpButton, ...
    else if ([objectL respondsToSelector:@selector(stringValue)])
    {
        contentsL = [objectL stringValue];
    }
    else
    {
        contentsL = @"";
    }
    return [NSString stringWithFormat:@"% d  %@ (%@)", aRow, [[objectL class]
        description], contentsL];
}

@end

// ------------------------- Function Definitions -----------------------------
