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

  Program:   Visualization Toolkit
  Module:    vtkCommand.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   vtkCommand
 * @brief   superclass for callback/observer methods
 *
 * vtkCommand is an implementation of the observer/command design
 * pattern.  In this design pattern, any instance of vtkObject can be
 * "observed" for any events it might invoke. For example,
 * vtkRenderer invokes a StartEvent as it begins to render and a
 * EndEvent when it finishes rendering. Filters (subclasses of
 * vtkProcessObject) invoke StartEvent, ProgressEvent, and EndEvent as
 * the filter processes data. Observers of events are added with the
 * AddObserver() method found in vtkObject.  AddObserver(), besides
 * requiring an event id or name, also takes an instance of vtkCommand
 * (or a subclasses). Note that vtkCommand is meant to be subclassed,
 * so that you can package the information necessary to support your
 * callback.
 *
 * Event processing can be organized in priority lists, so it is
 * possible to truncate the processing of a particular event by
 * setting the AbortFlag variable. The priority is set using the
 * AddObserver() method.  By default the priority is 0, events of the
 * same priority are processed in last-in-first-processed order. The
 * ordering/aborting of events is important for things like 3D
 * widgets, which handle an event if the widget is selected (and then
 * aborting further processing of that event).  Otherwise. the event
 * is passed along for further processing.
 *
 * When an instance of vtkObject invokes an event, it also passes an optional
 * void pointer to a callData. This callData is nullptr most of the time.
 * The callData is not specific to a type of event but specific to a type
 * of vtkObject invoking a specific event. For instance, vtkCommand::PickEvent
 * is invoked by vtkProp with a nullptr callData but is invoked by
 * vtkInteractorStyleImage with a pointer to the vtkInteractorStyleImage object
 * itself.
 *
 * Here is the list of events that may be invoked with a non-nullptr callData.
 * - vtkCommand::ProgressEvent
 *  - most of the objects return a pointer to a double value ranged between
 * 0.0 and 1.0
 *  - Infovis/vtkFixedWidthTextReader returns a pointer to a float value equal
 * to the number of lines read so far.
 * - vtkCommand::ErrorEvent
 *  - an error message as a const char * string
 * - vtkCommand::WarningEvent
 *  - a warning message as a const char * string
 * - vtkCommand::StartAnimationCueEvent
 *  - a pointer to a vtkAnimationCue::AnimationCueInfo object
 * - vtkCommand::EndAnimationCueEvent
 *  - a pointer to a vtkAnimationCue::AnimationCueInfo object
 * - vtkCommand::AnimationCueTickEvent
 *  - a pointer to a vtkAnimationCue::AnimationCueInfo object
 * - vtkCommand::PickEvent
 *  - Common/vtkProp returns nullptr
 *  - Rendering/vtkInteractorStyleImage returns a pointer to itself
 * - vtkCommand::StartPickEvent
 *  - Rendering/vtkPropPicker returns nullptr
 *  - Rendering/vtkInteractorStyleImage returns a pointer to itself
 * - vtkCommand::EndPickEvent
 *  - Rendering/vtkPropPicker returns nullptr
 *  - Rendering/vtkInteractorStyleImage returns a pointer to itself
 * - vtkCommand::WrongTagEvent
 *  - Parallel/vtkSocketCommunicator returns a received tag as a char *
 * - vtkCommand::SelectionChangedEvent
 *  - Views/vtkView returns nullptr
 *  - Views/vtkDataRepresentation returns a pointer to a vtkSelection
 *  - Rendering/vtkInteractorStyleRubberBand2D returns an array of 5 unsigned
 * integers (p1x, p1y, p2x, p2y, mode), where mode is
 * vtkInteractorStyleRubberBand2D::SELECT_UNION or
 * vtkInteractorStyleRubberBand2D::SELECT_NORMAL
 * - vtkCommand::AnnotationChangedEvent
 *  - GUISupport/Qt/vtkQtAnnotationView returns a pointer to a
 * vtkAnnotationLayers
 * - vtkCommand::PlacePointEvent
 *  - Widgets/vtkSeedWidget returns a pointer to an int, being the current
 * handle number
 * - vtkCommand::DeletePointEvent
 *  - Widgets/vtkSeedWidget returns a pointer to an int, being the
 * handle number of the deleted point
 * - vtkCommand::ResetWindowLevelEvent
 *  - Widgets/vtkImagePlaneWidget returns an array of 2 double values (window
 * and level)
 *  - Rendering/vtkInteractorStyleImage returns a pointer to itself
 * - vtkCommand::StartWindowLevelEvent
 *  - Widgets/vtkImagePlaneWidget returns an array of 2 double values (window
 * and level)
 *  - Rendering/vtkInteractorStyleImage returns a pointer to itself
 * - vtkCommand::EndWindowLevelEvent
 *  - Widgets/vtkImagePlaneWidget returns an array of 2 double values (window
 * and level)
 *  - Rendering/vtkInteractorStyleImage returns a pointer to itself
 * - vtkCommand::WindowLevelEvent
 *  - Widgets/vtkImagePlaneWidget returns an array of 2 double values (window
 * and level)
 *  - Rendering/vtkInteractorStyleImage returns a pointer to itself
 * - vtkCommand::CharEvent
 *  - most of the objects return nullptr
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QKeyEvent *
 * - vtkCommand::TimerEvent
 *  - most of the objects return a to an int representing a timer id
 *  - Widgets/vtkHoverWidget returns nullptr
 * - vtkCommand::CreateTimerEvent
 *  - Rendering/vtkGenericRenderWindowInteractor returns a to an int
 * representing a timer id
 * - vtkCommand::DestroyTimerEvent
 *  - Rendering/vtkGenericRenderWindowInteractor returns a to an int
 * representing a timer id
 * - vtkCommand::UserEvent
 *  - most of the objects return nullptr
 *  - Infovis/vtkInteractorStyleTreeMapHover returns a pointer to a vtkIdType
 * representing a pedigree id
 * - vtkCommand::KeyPressEvent
 *  - most of the objects return nullptr
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QKeyEvent*
 * - vtkCommand::KeyReleaseEvent
 *  - most of the objects return nullptr
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QKeyEvent*
 * - vtkCommand::LeftButtonPressEvent
 *  - most of the objects return nullptr
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QMouseEvent*
 * - vtkCommand::LeftButtonReleaseEvent
 *  - most of the objects return nullptr
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QMouseEvent*
 * - vtkCommand::MouseMoveEvent
 *  - most of the objects return nullptr
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QMouseEvent*
 * - vtkCommand::MouseWheelForwardEvent
 *  - most of the objects return nullptr
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QWheelEvent*
 * - vtkCommand::MouseWheelBackwardEvent
 *  - most of the objects return nullptr
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QWheelEvent*
 * - vtkCommand::RightButtonPressEvent
 *  - most of the objects return nullptr
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QMouseEvent*
 * - vtkCommand::RightButtonReleaseEvent
 *  - most of the objects return nullptr
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QMouseEvent*
 * - vtkCommand::MiddleButtonPressEvent
 *  - most of the objects return nullptr
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QMouseEvent*
 * - vtkCommand::MiddleButtonReleaseEvent
 *  - most of the objects return nullptr
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QMouseEvent*
 * - vtkCommand::CursorChangedEvent
 *  - most of the objects return a pointer to an int representing a shape
 *  - Rendering/vtkInteractorObserver returns nullptr
 * - vtkCommand::ResetCameraEvent
 *  - Rendering/vtkRenderer returns a pointer to itself
 * - vtkCommand::ResetCameraClippingRangeEvent
 *  - Rendering/vtkRenderer returns a pointer to itself
 * - vtkCommand::ActiveCameraEvent
 *  - Rendering/vtkRenderer returns a pointer to the active camera
 * - vtkCommand::CreateCameraEvent
 *  - Rendering/vtkRenderer returns a pointer to the created camera
 * - vtkCommand::EnterEvent
 *  - most of the objects return nullptr
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QEvent*
 * - vtkCommand::LeaveEvent
 *  - most of the objects return nullptr
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QEvent*
 * - vtkCommand::RenderWindowMessageEvent
 *  - Rendering/vtkWin32OpenGLRenderWindow return a pointer to a UINT message
 * - vtkCommand::ComputeVisiblePropBoundsEvent
 *  - Rendering/vtkRenderer returns a pointer to itself
 * - QVTKOpenGLStereoWidget::ContextMenuEvent
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QContextMenuEvent*
 * - QVTKOpenGLStereoWidget::DragEnterEvent
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QDragEnterEvent*
 * - QVTKOpenGLStereoWidget::DragMoveEvent
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QDragMoveEvent*
 * - QVTKOpenGLStereoWidget::DragLeaveEvent
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QDragLeaveEvent*
 * - QVTKOpenGLStereoWidget::DropEvent
 *  - GUISupport/Qt/QVTKOpenGLStereoWidget returns a QDropEvent*
 * - vtkCommand::ViewProgressEvent
 *  - View/vtkView returns a ViewProgressEventCallData*
 * - vtkCommand::VolumeMapperRenderProgressEvent
 *  - A pointer to a double value between 0.0 and 1.0
 * - vtkCommand::VolumeMapperComputeGradientsProgressEvent
 *  - A pointer to a double value between 0.0 and 1.0
 * - vtkCommand::TDxMotionEvent (TDx=3DConnexion)
 *  - A vtkTDxMotionEventInfo*
 * - vtkCommand::TDxButtonPressEvent
 *  - A int* being the number of the button
 * - vtkCommand::TDxButtonReleaseEvent
 *  - A int* being the number of the button
 * - vtkCommand::UpdateShaderEvent
 *  - A vtkOpenGLHelper* currently being used
 * - vtkCommand::FourthButtonPressEvent
 *  - most of the objects return nullptr
 * - vtkCommand::FourthButtonReleaseEvent
 *  - most of the objects return nullptr
 * - vtkCommand::FifthButtonPressEvent
 *  - most of the objects return nullptr
 * - vtkCommand::FifthButtonReleaseEvent
 *  - most of the objects return nullptr
 * - vtkCommand::MouseWheelLeftEvent
 *  - most of the objects return nullptr
 *  - GUISupport/Qt/QVTKOpenGLWidget returns a QWheelEvent*
 * - vtkCommand::MouseWheelRightEvent
 *  - most of the objects return nullptr
 *  - GUISupport/Qt/QVTKOpenGLWidget returns a QWheelEvent*
 * - vtkCommand::ErrorEvent
 *  - vtkOutputWindow fires this with `char char*` for the error message
 * - vtkCommand::WarningEvent
 *  - vtkOutputWindow fires this with `char char*` for the warning message
 * - vtkCommand::MessageEvent
 *  - vtkOutputWindow fires this with `char char*` for the message text
 * - vtkCommand::TextEvent
 *  - vtkOutputWindow fires this with `char char*` for the text
 *
 * @sa
 * vtkObject vtkCallbackCommand vtkOldStyleCallbackCommand
 * vtkInteractorObserver vtk3DWidget
 */

