/*****************************************************************************
*
* Copyright (c) 2000 - 2017, Lawrence Livermore National Security, LLC
* Produced at the Lawrence Livermore National Laboratory
* LLNL-CODE-442911
* All rights reserved.
*
* This file is  part of VisIt. For  details, see https://visit.llnl.gov/.  The
* full copyright notice is contained in the file COPYRIGHT located at the root
* of the VisIt distribution or at http://www.llnl.gov/visit/copyright.html.
*
* Redistribution  and  use  in  source  and  binary  forms,  with  or  without
* modification, are permitted provided that the following conditions are met:
*
*  - Redistributions of  source code must  retain the above  copyright notice,
*    this list of conditions and the disclaimer below.
*  - Redistributions in binary form must reproduce the above copyright notice,
*    this  list of  conditions  and  the  disclaimer (as noted below)  in  the
*    documentation and/or other materials provided with the distribution.
*  - Neither the name of  the LLNS/LLNL nor the names of  its contributors may
*    be used to endorse or promote products derived from this software without
*    specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT  HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR  IMPLIED WARRANTIES, INCLUDING,  BUT NOT  LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND  FITNESS FOR A PARTICULAR  PURPOSE
* ARE  DISCLAIMED. IN  NO EVENT  SHALL LAWRENCE  LIVERMORE NATIONAL  SECURITY,
* LLC, THE  U.S.  DEPARTMENT OF  ENERGY  OR  CONTRIBUTORS BE  LIABLE  FOR  ANY
* DIRECT,  INDIRECT,   INCIDENTAL,   SPECIAL,   EXEMPLARY,  OR   CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT  LIMITED TO, PROCUREMENT OF  SUBSTITUTE GOODS OR
* SERVICES; LOSS OF  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER
* CAUSED  AND  ON  ANY  THEORY  OF  LIABILITY,  WHETHER  IN  CONTRACT,  STRICT
* LIABILITY, OR TORT  (INCLUDING NEGLIGENCE OR OTHERWISE)  ARISING IN ANY  WAY
* OUT OF THE  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*****************************************************************************/

#include <SpreadsheetAttributes.h>
#include <DataNode.h>

//
// Enum conversion methods for SpreadsheetAttributes::NormalAxis
//

static const char *NormalAxis_strings[] = {
"X", "Y", "Z"
};

std::string
SpreadsheetAttributes::NormalAxis_ToString(SpreadsheetAttributes::NormalAxis t)
{
    int index = int(t);
    if(index < 0 || index >= 3) index = 0;
    return NormalAxis_strings[index];
}

std::string
SpreadsheetAttributes::NormalAxis_ToString(int t)
{
    int index = (t < 0 || t >= 3) ? 0 : t;
    return NormalAxis_strings[index];
}

bool
SpreadsheetAttributes::NormalAxis_FromString(const std::string &s, SpreadsheetAttributes::NormalAxis &val)
{
    val = SpreadsheetAttributes::X;
    for(int i = 0; i < 3; ++i)
    {
        if(s == NormalAxis_strings[i])
        {
            val = (NormalAxis)i;
            return true;
        }
    }
    return false;
}

// ****************************************************************************
// Method: SpreadsheetAttributes::SpreadsheetAttributes
//
// Purpose: 
//   Init utility for the SpreadsheetAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

void SpreadsheetAttributes::Init()
{
    subsetName = "Whole";
    formatString = "%1.6f";
    useColorTable = false;
    showTracerPlane = true;
    normal = Z;
    sliceIndex = 0;
    spreadsheetFont = "Courier,12,-1,5,50,0,0,0,0,0";
    showPatchOutline = true;
    showCurrentCellOutline = false;
    currentPick = 0;
    currentPickType = 0;
    currentPickValid = false;

    SpreadsheetAttributes::SelectAll();
}

// ****************************************************************************
// Method: SpreadsheetAttributes::SpreadsheetAttributes
//
// Purpose: 
//   Copy utility for the SpreadsheetAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

void SpreadsheetAttributes::Copy(const SpreadsheetAttributes &obj)
{
    subsetName = obj.subsetName;
    formatString = obj.formatString;
    useColorTable = obj.useColorTable;
    colorTableName = obj.colorTableName;
    showTracerPlane = obj.showTracerPlane;
    tracerColor = obj.tracerColor;
    normal = obj.normal;
    sliceIndex = obj.sliceIndex;
    spreadsheetFont = obj.spreadsheetFont;
    showPatchOutline = obj.showPatchOutline;
    showCurrentCellOutline = obj.showCurrentCellOutline;
    currentPick = obj.currentPick;
    currentPickType = obj.currentPickType;
    currentPickValid = obj.currentPickValid;
    currentPickLetter = obj.currentPickLetter;
    pastPicks = obj.pastPicks;
    pastPickLetters = obj.pastPickLetters;

    SpreadsheetAttributes::SelectAll();
}

