//  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
//
//  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
//  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2.1 of the License.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
//  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//

//  SALOME VTKViewer : build VTK viewer into Salome desktop
//  File   : VISU_PlanesWidget.h
//  Author : Peter KURNEV
//  Module : SALOME
//  $Header: /home/server/cvs/VISU/VISU_SRC/src/PIPELINE/VISU_PlanesWidget.hxx,v 1.6.2.1.8.1 2010-04-21 16:20:15 vsr Exp $
//
#ifndef __VISU_PlanesWidget_h
#define __VISU_PlanesWidget_h

#include "VISUPipeline.hxx"
#include "VISU_ImplicitFunctionWidget.hxx"
class vtkActor;
class vtkPolyDataMapper;
class vtkCellPicker;
class vtkConeSource;
class vtkLineSource;
class vtkSphereSource;
class vtkPlane;
class vtkCutter;
class vtkProperty;
class vtkImageData;
class vtkOutlineFilter;
class vtkFeatureEdges;
class vtkPolyData;
class vtkTransform;
class vtkImplicitBoolean;
class vtkImplicitFunction;
class VISU_UnScaledActor;
class vtkDataSet;

class VISU_PIPELINE_EXPORT VISU_PlanesWidget : public VISU_ImplicitFunctionWidget
{
public:
  // Description:
  // Instantiate the object.
  static VISU_PlanesWidget *New();

  vtkTypeRevisionMacro(VISU_PlanesWidget,VISU_ImplicitFunctionWidget);
  void PrintSelf(ostream& os, vtkIndent indent);

  void 
  SetDistance(const vtkFloatingPointType theDistance);

  vtkFloatingPointType
  Distance() const;

  vtkGetMacro(InitialLength,vtkFloatingPointType);

  virtual 
  vtkImplicitFunction* 
  ImplicitFunction();

  // Description:
  // Methods that satisfy the superclass' API.
  virtual
  void
  SetEnabled(int);

  virtual
  void
  PlaceWidget(vtkFloatingPointType bounds[6]);

  // Description:
  // Get the origin of the plane.
  void
  SetOrigin(vtkFloatingPointType x, 
            vtkFloatingPointType y, 
            vtkFloatingPointType z);

  void
  SetOrigin(vtkFloatingPointType x[3]);

  vtkFloatingPointType* 
  GetOrigin();

  void
  GetOrigin(vtkFloatingPointType xyz[3]);

  // Description:
  // Get the normal to the plane.
  void 
  SetNormal(vtkFloatingPointType x, 
            vtkFloatingPointType y, 
            vtkFloatingPointType z);

  void 
  SetNormal(vtkFloatingPointType x[3]);

  vtkFloatingPointType* 
  GetNormal();

  void
  GetNormal(vtkFloatingPointType xyz[3]);
  
  // Description:
  // Force the plane widget to be aligned with one of the x-y-z axes.
  // If one axis is set on, the other two will be set off.
  // Remember that when the state changes, a ModifiedEvent is invoked.
  // This can be used to snap the plane to the axes if it is orginally
  // not aligned.
  void
  SetNormalToXAxis(int);

  vtkGetMacro(NormalToXAxis,int);
  vtkBooleanMacro(NormalToXAxis,int);

  void
  SetNormalToYAxis(int);

  vtkGetMacro(NormalToYAxis,int);
  vtkBooleanMacro(NormalToYAxis,int);

  void
  SetNormalToZAxis(int);
  vtkGetMacro(NormalToZAxis,int);
  vtkBooleanMacro(NormalToZAxis,int);

  // Description:
  // Turn on/off tubing of the wire outline of the plane. The tube thickens
  // the line by wrapping with a vtkTubeFilter.
  //vtkSetMacro(Tubing,int);
  //vtkGetMacro(Tubing,int);
  //vtkBooleanMacro(Tubing,int);

  // Description:
  // Enable/disable the drawing of the plane. In some cases the plane
  // interferes with the object that it is operating on (i.e., the
  // plane interferes with the cut surface it produces producing
  // z-buffer artifacts.)
  void
  SetDrawPlane(int plane);

  int
  GetDrawPlane()
  {
    return myDrawPlane;
  }

  // Description:
  // Turn on/off the ability to translate the bounding box by grabbing it
  // with the left mouse button.
  vtkSetMacro(OutlineTranslation,int);
  vtkGetMacro(OutlineTranslation,int);
  vtkBooleanMacro(OutlineTranslation,int);

  // Description:
  // Grab the polydata that defines the plane. The polydata contains a single
  // polygon that is clipped by the bounding box.
  void
  GetPolyData(vtkPolyData *pd);

  // Description:
  // Satisfies superclass API.  This returns a pointer to the underlying
  // PolyData (which represents the plane).
  //vtkPolyDataSource* GetPolyDataSource();
   
  // Description:
  // Get the implicit function for the plane. The user must provide the
  // instance of the class vtkPlane. Note that vtkPlane is a subclass of
  // vtkImplicitFunction, meaning that it can be used by a variety of filters
  // to perform clipping, cutting, and selection of data.
  void
  GetPlane(vtkPlane *plane);

  // Description:
  // Satisfies the superclass API.  This will change the state of the widget
  // to match changes that have been made to the underlying PolyDataSource
  void
  UpdatePlacement(void);

  // Description:
  // Get the properties on the normal (line and cone).
  vtkGetObjectMacro(NormalProperty,vtkProperty);
  vtkGetObjectMacro(SelectedNormalProperty,vtkProperty);
  
