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

  Program:   ParaView
  Module:    vtkPVRenderView.cxx

  Copyright (c) Kitware, Inc.
  All rights reserved.
  See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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 "vtkPVRenderView.h"
#include "vtkPVRenderModule.h"

#include "vtkInstantiator.h"
#include "vtkCamera.h"
#include "vtkCollectionIterator.h"
#include "vtkCallbackCommand.h"
#include "vtkCommand.h"
#include "vtkInteractorObserver.h"
#include "vtkKWApplicationSettingsInterface.h"
#include "vtkKWChangeColorButton.h"
#include "vtkKWCheckButton.h"
#include "vtkKWComposite.h"
#include "vtkKWCompositeCollection.h"
#include "vtkKWCornerAnnotation.h"
#include "vtkKWFrame.h"
#include "vtkKWLabel.h"
#include "vtkKWLabeledFrame.h"
#include "vtkKWMenu.h"
#include "vtkKWNotebook.h"
#include "vtkKWPushButton.h"
#include "vtkKWRadioButton.h"
#include "vtkKWScale.h"
#include "vtkKWSplitFrame.h"
#include "vtkKWWindowCollection.h"
#include "vtkMultiProcessController.h"
#include "vtkObjectFactory.h"
#include "vtkPVApplication.h"
#include "vtkPVApplicationSettingsInterface.h"
#include "vtkPVAxesWidget.h"
#include "vtkPVCameraControl.h"
#include "vtkPVCameraIcon.h"
#include "vtkPVCompositeRenderModule.h"
#include "vtkPVConfig.h"
#include "vtkPVData.h"
#include "vtkPVDataInformation.h"
#include "vtkPVGenericRenderWindowInteractor.h"
#include "vtkPVInteractorStyleControl.h"
#include "vtkPVNavigationWindow.h"
#include "vtkPVPart.h"
#include "vtkPVPartDisplay.h"
#include "vtkPVProcessModule.h"
#include "vtkPVRenderModuleUI.h"
#include "vtkPVRenderView.h"
#include "vtkPVSource.h"
#include "vtkPVSourceCollection.h"
#include "vtkPVSourceList.h"
#include "vtkPVWindow.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkRenderer.h"
#include "vtkRendererCollection.h"
#include "vtkRenderWindow.h"
#include "vtkString.h"
#include "vtkTimerLog.h"
#include "vtkToolkits.h"
#include "vtkClientServerStream.h"


#ifdef _WIN32
#include "vtkWin32OpenGLRenderWindow.h"
#else
#include "vtkOpenGLRenderWindow.h"
#include "vtkOpenGLRenderer.h"
#endif

#define VTK_PV_NAV_FRAME_SIZE_REG_KEY "NavigationFrameSize"

/* 
 * This part was generated by ImageConvert from image:
 *    properties.png (zlib, base64)
 */
#define image_properties_width         16
#define image_properties_height        14
#define image_properties_pixel_size    4
#define image_properties_buffer_length 140

static unsigned char image_properties[] = 
  "eNrdkcENgDAMAxk9gzBMRmCjACqR3NSO4Islv5pz3dTdNxe+FMzjzOJ2x8axU48czSfbZ9"
  "jjtR+yKgP5lGJrBvZPfpoVWWx/OI9dVOa8J1uYqvo+uuuX6njsT//kx/d/ceVPtN4Pmg==";

//----------------------------------------------------------------------------
vtkStandardNewMacro(vtkPVRenderView);
vtkCxxRevisionMacro(vtkPVRenderView, "1.293.2.2");

int vtkPVRenderViewCommand(ClientData cd, Tcl_Interp *interp,
                             int argc, char *argv[]);

//===========================================================================
//***************************************************************************
class vtkPVRenderViewObserver : public vtkCommand
{
public:
  static vtkPVRenderViewObserver *New() 
    {return new vtkPVRenderViewObserver;};

  vtkPVRenderViewObserver()
    {
      this->PVRenderView = 0;
    }

  virtual void Execute(vtkObject* wdg, unsigned long event,  
                       void* calldata)
    {
      if ( this->PVRenderView )
        {
        if (event == vtkCommand::StartEvent &&
            vtkRenderer::SafeDownCast(wdg))
          {
          this->PVRenderView->StartRenderEvent();
          }
        else
          {
          this->PVRenderView->ExecuteEvent(wdg, event, calldata);
          this->AbortFlagOn();
          }
        }
    }

  vtkPVRenderView* PVRenderView;
};

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

//----------------------------------------------------------------------------
vtkPVRenderView::vtkPVRenderView()
{
  if (getenv("PV_SEPARATE_RENDER_WINDOW") != NULL)
    {
    this->TopLevelRenderWindow = vtkKWWidget::New();
    this->TopLevelRenderWindow->SetParent(this->Frame);
    this->VTKWidget->SetParent(NULL);
    this->VTKWidget->SetParent(this->TopLevelRenderWindow);
    }
  else
    {
    this->TopLevelRenderWindow = NULL;
    }    

  this->CommandFunction = vtkPVRenderViewCommand;
  this->SplitFrame = vtkKWSplitFrame::New();

  this->EventuallyRenderFlag = 0;
  this->RenderPending = NULL;

  this->MenuEntryUnderline = 4;
  this->SetMenuEntryName(VTK_PV_VIEW_MENU_LABEL);
  this->SetMenuEntryHelp("Show global view parameters (background color, annoations2 etc.)");

  this->StandardViewsFrame = vtkKWLabeledFrame::New();
  this->XMaxViewButton = vtkKWPushButton::New();
  this->XMinViewButton = vtkKWPushButton::New();
  this->YMaxViewButton = vtkKWPushButton::New();
  this->YMinViewButton = vtkKWPushButton::New();
  this->ZMaxViewButton = vtkKWPushButton::New();
  this->ZMinViewButton = vtkKWPushButton::New();
  
  this->RenderParametersFrame = vtkKWLabeledFrame::New();

  this->TriangleStripsCheck = vtkKWCheckButton::New();
  this->ParallelProjectionCheck = vtkKWCheckButton::New();
  this->ImmediateModeCheck = vtkKWCheckButton::New();

  this->RenderModuleUI = NULL;
 
  this->ManipulatorControl2D = vtkPVInteractorStyleControl::New();
  this->ManipulatorControl2D->SetRegisteryName("2D");
  this->ManipulatorControl3D = vtkPVInteractorStyleControl::New();
  this->ManipulatorControl3D->SetRegisteryName("3D");

  this->CameraControlFrame = vtkKWLabeledFrame::New();
  this->CameraControl = vtkPVCameraControl::New();
  
  this->NavigationFrame = vtkKWLabeledFrame::New();
  this->NavigationWindow = vtkPVNavigationWindow::New();
  this->SelectionWindow = vtkPVSourceList::New();

  this->NavigationWindowButton = vtkKWRadioButton::New();
  this->SelectionWindowButton = vtkKWRadioButton::New();

  this->ShowSelectionWindow = 0;
  this->ShowNavigationWindow = 0;

  this->InterfaceSettingsFrame = vtkKWLabeledFrame::New();
  this->Display3DWidgets = vtkKWCheckButton::New();

  this->OrientationAxesFrame = vtkKWLabeledFrame::New();
  this->OrientationAxesCheck = vtkKWCheckButton::New();
  this->OrientationAxesInteractiveCheck = vtkKWCheckButton::New();
  this->OrientationAxesOutlineColor = vtkKWChangeColorButton::New();
  this->OrientationAxes = vtkPVAxesWidget::New();

  int cc;
  for ( cc = 0; cc < 6; cc ++ )
    {
    this->CameraIcons[cc] = vtkPVCameraIcon::New();
    }
  this->CameraIconsFrame = vtkKWLabeledFrame::New();

  this->Observer = vtkPVRenderViewObserver::New();
  this->Observer->PVRenderView = this;

  this->PropertiesButton = vtkKWPushButton::New();
  this->MenuLabelSwitchBackAndForthToViewProperties = 0;
  
  this->Renderer2D = vtkRenderer::New();
  // Keep the zbuffer for picking.
  this->Renderer2D->EraseOff();
}

//----------------------------------------------------------------------------
void vtkPVRenderView::StartRenderEvent()
{
  // make the overlay renderer match the view of the 3d renderer
  if (this->Renderer2D)
    {
    this->Renderer2D->GetActiveCamera()->SetClippingRange(
      this->Renderer->GetActiveCamera()->GetClippingRange());
    this->Renderer2D->GetActiveCamera()->SetPosition(
      this->Renderer->GetActiveCamera()->GetPosition());
    this->Renderer2D->GetActiveCamera()->SetFocalPoint(
      this->Renderer->GetActiveCamera()->GetFocalPoint());
    this->Renderer2D->GetActiveCamera()->SetViewUp(
      this->Renderer->GetActiveCamera()->GetViewUp());
    }
}

//----------------------------------------------------------------------------
void vtkPVRenderView::ShowNavigationWindowCallback(int registery)
{
  this->Script("catch {eval pack forget [pack slaves %s]}",
               this->NavigationFrame->GetFrame()->GetWidgetName());
  this->Script("pack %s -fill both -expand t -side top -anchor n", 
               this->NavigationWindow->GetWidgetName());
  this->NavigationFrame->SetLabel("Navigation Window");
  this->ShowSelectionWindow = 0;
  this->ShowNavigationWindow = 1;

  this->NavigationWindowButton->StateOn();
  this->SelectionWindowButton->StateOff();
  if ( registery )
    {
    this->Application->SetRegisteryValue(2, "RunTime","SourcesBrowser",
                                         "NavigationWindow");
    }
}

