/*	XGMenuView.cpp
 *
 *		How to handle the XGMenuBar view
 */

/*  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>
#include <XError.h>
#include <XWindow.h>
#include <XCursorUtil.h>

/************************************************************************/
/*																		*/
/*	Constants															*/
/*																		*/
/************************************************************************/

/*	MenuInitRecord
 *
 *		The initialization record for my menu bar
 */

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

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

/*	XGMenuView::XGMenuView
 *
 *		Create me
 */

XGMenuView::XGMenuView(XGFocus *f, XGMenuBar *bar) : XGView(NULL,MenuInitRecord)
{
	fFocus = f;
	fMenuBar = bar;
}

/*	XGMenuView::~XGMenuView
 *
 *		Go away
 */

XGMenuView::~XGMenuView()
{
}

/************************************************************************/
/*																		*/
/*	Drawing																*/
/*																		*/
/************************************************************************/

/*	XGMenuView::DoDrawView
 *
 *		Handle drawing
 */

void XGMenuView::DoDrawView(Rect)
{
	Rect r;
	XGDraw draw(this);
	int i,len;
	char buffer[256];
	int x;

	/*
	 *	Set up drawing
	 */

	draw.SetFont(XGFont::LoadFont(0));			// set to system font

	/*
	 *	Now paint the menu border
	 */

	r = GetContentRect();
	draw.Draw3DRect(r,KXGEBackground);

	/*
	 *	Run the widths
	 */
	
	len = fMenuBar->GetLength();
	for (i = 0; i < len; i++) {
		fMenuBar->GetMenuName(i,buffer);
		fWidth[i] = 8 + draw.StringWidthA(buffer);
	}
	
	/*
	 *	Now draw the contents
	 */
	
	x = 7;
	for (i = 0; i < len; i++) {
		draw.MoveTo(x,14);
		fMenuBar->GetMenuName(i,buffer);
		draw.DrawStringA(buffer);
		
		x += fWidth[i];
	}
	
	/*
	 *	And the border
	 */
	
	r.bottom--;
	draw.Draw3DRect(r,KXGEOutset);
	r.top = r.bottom;
	r.bottom++;
	draw.FillRect(r,KXGColorBlack);		// border line
}

/*	XGMenuView::DoMouseDown
 *
 *		Where am I?
 */

bool XGMenuView::DoMouseDown(Point where, short)
{
	int i,len;
	Rect r;
	
	len = fMenuBar->GetLength();
	
	for (i = 0; i < len; i++) {
		r = CalcLocation(i);
		if (PtInRect(where,&r)) break;
	}
	if (i >= len) return false;
	
	/*
	 *	Mouse is in my menu bar. Set up drawing
	 */
	
	XGDraw draw(this);
	r = CalcLocation(i);
	draw.Draw3DRect(r,KXGEInset);
	fIndex = i;
	
	/*
	 *	Pop down the menu
	 */
	
	fPop = NULL;
	PopDownMenu(fIndex);	
	return true;
}

/*	XGMenuView::DoMouseMove
 *
 *		Handle mouse movement
 */

void XGMenuView::DoMouseMove(Point where, short flags)
{
	int i,len;
	Rect r;
	char buffer[256];

	if (flags & KCapturedMouse) {
		/*
		 *	Handle tracking inside popup menu
		 */
		
		if (TrackPopMenu(where)) return;
		if (fPop && where.v > 17) return;		// ignore if outside all
		
		/*
		 *	Handle dragging across menus
		 */
		
		len = fMenuBar->GetLength();
		for (i = 0; i < len; i++) {
			r = CalcLocation(i);
			if (PtInRect(where,&r)) break;
		}
		if (i >= len) i = -1;
		if (i == fIndex) return;
		
		/*
		 *	Time to update
		 */
		
		XGDraw draw(this);
		draw.SetFont(XGFont::LoadFont(0));
		
		if (i != -1) {
			r = CalcLocation(i);
			draw.Draw3DRect(r,KXGEInset);
		}
		if (fIndex != -1) {
			r = CalcLocation(fIndex);
			draw.Draw3DRect(r,KXGEBackground);
			draw.MoveTo(r.left + 4, 14);
			fMenuBar->GetMenuName(fIndex,buffer);
			draw.DrawStringA(buffer);
		}
		
		fIndex = i;
		PopDownMenu(fIndex);
	} else {
		::SetCursorID(KNormalCursor);
	}
}