// Type map format string
const char *SpreadsheetAttributes::TypeMapFormatString = SPREADSHEETATTRIBUTES_TMFS;
const AttributeGroup::private_tmfs_t SpreadsheetAttributes::TmfsStruct = {SPREADSHEETATTRIBUTES_TMFS};


// ****************************************************************************
// Method: SpreadsheetAttributes::SpreadsheetAttributes
//
// Purpose: 
//   Default constructor for the SpreadsheetAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

SpreadsheetAttributes::SpreadsheetAttributes() : 
    AttributeSubject(SpreadsheetAttributes::TypeMapFormatString),
    colorTableName("Default"), tracerColor(255, 0, 0, 150)
{
    SpreadsheetAttributes::Init();
}

// ****************************************************************************
// Method: SpreadsheetAttributes::SpreadsheetAttributes
//
// Purpose: 
//   Constructor for the derived classes of SpreadsheetAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

SpreadsheetAttributes::SpreadsheetAttributes(private_tmfs_t tmfs) : 
    AttributeSubject(tmfs.tmfs),
    colorTableName("Default"), tracerColor(255, 0, 0, 150)
{
    SpreadsheetAttributes::Init();
}

// ****************************************************************************
// Method: SpreadsheetAttributes::SpreadsheetAttributes
//
// Purpose: 
//   Copy constructor for the SpreadsheetAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

SpreadsheetAttributes::SpreadsheetAttributes(const SpreadsheetAttributes &obj) : 
    AttributeSubject(SpreadsheetAttributes::TypeMapFormatString)
{
    SpreadsheetAttributes::Copy(obj);
}

// ****************************************************************************
// Method: SpreadsheetAttributes::SpreadsheetAttributes
//
// Purpose: 
//   Copy constructor for derived classes of the SpreadsheetAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

SpreadsheetAttributes::SpreadsheetAttributes(const SpreadsheetAttributes &obj, private_tmfs_t tmfs) : 
    AttributeSubject(tmfs.tmfs)
{
    SpreadsheetAttributes::Copy(obj);
}

// ****************************************************************************
// Method: SpreadsheetAttributes::~SpreadsheetAttributes
//
// Purpose: 
//   Destructor for the SpreadsheetAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

SpreadsheetAttributes::~SpreadsheetAttributes()
{
    // nothing here
}

// ****************************************************************************
// Method: SpreadsheetAttributes::operator = 
//
// Purpose: 
//   Assignment operator for the SpreadsheetAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

SpreadsheetAttributes& 
SpreadsheetAttributes::operator = (const SpreadsheetAttributes &obj)
{
    if (this == &obj) return *this;

    SpreadsheetAttributes::Copy(obj);

    return *this;
}

// ****************************************************************************
// Method: SpreadsheetAttributes::operator == 
//
// Purpose: 
//   Comparison operator == for the SpreadsheetAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

bool
SpreadsheetAttributes::operator == (const SpreadsheetAttributes &obj) const
{
    // Create the return value
    return ((subsetName == obj.subsetName) &&
            (formatString == obj.formatString) &&
            (useColorTable == obj.useColorTable) &&
            (colorTableName == obj.colorTableName) &&
            (showTracerPlane == obj.showTracerPlane) &&
            (tracerColor == obj.tracerColor) &&
            (normal == obj.normal) &&
            (sliceIndex == obj.sliceIndex) &&
            (spreadsheetFont == obj.spreadsheetFont) &&
            (showPatchOutline == obj.showPatchOutline) &&
            (showCurrentCellOutline == obj.showCurrentCellOutline) &&
            (currentPick == obj.currentPick) &&
            (currentPickType == obj.currentPickType) &&
            (currentPickValid == obj.currentPickValid) &&
            (currentPickLetter == obj.currentPickLetter) &&
            (pastPicks == obj.pastPicks) &&
            (pastPickLetters == obj.pastPickLetters));
}

// ****************************************************************************
// Method: SpreadsheetAttributes::operator != 
//
// Purpose: 
//   Comparison operator != for the SpreadsheetAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

