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

  Program: 3D Slicer

  Portions (c) Copyright Brigham and Women's Hospital (BWH) All Rights Reserved.

  See COPYRIGHT.txt
  or http://www.slicer.org/copyright/copyright.txt for details.

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.

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

// .NAME vtkMRMLMarkupsDisplayNode - MRML node to represent display properties for markups
// .SECTION Description
// vtkMRMLMarkupsDisplayNode nodes store display properties of markups,
// keeping elements that are applicable to all parts of the markups in this superclass
//

#ifndef __vtkMRMLMarkupsDisplayNode_h
#define __vtkMRMLMarkupsDisplayNode_h

#include "vtkMRMLExport.h"

#include "vtkMRMLDisplayNode.h"
#include "vtkMRMLMarkupsNode.h"

// vtkAddon includes
#include <vtkAddonSetGet.h>

// STD includes
#include <map>

// VTK include
#include <vtkTextProperty.h>

class vtkMRMLInteractionEventData;
class vtkMRMLProceduralColorNode;

class VTK_MRML_EXPORT vtkMRMLMarkupsDisplayNode : public vtkMRMLDisplayNode
{
public:
  static vtkMRMLMarkupsDisplayNode* New();
  vtkTypeMacro(vtkMRMLMarkupsDisplayNode, vtkMRMLDisplayNode);
  void PrintSelf(ostream& os, vtkIndent indent) override;

  //--------------------------------------------------------------------------
  // MRMLNode methods
  //--------------------------------------------------------------------------

  vtkMRMLNode* CreateNodeInstance() override;

  /// Read node attributes from XML (MRML) file
  void ReadXMLAttributes(const char** atts) override;

  /// Write this node's information to a MRML file in XML format.
  void WriteXML(ostream& of, int indent) override;

  /// Copy node content (excludes basic data, such as name and node references).
  /// \sa vtkMRMLNode::CopyContent
  vtkMRMLCopyContentMacro(vtkMRMLMarkupsDisplayNode);

  /// Get node XML tag name (like Volume, Markups)
  const char* GetNodeTagName() override { return "MarkupsDisplay"; };

  /// Finds the storage node and read the data
  void UpdateScene(vtkMRMLScene* scene) override;

  /// Alternative method to propagate events generated in Display nodes
  void ProcessMRMLEvents(vtkObject* /*caller*/, unsigned long /*event*/, void* /*callData*/) override;

  /// Convenience function for getting the displayable markups node
  vtkMRMLMarkupsNode* GetMarkupsNode();

  /// Get name of the default interaction context (typically the mouse)
  static const std::string GetDefaultContextName() { return ""; };

  /// Active component (that the mouse or other interaction context is hovered over).
  /// This property is computed on-the-fly and saved to file.
  /// \param context Name of the interaction context. By default it is empty string, meaning mouse.
  ///   Additional devices, such as virtual reality controllers can specify additional context names.
  ///   This mechanism allows interacting with multiple markups at the same time (user can grab
  ///   different markup points with each controller at the same time).
  int GetActiveComponentType(std::string context = vtkMRMLMarkupsDisplayNode::GetDefaultContextName());
  enum ComponentType
  {
    ComponentNone = 0,
    ComponentControlPoint,
    ComponentCenterPoint,
    ComponentLine,
    ComponentPlane,
    ComponentRotationHandle,
    ComponentTranslationHandle,
    ComponentScaleHandle,
    Component_Last
  };
  struct ComponentInfo
  {
    ComponentInfo()
    {
      this->Type = ComponentNone;
      this->Index = -1;
    }
    int Type;
    int Index;
  };

  /// Index of active component (that the mouse or other interaction context is hovered over).
  /// This property is computed on-the-fly and saved to file.
  /// \param context Name of the interaction context. By default it is empty string, meaning mouse
  int GetActiveComponentIndex(std::string context = vtkMRMLMarkupsDisplayNode::GetDefaultContextName());

  /// Set active component type and index for interaction context (empty by default, meaning mouse)
  void SetActiveComponent(int componentType, int componentIndex, std::string context = vtkMRMLMarkupsDisplayNode::GetDefaultContextName());

  /// Query if there is an active component for any interaction context
  bool HasActiveComponent();

  /// Get list of interaction context names that have active components
  /// \return List of interaction context names that have active components
  std::vector<std::string> GetActiveComponentInteractionContexts();

  /// Set active component index to the provided value and component type to ComponentControlPoint.
  void SetActiveControlPoint(int controlPointIndex);

