Return to Appendix B.

GENWIN.CPP
// Matt Streeter
// 2/27/00
// GENWIN.CPP
// Implementation of class TGenerationWindow; window class for displaying
// networks in a population by generation.
// Copyright Matt Streeter, 2000.  All rights reserved

#include "genwin.h"
#include <owl\scroller.h>

// The following four #defines determine, respectively, the left, right, top
// and bottom borders, in pixels, between the window edge and window contents.
#define WINDOW_LBORDER 7
#define WINDOW_RBORDER 10
#define WINDOW_TBORDER 10
#define WINDOW_BBORDER 45

// The amount of horizontal space, in pixels, that is allocated to display
// the generation numbers.
#define LABEL_HSPACE	  23

// The following two #defines determine the face and height of the font
// used to display the generation numbers.
#define LABEL_FONT_FACE "Times New Roman"
#define LABEL_FONT_HEIGHT 15

// Vertical border, in pixels, one generation and the next.
#define GENERATION_VBORDER 10

// The maximum depth to which the links of a family tree will be displayed
// when a network is selected.
#define DEFAULT_MAX_TREE_DEPTH 6

DEFINE_RESPONSE_TABLE1(TGenerationWindow, THeredityWindow)
  EV_WM_SIZE,
  EV_WM_LBUTTONDOWN,
  EV_WM_LBUTTONDBLCLK,
END_RESPONSE_TABLE;

TColor TGenerationWindow::mLabelColor(255,255,255);

TGenerationWindow::TGenerationWindow(TWindow *pParent,char *pTitle,
	TGeneration *pGenerationList,Network *pNetwork,double dMaxWeight,
	Parameter *pParam):
	THeredityWindow(pParent,pTitle,pGenerationList,pNetwork,dMaxWeight,pParam)
{
	Attr.Style|=WS_VISIBLE|WS_OVERLAPPEDWINDOW|WS_VSCROLL;
	// tbd: account correctly for parent coords
	Attr.X=50+(pParent?pParent->Attr.X+3:0);
	Attr.Y=200+(pParent?pParent->Attr.Y+25:0);
	Attr.W=400;
	Attr.H=275;

	Scroller = new TScroller(this,1,1,100,100);

	miMaxTreeDepth=DEFAULT_MAX_TREE_DEPTH;
}

void TGenerationWindow::Paint(TDC& dc, bool, TRect&)
{
int n;
int iXCursor,iYCursor,iNetworkRectsDrawn;
TGeneration *pCurGeneration;
TRect DrawRect;
int iGeneration;

	GetClientRect(DrawRect);

	DrawRect.left+=WINDOW_LBORDER+LABEL_HSPACE;
	DrawRect.top+=WINDOW_TBORDER;
	DrawRect.right-=WINDOW_RBORDER;
	DrawRect.bottom-=WINDOW_BBORDER;

	if(DrawRect.bottom<DrawRect.top || DrawRect.right<DrawRect.left)
		return;

	if(mpNetworkRects)
		delete(mpNetworkRects);

	miNetworkRects=0;
	pCurGeneration=mpGenerationList;
	while(pCurGeneration)
	{
		miNetworkRects+=pCurGeneration->iSurvivors;
		pCurGeneration=pCurGeneration->pNext;
	}

   // prevent allocation of > 64K chunk if running in 16-bit mode
	if((sizeof(short)==sizeof(int)) &&
		(long)miNetworkRects*(long)sizeof(TNetworkRect)>65000L)
	{
		return;
	}

	mpNetworkRects=new TNetworkRect[miNetworkRects];
	iNetworkRectsDrawn=0;

	iYCursor=DrawRect.top;
	TBrush BoxBrush(mBoxColor);

	TFont LabelFont(LABEL_FONT_FACE,LABEL_FONT_HEIGHT);
	dc.SelectObject(LabelFont);
	dc.SetBkColor(mBackgroundColor);
	dc.SetTextColor(mLabelColor);

	pCurGeneration=mpGenerationList;
	iGeneration=0;
	while(pCurGeneration)
	{
		byte bIsVisible=0;
		if(Scroller->IsVisibleRect(DrawRect.left/Scroller->XUnit,
			iYCursor/Scroller->YUnit,
			(mMatrix.GetWidth()+1)/Scroller->XUnit,
			(mMatrix.GetHeight()+1)/Scroller->YUnit))
		{
			bIsVisible=1;
		}

		if(bIsVisible)
		{
			// draw current generation's label
			char pLabel[200];
			itoa(iGeneration,pLabel,10);
			TSize Size=dc.GetTextExtent(pLabel,strlen(pLabel));
			TPoint LabelPos(DrawRect.left-LABEL_HSPACE,
				iYCursor+(mMatrix.GetHeight()-Size.cy)/2);
			dc.TextOut(LabelPos,pLabel,strlen(pLabel));
		}

		// draw current generation networks
		iXCursor=DrawRect.left;
		for(n=0;n<pCurGeneration->iSurvivors;n++)
		{
			mpNetworkRects[iNetworkRectsDrawn].x=iXCursor+1;
			mpNetworkRects[iNetworkRectsDrawn].y=iYCursor+1;
			mpNetworkRects[iNetworkRectsDrawn].pChromosome
				=&(pCurGeneration->pSurvivors[n]);
			iNetworkRectsDrawn++;

			if(bIsVisible)
			{
				dc.FrameRect(iXCursor,iYCursor,iXCursor+mMatrix.GetWidth()+1,
					iYCursor+mMatrix.GetHeight()+1,BoxBrush);
				// draw weight matrices
				mMatrix.Paint(dc,iXCursor,iYCursor,
					&(pCurGeneration->pSurvivors[n]));
			}

			iXCursor+=mMatrix.GetWidth()+1;
		}

		pCurGeneration=pCurGeneration->pNext;
		iYCursor+=mMatrix.GetHeight()+2+GENERATION_VBORDER;
		iGeneration++;
	}

	if(miSelectedNetwork!=-1)
	{
		DrawHighlight(miSelectedNetwork,mSelectedHighlightColor);
		DrawParentLinks(miSelectedNetwork,0);
	}

	// set vertical scroll bar range
	long lYRange=iYCursor-DrawRect.top-(DrawRect.bottom-DrawRect.top+1);
	if(lYRange<0)
		lYRange=0;
	Scroller->SetRange(100,lYRange);
}