bool
SpreadsheetAttributes::operator != (const SpreadsheetAttributes &obj) const
{
    return !(this->operator == (obj));
}

// ****************************************************************************
// Method: SpreadsheetAttributes::TypeName
//
// Purpose: 
//   Type name method for the SpreadsheetAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

const std::string
SpreadsheetAttributes::TypeName() const
{
    return "SpreadsheetAttributes";
}

// ****************************************************************************
// Method: SpreadsheetAttributes::CopyAttributes
//
// Purpose:
//   CopyAttributes method for the SpreadsheetAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: Hank Childs
// Creation:   August 31, 2007
//
// Modifications:
//   Gunther H. Weber, Fri Sep 14 11:33:48 PDT 2007
//   Copy pick letters. Move clearing of pick history to custom
//   SetSubsetName() method.
//
//   Brad Whitlock, Thu May 21 14:43:24 PDT 2009
//   Use pick element and type instead of the pick point.
//
//   Brad Whitlock, Wed Jun 27 16:04:29 PDT 2012
//   Do not turn off the tracer plane if we're just clearing picks.
//
// ****************************************************************************

bool
SpreadsheetAttributes::CopyAttributes(const AttributeGroup *atts)
{
    if (atts->TypeName() == "PlaneAttributes")
    {
        PlaneAttributes *p = (PlaneAttributes *) atts;
        const double *n = p->GetNormal();
        if (fabs(n[2]) >= fabs(n[0]) && fabs(n[2]) >= fabs(n[1]))
            SetNormal(Z);
        else if (fabs(n[1]) >= fabs(n[0]) && fabs(n[1]) >= fabs(n[2]))
            SetNormal(Y);
        else
            SetNormal(X);
        return true;
    }
    if (atts->TypeName() == "PickAttributes")
    {
        PickAttributes *p = (PickAttributes *) atts;

        // Handle a clear of pick points
        if (p->GetClearWindow())
        {
            pastPicks.clear();
            pastPickLetters.clear();
            currentPickValid = false;
            return true;
        }

        // If we got this from a pick, then the tracer plane will just
        // get in the way, so turn it off.
        SetShowTracerPlane(false);

        // Handle subset changes
        if (p->GetSubsetName() != "" &&
            p->GetSubsetName() != subsetName)
        {
            SetSubsetName(p->GetSubsetName());
        }

        // Add current pick to history, if valid
        if (currentPickValid)
        {
            pastPicks.push_back(GetCurrentPick());
            pastPicks.push_back(GetCurrentPickType());
            pastPickLetters.push_back(GetCurrentPickLetter());
        }

        // Set current pick based on history
        currentPickValid = true;
        SetCurrentPick(p->GetElementNumber());
        SetCurrentPickType((int)p->GetPickType());
        SetCurrentPickLetter(p->GetPickLetter());

        return true;
    }

    if(TypeName() != atts->TypeName())
        return false;

    // Call assignment operator.
    const SpreadsheetAttributes *tmp = (const SpreadsheetAttributes *)atts;
    *this = *tmp;

    return true;
}

// ****************************************************************************
// Method: SpreadsheetAttributes::CreateCompatible
//
// Purpose:
//   CreateCompatible method for the SpreadsheetAttributes class.
//
// Programmer: Hank Childs
// Creation:   September 14, 2007
//
// Modifications:
//
// ****************************************************************************

AttributeSubject *
SpreadsheetAttributes::CreateCompatible(const std::string &tname) const
{
    AttributeSubject *retval = 0;
    if(TypeName() == tname)
        retval = new SpreadsheetAttributes(*this);
    else if (tname == "PickAttributes")
    {
        PickAttributes *p = new PickAttributes();
        p->SetSubsetName(GetSubsetName());
        retval = p;
    }
    return retval;
}

// ****************************************************************************
// Method: SpreadsheetAttributes::NewInstance
//
// Purpose: 
//   NewInstance method for the SpreadsheetAttributes class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

AttributeSubject *
SpreadsheetAttributes::NewInstance(bool copy) const
{
    AttributeSubject *retval = 0;
    if(copy)
        retval = new SpreadsheetAttributes(*this);
    else
        retval = new SpreadsheetAttributes;

    return retval;
}

// ****************************************************************************
// Method: SpreadsheetAttributes::SelectAll
//
// Purpose: 
//   Selects all attributes.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