/*	XGMenuView::DoMouseUp
 *
 *		Handle mouse up
 */

void XGMenuView::DoMouseUp(Point where, short flags)
{
	Rect r;
	char buffer[256];
	short cmdID;
	short loc;
	extern short GMenuCommand;
	
	if (!(flags & KCapturedMouse)) return;
	if (fIndex == -1) return;
	
	/*
	 *	Get the command
	 */
	
	cmdID = -1;
	if (fPop) {
		loc = fView->GetLocation();
		if (loc >= 0) {
			cmdID = fView->GetMenu()->GetItemID(loc);
			if (cmdID <= 0) cmdID = -1;
		}
	}
	
	/*
	 *	Get rid of popup (if any)
	 */
	
	PopDownMenu(-1);
	
	/*
	 *	Now redraw the menu bar to normal
	 */
	
	XGDraw draw(this);
	draw.SetFont(XGFont::LoadFont(0));
	
	r = CalcLocation(fIndex);
	draw.Draw3DRect(r,KXGEBackground);
	draw.MoveTo(r.left + 4, 14);
	fMenuBar->GetMenuName(fIndex,buffer);
	draw.DrawStringA(buffer);
	
	/*
	 *	Dispatch the event
	 */
	
	if (cmdID > 0) {
		GMenuCommand = cmdID;
	}
}

/************************************************************************/
/*																		*/
/*	Internal Support													*/
/*																		*/
/************************************************************************/

/*	XGMenuView::CalcLocation
 *
 *		Calculate the location of this menu item
 */

Rect XGMenuView::CalcLocation(short index)
{
	Rect r;
	int i;
	
	r = GetContentRect();
	r.top++;
	r.bottom -= 2;
	r.left = 3;
	
	for (i = 0; i < index; i++) {
		r.left += fWidth[i];
	}
	r.right = r.left + fWidth[index];
	
	return r;
}

/*	XGMenuView::PopDownMenu
 *
 *		Pop down the menu from the menu bar
 */

void XGMenuView::PopDownMenu(short index)
{
	Rect r;
	Point size;
	XGDraw draw(this);
	draw.SetFont(XGFont::LoadFont(0));
	
	/*
	 *	Is there already a popdown window?
	 */
	
	if (fPop) {
		delete fPop;
		fPop = NULL;
	}
	
	/*
	 *	Skip out if that's it
	 */
	
	if (index == -1) return;
	
	/*
	 *	Create the submenu
	 */
	
	fView = new XGMenuPop(fMenuBar->GetMenu(index));
	if (fView == NULL) return;
	
	size = fView->GetPopSize(draw);
	r = CalcLocation(index);
	
	r.top = r.bottom + 1;
	r.bottom = r.top + size.v;
	r.right = r.left + size.h;
	
	/*
	 *	Now pop up the window
	 */
	
	fPop = new XGPopWindow(this,r,fView);
}

/*	XGMenuView::TrackPopMenu
 *
 *		Track inside the popup menu. If this is not inside the
 *	popup menu, this returns false
 */

bool XGMenuView::TrackPopMenu(Point where)
{
	Rect r;
	
	if (fPop == NULL) return false;
	r = fPop->GetLocation();
	if (PtInRect(where,&r)) {
		/*
		 *	Inside popup menu. Convert to local coordinates
		 *	and send to view
		 */
		
		where.h -= r.left;
		where.v -= r.top;
		fView->DoMouseMove(where,0);
		return true;
	}
	
	where.h = -1;
	where.v = -1;				// kludge to unselect menu contents
	fView->DoMouseMove(where,0);
	return false;
}
