/**********************************************************************
 
	Copyright (C) 2003-2004
	Hirohisa MORI <joshua@nichibun.ac.jp>
	Tomoki SEKIYAMA <sekiyama@yahoo.co.jp>
 
	This program is free software; you can redistribute it 
	and/or modify it under the terms of the GLOBALBASE 
	Library General Public License (G-LGPL) as published by 

	http://www.globalbase.org/
 
	This program is distributed in the hope that it will be 
	useful, but WITHOUT ANY WARRANTY; without even the 
	implied warranty of MERCHANTABILITY or FITNESS FOR A 
	PARTICULAR PURPOSE.

**********************************************************************/



#include "VMouseTracker.h"
#include <LWindow.h>

#include <MacWindows.h>

short VMouseTracker::sButtonState = 0;
LPane *VMouseTracker::sTracked = 0;
LPane *VMouseTracker::sLastPointed = 0;
Point VMouseTracker::sLastPoint;
Point VMouseTracker::sPortMouse;
bool VMouseTracker::sNoForceQuitTracking;
const EventRecord *	VMouseTracker::sCurrentEvent = 0;

VMouseTracker::VMouseTracker()
{
}

VMouseTracker::~VMouseTracker()
{
}

LPane *
VMouseTracker::CheckEnterLeave(
	const EventRecord	&inMacEvent)
{
	WindowPtr	macWindowP;				// Ask Toolbox where the mouse is
	SInt16		thePart = ::MacFindWindow(inMacEvent.where, &macWindowP);

	LPane		*paneWithMouse = nil;
	LWindow		*theWindow;
	
	if ((thePart == inContent) || (thePart == inGrow)) { // Mouse is inside a Window
		theWindow = LWindow::FetchWindowObject(macWindowP);
		if (theWindow != nil) {			// Mouse is inside a PP Window
			sPortMouse = inMacEvent.where;
			theWindow->GlobalToPortPoint(sPortMouse);
			paneWithMouse = theWindow->FindDeepSubPaneContaining(
											sPortMouse.h, sPortMouse.v);
			if (paneWithMouse == nil)
				paneWithMouse = theWindow;
		}
	}
	
	sLastPointed = LPane::GetLastPaneMoused();
	
	if ( sTracked && sTracked->GetLastPaneClicked() != sTracked ) {	// pane may be deleted
		sTracked = 0;	// exit tracking mode
		sLastPointed = NULL;
	}
	
	if ( sTracked ) {	// tracking mode
		if ( paneWithMouse == sTracked ) {	// within tracked pane
			if ( sLastPointed != sTracked ) {
				sTracked->MouseEnter(sPortMouse, inMacEvent);
				sLastPointed = sTracked;
			}
		}
		else {								// out of tracked pane
			if ( sLastPointed == sTracked ) {
				sLastPointed = NULL;
				sTracked->MouseLeave();
			}
		}
	}
	else {				// normal mode
		if ( sLastPointed != paneWithMouse ) {
			if ( sLastPointed )
				sLastPointed->MouseLeave();
			if ( paneWithMouse )
				paneWithMouse->MouseEnter(sPortMouse, inMacEvent);
			sLastPointed = paneWithMouse;
		}
		else if ( sLastPointed != paneWithMouse ) {	// just turned into normal mode
			paneWithMouse->MouseEnter(sPortMouse, inMacEvent);
			sLastPointed = paneWithMouse;
		}
	}
	
	LPane::SetLastPaneMoused(sLastPointed);
	return sTracked ? sTracked : paneWithMouse;
}

void
VMouseTracker::SpendTime(
	const EventRecord	&inMacEvent)
{
	if ( inMacEvent.what == kHighLevelEvent ) {	// High level events don't
		return;									// pass the mouse location
	}											// in the EventRecord
	
	if ( inMacEvent.what == mouseUp ) {
		if ( ! sButtonState )
			return;
	}
	else if ( inMacEvent.what != mouseDown ) {
		EventRecord e;
		if ( EventAvail(mUpMask, &e) )
			return;
	}

	sCurrentEvent = &inMacEvent;

//if ( inMacEvent.what != nullEvent )	
//printf("inMacEvent.what : %d  (%d,%d) %d\n", inMacEvent.what, inMacEvent.where.h, inMacEvent.where.v, inMacEvent.modifiers);
	if ( inMacEvent.what != mouseDown && inMacEvent.what != mouseUp &&
			sLastPoint.h == inMacEvent.where.h && sLastPoint.v == inMacEvent.where.v )
		return;
	sLastPoint = inMacEvent.where;

	if ( inMacEvent.what == nullEvent || inMacEvent.what == mouseDown ||
			inMacEvent.what == mouseUp || inMacEvent.what == keyDown ||
			inMacEvent.what == keyUp || inMacEvent.what == autoKey )
		sButtonState = ! (inMacEvent.modifiers & btnState/*released*/);

	if ( inMacEvent.what == mouseUp ) {
		sTracked = 0;			// end tracking
	}
	
	if ( !sNoForceQuitTracking && inMacEvent.what == nullEvent ) {
		if ( sTracked ) {		// tracking mode
			if ( ! sButtonState ) {	// couldn't catch mosue up event
				sTracked = 0;			// force quit tracking
			}
		}
	}

	LPane *target = CheckEnterLeave(inMacEvent);
/*
static LPane*lt;
if ( lt != target )
printf("target : %x => %x\n", lt, target);
lt = target;
*/	
	if ( target && inMacEvent.what != mouseDown && inMacEvent.what != mouseUp ) {
		target->MouseWithin(sPortMouse, inMacEvent);
	}
	
	if ( inMacEvent.what == mouseDown ) {
		if ( ! sTracked ) {		// noraml mode
			sTracked = target;
			sNoForceQuitTracking = false;
		}
	}

	if ( inMacEvent.what == mouseUp )
		sButtonState = false;

	sCurrentEvent = 0;
}