void
SpreadsheetAttributes::SelectAll()
{
    Select(ID_subsetName,             (void *)&subsetName);
    Select(ID_formatString,           (void *)&formatString);
    Select(ID_useColorTable,          (void *)&useColorTable);
    Select(ID_colorTableName,         (void *)&colorTableName);
    Select(ID_showTracerPlane,        (void *)&showTracerPlane);
    Select(ID_tracerColor,            (void *)&tracerColor);
    Select(ID_normal,                 (void *)&normal);
    Select(ID_sliceIndex,             (void *)&sliceIndex);
    Select(ID_spreadsheetFont,        (void *)&spreadsheetFont);
    Select(ID_showPatchOutline,       (void *)&showPatchOutline);
    Select(ID_showCurrentCellOutline, (void *)&showCurrentCellOutline);
    Select(ID_currentPick,            (void *)&currentPick);
    Select(ID_currentPickType,        (void *)&currentPickType);
    Select(ID_currentPickValid,       (void *)&currentPickValid);
    Select(ID_currentPickLetter,      (void *)&currentPickLetter);
    Select(ID_pastPicks,              (void *)&pastPicks);
    Select(ID_pastPickLetters,        (void *)&pastPickLetters);
}

///////////////////////////////////////////////////////////////////////////////
// Persistence methods
///////////////////////////////////////////////////////////////////////////////

// ****************************************************************************
// Method: SpreadsheetAttributes::CreateNode
//
// Purpose: 
//   This method creates a DataNode representation of the object so it can be saved to a config file.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   Brad Whitlock, Tue May 26 11:42:36 PDT 2009
//   Prevent the pick-related attributes from being saved.
//
// ****************************************************************************

bool
SpreadsheetAttributes::CreateNode(DataNode *parentNode, bool completeSave, bool forceAdd)
{
    if(parentNode == 0)
        return false;

    SpreadsheetAttributes defaultObject;
    bool addToParent = false;
    // Create a node for SpreadsheetAttributes.
    DataNode *node = new DataNode("SpreadsheetAttributes");

    if(completeSave || !FieldsEqual(ID_subsetName, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("subsetName", subsetName));
    }

    if(completeSave || !FieldsEqual(ID_formatString, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("formatString", formatString));
    }

    if(completeSave || !FieldsEqual(ID_useColorTable, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("useColorTable", useColorTable));
    }

    if(completeSave || !FieldsEqual(ID_colorTableName, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("colorTableName", colorTableName));
    }

    if(completeSave || !FieldsEqual(ID_showTracerPlane, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("showTracerPlane", showTracerPlane));
    }

        DataNode *tracerColorNode = new DataNode("tracerColor");
        if(tracerColor.CreateNode(tracerColorNode, completeSave, true))
        {
            addToParent = true;
            node->AddNode(tracerColorNode);
        }
        else
            delete tracerColorNode;
    if(completeSave || !FieldsEqual(ID_normal, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("normal", NormalAxis_ToString(normal)));
    }

    if(completeSave || !FieldsEqual(ID_sliceIndex, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("sliceIndex", sliceIndex));
    }

    if(completeSave || !FieldsEqual(ID_spreadsheetFont, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("spreadsheetFont", spreadsheetFont));
    }

    if(completeSave || !FieldsEqual(ID_showPatchOutline, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("showPatchOutline", showPatchOutline));
    }

    if(completeSave || !FieldsEqual(ID_showCurrentCellOutline, &defaultObject))
    {
        addToParent = true;
        node->AddNode(new DataNode("showCurrentCellOutline", showCurrentCellOutline));
    }

    // Add the node to the parent node.
    if(addToParent || forceAdd)
        parentNode->AddNode(node);
    else
        delete node;

    return (addToParent || forceAdd);
}
// ****************************************************************************
// Method: SpreadsheetAttributes::SetFromNode
//
// Purpose: 
//   This method sets attributes in this object from values in a DataNode representation of the object.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