//----------------------------------------------------------------------------
void vtkPVRenderView::ShowSelectionWindowCallback(int registery)
{
  if ( !this->Application )
    {
    return;
    }
  this->Script("catch {eval pack forget [pack slaves %s]}",
               this->NavigationFrame->GetFrame()->GetWidgetName());
  this->Script("pack %s -fill both -expand t -side top -anchor n", 
               this->SelectionWindow->GetWidgetName());
  this->NavigationFrame->SetLabel("Selection Window");
  this->ShowNavigationWindow = 0;
  this->ShowSelectionWindow = 1;

  this->NavigationWindowButton->StateOff();
  this->SelectionWindowButton->StateOn();
  if ( registery )
    {
    this->Application->SetRegisteryValue(2, "RunTime","SourcesBrowser",
                                         "SelectionWindow");
    }
}

//----------------------------------------------------------------------------
vtkPVRenderView::~vtkPVRenderView()
{
  this->InterfaceSettingsFrame->Delete();
  this->Display3DWidgets->Delete();
  this->Display3DWidgets = NULL;

  this->OrientationAxesFrame->Delete();
  this->OrientationAxesCheck->Delete();
  this->OrientationAxesInteractiveCheck->Delete();
  this->OrientationAxesOutlineColor->Delete();
  this->OrientationAxes->Delete();
  
  if ( this->SelectionWindow )
    {
    this->SelectionWindow->Delete();
    }
  this->SplitFrame->Delete();
  this->SplitFrame = NULL;
 
  this->NavigationFrame->Delete();
  this->NavigationFrame = NULL;
 
  this->NavigationWindowButton->Delete();
  this->SelectionWindowButton->Delete();

  this->NavigationWindow->Delete();
  this->NavigationWindow = NULL;

  if (this->RenderModuleUI)
    {
    this->RenderModuleUI->Delete();
    this->RenderModuleUI = NULL;
    }

  if (this->Renderer)
    {
    this->Renderer->UnRegister(this);
    this->Renderer = NULL;
    }
  
  this->Renderer2D->Delete();
  this->Renderer2D = NULL;
  
  if (this->RenderWindow)
    {
    this->RenderWindow->UnRegister(this);
    this->RenderWindow = NULL;
    }
  
  // undo the binding we set up
  if ( this->Application )
    {
    this->Script("bind %s <Motion> {}", this->VTKWidget->GetWidgetName());
    }
  if (this->RenderPending && this->Application )
    {
    this->Script("after cancel %s", this->RenderPending);
    }
  this->SetRenderPending(NULL);

  if (this->TopLevelRenderWindow)
    {
    this->TopLevelRenderWindow->Delete();
    this->TopLevelRenderWindow = NULL;
    }
  
  this->StandardViewsFrame->Delete();
  this->StandardViewsFrame = NULL;
  this->XMaxViewButton->Delete();
  this->XMaxViewButton = NULL;
  this->XMinViewButton->Delete();
  this->XMinViewButton = NULL;
  this->YMaxViewButton->Delete();
  this->YMaxViewButton = NULL;
  this->YMinViewButton->Delete();
  this->YMinViewButton = NULL;
  this->ZMaxViewButton->Delete();
  this->ZMaxViewButton = NULL;
  this->ZMinViewButton->Delete();
  this->ZMinViewButton = NULL;

  this->RenderParametersFrame->Delete();
  this->RenderParametersFrame = 0;

  this->ParallelProjectionCheck->Delete();
  this->ParallelProjectionCheck = NULL;

  this->TriangleStripsCheck->Delete();
  this->TriangleStripsCheck = NULL;

  this->ImmediateModeCheck->Delete();
  this->ImmediateModeCheck = NULL;


  this->ManipulatorControl2D->Delete();
  this->ManipulatorControl3D->Delete();

  this->CameraControlFrame->Delete();
  this->CameraControl->Delete();
  
  this->CameraIconsFrame->Delete();
  this->CameraIconsFrame = 0;
  int cc;
  for ( cc = 0; cc < 6; cc ++ )
    {
    if ( this->CameraIcons[cc] )
      {
      this->CameraIcons[cc]->SetRenderView(0);
      this->CameraIcons[cc]->Delete();
      this->CameraIcons[cc] = 0;
      }
    }
  this->Observer->Delete();

  this->PropertiesButton->Delete();
  this->PropertiesButton = NULL;
  this->SetMenuLabelSwitchBackAndForthToViewProperties(NULL);
  vtkTimerLog::CleanupLog();
}

//----------------------------------------------------------------------------
void PVRenderViewAbortCheck(vtkObject*, unsigned long, void* arg, void*)
{
  vtkPVRenderView *me = (vtkPVRenderView*)arg;
  int abort;

  // if we are printing then do not abort
  if (me->GetPrinting())
    {
    return;
    }
  
  abort = me->ShouldIAbort();
  if (abort == 1)
    {
    me->GetRenderWindow()->SetAbortRender(1);
    me->EventuallyRender();
    }
  if (abort == 2)
    {
    //("Abort 2");
    me->GetRenderWindow()->SetAbortRender(2);
    }
}

//----------------------------------------------------------------------------
void vtkPVRenderView::CreateRenderObjects(vtkPVApplication *pvApp)
{
  // Get rid of renderer created by the superclass
  this->Renderer->Delete();
  this->Renderer = pvApp->GetRenderModule()->GetRenderer();
  this->Renderer->Register(this);

  // Create the call back that looks for events to abort rendering.
  pvApp->GetRenderModule()->RemoveObservers(vtkCommand::AbortCheckEvent);
  vtkCallbackCommand* abc = vtkCallbackCommand::New();
  abc->SetCallback(PVRenderViewAbortCheck);
  abc->SetClientData(this);
  pvApp->GetRenderModule()->AddObserver(vtkCommand::AbortCheckEvent, abc);
  abc->Delete();

  // Get rid of render window created by the superclass
  this->RenderWindow->Delete();
  this->RenderWindow = pvApp->GetRenderModule()->GetRenderWindow();
  this->RenderWindow->Register(this);
  this->RenderWindow->AddRenderer(this->Renderer2D);
  this->RenderWindow->SetNumberOfLayers(3);
  this->Renderer2D->SetLayer(2);
  
  // the 2d renderer must be kept in sync with the main renderer
  this->Renderer->AddObserver(
    vtkCommand::StartEvent, this->Observer);  

  this->RenderWindow->AddObserver(
    vtkCommand::CursorChangedEvent, this->Observer);
}


//----------------------------------------------------------------------------
// Here we are going to change only the satellite procs.
void vtkPVRenderView::PrepareForDelete()
{
  vtkPVApplication* pvapp = this->GetPVApplication();
  if (pvapp)
    {
    pvapp->SetRegisteryValue(2, "RunTime", "UseParallelProjection", "%d",
                             this->ParallelProjectionCheck->GetState());
    pvapp->SetRegisteryValue(2, "RunTime", "UseStrips", "%d",
                             this->TriangleStripsCheck->GetState());
    pvapp->SetRegisteryValue(2, "RunTime", "UseImmediateMode", "%d",
                             this->ImmediateModeCheck->GetState());
    double *vp = this->OrientationAxes->GetViewport();
    pvapp->SetRegisteryValue(2, "RunTime", "OrientationAxesViewport",
                             "%lf %lf %lf %lf", vp[0], vp[1], vp[2], vp[3]);

    // If it's the last win, save the size of the nav frame

    if (pvapp->GetWindows()->GetNumberOfItems() <= 1 &&
        pvapp->GetSaveWindowGeometry())
      {
      pvapp->SetRegisteryValue(
        2, "Geometry", VTK_PV_NAV_FRAME_SIZE_REG_KEY, "%d", 
        this->SplitFrame->GetFrame1Size());
      }
    }

  // We must call prepare for delete on the RenderModule !!!!!!!


  // Circular reference.
  if ( this->ManipulatorControl2D )
    {
    this->ManipulatorControl2D->SetManipulatorCollection(0);
    }
  if ( this->ManipulatorControl3D )
    {
    this->ManipulatorControl3D->SetManipulatorCollection(0);
    }
  if ( this->SelectionWindow )
    {
    this->SelectionWindow->PrepareForDelete();
    this->SelectionWindow->Delete();
    this->SelectionWindow = 0;
    }
  int cc;
  for ( cc = 0; cc < 6; cc ++ )
    {
    if ( this->CameraIcons[cc] )
      {
      this->CameraIcons[cc]->SetRenderView(0);
      this->CameraIcons[cc]->Delete();
      this->CameraIcons[cc] = 0;
      }
    }
}


//----------------------------------------------------------------------------
void vtkPVRenderView::Close()
{
  this->PrepareForDelete();
  vtkKWView::Close();
}  


//----------------------------------------------------------------------------
vtkRenderer *vtkPVRenderView::GetRenderer()
{
  return this->Renderer;
}