  /// Convenience method to perform several update operations at once, with minimum number of modified events.
  /// It updates the active control point index (if controlPointIndex<0 then it creates a new point) and
  /// updates its position and orientation.
  /// Returns the control point index (different from the input if the input was < 0).
  int UpdateActiveControlPointWorld(int controlPointIndex,
                                    vtkMRMLInteractionEventData* eventData,
                                    double accurateWorldOrientationMatrix[9],
                                    const char* viewNodeID,
                                    const char* associatedNodeID,
                                    int positionStatus);

  /// Returns index of active control point for all interaction contexts if active component type is
  /// ComponentControlPoint.
  void GetActiveControlPoints(std::vector<int>& controlPointIndices);
  /// Returns index of active control point for interaction context if active component type is
  /// ComponentControlPoint, -1 otherwise.
  /// \param context Name of the interaction context. By default it is empty string, meaning mouse
  int GetActiveControlPoint(std::string context = vtkMRMLMarkupsDisplayNode::GetDefaultContextName());

  ///@{
  /// Constants representing the context in which a Markups control point is being moved.
  ///
  /// - `Markups.MovingInSliceView` stores the layout name of the slice view where the control point is being manipulated.
  /// - `Markups.MovingMarkupIndex` stores the index of the control point currently being moved.
  ///
  /// These attributes are used to track interactions with Markups nodes during user input events.
  static const char* GetMovingInSliceViewAttributeName() { return "Markups.MovingInSliceView"; }
  static const char* GetMovingMarkupIndexAttributeName() { return "Markups.MovingMarkupIndex"; }
  ///@}

  /// Set the text scale of the associated text.
  vtkGetMacro(TextScale, double);
  vtkSetMacro(TextScale, double);

  //@{
  /**
   * Control visibility of control point labels.
   */
  vtkSetMacro(PointLabelsVisibility, bool);
  vtkGetMacro(PointLabelsVisibility, bool);
  vtkBooleanMacro(PointLabelsVisibility, bool);
  //@}

  //@{
  /**
   * Control visibility of information box.
   */
  vtkSetMacro(PropertiesLabelVisibility, bool);
  vtkGetMacro(PropertiesLabelVisibility, bool);
  vtkBooleanMacro(PropertiesLabelVisibility, bool);
  //@}

  //@{
  /**
   * Control visibility of representation fill.
   */
  vtkSetMacro(FillVisibility, bool);
  vtkGetMacro(FillVisibility, bool);
  vtkBooleanMacro(FillVisibility, bool);

  //@{
  /**
   * Control visibility of representation outline.
   */
  vtkSetMacro(OutlineVisibility, bool);
  vtkGetMacro(OutlineVisibility, bool);
  vtkBooleanMacro(OutlineVisibility, bool);

  //@{
  /**
   * Control opacity of representation fill.
   */
  vtkSetMacro(FillOpacity, double);
  vtkGetMacro(FillOpacity, double);
  vtkBooleanMacro(FillOpacity, double);

  //@{
  /**
   * Control opacity of representation edges.
   */
  vtkSetMacro(OutlineOpacity, double);
  vtkGetMacro(OutlineOpacity, double);
  vtkBooleanMacro(OutlineOpacity, double);

  /// Define how points are placed and moved in views
  enum SnapModes
  {
    SnapModeUnconstrained,    //< point is moved independently from displayed objects in 3D views (e.g., in parallel with camera plane)
    SnapModeToVisibleSurface, //< point is snapped to any visible surface in 3D views
    // SnapModeToNode //< point is snapped to a specific node, not implemented yet
    SnapMode_Last // insert new items above this line
  };

  /// Which kind of glyph should be used to display this markup?
  /// Vertex2D is supposed to start at 1
  enum GlyphShapes
  {
    GlyphTypeInvalid = 0,
    StarBurst2D,
    Cross2D,
    CrossDot2D,
    ThickCross2D,
    Dash2D,
    Sphere3D,
    Vertex2D,
    Circle2D,
    Triangle2D,
    Square2D,
    Diamond2D,
    Arrow2D,
    ThickArrow2D,
    HookedArrow2D,
    GlyphType_Last // insert new types above this line
  };
  /// Return the min/max glyph types, for iterating over them in tcl
  static int GetMinimumGlyphType() { return 1; };
  static int GetMaximumGlyphType() { return vtkMRMLMarkupsDisplayNode::GlyphType_Last - 1; };