void
SpreadsheetAttributes::SetFromNode(DataNode *parentNode)
{
    if(parentNode == 0)
        return;

    DataNode *searchNode = parentNode->GetNode("SpreadsheetAttributes");
    if(searchNode == 0)
        return;

    DataNode *node;
    if((node = searchNode->GetNode("subsetName")) != 0)
        SetSubsetName(node->AsString());
    if((node = searchNode->GetNode("formatString")) != 0)
        SetFormatString(node->AsString());
    if((node = searchNode->GetNode("useColorTable")) != 0)
        SetUseColorTable(node->AsBool());
    if((node = searchNode->GetNode("colorTableName")) != 0)
        SetColorTableName(node->AsString());
    if((node = searchNode->GetNode("showTracerPlane")) != 0)
        SetShowTracerPlane(node->AsBool());
    if((node = searchNode->GetNode("tracerColor")) != 0)
        tracerColor.SetFromNode(node);
    if((node = searchNode->GetNode("normal")) != 0)
    {
        // Allow enums to be int or string in the config file
        if(node->GetNodeType() == INT_NODE)
        {
            int ival = node->AsInt();
            if(ival >= 0 && ival < 3)
                SetNormal(NormalAxis(ival));
        }
        else if(node->GetNodeType() == STRING_NODE)
        {
            NormalAxis value;
            if(NormalAxis_FromString(node->AsString(), value))
                SetNormal(value);
        }
    }
    if((node = searchNode->GetNode("sliceIndex")) != 0)
        SetSliceIndex(node->AsInt());
    if((node = searchNode->GetNode("spreadsheetFont")) != 0)
        SetSpreadsheetFont(node->AsString());
    if((node = searchNode->GetNode("showPatchOutline")) != 0)
        SetShowPatchOutline(node->AsBool());
    if((node = searchNode->GetNode("showCurrentCellOutline")) != 0)
        SetShowCurrentCellOutline(node->AsBool());
    if((node = searchNode->GetNode("currentPick")) != 0)
        SetCurrentPick(node->AsInt());
    if((node = searchNode->GetNode("currentPickType")) != 0)
        SetCurrentPickType(node->AsInt());
    if((node = searchNode->GetNode("currentPickValid")) != 0)
        SetCurrentPickValid(node->AsBool());
    if((node = searchNode->GetNode("currentPickLetter")) != 0)
        SetCurrentPickLetter(node->AsString());
    if((node = searchNode->GetNode("pastPicks")) != 0)
        SetPastPicks(node->AsDoubleVector());
    if((node = searchNode->GetNode("pastPickLetters")) != 0)
        SetPastPickLetters(node->AsStringVector());
}

///////////////////////////////////////////////////////////////////////////////
// Set property methods
///////////////////////////////////////////////////////////////////////////////

// ****************************************************************************
// Method: SpreadsheetAttributes::SetSubsetName
//
// Purpose:
//   Custom SetSubsetName method for the SpreadsheetAttributes class
//   that clears the pick history if the subset changes.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: Gunther H. Weber
// Creation:   September 13, 2007
//
// Modifications:
//
// ****************************************************************************

void
SpreadsheetAttributes::SetSubsetName(const std::string &subsetName_)
{
    subsetName = subsetName_;
    pastPicks.clear();
    pastPickLetters.clear();
    SetCurrentPickValid(false);
    Select(0, (void *)&subsetName);
}

void
SpreadsheetAttributes::SetFormatString(const std::string &formatString_)
{
    formatString = formatString_;
    Select(ID_formatString, (void *)&formatString);
}

void
SpreadsheetAttributes::SetUseColorTable(bool useColorTable_)
{
    useColorTable = useColorTable_;
    Select(ID_useColorTable, (void *)&useColorTable);
}

void
SpreadsheetAttributes::SetColorTableName(const std::string &colorTableName_)
{
    colorTableName = colorTableName_;
    Select(ID_colorTableName, (void *)&colorTableName);
}

void
SpreadsheetAttributes::SetShowTracerPlane(bool showTracerPlane_)
{
    showTracerPlane = showTracerPlane_;
    Select(ID_showTracerPlane, (void *)&showTracerPlane);
}

void
SpreadsheetAttributes::SetTracerColor(const ColorAttribute &tracerColor_)
{
    tracerColor = tracerColor_;
    Select(ID_tracerColor, (void *)&tracerColor);
}

void
SpreadsheetAttributes::SetNormal(SpreadsheetAttributes::NormalAxis normal_)
{
    normal = normal_;
    Select(ID_normal, (void *)&normal);
}

void
SpreadsheetAttributes::SetSliceIndex(int sliceIndex_)
{
    sliceIndex = sliceIndex_;
    Select(ID_sliceIndex, (void *)&sliceIndex);
}

void
SpreadsheetAttributes::SetSpreadsheetFont(const std::string &spreadsheetFont_)
{
    spreadsheetFont = spreadsheetFont_;
    Select(ID_spreadsheetFont, (void *)&spreadsheetFont);
}

void
SpreadsheetAttributes::SetShowPatchOutline(bool showPatchOutline_)
{
    showPatchOutline = showPatchOutline_;
    Select(ID_showPatchOutline, (void *)&showPatchOutline);
}