//----------------------------------------------------------------------------
vtkRenderWindow *vtkPVRenderView::GetRenderWindow()
{
  return this->RenderWindow;
}

//----------------------------------------------------------------------------
void vtkPVRenderView::Create(vtkKWApplication *app, const char *args)
{
  char *local;
  const char *wname;
  
  local = new char [strlen(args)+100];

  if (this->Application)
    {
    vtkErrorMacro("RenderView already created");
    return;
    }
  
  // Must set the application

  if (this->Application)
    {
    vtkErrorMacro("RenderView already created");
    return;
    }
  this->SetApplication(app);



  // Create the frames

  wname = this->GetWidgetName();
  this->Script("frame %s -bd 0 %s",wname,args);

  this->Frame->Create(app,"frame","-bd 3 -relief ridge");
  this->Script("pack %s -expand yes -fill both -side top -anchor nw",
               this->Frame->GetWidgetName());

  this->Frame2->Create(app,"frame","-bd 0");
  this->Script("pack %s -fill x -side top -anchor nw",
               this->Frame2->GetWidgetName());

  this->Label->Create(app,"label","-fg #fff -text {3D View} -bd 0");

  this->Script("pack %s -side left -anchor w",
               this->Label->GetWidgetName());

  this->Script("bind %s <Any-ButtonPress> {%s MakeSelected}",
               this->Label->GetWidgetName(), this->GetTclName());

  // Properties button

  this->PropertiesButton->SetParent(this->Label->GetParent());
  // The -bg color is hardcoded here since the real -bg of the frame is
  // changed when it's active (it's not active at the moment). But inside
  // paraview tehre is only one view, and it's always active, so use the
  // active color.
  this->PropertiesButton->Create(
    app, "-bd 0 -bg #008 -padx 0 -pady 0 -highlightthickness 0 -relief flat");
  this->PropertiesButton->SetCommand(this, "SwitchBackAndForthToViewProperties");
  this->PropertiesButton->SetBalloonHelpString(
    "Switch back and forth between the current view properties and the" 
    VTK_PV_VIEW_MENU_LABEL ".");

  this->PropertiesButton->SetImageOption(image_properties, 
                                         image_properties_width, 
                                         image_properties_height, 
                                         image_properties_pixel_size,
                                         image_properties_buffer_length);

  this->Script("pack %s %s -side left -anchor w -padx 2",
               this->Label->GetWidgetName(),
               this->PropertiesButton->GetWidgetName());

  this->Script("bind %s <Any-ButtonPress> {%s MakeSelected}",
               this->Frame2->GetWidgetName(), this->GetTclName());

  // Create the control frame - only pack it if support option enabled

  this->ControlFrame->Create(app,"frame","-bd 0");
  if (this->SupportControlFrame)
    {
    this->Script("pack %s -expand t -fill both -side top -anchor nw",
                 this->ControlFrame->GetWidgetName());
    }
  
  // Separate window for the renderer.

  if (getenv("PV_SEPARATE_RENDER_WINDOW") != NULL)
    {
    this->TopLevelRenderWindow->Create(app, "toplevel", "");
    this->Script("wm title %s %s", 
                 this->TopLevelRenderWindow->GetWidgetName(),
                 this->Application->GetApplicationName());
    }

  // Add the -rw argument

  sprintf(local,"%s -rw Addr=%p",args,this->RenderWindow);
  this->Script("vtkTkRenderWidget %s %s",
               this->VTKWidget->GetWidgetName(),local);

  this->Script("pack %s -expand yes -fill both -side top -anchor nw",
               this->VTKWidget->GetWidgetName());
  
  // Expose

  this->Script("bind %s <Expose> {%s Exposed}", 
               this->GetTclName(), this->GetTclName());

  // Configure

  this->Script("bind %s <Configure> {%s Configured}", 
               this->GetTclName(), this->GetTclName());

  // Configure the split frame

  this->SplitFrame->SetParent(this->GetPropertiesParent());
  this->SplitFrame->SetOrientationToVertical();
  this->SplitFrame->SetSeparatorSize(5);
  this->SplitFrame->SetFrame1MinimumSize(80);

  if (this->Application->GetSaveWindowGeometry() &&
      this->Application->HasRegisteryValue(
        2, "Geometry", VTK_PV_NAV_FRAME_SIZE_REG_KEY))
    {
    this->SplitFrame->SetFrame1Size(
      this->Application->GetIntRegisteryValue(
        2, "Geometry", VTK_PV_NAV_FRAME_SIZE_REG_KEY));
    }
  else
    {
    this->SplitFrame->SetFrame1Size(80);
    }

  this->SplitFrame->Create(this->Application);

  this->Script("pack %s -fill both -expand t -side top", 
               this->SplitFrame->GetWidgetName());

  // Configure the navigation frame

  this->NavigationFrame->SetParent(this->SplitFrame->GetFrame1());
  this->NavigationFrame->ShowHideFrameOff();
  this->NavigationFrame->Create(this->Application, 0);
  this->NavigationFrame->SetLabel("Navigation");
  this->Script("pack %s -fill both -expand t -side top", 
               this->NavigationFrame->GetWidgetName());

  // Configure the navigation window

  this->NavigationWindow->SetParent(this->NavigationFrame->GetFrame());
  this->NavigationWindow->SetWidth(341);
  this->NavigationWindow->SetHeight(545);
  this->NavigationWindow->Create(this->Application, 0); 

  // Configure the selection window

  this->SelectionWindow->SetParent(this->NavigationFrame->GetFrame());
  this->SelectionWindow->SetWidth(341);
  this->SelectionWindow->SetHeight(545);
  this->SelectionWindow->Create(this->Application, 0); 

  this->SelectionWindowButton->SetParent(
    this->NavigationFrame->GetLabelFrame());
  this->SelectionWindowButton->Create(
    this->Application, 
    "-indicatoron 0 -highlightthickness 0 -image PVSelectionWindowButton "
    "-selectimage PVSelectionWindowButton");
  this->SelectionWindowButton->SetBalloonHelpString(
    "Switch to selection window mode.");
  this->SelectionWindowButton->SetCommand(
    this, "ShowSelectionWindowCallback 1");
  
  this->NavigationWindowButton->SetParent(
    this->NavigationFrame->GetLabelFrame());
  this->NavigationWindowButton->Create(
    this->Application, 
    "-indicatoron 0 -highlightthickness 0 -image PVNavigationWindowButton "
    "-selectimage PVNavigationWindowButton");
  this->NavigationWindowButton->SetBalloonHelpString(
    "Switch to navigation window mode.");
  this->NavigationWindowButton->SetCommand(
    this, "ShowNavigationWindowCallback 1");

  this->Script("pack %s %s -side left -anchor w -before %s -padx 1",
               this->SelectionWindowButton->GetWidgetName(),
               this->NavigationWindowButton->GetWidgetName(),
               this->NavigationFrame->GetLabel()->GetWidgetName());

  if (this->Application->HasRegisteryValue(2, "RunTime", "SourcesBrowser"))
    {
    if (this->Application->BooleanRegisteryCheck(2, "RunTime", 
                                                 "SourcesBrowser",
                                                 "SelectionWindow"))
      {
      this->ShowSelectionWindowCallback(0);
      }
    else
      {
      this->ShowNavigationWindowCallback(0);
      }
    }
  else
    {
    this->ShowSelectionWindowCallback(0);
    }

  this->SetSourcesBrowserAlwaysShowName(
    this->GetPVApplication()->GetSourcesBrowserAlwaysShowName());

  this->EventuallyRender();
  delete [] local;
}

//----------------------------------------------------------------------------
void vtkPVRenderView::SwitchBackAndForthToViewProperties()
{
  vtkKWWindow *win = this->GetPVWindow();
  if (!win)
    {
    return;
    }

  vtkKWMenu *viewmenu = win->GetMenuView();
  if (!viewmenu)
    {
    return;
    }

  if (!viewmenu->HasItem(VTK_PV_VIEW_MENU_LABEL))
    {
    return;
    }
  int prop_position = viewmenu->GetIndex(VTK_PV_VIEW_MENU_LABEL);

  // First check where we are in the view menu

  int position = viewmenu->GetCheckedRadioButtonItem(viewmenu, "Radio");
  if (position < 0)
    {
    return;
    }

  // Now if we are not in the view prop, save the old pos and go to it
  // otherwise restore the old one

  if (position != prop_position)
    {
    this->SetMenuLabelSwitchBackAndForthToViewProperties(this->Script(
      "%s entrycget %d -label", viewmenu->GetWidgetName(), position));
    viewmenu->Invoke(prop_position);
    }
  else
    {
    if (this->MenuLabelSwitchBackAndForthToViewProperties &&
        viewmenu->HasItem(this->MenuLabelSwitchBackAndForthToViewProperties))
      {
      // This entry of the view menu must be in "normal" state to switch
      // between source and 3D views.
      int state = viewmenu->GetState(this->MenuLabelSwitchBackAndForthToViewProperties);
      viewmenu->SetState(this->MenuLabelSwitchBackAndForthToViewProperties,
                         vtkKWMenu::Normal);
      viewmenu->Invoke(
        viewmenu->GetIndex(this->MenuLabelSwitchBackAndForthToViewProperties));
      viewmenu->SetState(this->MenuLabelSwitchBackAndForthToViewProperties,
                         state);
      }
    }
}

