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

  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.

=========================================================================*/
// .NAME vtkKWVolumeWidget - a render widget for volumes
// .SECTION Description

#ifndef __vtkKWVolumeWidget_h
#define __vtkKWVolumeWidget_h

#include "vtkKWRenderWidgetPro.h"
#include "XML/vtkXMLIOBaseMacros.h" // Needed for XML reader/writer macros

class vtk3DCursorAnnotation;
class vtkActor;
class vtkBoundingBoxAnnotation;
class vtkCollection;
class vtkColorTransferFunction;
class vtkImageData;
class vtkImageResample;
class vtkImplicitPlaneWidget;
class vtkKWHistogramSet;
class vtkKWInteractorStyleVolumeView;
class vtkKWScalarBarWidget;
class vtkKWScaleBarWidget;
class vtkKWEVolumeMapper;
class vtkKWVolumeWidgetInternals;
class vtkLight;
class vtkPiecewiseFunction;
class vtkPolyData;
class vtkPolyDataMapper;
class vtkStructuredGrid;
class vtkSurfaceAnnotation;
class vtkTimerLog;
class vtkTransform;
class vtkVolume;
class vtkVolumeMapper;

class VTK_EXPORT vtkKWVolumeWidget : public vtkKWRenderWidgetPro
{
public:
  static vtkKWVolumeWidget* New();
  vtkTypeRevisionMacro(vtkKWVolumeWidget, vtkKWRenderWidgetPro);
  void PrintSelf(ostream& os, vtkIndent indent);
  //BTX
  vtkKWGetXMLReaderWriterObjectsMacro();
  //ETX

  // Description:
  // Set/Get/Reset the window/level for those elements that support W/L
  virtual void SetWindowLevel(double, double);
  virtual void ResetWindowLevel();

  // Description:
  // Reset the camera	 
  virtual void ResetCamera();

  // Description:
  // Set/Get the zoom ratio to be used when resetting the camera.
  // A larger value means a larger view of the data in the scene.
  vtkSetClampMacro(ResetCameraZoomRatio,double,0.0,1.0);
  vtkGetMacro(ResetCameraZoomRatio,double);

  // Description:
  // Render actors
  // The widget tracks the render state it is in (i.e. the LOD that 
  // was last used). Sometimes you need to clear that stage so that
  // the widget does not assume it is in a given state.
  virtual void Render();

  // Description:
  // Accessors to the LOD volume and various LOD IDs
  vtkGetObjectMacro(Volume, vtkVolume);
  
  // Description:
  // Accessors to the volume mapper
  vtkGetObjectMacro(VolumeMapper, vtkKWEVolumeMapper);
  
  // Description:
  // Projection type
  //BTX
  enum
  {
    PARALLEL_PROJECTION = 0,
    PERSPECTIVE_PROJECTION = 1
  };
  //ETX
  virtual int GetProjectionType();
  virtual void SetProjectionType(int);
  virtual void SetProjectionTypeToParallel()
    { this->SetProjectionType(vtkKWVolumeWidget::PARALLEL_PROJECTION); }
  virtual void SetProjectionTypeToPerspective()
    { this->SetProjectionType(vtkKWVolumeWidget::PERSPECTIVE_PROJECTION); }
  virtual void SetPerspectiveViewAngle(double val);
  virtual double GetPerspectiveViewAngle();
 
  // Description:
  // Register and unregister the use of IntermixIntersectingGeometry.
  virtual void RegisterIntermixIntersectingGeometry();
  virtual void UnRegisterIntermixIntersectingGeometry();

  // Description:
  // Set/get the interaction style.
  // This method can be used to control which main interaction style is in
  // effect (either Pan, Zoom or Rotate). The corresponding action
  // is triggered by the left mouse button. If set to All, all actions
  // are mapped to as many buttons as possible.
  //BTX
  enum
  {
    INTERACTION_MODE_PAN = 0,
    INTERACTION_MODE_ZOOM,
    INTERACTION_MODE_ROTATE,
    INTERACTION_MODE_ALL,
  };
  //ETX
  vtkGetMacro(InteractionMode, int);
  virtual void SetInteractionMode(int type);
  virtual void SetInteractionModeToPan()
    { this->SetInteractionMode(INTERACTION_MODE_PAN); };
  virtual void SetInteractionModeToZoom()
    { this->SetInteractionMode(INTERACTION_MODE_ZOOM); };
  virtual void SetInteractionModeToRotate()
    { this->SetInteractionMode(INTERACTION_MODE_ROTATE); };
  virtual void SetInteractionModeToAll()
    { this->SetInteractionMode(INTERACTION_MODE_ALL); };