void TGenerationWindow::EvLButtonDown(uint, TPoint& point)
{
int iNetwork;

	iNetwork=FindNetworkRect(point);
	if(iNetwork==-1)
		return;

	if(iNetwork==miSelectedNetwork)
	{
		DrawHighlight(iNetwork,mBoxColor);
		DrawParentLinks(iNetwork,1);
		miSelectedNetwork=-1;
		return;
	}

	if(miSelectedNetwork!=-1)
	{
		DrawHighlight(miSelectedNetwork,mBoxColor);
		DrawParentLinks(miSelectedNetwork,1);
	}
	DrawHighlight(iNetwork,mSelectedHighlightColor);
	DrawParentLinks(iNetwork,0);
	miSelectedNetwork=iNetwork;
}

void TGenerationWindow::EvLButtonDblClk(uint, TPoint& point)
{
int iNetwork;

	iNetwork=FindNetworkRect(point);
	if(iNetwork==-1)
		return;

	DrawHighlight(iNetwork,mSelectedHighlightColor);
	DrawParentLinks(iNetwork,0);
	miSelectedNetwork=iNetwork;

	CmEditNetwork();
}

void TGenerationWindow::DrawParentLinks(int iNetwork,byte bErase,int iDepth)
{
	if(iNetwork==-1)
		return;

	if(iDepth>=miMaxTreeDepth)
		return;

	if(mpNetworkRects[iNetwork].pChromosome->miGeneration==0)
		return;

	int iWeightParent1=FindNetworkRect(
		mpNetworkRects[iNetwork].pChromosome->miGeneration-1,
		mpNetworkRects[iNetwork].pChromosome->miWeightParent1);
	int iWeightParent2=FindNetworkRect(
		mpNetworkRects[iNetwork].pChromosome->miGeneration-1,
		mpNetworkRects[iNetwork].pChromosome->miWeightParent2);

	// tbd: draw links
	TClientDC dc(*this);
	TPen HighlightPen(mParentHighlightColor,1);
	TPen BoxPen(mBoxColor,1);
	TPen BackgroundPen(mBackgroundColor,1);
	if(bErase)
		dc.SelectObject(BackgroundPen);


	if(iWeightParent1!=-1)
	{
		if(!bErase)
		{
			if(mpNetworkRects[iNetwork].pChromosome->miWeightParent2!=-1)
				dc.SelectObject(HighlightPen);
			else
				dc.SelectObject(BoxPen);
		}

		dc.MoveTo(mpNetworkRects[iNetwork].x-X_SCROLL_OFFSET-1+mMatrix.GetWidth()/2,
			mpNetworkRects[iNetwork].y-Y_SCROLL_OFFSET-2);
		dc.LineTo(
			mpNetworkRects[iWeightParent1].x-X_SCROLL_OFFSET-1+mMatrix.GetWidth()/2,
			mpNetworkRects[iWeightParent1].y-Y_SCROLL_OFFSET+mMatrix.GetHeight()+1);

		DrawHighlight(iWeightParent1,bErase?mBoxColor:mParentHighlightColor);
	}

	if(iWeightParent2!=-1)
	{
		if(!bErase)
			dc.SelectObject(HighlightPen);
		dc.MoveTo(mpNetworkRects[iNetwork].x-X_SCROLL_OFFSET-1
			+mMatrix.GetWidth()/2,mpNetworkRects[iNetwork].y-Y_SCROLL_OFFSET-2);
		dc.LineTo(
			mpNetworkRects[iWeightParent2].x-X_SCROLL_OFFSET-1
				+mMatrix.GetWidth()/2,
				mpNetworkRects[iWeightParent2].y
				-Y_SCROLL_OFFSET+mMatrix.GetHeight()+1);
		DrawHighlight(iWeightParent2,bErase?mBoxColor:mParentHighlightColor);
	}

	DrawParentLinks(iWeightParent1,bErase,iDepth+1);
	DrawParentLinks(iWeightParent2,bErase,iDepth+1);
}

void TGenerationWindow::EvSize(UINT SizeType, TSize& Size)
{
	TWindow::EvSize(SizeType, Size);
	if(SizeType != SIZEICONIC)
	{
		Invalidate(FALSE);
	}
}

Return to Appendix B.