//----------------------------------------------------------------------------
vtkKWWidget *vtkPVRenderView::GetSourceParent()
{
  return this->SplitFrame->GetFrame2();
}

//----------------------------------------------------------------------------
void vtkPVRenderView::Display3DWidgetsCallback()
{
  int val = this->Display3DWidgets->GetState();
  this->SetDisplay3DWidgets(val);
  this->Application->SetRegisteryValue(2, "RunTime","Display3DWidgets",
                                      (val?"1":"0"));
}

//----------------------------------------------------------------------------
void vtkPVRenderView::SetDisplay3DWidgets(int s)
{
  this->Display3DWidgets->SetState(s);
  this->GetPVApplication()->SetDisplay3DWidgets(s);
}

//----------------------------------------------------------------------------
void vtkPVRenderView::SetSourcesBrowserAlwaysShowName(int s)
{
  if (this->NavigationWindow)
    {
    this->NavigationWindow->SetAlwaysShowName(s);
    }
  if (this->SelectionWindow)
    {
    this->SelectionWindow->SetAlwaysShowName(s);
    }
}

//----------------------------------------------------------------------------
void vtkPVRenderView::CreateViewProperties()
{
  this->vtkKWView::CreateViewProperties();

  this->BackgroundColor->SetBalloonHelpString("Change the background color of the 3D View window");

  vtkPVWindow* pvwindow = this->GetPVWindow();
  vtkPVApplication* pvapp = this->GetPVApplication();

  // Render parameters

  this->RenderParametersFrame->SetParent(this->GeneralProperties->GetFrame());
  this->RenderParametersFrame->ShowHideFrameOn();
  this->RenderParametersFrame->Create(this->Application,0);
  this->RenderParametersFrame->SetLabel("Advanced Render Parameters");
  this->Script("pack %s -padx 2 -pady 2 -fill x -expand yes -anchor w",
               this->RenderParametersFrame->GetWidgetName());

  // Render parameters: parallel projection

  this->ParallelProjectionCheck->SetParent(
    this->RenderParametersFrame->GetFrame());
  this->ParallelProjectionCheck->Create(this->Application, "");
  this->ParallelProjectionCheck->SetText("Use parallel projection");
  if (pvapp && pvwindow && 
      pvapp->GetRegisteryValue(2, "RunTime", "UseParallelProjection", 0))
    {
    this->ParallelProjectionCheck->SetState(
      pvwindow->GetIntRegisteryValue(2, "RunTime", "UseParallelProjection"));
    this->ParallelProjectionCallback();
    }
  else
    {
    this->ParallelProjectionCheck->SetState(0);
    }
  this->ParallelProjectionCheck->SetCommand(this, 
                                            "ParallelProjectionCallback");
  this->ParallelProjectionCheck->SetBalloonHelpString(
    "Toggle the use of parallel projection "
    "(if parallel project is off, perspective projection is used).");
  
  // Render parameters: triangle strips

  this->TriangleStripsCheck->SetParent(
    this->RenderParametersFrame->GetFrame());
  this->TriangleStripsCheck->Create(this->Application, "");
  this->TriangleStripsCheck->SetText("Use triangle strips");
  if (pvapp && pvwindow && 
      pvapp->GetRegisteryValue(2, "RunTime", "UseStrips", 0))
    {
    this->TriangleStripsCheck->SetState(
      pvwindow->GetIntRegisteryValue(2, "RunTime", "UseStrips"));
    }
  else
    {
    this->TriangleStripsCheck->SetState(0);
    }
  this->TriangleStripsCheck->SetCommand(this, "TriangleStripsCallback");
  this->TriangleStripsCheck->SetBalloonHelpString(
    "If this option is chosen, all triangles are converted into triangle "
    "strips before rendering. This may improve the rendering perfermance.");
  
  // Render parameters: immediate mode

  this->ImmediateModeCheck->SetParent(this->RenderParametersFrame->GetFrame());
  this->ImmediateModeCheck->Create(this->Application, 
                                   "-text \"Use immediate mode rendering\"");
  this->ImmediateModeCheck->SetCommand(this, "ImmediateModeCallback");
  if (pvapp && pvwindow && 
      pvapp->GetRegisteryValue(2, "RunTime", "UseImmediateMode", 0))
    {
    this->ImmediateModeCheck->SetState(
      pvwindow->GetIntRegisteryValue(2, "RunTime", "UseImmediateMode"));
    }
  else
    {
    this->ImmediateModeCheck->SetState(1);
    }
  this->ImmediateModeCheck->SetBalloonHelpString(
    "When this option is off, OpenGL display lists are used when rendering."
    "Using display lists improves performance for small datasets "
    "but is not recommended for large datasets due to excessive memory "
    "usage and long display list creating times.");

  // Render parameters: pack

  this->Script("pack %s %s %s -side top -anchor w",
               this->ParallelProjectionCheck->GetWidgetName(),
               this->TriangleStripsCheck->GetWidgetName(),
               this->ImmediateModeCheck->GetWidgetName());

  // Create the render module user interface.
  char* rmuiClassName;
  rmuiClassName = new char[strlen(pvapp->GetRenderModuleName()) + 20];
  sprintf(rmuiClassName, "vtkPV%sUI", pvapp->GetRenderModuleName());
  vtkObject* rmui = vtkInstantiator::CreateInstance(rmuiClassName);
  vtkPVRenderModuleUI* rmuio = vtkPVRenderModuleUI::SafeDownCast(rmui);
  if ( rmuio )
    {
    this->RenderModuleUI = rmuio;
    this->RenderModuleUI->SetRenderModule(pvapp->GetRenderModule());
    this->RenderModuleUI->SetParent(this->GeneralProperties->GetFrame());
    this->RenderModuleUI->Create(this->Application,0);
    this->RenderModuleUI->SetTraceReferenceObject(this);
    this->RenderModuleUI->SetTraceReferenceCommand("GetRenderModuleUI");
    this->Script("pack %s -padx 2 -pady 2 -fill x -expand yes -anchor w",
      this->RenderModuleUI->GetWidgetName());
    }
  else
    {
    this->RenderModuleUI = 0;
    }
  delete [] rmuiClassName;
  rmuiClassName = NULL;

  // Interface settings

  this->InterfaceSettingsFrame->SetParent(this->GeneralProperties->GetFrame());
  this->InterfaceSettingsFrame->ShowHideFrameOn();
  this->InterfaceSettingsFrame->Create(this->Application,0);
  this->InterfaceSettingsFrame->SetLabel("3D Interface Settings");
  this->Script("pack %s -padx 2 -pady 2 -fill x -expand yes -anchor w",
               this->InterfaceSettingsFrame->GetWidgetName());

  // Interface settings: 3D widgets

  this->Display3DWidgets->SetParent(
    this->InterfaceSettingsFrame->GetFrame());
  this->Display3DWidgets->Create(this->Application, 0);
  this->Display3DWidgets->SetText("Display 3D widgets automatically");
  this->Display3DWidgets->SetBalloonHelpString(
    "When this advanced option is on, all 3D widgets (manipulators) are "
    "visible when created. Turn this off to avoid unnecessary "
    "renders when working with large data and not using 3D widgets "
    "to adjust parameters.");
  this->Display3DWidgets->SetCommand(this, "Display3DWidgetsCallback");

  if (!this->Application->GetRegisteryValue(2,"RunTime","Display3DWidgets",0)||
    this->GetPVWindow()->GetIntRegisteryValue(2,"RunTime","Display3DWidgets"))
    {
    this->SetDisplay3DWidgets(1);
    }
  else
    {
    this->SetDisplay3DWidgets(0);
    }
  
  // Interface settings: pack

  this->Script("pack %s -side top -padx 2 -pady 2 -anchor w",
               this->Display3DWidgets->GetWidgetName());

  // Orientation axes settings
  
  this->OrientationAxesFrame->SetParent(this->AnnotationProperties->GetFrame());
  this->OrientationAxesFrame->ShowHideFrameOn();
  this->OrientationAxesFrame->Create(this->Application, 0);
  this->OrientationAxesFrame->SetLabel("Orientation Axes");
  this->Script("pack %s -padx 2 -pady 2 -fill x -expand yes -anchor w",
               this->OrientationAxesFrame->GetWidgetName());
  
  // Orientation axes settings: visibility check
  
  this->OrientationAxesCheck->SetParent(this->OrientationAxesFrame->GetFrame());
  this->OrientationAxesCheck->Create(this->Application, 0);
  this->OrientationAxesCheck->SetText("Display orientation axes");
  this->OrientationAxesCheck->SetCommand(this, "OrientationAxesCheckCallback");
  if (pvapp && pvwindow &&
      pvapp->GetRegisteryValue(2, "RunTime", "OrientationAxesVisibility", 0))
    {
    this->OrientationAxesCheck->SetState(
      pvwindow->GetIntRegisteryValue(2, "RunTime", "OrientationAxesVisibility"));
    this->OrientationAxesCheckCallback();
    }
  else
    {
    this->OrientationAxesCheck->SetState(0);
    }
  
  // Orientation axes settings: interactive check
  
  this->OrientationAxesInteractiveCheck->SetParent(
    this->OrientationAxesFrame->GetFrame());
  this->OrientationAxesInteractiveCheck->Create(this->Application, 0);
  this->OrientationAxesInteractiveCheck->SetText("Interactive");
  this->OrientationAxesInteractiveCheck->SetCommand(this, "OrientationAxesInteractiveCallback");
  if (pvapp && pvwindow &&
      pvapp->GetRegisteryValue(2, "RunTime", "OrientationAxesInteractivity", 0))
    {
    this->OrientationAxesInteractiveCheck->SetState(
      pvwindow->GetIntRegisteryValue(2, "RunTime", "OrientationAxesInteractivity"));
    }
  else
    {
    this->OrientationAxesInteractiveCheck->SetState(1);
    }
  
  this->OrientationAxesInteractiveCallback();
  
  // Orientation axes settings: outline color
  
  this->OrientationAxesOutlineColor->SetParent(
    this->OrientationAxesFrame->GetFrame());
  this->OrientationAxesOutlineColor->SetText("Set Outline Color");
  this->OrientationAxesOutlineColor->Create(this->Application, 0);
  this->OrientationAxesOutlineColor->SetCommand(this, "SetOrientationAxesOutlineColor");
  float rgb[3];
  if (pvapp && pvwindow)
    {
    pvwindow->RetrieveColor(2, "OrientationAxesOutline", rgb);
    if (rgb[0] == -1)
      {
      rgb[0] = 1.0;
      rgb[1] = 1.0;
      rgb[2] = 1.0;
      }
    }
  else
    {
    rgb[0] = 1.0;
    rgb[1] = 1.0;
    rgb[2] = 1.0;
    }
  this->SetOrientationAxesOutlineColor(rgb[0], rgb[1], rgb[2]);
    
  // Orientation axes settings: pack
  
  this->Script("pack %s %s -padx 2 -side top -anchor w",
               this->OrientationAxesCheck->GetWidgetName(),
               this->OrientationAxesInteractiveCheck->GetWidgetName());
  this->Script("pack %s -padx 2 -fill x -side top -anchor w",
               this->OrientationAxesOutlineColor->GetWidgetName());

  // Orientation axes widget
  
  this->OrientationAxes->SetParentRenderer(this->Renderer);

  char buffer[1024];
  double vp[4];
  if (pvapp && pvwindow &&
      pvapp->GetRegisteryValue(2, "RunTime", "OrientationAxesViewport", buffer))
    {
    if (*buffer)
      {
      sscanf(buffer, "%lf %lf %lf %lf", vp, vp+1, vp+2, vp+3);
      this->OrientationAxes->SetViewport(vp[0], vp[1], vp[2], vp[3]);
      }
    else
      {
      this->OrientationAxes->SetViewport(0, 0, 0.2, 0.2);
      }
    }
  else
    {
    this->OrientationAxes->SetViewport(0, 0, 0.2, 0.2);
    }
  
  // Camera settings

  this->Notebook->AddPage("Camera", 
                          "Camera and viewing navigation properties page");
  vtkKWWidget* page = this->Notebook->GetFrame("Camera");

  vtkKWFrame* frame = vtkKWFrame::New();
  frame->SetParent(page);
  frame->ScrollableOn();
  frame->Create(this->Application,0);
  this->Script("pack %s -fill both -expand yes", frame->GetWidgetName());

  // Camera: standard views

  this->StandardViewsFrame->SetParent( frame->GetFrame() );
  this->StandardViewsFrame->ShowHideFrameOn();
  this->StandardViewsFrame->Create(this->Application, 0);
  this->StandardViewsFrame->SetLabel("Standard Views");

  const char *views_grid_settings = " -padx 1 -pady 1 -ipadx 5 -sticky ew";

  this->XMaxViewButton->SetParent(this->StandardViewsFrame->GetFrame());
  this->XMaxViewButton->SetLabel("+X");
  this->XMaxViewButton->Create(this->Application, "");
  this->XMaxViewButton->SetCommand(this, "StandardViewCallback 1 0 0");
  this->XMaxViewButton->SetBalloonHelpString(
    "Looking down X axis from (1,0,0)");
  this->Script("grid configure %s -column 0 -row 0 %s",
               this->XMaxViewButton->GetWidgetName(), views_grid_settings);

  this->XMinViewButton->SetParent(this->StandardViewsFrame->GetFrame());
  this->XMinViewButton->SetLabel("-X");
  this->XMinViewButton->Create(this->Application, "");
  this->XMinViewButton->SetCommand(this, "StandardViewCallback -1 0 0");
  this->XMinViewButton->SetBalloonHelpString(
    "Looking down X axis from (-1,0,0)");
  this->Script("grid configure %s -column 0 -row 1 %s",
               this->XMinViewButton->GetWidgetName(), views_grid_settings);

  this->YMaxViewButton->SetParent(this->StandardViewsFrame->GetFrame());
  this->YMaxViewButton->SetLabel("+Y");
  this->YMaxViewButton->Create(this->Application, "");
  this->YMaxViewButton->SetCommand(this, "StandardViewCallback 0 1 0");
  this->YMaxViewButton->SetBalloonHelpString(
    "Looking down Y axis from (0,1,0)");
  this->Script("grid configure %s -column 1 -row 0 %s",
               this->YMaxViewButton->GetWidgetName(), views_grid_settings);

  this->YMinViewButton->SetParent(this->StandardViewsFrame->GetFrame());
  this->YMinViewButton->SetLabel("-Y");
  this->YMinViewButton->Create(this->Application, "");
  this->YMinViewButton->SetCommand(this, "StandardViewCallback 0 -1 0");
  this->YMinViewButton->SetBalloonHelpString(
    "Looking down Y axis from (0,-1,0)");
  this->Script("grid configure %s -column 1 -row 1 %s",
               this->YMinViewButton->GetWidgetName(), views_grid_settings);

  this->ZMaxViewButton->SetParent(this->StandardViewsFrame->GetFrame());
  this->ZMaxViewButton->SetLabel("+Z");
  this->ZMaxViewButton->Create(this->Application, "");
  this->ZMaxViewButton->SetCommand(this, "StandardViewCallback 0 0 1");
  this->ZMaxViewButton->SetBalloonHelpString(
    "Looking down Z axis from (0,0,1)");
  this->Script("grid configure %s -column 2 -row 0 %s",
               this->ZMaxViewButton->GetWidgetName(), views_grid_settings);

  this->ZMinViewButton->SetParent(this->StandardViewsFrame->GetFrame());
  this->ZMinViewButton->SetLabel("-Z");
  this->ZMinViewButton->Create(this->Application, "");
  this->ZMinViewButton->SetCommand(this, "StandardViewCallback 0 0 -1");
  this->ZMinViewButton->SetBalloonHelpString(
    "Looking down Z axis from (0,0,-1)");
  this->Script("grid configure %s -column 2 -row 1 %s",
               this->ZMinViewButton->GetWidgetName(), views_grid_settings);

  // Camera: stored camera position

  int cc;
  this->CameraIconsFrame->SetParent(frame->GetFrame());
  this->CameraIconsFrame->ShowHideFrameOn();
  this->CameraIconsFrame->Create(this->Application, 0);
  this->CameraIconsFrame->SetLabel("Stored Camera Positions");

  vtkKWWidget* cframe = this->CameraIconsFrame->GetFrame();
  for ( cc = 0; cc < 6; cc ++ )
    {
    int x, y;
    this->CameraIcons[cc]->SetRenderView(this);
    this->CameraIcons[cc]->SetParent(cframe);
    this->CameraIcons[cc]->Create(this->Application, "");

    x = cc % 3;
    y = cc / 3;

    this->Script("grid configure %s -column %d -row %d "
                 "-padx 1 -pady 1 -ipadx 0 -ipady 0 -sticky news",
                 this->CameraIcons[cc]->GetWidgetName(),
                 x, y);
                 
    }

  // Camera: manipulators

  this->ManipulatorControl2D->SetParent(frame->GetFrame());
  this->ManipulatorControl2D->Create(pvapp, 0);
  this->ManipulatorControl2D->SetLabel("2D Movements");
  this->ManipulatorControl2D->SetTraceReferenceObject(this);
  this->ManipulatorControl2D->SetTraceReferenceCommand("GetManipulatorControl2D");
  
  this->ManipulatorControl3D->SetParent(frame->GetFrame());
  this->ManipulatorControl3D->Create(pvapp, 0);
  this->ManipulatorControl3D->SetLabel("3D Movements");
  this->ManipulatorControl3D->SetTraceReferenceObject(this);
  this->ManipulatorControl3D->SetTraceReferenceCommand("GetManipulatorControl3D");
  
  // Camera: camera control frame

  this->CameraControlFrame->SetParent(frame->GetFrame());
  this->CameraControlFrame->ShowHideFrameOn();
  this->CameraControlFrame->Create(this->Application, 0);
  this->CameraControlFrame->SetLabel("Camera Control");
  
  // Camera: camera control
  
  this->CameraControl->SetParent(this->CameraControlFrame->GetFrame());
  this->CameraControl->Create(this->Application, 0);
  this->CameraControl->SetInteractorStyle(this->GetPVWindow()->GetCenterOfRotationStyle());
  this->CameraControl->SetRenderView(this);
  this->CameraControl->SetTraceReferenceObject(this);
  this->CameraControl->SetTraceReferenceCommand("GetCameraControl");
  
  this->Script("pack %s -side top -fill x -expand y", this->CameraControl->GetWidgetName());
  
  // Camera: pack

  this->Script("pack %s %s %s %s %s -padx 2 -pady 2 -fill x -expand 1 -anchor w",
               this->StandardViewsFrame->GetWidgetName(),
               this->CameraIconsFrame->GetWidgetName(),
               this->ManipulatorControl2D->GetWidgetName(),
               this->ManipulatorControl3D->GetWidgetName(),
               this->CameraControlFrame->GetWidgetName());

  frame->Delete();

  this->Notebook->Raise("General");
}

