// $Id: gc_assigntab.cpp,v 1.29 2018/01/03 21:32:58 mkkuhner Exp $

/*
Copyright 2002-2005 Mary K. Kuhner, Peter Beerli, and Joseph Felsenstein

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

/* Authors: Mary Kuhner, Jon Yamato, and Joseph Felsenstein */


#include <cassert>
#include <stdio.h>

#include "gc_assigntab.h"
#include "gc_block_dialogs.h"
#include "gc_clickpanel.h"
#include "gc_data_display.h"
#include "gc_default.h"
#include "gc_event_publisher.h"
#include "gc_file_list.h"               // EWFIX.P3 for GCExclaimBitmap
#include "gc_locus_dialogs.h"
#include "gc_logic.h"
//#include "gc_matrix_dialogs.h"
#include "gc_parse_block.h"
#include "gc_population_dialogs.h"
#include "gc_region_dialogs.h"
#include "gc_panel.h"
#include "gc_panel_dialogs.h"
#include "gc_parent.h"
#include "gc_parent_dialogs.h"
#include "gc_strings.h"
#include "gc_strings_region.h"
#include "gc_structures.h"
#include "gc_structures_err.h"          // JMDBG
#include "gc_frame.h"
#include "wx/log.h"                     // JMDBG
#include "wx/notebook.h"
#include "wx/colour.h"
//#include "wx/gdicmn.h"
#include "wx/statline.h"

//------------------------------------------------------------------------------------

gcBlockCell::gcBlockCell(wxWindow * parent, const GCParseBlock & blockRef)
    :   gcClickCell(parent,gcstr::dataBlocks),
        m_blockId(blockRef.GetId())
{
    AddText(wxString::Format(gcstr::blockInfo1,
                             (int)(blockRef.GetSamples().size()),
                             blockRef.GetParse().GetDataTypeString().c_str()));
    AddText(wxString::Format(gcstr::blockInfo2,
                             blockRef.GetParse().GetFileRef().GetShortName().c_str()));
    FinishSizing();
}

gcBlockCell::~gcBlockCell()
{
}

void
gcBlockCell::NotifyLeftDClick()
{
    gcEventActor * blockEditActor = new gcActor_BlockEdit(m_blockId);
    PublishScreenEvent(GetEventHandler(),blockEditActor);
}

//------------------------------------------------------------------------------------

gcPopCell::gcPopCell(wxWindow * parent, const gcPopulation & popRef)
    :   gcClickCell(parent,gcstr::population),
        m_popId(popRef.GetId())
{
    AddText(wxString::Format(gcstr::popLabelName,popRef.GetName().c_str()));
    FinishSizing();
}

gcPopCell::~gcPopCell()
{
}

void
gcPopCell::NotifyLeftDClick()
{
    gcEventActor * popEditActor = new gcActor_Pop_Edit(m_popId);
    PublishScreenEvent(GetEventHandler(),popEditActor);
}

//------------------------------------------------------------------------------------

gcRegionCell::gcRegionCell(wxWindow * parent, const gcRegion & regRef)
    :   gcClickCell(parent,gcstr::region),
        m_regionId(regRef.GetId())
{
    AddText(wxString::Format(gcstr::regionLabelName,regRef.GetName().c_str()));
    if(regRef.HasEffectivePopulationSize())
    {
        AddText(wxString::Format(gcstr_region::effPopSize,regRef.GetEffectivePopulationSize()));
    }
    FinishSizing();
}

gcRegionCell::~gcRegionCell()
{
}

void
gcRegionCell::NotifyLeftDClick()
{
    gcEventActor * regionEditActor = new gcActor_RegionEdit(m_regionId);
    PublishScreenEvent(GetEventHandler(),regionEditActor);
}

//------------------------------------------------------------------------------------

