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

  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/vtkXMLVVSelectionFrameReader.h"

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

#include "XML/vtkXMLVVSelectionFrameWriter.h"

#include "KWCommonProInstantiator.h"

vtkStandardNewMacro(vtkXMLVVSelectionFrameReader);
vtkCxxRevisionMacro(vtkXMLVVSelectionFrameReader, "$Revision: 1.21 $");

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

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

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

  // Get Attributes

  const char *cptr;
  int ival;

  cptr = elem->GetAttribute("DataItemName");

  // Get nested elements

  vtkXMLDataElement *nested_elem;

  // Render Widget

  vtkKWRenderWidgetPro *widget = vtkKWRenderWidgetPro::SafeDownCast(
    obj->GetRenderWidget());
  if (widget)
    {
    nested_elem = elem->FindNestedElementWithName(
      vtkXMLVVSelectionFrameWriter::GetRenderWidgetElementName());
    if (nested_elem)
      {
      vtkXMLDataElement *widget_elem = nested_elem->GetNestedElement(0);
      vtkXMLObjectReader *xmlr = widget->GetNewXMLReader();
      xmlr->Parse(widget_elem);
      xmlr->Delete();
      }
    }
  
  // Let's update the annotations anyway, since it uses info from the file
  // which may have changed since the last time we save the state

  obj->GetDataItem()->UpdateRenderWidgetsAnnotations();

  // Interactor Widgets

  obj->RemoveAllInteractorWidgets();

  nested_elem = elem->FindNestedElementWithName(
    vtkXMLVVSelectionFrameWriter::GetInteractorWidgetsElementName());
  if (nested_elem)
    {
    int idx, nb_widgets_elems = nested_elem->GetNumberOfNestedElements();
    for (idx = 0; idx < nb_widgets_elems; idx++)
      {
      vtkXMLDataElement *widget_elem = nested_elem->GetNestedElement(idx);
      const char *classname = widget_elem->GetAttribute("ClassName");
      if (classname)
        {
        vtkObject *ptr = vtkInstantiator::CreateInstance(classname);
        if (ptr)
          {
          vtkAbstractWidget *widget = 
            vtkAbstractWidget::SafeDownCast(ptr);

          vtkKWDistanceWidget *distance_w = 
            vtkKWDistanceWidget::SafeDownCast(ptr);
          if (distance_w && obj->AddDistanceWidget(distance_w))
            {
            vtkXMLObjectReader *xmlr = distance_w->GetNewXMLReader();
            xmlr->Parse(widget_elem);
            xmlr->Delete();
            }

          vtkKWBiDimensionalWidget *bidimensional_w = 
            vtkKWBiDimensionalWidget::SafeDownCast(ptr);
          if (bidimensional_w && obj->AddBiDimensionalWidget(bidimensional_w))
            {
            vtkXMLObjectReader *xmlr = bidimensional_w->GetNewXMLReader();
            xmlr->Parse(widget_elem);
            xmlr->Delete();
            }

          vtkKWAngleWidget *angle_w = 
            vtkKWAngleWidget::SafeDownCast(ptr);
          if (angle_w && obj->AddAngleWidget(angle_w))
            {
            vtkXMLObjectReader *xmlr = angle_w->GetNewXMLReader();
            xmlr->Parse(widget_elem);
            xmlr->Delete();
            }

          vtkKWContourWidget *contour_w = 
            vtkKWContourWidget::SafeDownCast(ptr);
          if (contour_w && obj->AddContourWidget(contour_w))
            {
            vtkXMLObjectReader *xmlr = contour_w->GetNewXMLReader();
            xmlr->Parse(widget_elem);
            xmlr->Delete();
            }

          vtkKWCaptionWidget *label_w = 
            vtkKWCaptionWidget::SafeDownCast(ptr);
          if (label_w && obj->AddLabel2DWidget(label_w))
            {
            vtkXMLObjectReader *xmlr = label_w->GetNewXMLReader();
            xmlr->Parse(widget_elem);
            xmlr->Delete();
            }

          vtkVVHandleWidget *handle_w = 
            vtkVVHandleWidget::SafeDownCast(ptr);
          if (handle_w && obj->AddHandleWidget(handle_w))
            {
            vtkXMLObjectReader *xmlr = handle_w->GetNewXMLReader();
            xmlr->Parse(widget_elem);
            xmlr->Delete();
            }
          
          ptr->Delete();

          // Visibility, Lock, Original Slice

          if (widget_elem->GetScalarAttribute("Visibility", ival))
            {
            obj->SetInteractorWidgetVisibility(widget, ival);
            }
          else
            {
            // Legacy
            obj->SetInteractorWidgetVisibility(widget, widget->GetEnabled());
            }
          if (widget_elem->GetScalarAttribute("Lock", ival) && ival >= 0)
            {
            obj->SetInteractorWidgetLock(widget, ival);
            }
          if (widget_elem->GetScalarAttribute("OriginalSlice", ival) && 
              ival >= 0)
            {
            obj->SetInteractorWidgetOriginalSlice(widget, ival);
            }
          }
        }
      }
    }

  return 1;
}

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