  // Description:
  // Blend modes
  //BTX	 
  enum	 
  {	 
    BLEND_MODE_MIP = 1,	 
    BLEND_MODE_COMPOSITE
  };	 
  //ETX
  virtual void SetBlendMode(int);
  virtual int GetBlendMode();
  virtual void SetBlendModeToMIP();
  virtual void SetBlendModeToComposite();

  // Description:
  // Enable/disable the volume visibility
  virtual void SetVolumeVisibility(int);
  virtual int  GetVolumeVisibility();
  virtual void ToggleVolumeVisibility();
  vtkBooleanMacro(VolumeVisibility, int);

  // Description:
  // Enable/set cropping
  virtual void SetCropping(int state);
  virtual int GetCropping();
  vtkBooleanMacro(Cropping, int);
  virtual void SetCroppingPlanes(double p[6]);
  virtual void SetCroppingPlanes(
    double p0, double p1, double p2, double p3, double p4, double p5);
  virtual double* GetCroppingPlanes();
  virtual void ResetCroppingPlanes();
  virtual void SetCroppingRegionFlags(int i);
  virtual int GetCroppingRegionFlags();
  
  // Description:
  // Convenience method to set the visibility of all annotations.
  virtual void SetAnnotationsVisibility(int v);

  // Description:
  // Enable/set reformat
  //BTX
  enum
  {
    CAMERA_MANIPULATION_STYLE = 0,
    REFORMAT_MANIPULATION_STYLE = 1
  };
  //ETX
  vtkGetMacro(Reformat, int);
  virtual void SetReformat(int i);
  vtkBooleanMacro(Reformat, int);
  vtkGetMacro(ReformatThickness, double);
  virtual void SetReformatThickness(double t);
  vtkGetMacro(ReformatManipulationStyle, int);
  virtual void SetReformatManipulationStyle(int i);
  vtkGetMacro(ReformatBoxVisibility, int);
  vtkBooleanMacro(ReformatBoxVisibility, int);
  virtual void SetReformatBoxVisibility(int i);
  vtkGetVector3Macro(ReformatNormal, double);
  virtual void SetReformatNormal(double, double, double);
  virtual void SetReformatNormal(double v[3])
    { this->SetReformatNormal(v[0], v[1], v[2]); }
  vtkGetVector3Macro(ReformatUp, double);
  virtual void SetReformatUp(double, double, double);
  virtual void SetReformatUp(double v[3])
    { this->SetReformatUp(v[0], v[1], v[2]); }
  vtkGetVector3Macro(ReformatLocation, double);
  virtual void SetReformatLocation(double, double, double);
  virtual void SetReformatLocation(double v[3])
    { this->SetReformatLocation(v[0], v[1], v[2]); }

  // Description:
  // These are the event handlers that UIs can use or override.
  virtual void ReformatButtonPress(int x, int y);
  virtual void ReformatButtonRelease();
  virtual void ReformatButton1Motion(int x, int y);
  virtual void ReformatButton2Motion(int x, int y);
  virtual void ReformatButton3Motion(int x, int y);

  // Description:
  // Enable/disable bounding box
  virtual void SetBoundingBoxVisibility(int);
  virtual int  GetBoundingBoxVisibility();
  virtual void ToggleBoundingBoxVisibility();
  vtkBooleanMacro(BoundingBoxVisibility, int);
  virtual void SetBoundingBoxColor(double r, double g, double b);
  virtual void SetBoundingBoxColor(double rgb[3])
    { this->SetBoundingBoxColor(rgb[0], rgb[1], rgb[2]); }
  virtual double* GetBoundingBoxColor();
  vtkGetObjectMacro(BoundingBoxAnnotation, vtkBoundingBoxAnnotation);

  // Description:
  // Enable/disable scale bar
  virtual void SetScaleBarVisibility(int state);
  virtual int  GetScaleBarVisibility();
  virtual void ToggleScaleBarVisibility();
  vtkBooleanMacro(ScaleBarVisibility, int);
  virtual void SetScaleBarColor(double r, double g, double b);
  virtual void SetScaleBarColor(double rgb[3])
    { this->SetScaleBarColor(rgb[0], rgb[1], rgb[2]); }
  virtual double* GetScaleBarColor();
  vtkGetObjectMacro(ScaleBarWidget, vtkKWScaleBarWidget);
  