  /// The glyph type used to display this fiducial
  vtkSetMacro(GlyphType, int);
  vtkGetMacro(GlyphType, int);
  /// Returns 1 if the type is a 3d one, 0 else
  int GlyphTypeIs3D(int glyphType);
  int GlyphTypeIs3D() { return this->GlyphTypeIs3D(this->GlyphType); };

  /// Return a string representing the glyph type, set it from a string
  const char* GetGlyphTypeAsString();
  void SetGlyphTypeFromString(const char* glyphString);

  static const char* GetGlyphTypeAsString(int g);
  static int GetGlyphTypeFromString(const char*);

  /// Specifies if position of control points are snapped to selected surfaces
  /// \sa SnapModes
  vtkSetMacro(SnapMode, int);
  vtkGetMacro(SnapMode, int);

  static const char* GetSnapModeAsString(int g);
  static int GetSnapModeFromString(const char*);

  /// Get/Set markup point size relative to the window size.
  /// This value is only used in slice views and only if SliceUseGlyphScale is set to true.
  /// Diameter of the point is defined as percentage of "window size".
  /// "Window size" is computed as diagonal size of the screen multiplied by ScreenScaleFactor
  /// (stored in the view node).
  vtkSetMacro(GlyphScale, double);
  vtkGetMacro(GlyphScale, double);

  /// Get/Set absolute markup point size.
  /// This value is used in 3D views. This value is used in slice views if SliceUseGlyphScale is set to false.
  /// Diameter of the point is defined as "scale" percentage of diagonal size of the window.
  vtkSetMacro(GlyphSize, double);
  vtkGetMacro(GlyphSize, double);

  /// This flag controls if GlyphScale relative or GlyphSize absolute size is used
  /// to determine size of point glyphs.
  /// On by default (GlyphScale is used for point sizing in 2D views).
  /// \sa SetGlyphScale, SetGlyphSize
  vtkSetMacro(UseGlyphScale, bool);
  vtkGetMacro(UseGlyphScale, bool);
  vtkBooleanMacro(UseGlyphScale, bool);

  enum
  {
    ResetToDefaultsEvent = 19001, //< reset this node to the default values, request completed by markups logic
    JumpToPointEvent,             /**< request jump to a selected control point, request completed by markups logic,
                                  event data is vtkMRMLInteractionEventData*/
    ActionEvent,                  /**< this event is invoked in on the display node if the widget performs WidgetEventAction action
                                  (mapped to double-click interaction event by default), event data is vtkMRMLInteractionEventData */
    CustomActionEvent1,           /**< this event is invoked in on the display node if the widget performs WidgetEventCustomAction1 action
                           (not mapped to any interaction event by default but it can be specified by modules to specify additional
                           actions for a widget), event data is vtkMRMLInteractionEventData */
    CustomActionEvent2,           /**< this event is invoked in on the display node if the widget performs WidgetEventCustomAction2 action
                          (not mapped to any interaction event by default but it can be specified by modules to specify additional
                          actions for a widget), event data is vtkMRMLInteractionEventData */
    CustomActionEvent3,           /**< this event is invoked in on the display node if the widget performs WidgetEventCustomAction3 action
                            (not mapped to any interaction event by default but it can be specified by modules to specify additional
                            actions for a widget), event data is vtkMRMLInteractionEventData */
    CustomActionEvent4,           /**< this event is invoked in on the display node if the widget performs WidgetEventCustomAction4 action
                            (not mapped to any interaction event by default but it can be specified by modules to specify additional
                            actions for a widget), event data is vtkMRMLInteractionEventData */
    CustomActionEvent5,           /**< this event is invoked in on the display node if the widget performs WidgetEventCustomAction5 action
                            (not mapped to any interaction event by default but it can be specified by modules to specify additional
                            actions for a widget), event data is vtkMRMLInteractionEventData */
    CustomActionEvent6,           /**< this event is invoked in on the display node if the widget performs WidgetEventCustomAction6 action
                            (not mapped to any interaction event by default but it can be specified by modules to specify additional
                            actions for a widget), event data is vtkMRMLInteractionEventData */
  };

  /// Set SliceProjection flag that controls if the projection of markups
  /// is visible or not in 2D viewers on slices on which it is normally
  /// not visible.
  /// Off by default
  /// \sa SliceIntersectionVisibility, SliceProjectionColor
  vtkSetMacro(SliceProjection, bool);
  vtkGetMacro(SliceProjection, bool);
  vtkBooleanMacro(SliceProjection, bool);

