/*=========================================================================

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/VolViewCopyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "XML/vtkXMLVVSelectionFrameWriter.h"

#include "vtkObjectFactory.h"
#include "vtkVVSelectionFrame.h"
#include "vtkXMLDataElement.h"
#include "vtkVVDataItem.h"
#include "vtkKWRenderWidgetPro.h"
#include "vtkKWCaptionWidget.h"
#include "vtkKWContourWidget.h"
#include "vtkKWDistanceWidget.h"
#include "vtkVVHandleWidget.h"
#include "vtkKWBiDimensionalWidget.h"
#include "vtkKWAngleWidget.h"

vtkStandardNewMacro(vtkXMLVVSelectionFrameWriter);
vtkCxxRevisionMacro(vtkXMLVVSelectionFrameWriter, "$Revision: 1.18 $");

//----------------------------------------------------------------------------
const char* vtkXMLVVSelectionFrameWriter::GetRootElementName()
{
  return "VVSelectionFrame";
}

//----------------------------------------------------------------------------
const char* vtkXMLVVSelectionFrameWriter::GetRenderWidgetElementName()
{
  return "RenderWidget";
}

//----------------------------------------------------------------------------
const char* vtkXMLVVSelectionFrameWriter::GetInteractorWidgetsElementName()
{
  return "InteractorWidgets";
}

//----------------------------------------------------------------------------
int vtkXMLVVSelectionFrameWriter::AddAttributes(vtkXMLDataElement *elem)
{
  if (!this->Superclass::AddAttributes(elem))
    {
    return 0;
    }

  vtkVVSelectionFrame *obj = vtkVVSelectionFrame::SafeDownCast(this->Object);
  if (!obj)
    {
    vtkWarningMacro(<< "The VVSelectionFrame is not set!");
    return 0;
    }

  if (obj->GetDataItem() && obj->GetDataItem()->GetName())
    {
    elem->SetAttribute("DataItemName", obj->GetDataItem()->GetName());
    }

  return 1;
}

//----------------------------------------------------------------------------
int vtkXMLVVSelectionFrameWriter::AddNestedElements(vtkXMLDataElement *elem)
{
  if (!this->Superclass::AddNestedElements(elem))
    {
    return 0;
    }

  vtkVVSelectionFrame *obj = vtkVVSelectionFrame::SafeDownCast(this->Object);
  if (!obj)
    {
    vtkWarningMacro(<< "The VVSelectionFrame is not set!");
    return 0;
    }

  // Render Widget

#if 1
  vtkKWRenderWidgetPro *widget = vtkKWRenderWidgetPro::SafeDownCast(
    obj->GetRenderWidget());
  if (widget)
    {
    vtkXMLObjectWriter *xmlw = widget->GetNewXMLWriter();
    xmlw->CreateInNestedElement(
      elem, vtkXMLVVSelectionFrameWriter::GetRenderWidgetElementName());
    xmlw->Delete();
    }
#endif

  // Interactor Widgets

  if (obj->GetNumberOfInteractorWidgets())
    {
    vtkXMLDataElement *nested_elem = this->NewDataElement();
    nested_elem->SetName(
      vtkXMLVVSelectionFrameWriter::GetInteractorWidgetsElementName());
    elem->AddNestedElement(nested_elem);
    nested_elem->Delete();
    
    for (int i = 0; i < obj->GetNumberOfInteractorWidgets(); i++)
      {
      vtkXMLDataElement *widget_elem = NULL;
      vtkAbstractWidget *widget = obj->GetNthInteractorWidget(i);

      vtkKWDistanceWidget *distance_w = 
        vtkKWDistanceWidget::SafeDownCast(widget);
      if (distance_w)
        {
        vtkXMLObjectWriter *xmlw = distance_w->GetNewXMLWriter();
        widget_elem = xmlw->CreateInElement(nested_elem);
        xmlw->Delete();
        }

      vtkKWBiDimensionalWidget *bidimensional_w = 
        vtkKWBiDimensionalWidget::SafeDownCast(widget);
      if (bidimensional_w)
        {
        vtkXMLObjectWriter *xmlw = bidimensional_w->GetNewXMLWriter();
        widget_elem = xmlw->CreateInElement(nested_elem);
        xmlw->Delete();
        }

      vtkKWAngleWidget *angle_w = 
        vtkKWAngleWidget::SafeDownCast(widget);
      if (angle_w)
        {
        vtkXMLObjectWriter *xmlw = angle_w->GetNewXMLWriter();
        widget_elem = xmlw->CreateInElement(nested_elem);
        xmlw->Delete();
        }

      vtkKWContourWidget *contour_w = 
        vtkKWContourWidget::SafeDownCast(widget);
      if (contour_w)
        {
        vtkXMLObjectWriter *xmlw = contour_w->GetNewXMLWriter();
        widget_elem = xmlw->CreateInElement(nested_elem);
        xmlw->Delete();
        }

      vtkKWCaptionWidget *label_w = 
        vtkKWCaptionWidget::SafeDownCast(widget);
      if (label_w)
        {
        vtkXMLObjectWriter *xmlw = label_w->GetNewXMLWriter();
        widget_elem = xmlw->CreateInElement(nested_elem);
        xmlw->Delete();
        }

      vtkVVHandleWidget *handle_w = 
        vtkVVHandleWidget::SafeDownCast(widget);
      if (handle_w)
        {
        vtkXMLObjectWriter *xmlw = handle_w->GetNewXMLWriter();
        widget_elem = xmlw->CreateInElement(nested_elem);
        xmlw->Delete();
        }

      // Visibility, Lock, Original Slice

      if (widget_elem)
        {
        int visibility = obj->GetInteractorWidgetVisibility(widget);
        widget_elem->SetIntAttribute("Visibility", visibility);

        int lock = obj->GetInteractorWidgetLock(widget);
        if (lock >= 0)
          {
          widget_elem->SetIntAttribute("Lock", lock);
          }

        int orig_slice = obj->GetInteractorWidgetOriginalSlice(widget);
        if (orig_slice >= 0)
          {
          widget_elem->SetIntAttribute("OriginalSlice", orig_slice);
          }

        // Legacy. The widget's Enabled flag used to be the attribute
        // representing the visibility of the widget. This is no more the
        // case since visibility depends on whether or not the widget is
        // locked to a specific slice, and if we are on that slice.
        // Previous versions of VolView will be able to read sessions written
        // with the code above, but it's likely a locked widget will appear
        // invisible since Enabled can be serialized as 0 now even though it
        // is meant to be visible according to the Visibility flag. To cope
        // with that, override the Enabled flag to reflect the value of 
        // Visibility. This should not be a big deal for new versions since
        // the Enabled flag is refreshed automatically based on the values
        // of Visibility, Lock and OriginalSlice.

        widget_elem->SetIntAttribute("Enabled", visibility);
        }
      }
    }
  
  return 1;
}

//----------------------------------------------------------------------------
void vtkXMLVVSelectionFrameWriter::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
}