//----------------------------------------------------------------------------
void vtkPVRenderView::StandardViewCallback(float x, float y, float z)
{
  this->AddTraceEntry("$kw(%s) StandardViewCallback %f %f %f",
                      this->GetTclName(), x, y, z);
  
  vtkCamera *cam = this->Renderer->GetActiveCamera();
  cam->SetFocalPoint(0.0, 0.0, 0.0);
  cam->SetPosition(x, y, z);
  if (y == 0.0)
    {
    cam->SetViewUp(0.0, 1.0, 0.0);
    }
  else
    {
    cam->SetViewUp(1.0, 0.0, 0.0);
    }

  this->ResetCamera();
  this->EventuallyRender();
}

//----------------------------------------------------------------------------
void vtkPVRenderView::UpdateNavigationWindow(vtkPVSource *currentSource, 
                                             int nobind)
{
  if (this->NavigationWindow)
    {
    this->NavigationWindow->SetCreateSelectionBindings(!nobind);
    this->NavigationWindow->Update(currentSource);
    }
  if (this->SelectionWindow)
    {
    this->SelectionWindow->SetCreateSelectionBindings(!nobind);
    this->SelectionWindow->Update(currentSource);
    }
}

//----------------------------------------------------------------------------
void vtkPVRenderView::SetBackgroundColor(double r, double g, double b)
{
  vtkPVApplication *pvApp = this->GetPVApplication();
  
  // Set the color of the interface button.
  this->BackgroundColor->SetColor(r, g, b);
  // Since setting the color of the button from a script does
  // not invoke the callback, We also trace the view.
  this->AddTraceEntry("$kw(%s) SetBackgroundColor %f %f %f",
                      this->GetTclName(), r, g, b);
  pvApp->GetRenderModule()->SetBackgroundColor(r, g, b);
  this->EventuallyRender();
}