  /// Set projection color to be the same as the fiducial color
  /// On by default
  vtkSetMacro(SliceProjectionUseFiducialColor, bool);
  vtkGetMacro(SliceProjectionUseFiducialColor, bool);
  vtkBooleanMacro(SliceProjectionUseFiducialColor, bool);

  /// Set projection's view different if under/over/in the plane
  /// Off by default
  vtkSetMacro(SliceProjectionOutlinedBehindSlicePlane, bool);
  vtkGetMacro(SliceProjectionOutlinedBehindSlicePlane, bool);
  vtkBooleanMacro(SliceProjectionOutlinedBehindSlicePlane, bool);

  /// Set color of the projection on the 2D viewers
  /// White (1.0, 1.0, 1.0) by default.
  vtkSetVector3Macro(SliceProjectionColor, double);
  vtkGetVector3Macro(SliceProjectionColor, double);

  /// Set opacity of projection on the 2D viewers
  /// 0.6 by default
  vtkSetClampMacro(SliceProjectionOpacity, double, 0.0, 1.0);
  vtkGetMacro(SliceProjectionOpacity, double);

  /// Way of determining line radius of markup curves. Default is relative thickness
  /// Current mode is stored in \sa CurveLineSizeMode
  enum CurveLineSizeModes
  {
    UseLineThickness = 0,
    UseLineDiameter,
    CurveLineSizeMode_Last // insert new types above this line
  };

  /// Configure mode of determining line radius of markup curves.
  /// Default is relative thickness. Available modes in \sa CurveLineSizeModes
  vtkSetMacro(CurveLineSizeMode, int);
  vtkGetMacro(CurveLineSizeMode, int);
  const char* GetCurveLineSizeModeAsString();
  void SetCurveLineSizeModeFromString(const char* modeString);
  static const char* GetCurveLineSizeModeAsString(int mode);
  static int GetCurveLineSizeModeFromString(const char*);

  /// Configure line thickness
  /// Thickness is specified relative to markup point size
  /// (1.0 means line diameter is the same as diameter of point glyphs).
  /// This relative value is used if \sa CurveLineSizeMode is UseLineThickness
  /// For absolute control of thickness, \sa LineDiameter should be used.
  vtkGetMacro(LineThickness, double);
  vtkSetMacro(LineThickness, double);

  /// Configure line diameter
  /// Diameter is specified in absolute mm value
  /// This absolute value is used if \sa CurveLineSizeMode is UseLineDiameter
  /// For relative control of diameter, \sa LineThickness should be used.
  vtkGetMacro(LineDiameter, double);
  vtkSetMacro(LineDiameter, double);

  /// Configure the line color fading appearance
  /// Default value = 1.0
  vtkGetMacro(LineColorFadingStart, double);
  vtkSetMacro(LineColorFadingStart, double);

  /// Configure the line color fading appearance
  /// Default value = 10.0
  vtkGetMacro(LineColorFadingEnd, double);
  vtkSetMacro(LineColorFadingEnd, double);

  /// Configures the line color fading appearance
  /// Default value = 1.0
  vtkSetClampMacro(LineColorFadingSaturation, double, 0.0, 1.0);
  vtkGetMacro(LineColorFadingSaturation, double);

  /// Configures the line color fading appearance
  /// Default value = 0.0
  vtkSetClampMacro(LineColorFadingHueOffset, double, 0.0, 1.0);
  vtkGetMacro(LineColorFadingHueOffset, double);

  /// Show or hide direction markers (arrows) along the curve/line.
  /// Default value = false
  vtkSetMacro(LineDirectionVisibility, bool);
  vtkGetMacro(LineDirectionVisibility, bool);
  vtkBooleanMacro(LineDirectionVisibility, bool);

  /// Show direction markers in 3D views (effective only when LineDirectionVisibility is true).
  /// Default value = true
  vtkSetMacro(LineDirectionVisibility3D, bool);
  vtkGetMacro(LineDirectionVisibility3D, bool);
  vtkBooleanMacro(LineDirectionVisibility3D, bool);

  /// Show direction markers in 2D slice views (effective only when LineDirectionVisibility is true).
  /// Default value = true
  vtkSetMacro(LineDirectionVisibility2D, bool);
  vtkGetMacro(LineDirectionVisibility2D, bool);
  vtkBooleanMacro(LineDirectionVisibility2D, bool);

