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

  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 vtkKWRenderWidgetPro
// .SECTION Description

#ifndef __vtkKWRenderWidgetPro_h
#define __vtkKWRenderWidgetPro_h

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

class vtkColorTransferFunction;
class vtkImageData;
class vtkKW3DMarkersWidget;
class vtkKW3DSplineCurvesWidget;
class vtkKW3DSplineSurfacesWidget;
class vtkKWEventMap;
class vtkKWMarker2D;
class vtkKWOrientationWidget;
class vtkVolumeProperty;

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

  // Description:
  // Set the input data for this widget.
  virtual void SetInput(vtkImageData *data);
  vtkGetObjectMacro(Input, vtkImageData);

  // Description:
  // Update the widget according the Input data. This method is 
  // automatically called when the Input Ivar is changed. 
  // It can be called "manually" when the contents of the Input's data 
  // may have changed while the Input Ivar remained the same. 
  // This can occur when an in-place filter is applied, for example.
  // Depending on the changes that occured on the Input since the previous
  // call to this method, the following methods will be called in that order:
  // - InputScalarStructureHasChanged(): the input scalar structure was changed
  // - InputBoundsHaveChanged(): the input bounds were changed
  // - InputHasChanged(): any of the above changed happened, it is passed
  //                      a mask representing the changes.
  // Returns a binary mask representing the changes and combining the below 
  // values (if 0, it is safe to assume that nothing changed)
  //BTX
  enum 
  {
    INPUT_UNCHANGED                = 0,
    INPUT_SCALAR_STRUCTURE_CHANGED = 1,
    INPUT_BOUNDS_CHANGED           = 2
  };
  //ETX
  virtual int UpdateAccordingToInput();

  // Description:
  // Are the scalar components of this data independent of each other ?
  virtual void SetIndependentComponents(int);
  vtkBooleanMacro(IndependentComponents, int);
  virtual int GetIndependentComponents();
  
  // Description:
  // Set the color mapping mode.
  // Not that those should be considered as 'hints', or 'requests'. Depending
  // on the data and the IndependentComponents ivar, adjusted/valid values
  // will be propagated to the color maps by UpdateColorMapping(). 
  virtual void SetDisplayChannels(int arg);
  vtkGetMacro(DisplayChannels, int);
  virtual void SetUseOpacityModulation(int arg);
  vtkGetMacro(UseOpacityModulation, int);
  vtkBooleanMacro(UseOpacityModulation, int);

  // Description:
  // Set/Get the scalar unit for a given scalar component 
  // (e.g. density, T1, T2, etc)
  virtual void SetScalarUnits(int i, const char *units);
  virtual const char *GetScalarUnits(int i);

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

  // Description:
  // Close the widget. 
  // Usually called when new data is about to be loaded.
  virtual void Close();
  
  // Description:
  // Get and control the 2D cursor annotation.
  virtual void SetMarker2DVisibility(int v);
  virtual int GetMarker2DVisibility();
  vtkBooleanMacro(Marker2DVisibility, int);
  virtual void SetMarker2DColor(double r, double g, double b);
  virtual void SetMarker2DColor(double *rgb)
    { this->SetMarker2DColor(rgb[0], rgb[1], rgb[2]); };
  virtual double* GetMarker2DColor();
  virtual void SetMarker2DPosition(double x1, double y1, double x2, double y2);
  virtual void GetMarker2DPosition(double pos[4]);
  vtkGetObjectMacro(Marker2D, vtkKWMarker2D);

  // Description:
  // Get and control the 3D markers, probably all of these routines
  // should be removed. The manipulation of markers whould not be done
  // at this level, remove with event cleanup.
  virtual void SetMarkers3DVisibility(int v);
  virtual int GetMarkers3DVisibility();
  vtkBooleanMacro(Markers3DVisibility, int);
  virtual void SetMarkers3DGroupColor(
    unsigned int gid, double r, double g, double b);
  virtual void SetMarkers3DGroupColor(unsigned int gid, double *rgb)
    { this->SetMarkers3DGroupColor(gid, rgb[0], rgb[1], rgb[2]); };
  virtual double* GetMarkers3DGroupColor(unsigned int gid) const;
  virtual unsigned int GetNumberOfMarkers3DGroups() const;
  virtual const char * GetMarkers3DGroupName(unsigned int gid) const;
  virtual int GetMarkers3DGroupId(const char *) const;
  vtkGetObjectMacro(Markers3D, vtkKW3DMarkersWidget);
  virtual void Add3DMarker(unsigned int gid, double x, double y, double z);
  virtual void Set3DMarkerPosition(
    unsigned int id, double x, double y, double z);
  virtual double* Get3DMarkerPosition(unsigned int idx);
  virtual void RemoveSelected3DMarker();
  virtual void RemoveAll3DMarkers();
  virtual void Add3DMarkersGroup(const char *name, const double * color)
    { this->Add3DMarkersGroup(name, color[0], color[1], color[2]); };
  virtual void Add3DMarkersGroup(const char *, double r, double g, double b);
  virtual int Remove3DMarkersGroup(const char *);
  virtual void RemoveAll3DMarkersGroups();
   
  // Description:
  // Get / Set the widget holding multiple spline curves
  // Get / Set its visibility
  // Add a new spline curve to the current set
  vtkGetObjectMacro(SplineCurves3D, vtkKW3DSplineCurvesWidget);
  virtual void SetSplineCurves3D( vtkKW3DSplineCurvesWidget * curves );
  void SetSplineCurves3DVisibility(int v);
  virtual int GetSplineCurves3DVisibility();
  virtual void Add3DSplineCurve();

  // Description:
  // Get / Set the widget holding multiple spline surfaces
  vtkGetObjectMacro(SplineSurfaces3D, vtkKW3DSplineSurfacesWidget);
  virtual void SetSplineSurfaces3D( vtkKW3DSplineSurfacesWidget * surfaces );

  // Description:
  // Enable/disable orientation marker
  virtual void SetOrientationMarkerVisibility(int);
  virtual int  GetOrientationMarkerVisibility();
  virtual void ToggleOrientationMarkerVisibility();
  vtkBooleanMacro(OrientationMarkerVisibility, int);
  virtual void SetOrientationMarkerColor(double r, double g, double b);
  virtual void SetOrientationMarkerColor(double rgb[3])
    { this->SetOrientationMarkerColor(rgb[0], rgb[1], rgb[2]); }
  virtual double* GetOrientationMarkerColor();
  vtkGetObjectMacro(OrientationWidget, vtkKWOrientationWidget);
  
  // Description:
  // Get the event map
  vtkGetObjectMacro(EventMap, vtkKWEventMap);

  // Description:
  // This id is a hint that should be appended to the call data and
  // should help identify who sent the event. Of course, the client data
  // is a pointer to who sent the event, but in some situation it is either
  // not available nor very usable. Default to -1.
  // Can be safely ignored in most cases.
  vtkSetMacro(EventIdentifier, int);
  vtkGetMacro(EventIdentifier, int);

  // Description:
  // Material properties
  vtkGetObjectMacro(VolumeProperty, vtkVolumeProperty);
  virtual void SetVolumeProperty(vtkVolumeProperty *vprop);
  virtual void SetEnableShading(int index, int shade);
  virtual int  GetEnableShading(int index);
  virtual void SetGradientOpacityEnable(int index, int state);
  virtual int GetGradientOpacityEnable(int index);
  virtual void VolumePropertyChanged();
  virtual void VolumePropertyChanging();

  // Description:
  // Event list
  //BTX
  enum
  {
    DisplayChannelsChangedEvent = 20000,
    UseOpacityModulationChangedEvent
  };
  //ETX

  // Description:
  // Update the color mapping parameters
  virtual void UpdateColorMapping() {};