gcLocusCell::gcLocusCell(wxWindow * parent, const gcLocus & locusRef)
    :   gcClickCell(parent,locusRef.GetLinked() ? gcstr::locus : gcstr::locusUnlinked),
        m_locusId(locusRef.GetId())
{
    AddText(wxString::Format(gcstr::locusLabelName,locusRef.GetName().c_str()));
    AddText(wxString::Format(gcstr::locusLabelDataType,locusRef.GetDataTypeString().c_str()));
    AddText(wxString::Format(gcstr::locusLabelSites,locusRef.GetNumMarkersString().c_str()));

    FinishSizing();
}

gcLocusCell::~gcLocusCell()
{
}

void
gcLocusCell::NotifyLeftDClick()
{
    gcEventActor * locusEditActor = new gcActor_LocusEdit(m_locusId);
    PublishScreenEvent(GetEventHandler(),locusEditActor);
}

//------------------------------------------------------------------------------------

gcPanelCell::gcPanelCell(wxWindow * parent, const gcPanel & panRef)
    :   gcClickCell(parent,gcstr::panel),
        m_panelId(panRef.GetId())
{
    //wxLogVerbose("gcPanelCell panRefID:%i",(int)panRef.GetId());  // JMDBG
    AddText(wxString::Format(gcstr::panelLabelName, panRef.GetName().c_str()));
    AddText(wxString::Format(gcstr::members, panRef.GetNumPanelsString().c_str()));
    //wxLogVerbose("gcPanelCell m_panelid: %i",(int)m_panelId);  // JMDBG

    FinishSizing();
}

gcPanelCell::~gcPanelCell()
{
}

void
gcPanelCell::NotifyLeftDClick()
{
    //wxLogVerbose("notifyLeftDClick m_panelid: %s",ToWxString(m_panelId).c_str());  // JMDBG
    //wxLogVerbose("notifyLeftDClick m_panelid: %i",(int)m_panelId);  // JMDBG
    gcEventActor * panelEditActor = new gcActor_PanelEdit(m_panelId);
    PublishScreenEvent(GetEventHandler(),panelEditActor);
}

//------------------------------------------------------------------------------------

gcEmptyCell::gcEmptyCell(wxWindow * parent)
    :   wxPanel(parent,-1,wxDefaultPosition,wxDefaultSize),
        m_sizer(NULL)
{
    // m_sizer = new wxStaticBoxSizer(wxVERTICAL,this); // don't do this
    // it generates an odd little spot on the screen that looks like a bug
    // but is actually a zero by zero dimensioned box frame.
}

gcEmptyCell::~gcEmptyCell()
{
}

//------------------------------------------------------------------------------------

gcDivergenceToggleCell::gcDivergenceToggleCell(wxWindow * parent, bool divergenceOn, int unused)
    :   gcClickCell(parent,gcstr::divergence),
        m_divergenceOn(divergenceOn)
{
    if(!m_divergenceOn)
    {
        AddText(wxString::Format("%s", gcstr::off.c_str()));
    }
    else
    {
        if (unused < 2)
        {
            AddText(wxString::Format("%s", "Done"));
        }
        else
        {
            AddText(wxString::Format("%s", "Continue"));
        }
    }
    FinishSizing();
}

gcDivergenceToggleCell::~gcDivergenceToggleCell()
{
}

void
gcDivergenceToggleCell::NotifyLeftDClick()
{
    ClearBackground ();
    //wxLogVerbose(" DivergenceToggle button pushed");  // JMDBG
    gcEventActor * parentActor = new gcActor_ParentNew();
    PublishScreenEvent(GetEventHandler(),parentActor);
}

//------------------------------------------------------------------------------------

gcPanelsToggleCell::gcPanelsToggleCell(wxWindow * parent, bool panelsOn)
    :   gcClickCell(parent,gcstr::panelToggle),
        m_panelsOn(panelsOn)

{
    if (!m_panelsOn)
    {
        AddText(gcstr::off);
    }
    else
    {
        AddText(gcstr::on);
    }
    FinishSizing();
}

gcPanelsToggleCell::~gcPanelsToggleCell()
{
}

