Milán Major

netscape-revival

1 branch
Code

lib/mac/VText/V_PowerPlant_Mods/LEventHandler.cp

//	===========================================================================
//	LEventHandler.cp			©1994-5 Metrowerks Inc. All rights reserved.
//	===========================================================================

#ifdef PowerPlant_PCH
#include PowerPlant_PCH
#endif

#include	"LEventHandler.h"
#include	<LSelection.h>
#include	<LSelectableItem.h>
#include	<UCursor.h>
#include	<LModelProperty.h>
#include	<LSelectHandlerView.h>
#include	<LStream.h>

#ifndef		__AEREGISTRY__
#include	<AERegistry.h>
#endif

#pragma	warn_unusedarg off

LManipulator *	LEventHandler::sLastManDown = NULL;

//	===========================================================================
//	Maintenance

LEventHandler::LEventHandler()
{
	mEvtItem = NULL;
	mEvtThing = NULL;
	mEvtManipulator = NULL;
	mEvtSelection = NULL;

	mSelection = NULL;
	mDragItem = NULL;

	mSelectionCanMove = false;
}

LEventHandler::~LEventHandler()
{
	ReplaceSharable(mEvtItem, (LSelectableItem *)NULL, this);
	ReplaceSharable(mEvtThing, (LManipulator *)NULL, this);
	ReplaceSharable(mEvtSelection, (LSelection *)NULL, this);
	ReplaceSharable(mEvtManipulator, (LManipulator *)NULL, this);
	
	ReplaceSharable(mDragItem, (LManipulator *)NULL, this);

	ReplaceSharable(mSelection, (LSelection *)NULL, this);

	ReplaceSharable(sLastManDown, (LManipulator *)NULL, this);
}

#ifndef	PP_No_ObjectStreaming

void	LEventHandler::WriteObject(LStream &inStream) const
{
	inherited::WriteObject(inStream);
	
	inStream << mSelection;
}

void	LEventHandler::ReadObject(LStream &inStream)
{
	inherited::ReadObject(inStream);
	
	SetSelection(ReadStreamable<LSelection *>()(inStream));
}

#endif

void	LEventHandler::Reset(void)
{
	OSErr	err = noErr;

	ReplaceSharable(mEvtItem, (LSelectableItem *)NULL, this);
	ReplaceSharable(mEvtThing, (LManipulator *)NULL, this);
	ReplaceSharable(mEvtSelection, (LSelection *)NULL, this);
	ReplaceSharable(mEvtManipulator, (LManipulator *)NULL, this);

	ReplaceSharable(mDragItem, (LManipulator *)NULL, this);

	ReplaceSharable(sLastManDown, (LManipulator *)NULL, this);

	mSelectionCanMove = false;

	inherited::Reset();
}

LSelection *	LEventHandler::GetSelection(void)
{
	return mSelection;
}

void	LEventHandler::SetSelection(LSelection *inSelection)
{
	ReplaceSharable(mSelection, inSelection, this);
}

void	LEventHandler::NoteOverNewThing(LManipulator *inThing)
/*
	This function is called with appropriate parameters when
	the mouse is over a new manipulator or newly over no manipulator
	(inItem will be NULL).
	
	Override & inherit to provide for cursor shape feedback on based on
	mouse position over manipulators, selectable items, or selections
	(check inItem->ItemType() to determine which).
	
	NOTE:	A first place to look to overide this functionality is in
	LHandlerView
*/
{
	if (mHandlerView)
		mHandlerView->NoteOverNewThing(inThing);
}

void	LEventHandler::NoteOverNewThingSelf(LManipulator *inThing)
/*
	Override & inherit to provide for cursor shape feedback on based on
	mouse position over manipulators, selectable items, or selections
	(check inItem->ItemType() to determine which).
	
	NOTE:	A first place to look to overide this functionality is in
	LHandlerView
*/
{
	if (inThing) {
		switch(inThing->ItemType()) {
			case kManipulator:
				UCursor::Tick(cu_Hand);
				break;
			case kSelectableItem:
			case kSelection:
				UCursor::Tick(cu_Arrow);
				break;
		}
	} else {
		UCursor::Tick(cu_Arrow);
	}
}

