// Matt Streeter
// 2/27/00
// TREE.CPP
// Implementation of class TFamilyTreeWindow; window class for display of
// network's "family tree".
// Copyright Matt Streeter, 2000. All rights reserved
#include "tree.h"
#include "matrix.h"
DEFINE_RESPONSE_TABLE1(TFamilyTreeWindow, THeredityWindow)
EV_WM_SIZE,
END_RESPONSE_TABLE;
// The following four #defines determine, in pixels, the left, right, top,
// and bottom borders, respectively, between window contents and the window
// edge.
#define WINDOW_LBORDER 10
#define WINDOW_RBORDER 10
#define WINDOW_TBORDER 10
#define WINDOW_BBORDER 10
// Sets the amount of vertical spacing, in pixels, between successive
// generations in the family tree.
#define GENERATION_VSPACING 20
TFamilyTreeWindow::TFamilyTreeWindow(TWindow *pParent,char *pTitle,
TGeneration *pGenerationList,Chromosome *pSelectedNetwork,
Network *pNetwork,double dMaxWeight,Parameter *pParam):
THeredityWindow(pParent,pTitle,pGenerationList,pNetwork,dMaxWeight,pParam)
{
Attr.Style|=WS_VISIBLE|WS_OVERLAPPEDWINDOW;
// tbd: account correctly for parent coords
Attr.X=475+(pParent?pParent->Attr.X+3:0);
Attr.Y=200+(pParent?pParent->Attr.Y+25:0);
Attr.W=275;
Attr.H=325;
mpSelectedNetwork=pSelectedNetwork;
}
void TFamilyTreeWindow::Paint(TDC& dc, bool, TRect&)
{
TRect DrawRect;
GetClientRect(DrawRect);
DrawRect.left+=WINDOW_LBORDER;
DrawRect.top+=WINDOW_TBORDER;
DrawRect.right-=WINDOW_RBORDER;
DrawRect.bottom-=WINDOW_BBORDER;
if(DrawRect.bottom<DrawRect.top || DrawRect.right<DrawRect.left)
return;
DrawTree(dc,DrawRect);
}
void TFamilyTreeWindow::EvSize(UINT SizeType, TSize& Size)
{
TWindow::EvSize(SizeType, Size);
if(SizeType != SIZEICONIC)
{
Invalidate(TRUE);
}
}
int TFamilyTreeWindow::DrawTree(TDC& dc,TRect& DrawRect)
{
int x=DrawRect.left+(DrawRect.right-DrawRect.left)/2;
int iYCursor=DrawRect.bottom;
int iWidth=DrawRect.right-DrawRect.left+1;
for(int iDepth=0;;iDepth++)
{
if(iYCursor+mMatrix.GetHeight()+1<DrawRect.top)
break;
// determine matrix size for this layer
long lNodes=pow(2,iDepth);
while((long)iWidth<lNodes*mMatrix.GetWidth())
{
if(!mMatrix.GetPixelsPerSquare())
break;
mMatrix.SetPixelsPerSquare(mMatrix.GetPixelsPerSquare()-1);
}
if(!iDepth)
iYCursor=DrawRect.bottom-mMatrix.GetHeight()+1;
else
iYCursor-=mMatrix.GetHeight()+1+GENERATION_VSPACING;
DrawTreeLayer(dc,mpSelectedNetwork,x,iYCursor,iWidth,iDepth);
}
mMatrix.SetPixelsPerSquare(BASE_PIXELS_PER_WEIGHT);
return(0);
}
int TFamilyTreeWindow::DrawTreeLayer(TDC& dc,Chromosome *pChromosome,
int x,int y,int iWidth,int iDrawDepth,int iCurDepth)
{
Chromosome *pParent1,*pParent2;
if(iCurDepth>iDrawDepth)
return(0);
pParent1=FindNetwork(pChromosome->miGeneration-1,
pChromosome->miWeightParent1);
pParent2=FindNetwork(pChromosome->miGeneration-1,
pChromosome->miWeightParent2);
if(pChromosome->miGeneration>0 && pChromosome->miWeightParent2==-1)
{
if(!pParent1)
return(-1); // internal error
else
return(DrawTreeLayer(dc,pParent1,x,y,iWidth,iDrawDepth,iCurDepth));
}
TBrush BoxBrush(mBoxColor);
if(iDrawDepth==iCurDepth)
{
dc.FrameRect(x-mMatrix.GetWidth()/2-1,y,x+mMatrix.GetWidth()/2+1,
y+mMatrix.GetHeight()+1,BoxBrush);
mMatrix.Paint(dc,x-mMatrix.GetWidth()/2,y+1,pChromosome);
}
// tbd: stop drawing if outside window
Chromosome *pLeftParent,*pRightParent;
if(!pParent1)
{
pLeftParent=pParent2;
pRightParent=0;
}
else if(!pParent2)
{
pLeftParent=pParent1;
pRightParent=0;
}
else
{
if(pChromosome->miWeightParent1<pChromosome->miWeightParent2)
{
pLeftParent=pParent1;
pRightParent=pParent2;
}
else
{
pLeftParent=pParent2;
pRightParent=pParent1;
}
}
TPen HighlightPen(mParentHighlightColor,1);
if(iDrawDepth==iCurDepth)
dc.SelectObject(HighlightPen);
if(pLeftParent)
{
if(iDrawDepth==iCurDepth)
{
dc.MoveTo(x,y-1);
dc.LineTo(x-iWidth/4,y-GENERATION_VSPACING);
}
DrawTreeLayer(dc,pLeftParent,x-iWidth/4,y,iWidth/2,iDrawDepth,
iCurDepth+1);
}
if(pRightParent)
{
if(iDrawDepth==iCurDepth)
{
dc.MoveTo(x,y-1);
dc.LineTo(x+iWidth/4,y-GENERATION_VSPACING);
}
DrawTreeLayer(dc,pRightParent,x+iWidth/4, y,iWidth/2,iDrawDepth,
iCurDepth+1);
}
return(0);
}
Chromosome *TFamilyTreeWindow::FindNetwork(int iGeneration,int iIndex)
{
TGeneration *pCurGeneration;
int n;
if(iGeneration<0)
return(0);
pCurGeneration=mpGenerationList;
while(pCurGeneration)
{
for(n=0;n<pCurGeneration->iSurvivors;n++)
{
if(pCurGeneration->pSurvivors[n].miGeneration==iGeneration &&
pCurGeneration->pSurvivors[n].miIndex==iIndex)
return(&(pCurGeneration->pSurvivors[n]));
}
pCurGeneration=pCurGeneration->pNext;
}
return(0);
}
void GetFamilyTreeTitle(char *pTitle,Chromosome *pChromosome)
{
strcpy(pTitle,"Family Tree - ");
pChromosome->GetName(&(pTitle[strlen(pTitle)]));
}