package edu.byu.cs.roots.opg.chart.multisheet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Rectangle;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.HashMap;
import edu.byu.cs.roots.opg.chart.ChartMaker;
import edu.byu.cs.roots.opg.chart.cmds.DrawCmdEndChartArrow;
import edu.byu.cs.roots.opg.chart.cmds.DrawCmdMoveTo;
import edu.byu.cs.roots.opg.chart.cmds.DrawCmdPageLink;
import edu.byu.cs.roots.opg.chart.cmds.DrawCmdRelLineTo;
import edu.byu.cs.roots.opg.chart.cmds.DrawCmdSetFont;
import edu.byu.cs.roots.opg.chart.cmds.DrawCmdStartChartArrow;
import edu.byu.cs.roots.opg.chart.preset.templates.AncesBoxParent;
import edu.byu.cs.roots.opg.chart.preset.templates.ChartMargins;
import edu.byu.cs.roots.opg.chart.preset.templates.PresetChartOptions;
import edu.byu.cs.roots.opg.chart.preset.templates.StylingBox;
import edu.byu.cs.roots.opg.chart.preset.templates.StylingBoxScheme;
import edu.byu.cs.roots.opg.chart.preset.templates.StylingBox.TextDirection;
import edu.byu.cs.roots.opg.model.Gender;
import edu.byu.cs.roots.opg.model.Individual;
import edu.byu.cs.roots.opg.model.OpgOptions;
import edu.byu.cs.roots.opg.model.OpgSession;
import edu.byu.cs.roots.opg.model.Single;
import edu.byu.cs.roots.opg.chart.multisheet.MultisheetChartMaker;
public class AncesBox extends AncesBoxParent
{
private static final long serialVersionUID = 1L;
public AncesBox(Individual indi) {
super(indi);
}
/**
* Recursively calculates the minimum coordinates for this indivdual
* (and its subtree(s)) based on the minimum font size.
* Steps:
* 1) Create two arrays for each generation to store the upper and lower bounds for each generation
* 2)
*
* @param options - chart options that contain the minimum font size
* @param curGen - current generation of Individual in this AncesBox (usually starts as 0)
* @param duplicateMap
*/
@Override
public void calcCoords(PresetChartOptions options, ChartMaker maker, int curGen, StylingBoxScheme stylingBoxes, OpgSession session)
{
OpgOptions opgOptions = session.getOpgOptions();
getIndi().isInTree = true;
session.addIndiToTree(getIndi());
//----------------
int maxGen;
if(maker.equals(session.getBaseMaker()) && options.getAncesGens() == 5)
maxGen = options.getAncesGens()-1;
else
maxGen = options.getAncesGens();
double boxHeight = styleBox.boxHeight;
boxWidth = styleBox.getBoxWidth();
if (styleBox.weddingLayout.lines.size() > 0){
if((getIndi().gender == Gender.MALE && styleBox.weddingDisplayType == StylingBox.WeddingPositions.HUSBAND_POSTFIX) ||
(getIndi().gender == Gender.FEMALE && styleBox.weddingDisplayType == StylingBox.WeddingPositions.WIFE_POSTFIX) ||
styleBox.weddingDisplayType == StylingBox.WeddingPositions.BOTH_POSTFIX){
double increaseVariable = 0.0;
for (int i = 0; i < styleBox.weddingLayout.lines.size(); i++){
int listPosition = i + styleBox.layout.lines.size();
if (styleBox.textPositions.size() == 0)
styleBox.textPositions.add(0.0);
if (styleBox.textPositions.size() == 1)
increaseVariable += styleBox.textPositions.get(0);
if (listPosition >= styleBox.textPositions.size())
increaseVariable += (styleBox.textPositions.get(styleBox.textPositions.size() - 1) - styleBox.textPositions.get(styleBox.textPositions.size() - 2));
else
increaseVariable += (styleBox.textPositions.get(listPosition) - styleBox.textPositions.get(listPosition - 1));
}
if(styleBox.direction == StylingBox.TextDirection.NORMAL || styleBox.direction == TextDirection.ONE_EIGHTY)
boxHeight += increaseVariable;
else
boxWidth += increaseVariable;
}
}
double vertSeperation = 0; //: calculate vertical seperation
if (curGen > maxGen)
return;
setUpperBounds(new ArrayList<Double>(maxGen - curGen));
setLowerBounds(new ArrayList<Double>(maxGen - curGen));
intersectUpperHeight = 0.0;
intersectLowerHeight = 0.0;
//calculate first element of upper bounds array for tight fit
getUpperBounds().add(new Double(boxHeight/2.0 + styleBox.paddingAmount));
//calculate first element of lower bounds array for tight fit
getLowerBounds().add(new Double( -(boxHeight/2.0 + vertSeperation + styleBox.paddingAmount)));
upperBoxBound = boxHeight/2.0;
lowerBoxBound = -upperBoxBound;
upperSubTreeHeight = boxHeight/2.0 + styleBox.paddingAmount;
lowerSubTreeHeight = -upperSubTreeHeight;
int maxGensOfSubTree = 0;
int offset = curGen + 1;
HashMap<String, Single<String>> duplicateLabels = opgOptions.getDuplicateLabels();
HashMap<String, String> duplicates = opgOptions.getDuplicateMap();
if (curGen < maxGen)
{
if ((father != null) && ((!opgOptions.isCollapsed(getIndi()) && !duplicates.containsKey(getIndi().id)) || options.getRoot() == getIndi()))
{
//This is where you add the specific duplicate label
if (duplicates.containsKey(father.getIndi().id))
{
//ChartMaker addedMaker = session.addMaker(ChartType.MULTISHEET, father.getIndi(), offset);
((MultisheetChartMaker) maker).addMakerToAddList(father.getIndi(), offset);
duplicateLabels.put(father.getIndi().id, father.getIndi().pageId);
}
father.calcCoords(options, maker, curGen+1, stylingBoxes, session);
//keep track of the maximum number of generations in each subTree
if (father.maxGensOfTree > maxGensOfSubTree)
maxGensOfSubTree = father.maxGensOfTree;
}
if ((mother != null) && ((!opgOptions.isCollapsed(getIndi()) && !duplicates.containsKey(getIndi().id)) || options.getRoot() == getIndi()))
{
//This is where you add the specific duplicate label
if (duplicates.containsKey(mother.getIndi().id))
{
//ChartMaker addedMaker = session.addMaker(ChartType.MULTISHEET, father.getIndi(), offset);
((MultisheetChartMaker) maker).addMakerToAddList(mother.getIndi(), offset);
duplicateLabels.put(mother.getIndi().id, mother.getIndi().pageId);
}
mother.calcCoords(options, maker, curGen+1, stylingBoxes, session);
//keep track of the maximum number of generations in each subTree
if (mother.maxGensOfTree > maxGensOfSubTree)
maxGensOfSubTree = mother.maxGensOfTree;
}
}
if (options.getArrowStyle() == PresetChartOptions.EndLineArrowStyle.PARENTS){
//Create the new Page for the father, and store the page number
if (curGen == maxGen &&//session.getBaseOptions().getAncesGens() &&
(getIndi().father != null))
{
// MultisheetChartMaker temp =
// (MultisheetChartMaker) session.addMaker(ChartType.MULTISHEET, getIndi().father, offset);
((MultisheetChartMaker) maker).addMakerToAddList(getIndi().father, offset);
}
//Create the new Page for the mother, and store the page number
if (curGen == maxGen &&//session.getBaseOptions().getAncesGens() &&
(getIndi().mother != null))
{
// MultisheetChartMaker temp =
// (MultisheetChartMaker)session.addMaker(ChartType.MULTISHEET, getIndi().mother, offset);
((MultisheetChartMaker) maker).addMakerToAddList(getIndi().mother, offset);
}
}
//If new page style is 'self', create the new page with this box as the root. Store the page number
else if (options.getArrowStyle() == PresetChartOptions.EndLineArrowStyle.SELF){
if (curGen == maxGen &&//session.getBaseOptions().getAncesGens() &&
(getIndi().father != null || getIndi().mother != null))
{
offset = offset - 1;
// MultisheetChartMaker temp =
// (MultisheetChartMaker)session.addMaker(ChartType.MULTISHEET, getIndi(), offset);
((MultisheetChartMaker) maker).addMakerToAddList(getIndi(), offset);
}
}
//set the maximun number of generations in this tree
maxGensOfTree = maxGensOfSubTree + 1;
//Tight fit (jigsaw puzzle like) intersection
//calculate the distances between each of the parents by intersecting their subtrees
//Extends the upper and lower box trees to include this intruding box
if (styleBox.isIntruding && options.isAllowIntrusion()){
double remainingIntrudeWidth = styleBox.intrudeWidth;
for (int i = gen; remainingIntrudeWidth > 0; i++)
{
if (getLowerBounds().size() > (i - gen)){
if (getLowerBounds().get(i - gen) > (getLowerBounds().get(0)))
getLowerBounds().set(i - gen, getLowerBounds().get(0));
}
else
getLowerBounds().add(getLowerBounds().get(0));
if (getUpperBounds().size() > (i - gen)){
if (getUpperBounds().get(i - gen) < (getUpperBounds().get(0)))
getUpperBounds().set(i-gen, getUpperBounds().get(0));
}
else
getUpperBounds().add(getUpperBounds().get(0));
remainingIntrudeWidth -= (stylingBoxes.getAncesStyle(i).getBoxWidth() + stylingBoxes.getAncesStyle(i).getRelativeOffset());
}
}else if(opgOptions.getDuplicateMap().containsKey(getIndi().id) && options.getRoot() != getIndi()){
double remainingIntrudeWidth = styleBox.getBoxWidth() + styleBox.endLineArrowShaftLength + styleBox.endLineArrowHeadLength;
for (int i = gen; remainingIntrudeWidth > 0; i++)
{
if (getLowerBounds().size() > (i - gen)){
if (getLowerBounds().get(i - gen) > (getLowerBounds().get(0)))
getLowerBounds().set(i - gen, getLowerBounds().get(0));
}
else
getLowerBounds().add(getLowerBounds().get(0));
if (getUpperBounds().size() > (i - gen)){
if (getUpperBounds().get(i - gen) < (getUpperBounds().get(0)))
getUpperBounds().set(i-gen, getUpperBounds().get(0));
}
else
getUpperBounds().add(getUpperBounds().get(0));
remainingIntrudeWidth -= (stylingBoxes.getAncesStyle(i).getBoxWidth() + stylingBoxes.getAncesStyle(i).getRelativeOffset());
}
}
if ((father != null || mother != null) && ((!opgOptions.isCollapsed(getIndi()) && !duplicates.containsKey(getIndi().id)) || options.getRoot() == getIndi()) && curGen < maxGen)
{
//if no father is visible
if ((father == null))
{
//add gap onto bottom of lower parent to ensure that different sets of grandparents are spaced father than spouses
mother.getLowerBounds().set(0, mother.getLowerBounds().get(0) - vertSeperation);
motherVOffset = ((styleBox.isIntruding && options.isAllowIntrusion())?(getLowerBounds().get(0) - mother.getUpperBounds().get(0)):-3);////insert vertical offset here
if(styleBox.isIntruding && options.isAllowIntrusion()){
double lowerLine = motherVOffset - getLowerBounds().get(0);
double motherUpperBound = mother.getUpperBounds().get(0) + mother.intersectUpperHeight;
if(((lowerLine) + (motherUpperBound))>0)
motherVOffset = (-(motherUpperBound - getLowerBounds().get(0)));
}
//calculate rest of upper and lower bounds array
for (int i = 0; i < mother.getUpperBounds().size(); ++i)
{
if (getUpperBounds().size() > i + 1)
getUpperBounds().set(i+1, Math.max(new Double(motherVOffset + mother.getUpperBounds().get(i)), getUpperBounds().get(0)));
else
getUpperBounds().add(new Double(motherVOffset + mother.getUpperBounds().get(i)));
}
for (int i = 0; i < mother.getLowerBounds().size(); ++i)
{
if (getLowerBounds().size() > i + 1)
getLowerBounds().set(i+1, new Double(motherVOffset + mother.getLowerBounds().get(i)));
else
getLowerBounds().add(new Double(motherVOffset + mother.getLowerBounds().get(i)));
}
upperSubTreeHeight = Math.max(upperSubTreeHeight, motherVOffset + mother.upperSubTreeHeight);
lowerSubTreeHeight = Math.min(lowerSubTreeHeight, motherVOffset + mother.lowerSubTreeHeight);
}
//if no mother is visible
else if ((mother == null))
{
//add gap onto bottom of lower parent to ensure that different sets of grandparents are spaced father than spouses
father.getLowerBounds().set(0, father.getLowerBounds().get(0) - vertSeperation);
fatherVOffset = ((styleBox.isIntruding && options.isAllowIntrusion())?(getUpperBounds().get(0) - father.getLowerBounds().get(0)):3);////insert vertical offset here
if(styleBox.isIntruding && options.isAllowIntrusion()){
double upperLine = fatherVOffset - getUpperBounds().get(0);
double fatherLowerBound = (father.getLowerBounds().get(0) + father.intersectLowerHeight);
if(((upperLine) + (fatherLowerBound))<0)
fatherVOffset = (-(fatherLowerBound - getUpperBounds().get(0)));
}
//calculate rest of upper and lower bounds array
for (int i = 0; i < father.getUpperBounds().size(); ++i)
{
if (getUpperBounds().size() > i + 1)
getUpperBounds().set(i+1, new Double(fatherVOffset + father.getUpperBounds().get(i)));
else
getUpperBounds().add(new Double(fatherVOffset + father.getUpperBounds().get(i)));
}
for (int i = 0; i < father.getLowerBounds().size(); ++i)
{
if (getLowerBounds().size() > i + 1)
getLowerBounds().set(i+1, Math.min(new Double(fatherVOffset + father.getLowerBounds().get(i)), getLowerBounds().get(0)));
else
getLowerBounds().add(new Double(fatherVOffset + father.getLowerBounds().get(i)));
}
upperSubTreeHeight = Math.max(upperSubTreeHeight, fatherVOffset + father.upperSubTreeHeight);
lowerSubTreeHeight = Math.min(lowerSubTreeHeight, fatherVOffset + father.lowerSubTreeHeight);
}
else
{
//add gap onto bottom of lower parent to ensure that different sets of grandparents are spaced father than spouses
mother.getLowerBounds().set(0, mother.getLowerBounds().get(0) - vertSeperation );
//calculate distance in between mother and father and offsets from child
fatherVOffset = 0;
motherVOffset = -fatherVOffset;
int intrudeGen = 0;
//TODO FIX THESE CHECKS!
boolean firstNotSpouse = false;
firstNotSpouse = (this.gen == 0 && options.getDescGens() > 0 && !options.isIncludeSpouses());
if (styleBox.isIntruding && options.isAllowIntrusion() && !firstNotSpouse){
double remainingIntrudeWidth = styleBox.intrudeWidth - (stylingBoxes.getAncesStyle(gen).getBoxWidth() + stylingBoxes.getAncesStyle(gen).getRelativeOffset());
for (int i = gen; remainingIntrudeWidth > 0; i++)
{
if (father.getLowerBounds().size() > (i - gen)){
if (-father.getLowerBounds().get(i - gen) > (fatherVOffset - getUpperBounds().get(0))){
fatherVOffset += -father.getLowerBounds().get(i - gen) - (fatherVOffset - getUpperBounds().get(0));
}
}
else
father.getLowerBounds().add(-(fatherVOffset + getUpperBounds().get(0)));
if (mother.getUpperBounds().size() > (i - gen)){
if (mother.getUpperBounds().get(i - gen) > (-motherVOffset - getUpperBounds().get(0))){
motherVOffset -= mother.getUpperBounds().get(i - gen) - (-motherVOffset - getUpperBounds().get(0));
}
}
else
mother.getUpperBounds().add(-(motherVOffset - getUpperBounds().get(0)));
remainingIntrudeWidth -= (stylingBoxes.getAncesStyle(i+1).getBoxWidth() + stylingBoxes.getAncesStyle(i+1).getRelativeOffset());
intrudeGen = i - gen;
}
int maxIntersectGen = Math.min(father.getUpperBounds().size(), mother.getUpperBounds().size());
for (int i = intrudeGen; i < maxIntersectGen; i++){
if ((fatherVOffset + father.getLowerBounds().get(i))<(motherVOffset + mother.getUpperBounds().get(i))){
double distance = ((motherVOffset + mother.getUpperBounds().get(i)) - (fatherVOffset + father.getLowerBounds().get(i)))/2.0;
fatherVOffset += (distance < 0? -distance:distance);
motherVOffset -= (distance < 0? -distance:distance);
}
}
}
else
{
double maxDistance = calcIntersectDist(father, mother);
fatherVOffset = maxDistance / 2.0;
motherVOffset = -fatherVOffset;
}
//This is to stop the lines from crossing into intruding boxes
if(styleBox.isIntruding && options.isAllowIntrusion()){
double upperLine = fatherVOffset - getUpperBounds().get(0);
double fatherLowerBound = (father.getLowerBounds().get(0) + father.intersectLowerHeight);
if(((upperLine) + (fatherLowerBound))<0)
fatherVOffset = (-(fatherLowerBound - getUpperBounds().get(0)));
double lowerLine = motherVOffset - getLowerBounds().get(0);
double motherUpperBound = mother.getUpperBounds().get(0) + mother.intersectUpperHeight;
if(((lowerLine) + (motherUpperBound))>0)
motherVOffset = (-(motherUpperBound - getLowerBounds().get(0)));
}
//calculate rest of upper bounds array
int i;
for (i = 0; i < father.getUpperBounds().size(); ++i)
{
if (getUpperBounds().size() > i + 1)
getUpperBounds().set(i+1, new Double(fatherVOffset + father.getUpperBounds().get(i)));
else
getUpperBounds().add(new Double(fatherVOffset + father.getUpperBounds().get(i)));
}
for ( ; i < mother.getUpperBounds().size(); ++i)
{
if (getUpperBounds().size() > i + 1)
getUpperBounds().set(i+1, new Double(motherVOffset + mother.getUpperBounds().get(i)));
else
getUpperBounds().add(new Double(motherVOffset + mother.getUpperBounds().get(i)));
}
//calculate rest of lower bounds array
for (i = 0; i < mother.getLowerBounds().size(); ++i)
{
if (getLowerBounds().size() > i + 1)
getLowerBounds().set(i+1, new Double(motherVOffset + mother.getLowerBounds().get(i)));
else
getLowerBounds().add(new Double(motherVOffset + mother.getLowerBounds().get(i)));
}
for ( ; i < father.getLowerBounds().size(); ++i)
{
if (getLowerBounds().size() > i + 1)
getLowerBounds().set(i+1, new Double(fatherVOffset + father.getLowerBounds().get(i)));
else
getLowerBounds().add(new Double(fatherVOffset + father.getLowerBounds().get(i)));
}
upperSubTreeHeight = Math.max(Math.max(upperSubTreeHeight, fatherVOffset + father.upperSubTreeHeight), motherVOffset + mother.upperSubTreeHeight);
lowerSubTreeHeight = Math.min(Math.min(lowerSubTreeHeight, motherVOffset + mother.lowerSubTreeHeight), fatherVOffset + father.lowerSubTreeHeight);
}
if(options.isAllowIntrusion() && styleBox.isIntruding){
intersectUpperHeight = (fatherVOffset - getUpperBounds().get(0)) + 3*styleBox.borderlineWidth;
intersectLowerHeight = (motherVOffset - getLowerBounds().get(0)) - 3*styleBox.borderlineWidth;
}
}
}
//-----------------------------------------------------------------------
void drawAncesRootTree(ChartMargins chart, MultisheetChartOptions options, double x, double y, OpgSession session)
{
//start recursion on self
if (!(options.getAncesGens() == 0 && options.getDescGens() > 0) ||
(options.getAncesGens() == 0 && options.isIncludeSpouses()))
{
drawAncesTreeRec(0, chart, options, x,y, session);
}
}
//-----------------------------------------------------------------------
@Override
public void drawAncesTreeRec(int curGen, ChartMargins chart, PresetChartOptions options, double x, double y, OpgSession session)
{
OpgOptions opgOptions = session.getOpgOptions();
int maxGen;
/*if(maker.equals(session.getBaseMaker()))
maxGen = options.getAncesGens()-1;
else
maxGen = options.getAncesGens();*/
if(session.getMakerByRoot(options.getRoot().id) == session.getBaseMaker() && options.getAncesGens() == 5)
maxGen = options.getAncesGens() -1;
else
maxGen = options.getAncesGens();
//increase box Width and height to allow intrusion of a box into the next generation
double myBoxWidth = boxWidth;
boolean intrudes = false;
if (styleBox.isIntruding && options.isAllowIntrusion())
{
myBoxWidth = styleBox.intrudeWidth;
intrudes = true;
}
System.out.println(getIndi().id+" "+getIndi().givenName+" "+getIndi().surname+" "+this.maxVisibleGensInTree);
if (!(curGen == 0 && options.getAncesGens() > 0 && options.getDescGens() > 0) || (options.isIncludeSpouses() && options.getDescGens() > 0))
drawBox(chart, options, chart.xOffset(x), chart.yOffset(y), myBoxWidth, (upperBoxBound - lowerBoxBound), session);
if (maxGen > curGen)//options.getAncesGens() > curGen)
{
double xsepvalue = styleBox.getRelativeOffset();
if ((!opgOptions.isCollapsed(getIndi()) && !opgOptions.getDuplicateMap().containsKey(getIndi().id)) || options.getRoot() == getIndi())
{
if ((father != null))
{
//draw father (recursively)
try {
father.drawAncesTreeRec(curGen+1, chart, options, x + styleBox.getBoxWidth() + xsepvalue, y + yXForm(fatherVOffset), session);
} catch (Exception e) {
// Auto-generated catch block
e.printStackTrace();
}
//draw lines to father
if (!intrudes)
{
chart.addDrawCommand(new DrawCmdMoveTo(chart.xOffset(x + styleBox.getBoxWidth()), chart.yOffset(y)));
chart.addDrawCommand(new DrawCmdRelLineTo(xsepvalue/2.0,0.0,1, Color.BLACK));
chart.addDrawCommand(new DrawCmdRelLineTo(0.0,yXForm(fatherVOffset),1, Color.BLACK));
chart.addDrawCommand(new DrawCmdRelLineTo(xsepvalue/2.0,0.0,1, Color.BLACK));
} else
{
if(curGen==0 && options.getDescGens() == 0){
chart.addDrawCommand(new DrawCmdMoveTo(chart.xOffset(x + styleBox.getBoxWidth()/2.0), chart.yOffset(y + upperBoxBound)));
chart.addDrawCommand(new DrawCmdRelLineTo(0.0,yXForm(fatherVOffset)- upperBoxBound ,1, Color.black));
chart.addDrawCommand(new DrawCmdRelLineTo(styleBox.getBoxWidth()/2.0 + xsepvalue, 0.0,1, Color.black));
}
else if (curGen == 0){
chart.addDrawCommand(new DrawCmdMoveTo(chart.xOffset(x + styleBox.getBoxWidth()/2.0), chart.yOffset(y + upperBoxBound)));
chart.addDrawCommand(new DrawCmdRelLineTo(0.0,yXForm(fatherVOffset)- upperBoxBound ,1, Color.black));
chart.addDrawCommand(new DrawCmdRelLineTo(styleBox.getBoxWidth()/2.0 + xsepvalue, 0.0,1, Color.black));
}
else{
chart.addDrawCommand(new DrawCmdMoveTo(chart.xOffset(x + styleBox.getBoxWidth()/2.0), chart.yOffset(y + upperBoxBound)));
chart.addDrawCommand(new DrawCmdRelLineTo(0.0,yXForm(fatherVOffset) - upperBoxBound,1, Color.BLACK));
chart.addDrawCommand(new DrawCmdRelLineTo(styleBox.getBoxWidth()/2.0 + xsepvalue, 0.0,1, Color.BLACK));
}
}
}
if ((mother != null))
{
//draw mother (recursively)
mother.drawAncesTreeRec(curGen + 1, chart, options, x + styleBox.getBoxWidth() + xsepvalue, y + yXForm(motherVOffset), session);
//draw lines to mother
if (!intrudes)
{
chart.addDrawCommand(new DrawCmdMoveTo(chart.xOffset(x + styleBox.getBoxWidth()), chart.yOffset(y)));
chart.addDrawCommand(new DrawCmdRelLineTo(xsepvalue/2.0,0.0,1, Color.BLACK));
chart.addDrawCommand(new DrawCmdRelLineTo(0.0, yXForm(motherVOffset),1, Color.BLACK));
chart.addDrawCommand(new DrawCmdRelLineTo(xsepvalue/2.0,0,1, Color.BLACK));
} else
{
if(curGen == 0 && options.getDescGens() == 0){
chart.addDrawCommand(new DrawCmdMoveTo(chart.xOffset(x + styleBox.getBoxWidth()/2.0), chart.yOffset(y + lowerBoxBound)));
chart.addDrawCommand(new DrawCmdRelLineTo(0.0,yXForm(motherVOffset) - lowerBoxBound,1, Color.BLACK));
chart.addDrawCommand(new DrawCmdRelLineTo(styleBox.getBoxWidth()/2.0 + xsepvalue, 0.0,1, Color.BLACK));
}
else if(curGen == 0){
chart.addDrawCommand(new DrawCmdMoveTo(chart.xOffset(x + styleBox.getBoxWidth()/2.0), chart.yOffset(y + lowerBoxBound)));
chart.addDrawCommand(new DrawCmdRelLineTo(0.0,yXForm(motherVOffset) - lowerBoxBound,1, Color.BLACK));
chart.addDrawCommand(new DrawCmdRelLineTo(styleBox.getBoxWidth()/2.0 + xsepvalue, 0.0,1, Color.BLACK));
}
else{
chart.addDrawCommand(new DrawCmdMoveTo(chart.xOffset(x + styleBox.getBoxWidth()/2.0), chart.yOffset(y + lowerBoxBound)));
chart.addDrawCommand(new DrawCmdRelLineTo(0.0,yXForm(motherVOffset) - lowerBoxBound,1, Color.BLACK));
chart.addDrawCommand(new DrawCmdRelLineTo(styleBox.getBoxWidth()/2.0 + xsepvalue, 0.0,1, Color.BLACK));
}
}
}
}else if(opgOptions.getDuplicateMap().containsKey(getIndi().id)){
Font arrowFont = session.getOpgOptions().getFont().getFont(Font.PLAIN, (float)styleBox.endLineArrowFontSize);
double xOffset = ((styleBox.isIntruding && options.isAllowIntrusion())?styleBox.intrudeWidth:styleBox.getBoxWidth());
chart.addDrawCommand(new DrawCmdMoveTo(chart.xOffset(x + xOffset), chart.yOffset(y)));
chart.addDrawCommand(new DrawCmdEndChartArrow(styleBox.endLineArrowShaftHeight, styleBox.endLineArrowHeadHeight, styleBox.endLineArrowHeadLength, styleBox.endLineArrowShaftLength, styleBox.borderlineWidth, Color.black, session.getBaseOptions().getAncesScheme().getColor(getIndi().id)));
chart.addDrawCommand(new DrawCmdPageLink(styleBox.endLineArrowHeadLength + styleBox.endLineArrowShaftLength, styleBox.endLineArrowHeadHeight, this.getIndi()));
chart.addDrawCommand(new DrawCmdSetFont(arrowFont, Color.black));
chart.addDrawCommand(new DrawCmdMoveTo(chart.xOffset(x + xOffset), chart.yOffset(y)));
BoxLayout b = new BoxLayout();
styleBox.layout.convertToSpecificLayout(b);
b.drawEndArrowText(chart, styleBox, options, x, y, this, session, arrowFont);
}
}
else
{
//TODO get the arrows at the ends of lists drawing. Also, standardize the font with the rest of program
//TODO change the null on the endchart arrow!
//If the program has reached here, it's because its drawing the last generation.
//If there are people beyond that not shown, it will draw an arrow that displays how
//Many generations and ancestors
//if(((father != null) || (mother!=null) || ((father == null)? false : (!opgOptions.isCollapsed(getIndi().father))) || ((mother == null)? false : (!opgOptions.isCollapsed(getIndi().mother)))) && options.isDrawEndOfLineArrows())
if(((father == null)? false : (!opgOptions.isCollapsed(getIndi().father))) || ((mother == null)? false : (!opgOptions.isCollapsed(getIndi().mother))) && options.isDrawEndOfLineArrows())
{
Font arrowFont = session.getOpgOptions().getFont().getFont(Font.PLAIN, (float)styleBox.endLineArrowFontSize);
double xOffset = ((styleBox.isIntruding && options.isAllowIntrusion())?styleBox.intrudeWidth:styleBox.getBoxWidth());
chart.addDrawCommand(new DrawCmdMoveTo(chart.xOffset(x + xOffset), chart.yOffset(y)));
chart.addDrawCommand(new DrawCmdEndChartArrow(styleBox.endLineArrowShaftHeight, styleBox.endLineArrowHeadHeight, styleBox.endLineArrowHeadLength, styleBox.endLineArrowShaftLength, styleBox.borderlineWidth, Color.black, session.getBaseOptions().getAncesScheme().getColor(getIndi().id)));
chart.addDrawCommand(new DrawCmdPageLink(styleBox.endLineArrowHeadLength + styleBox.endLineArrowShaftLength, styleBox.endLineArrowHeadHeight, this.getIndi()));
chart.addDrawCommand(new DrawCmdSetFont(arrowFont, Color.black));
chart.addDrawCommand(new DrawCmdMoveTo(chart.xOffset(x + xOffset), chart.yOffset(y)));
BoxLayout b = new BoxLayout();
styleBox.layout.convertToSpecificLayout(b);
b.drawEndArrowText(chart, styleBox, options, x, y, this, session, arrowFont);
}
}
if(gen == 0 && !getIndi().originatingPages.isEmpty()){
ArrayList<String> lines = new ArrayList<String>();
Font arrowFont = session.getOpgOptions().getFont().getFont(Font.PLAIN, (float)styleBox.endLineArrowFontSize);
for(Individual i : getIndi().getOriginatingPages()){
lines.add(""+i.pageId);
}
chart.addDrawCommand(new DrawCmdMoveTo(chart.xOffset(x), chart.yOffset(y)));
chart.addDrawCommand(new DrawCmdStartChartArrow(styleBox.endLineArrowShaftHeight, styleBox.endLineArrowHeadHeight, styleBox.endLineArrowHeadLength, styleBox.endLineArrowShaftLength, styleBox.borderlineWidth, Color.black, session.getBaseOptions().getAncesScheme().getColor(getIndi().id), lines, arrowFont));
BoxLayout b = new BoxLayout();
styleBox.layout.convertToSpecificLayout(b);
b.drawStartArrowText(chart, styleBox, options, x, y,
styleBox.endLineArrowShaftLength + styleBox.endLineArrowHeadLength,
styleBox.endLineArrowHeadHeight, styleBox.endLineArrowShaftHeight,
lines, session, arrowFont, getIndi().getOriginatingPages());
}
}
//-----------------------------------------------------------------------
void drawBox (ChartMargins chart, PresetChartOptions options, double x, double y, double width, double height, OpgSession session)
{
setBoxInfo(new Rectangle2D.Double());
HashMap<String, Single<String>> duplicateLabels = session.getOpgOptions().getDuplicateLabels();
String duplicateLabel = (duplicateLabels.containsKey(getIndi().id)) ? ("<" + duplicateLabels.get(getIndi().id) + ">") : "";
BoxLayout b = new BoxLayout();
styleBox.layout.convertToSpecificLayout(b);
b.drawAnces(chart, options, styleBox, x, y, width, height,
getIndi(), duplicateLabel, getBoxInfo(), session);
// if (duplicateMap.containsKey(getIndi().id))
// System.out.println(duplicateLabel+": F:"+getIndi().father+" M:"+getIndi().mother);
}
@Override
public AncesBoxParent addSpecificBox(Individual indi){return new AncesBox(indi);};
}