/*	XGMenuPop.cpp
 *
 *		This is the view which manages the popup menu lists
 */

/*  YAAF - Yet another application framework
 *  Copyright (C) 1997, 1998 William Edward Woody
 *  
 *  This library is free software; you can redistribute it
 *  and/or modify it under the terms of the GNU Library
 *  General Public License as published by the Free Software
 *  Foundation; either version 2 of the License, or any
 *  later version.
 *  
 *  This library is distributed in the hope that it will be
 *  useful, but WITHOUT ANY WARRANTY; without even the implied
 *  warranty of MERCHANTABIILITY or FITNESS FOR A PARTICULAR
 *  PURPOSE. See the GNU Library General Public License for
 *  more details.
 *  
 *  You should have received a copy of the GNU Library General
 *  Public License along with this library; if not, write to the
 *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 *  Boston, MA 02111-1307, USA.
 *  
 *  To contact the author, either e-mail me at woody@pandawave.com, 
 *	or write to
 *  
 *          William Edward Woody
 *          In Phase Consulting
 *          1545 Ard Eevin Avenue
 *          Glendale, CA 91202
 *
 *	Or visit us on the web at http://www.pandawave.com
 */

#include "XGMenuView.h"
#include <XDraw.h>
#include <XMenu.h>

/************************************************************************/
/*																		*/
/*	Globals																*/
/*																		*/
/************************************************************************/

static XGSViewInitRecord MenuInitRecord = {
	'****', 1, 0,
	0, 0, 0, 20,
	true, true, true, false,
	true, true, false
};

/************************************************************************/
/*																		*/
/*	Construction/Destruction											*/
/*																		*/
/************************************************************************/

/*	XGMenuPop::XGMenuPop
 *
 *		Create me
 */

XGMenuPop::XGMenuPop(XGMenu *m) : XGView(NULL,MenuInitRecord)
{
	fMenu = m;
	fLocation = -1;
}

/*	XGMenuPop::~XGMenuPop
 *
 *		Go away
 */

XGMenuPop::~XGMenuPop()
{
}

/************************************************************************/
/*																		*/
/*	Size preflight														*/
/*																		*/
/************************************************************************/

/*	XGMenuPop::GetPopSize
 *
 *		The drawing object I'm handed is already initialized. All I
 *	do is figure out how big my menu should be.
 *
 *		Dimensions:
 *
 *			| <-20-> MENUNAME <-5-> ACCEL <-5-> |
 */

Point XGMenuPop::GetPopSize(XGDraw &draw)
{
	Point size;
	int i,len;
	char buffer[256];
	int width;
	int x;
	XGSMenuItem im;
	
	/*
	 *	Find height 
	 */
	
	len = fMenu->GetLength();
	size.v = (draw.GetFontHeight()+2) * len;

	/*
	 *	Find width 
	 */
	
	width = 20;
	for (i = 0; i < len; i++) {
		
		fMenu->fMenuData.GetString(i,buffer);
		fMenu->fMenuData.GetExtra(i,(void *)&im);
		x = draw.StringWidthA(buffer) + 30;
		if (im.fAccelerator) {
			sprintf(buffer,"Meta+%c",(char)im.fAccelerator);
			x += draw.StringWidth(buffer);
		}
		if (width < x) width = x;
	}
	size.h = width;
	
	/*
	 *	Now bump for the border
	 */
	
	size.h += 6;
	size.v += 6;
	return size;
}

/************************************************************************/
/*																		*/
/*	Event Processing													*/
/*																		*/
/************************************************************************/

/*	XGMenuPop::DoDrawView
 *
 *		Draw the contents of this view
 */

void XGMenuPop::DoDrawView(Rect)
{
	Rect r;
	int i;
	XGDraw draw(this);
	draw.SetFont(XGFont::LoadFont(0));			// system font

	r = GetContentRect();	
	draw.Draw3DRect(r,KXGEBackground);
	draw.Draw3DRect(r,KXGEFrame);
	::InsetRect(&r,1,1);
	draw.Draw3DRect(r,KXGEOutset);
	::InsetRect(&r,1,1);

	for (i = 0; i < fMenu->GetLength(); i++) {
		DrawLine(draw,i,(i == fLocation));
	}
}

