/* TVC.h created by test on Sat 01-Feb-1997 */

#import <AppKit/AppKit.h>

#define TVC_COLUMN_SORTING_ATT 		@"sorting"
#define TVC_COLUMN_IDENTIFIER_ATT	@"identifier"
#define TVC_COLUMN_HIDE_ATT			@"hide"
#define TVC_COLUMN_DISPLAY_ATT		@"display"
#define TVC_COLUMN_CELLCLASS_ATT	@"cellclass"

// These channels are used along with the channelBroadcaster outlet to enable/disable controls. - START
#define	ENABLE_WHILE_ROW_SELECTED_Channel	@"EnableWhileRowSelected"
#define	ENABLE_WHILE_MODEL_PRESENT_Channel	@"EnableWhileModelPresent"
// END

#define MCObjectsDetermineRowColor			@"MCObjectsDetermineRowColor"

#define MCTVCPrefersCaseInsensitiveCompare	@"MCTVCPrefersCaseInsensitiveCompare"

@class MCTableViewAnalyzer;

typedef enum
{
    TC_SORT_ASCENDING = 0,
    TC_SORT_DESCENDING,
    TC_SORT_NONE
} TC_SORT_MODE;

@interface MCTableviewController : NSObject <NSCoding>
{
    id		tableView;
    id		delegate;
    id		(model);
    id		(columnIdentifiers);
    id		(attributes);
    id		(displayList);
    id		(displayListDictionary);
    id		(lastSelectionCheck);
    id		(childrenAttribute);
    NSString *childrenAttributeName;
    BOOL	sortedDisplay;
    BOOL	tableEditable;
    BOOL	cornerDeselectFlag;

    id		countField;
    id		countSelectField;
	id		summaryCountField;

    BOOL	isMutable;
    SEL		doubleAction;
    id		target;
    NSColor	*tableCellsOriginalDisplayColor;
    id		channelBroadcaster;
    
    BOOL		confirmDelete;
    NSString	*alertPanelTitle; 
    NSString	*alertPanelBody;
    id			(objectClass);
    NSString	*objectClassName;
    BOOL		selectOnAdd;
	
	
	BOOL		wantsAlternateColors;
	NSColor		*rowColor;
	NSColor		*alternateColor;
	
    
    BOOL		allowDragDestination;
	BOOL		allowDragSource;
	
	BOOL		observeSingleSelectionPattern;
	BOOL		isHelper;
    
	
	NSString	*autosaveName;
	BOOL		_blockColumnConfigSaving;
	
	// Instead of asking if the delegate responds each time we need something, we ask when at awakeFromNib and setDelegate ... 
	BOOL		_delegConfigsNumberOfOVChilds;
	BOOL		_delegProvidesObjValForColumns;
	BOOL		_delegProvidesOVChildren;
	BOOL		_delegDetermineExpandable;
	BOOL		_delegSetsObjValForColumns;
	
	BOOL		_didBeginEditingCell;
	
	NSMutableArray	*_lastUserSortIdentifiers;
	int				_lastUserSortDirection;
	
	BOOL		_shouldAskObjectForRowColor;
}

- tableView;
- (void)setModel:anObject;
- model;
- (NSInteger)rowForObject:(id)anObject;

// sets the needsDisplay bit on the rows and columns of the passed values. If nil columns is passed in then the whole row is marked as needing display
- (void)updateRowsForObjects:(NSArray *)objs columns:(NSArray *)columns;

// updates the whole thing
- (void)update;


- (id)delegate;
- (void)setDelegate:(id)anObject; 

- (void)setBlockColumnConfigSaving:(BOOL)flag;

- (BOOL)sortedDisplay;
- (void)setSortedDisplay:(BOOL)aFlag;
- displayList;
- (BOOL)tableEditable;
- (void)setTableEditable:(BOOL)aFlag;
- (BOOL)cornerDeselectFlag;
- (void)setCornerDeselectFlag:(BOOL)aFlag;
- columnIdentifiers;

// Returns the column identifier dictionary that has the exact same attribute 
- (id)columnIdentifierForAttribute:(NSString *)anAttribute;

- (BOOL)observesSingleSelectionPattern;
- (void)setObservesSingleSelectionPattern:(BOOL)flag;

- (void)observedObjectDidChange:(NSNotification *)notif;