  // Description:
  // Enable/disable scalar bar
  virtual void SetScalarBarVisibility(int state);
  virtual int  GetScalarBarVisibility();
  virtual void ToggleScalarBarVisibility();
  vtkBooleanMacro(ScalarBarVisibility, int);
  virtual void SetScalarBarComponent(int comp);
  virtual int  GetScalarBarComponent();
  vtkGetObjectMacro(ScalarBarWidget, vtkKWScalarBarWidget);
  
  // Description:
  // Set/Get plane widget parameters
  virtual void SetPlaneWidgetVisibility(int state);
  virtual int GetPlaneWidgetVisibility();
  vtkBooleanMacro(PlaneWidgetVisibility, int);
  virtual void SetPlaneWidgetColor(double r, double g, double b);
  virtual void SetPlaneWidgetColor(double rgb[3])
    { this->SetPlaneWidgetColor(rgb[0], rgb[1], rgb[2]); }
  virtual double* GetPlaneWidgetColor();
  virtual void SetPlaneWidgetScalarsVisibility(int state);
  virtual int GetPlaneWidgetScalarsVisibility();
  vtkBooleanMacro(PlaneWidgetScalarsVisibility, int);
  virtual void ResetPlaneWidget();
  vtkGetObjectMacro(PlaneWidget, vtkImplicitPlaneWidget);
  
  // Description:
  // Update the probe filter associated with the plane widget
  virtual void UpdateProbe();
  
  // Description:
  // 3D Cursor
  //BTX
  enum
  {
    CURSOR_TYPE_CROSSHAIR = 0,
    CURSOR_TYPE_PLANE = 1
  };
  //ETX
  virtual void SetCursor3DPosition(double x, double y, double z);
  virtual double* GetCursor3DPosition();
  virtual double* GetCursor3DXColor();
  virtual double* GetCursor3DYColor();
  virtual double* GetCursor3DZColor();
  virtual void SetCursor3DXColor(double r, double g, double b);
  virtual void SetCursor3DXColor(double rgb[3])
    { this->SetCursor3DXColor(rgb[0], rgb[1], rgb[2]); }
  virtual void SetCursor3DYColor(double r, double g, double b);
  virtual void SetCursor3DYColor(double rgb[3])
    { this->SetCursor3DYColor(rgb[0], rgb[1], rgb[2]); }
  virtual void SetCursor3DZColor(double r, double g, double b);
  virtual void SetCursor3DZColor(double rgb[3])
    { this->SetCursor3DZColor(rgb[0], rgb[1], rgb[2]); }
  virtual void SetCursor3DType(int type);
  virtual int GetCursor3DType();
  virtual void SetCursor3DVisibility(int state);
  virtual int GetCursor3DVisibility();
  vtkBooleanMacro(Cursor3DVisibility, int);
  virtual void StartUsingCursor3D();
  virtual void StopUsingCursor3D();

  // Description:
  // Update internal objects according to the 3d cursor annotation values
  vtkGetObjectMacro(Cursor3DAnnotation, vtk3DCursorAnnotation);
  virtual void UpdateAccordingTo3DCursorAnnotation();
  
  // Description:
  // Set the spline curves in 3D
  virtual void SetSplineCurves3D( vtkKW3DSplineCurvesWidget * curves );
  
  // Description:
  // Set the spline surfaces in 3D
  virtual void SetSplineSurfaces3D( vtkKW3DSplineSurfacesWidget * surfaces );
  
  // Description:
  // Close the widget. 
  // Usually called when new data is about to be loaded.
  virtual void Close();

  // Description:
  // Set the camera to a standard view. 
  //BTX
  enum
  {
    STANDARD_VIEW_PLUS_X  = 0,
    STANDARD_VIEW_PLUS_Y  = 1,
    STANDARD_VIEW_PLUS_Z  = 2,
    STANDARD_VIEW_MINUS_X = 3,
    STANDARD_VIEW_MINUS_Y = 4,
    STANDARD_VIEW_MINUS_Z = 5
  };
  //ETX
  virtual void SetStandardCameraView(int type);
  static const char* GetStandardCameraViewAsMedicalString(int);
  static const char* GetStandardCameraViewAsMedicalHelpString(int);
  static const char* GetStandardCameraViewAsDefaultString(int);
  static const char* GetStandardCameraViewAsDefaultHelpString(int);