//----------------------------------------------------------------------------
// a litle more complex than just "bind $widget <Expose> {%W Render}"
// we have to handle all pending expose events otherwise they que up.
void vtkPVRenderView::Exposed()
{  
  if (this->InExpose)
    {
    return;
    }
  this->InExpose = 1;
  this->Script("update");
  this->EventuallyRender();
  this->InExpose = 0;
}

//----------------------------------------------------------------------------
// called on Configure event. Configure events might not generate an
// expose event if the size of the view gets smaller.
// At the moment, just call Exposed(), which does what we want to do,
// i.e. eventually render. If an Expose event was also generated after
// that Configure event, it will be discard because of the InExpose ivar
// logic (see above)
void vtkPVRenderView::Configured()
{
  vtkPVRenderModule* rm = this->GetPVApplication()->GetRenderModule();
  if (rm)
    {
    rm->InteractiveRender();
    }
}


//----------------------------------------------------------------------------
void vtkPVRenderView::ResetCamera()
{
  double bds[6];


  this->GetPVApplication()->GetRenderModule()->ComputeVisiblePropBounds(bds);
  if (bds[0] <= bds[1] && bds[2] <= bds[3] && bds[4] <= bds[5])
    {
    this->GetRenderer()->ResetCamera(bds);
    }
}

//----------------------------------------------------------------------------
void vtkPVRenderView::SetCameraState(float p0, float p1, float p2,
                                     float fp0, float fp1, float fp2,
                                     float up0, float up1, float up2)
{
  vtkCamera *cam; 
  
  // This is to trace effects of loaded scripts. 
  this->AddTraceEntry(
    "$kw(%s) SetCameraState %.3f %.3f %.3f  %.3f %.3f %.3f  %.3f %.3f %.3f", 
    this->GetTclName(), p0, p1, p2, fp0, fp1, fp2, up0, up1, up2); 
  
  cam = this->GetRenderer()->GetActiveCamera(); 
  cam->SetPosition(p0, p1, p2); 
  cam->SetFocalPoint(fp0, fp1, fp2); 
  cam->SetViewUp(up0, up1, up2); 
  
  this->EventuallyRender(); 
}

//----------------------------------------------------------------------------
void vtkPVRenderView::AddBindings()
{
  this->Script("bind %s <Motion> {%s MotionCallback %%x %%y}",
               this->VTKWidget->GetWidgetName(), this->GetTclName());
}
    
//----------------------------------------------------------------------------
vtkPVApplication* vtkPVRenderView::GetPVApplication()
{
  if (this->Application == NULL)
    {
    return NULL;
    }
  
  if (this->Application->IsA("vtkPVApplication"))
    {  
    return (vtkPVApplication*)(this->Application);
    }
  else
    {
    vtkErrorMacro("Bad typecast");
    return NULL;
    } 
}



//----------------------------------------------------------------------------
void vtkPVRenderView::Render()
{
  int abort;

  // Some aborts require us to que another render.
  abort = this->ShouldIAbort();
  if (abort)
    {
    if (abort == 1)
      {
      this->EventuallyRender();
      }
    return;
    }

  vtkPVRenderModule* rm = this->GetPVApplication()->GetRenderModule();
  if (rm)
    {
    rm->InteractiveRender();
    }
}





//----------------------------------------------------------------------------
// There are a couple of ways I could do this.
// I could allow eventually render callback to occur
// and abort the render using the disable rendering flag ...
void vtkPVRenderView::UpdateTclButAvoidRendering()
{
  int saveRender = 0;

  // Remove any pending renders.
  if (this->RenderPending && this->Application )
    {
    saveRender = 1;
    this->Script("after cancel %s", this->RenderPending);
    this->SetRenderPending(NULL);
    // This flag is not necessary.  We should just use render pending ivar.
    this->EventuallyRenderFlag = 0;
    }

  this->Script("update");

  // Add render pending back.
  if (saveRender)
    {
    this->EventuallyRender();
    }
}




//----------------------------------------------------------------------------
void vtkPVRenderView::EventuallyRender()
{
  if (this->EventuallyRenderFlag)
    {
    return;
    }
  this->EventuallyRenderFlag = 1;
  //cout << "EventuallyRender()" << endl;

  // Keep track of whether there is a render pending so that if a render is
  // pending when this object is deleted, we can cancel the "after" command.
  // We don't want to have this object register itself because this can
  // cause leaks if we exit before EventuallyRenderCallBack is called.
  this->Script("update idletasks");
  this->Script("after idle {%s EventuallyRenderCallBack}",this->GetTclName());
  this->SetRenderPending(this->Application->GetMainInterp()->result);

}
                      
//----------------------------------------------------------------------------
void vtkPVRenderView::EventuallyRenderCallBack()
{
  int abort;

  vtkPVApplication *pvApp = this->GetPVApplication();

  // sanity check
  if (this->EventuallyRenderFlag == 0 || !this->RenderPending)
    {
    vtkErrorMacro("Inconsistent EventuallyRenderFlag");
    return;
    }
  // We could get rid of the flag and use the pending ivar.
  this->EventuallyRenderFlag = 0;
  this->SetRenderPending(NULL);

  // I do not know if these are necessary here.
  abort = this->ShouldIAbort();
  if (abort)
    {
    if (abort == 1)
      {
      this->EventuallyRender();
      }
    return;
    }

  pvApp->SetGlobalLODFlag(0);
  pvApp->GetRenderModule()->StillRender();
}

//----------------------------------------------------------------------------
void vtkPVRenderView::TriangleStripsCallback()
{
  if (this->TriangleStripsCheck->GetState())
    {
    vtkTimerLog::MarkEvent("--- Enable triangle strips.");
    }
  else
    {
    vtkTimerLog::MarkEvent("--- Disable triangle strips.");
    }

  this->SetUseTriangleStrips(this->TriangleStripsCheck->GetState());
}

//----------------------------------------------------------------------------
void vtkPVRenderView::SetUseTriangleStrips(int state)
{
  vtkPVWindow *pvWin;
  vtkPVSourceCollection *sources;
  vtkPVSource *pvs;
  vtkPVApplication *pvApp;
  int numParts, partIdx;

  this->AddTraceEntry("$kw(%s) SetUseTriangleStrips %d", this->GetTclName(),
                      state);

  if (this->TriangleStripsCheck->GetState() != state)
    {
    this->TriangleStripsCheck->SetState(state);
    }
  
  if ( ! this->ImmediateModeCheck->GetState() && ! state)
    { // Make sure immediate mode is on when strips are off.
    this->SetUseImmediateMode(1);
    }

  pvApp = this->GetPVApplication();
  pvWin = this->GetPVWindow();
  if (pvWin == NULL)
    {
    vtkErrorMacro("Missing window.");
    return;
    }
  sources = pvWin->GetSourceList("Sources");
  
  sources->InitTraversal();
  while ( (pvs = sources->GetNextPVSource()) )
    {
    numParts = pvs->GetNumberOfParts();
    for (partIdx = 0; partIdx < numParts; ++partIdx)
      {
      vtkPVProcessModule* pm = pvApp->GetProcessModule();
      vtkClientServerStream& stream = pm->GetStream();
      stream << vtkClientServerStream::Invoke << pvs->GetPart(partIdx)->GetGeometryID()
             <<  "SetUseStrips" << state << vtkClientServerStream::End;
      pm->SendStreamToServer();
      pvs->GetPart(partIdx)->GetPartDisplay()->InvalidateGeometry();
      }
    }

  this->EventuallyRender();
}

