/*===============================
|	PopupMenuContentHandler.c
|
|	Blugs 1.1 handler for a pop-up menu
|	www.blugs.com
|
|	Copyright © 1998-2001 Kyle Hammond, Brian Hall
|
|===============================*/
#ifdef __APPLE_CC__
#include <Carbon/Carbon.h>
#else
#ifndef __MENUS__
#include <Menus.h>
#endif

#ifndef __TEXTUTILS__
#include <TextUtils.h>
#endif

#ifndef __TOOLUTILS__
#include <ToolUtils.h>
#endif
#endif

#include "PopupMenuContentHandler.h"
#include "BlugsAppearanceExtras.h"


static void		local_PMDraw( Rect *r, BLPopupMenuHdl data, UInt8 indent, Boolean active );
static void		local_PMSet( BLPopupMenuHdl popupMenu, ResType flavor, Ptr data, UInt32 dataSize );
static void		local_PMGet( BLPopupMenuHdl inPopupMenu, BLHandlerParamPtr ioParam );
static UInt32	local_PMClick( const Rect *box, BLPopupMenuHdl data  );


#if !__BL_USE_CARBON_API__
#define GetMenuWidth(menuH)		((**menuH).menuWidth)
#endif


pascal UInt32 PopupMenuContentHandler(	BLMessage			message,
										BLHandlerParamPtr	param		)
{
	UInt32			response = 0;
	BLPopupMenuHdl	menuH = nil;
	
	if (param) menuH = (BLPopupMenuHdl)param->ioStorage;
	switch (message)
	{
		case blHandlerInitMsg:
		response = blWantsClick;
		break;

		case blCellDrawMsg:
		local_PMDraw( &param->inRect, menuH, param->inIndent, BLIsActive( param->inList ) );
		break;
		
		case blCellInitMsg:
		param->ioStorage = NewHandleClear( sizeof(BLPopupMenuRec) );
		break;
		
		case blCellSetDataMsg:
		local_PMSet( menuH,  param->ioDataFlavor, param->ioDataBuffer, param->ioDataSize );
		break;

		case blCellGetDataMsg:
		local_PMGet( menuH,  param );
		break;
		
		case blCellClickMsg:
		response = local_PMClick( &param->inRect, menuH );
		break;

		case blCellDeinitMsg:
		if (menuH) DisposeHandle( (Handle)menuH );
		break;
		
		default:
		break;
	}
	return response;
}

//===============================
static void local_PMDraw( Rect *r, BLPopupMenuHdl data, UInt8 indent, Boolean active )
{
	MenuRef		menu;
	
	menu = (*data)->menu;
	if (menu)
	{
		Rect			box = *r, arrowRect;
		SInt16			value;
		
		box.left += indent;
		box.right -= 11;
		value = (*data)->value;
		if (value)
		{
			Str255		truncatedString;
			OSErr		err;
			Boolean		truncated;
			Rect		textRect;
			Point		bounds;
			SInt16		baseline;
			
			GetMenuItemText( menu, value, truncatedString );
			err = BLTruncateString( truncatedString, kThemeCurrentPortFont,
									box.right - box.left,
									((BLEnvironment() & blHasAqua) == blHasAqua) ? truncMiddle : truncEnd,
									&truncated );
			textRect = box;
			err = BLGetTextDimensions( &truncatedString[1], truncatedString[0], kThemeCurrentPortFont,
										kThemeStateActive, false, &bounds, &baseline );
			textRect.bottom = textRect.top + bounds.v;
			textRect.right = textRect.left + bounds.h;
			BLAlignRectInRect( blAlignVCenter, false, &textRect, r );
			err = BLDrawTextBox( &truncatedString[1], truncatedString[0], kThemeCurrentPortFont,
								kThemeStateActive, false, &textRect, teFlushDefault );
		}
		arrowRect = *r;
		arrowRect.bottom--;
		arrowRect.left = box.right;
		arrowRect.top = arrowRect.bottom - 7;
		BLDrawPopupArrow( arrowRect, kThemeArrowDown, kThemeArrow9pt,
						(active) ? kThemeStateActive : kThemeStateInactive );
	}
}

//===============================
static void local_PMSet( BLPopupMenuHdl popupMenu, ResType flavor, Ptr data, UInt32 dataSize )
{
	MenuHandle			menu;
	BLPopupMenuResRec	res;
	
	switch (flavor)
	{
		case kPopupMenuHandler_DataFlavor:
		BlockMoveData( data, *popupMenu, dataSize );
		break;
		
		case kPopupMenuHandler_ResourceDataFlavor:
		BlockMoveData( data, (Ptr)&res, dataSize );
		(*popupMenu)->value = res.value;
		(*popupMenu)->fontNumber = res.fontNumber;
		(*popupMenu)->fontSize = res.fontSize;
		menu = GetMenu( res.menuID );
		if (menu)
		{
			InsertMenu( menu, -1 );
			if (res.value) CheckMenuItem( menu, res.value, true );
		}
		(*popupMenu)->menu = menu;
		break;
	}
}

//===============================
static void local_PMGet( BLPopupMenuHdl inPopupMenu, BLHandlerParamPtr ioParam )
{
	UInt32	bytes = 0;
	
	switch (ioParam->ioDataFlavor)
	{
		case kPopupMenuHandler_DataFlavor:
		bytes = sizeof(BLPopupMenuRec);
		if (ioParam->ioDataBuffer) BlockMoveData( *inPopupMenu, ioParam->ioDataBuffer, bytes );
		break;
	}
	ioParam->ioDataSize = bytes;
}

//===============================
static UInt32 local_PMClick( const Rect *box, BLPopupMenuHdl data )
{
	UInt32		answer = blCellClickHandled;
		
	if (data)
	{
		MenuRef		menu;
		
		menu = (*data)->menu;
		if (menu)
		{
			Point			menuDisplayPt;
			UInt16			menuWidth;
			SInt32			theResult;
			SInt16			oldValue, newValue;
			
			CalcMenuSize( menu );
			menuWidth = GetMenuWidth( menu );
			menuDisplayPt.h = (box->left + box->right - menuWidth) / 2;
			menuDisplayPt.v = box->top;
			LocalToGlobal( &menuDisplayPt );
			oldValue = (*data)->value;
			theResult = PopUpMenuSelect( menu, menuDisplayPt.v, menuDisplayPt.h, oldValue );
			newValue = LoWord( theResult );
			if (newValue && newValue != oldValue)
			{
				(*data)->value = newValue;
				CheckMenuItem( menu, newValue, true );
				CheckMenuItem( menu, oldValue, false );
				answer |= blCellClickUpdate;
			}
		}
	}
	return answer;
}