// If you are observing singleSelectionPattern but don't 
// want to deselect if the selection changes in something 
// like an inspector, then specify that TVC as a helper
- (BOOL)isHelper;
- (void)setIsHelper:(BOOL)flag;

- (BOOL)wantsAlternateColors;
- (void)setWantsAlternateColors:(BOOL)flag;

- (BOOL)isDraggable;
- (void)setIsDraggable:(BOOL)flag;

- (BOOL)acceptsDrags;
- (void)setAcceptsDrags:(BOOL)flag;

- (NSColor *)rowColor;
- (void)setRowColor:(NSColor *)aColor;

- (NSColor *)alternateRowColor;
- (void)setAlternateRowColor:(NSColor *)aColor;

- (NSString *)alertPanelBody;
- (void)setAlertPanelBody:(NSString *)aValue;

- (NSString *)alertPanelTitle;
- (void)setAlertPanelTitle:(NSString *)aValue;

- (void)setConfirmsDelete:(BOOL)flag;
- (BOOL)confirmsDelete;

- (void)setSelectsOnAdd:(BOOL)flag;
- (BOOL)selectsOnAdd;

- (void)setObjectCreationClassname:(NSString *)aValue;
- (NSString *)objectCreationClassname;

- (void)setAutosaveName:(NSString *)aValue;
- (NSString *)autosaveName;

// When this is set, then whenever recalc display is called, it sorts according to these rules, and not with the stuff specified in the identifiers dictionary
- (void)addToLastUserSortIdentifiers:(id)aColumn;
- (void)setLastUserSortIdentifiers:(NSMutableArray *)anArray;
- (NSMutableArray *)lastUserSortIdentifiers;


// If autosaveName is valid returns the config dict
- (NSDictionary *)columnConfigurationFromDefaults;

- (void)setIndicatorImage:(NSImage *)img 
	inTableColumn:(NSTableColumn *)tableColumn clearOthers:(BOOL)flag;
- (NSTableColumn *)firstColumnWithIndicatorImage;


- (void)setSortingMode:(TC_SORT_MODE)mode forColumnAtIndex:(int)index;
- (void)setSortingMode:(TC_SORT_MODE)mode forColumnIdentifiedBy:(NSString *)identifier;

- (void)toggleSortTableColumn:(NSTableColumn *)tableColumn;

    // TARGET/ACTION METHODS - START
- (IBAction)analyzeTableView:(id)sender;	
	
- (IBAction)addObject:(id)sender;
- (IBAction)deleteObject:(id)sender;
- (IBAction)delete:(id)sender;

// not outlineview safe!
- (IBAction)narrowToSelection:(id)sender;
- (IBAction)excludeSelection:(id)sender;

- target;
- (void)setTarget:sender;
- (SEL)doubleAction;
// invoke the
- doubleActionMethod:sender;
- (void)setDoubleAction:(SEL)aSel;
    // TARGET/ACTION METHODS - END

    /*	
    *	==================================================
     *	NSOutlineView SPECIFIC INTERFACE METHODS - START
     */

- (void)setChildrenAttributeName: anAttribute;
- childrenAttributeName;
// Expands all necessary objects to display the given object.
- (void)showObject: anObject;

- (BOOL)isExpandable:(id)item;		// can the item contain other items?
- (void)expandItem:(id)item expandChildren:(BOOL)expandChildren;
- (void)expandItem:(id)item;		// Above with expandChildren == NO.
- (void)collapseItem:(id)item collapseChildren:(BOOL)collapseChildren;
- (void)collapseItem:(id)item;		// Above with collapseChildren == NO.

- (int)levelForItem:(id)item;
- (BOOL)isItemExpanded:(id)item;
- (void)setIndentationPerLevel:(float)indentationPerLevel;
- (float)indentationPerLevel;
// The indentation marker is the visual indicator for an item that is expandable
//  (i.e. disclosure triangle, +/- indicators)
- (void)setIndentationMarkerFollowsCell: (BOOL)drawInCell;
- (BOOL)indentationMarkerFollowsCell;
- (void)setAutoresizesOutlineColumn: (BOOL)resize;
- (BOOL)autoresizesOutlineColumn;

- (void) registerForAllBindersNotification;