#ifndef vtkCommand_h
#define vtkCommand_h

#include "vtkCommonCoreModule.h" // For export macro
#include "vtkObject.h"           // Need vtkTypeMacro
#include "vtkObjectBase.h"

// clang-format off
// Define all types of events here.
// Using this macro makes it possible to avoid mismatches between the event
// enums and their string counterparts.
#define vtkAllEventsMacro()                                                                        \
    _vtk_add_event(AnyEvent)                                                                       \
    _vtk_add_event(DeleteEvent)                                                                    \
    _vtk_add_event(StartEvent)                                                                     \
    _vtk_add_event(EndEvent)                                                                       \
    _vtk_add_event(RenderEvent)                                                                    \
    _vtk_add_event(ProgressEvent)                                                                  \
    _vtk_add_event(PickEvent)                                                                      \
    _vtk_add_event(StartPickEvent)                                                                 \
    _vtk_add_event(EndPickEvent)                                                                   \
    _vtk_add_event(AbortCheckEvent)                                                                \
    _vtk_add_event(ExitEvent)                                                                      \
    _vtk_add_event(LeftButtonPressEvent)                                                           \
    _vtk_add_event(LeftButtonReleaseEvent)                                                         \
    _vtk_add_event(MiddleButtonPressEvent)                                                         \
    _vtk_add_event(MiddleButtonReleaseEvent)                                                       \
    _vtk_add_event(RightButtonPressEvent)                                                          \
    _vtk_add_event(RightButtonReleaseEvent)                                                        \
    _vtk_add_event(EnterEvent)                                                                     \
    _vtk_add_event(LeaveEvent)                                                                     \
    _vtk_add_event(KeyPressEvent)                                                                  \
    _vtk_add_event(KeyReleaseEvent)                                                                \
    _vtk_add_event(CharEvent)                                                                      \
    _vtk_add_event(ExposeEvent)                                                                    \
    _vtk_add_event(ConfigureEvent)                                                                 \
    _vtk_add_event(TimerEvent)                                                                     \
    _vtk_add_event(MouseMoveEvent)                                                                 \
    _vtk_add_event(MouseWheelForwardEvent)                                                         \
    _vtk_add_event(MouseWheelBackwardEvent)                                                        \
    _vtk_add_event(ActiveCameraEvent)                                                              \
    _vtk_add_event(CreateCameraEvent)                                                              \
    _vtk_add_event(ResetCameraEvent)                                                               \
    _vtk_add_event(ResetCameraClippingRangeEvent)                                                  \
    _vtk_add_event(ModifiedEvent)                                                                  \
    _vtk_add_event(WindowLevelEvent)                                                               \
    _vtk_add_event(StartWindowLevelEvent)                                                          \
    _vtk_add_event(EndWindowLevelEvent)                                                            \
    _vtk_add_event(ResetWindowLevelEvent)                                                          \
    _vtk_add_event(SetOutputEvent)                                                                 \
    _vtk_add_event(ErrorEvent)                                                                     \
    _vtk_add_event(WarningEvent)                                                                   \
    _vtk_add_event(StartInteractionEvent)                                                          \
    _vtk_add_event(DropFilesEvent)                                                                 \
    _vtk_add_event(UpdateDropLocationEvent)                                                        \
        /*^ mainly used by vtkInteractorObservers*/                                                \
    _vtk_add_event(InteractionEvent)                                                               \
    _vtk_add_event(EndInteractionEvent)                                                            \
    _vtk_add_event(EnableEvent)                                                                    \
    _vtk_add_event(DisableEvent)                                                                   \
    _vtk_add_event(CreateTimerEvent)                                                               \
    _vtk_add_event(DestroyTimerEvent)                                                              \
    _vtk_add_event(PlacePointEvent)                                                                \
    _vtk_add_event(DeletePointEvent)                                                               \
    _vtk_add_event(PlaceWidgetEvent)                                                               \
    _vtk_add_event(CursorChangedEvent)                                                             \
    _vtk_add_event(ExecuteInformationEvent)                                                        \
    _vtk_add_event(RenderWindowMessageEvent)                                                       \
    _vtk_add_event(WrongTagEvent)                                                                  \
    _vtk_add_event(StartAnimationCueEvent)                                                         \
    _vtk_add_event(ResliceAxesChangedEvent)                                                        \
        /*^ used by vtkAnimationCue*/                                                              \
    _vtk_add_event(AnimationCueTickEvent)                                                          \
    _vtk_add_event(EndAnimationCueEvent)                                                           \
    _vtk_add_event(VolumeMapperRenderEndEvent)                                                     \
    _vtk_add_event(VolumeMapperRenderProgressEvent)                                                \
    _vtk_add_event(VolumeMapperRenderStartEvent)                                                   \
    _vtk_add_event(VolumeMapperComputeGradientsEndEvent)                                           \
    _vtk_add_event(VolumeMapperComputeGradientsProgressEvent)                                      \
    _vtk_add_event(VolumeMapperComputeGradientsStartEvent)                                         \
    _vtk_add_event(WidgetModifiedEvent)                                                            \
    _vtk_add_event(WidgetValueChangedEvent)                                                        \
    _vtk_add_event(WidgetActivateEvent)                                                            \
    _vtk_add_event(ConnectionCreatedEvent)                                                         \
    _vtk_add_event(ConnectionClosedEvent)                                                          \
    _vtk_add_event(DomainModifiedEvent)                                                            \
    _vtk_add_event(PropertyModifiedEvent)                                                          \
    _vtk_add_event(UpdateEvent)                                                                    \
    _vtk_add_event(RegisterEvent)                                                                  \
    _vtk_add_event(UnRegisterEvent)                                                                \
    _vtk_add_event(UpdateInformationEvent)                                                         \
    _vtk_add_event(AnnotationChangedEvent)                                                         \
    _vtk_add_event(SelectionChangedEvent)                                                          \
    _vtk_add_event(UpdatePropertyEvent)                                                            \
    _vtk_add_event(ViewProgressEvent)                                                              \
    _vtk_add_event(UpdateDataEvent)                                                                \
    _vtk_add_event(CurrentChangedEvent)                                                            \
    _vtk_add_event(ComputeVisiblePropBoundsEvent)                                                  \
    _vtk_add_event(TDxMotionEvent)                                                                 \
      /*^ 3D Connexion device event */                                                             \
    _vtk_add_event(TDxButtonPressEvent)                                                            \
      /*^ 3D Connexion device event */                                                             \
    _vtk_add_event(TDxButtonReleaseEvent)                                                          \
      /* 3D Connexion device event */                                                              \
    _vtk_add_event(HoverEvent)                                                                     \
    _vtk_add_event(LoadStateEvent)                                                                 \
    _vtk_add_event(SaveStateEvent)                                                                 \
    _vtk_add_event(StateChangedEvent)                                                              \
    _vtk_add_event(WindowMakeCurrentEvent)                                                         \
    _vtk_add_event(WindowIsCurrentEvent)                                                           \
    _vtk_add_event(WindowFrameEvent)                                                               \
    _vtk_add_event(HighlightEvent)                                                                 \
    _vtk_add_event(WindowSupportsOpenGLEvent)                                                      \
    _vtk_add_event(WindowIsDirectEvent)                                                            \
    _vtk_add_event(WindowStereoTypeChangedEvent)                                                   \
    _vtk_add_event(WindowResizeEvent)                                                              \
    _vtk_add_event(UncheckedPropertyModifiedEvent)                                                 \
    _vtk_add_event(UpdateShaderEvent)                                                              \
    _vtk_add_event(MessageEvent)                                                                   \
    _vtk_add_event(StartSwipeEvent)                                                                \
    _vtk_add_event(SwipeEvent)                                                                     \
    _vtk_add_event(EndSwipeEvent)                                                                  \
    _vtk_add_event(StartPinchEvent)                                                                \
    _vtk_add_event(PinchEvent)                                                                     \
    _vtk_add_event(EndPinchEvent)                                                                  \
    _vtk_add_event(StartRotateEvent)                                                               \
    _vtk_add_event(RotateEvent)                                                                    \
    _vtk_add_event(EndRotateEvent)                                                                 \
    _vtk_add_event(StartPanEvent)                                                                  \
    _vtk_add_event(PanEvent)                                                                       \
    _vtk_add_event(EndPanEvent)                                                                    \
    _vtk_add_event(TapEvent)                                                                       \
    _vtk_add_event(LongTapEvent)                                                                   \
    _vtk_add_event(FourthButtonPressEvent)                                                         \
    _vtk_add_event(FourthButtonReleaseEvent)                                                       \
    _vtk_add_event(FifthButtonPressEvent)                                                          \
    _vtk_add_event(FifthButtonReleaseEvent)                                                        \
    _vtk_add_event(Move3DEvent)                                                                    \
    _vtk_add_event(Button3DEvent)                                                                  \
    _vtk_add_event(TextEvent)                                                                      \
    _vtk_add_event(LeftButtonDoubleClickEvent)                                                     \
    _vtk_add_event(MiddleButtonDoubleClickEvent)                                                   \
    _vtk_add_event(RightButtonDoubleClickEvent)                                                    \
    _vtk_add_event(MouseWheelLeftEvent)                                                            \
    _vtk_add_event(MouseWheelRightEvent)