Boolean	LEventHandler::OverDifferentThing(
				const Point		inWhere,		//	local coordinates
				LManipulator	*inOldThing,	//	Old item pointer
				LManipulator	**outNewThing	//	Location for new item ptr.
)
/*
	Note, this method gives priority to "things" in the order:
	
		Manipulators (not selections or selectable items)
		Selections
		Selectable items
*/
{
	LManipulator	*itemFound = NULL;
	
	Assert_(outNewThing != NULL);
	
	if (mInBounds)
		itemFound = OverManipulator(inWhere);
	ReplaceSharable(mEvtManipulator, itemFound, this);

	if (mInBounds)
		itemFound = OverSelection(inWhere);
	ReplaceSharable(mEvtSelection, (LSelection *)itemFound, this);

	if (mInBounds)
		itemFound = OverItem(inWhere);
	ReplaceSharable(mEvtItem, (LSelectableItem *)itemFound, this);

	do {
		itemFound = mEvtManipulator;
		if (itemFound)
			break;
		
		itemFound = mEvtSelection;
		if (itemFound)
			break;
		
		itemFound = mEvtItem;
	} while (false);
	
	//	Return
	if (itemFound != inOldThing) {
		*outNewThing = itemFound;
		return true;
	} else {
		return false;
	}
}

LManipulator *	LEventHandler::OverManipulator(Point inWhere)
{
	LManipulator	*rval = NULL;
	
	if (sLastManDown && sLastManDown->PointInRepresentation(inWhere))
		rval = sLastManDown;
	
	if (!rval)
		rval = mHandlerView->OverManipulator(inWhere);
	
	if (rval)
		return rval;
	
	return OverManipulatorSelf(inWhere);
}

LSelection *	LEventHandler::OverSelection(Point inWhere)
{
	LSelection *rval = mHandlerView->OverSelection(inWhere);
	
	if (rval)
		return rval;
	
	return OverSelectionSelf(inWhere);
}

LSelectableItem *	LEventHandler::OverReceiver(Point inWhere)
{
	LSelectableItem *rval = mHandlerView->OverReceiver(inWhere);
	
	if (rval)
		return rval;
	
	return OverReceiverSelf(inWhere);
}

LSelectableItem *	LEventHandler::OverItem(Point inWhere)
{
	LSelectableItem *rval = mHandlerView->OverItem(inWhere);
	
	if (rval)
		return rval;
	
	return OverItemSelf(inWhere);
}

LManipulator *	LEventHandler::OverManipulatorSelf(Point inWhere)
/*
	If overridden, inherit this method.  In the overriding method,
	return the inherited rval if it is non-NULL.
*/
{
	if (mEvtManipulator && mEvtManipulator->PointInRepresentation(inWhere))
		return mEvtManipulator;
			
	return NULL;
}

LSelection *	LEventHandler::OverSelectionSelf(Point inWhere)
/*
	Clients likely will not need to override this method.
*/
{
/*
	Note this checks mSelection and not mEvtSelection -- mEvtSelection
	can pretty much be considered a Boolean flag.
*/
	if (mSelection && mSelection->PointInRepresentation(inWhere))
		return mSelection;
	
	return NULL;
}

LSelectableItem *	LEventHandler::OverReceiverSelf(Point inWhere)
/*
	This is defined here just to avoid ugly casts.

	Functionality is normally provided by a subclass of LHandlerView or
	possibly an event handler subclass.
*/
{
	return NULL;
}

LSelectableItem *	LEventHandler::OverItemSelf(Point inWhere)
{
	if (mEvtItem && mEvtItem->PointInRepresentation(inWhere))
		return mEvtItem;
	
	return NULL;
}

void	LEventHandler::SetEvtThing(LManipulator *inThing)
{
	Assert_(inThing != mEvtThing);
	
	if (mEvtThing)
		mEvtThing->MouseExit();
		
	ReplaceSharable(mEvtThing, inThing, this);
	
	if (mEvtThing)
		mEvtThing->MouseEnter();
}

void	LEventHandler::PreScroll(Point inVector)
{
	inherited::PreScroll(inVector);
	
	if (mDragItem && (GetEvtState() == evs_Drag))
		mDragItem->UnDrawDragFeedback(mLastEvtMouse);
}

void	LEventHandler::PostScroll(Point inVector)
{
	inherited::PostScroll(inVector);
	
	if (mDragItem && (GetEvtState() == evs_Drag))
		mDragItem->DrawDragFeedback(mEvtMouse);
}

//	===========================================================================
//	Implementation

DragTypeT	LEventHandler::GetDragType(void)
{
	DragTypeT	rval = dragType_Unknown;

	if (mEvtThing) {
		switch(mEvtThing->ItemType()) {

			case kManipulator:
				rval = dragType_Manipulator;
				break;
			
			case kSelectableItem:
			case kSelection:
				rval = dragType_Selecting;
				break;
		}
	}
			
	return rval;
}
		