// Persistence
- (BOOL)autosaveExpandedItems;
- (void)setAutosaveExpandedItems:(BOOL)save;

    /*	
    *	NSOutlineView SPECIFIC INTERFACE METHODS - END
     *	==================================================
     */

	/*** Selection ***/

// when observing single selection pattern. If the object is the 
// notif is anything other than our tableView and that object's 
// delegate doesn't specify it as a helper, it calls deselectAll:
- (void)selectionDidChange:(NSNotification *)aNotif;

- (void)selectObject:anObject;
- (void)selectObject:anObject byExtension:(BOOL)flag;
- (void)selectObjectAt:(int)aDisplayPosition;
- (void)selectObjectAt:(int)aDisplayPosition byExtension:(BOOL)flag;

- (void)selectObjects:aList;
- (void)selectObjects:aList byExtension:(BOOL)flag;
- (void)selectAllObjects;

- (void)deselectAll:sender;
- (void)deselectAllColumns:(id)sender;

- selectedObject;
- selectedObjects:aList;	// Old way
- (NSArray *)selectedObjects;
- (unsigned int)selectedCount;

- (BOOL)selectUIForModel:aModel andAttribute:(NSString *)anAttribute;
- (BOOL)allFieldsIncomplete;
- (void)triggerFormatterForUI:errorList;

	/*** Private ***/
- (void)adjustColumnWidthForTableColumn: (NSTableColumn *)col;
- nsOutlineViewClass;
- (void)removeHierarchyObjectsInArray: removalArray;
- (NSArray *)objectPathToObject: anObject
                        inModel: aModel;
- childrenDisplayListForModel: aModel;

// Returns the sorted display list of children -- registers them with the display list, they aren't already there
- (NSArray *)fillAndRegisterChildren:(NSArray *)children forModel:(id)aModel;


- (void)updateTooltip;
- (void)updateCountField;
-       (BOOL)object: anObject
  isInArrayHierarchy: anArray;
- (void)fillDisplayList: (NSMutableArray *)destList
            withObjects: (NSArray *)srcList;
- objectAtRow: (int)row;
- childrenOfModel: item;
- (void)checkSelectionForChange;
- (void)recalculateDisplay;
- (void)prepareDisplayList;
- attributeForIdentifier:aColumnIdentifier;
- (void)privateSelectObject:anObject byExtension:(BOOL)flag;
- (void)scrollSelectionToVisible;
- (void)_IBsetSortedDisplay:(BOOL)aFlag;

- (void)modelIsComing:aModel;
- (void)modelIsLeaving:aModel;

- (NSString *)_defaultsName;
- (void)_saveColumnConfigsToDefaultsWithDefaultName:(NSString *)defName;

// Returns the column configuration dictionary (includes sort column)
- (NSMutableDictionary *)columnConfiguration;

// gets the column configuration dictionary and restore the sort ordering 
- (void)restoreLastUserSortFromDefaults;
- (void)restoreLastUserSortAccordingToDictionary:(NSDictionary *)dict;


@end

//   **********************  Back row support ***************************

@interface NSObject (MCBackgroundRowColorSupport)

// returns nil by default
- (NSColor *)backgroundRowColorForRow:(int)rowIndex;
- (NSColor *)backgroundDisplayColor;

@end


//   **********************  TVC Delegate ***************************

@interface NSObject (TVCDelegate)

- (void)tvc:aTVC willDisplayCell:(id)aCell forColumn:(NSTableColumn *)tc item:(id)object;

- (void)tvc:aTVC initingDataCell:aCell ofTableColumn:aTBC;

/*!

	Called during awake. Delegate has the ability to rename the table columns. Delegate can return nil to leave the default alone. Delegate can return an NSString, NSImage or NSAttributedString (not tested).
*/
- (id)tvc:aTVC 
		headerReplacementValueForTableColumn:(NSTableColumn *)tc 
		tvcIdentifier:(NSDictionary *)ident 
		keyPath:(NSString *)keyPath;

- (void)tvcDidDoubleClick:aTVC;
- (void)tvc:aTVC didChangeSelection:selectedObject;
- (BOOL)tvcShouldChangeSelection:aTVC;
- (BOOL)tvc:aTVC shouldDisplayObject:anObject;

/*!
	@method tvcDidUpdateCountFields:
	@discussion sent to the delegate once the count fields have been updated
*/
- (void)tvcDidUpdateCountFields:aTVC;

