// modifided from AccpetWindow.m in NextDeveloper/Examples/WhatADrag
//  by Miyai, ISR	1992.7.28

// AcceptWindow.m
// By Jayson Adams, NeXT Developer Support Team
// You may freely copy, distribute and reuse the code in this example.
// NeXT disclaims any warranty of any kind, expressed or implied, as to its
// fitness for any particular use.

#import <stdlib.h>
#import <objc/Storage.h>

#import "AcceptWindow.h"
#import "IFolderCell.h"
#import "TransparentWindow.h"
#import "errdebug.h"

#define NOVIEWRECT -1

typedef struct _ViewRectPair {
	id	view;
	id	controlView;
	NXRect	rect;
	} ViewRectPair;


@implementation AcceptWindow


/* instance methods */

- initContent:(const NXRect *)contentRect style:(int)aStyle
  backing:(int)bufferingType buttonMask:(int)mask defer:(BOOL)flag
{
    [super initContent:contentRect
	   style:aStyle
	   backing:bufferingType
	   buttonMask:mask
	   defer:flag];

    viewRectList = [[Storage alloc] initCount:0
				    elementSize:sizeof(ViewRectPair)
				    description:"{@@ffff}"];
    
    viewRectUnderPoint = NOVIEWRECT;
    
    return self;
}

- registerRect:(NXRect *)rect forCell:cell controlView:cView
{
    ViewRectPair    *newViewRect, *viewRect;
    int		listCount;
    
    // check if the same cell is already registered,
    // and if it registered, remove it from view list
    listCount = [viewRectList count];
    while (listCount--) {
	// element num. is (listCount-1)
	viewRect = [viewRectList elementAt:listCount];
	if ((viewRect->view) == cell) {
	    //[viewRectList removeAt:listCount];
	    [viewRectList removeElementAt:listCount];
	    DBG(10,fprintf(stderr," remove old viewRect from list for cell that is already registered and try to register new one.\n"));
	    break;
	}
    }
    
  /* add the view-rect pair to our list */
    newViewRect = (ViewRectPair *)malloc(sizeof(ViewRectPair));
    newViewRect->view = cell;
    newViewRect->controlView = cView;
    newViewRect->rect = *rect;
    
    [viewRectList addElement:newViewRect];
    
    return self;
}

- unregisterRectForCell:cell
{
    int		listCount;
    ViewRectPair	*viewRect;

    listCount = [viewRectList count];
    while (listCount--) {
	viewRect = [viewRectList elementAt:listCount];
	if ((viewRect->view) == cell) {
	    //[viewRectList removeAt:listCount];
	    [viewRectList removeElementAt:listCount];
	    return (cell);
	}
    }
    DBG(10,fprintf(stderr," couldn't find cell to be unregisterd\n"));
    return nil;
}

- (BOOL)windowEntered:(NXPoint *)mouseLocation fromSource:dragSource
{
    NXPoint	    windowPoint;
    int		    newViewRectUnderPoint;
    ViewRectPair    *viewRect, *oldViewRect;
    BOOL	    oldViewDrew = NO, newViewDrew = NO;
        
  /* convert the mouse location to local coordinates */
    windowPoint = *mouseLocation;
    [self convertScreenToBase:&windowPoint];
    
  /* see if any of the views in our list lay under the mouse point */
    newViewRectUnderPoint = [viewRectList count];
    while (newViewRectUnderPoint--) {
	viewRect = (ViewRectPair *)[viewRectList
      					    elementAt:newViewRectUnderPoint];
	if (NXPointInRect(&windowPoint, &(viewRect->rect))) {
	    break;
	}
    }
    
  /* see if the mouse has moved over a different view */
    if (viewRectUnderPoint != newViewRectUnderPoint) {
      /* tell the view previously under the mouse that the window has exited */
	if (viewRectUnderPoint != NOVIEWRECT) {
	    oldViewRect = (ViewRectPair *)[viewRectList
						 elementAt:viewRectUnderPoint];
//	    oldViewDrew = [oldViewRect->view windowExited:dragSource];
	    oldViewDrew = [oldViewRect->view windowExited:dragSource
	    				controlView:oldViewRect->controlView];
	}
      /* save the new view under the mouse */
	viewRectUnderPoint = newViewRectUnderPoint;
	
      /*
       * if there's a view under the mouse point, tell it that a window has
       * entered it
       */
	if (viewRectUnderPoint != NOVIEWRECT) {
	    viewRect = (ViewRectPair *)[viewRectList
	    					elementAt:viewRectUnderPoint];
//	    newViewDrew = [viewRect->view windowEntered:dragSource];
	    newViewDrew = [viewRect->view windowEntered:dragSource
	    				controlView:viewRect->controlView];
	}
    }
    
  /* let the caller know if any of our accept views has done any drawing */
    return (oldViewDrew || newViewDrew);
}

- (BOOL)windowExited:dragSource
{
    ViewRectPair    *viewRect;
    BOOL	    viewDrew = NO;
    
  /* tell any view previously under the mouse point that it no longer is */
    if (viewRectUnderPoint != NOVIEWRECT) {
	viewRect = [viewRectList elementAt:viewRectUnderPoint];
//	viewDrew = [viewRect->view windowExited:dragSource];
	viewDrew = [viewRect->view windowExited:dragSource 
					controlView:viewRect->controlView];
	viewRectUnderPoint = NOVIEWRECT;
    }
    
  /* tell the caller whether or not the view did some drawing */
    return viewDrew;
}

- (BOOL)windowDropped:(NXPoint *)mouseLocation fromSource:source
{
    NXPoint	    windowPoint;
    int		    newViewRectUnderPoint;
    ViewRectPair    *viewRect;
//    BOOL	    accepted = NO;
    BOOL	    accepted;
    
    accepted = [source defaultAccepted];
    
  /* convert the mouse location to local coordinates */
    windowPoint = *mouseLocation;
    [self convertScreenToBase:&windowPoint];
    
  /* see if any of the views in our list lay under the mouse point */
    newViewRectUnderPoint = [viewRectList count];
    while (newViewRectUnderPoint--) {
	viewRect = (ViewRectPair *)[viewRectList
     					    elementAt:newViewRectUnderPoint];
	if (NXPointInRect(&windowPoint, &(viewRect->rect))) {
	    break;
	}
    }
 
  /* tell any view previously under the mouse point that the window moved */
    if (viewRectUnderPoint != NOVIEWRECT &&
	viewRectUnderPoint != newViewRectUnderPoint) {
	
	viewRect = (ViewRectPair *)[viewRectList elementAt:viewRectUnderPoint];
//	[viewRect->view windowExited:source];   
	[viewRect->view windowExited:source controlView:viewRect->controlView];   
    }
    
  /*
   * tell the view under the mouse point (if any) that the user dropped a
   * window on it
   */
    if (newViewRectUnderPoint != NOVIEWRECT) {
	viewRect = (ViewRectPair *)[viewRectList
      					     elementAt:newViewRectUnderPoint];
//	accepted = [viewRect->view windowDropped:source];
	accepted = [viewRect->view windowDropped:source 
				controlView:viewRect->controlView];
    }
    
  /* no window under the mouse now */
    viewRectUnderPoint = NOVIEWRECT;
    
    return accepted;
}

@end