void
SpreadsheetAttributes::SetShowCurrentCellOutline(bool showCurrentCellOutline_)
{
    showCurrentCellOutline = showCurrentCellOutline_;
    Select(ID_showCurrentCellOutline, (void *)&showCurrentCellOutline);
}

void
SpreadsheetAttributes::SetCurrentPick(int currentPick_)
{
    currentPick = currentPick_;
    Select(ID_currentPick, (void *)&currentPick);
}

void
SpreadsheetAttributes::SetCurrentPickType(int currentPickType_)
{
    currentPickType = currentPickType_;
    Select(ID_currentPickType, (void *)&currentPickType);
}

void
SpreadsheetAttributes::SetCurrentPickValid(bool currentPickValid_)
{
    currentPickValid = currentPickValid_;
    Select(ID_currentPickValid, (void *)&currentPickValid);
}

void
SpreadsheetAttributes::SetCurrentPickLetter(const std::string &currentPickLetter_)
{
    currentPickLetter = currentPickLetter_;
    Select(ID_currentPickLetter, (void *)&currentPickLetter);
}

void
SpreadsheetAttributes::SetPastPicks(const doubleVector &pastPicks_)
{
    pastPicks = pastPicks_;
    Select(ID_pastPicks, (void *)&pastPicks);
}

void
SpreadsheetAttributes::SetPastPickLetters(const stringVector &pastPickLetters_)
{
    pastPickLetters = pastPickLetters_;
    Select(ID_pastPickLetters, (void *)&pastPickLetters);
}

///////////////////////////////////////////////////////////////////////////////
// Get property methods
///////////////////////////////////////////////////////////////////////////////

const std::string &
SpreadsheetAttributes::GetSubsetName() const
{
    return subsetName;
}

std::string &
SpreadsheetAttributes::GetSubsetName()
{
    return subsetName;
}

const std::string &
SpreadsheetAttributes::GetFormatString() const
{
    return formatString;
}

std::string &
SpreadsheetAttributes::GetFormatString()
{
    return formatString;
}

bool
SpreadsheetAttributes::GetUseColorTable() const
{
    return useColorTable;
}

const std::string &
SpreadsheetAttributes::GetColorTableName() const
{
    return colorTableName;
}

std::string &
SpreadsheetAttributes::GetColorTableName()
{
    return colorTableName;
}

bool
SpreadsheetAttributes::GetShowTracerPlane() const
{
    return showTracerPlane;
}

const ColorAttribute &
SpreadsheetAttributes::GetTracerColor() const
{
    return tracerColor;
}

ColorAttribute &
SpreadsheetAttributes::GetTracerColor()
{
    return tracerColor;
}

SpreadsheetAttributes::NormalAxis
SpreadsheetAttributes::GetNormal() const
{
    return NormalAxis(normal);
}

int
SpreadsheetAttributes::GetSliceIndex() const
{
    return sliceIndex;
}

const std::string &
SpreadsheetAttributes::GetSpreadsheetFont() const
{
    return spreadsheetFont;
}

std::string &
SpreadsheetAttributes::GetSpreadsheetFont()
{
    return spreadsheetFont;
}

bool
SpreadsheetAttributes::GetShowPatchOutline() const
{
    return showPatchOutline;
}

bool
SpreadsheetAttributes::GetShowCurrentCellOutline() const
{
    return showCurrentCellOutline;
}

int
SpreadsheetAttributes::GetCurrentPick() const
{
    return currentPick;
}

int
SpreadsheetAttributes::GetCurrentPickType() const
{
    return currentPickType;
}

bool
SpreadsheetAttributes::GetCurrentPickValid() const
{
    return currentPickValid;
}

const std::string &
SpreadsheetAttributes::GetCurrentPickLetter() const
{
    return currentPickLetter;
}

std::string &
SpreadsheetAttributes::GetCurrentPickLetter()
{
    return currentPickLetter;
}

const doubleVector &
SpreadsheetAttributes::GetPastPicks() const
{
    return pastPicks;
}

doubleVector &
SpreadsheetAttributes::GetPastPicks()
{
    return pastPicks;
}

const stringVector &
SpreadsheetAttributes::GetPastPickLetters() const
{
    return pastPickLetters;
}

stringVector &
SpreadsheetAttributes::GetPastPickLetters()
{
    return pastPickLetters;
}

///////////////////////////////////////////////////////////////////////////////
// Select property methods
///////////////////////////////////////////////////////////////////////////////

void
SpreadsheetAttributes::SelectSubsetName()
{
    Select(ID_subsetName, (void *)&subsetName);
}