  // Description:
  // Set the Z super sampling
  virtual void SetZSampling(int s);
  vtkGetMacro(ZSampling, int);

  // Description:
  // Control the lights
  virtual int    GetNumberOfLights();
  virtual void   SetLightPosition(int idx, double x, double y, double z);
  virtual double* GetLightPosition(int idx);
  virtual void   SetLightVisibility(int idx, int vis);
  virtual int    GetLightVisibility(int idx);
  virtual void   SetLightColor(int idx, double r, double g, double b);
  virtual double* GetLightColor(int idx);
  virtual void   SetLightIntensity(int idx, double val);
  virtual double  GetLightIntensity(int idx);

  // Description:
  // Transfer function changes
  virtual void SetVolumeProperty(vtkVolumeProperty *vprop);

  // Description:
  // Render-related callbacks
  virtual void IdleRenderCallback();
  virtual int ShouldIAbort();

  // Description:
  // Interaction-related callbacks
  virtual void UpdateRenderer(int x, int y);
  virtual void EnterCallback(int x, int y);
  virtual void MouseButtonPressCallback(
    int num, int x, int y, int ctrl, int shift, int alt, int repeat);
  virtual void MouseButtonReleaseCallback(
    int num, int x, int y, int ctrl, int shift, int alt);

  // Description:
  // Access to contour and surface annotation
  vtkGetObjectMacro(SurfaceAnnotation, vtkSurfaceAnnotation);

  // Description:
  // Access to the interactor style
  vtkGetObjectMacro(InteractorStyle, vtkKWInteractorStyleVolumeView);

  // Description:
  // Perform an actual recompute of reformat plane. The argument is
  // array of doubles which contains normal and vector up for reformat
  // plane.
  virtual void PerformRecomputeReformatPlane(double*);

  // Description:
  // Set/get the single update rate
  // When the render mode is set to single, such as for making animations,
  // how much time should be allowed for each rendered frame to be generated.
  // This is expressed in terms of frames per second and defaults to 0.2.
  vtkSetMacro(SingleUpdateRate, double);
  vtkGetMacro(SingleUpdateRate, double);

  // Description:
  // Set/get the interactive update rate
  // This is expressed in terms of frames per second.
  vtkSetMacro(InteractiveUpdateRate, double);
  vtkGetMacro(InteractiveUpdateRate, double);

  // Description:
  // Set/Get the histogram set. This histogram (most likely shared by
  // different classes) will be used to compute default tfuncs
  virtual void SetHistogramSet(vtkKWHistogramSet*);
  vtkGetObjectMacro(HistogramSet, vtkKWHistogramSet);
  
  // Description:
  // Setup/remove the widget bindings.
  // AddBindings(), which sets up general bindings like Expose or Configure
  // events, will ultimately call AddInteractionBindings() which sets up
  // interaction bindings (mouse events, keyboard events, etc.).
  virtual void AddInteractionBindings();

  // Description:
  // Are we printing ?
  virtual void SetPrinting(int arg);

  // Description:
  // Create a canonical view of the volume given the current blend mode
  // volume properties. This is a not screenshot of the internal renderwindow
  // but a canonical view of the volume along some meaningful axis.
  // It can be used to create a thumbnail icon of the current volume 
  // properties independent of the camera position.
  // The method is passed a vtkImageData. The resulting view will match
  // the current dimensions of the image.
  // See SetBlendMode for the different values the blend_mode parameter
  // can accept (not that those are *not* the values from vtkVolumeMapper)
  // Return 1 on success, 0 otherwise
  virtual int CreateCanonicalView(
    vtkImageData *image, 
    vtkVolumeProperty *prop, 
    int blend_mode);
  
  // Description:
  // Add all the default observers needed by that object, or remove
  // all the observers that were added through AddCallbackCommandObserver.
  // Subclasses can override these methods to add/remove their own default
  // observers, but should call the superclass too.
  virtual void AddCallbackCommandObservers();
  virtual void RemoveCallbackCommandObservers();

  // Description:
  // Push all volume mappers to a collection.
  virtual void GetAllVolumeMappers(vtkCollection *mappers);

  // Description:
  // Apply default preset
  virtual void ApplyDefaultPreset();

protected:
  vtkKWVolumeWidget();
  ~vtkKWVolumeWidget();
  