//----------------------------------------------------------------------------
void vtkPVRenderView::ParallelProjectionOn()
{
  this->AddTraceEntry("$kw(%s) ParallelProjectionOn", this->GetTclName());

  if (!this->ParallelProjectionCheck->GetState())
    {
    this->ParallelProjectionCheck->SetState(1);
    }
  this->Renderer->GetActiveCamera()->ParallelProjectionOn();
  this->EventuallyRender();
}

//----------------------------------------------------------------------------
void vtkPVRenderView::ParallelProjectionOff()
{
  this->AddTraceEntry("$kw(%s) ParallelProjectionOff", this->GetTclName());
  if (this->ParallelProjectionCheck->GetState())
    {
    this->ParallelProjectionCheck->SetState(0);
    }
  this->Renderer->GetActiveCamera()->ParallelProjectionOff();
  this->EventuallyRender();
}

//----------------------------------------------------------------------------
void vtkPVRenderView::ParallelProjectionCallback()
{

  if (this->ParallelProjectionCheck->GetState())
    {
    vtkTimerLog::MarkEvent("--- Enable parallel projection.");
    this->ParallelProjectionOn();
    }
  else
    {
    vtkTimerLog::MarkEvent("--- Disable parallel projection.");
    this->ParallelProjectionOff();
    }
}

//----------------------------------------------------------------------------
void vtkPVRenderView::ImmediateModeCallback()
{
  if (this->ImmediateModeCheck->GetState())
    {
    vtkTimerLog::MarkEvent("--- Disable display lists.");
    }
  else
    {
    vtkTimerLog::MarkEvent("--- Enable display lists.");
    }
  
  this->SetUseImmediateMode(this->ImmediateModeCheck->GetState());
}

//----------------------------------------------------------------------------
void vtkPVRenderView::SetUseImmediateMode(int state)
{
  vtkPVWindow *pvWin;
  vtkPVSourceCollection *sources;
  vtkPVSource *pvs;
  int partIdx, numParts;

  this->AddTraceEntry("$kw(%s) SetUseImmediateMode %d", this->GetTclName(),
                      state);

  if (this->ImmediateModeCheck->GetState() != state)
    {
    this->ImmediateModeCheck->SetState(state);
    }
  
  if ( ! state && ! this->TriangleStripsCheck->GetState())
    { // Make sure triangle strips are on.
    // When immediate mode is off, triangle strips must be on.
    this->SetUseTriangleStrips(1);
    }

  pvWin = this->GetPVWindow();
  if (pvWin == NULL)
    {
    vtkErrorMacro("Missing window.");
    return;
    }
  sources = pvWin->GetSourceList("Sources");
  
  sources->InitTraversal();
  while ( (pvs = sources->GetNextPVSource()) )
    {
    numParts = pvs->GetNumberOfParts();
    for (partIdx = 0; partIdx < numParts; ++partIdx)
      {
      pvs->GetPart(partIdx)->GetPartDisplay()->SetUseImmediateMode(state);
      }
    }

  this->EventuallyRender();
}

//----------------------------------------------------------------------------
vtkPVWindow *vtkPVRenderView::GetPVWindow()
{
  vtkPVWindow *pvWin = vtkPVWindow::SafeDownCast(this->GetParentWindow());

  return pvWin;
}

//----------------------------------------------------------------------------
void vtkPVRenderView::SaveInBatchScript(ofstream* file)
{
  vtkCamera *camera;
  double position[3];
  double focalPoint[3];
  double viewUp[3];
  double viewAngle;
  double clippingRange[2];
  double *color;
  int *size;

  size = this->RenderWindow->GetSize();
  *file << "vtkRenderer " << "Ren1" << "\n\t";
  color = this->Renderer->GetBackground();
  *file << "Ren1" << " SetBackground "
        << color[0] << " " << color[1] << " " << color[2] << endl;
  *file << "vtkRenderWindow " << "RenWin1" << "\n\t"
        << "RenWin1" << " AddRenderer "
        << "Ren1" << "\n\t";
  *file << "RenWin1" << " SetSize " << size[0] << " " << size[1] << endl;

  camera = this->GetRenderer()->GetActiveCamera();
  camera->GetPosition(position);
  camera->GetFocalPoint(focalPoint);
  camera->GetViewUp(viewUp);
  viewAngle = camera->GetViewAngle();
  camera->GetClippingRange(clippingRange);
  
  *file << "# camera parameters\n"
        << "set camera [" << "Ren1" << " GetActiveCamera]\n\t"
        << "$camera SetPosition " << position[0] << " " << position[1] << " "
        << position[2] << "\n\t"
        << "$camera SetFocalPoint " << focalPoint[0] << " " << focalPoint[1]
        << " " << focalPoint[2] << "\n\t"
        << "$camera SetViewUp " << viewUp[0] << " " << viewUp[1] << " "
        << viewUp[2] << "\n\t"
        << "$camera SetViewAngle " << viewAngle << "\n\t"
        << "$camera SetClippingRange " << clippingRange[0] << " "
        << clippingRange[1] << "\n";
}


//----------------------------------------------------------------------------
void vtkPVRenderView::SaveState(ofstream* file)
{
  vtkCamera *camera;
  double position[3];
  double focalPoint[3];
  double viewUp[3];
  double *color;

  color = this->Renderer->GetBackground();
  *file << "$kw(" << this->GetTclName() << ") SetBackgroundColor " 
        << color[0] << " " << color[1] << " " << color[2] << endl;

  camera = this->GetRenderer()->GetActiveCamera();
  camera->GetPosition(position);
  camera->GetFocalPoint(focalPoint);
  camera->GetViewUp(viewUp);
  
  if (camera->GetParallelProjection())
    {
    *file << "$kw(" << this->GetTclName() << ") ParallelProjectionOn" << endl;
    *file << "[[$kw(" << this->GetTclName()
          << ") GetRenderer] GetActiveCamera] SetParallelScale "
          << camera->GetParallelScale() << endl;
    }
  else
    {
    *file << "$kw(" << this->GetTclName() << ") ParallelProjectionOff" << endl;
    }
  
  *file << "$kw(" << this->GetTclName() << ") SetCameraState " 
        << position[0] << " " << position[1] << " " << position[2] << " "
        << focalPoint[0] << " " << focalPoint[1] << " " << focalPoint[2] << " "
        << viewUp[0] << " " << viewUp[1] << " " << viewUp[2] << endl; 

  *file << "$kw(" << this->GetTclName() << ") SetUseTriangleStrips "
        << this->TriangleStripsCheck->GetState() << endl;
  
  *file << "$kw(" << this->GetTclName() << ") SetUseImmediateMode "
        << this->ImmediateModeCheck->GetState() << endl;
  
  if (this->RenderModuleUI)
    {
    *file << "set kw(" << this->RenderModuleUI->GetTclName()
          << ") [$kw(" << this->GetTclName() << ") GetRenderModuleUI]" << endl;
    this->RenderModuleUI->SaveState(file);
    }
  
  *file << "set kw(" << this->CornerAnnotation->GetTclName()
        << ") [$kw(" << this->GetTclName() << ") GetCornerAnnotation]" << endl;
  this->CornerAnnotation->SaveState(file);
  
  *file << "$kw(" << this->GetTclName() << ") SetOrientationAxesVisibility "
        << this->OrientationAxesCheck->GetState() << endl;
  *file << "$kw(" << this->GetTclName() << ") SetOrientationAxesInteractivity "
        << this->OrientationAxesInteractiveCheck->GetState() << endl;
  color = this->OrientationAxesOutlineColor->GetColor();
  *file << "$kw(" << this->GetTclName() << ") SetOrientationAxesOutlineColor "
        << color[0] << " " << color[1] << " " << color[2] << endl;
  
  *file << "set kw(" << this->ManipulatorControl2D->GetTclName()
        << ") [$kw(" << this->GetTclName() << ") GetManipulatorControl2D]"
        << endl;
  this->ManipulatorControl2D->SaveState(file);
  
  *file << "set kw(" << this->ManipulatorControl3D->GetTclName()
        << ") [$kw(" << this->GetTclName() << ") GetManipulatorControl3D]"
        << endl;
  this->ManipulatorControl3D->SaveState(file);
}

//----------------------------------------------------------------------------
int* vtkPVRenderView::GetRenderWindowSize()
{
  if ( this->GetRenderWindow() )
    {
    return this->GetRenderWindow()->GetSize();
    }
  return 0;
}

//----------------------------------------------------------------------------
void vtkPVRenderView::UpdateCameraManipulators()
{
  vtkPVInteractorStyleControl *iscontrol3D = this->GetManipulatorControl3D();
  vtkPVInteractorStyleControl *iscontrol2D = this->GetManipulatorControl2D();
  iscontrol3D->UpdateMenus();
  iscontrol2D->UpdateMenus();
}