protected:
  vtkKWRenderWidgetPro();
  ~vtkKWRenderWidgetPro();

  // 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
  //   (the default implementation will call ConnectInternalPipeline()).
  // - 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:
  // Check if we have a valid IndependentComponents value depending on
  // the number/type of components. If not, return a valid value, otherwise
  // the current value.
  virtual int GetValidIndependentComponents();
  
  // Description:
  // Configure the event map
  virtual void ConfigureEventMap();

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

  // Description:
  // Populate the context menu
  virtual void PopulateContextMenuWithAnnotationEntries(vtkKWMenu*);

  // The Input, and a cache used to check what has been modified since the 
  // last call to UpdateAccordingToInput.

  vtkImageData *Input;
  vtkImageData *LastInputCheck;
  
  vtkKW3DMarkersWidget* Markers3D;
  vtkKWMarker2D* Marker2D;
  vtkKW3DSplineCurvesWidget* SplineCurves3D;
  vtkKW3DSplineSurfacesWidget* SplineSurfaces3D;
  vtkKWOrientationWidget *OrientationWidget;

  vtkVolumeProperty *VolumeProperty;
 
  vtkKWEventMap *EventMap;

  int DisplayChannels;
  int UseOpacityModulation;
  char *ScalarUnits[VTK_MAX_VRCOMP];
  double Window;
  double Level;
  int EventIdentifier;

  int LastIndependentComponents;

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

#endif