  // Description:
  // Create the widget
  virtual void CreateWidget();
  
  // Description:
  // Connects the internal object together given the Input.
  // Returns 1 on success, 0 on error or to signal that it is safe to abort
  virtual int ConnectInternalPipeline();

  // Description:
  // Those methods are called automatically by UpdateAccordingToInput() if:
  // - InputScalarStructureHasChanged(): the input scalar structure has changed
  // - InputBoundsHaveChanged(): the input bounds have changed
  // - InputHasChanged(): any of the above changes happened, it is passed
  //                      a mask representing the changes.
  // Returns 1 on success, 0 on error or to signal that it is safe to abort
  virtual int InputScalarStructureHasChanged();
  virtual int InputBoundsHaveChanged();
  virtual int InputHasChanged(int mask);

  // Description:
  // Update internal objects according to the current unit
  virtual void UpdateAccordingToUnits();

  // Description:
  // Update internal objects according to input spacing
  virtual void UpdateAccordingToInputSpacing();
  
  // Description:
  // Render a smaller image if necessary to keep texture mapping rendering
  // at a fast enough rate. Also handle multipass rendering, and be sure
  // to avoid the texture mapper if it is not supported
  virtual void LevelOfDetailRender();
  
  // Description:
  // Configure the event map
  virtual void ConfigureEventMap();

  vtkKWEVolumeMapper *VolumeMapper;

  // Description:
  // Create the default renderers inside the render window.
  // Superclass can override to create different renderers.
  // It is called by Create().
  virtual void CreateDefaultRenderers();

  vtkVolume         *Volume;

  int UseIntermixIntersectingGeometry;

  double InteractiveUpdateRate;
  double SingleUpdateRate;
  
  vtkKWScaleBarWidget    *ScaleBarWidget;
  vtkKWScalarBarWidget   *ScalarBarWidget;
  vtkImplicitPlaneWidget *PlaneWidget;

  int Reformat;
  int ReformatManipulationStyle;
  int ReformatBoxVisibility;
  double ReformatThickness;
  double ReformatNormal[3];
  double ReformatUp[3];
  double ReformatLocation[3];
  vtkPolyData *ReformatData;
  vtkActor *ReformatPlane;
  vtkTransform *ReformatTransform;
  virtual void RecomputeReformatPlane();

  int LastPosition[2];
  
  int ZSampling;

  int UseCursor3D;

  int InteractionMode;

  vtkKWInteractorStyleVolumeView *InteractorStyle;

  vtkLight *CurrentLight;
  vtkTimerLog *RenderTimer;
  Tcl_TimerToken TimerToken;

  vtkSurfaceAnnotation    *SurfaceAnnotation;
  vtkBoundingBoxAnnotation *BoundingBoxAnnotation;
  vtk3DCursorAnnotation *Cursor3DAnnotation;

  // Histograms
  vtkKWHistogramSet *HistogramSet;
  virtual void UpdateHistogramSet();
  virtual void UpdateHistogramSetForGradients();

  // Description:
  // Processes the events that are passed through CallbackCommand (or others).
  // Subclasses can oberride this method to process their own events, but
  // should call the superclass too.
  virtual void ProcessCallbackCommandEvents(
    vtkObject *caller, unsigned long event, void *calldata);
  
  // Description:
  // Populate the context menu
  virtual void PopulateContextMenuWithInteractionEntries(vtkKWMenu*);
  virtual void PopulateContextMenuWithAnnotationEntries(vtkKWMenu*);
  virtual void PopulateContextMenuWithCameraEntries(vtkKWMenu*);

  // Description:
  // Zoom Factor, specific for Volume Render (85% being the default)
  double ResetCameraZoomRatio;

  // Description:
  // Add/Remove progress to a volume mapper
  virtual void AddVolumeMapperProgress(
    vtkVolumeMapper *mapper, const char *message);
  virtual void RemoveVolumeMapperProgress(vtkVolumeMapper *mapper);
  virtual void AddVolumeMapperGradientProgress(
    vtkVolumeMapper *mapper, const char *message);
  virtual void RemoveVolumeMapperGradientProgress(vtkVolumeMapper *mapper);
  
  // PIMPL Encapsulation for STL containers

  vtkKWVolumeWidgetInternals *Internals;

private:
  vtkKWVolumeWidget(const vtkKWVolumeWidget&);  // Not implemented
  void operator=(const vtkKWVolumeWidget&);  // Not implemented
};

#endif