/*	XGMenuPop::DoMouseMove
 *
 *		Handle mouse move. I assume this is down
 */

void XGMenuPop::DoMouseMove(Point where,short)
{
	short h;
	XGDraw draw(this);
	draw.SetFont(XGFont::LoadFont(0));
	
	if (where.v < 3) {
		h = -1;
	} else {
		h = draw.GetFontHeight() + 2;
		h = (where.v - 3) / h;
	
		if ((h < 0) || (h >= fMenu->GetLength())) h = -1;
	}
	if (fLocation == h) return;
	
	/*
	 *	Redraw the two items
	 */
	
	if (fLocation != -1) DrawLine(draw,fLocation,false);
	if (h != -1) DrawLine(draw,h,true);
	fLocation = h;
}


/************************************************************************/
/*																		*/
/*	Low level															*/
/*																		*/
/************************************************************************/

/*	XGMenuPop::DrawLine
 *
 *		Draw the text line
 */

void XGMenuPop::DrawLine(XGDraw &draw, short line, bool hilite)
{
	Rect r;
	int h;
	XGSMenuItem im;
	char buffer[32];
	char title[256];
	
	r = GetContentRect();
	::InsetRect(&r,3,3);
	h = draw.GetFontHeight() + 2;
	r.top = line * h + 3;
	r.bottom = r.top + h;
	
	h = r.bottom - 1 - draw.GetFontDescent();
	
	/*
	 *	Draw the dsabled text line (if the line is disabled)
	 */

	fMenu->fMenuData.GetExtra(line,(void *)&im);
	fMenu->fMenuData.GetString(line,title);
	
	if (title[0] == 0) {
		Rect s;
		
		/*
		 *	Separator
		 */
		
		draw.Draw3DRect(r,KXGEBackground);
		s = r;
		s.top = (r.top + r.bottom) / 2;
		s.bottom = s.top + 1;
		draw.FillRect(s,KXGColorBtnShadow);
		s.top++;
		s.bottom++;
		draw.FillRect(s,KXGColorWhite);
		return;
	}
	
	if (!im.fEnabled) {
		draw.Draw3DRect(r,KXGEBackground);
		draw.SetForeColor(KXGColorBtnShadow);			// dim color
		
		if (im.fCheckmark) {
			char check;
			check = im.fCheckmark;
			
			if (check < ' ') {
				draw.MoveTo(5,h-3);
				draw.LineTo(7,h-1);
				draw.LineTo(11,h-9);
			} else {
				draw.MoveTo(5,h);
				draw.DrawString(&check,1);
			}
		}
	
		draw.MoveTo(20,h);
		draw.DrawStringA(title);
		
		if (im.fAccelerator) {
			sprintf(buffer,"Meta+%c",im.fAccelerator);
			draw.MoveTo(r.right - 5 - draw.StringWidth(buffer),h);
			draw.DrawString(buffer);
		}
		return;
	} else {
		draw.SetForeColor(KXGColorBlack);
	}
	
	/*
	 *	Draw the hilite
	 */
	
	if (hilite) {
		draw.FillRect(r,KXGColorBtnFace);
		draw.Draw3DRect(r,KXGEInset);
	} else {
		draw.Draw3DRect(r,KXGEBackground);
	}
	
	/*
	 *	Draw the line
	 */
	
		
	if (im.fCheckmark) {
		char check;
		check = im.fCheckmark;
		
		if (check < ' ') {
			draw.MoveTo(5,h-3);
			draw.LineTo(7,h-1);
			draw.LineTo(11,h-9);
		} else {
			draw.MoveTo(5,h);
			draw.DrawString(&check,1);
		}
	}
	
	draw.MoveTo(20,h);
	draw.DrawStringA(title);
	
	if (im.fAccelerator) {
		sprintf(buffer,"Meta+%c",(char)im.fAccelerator);
		draw.MoveTo(r.right - 5 - draw.StringWidth(buffer),h);
		draw.DrawString(buffer);
	}
}
