text: /*=========================================================================
  
    Program:   Visualization Toolkit
    Module:    vtkOrientationMarkerWidget.h
  
    Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
    All rights reserved.
    See Copyright.txt or http://www.kitware.com/Copyright.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.
  
  =========================================================================*/
  /**
   * @class   vtkOrientationMarkerWidget
   * @brief   2D widget for manipulating a marker prop
   *
   * This class provides support for interactively manipulating the position,
   * size, and apparent orientation of a prop that represents an orientation
   * marker.  This class works by adding its internal renderer to an external
   * "parent" renderer on a different layer.  The input orientation marker is
   * rendered as an overlay on the parent renderer and, thus, appears superposed
   * over all props in the parent's scene.  The camera view of the orientation
   * the marker is made to match that of the parent's by means of an observer
   * mechanism, giving the illusion that the orientation of the marker reflects
   * that of the prop(s) in the parent's scene.
   *
   * The widget listens to left mouse button and mouse movement events. It will
   * change the cursor shape based on its location. If the cursor is over the
   * overlay renderer, it will change the cursor shape to a SIZEALL shape
   * or to a resize corner shape (e.g., SIZENW) if the cursor is near a corner.
   * If the left mouse button is pressed and held down while moving, the overlay
   * renderer, and hence, the orientation marker, is resized or moved.  I the case
   * of a resize operation, releasing the left mouse button causes the widget
   * to enforce its renderer to be square.  The diagonally opposite corner to the
   * one moved is repositioned such that all edges of the renderer have the same
   * length: the minimum.
   *
   * To use this object, there are two key steps: 1) invoke SetInteractor() with
   * the argument of the method a vtkRenderWindowInteractor, and 2) invoke
   * SetOrientationMarker with an instance of vtkProp (see caveats below).
   * Specifically, vtkAxesActor and vtkAnnotatedCubeActor are two classes
   * designed to work with this class.  A composite orientation marker can be
   * generated by adding instances of vtkAxesActor and vtkAnnotatedCubeActor to a
   * vtkPropAssembly, which can then be set as the input orientation marker.
   * The widget can be also be set up in a non-interactive fashion by setting
   * Ineractive to Off and sizing/placing the overlay renderer in its parent
   * renderer by calling the widget's SetViewport method.
   *
   * @par Thanks:
   * This class was based originally on Paraview's vtkPVAxesWidget.
   *
   * @warning
   * The input orientation marker prop should calculate its bounds as though they
   * are symmetric about it's origin.  This must currently be done to correctly
   * implement the camera synchronization between the ivar renderer and the
   * renderer associated with the set interactor.  Importantly, the InteractorStyle
   * associated with the interactor must be of the type vtkInteractorStyle*Camera.
   * Where desirable, the parent renderer should be set by the SetDefaultRenderer
   * method.  The parent renderer's number of layers is modified to 2 where
   * required.
   *
   * @sa
   * vtkInteractorObserver vtkXYPlotWidget vtkScalarBarWidget vtkAxesActor
   * vtkAnnotatedCubeActor
  */
  
  #ifndef vtkOrientationMarkerWidget_h
  #define vtkOrientationMarkerWidget_h
  
  #include "vtkInteractionWidgetsModule.h" // For export macro
  #include "vtkInteractorObserver.h"
  
  class vtkActor2D;
  class vtkPolyData;
  class vtkProp;
  class vtkOrientationMarkerWidgetObserver;
  class vtkRenderer;
  
  class VTKINTERACTIONWIDGETS_EXPORT vtkOrientationMarkerWidget : public vtkInteractorObserver
  {
  public:
    static vtkOrientationMarkerWidget* New();
    vtkTypeMacro(vtkOrientationMarkerWidget, vtkInteractorObserver);
    void PrintSelf(ostream& os, vtkIndent indent) override;
  
    //@{
    /**
     * Set/get the orientation marker to be displayed in this widget.
     */
    virtual void SetOrientationMarker(vtkProp *prop);
    vtkGetObjectMacro(OrientationMarker, vtkProp);
    //@}
  
    /**
     * Enable/disable the widget. Default is 0 (disabled).
     */
    void SetEnabled(int) override;
  
    /**
     * Callback to keep the camera for the orientation marker up to date with the
     * camera in the parent renderer.
     */
    void ExecuteCameraUpdateEvent(vtkObject *o, unsigned long event, void *calldata);
  
    //@{
    /**
     * Set/get whether to allow this widget to be interactively moved/scaled.
     * Default is On.
     */
    void SetInteractive(int state);
    vtkGetMacro(Interactive, int);
    vtkBooleanMacro(Interactive, int);
    //@}
  
    //@{
    /**
     * Set/get the color of the outline of this widget.  The outline is visible
     * when (in interactive mode) the cursor is over this widget.
     * Default is white (1,1,1).
     */
    void SetOutlineColor(double r, double g, double b);
    double *GetOutlineColor();
    //@}
  
    //@{
    /**
     * Set/get the viewport to position/size this widget.
     * Coordinates are expressed as (xmin,ymin,xmax,ymax), where each
     * coordinate is 0 <= coordinate <= 1.0.
     * Default is bottom left corner (0,0,0.2,0.2).
     * Note that this viewport is scaled with respect to the viewport of the
     * current renderer i.e. if the viewport of the current renderer is
     * (0.5, 0.5, 0.75, 0.75) and Viewport is set to (0, 0, 1, 1), the orientation
     * marker will be confined to a viewport of (0.5, 0.5, 0.75, 0.75) in the
     * render window.
     * \sa SetCurrentRenderer()
     */
    vtkSetVector4Macro(Viewport, double);
    vtkGetVector4Macro(Viewport, double);
    //@}
  
    //@{
    /**
     * The tolerance representing the distance to the widget (in pixels)
     * in which the cursor is considered to be on the widget, or on a
     * widget feature (e.g., a corner point or edge).
     */
    vtkSetClampMacro(Tolerance,int,1,10);
    vtkGetMacro(Tolerance,int);
    //@}
  
    //@{
    /**
     * Need to reimplement this->Modified() because of the
     * vtkSetVector4Macro/vtkGetVector4Macro use
     */
    void Modified() override;
    //@}
  
  protected:
    vtkOrientationMarkerWidget();
    ~vtkOrientationMarkerWidget() override;
  
    vtkRenderer *Renderer;
    vtkProp     *OrientationMarker;
    vtkPolyData *Outline;
    vtkActor2D  *OutlineActor;
  
    unsigned long StartEventObserverId;
  
    static void ProcessEvents(vtkObject *object, unsigned long event,
                              void *clientdata, void *calldata);
  
    // ProcessEvents() dispatches to these methods.
    virtual void OnLeftButtonDown();
    virtual void OnLeftButtonUp();
    virtual void OnMouseMove();
  
    // observer to update the renderer's camera
    vtkOrientationMarkerWidgetObserver *Observer;
  
    int Interactive;
    int Tolerance;
    int Moving;
  
    // viewport to position/size this widget
    double Viewport[4];
  
    // used to compute relative movements
    int StartPosition[2];
  
    // Manage the state of the widget
    int State;
    enum WidgetState
    {
      Outside = 0,
      Inside,
      Translating,
      AdjustingP1,
      AdjustingP2,
      AdjustingP3,
      AdjustingP4
    };
  
  
    // use to determine what state the mouse is over, edge1 p1, etc.
    // returns a state from the WidgetState enum above
    virtual int ComputeStateBasedOnPosition(int X, int Y, int *pos1, int *pos2);
  
    // set the cursor to the correct shape based on State argument
    virtual void SetCursor(int state);
  
    // adjust the viewport depending on state
    void MoveWidget(int X, int Y);
    void ResizeTopLeft(int X, int Y);
    void ResizeTopRight(int X, int Y);
    void ResizeBottomLeft(int X, int Y);
    void ResizeBottomRight(int X, int Y);
  
    void SquareRenderer();
    void UpdateOutline();
  
    // Used to reverse compute the Viewport ivar with respect to the current
    // renderer viewport
    void UpdateViewport();
    // Used to compute and set the viewport on the internal renderer based on the
    // Viewport ivar. The computed viewport will be with respect to the whole
    // render window
    void UpdateInternalViewport();
  
  private:
    vtkOrientationMarkerWidget(const vtkOrientationMarkerWidget&) = delete;
    void operator=(const vtkOrientationMarkerWidget&) = delete;
  };
  
  #endif
  