void
gcPanelsToggleCell::NotifyLeftDClick()
{
    ClearBackground ();
    wxLogVerbose("PanelToggle button pushed");  // JMDBG
    gcEventActor * PanelsToggleActor = new gcActor_PanelsToggle();
    PublishScreenEvent(GetEventHandler(),PanelsToggleActor);
}

//------------------------------------------------------------------------------------

bool
gcActor_PanelsToggle::OperateOn(wxWindow * parent, GCDataStore & dataStore)
{
    dataStore.GetStructures().SetPanelsState(!dataStore.GetStructures().GetPanelsState());
    return true;
}

//------------------------------------------------------------------------------------

gcParentCell::gcParentCell(wxWindow * parent, const gcParent & parRef)
    :   gcClickCell(parent,gcstr::parent),
        m_parentId(parRef.GetId())
{
    // wxLogVerbose("gcParentCell parRefID:%i",(int)parRef.GetId());  // JMDBG
    AddText(wxString::Format(gcstr::parentLabelName,parRef.GetName().c_str()));
    //wxLogVerbose("gcParentCell m_panelid: %i",(int)m_parentId);  // JMDBG

    FinishSizing();
}

gcParentCell::~gcParentCell()
{
}

void
gcParentCell::NotifyLeftDClick()
{
    //wxLogVerbose("notifyLeftDClick m_panelid: %s",ToWxString(m_panelId).c_str());  // JMDBG
    //wxLogVerbose("notifyLeftDClick m_panelid: %i",(int)m_parentId);  // JMDBG
    gcEventActor * parentActor = new gcActor_ParentEdit(m_parentId);
    PublishScreenEvent(GetEventHandler(),parentActor);
}

//------------------------------------------------------------------------------------

wxPanel *
GCAssignmentTab::blockControl(wxWindow * window, constBlockVector & blocks)
{
    wxPanel * unitPanel = new wxPanel(window);
    if(blocks.empty())
    {
        wxBoxSizer * statBox = new wxBoxSizer(wxHORIZONTAL);
        statBox->AddStretchSpacer(1);
        statBox->Add(new wxStaticBitmap(unitPanel,-1,GCExclaimBitmap::exclBitmap()),0,wxALIGN_CENTRE_VERTICAL);
        statBox->Add(new wxStaticText(unitPanel,-1,gcdefault::emptyBlock),0,wxALIGN_CENTRE_VERTICAL);
        statBox->AddStretchSpacer(1);
        unitPanel->SetSizerAndFit(statBox);
        return unitPanel;
    }
    else
    {
        wxBoxSizer * statBox = new wxBoxSizer(wxVERTICAL);
        for(constBlockVector::const_iterator iter = blocks.begin();
            iter != blocks.end(); iter++)
        {
            const GCParseBlock * blockP = *iter;
            assert(blockP != NULL);
            statBox->Add(new gcBlockCell(unitPanel,*blockP),1,wxEXPAND);
        }
        unitPanel->SetSizerAndFit(statBox);
        return unitPanel;
    }
    assert(false);
    return NULL;
}

GCAssignmentTab::GCAssignmentTab( wxWindow * parent, GCLogic & logic)
    :
    gcInfoPane(parent, logic, gcstr::assignTabTitle)
{
}

GCAssignmentTab::~GCAssignmentTab()
{
}