  /// Base multiplier applied to LineDirectionMarkerScale before converting to physical size.
  /// Ensures that at the default scale (150%) the marker is clearly visible relative to the line.
  static constexpr double LineDirectionMarkerBaseScaleFactor = 3.0;

  /// Size of the line direction marker relative to the physical line thickness, expressed as a decimal fraction
  /// (1.0 = 100% = same as line thickness, 1.5 = 150% = one and a half times the line thickness).
  /// Default value = 1.5 (150% of line thickness)
  vtkSetMacro(LineDirectionMarkerScale, double);
  vtkGetMacro(LineDirectionMarkerScale, double);

  /// Distance between consecutive line direction markers relative to the physical marker height
  /// (1.0 = 100% = markers touch, 2.0 = 200% = one gap-width between markers).
  /// Default value = 2.0 (200% of marker height)
  vtkSetMacro(LineDirectionMarkerSpacingScale, double);
  vtkGetMacro(LineDirectionMarkerSpacingScale, double);

  /// Direction of the line direction markers (arrows) along the curve/line.
  /// If true, the arrows point from the first to the last control point of the curve/line.
  /// Default value = true
  vtkSetMacro(LineDirectionFirstToLastControlPoint, bool);
  vtkGetMacro(LineDirectionFirstToLastControlPoint, bool);
  vtkBooleanMacro(LineDirectionFirstToLastControlPoint, bool);

  /// Show or hide slice line intersection point markers in 2D slice views.
  /// These markers indicate where curves/lines cross the slice plane.
  /// Default value = false
  vtkSetMacro(LineSliceIntersectionPointVisibility, bool);
  vtkGetMacro(LineSliceIntersectionPointVisibility, bool);
  vtkBooleanMacro(LineSliceIntersectionPointVisibility, bool);

  /// Set the line color node ID used for the projection on the line actors on the 2D viewers.
  /// Setting a line color node allows to define any arbitrary color mapping.
  /// Setting a line color node will overwrite the settings given by the
  /// color, opacity and LineColorFading variables of the displayNode.
  virtual void SetLineColorNodeID(const char* lineColorNodeID);

  /// Get the line color node ID used for the projection on the line actors on the 2D viewers.
  const char* GetLineColorNodeID();

  /// Get the line color node used for the projection on the line actors on the 2D viewers.
  vtkMRMLProceduralColorNode* GetLineColorNode();
  virtual const char* GetLineColorNodeReferenceRole();

  /// Displays the occluded regions of the markup on top of other objects.
  /// Opacity can be adjusted with OccludedOpacity
  /// \sa SetOccludedOpacity, GetOccludedOpacity
  vtkGetMacro(OccludedVisibility, bool);
  vtkSetMacro(OccludedVisibility, bool);
  vtkBooleanMacro(OccludedVisibility, bool);

  /// Opacity of the occluded parts of the markup.
  /// 0.0 results in the markup being fully transparent, while 1.0 is fully opaque.
  /// \sa SetOccludedVisibility, GetOccludedVisibility
  vtkGetMacro(OccludedOpacity, double);
  vtkSetMacro(OccludedOpacity, double);

  /// Text property object that controls the display properties of text actors in 2D and 3D.
  /// The text object property controls background color/opacity, frame size/color, font, etc.
  /// This function always returns a valid vtkTextProperty pointer.
  vtkGetObjectMacro(TextProperty, vtkTextProperty);

  /// Set the active color of the markup. This color is used when the mouse pointer hovers over a markup.
  vtkSetVector3Macro(ActiveColor, double);
  /// Get the active color of the markup. This color is used when the mouse pointer hovers over a markup.
  vtkGetVector3Macro(ActiveColor, double);

  //@{
  /// The visibility and interactability of the interaction handles
  vtkGetMacro(HandlesInteractive, bool);
  vtkSetMacro(HandlesInteractive, bool);
  vtkBooleanMacro(HandlesInteractive, bool);
  vtkGetMacro(TranslationHandleVisibility, bool);
  vtkSetMacro(TranslationHandleVisibility, bool);
  vtkBooleanMacro(TranslationHandleVisibility, bool);
  vtkGetMacro(RotationHandleVisibility, bool);
  vtkSetMacro(RotationHandleVisibility, bool);
  vtkBooleanMacro(RotationHandleVisibility, bool);
  vtkGetMacro(ScaleHandleVisibility, bool);
  vtkSetMacro(ScaleHandleVisibility, bool);
  vtkBooleanMacro(ScaleHandleVisibility, bool);
  void SetHandleVisibility(int handleType, bool visibility);
  bool GetHandleVisibility(int handleType);
  //@}