//----------------------------------------------------------------------------
void vtkPVRenderView::SetupCameraManipulators()
{
  vtkPVInteractorStyleControl *iscontrol3D = this->GetManipulatorControl3D();
  vtkPVInteractorStyleControl *iscontrol2D = this->GetManipulatorControl2D();

  iscontrol3D->SetCurrentManipulator(0, 0, "Rotate");
  iscontrol3D->SetCurrentManipulator(1, 0, "Pan");
  iscontrol3D->SetCurrentManipulator(2, 0, "Zoom");
  iscontrol3D->SetCurrentManipulator(0, 1, "Roll");
  iscontrol3D->SetCurrentManipulator(1, 1, "Center");
  iscontrol3D->SetCurrentManipulator(2, 1, "Pan");
  iscontrol3D->SetCurrentManipulator(0, 2, "FlyIn");
  iscontrol3D->SetCurrentManipulator(2, 2, "FlyOut");
  iscontrol3D->SetDefaultManipulator("Rotate");
  iscontrol3D->UpdateMenus();

  iscontrol2D->SetCurrentManipulator(0, 1, "Roll");
  iscontrol2D->SetCurrentManipulator(1, 0, "Pan");
  iscontrol2D->SetCurrentManipulator(2, 1, "Pan");
  iscontrol2D->SetCurrentManipulator(2, 0, "Zoom");
  iscontrol2D->SetDefaultManipulator("Pan");
  iscontrol2D->UpdateMenus();
}

//----------------------------------------------------------------------------
void vtkPVRenderView::StoreCurrentCamera(int position)
{
  if ( this->CameraIcons[position] )
    {
    this->CameraIcons[position]->StoreCamera();
    }
}

//----------------------------------------------------------------------------
void vtkPVRenderView::RestoreCurrentCamera(int position)
{
  if ( this->CameraIcons[position] )
    {
    this->CameraIcons[position]->RestoreCamera();
    }
}

//----------------------------------------------------------------------------
void vtkPVRenderView::SaveAsImage(const char* filename) 
{
  this->EventuallyRender();
  this->Script("update");
  this->Superclass::SaveAsImage(filename);
}


//----------------------------------------------------------------------------
void vtkPVRenderView::ExecuteEvent(vtkObject*, unsigned long event, void* par)
{
  if ( event == vtkCommand::CursorChangedEvent )
    {
    int val = *(static_cast<int*>(par));
    const char* image = "left_ptr";
    switch ( val ) 
      {
      case VTK_CURSOR_ARROW:
        image = "arror";
        break;
      case VTK_CURSOR_SIZENE:
        image = "top_right_corner";
        break;
      case VTK_CURSOR_SIZENW:        
        image = "top_left_corner";
        break;
      case VTK_CURSOR_SIZESW:
        image = "bottom_left_corner";
        break;
      case VTK_CURSOR_SIZESE:
        image = "bottom_right_corner";
        break;
      case VTK_CURSOR_SIZENS:
        image = "sb_v_double_arrow";
        break;
      case VTK_CURSOR_SIZEWE:
        image = "sb_h_double_arrow";
        break;
      case VTK_CURSOR_SIZEALL:
        image = "hand2";
        break;
      case VTK_CURSOR_HAND:
        image = "hand2";
        break;
      }
    this->Script("%s config -cursor %s", 
                 this->GetPVWindow()->GetWidgetName(), image);
    } 
}

//----------------------------------------------------------------------------
void vtkPVRenderView::Add2DComposite(vtkKWComposite *c)
{
  c->SetView(this);
  // never allow a composite to be added twice
  if (this->Composites->IsItemPresent(c))
    {
    return;
    }
  this->Composites->AddItem(c);
  if (c->GetProp() != NULL)
    {
    this->GetRenderer2D()->AddProp(c->GetProp());
    }
}

//----------------------------------------------------------------------------
void vtkPVRenderView::Remove2DComposite(vtkKWComposite *c)
{
  c->SetView(NULL);
  this->GetRenderer2D()->RemoveProp(c->GetProp());
  this->Composites->RemoveItem(c);
}

//----------------------------------------------------------------------------
void vtkPVRenderView::Enable3DWidget(vtkInteractorObserver *o)
{
  vtkRenderer *ren = this->GetRenderer2D();
  if (!ren)
    {
    return;
    }
  
  vtkRendererCollection *savedRens = vtkRendererCollection::New();
  vtkRenderWindow *renWin = this->GetRenderWindow();
  vtkRendererCollection *rens = renWin->GetRenderers();
  
  vtkRenderer *current;
  
  int i, numRens = rens->GetNumberOfItems();
  int renId = rens->IsItemPresent(ren) - 1;
  rens->InitTraversal();
  for (i = 0; i < numRens; i++)
    {
    current = rens->GetNextItem();
    if (current != ren)
      {
      savedRens->AddItem(current);
      renWin->RemoveRenderer(current);
      }
    }
  
  o->SetEnabled(1);  

  // put the renderers back in the correct order
  renWin->RemoveRenderer(ren);
  savedRens->InitTraversal();
  for (i = 0 ; i < numRens; i++)
    {
    if (i == renId)
      {
      renWin->AddRenderer(ren);
      }
    else
      {
      renWin->AddRenderer(savedRens->GetNextItem());
      }
    }      
  savedRens->Delete();
}

//----------------------------------------------------------------------------
void vtkPVRenderView::SetOrientationAxesVisibility(int val)
{
  if (this->OrientationAxesCheck->GetState() != val)
    {
    this->AddTraceEntry("$kw(%s) SetOrientationAxesVisibility %d",
                        this->GetTclName(), val);
    this->OrientationAxesCheck->SetState(val);
    }
  
  if (!this->OrientationAxes->GetInteractor())
    {
    this->OrientationAxes->SetInteractor(this->GetPVWindow()->GetInteractor());
    }
  if (!this->OrientationAxes->GetParentRenderer())
    {
    this->OrientationAxes->SetParentRenderer(this->Renderer);
    }

  this->OrientationAxes->SetEnabled(val);
}

//----------------------------------------------------------------------------
void vtkPVRenderView::OrientationAxesCheckCallback()
{
  int val = this->OrientationAxesCheck->GetState();
  this->AddTraceEntry("$kw(%s) SetOrientationAxesVisibility %d",
                      this->GetTclName(), val);
  this->SetOrientationAxesVisibility(val);
  this->EventuallyRender();
  
  this->Application->SetRegisteryValue(2, "RunTime",
                                       "OrientationAxesVisibility",
                                       (val ? "1" : "0"));
}

//----------------------------------------------------------------------------
void vtkPVRenderView::SetOrientationAxesInteractivity(int val)
{
  if (this->OrientationAxesInteractiveCheck->GetState() != val)
    {
    this->AddTraceEntry("$kw(%s) SetOrientationAxesInteractivity %d",
                        this->GetTclName(), val);
    this->OrientationAxesInteractiveCheck->SetState(val);
    }
  
  this->OrientationAxes->SetInteractive(val);
}

//----------------------------------------------------------------------------
void vtkPVRenderView::OrientationAxesInteractiveCallback()
{
  int val = this->OrientationAxesInteractiveCheck->GetState();
  this->AddTraceEntry("$kw(%s) SetOrientationAxesInteractivity %d",
                      this->GetTclName(), val);
  this->SetOrientationAxesInteractivity(val);
  this->Application->SetRegisteryValue(2, "RunTime",
                                       "OrientationAxesInteractivity",
                                       (val ? "1" : "0"));
}

//----------------------------------------------------------------------------
void vtkPVRenderView::SetOrientationAxesOutlineColor(double r, double g, double b)
{
  double *color = this->OrientationAxesOutlineColor->GetColor();
  if (r != color[0] || g != color[1] || b != color[2])
    {
    this->OrientationAxesOutlineColor->SetColor(r, g, b);
    }
  this->AddTraceEntry("$kw(%s) SetOrientationAxesOutlineColor %lf %lf %lf",
                      this->GetTclName(), r, g, b);
  this->OrientationAxes->SetOutlineColor(r, g, b);
  this->GetPVWindow()->SaveColor(2, "OrientationAxesOutline",
                                 this->OrientationAxes->GetOutlineColor());
}

//----------------------------------------------------------------------------
void vtkPVRenderView::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os,indent);
  os << indent << "ImmediateModeCheck: " 
     << this->GetImmediateModeCheck() << endl;
  os << indent << "SplitFrame: " 
     << this->GetSplitFrame() << endl;
  os << indent << "NavigationFrame: " 
     << this->GetNavigationFrame() << endl;
  os << indent << "TriangleStripsCheck: " 
     << this->GetTriangleStripsCheck() << endl;
  os << indent << "ParallelProjectionCheck: "
     << this->GetParallelProjectionCheck();
  os << indent << "ManipulatorControl2D: " 
     << this->ManipulatorControl2D << endl;
  os << indent << "ManipulatorControl3D: " 
     << this->ManipulatorControl3D << endl;
  os << indent << "Renderer2D: " << this->Renderer2D << endl;
  os << indent << "RenderModuleUI: " << this->RenderModuleUI << endl;
  os << indent << "CameraControl: " << this->CameraControl << endl;
}