// clang-format on

#define vtkEventDeclarationMacro(_enum_name)                                                       \
  enum _enum_name                                                                                  \
  {                                                                                                \
    NoEvent = 0,                                                                                   \
    vtkAllEventsMacro() UserEvent = 1000                                                           \
  }

// The superclass that all commands should be subclasses of
class VTKCOMMONCORE_EXPORT vtkCommand : public vtkObjectBase
{
public:
  vtkBaseTypeMacro(vtkCommand, vtkObjectBase);

  /**
   * Decrease the reference count (release by another object). This has
   * the same effect as invoking Delete() (i.e., it reduces the reference
   * count by 1).
   */
  void UnRegister();
  void UnRegister(vtkObjectBase*) override { this->UnRegister(); }

  /**
   * All derived classes of vtkCommand must implement this
   * method. This is the method that actually does the work of the
   * callback. The caller argument is the object invoking the event,
   * the eventId parameter is the id of the event, and callData
   * parameter is data that can be passed into the execute
   * method. (Note: vtkObject::InvokeEvent() takes two parameters: the
   * event id (or name) and call data. Typically call data is nullptr,
   * but the user can package data and pass it this
   * way. Alternatively, a derived class of vtkCommand can be used to
   * pass data.)
   */
  virtual void Execute(vtkObject* caller, unsigned long eventId, void* callData) = 0;