wxPanel *
GCAssignmentTab::MakeContent()
{
    wxPanel * newPanel = new wxPanel(   m_scrolled,
                                        -1,
                                        wxDefaultPosition,
                                        wxDefaultSize,
                                        wxTAB_TRAVERSAL);

    GCDataDisplaySizer * dds = new GCDataDisplaySizer();
    const GCStructures & st = m_logic.GetStructures();
    GCStructures & st_var = m_logic.GetStructures();

    size_t popIndex = 0;
    size_t parIndex = 0;
    constObjVector popsToDisplay    =  st.GetConstDisplayablePops();
    constObjVector regionsToDisplay =  st.GetConstDisplayableRegions();
    constObjVector parents          =  st.GetConstParents();

    int panelMult = 1;
    if (st.GetPanelsState())
    {
        panelMult = 2;
    }

    // panel toggle button
    if (popsToDisplay.size() > 0) {
        dds->AddPanelsToggleCell(new gcPanelsToggleCell(newPanel,st.GetPanelsState()));
        wxLogVerbose(" Make Panels button");  // JMDBG
    }

    dds->SetOffset(parents.size());

    if (popsToDisplay.size() > 1) {
        int unused = st.GetUnusedPopCount() + st.GetUnusedParentCount();
        dds->AddDivergenceToggleCell(new gcDivergenceToggleCell(newPanel,st.GetDivergenceState(),unused));
        wxLogVerbose(" Make Divergence button");  // JMDBG
    }

    int nPopsDisplayOrder = 0;
    for(    constObjVector::const_iterator piter=popsToDisplay.begin();
            piter != popsToDisplay.end();
            piter++)
    {
        size_t popId = (*piter)->GetId();
        if (st.GetPop(popId).HasDispOrder())
        {
            nPopsDisplayOrder++;
        }
    }
    wxLogVerbose(" nPopsDisplayOrder: %i", nPopsDisplayOrder);  // JMDBG

    int dispIndex = 0;
    if(nPopsDisplayOrder == 0)
    {
        // no display order defined, output in the order found
        for(    constObjVector::const_iterator piter=popsToDisplay.begin();
                piter != popsToDisplay.end();
                piter++)
        {
            popIndex++;
            size_t popId = (*piter)->GetId();
            const gcPopulation & pop = st.GetPop(popId);
            dispIndex = (panelMult*(popIndex-1)) + 2;
            st_var.GetPop(popId).SetDispIndex(dispIndex);
            dds->AddPop(new gcPopCell(newPanel,pop),dispIndex, panelMult);
            wxLogVerbose(" unordered MakeContent Pop: %s dispIndex: %i Id: %i",(*piter)->GetName().c_str(), dispIndex, popId);  // JMDBG
        }
    }
    else
    {
        // has a display order, so use it
        int nPopDisplay = 1;

        while (nPopDisplay <= nPopsDisplayOrder)
        {
            for(    constObjVector::const_iterator piter=popsToDisplay.begin();
                    piter != popsToDisplay.end();
                    piter++)
            {
                size_t popId = (*piter)->GetId();
                wxLogVerbose(" check order MakeContent Pop: %s display order: %i",(*piter)->GetName().c_str(),                 st.GetPop(popId).GetDispOrder());  // JMDBG
                if (st.GetPop(popId).GetDispOrder() == nPopDisplay)
                {
                    popIndex++;
                    const gcPopulation & pop = st.GetPop(popId);
                    dispIndex = (panelMult*(popIndex-1)) + 2;
                    st_var.GetPop(popId).SetDispIndex(dispIndex);
                    dds->AddPop(new gcPopCell(newPanel,pop),dispIndex, panelMult);
                    nPopDisplay++;
                    wxLogVerbose(" ordered MakeContent Pop: %s",(*piter)->GetName().c_str());  // JMDBG
                }
            }
        }
        // now display the ones that haven't been used yet
        for(    constObjVector::const_iterator piter=popsToDisplay.begin();
                piter != popsToDisplay.end();
                piter++)
        {
            size_t popId = (*piter)->GetId();
            if (st.GetPop(popId).GetDispOrder() == 0)
            {
                popIndex++;
                const gcPopulation & pop = st.GetPop(popId);
                dispIndex = (panelMult*(popIndex-1)) + 2;
                st_var.GetPop(popId).SetDispIndex(dispIndex);
                dds->AddPop(new gcPopCell(newPanel,pop),dispIndex, panelMult);
                wxLogVerbose(" not ordered MakeContent Pop: %s",(*piter)->GetName().c_str());  // JMDBG
            }
        }
    }

    size_t locusIndex = 0;
    for(    constObjVector::const_iterator giter=regionsToDisplay.begin();
            giter != regionsToDisplay.end();
            giter++)
    {
        size_t regionId = (*giter)->GetId();
        const gcRegion & group = st.GetRegion(regionId);
        constObjVector loci = st.GetConstDisplayableLociInMapOrderFor(regionId);
        wxLogVerbose(" MakeContent Region: %s Id: %i",(*giter)->GetName().c_str(), regionId);  // JMDBG

        if(loci.size() == 0)
        {
            dds->AddRegion(new gcRegionCell(newPanel,group), locusIndex,locusIndex);
            locusIndex++;
        }
        else
        {
            if(st.RegionHasAnyLinkedLoci(regionId))
            {
                dds->AddRegion(new gcRegionCell(newPanel,group),locusIndex,locusIndex+loci.size()-1);
            }

            int subRegionLocusCount = 0;
            for(constObjVector::const_iterator liter=loci.begin(); liter != loci.end(); liter++)
            {

                size_t locusId = (*liter)->GetId();

                // display locus
                const gcLocus & locus = st.GetLocus(locusId);
                dds->AddLocus(new gcLocusCell(newPanel,locus),locusIndex);
                wxLogVerbose(" MakeContent Locus: %s id: %i",locus.GetName().c_str(), locusId);  // JMDBG

                // display blocks for locus
                popIndex = 0;
                int npanel = 0;

                if(nPopsDisplayOrder == 0)
                {
                    // no display order defined, output in the order found
                    for(constObjVector::const_iterator piter=popsToDisplay.begin();
                        piter != popsToDisplay.end();
                        piter++)
                    {
                        popIndex++;
                        size_t popId = (*piter)->GetId();
                        wxLogVerbose(" No Order MakeContent block pop: %i locus: %i",(int)popId, (int) locusId);  // JMDBG
                        constBlockVector blockVec = m_logic.GetBlocks(popId,locusId);
                        dispIndex = (panelMult*(popIndex-1)) + 2;
                        dds->AddData(blockControl(newPanel,blockVec), dispIndex, locusIndex+1);

                        if (st.GetPanelsState())
                        {
                            dispIndex = (panelMult*(popIndex-1)) + 3;
                            if (subRegionLocusCount == 0)
                            {
                                int offset = dds->GetOffset();

                                if(blockVec.empty() && (loci.size() == 1))
                                {
                                    wxLogVerbose("AddPanel Empty cell row: %i column: %i length: %i", dispIndex,locusIndex+1+offset, loci.size());

                                    dds->AddPanel(new gcEmptyCell(newPanel), dispIndex, locusIndex+1, loci.size());
                                    if(!st.HasPanel(regionId, popId))
                                    {
                                        wxLogVerbose("blockVec Making panel for Region: %i pop: %i", regionId, popId);
                                        st_var.CreatePanel(regionId, popId);
                                    }
                                }
                                else
                                {
                                    if(!st.HasPanel(regionId, popId))
                                    {
                                        // have to make a new one because the region didn't exist when this population was read in
                                        wxLogVerbose("!HasPanel Making panel for Region: %i pop: %i", regionId, popId);
                                        st_var.CreatePanel(regionId, popId);
                                    }
                                    else
                                    {
                                        wxLogVerbose("Panel exists for Region: %i pop: %i", regionId, popId);
                                        const gcPanel& panel= st.GetPanel(regionId, popId);
                                        dds->AddPanel(new gcPanelCell(newPanel, panel), dispIndex, locusIndex+1, loci.size());
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    // has a display order, so use it
                    int nPopDisplay = 1;
                    while (nPopDisplay <= nPopsDisplayOrder)
                    {
                        for(    constObjVector::const_iterator piter=popsToDisplay.begin();
                                piter != popsToDisplay.end();
                                piter++)
                        {
                            size_t popId = (*piter)->GetId();
                            if (st.GetPop(popId).GetDispOrder() == nPopDisplay)
                            {
                                popIndex++;
                                wxLogVerbose(" Display Order MakeContent block pop: %i locus: %i",(int)popId, (int) locusId);  // JMDBG
                                constBlockVector blockVec = m_logic.GetBlocks(popId,locusId);
                                dispIndex = (panelMult*(popIndex-1)) + 2;
                                dds->AddData(blockControl(newPanel,blockVec), dispIndex, locusIndex+1);
                                nPopDisplay++;
                                if (st.GetPanelsState())
                                {
                                    dispIndex = (panelMult*(popIndex-1)) + 3;
                                    if (subRegionLocusCount == 0)
                                    {
                                        int offset = dds->GetOffset();

                                        if(blockVec.empty() && (loci.size() == 1))
                                        {
                                            wxLogVerbose("AddPanel Empty cell row: %i column: %i length: %i", dispIndex,locusIndex+1+offset, loci.size());

                                            dds->AddPanel(new gcEmptyCell(newPanel), dispIndex, locusIndex+1, loci.size());
                                        }
                                        else
                                        {
                                            if(!st.HasPanel(regionId, popId))
                                            {
                                                wxLogVerbose("No panel for Region: %i pop: %i", regionId, popId);
                                            }
                                            else
                                            {
                                                wxLogVerbose("Panel exists for Region: %i pop: %i", regionId, popId);
                                                const gcPanel& panel= st.GetPanel(regionId, popId);
                                                dds->AddPanel(new gcPanelCell(newPanel, panel), dispIndex, locusIndex+1, loci.size());
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // now display the ones that haven't been used yet
                    for(    constObjVector::const_iterator piter=popsToDisplay.begin();
                            piter != popsToDisplay.end();
                            piter++)
                    {
                        size_t popId = (*piter)->GetId();
                        if (st.GetPop(popId).GetDispOrder() == 0)
                        {
                            popIndex++;
                            wxLogVerbose(" After Display Order MakeContent block pop: %i locus: %i",(int)popId, (int) locusId);  // JMDBG
                            constBlockVector blockVec = m_logic.GetBlocks(popId,locusId);
                            dispIndex = (panelMult*(popIndex-1)) + 2;
                            dds->AddData(blockControl(newPanel,blockVec), dispIndex, locusIndex+1);
                            nPopDisplay++;
                            if (st.GetPanelsState())
                            {
                                dispIndex = (panelMult*(popIndex-1)) + 3;
                                if (subRegionLocusCount == 0)
                                {
                                    int offset = dds->GetOffset();

                                    if(blockVec.empty() && (loci.size() == 1))
                                    {
                                        wxLogVerbose("AddPanel Empty cell row: %i column: %i length: %i", dispIndex,locusIndex+1+offset, loci.size());

                                        dds->AddPanel(new gcEmptyCell(newPanel), dispIndex, locusIndex+1, loci.size());
                                    }
                                    else
                                    {
                                        if(!st.HasPanel(regionId, popId))
                                        {
                                            wxLogVerbose("No panel for Region: %i pop: %i", regionId, popId);
                                        }
                                        else
                                        {
                                            wxLogVerbose("Panel exists for Region: %i pop: %i", regionId, popId);
                                            const gcPanel& panel= st.GetPanel(regionId, popId);
                                            dds->AddPanel(new gcPanelCell(newPanel, panel), dispIndex, locusIndex+1, loci.size());
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                subRegionLocusCount++;
                locusIndex++;
            }
        }
    }

    // display parents on left side of display
    int npar = 0;
    int lastDispLevel = 0;
    int lastDispIndex = 0;
    if (parents.size() > 0)
    {
        wxLogVerbose(" parents.size(): %i",(int)parents.size());  // JMDBG
        for(constObjVector::const_iterator piter=parents.begin();
            piter != parents.end();
            piter++)
        {
            int curDispLevel = parents.size() - npar - 1;
            npar++;
            size_t parId = (*piter)->GetId();
            gcParent & par = st_var.GetParent(parId);
            //int curDispIndex = par.GetDispIndex();
            //int curDispLength = par.GetDispLength();
            int child1DispIndex;
            int child2DispIndex;
            int child1DispLength;
            int child2DispLength;

            // get the child dimensions
            if (st.IsPop(par.GetChild1Id()))
            {
                child1DispIndex  = st.GetPop(par.GetChild1Id()).GetDispIndex();
                child1DispLength = panelMult;
                wxLogVerbose("Child1: pop child1DispIndex: %i child1DispLength: %i", child1DispIndex, child1DispLength);  // JMDBG
            }
            else
            {
                child1DispIndex  = st.GetParent(par.GetChild1Id()).GetDispIndex();
                child1DispLength = st.GetParent(par.GetChild1Id()).GetDispLength();
                wxLogVerbose("Child1: parent child1DispIndex: %i child1DispLength: %i", child1DispIndex, child1DispLength);  // JMDBG
            }

            if (st.IsPop(par.GetChild2Id()))
            {
                child2DispIndex  = st.GetPop(par.GetChild2Id()).GetDispIndex();
                child2DispLength = panelMult;
                wxLogVerbose("Child2: pop child1DispIndex: %i child1DispLength: %i", child2DispIndex, child2DispLength);  // JMDBG
            }
            else
            {
                child2DispIndex  = st.GetParent(par.GetChild2Id()).GetDispIndex();
                child2DispLength = st.GetParent(par.GetChild2Id()).GetDispLength();
                wxLogVerbose("Child2: parent child1DispIndex: %i child1DispLength: %i", child2DispIndex, child2DispLength);  // JMDBG
            }

            // *** the following calculation is messy ***
            int topChildIndex;
            int botChildIndex;
            int topChildLength;
            int botChildLength;

            // find the top child
            if (child1DispIndex < child2DispIndex)
            {
                topChildIndex  = child1DispIndex;
                botChildIndex  = child2DispIndex;
                topChildLength = child1DispLength;
                botChildLength = child2DispLength;
            }
            else
            {
                topChildIndex  = child2DispIndex;
                botChildIndex  = child1DispIndex;
                topChildLength = child2DispLength;
                botChildLength = child1DispLength;
            }
            wxLogVerbose("topChildIndex: %i topChildLength: %i", topChildIndex, topChildLength);  // JMDBG
            wxLogVerbose("botChildIndex: %i botChildLength: %i", botChildIndex, botChildLength);  // JMDBG

            int curDispLength = 2 * panelMult;

            // find where the top of the parent box is
            int curDispIndex;
            if ((topChildLength + botChildLength) == curDispLength)
            {
                // 2 pop child case
                curDispIndex = topChildIndex;
                wxLogVerbose("2 pop child case");
            }
            else if ((topChildLength + botChildLength) == 3*panelMult)
            {
                // 1 pop, 1 parent child case
                if (topChildLength > botChildLength)
                {
                    // parent on top
                    curDispIndex = topChildIndex + panelMult;
                    wxLogVerbose("1 pop, 1 parent, parent on top case");
                }
                else
                {
                    // pop on top
                    curDispIndex = topChildIndex;
                    wxLogVerbose("1 pop, 1 parent, child on top case");
                }
            }
            else
            {
                // 2 parent child case
                curDispIndex = topChildIndex + panelMult;
                wxLogVerbose("2 parent child case");
            }

            dds->AddParent(new gcParentCell(newPanel,par),curDispIndex,curDispLevel, curDispLength);
            parIndex++;
            par.SetDispIndex(curDispIndex);
            par.SetDispLevel(curDispLevel);
            par.SetDispLength(curDispLength);
            wxLogVerbose(" MakeContent Parent: %s level: %i",(*piter)->GetName().c_str(), par.GetDispLevel());  // JMDBG
        }
    }
    newPanel->SetSizerAndFit(dds);

    wxLogVerbose("****newPanel done****");
    return newPanel;
}

wxString
GCAssignmentTab::MakeLabel()
{
    return m_panelLabelFmt;
}

//____________________________________________________________________________________
