
//======================================================================
//
//	Portions written by FreemanSoft Inc.
//
//	FreemanSoft disclaims any warranty of any kind, expressed or implied,
//	as to this source code's fitness for any particular use.
//
//	For more information, use the following electronic mail addresses:
//	 
//		info@FreemanSoft.com	general questions
//		support@FreemanSoft.com	technical questions
//
//======================================================================


/* Written by
 *	Joe Freeman	jfreeman@next.com	
 *	DragView
 *
 *	This code has no warranty.  
 *	It is provided so that the consumer may maintain and modify it
 *	at their own risk.  Use this code at your own risk.
 */

#import "DragView.h"
#import <appkit/appkit.h>

#define bozo_alert	"Bozo Alert"
#define make_mind_up "Can you please decide what folder you want to drag in?"
#define OK		"OK"



@implementation DragView


- setDelegate:anObject
{
    delegate = anObject;
    [self registerForDraggedTypes:&NXFilenamePboardType
    				count:1 ];
    return self;
}
 
/*========================================================================
 * notifies workspace to slide browser to that points
 *========================================================================*/
- mouseDown:(NXEvent *)theEvent
{
    NXEvent localCopy = *theEvent;
    [self convertPoint: &localCopy.location fromView:nil];
    if (delegate && 
    		[delegate respondsTo:@selector(userClicked:at:inDragView:)])
	[delegate 	userClicked:localCopy.data.mouse.click 
			at:&localCopy.location 
			inDragView:self];
    return self;
}


/*========================================================================
 *
 *========================================================================*/

- (NXDragOperation)draggingEntered:(id <NXDraggingInfo>)sender
{    
    /* we only support generic kinds of drags (no links or copies) */

    if (delegate && 
    	[delegate respondsTo:@selector(iconEntered:)] &&
    	[delegate respondsTo:@selector(iconBogus:)]
	)
    {
        [self proposedImage:[sender draggedImage]];
	if ( [delegate isFilePBValid:[sender draggingPasteboard] forView:self])
	{
		[delegate iconEntered:self];
	}
	else
	{
		[delegate iconBogus:self];
	}
    	return NX_DragOperationGeneric;
    } 
    else 
    {
    	return NX_DragOperationNone;
    }
}

- draggingExited:(id <NXDraggingInfo>)sender
{
    if (delegate && [delegate respondsTo:@selector(iconLeft:)]) {
        [self abortProposedImage:self];
	[delegate  iconLeft:self];
	if (++exit_count > 6){
		NXRunAlertPanel("Bozo Alert",
		make_mind_up,
		OK,NULL,NULL);
		exit_count = 0;
	}
    	return self;
    }
    else
    	return nil;
}

/* after the icon is let go but while still on the screen 
 * return yes to accept , no to not accept
 */
- (BOOL)prepareForDragOperation:(id <NXDraggingInfo>)sender
{
    Pasteboard *filePB;
    BOOL	retFlag = NO;
    
    exit_count = 0;
    filePB = [sender draggingPasteboard];
    if ( delegate &&
	[delegate acceptedFilePB:[sender draggingPasteboard] forView:self])
    {
	[self currentImage:[sender draggedImageCopy]];
	[delegate iconDropped:self];
	retFlag =  YES;
    }
    else
    {
    	[self abortProposedImage:self];
    	retFlag =  NO;
    }
    if (delegate && [delegate respondsTo:@selector(iconDropped:)])
		[delegate iconDropped:self];
    return retFlag;
}

/*
 * last message received
 * 
 * through experimentation I determined
 * we only get here if we returned YES in prepareForDragOperaton
 */
 
- (BOOL)performDragOperation:(id <NXDraggingInfo>)sender
{
    return YES;
}

/*========================================================================
 * so someone can programaticly tell to grab an icon for a specific file
 *========================================================================*/
- useIconForFile:(char *)aFullFilePath
{
    NXImage *imageForFile;
    
    imageForFile = [[Application workspace] getIconForFile:aFullFilePath];
    
    if (imageForFile)
    {
    	[self currentImage:imageForFile];
    	return self;
    }
    else
    {
    	/* should never get this.  workspace returns unknown icon */
        [self currentImage: [[NXImage alloc] initFromSection:"JumpBack_help"]];
    	return nil;
    }
}

/*========================================================================
 *
 *	dual icon handling code
 *
 *========================================================================*/

- proposedImage:theImage 
{
	if (theImage != proposedImage) {
		proposedImage = theImage;
		[self display];
	}
	return self;
}


- currentImage:theImage 
{
	proposedImage = nil;
	if (currentImage != theImage)  {
		[currentImage  free];
		currentImage = theImage;
		[self display];
	}
	return self;
}

- (NXImage *)currentImage
{
    return currentImage;
}

- abortProposedImage:sender
{
    return [self proposedImage:nil];
}

- acceptProposedImage:sender
{
    return [self currentImage: proposedImage];
}

- clearCurrentImage:sender
{
    return [self currentImage: nil];
}



- drawSelf:(const NXRect *)r :(int)c
{
	NXPoint 	iconOrigin;
	NXSize		iconSize;
	
	NXDrawGrayBezel(&bounds, &bounds);
	/*
	 * proposed is checked first in case we 
	 * have current but are proposing new 
	 */
	if (proposedImage){
		[proposedImage getSize:&iconSize];
		iconOrigin.x= (bounds.size.width-iconSize.width)/2.0;
		iconOrigin.y= (bounds.size.height-iconSize.height)/2.0;
		[proposedImage composite:NX_SOVER 
				toPoint: (const NXPoint *)&iconOrigin];
		/* really ugly */
		PSsetalpha(.5);
		PScompositerect(	iconOrigin.x, 
					iconOrigin.y,
					iconSize.width, 		
					iconSize.height,
					 NX_SOVER);
	} else if (currentImage){
		[currentImage getSize:&iconSize];
		iconOrigin.x= (bounds.size.width-iconSize.width)/2.0;
		iconOrigin.y= (bounds.size.height-iconSize.height)/2.0;
		[currentImage composite:NX_SOVER 
					toPoint: (const NXPoint *)&iconOrigin];
	}
	return self;
}



@end