  // Description:
  // Get the plane properties. The properties of the plane when selected 
  // and unselected can be manipulated.
  vtkGetObjectMacro(PlaneProperty,vtkProperty);
  vtkGetObjectMacro(SelectedPlaneProperty,vtkProperty);

  // Description:
  // Get the property of the outline.
  vtkGetObjectMacro(OutlineProperty,vtkProperty);
  vtkGetObjectMacro(SelectedOutlineProperty,vtkProperty);

  // Description:
  // Get the property of the intersection edges. (This property also
  // applies to the edges when tubed.)
  vtkGetObjectMacro(EdgesProperty,vtkProperty);

  void
  InitialPlaceWidget(vtkFloatingPointType bds[6]);

protected:
  VISU_PlanesWidget();
  ~VISU_PlanesWidget();

//BTX - manage the state of the widget
  int State;
  enum WidgetState
  {
    Start=0,
    MovingPlane,
    MovingOutline,
    MovingOrigin,
    Scaling,
    Pushing,
    Rotating,
    Outside,
    ChangeDistance
  };
//ETX
    
  //handles the events
  static
  void
  ProcessEvents(vtkObject* object, unsigned long event,
                void* clientdata, void* calldata);

  // ProcessEvents() dispatches to these methods.
  void OnLeftButtonDown();
  void OnLeftButtonUp();
  void OnMiddleButtonDown();
  void OnMiddleButtonUp();
  void OnRightButtonDown();
  void OnRightButtonUp();
  void OnMouseMove();
  //
  // Methods to manipulate the plane
  void ConstrainOrigin(vtkFloatingPointType x[3]);
  void Rotate(int X, int Y, double *p1, double *p2, double *vpn);
  void TranslatePlane(double *p1, double *p2);
  void TranslateOutline(double *p1, double *p2);
  void TranslateOrigin(double *p1, double *p2);
  void Push(double *p1, double *p2);
  void Scale(double *p1, double *p2, int X, int Y);
  void PushDistance(double *p1, double *p2);

  void CreateDefaultProperties();
  
  void GeneratePlane();
  //virtual void SizeHandles();
  void HighlightPlane(int highlight);
  void HighlightNormal(int highlight);
  void HighlightOutline(int highlight);
  void UpdateRepresentation();
  void SetOriginInternal(vtkFloatingPointType x[3]);

  // Controlling ivars
  int NormalToXAxis;
  int NormalToYAxis;
  int NormalToZAxis;
  

  // Flags to handle mouse events
  bool HandleMoveEvent;
  bool HandleLeftButtonEvent;
  bool HandleMiddleButtonEvent;
  bool HandleRightButtonEvent;
  // The actual plane which is being manipulated
  vtkPlane *myPlane1;
  vtkPlane *myPlane2;
  
  vtkFloatingPointType myDistance; 
  vtkImplicitBoolean *myImplicitFunction;

  // The bounding box is represented by a single voxel image data
  vtkImageData      *myBox;
  vtkOutlineFilter  *myOutline;
  vtkPolyDataMapper *myOutlineMapper;
  vtkActor          *myOutlineActor;
  
  int OutlineTranslation; //whether the outline can be moved
  
  // The cut plane is produced with a vtkCutter
  vtkCutter         *myCutter1;
  vtkPolyDataMapper *myCutMapper1;
  vtkActor          *myCutActor1;

  vtkCutter         *myCutter2;
  vtkPolyDataMapper *myCutMapper2;
  vtkActor          *myCutActor2;
  
  vtkFeatureEdges   *myEdges2;
  vtkPolyDataMapper *myEdgesMapper2;
  vtkActor          *myEdgesActor2;

  int               myDrawPlane;

  vtkFeatureEdges   *myEdges1;
  vtkPolyDataMapper *myEdgesMapper1;
  vtkActor          *myEdgesActor1;

  // The + normal cone
  vtkConeSource      *ConeSource;
  vtkPolyDataMapper  *ConeMapper;
  VISU_UnScaledActor *ConeActor;
  // The + normal line
  vtkLineSource     *LineSource;
  vtkPolyDataMapper *LineMapper;
  vtkActor          *LineActor;
  // The - normal cone
  vtkConeSource      *ConeSource2;
  vtkPolyDataMapper  *ConeMapper2;
  VISU_UnScaledActor *ConeActor2;
  // The - normal line
  vtkLineSource     *LineSource2;
  vtkPolyDataMapper *LineMapper2;
  vtkActor          *LineActor2;
  // The origin positioning handle
  vtkSphereSource    *Sphere;
  vtkPolyDataMapper  *SphereMapper;
  VISU_UnScaledActor *SphereActor;

  // Do the picking
  vtkCellPicker *Picker;
  
  // Transform the normal (used for rotation)
  vtkTransform *Transform;
  // Properties used to control the appearance of selected objects and
  // the manipulator in general.
  vtkProperty *NormalProperty;
  vtkProperty *SelectedNormalProperty;
  vtkProperty *PlaneProperty;
  vtkProperty *SelectedPlaneProperty;
  vtkProperty *OutlineProperty;
  vtkProperty *SelectedOutlineProperty;
  vtkProperty *EdgesProperty;
  
private:
  VISU_PlanesWidget(const VISU_PlanesWidget&);  //Not implemented
  void operator=(const VISU_ImplicitFunctionWidget&);  //Not implemented
};

#endif