- tvc:aTVC needsNewObjectForRelationshipList:aList;
    // The delegate can utilize this method to provide the new object
    // to be used in the add operation


- (BOOL)tvcShouldPreventColumnConfigurationFromDefaults:aTVC;
	// called at awake from nib, if you *don't* want to restore from the defaults, return YES

    /*	
    *	--------------------------------------------------
     *	NSOutlineView SPECIFIC TVC DELEGATE METHODS - START
     */

- (void)tvc: aTVC itemWillCollapse: (NSNotification *)notification;
- (void)tvc: aTVC itemWillExpand: (NSNotification *)notification;
- (BOOL)tvc: aTVC shouldCollapseItem: anItem;
- (BOOL)tvc: aTVC shouldExpandItem: anItem;
- (BOOL)tvc: aTVC shouldSelectTableColumn: (NSTableColumn *)tableColumn;
- (BOOL)tvc: aTVC isItemExpandable: anItem;
- (int)tvc: aTVC numberOfChildrenOfItem: anItem;
- (BOOL)tvc: aTVC shouldSelectItem: anItem;
- (BOOL)tvc: aTVC shouldSortChildrenOfModel: anItem;

// if the delegate responds to this, then the delegate MUST provide the children objects
- (NSArray *)tvc: aTVC childrenOfModel: anItem;

// delegate is given an opportunity to replace the keypath that will be used to sort a column. Let's say that a column display an image type and the user whats to sort by that column. If no replacement key is needed, then nil should be returned (not an empty string)
- (NSString *)tvc:ATVC replacementSortKeyForUserSortKey:(NSString *)aKeyPath identifierInfo:(NSDictionary *)info;

- (id)tvc: aTVC childAtIndex:(int)index ofObject:(id)anObject;

- (id)tvc: aTVC objectValueForAttribute:(id)anIdent 
	ofObject:(id)anObject tableColumn:(NSTableColumn *)tableColumn;
	
- (void)tvc: aTVC 
	setObjectValue:(id)obj 
	forAttribute:(id)ident 
	ofObject:(id)obj 
	tableColumn:(NSTableColumn *)tableColumn;

    /*	
    *	NSOutlineView SPECIFIC TVC DELEGATE METHODS - END
     *	--------------------------------------------------
     */


    /****** Add / Modify / Delete *******/

- (BOOL)tvc:aTVC willAdd:anObject inRelationshipList:aList;
    // warns the delegate of an impending add. If the delegate returns nil
    // the addition is cancelled. The delegate should not free any of these
    // objects. At this point 'anObject' is populated.

- (void)tvc:aTVC didAdd:anObject inRelationshipList:aList;
    // Notifies the delegate that an addition has been completed. Disregards
    // the return value.

//- amd:anAMD willModify:anObject usingBinder:aBinder inRelationshipList:aList;
    // Warns the delegate of an impending 'modify'. If the delegate returns nil.
    // the modification is cancelled.

//- (void)amd:anAMD didModify:anObject usingBinder:aBinder inRelationshipList:aList;
    // Notifies the delegate that a modification has been done. Disregards the 
    // return value.
	
- (void)tvc:(id)aTVC gotDeleteFrom:(id)sender;
	// Tells the delegate that we got a 'delete:' from the responder chain. WARNING If the 
	// delegate responds to this method, it is the delegate sole responsibility 
	// to delete selected rows/objects 

- (BOOL)tvc:aTVC willDelete:anObject inRelationshipList:aList;
- (BOOL)tvc:aTVC willDeleteObjects:(NSArray *)objectList inRelationshipList:aList;
    // Warns the delegate of an impending deletion. If the delegate returns nil,
    // the deletion is cancelled.

- (void)tvc:aTVC didDelete:anObject inRelationshipList:aList;
- (void)tvc:aTVC didDeleteObjects:anObject inRelationshipList:aList;
    // Notifies the delegate that a deletion has just occurred. Disregards the 
    // return value.

- (BOOL)tvc:aTVC willEditAttribute:anAtt inDBO:aDBO;
- (BOOL)tvc:(id)aTVC
              control:(id)aControl
 textShouldEndEditing:(id)editor
               forDBO:(id)aDBO
         andAttribute:(id)anAttribute;
		 