  //@{
  /// Get/Set interaction handle size relative to the window size.
  /// Diameter of the interaction handle points is defined as "scale" percentage of diagonal size of the window.
  vtkSetMacro(InteractionHandleScale, double);
  vtkGetMacro(InteractionHandleScale, double);
  //@}

  //@{
  /// Get/Set the visibility of the individual handle axes
  /// The order of the vector is: [X, Y, Z, ViewPlane]
  /// "ViewPlane" scale/translation allows transformations to take place along the active view plane.
  /// (ex. center translation point and ROI corner scale handles.
  vtkSetVector4Macro(RotationHandleComponentVisibility, bool);
  vtkGetVector4Macro(RotationHandleComponentVisibility, bool);
  vtkSetVector4Macro(ScaleHandleComponentVisibility, bool);
  vtkGetVector4Macro(ScaleHandleComponentVisibility, bool);
  vtkSetVector4Macro(TranslationHandleComponentVisibility, bool);
  vtkGetVector4Macro(TranslationHandleComponentVisibility, bool);
  //@}

  /// Get data set containing the scalar arrays for this node type.
  /// For markups it is the curve poly data
  virtual vtkDataSet* GetScalarDataSet() override;
  /// Return the current active scalar array (based on active scalar name and location)
  virtual vtkDataArray* GetActiveScalarArray() override;

  /// Update scalar range and update markups pipeline when the active scalar array is changed
  virtual void UpdateAssignedAttribute() override;

  virtual void SetScalarVisibility(int visibility) override;

  /// Get flag indicating if the markups node can display scale handles
  vtkGetMacro(CanDisplayScaleHandles, bool);

protected:
  vtkMRMLMarkupsDisplayNode();
  ~vtkMRMLMarkupsDisplayNode() override;
  vtkMRMLMarkupsDisplayNode(const vtkMRMLMarkupsDisplayNode&);
  void operator=(const vtkMRMLMarkupsDisplayNode&);

  // Set the text style from a string
  // String format follows html-style conventions
  void SetTextPropertyFromString(std::string textPropertyString);

  // Return a string representing the text style
  // String format follows html-style conventions
  std::string GetTextPropertyAsString();

  /// Current active point or widget component type and index (hovered by the mouse or other interaction context)
  /// Map interaction context identifier (empty string for mouse) to component type enum
  std::map<std::string, ComponentInfo> ActiveComponents;

  int SnapMode;

  bool PropertiesLabelVisibility;
  bool PointLabelsVisibility;
  bool FillVisibility;
  bool OutlineVisibility;
  double FillOpacity;
  double OutlineOpacity;
  double TextScale;
  int GlyphType;
  double GlyphScale;
  double GlyphSize;
  bool UseGlyphScale;

  bool SliceProjection;
  bool SliceProjectionUseFiducialColor;
  bool SliceProjectionOutlinedBehindSlicePlane;
  double SliceProjectionColor[3];
  double SliceProjectionOpacity;

  virtual const char* GetLineColorNodeReferenceMRMLAttributeName();

  static const char* LineColorNodeReferenceRole;
  static const char* LineColorNodeReferenceMRMLAttributeName;

  int CurveLineSizeMode;
  double LineThickness;
  double LineDiameter;

  double LineColorFadingStart;
  double LineColorFadingEnd;
  double LineColorFadingSaturation;
  double LineColorFadingHueOffset;

  bool LineDirectionVisibility;
  bool LineDirectionVisibility3D;
  bool LineDirectionVisibility2D;
  double LineDirectionMarkerScale;
  double LineDirectionMarkerSpacingScale;
  bool LineDirectionFirstToLastControlPoint;
  bool LineSliceIntersectionPointVisibility;

  bool OccludedVisibility;
  double OccludedOpacity;

  vtkTextProperty* TextProperty;

  double ActiveColor[3];

  bool HandlesInteractive;
  bool TranslationHandleVisibility;
  bool RotationHandleVisibility;
  bool ScaleHandleVisibility;
  double InteractionHandleScale;

  bool RotationHandleComponentVisibility[4];
  bool ScaleHandleComponentVisibility[4];
  bool TranslationHandleComponentVisibility[4];

  bool CanDisplayScaleHandles;
};
#endif