void
SpreadsheetAttributes::SelectFormatString()
{
    Select(ID_formatString, (void *)&formatString);
}

void
SpreadsheetAttributes::SelectColorTableName()
{
    Select(ID_colorTableName, (void *)&colorTableName);
}

void
SpreadsheetAttributes::SelectTracerColor()
{
    Select(ID_tracerColor, (void *)&tracerColor);
}

void
SpreadsheetAttributes::SelectSpreadsheetFont()
{
    Select(ID_spreadsheetFont, (void *)&spreadsheetFont);
}

void
SpreadsheetAttributes::SelectCurrentPickLetter()
{
    Select(ID_currentPickLetter, (void *)&currentPickLetter);
}

void
SpreadsheetAttributes::SelectPastPicks()
{
    Select(ID_pastPicks, (void *)&pastPicks);
}

void
SpreadsheetAttributes::SelectPastPickLetters()
{
    Select(ID_pastPickLetters, (void *)&pastPickLetters);
}

///////////////////////////////////////////////////////////////////////////////
// Keyframing methods
///////////////////////////////////////////////////////////////////////////////

// ****************************************************************************
// Method: SpreadsheetAttributes::GetFieldName
//
// Purpose: 
//   This method returns the name of a field given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

std::string
SpreadsheetAttributes::GetFieldName(int index) const
{
    switch (index)
    {
    case ID_subsetName:             return "subsetName";
    case ID_formatString:           return "formatString";
    case ID_useColorTable:          return "useColorTable";
    case ID_colorTableName:         return "colorTableName";
    case ID_showTracerPlane:        return "showTracerPlane";
    case ID_tracerColor:            return "tracerColor";
    case ID_normal:                 return "normal";
    case ID_sliceIndex:             return "sliceIndex";
    case ID_spreadsheetFont:        return "spreadsheetFont";
    case ID_showPatchOutline:       return "showPatchOutline";
    case ID_showCurrentCellOutline: return "showCurrentCellOutline";
    case ID_currentPick:            return "currentPick";
    case ID_currentPickType:        return "currentPickType";
    case ID_currentPickValid:       return "currentPickValid";
    case ID_currentPickLetter:      return "currentPickLetter";
    case ID_pastPicks:              return "pastPicks";
    case ID_pastPickLetters:        return "pastPickLetters";
    default:  return "invalid index";
    }
}

// ****************************************************************************
// Method: SpreadsheetAttributes::GetFieldType
//
// Purpose: 
//   This method returns the type of a field given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

AttributeGroup::FieldType
SpreadsheetAttributes::GetFieldType(int index) const
{
    switch (index)
    {
    case ID_subsetName:             return FieldType_string;
    case ID_formatString:           return FieldType_string;
    case ID_useColorTable:          return FieldType_bool;
    case ID_colorTableName:         return FieldType_colortable;
    case ID_showTracerPlane:        return FieldType_bool;
    case ID_tracerColor:            return FieldType_color;
    case ID_normal:                 return FieldType_enum;
    case ID_sliceIndex:             return FieldType_int;
    case ID_spreadsheetFont:        return FieldType_string;
    case ID_showPatchOutline:       return FieldType_bool;
    case ID_showCurrentCellOutline: return FieldType_bool;
    case ID_currentPick:            return FieldType_int;
    case ID_currentPickType:        return FieldType_int;
    case ID_currentPickValid:       return FieldType_bool;
    case ID_currentPickLetter:      return FieldType_string;
    case ID_pastPicks:              return FieldType_doubleVector;
    case ID_pastPickLetters:        return FieldType_stringVector;
    default:  return FieldType_unknown;
    }
}

// ****************************************************************************
// Method: SpreadsheetAttributes::GetFieldTypeName
//
// Purpose: 
//   This method returns the name of a field type given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

std::string
SpreadsheetAttributes::GetFieldTypeName(int index) const
{
    switch (index)
    {
    case ID_subsetName:             return "string";
    case ID_formatString:           return "string";
    case ID_useColorTable:          return "bool";
    case ID_colorTableName:         return "colortable";
    case ID_showTracerPlane:        return "bool";
    case ID_tracerColor:            return "color";
    case ID_normal:                 return "enum";
    case ID_sliceIndex:             return "int";
    case ID_spreadsheetFont:        return "string";
    case ID_showPatchOutline:       return "bool";
    case ID_showCurrentCellOutline: return "bool";
    case ID_currentPick:            return "int";
    case ID_currentPickType:        return "int";
    case ID_currentPickValid:       return "bool";
    case ID_currentPickLetter:      return "string";
    case ID_pastPicks:              return "doubleVector";
    case ID_pastPickLetters:        return "stringVector";
    default:  return "invalid index";
    }
}