Boolean	LEventHandler::CheckCursor(void)
{
	Boolean	rval = false;
	
	if (mInBounds) {
		rval = inherited::CheckCursor();
		NoteOverNewThing(mEvtThing);
	}
	
	return rval;
}

Boolean	LEventHandler::CheckThings(void)
{
	Boolean			rval = false;
	LManipulator	*tempThing;
	
	if (OverDifferentThing(mEvtMouse, mEvtThing, &tempThing)) {
		SetEvtThing(tempThing);
		rval = true;
	}
	return rval;
}

void	LEventHandler::MouseDown(void)
{
	inherited::MouseDown();
	
	if (mEvtThing)
		mEvtThing->MouseDown();
}

void	LEventHandler::MouseUp(void)
{
	if (mEvtThing)
		mEvtThing->MouseUp();

	inherited::MouseUp();
}

Boolean	LEventHandler::DoCondition(EventConditionT inCondition)
{
	Boolean	rval = false;

	switch (inCondition) {

		//	Actions
		case eva_Down:
			mEvtClickCount++;
			mMaybeDragDragged = false;
			mSelectionCanMove = false;
			mEvtClickChangedSelection = false;
			CheckThings();
			
			if (mEvtSelection && (mEvtClickCount == 1)) {
				mSelectionCanMove = true;
			} else {
			
				CheckThings();	//	adjust for count increment...

				if (mSelection) {
					mEvtClickChangedSelection = true;
					
					if (mEvtRecord.modifiers & cmdKey) {
						mSelection->SelectDiscontinuous(mEvtItem);
					} else if (mEvtRecord.modifiers & shiftKey) {
						mSelection->SelectContinuous(mEvtItem);
					} else {
						mSelection->SelectSimple(mEvtItem);
					}
					
					CheckThings();
					if (mAllowSingleGestureDrag && mEvtSelection) {
						mSelectionCanMove = true;
						CheckCursor();
					}
				}
			}
			break;
		
		case eva_Up:
			if (mSelection && !mEvtClickChangedSelection) {
				mSelection->SelectSimple(mEvtItem);	//	A click through de-selection / selection
				CheckThings();
				CheckCursor();
			}
			break;

		case eva_DStart:
		{
			mMaybeDragDragged = true;
			mDragType = GetDragType();
			
			switch (mDragType) {

				case dragType_Manipulator:
					Assert_(mDragItem == NULL);
					ReplaceSharable(mDragItem, mEvtThing, this);
					if (mDragItem)
						mDragItem->DragStart(mEvtLastButtonWhere);	//	Use real down location
					break;
			}
			break;
		}
		
		case eva_DMove:
		{
			if (mInBounds) {
				switch (mDragType) {
	
					case dragType_Selecting:
						CheckThings();
						if (mSelection)
							mSelection->SelectContinuous(mEvtItem);
						break;
					
					case dragType_Manipulator:
						if (mDragItem)
							mDragItem->DragMove(mLastEvtMouse, mEvtMouse);
						break;
				}
			}
			CheckBoundaryDrag();
			break;
		}
		
		case eva_DStop:
		{
			switch (mDragType) {

				case dragType_Manipulator:
					if (mDragItem)
						mDragItem->DragStop(mEvtMouse);
					break;
			}
			ReplaceSharable(mDragItem, (LManipulator *)NULL, this);
			mEvtClickCount = 0;
			CheckThings();
			CheckCursor();	//	note absent if
			break;
		}

		//	Button conditions
		case evc_Out:
			if (CheckThings())
				CheckCursor();
			rval = mEvtThing != sLastManDown;
			break;
			
		case evc_In:
			if (CheckThings())
				CheckCursor();
			rval = mEvtThing == sLastManDown;
			break;
		
		case evc_Button:
			if (CheckThings())
				CheckCursor();
			if (mEvtThing)
				rval = !mEvtThing->Dragable();
			break;
		
		case evc_NButton:
			rval = !DoCondition(evc_Button);
			break;
		
		//	Button actions
		case eva_BSet:
			ThrowIfNULL_(mEvtThing);
			ReplaceSharable(sLastManDown, mEvtThing, this);
			break;
				
		case eva_BClear:
			ReplaceSharable(sLastManDown, (LManipulator *)NULL, this);
			break;

		//	Default
		default:
			rval = inherited::DoCondition(inCondition);
			break;
	}
	
	return rval;
}