- (BOOL)tvcCanCopyTabularDataToPasteboard:aTVC;
- (BOOL)tvcCanExportTabularData:aTVC;
- (BOOL)tvcCanAnalyzeTableView:aTVC;		 
//
// DRAG SUPPORT
// 		

// These methods are only called if allowDrag is YES. A location value of -1 
// means add to the list as you wish, a location value of count + 1 means
// add to the bottom of the list. aModel can be an array, a specific object or
// if TVC is working with an outline then it aModel will be the object that
// children
//
// if allowDrag is YES then the delegate MUST implement these methods
// otherwise an exception is thrown in the awakeFromNib or setDelegate
// methods
- (NSArray *)tvcAcceptableDropTypes:(MCTableviewController *)aTVC;

- (NSDragOperation)tvc:(MCTableviewController *)aTVC 
		validateDrop:(id <NSDraggingInfo>)info ontoModel:(id)aModel;

- (NSDragOperation)tvc:(MCTableviewController *)aTVC 
		validateDrop:(id <NSDraggingInfo>)info ontoModel:(id)aModel 
		atLocation:(int)aLoc;

- (BOOL)tvc:(MCTableviewController *)aTVC 
		acceptDrop:(id <NSDraggingInfo>)info ontoModel:(id)aModel;

- (BOOL)tvc:(MCTableviewController *)aTVC 
		acceptDrop:(id <NSDraggingInfo>)info ontoModel:(id)aModel 
		atLocation:(int)aLoc;

// TVC as a drag source
- (BOOL)tvc:(MCTableviewController *)aTVC writeObjects:(NSArray *)objs 
	toPasteboardForDrag:(NSPasteboard*)pboard;
	
	
	
	
// the table analyzer is a different object, it is controller by the TVC, but the TVC's delegate must determine a few things. When the table analyzer is invoked, the TVC's delegate is passed to the analyzer as a delegate to consult.

// before the popup is displayed showing which column can be analyzed, this method is called. Returning YES prevents the column from being a choice
- (BOOL)tableAnalyzer:(MCTableViewAnalyzer *)analyzer shouldHideColumn:(NSTableColumn *)column keyPath:(NSString *)path;

// if a column displays a values that a combined, you can return the separator for that column. If the column does not display a combined string, then just return nil	
- (NSString *)tableAnalyzer:(MCTableViewAnalyzer *)analyzer shouldSeparateValueFromColumn:(NSTableColumn *)column keyPath:(NSString *)path;

@end

@interface MCTableviewController (Sorting)

- (void)sortObjects:modelList forColumns:columnList into:sortedModelList;
- (void)sortObjects:modelList forColumns:columnList into:sortedModelList sortDirection:(int)direction;

// uses BDSortOrdering
- (NSArray *)sortObjectsAccordingTVCRules:(NSArray *)objs;

// uses BDSortOrdering and LastSortDirection key
- (NSArray *)userSortedObjects:(NSArray *)objs usingColumnIdentifiers:(NSArray *)idents;
// returns sorted objects according to LastSortDirection in all visible table column identifiers
- (NSArray *)userSortedObjects:(NSArray *)objs;

// sorts and redisplays the list according to LastSortDirection
- (IBAction)sortTableView:(id)sender;

@end


@interface MCModelSort : NSObject

+ (void)sortModels:(NSArray *)modelList 
	usingAttributeNamed:(NSString *)anAttribute 
	into:(NSMutableArray *)sortedModelList 
	sortDirection:(int)direction;

@end




//   **********************  Dynamic Table Views ***************************

@interface NSTableView (CCSDynamicSettings)

- (void)setDynamicSettings:(id)settings;

@end

/* Example Plist

{
    columns =
    (
     {
         title 			= "Judge ID";
         identifier 		= "judge_id";
         editable		= "N";
         resizable		= "Y";
         sorting		= "2";         
     },
     {
         title 			= "Judge Name";
         identifier 		= "judge_name";
         editable		= "N";
         resizable		= "Y";
         sorting		= "2";
     }
    )
}

*/

@interface NSObject (DBOInTVC)

- (NSColor *)tableDisplayColorForAttribute:(NSString *)anAttribute;
    // The DBOs in a TVC's model can implement this to change the background color of each cell in the table view. If this method returns *nil*, the background is set back to it's orginal color.

@end