// ****************************************************************************
// Method: SpreadsheetAttributes::FieldsEqual
//
// Purpose: 
//   This method compares two fields and return true if they are equal.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//   
// ****************************************************************************

bool
SpreadsheetAttributes::FieldsEqual(int index_, const AttributeGroup *rhs) const
{
    const SpreadsheetAttributes &obj = *((const SpreadsheetAttributes*)rhs);
    bool retval = false;
    switch (index_)
    {
    case ID_subsetName:
        {  // new scope
        retval = (subsetName == obj.subsetName);
        }
        break;
    case ID_formatString:
        {  // new scope
        retval = (formatString == obj.formatString);
        }
        break;
    case ID_useColorTable:
        {  // new scope
        retval = (useColorTable == obj.useColorTable);
        }
        break;
    case ID_colorTableName:
        {  // new scope
        retval = (colorTableName == obj.colorTableName);
        }
        break;
    case ID_showTracerPlane:
        {  // new scope
        retval = (showTracerPlane == obj.showTracerPlane);
        }
        break;
    case ID_tracerColor:
        {  // new scope
        retval = (tracerColor == obj.tracerColor);
        }
        break;
    case ID_normal:
        {  // new scope
        retval = (normal == obj.normal);
        }
        break;
    case ID_sliceIndex:
        {  // new scope
        retval = (sliceIndex == obj.sliceIndex);
        }
        break;
    case ID_spreadsheetFont:
        {  // new scope
        retval = (spreadsheetFont == obj.spreadsheetFont);
        }
        break;
    case ID_showPatchOutline:
        {  // new scope
        retval = (showPatchOutline == obj.showPatchOutline);
        }
        break;
    case ID_showCurrentCellOutline:
        {  // new scope
        retval = (showCurrentCellOutline == obj.showCurrentCellOutline);
        }
        break;
    case ID_currentPick:
        {  // new scope
        retval = (currentPick == obj.currentPick);
        }
        break;
    case ID_currentPickType:
        {  // new scope
        retval = (currentPickType == obj.currentPickType);
        }
        break;
    case ID_currentPickValid:
        {  // new scope
        retval = (currentPickValid == obj.currentPickValid);
        }
        break;
    case ID_currentPickLetter:
        {  // new scope
        retval = (currentPickLetter == obj.currentPickLetter);
        }
        break;
    case ID_pastPicks:
        {  // new scope
        retval = (pastPicks == obj.pastPicks);
        }
        break;
    case ID_pastPickLetters:
        {  // new scope
        retval = (pastPickLetters == obj.pastPickLetters);
        }
        break;
    default: retval = false;
    }

    return retval;
}

///////////////////////////////////////////////////////////////////////////////
// User-defined methods.
///////////////////////////////////////////////////////////////////////////////

bool
SpreadsheetAttributes::ChangesRequireRecalculation(const SpreadsheetAttributes &obj) const
{
    return (subsetName != obj.subsetName);
}

// ****************************************************************************
// Method: SpreadsheetAttributes::ProcessOldVersions
//
// Purpose:
//   This method handles some old fields by converting them to new fields.
//
// Programmer: Burlen Loring
// Creation:   Fri Jul 18 15:20:59 PDT 2014
//
// Modifications:
//
// ****************************************************************************
void
SpreadsheetAttributes::ProcessOldVersions(DataNode *parentNode,
    const char *configVersion)
{
    if(parentNode == 0)
        return;

    DataNode *searchNode = parentNode->GetNode("SpreadsheetAttributes");
    if(searchNode == 0)
        return;

    // deal with the changes in r7405 where type of currentPick was
    // changed from double[3] to int. Since that patch pick related
    // attributes are no longer recorded in session files so we will
    // need to ignore them here.
    if(VersionLessThan(configVersion, "2.0.0"))
    {
        const char *pickAtts[] = {
            "currentPick",
            "currentPickType",
            "currentPickValid",
            "currentPickLetter",
            "pastPicks",
            "pastPickLetters"
            };
        for (size_t i=0; i<6; ++i)
        {
            DataNode *pickAtt = searchNode->GetNode(pickAtts[i]);
            if (pickAtt)
            {
                searchNode->RemoveNode(pickAtt, true);
            }
        }
    }
}

