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

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

#include "vtkObjectFactory.h"
#include "vtkVVSelectionFrameLayoutManager.h"
#include "vtkXMLDataElement.h"
#include "vtkVVSelectionFrame.h"
#include "vtkKWApplication.h"
#include "vtkKW2DRenderWidget.h"

#include "XML/vtkXMLVVSelectionFrameLayoutManagerWriter.h"
#include "XML/vtkXMLVVSelectionFrameReader.h"

vtkStandardNewMacro(vtkXMLVVSelectionFrameLayoutManagerReader);
vtkCxxRevisionMacro(vtkXMLVVSelectionFrameLayoutManagerReader, "$Revision: 1.10 $");

//----------------------------------------------------------------------------
const char* vtkXMLVVSelectionFrameLayoutManagerReader::GetRootElementName()
{
  return "VVSelectionFrameLayoutManager";
}

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

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

  // Get Attributes

  int old_reorg = obj->GetReorganizeWidgetPositionsAutomatically();
  obj->SetReorganizeWidgetPositionsAutomatically(0);

  // Set the resolution to an empty screen, so that we are sure repacking
  // will occur. Since the position of each frame is set explicitly in the
  // loop below, loading a session, closing the data (i.e. unpack), then
  // reloading it would not repack anything.

  int res[2] = {0, 0};
  int origin[2] = {0, 0};
  obj->SetResolutionAndOrigin(res, origin);

  // Get nested elements

  vtkXMLDataElement *nested_elem;

  // Selection Frames

  int pos_changed = 0;
  nested_elem = elem->FindNestedElementWithName(
    vtkXMLVVSelectionFrameLayoutManagerWriter::GetSelectionFramesElementName());
  if (nested_elem)
    {
    int idx, nb_container_elems = nested_elem->GetNumberOfNestedElements();
    for (idx = 0; idx < nb_container_elems; idx++)
      {
      vtkXMLDataElement *container_elem = nested_elem->GetNestedElement(idx);
      if (!strcmp(container_elem->GetName(), 
                  vtkXMLVVSelectionFrameLayoutManagerWriter::GetSelectionFrameContainerElementName()))
        {
        const char *tag = container_elem->GetAttribute("Tag");
        const char *group = container_elem->GetAttribute("Group");
        int pos[2];
        if (tag && group && 
            container_elem->GetVectorAttribute("Position", 2, pos) == 2)
          {
          vtkVVSelectionFrame *sel = vtkVVSelectionFrame::SafeDownCast(
            obj->GetWidgetWithTagAndGroup(tag, group));
          // Backward compatibility: the tag here was created by
          // vtkVVDataItemVolume::CreateRenderWidget, according to the "scope"
          // of the data (medical or scientific). Sadly, the scope is
          // detected from the file type: if that test fails, the scope
          // ends up different, all selection frames are created with 
          // different tags (i.e. "Axial" instead of "X-Y" for example), 
          // and no match is found.
          // The scope is now stored in the session, but let's try harder.
          if (!sel)
            {
            int orient = vtkKW2DRenderWidget::
              GetSliceOrientationFromMedicalOrientationString(tag);
            if (orient >= vtkKW2DRenderWidget::SLICE_ORIENTATION_YZ)
              {
              // Found tag as a default orientation string, try medical tag
              tag = vtkKW2DRenderWidget::
                GetSliceOrientationAsDefaultOrientationString(orient);
              }
            else
              {
              orient = vtkKW2DRenderWidget::
                GetSliceOrientationFromDefaultOrientationString(tag);
              if (orient >= vtkKW2DRenderWidget::SLICE_ORIENTATION_YZ)
                {
                // Found tag as a medical orientation string, try default tag
                tag = vtkKW2DRenderWidget::
                  GetSliceOrientationAsMedicalOrientationString(orient);
                }
              }
            sel = vtkVVSelectionFrame::SafeDownCast(
              obj->GetWidgetWithTagAndGroup(tag, group));
            }
          if (sel)
            {
            vtkXMLObjectReader *xmlr = sel->GetNewXMLReader();
            xmlr->ParseInElement(container_elem);
            xmlr->Delete();
            pos_changed += obj->SetImmediateWidgetPosition(sel, pos);
            }
          }
        }
      }
    }
  
  // What's going on here is that new selection frames have been added, and 
  // this usually triggers a reorganization in the manager *asynchronously*,
  // i.e. when the app becomes idle. So even if we set the resolution below
  // the reorganization code will be called later on (at idle time) and
  // the resolution will be re-adjusted automatically to fit *all* widgets.
  // To bypass that, let's just call the callback manually, this will perform
  // the reorganisation and cancel the timer that was going to schedule the
  // reorg. But first, make sure we start from a (0,0) layout, as the loop
  // above may have change the resolution already to a value identical
  // to the one we are aiming at but *before* each widget had a valid position
  // assigned (the callback would then be useless).

  obj->SetResolutionAndOrigin(res, origin);
  obj->NumberOfWidgetsHasChangedCallback();

  // Get Attributes

  int ival;

  obj->GetResolution(res);
  elem->GetVectorAttribute("Resolution", 2, res);

  obj->GetOrigin(origin);
  elem->GetVectorAttribute("Origin", 2, origin);

  obj->SetResolutionAndOrigin(res, origin);

  obj->SetReorganizeWidgetPositionsAutomatically(old_reorg);

  if (elem->GetScalarAttribute("ReorganizeWidgetPositionsAutomatically", ival))
    {
    obj->SetReorganizeWidgetPositionsAutomatically(ival);
    }


  return 1;
}

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