  //@{
  /**
   * Convenience methods for translating between event names and event
   * ids.
   */
  static const char* GetStringFromEventId(unsigned long event);
  static unsigned long GetEventIdFromString(const char* event);
  //@}

  /**
   * Does this event type contain vtkEventData
   */
  static bool EventHasData(unsigned long event);

  /**
   * Set/Get the abort flag. If this is set to true no further
   * commands are executed.
   */
  void SetAbortFlag(int f) { this->AbortFlag = f; }
  int GetAbortFlag() { return this->AbortFlag; }
  void AbortFlagOn() { this->SetAbortFlag(1); }
  void AbortFlagOff() { this->SetAbortFlag(0); }

  /**
   * Set/Get the passive observer flag. If this is set to true, this
   * indicates that this command does not change the state of the
   * system in any way. Passive observers are processed first, and
   * are not called even when another command has focus.
   */
  void SetPassiveObserver(int f) { this->PassiveObserver = f; }
  int GetPassiveObserver() { return this->PassiveObserver; }
  void PassiveObserverOn() { this->SetPassiveObserver(1); }
  void PassiveObserverOff() { this->SetPassiveObserver(0); }

  /**
   * All the currently defined events are listed here.  Developers can
   * use -- vtkCommand::UserEvent + int to specify their own event
   * ids.
   * Add new events by updating vtkAllEventsMacro.
   */
#define _vtk_add_event(Enum) Enum,
  vtkEventDeclarationMacro(EventIds);
#undef _vtk_add_event

protected:
  int AbortFlag;
  int PassiveObserver;

  vtkCommand();
  ~vtkCommand() override = default;

  friend class vtkSubjectHelper;

  vtkCommand(const vtkCommand& c)
    : vtkObjectBase(c)
  {
  }
  void operator=(const vtkCommand&) {}
};

#endif /* vtkCommand_h */

// VTK-HeaderTest-Exclude: vtkCommand.h
