Lectura de código fuente VTK: modo de comando/observador de clase vtkObject

clase vtkObject

        La clase vtkObject es la clase base de la mayoría de las clases en VTK;
        la clase vtkObject proporciona muchas API para rastrear el tiempo de modificación de objetos, mensajes de depuración, imprimir pilas de clases y devoluciones de llamadas de eventos; la
        clase vtkObject y sus muchas clases derivadas constituyen el marco VTK;
        un pocas excepciones El caso tiende a ser clases auxiliares muy pequeñas que generalmente nunca se instancian, o donde la herencia múltiple se interpone.
        vtkObject también realiza el recuento de referencias: los objetos contados por referencia existen siempre que otros objetos los utilicen.
         Una vez que se elimina la última referencia a un objeto contado de referencia, el objeto se destruye automáticamente. ]
        Nota: 1. Los objetos en VTK deben aplicarse y liberarse usando Nuevo y Eliminar
                   2. Los objetos VTK no se asignarán en el espacio de la pila porque el constructor está configurado como un método protegido;

#ifndef vtkObject_h
#define vtkObject_h

#include "vtkCommonCoreModule.h" // For export macro
#include "vtkObjectBase.h"
#include "vtkSetGet.h"
#include "vtkTimeStamp.h"
#include "vtkWeakPointerBase.h" // needed for vtkWeakPointer

class vtkSubjectHelper;
class vtkCommand;

class VTKCOMMONCORE_EXPORT vtkObject : public vtkObjectBase
{
public:
  vtkBaseTypeMacro(vtkObject, vtkObjectBase);

  // 创建一个对象,关闭Debug标识;
  // 时间戳初始为0,启用引用计数
  static vtkObject* New();

#ifdef _WIN32
  // avoid dll boundary problems
  void* operator new(size_t tSize);
  void operator delete(void* p);
#endif

  // Turn debugging output on.
  virtual void DebugOn();
  // Turn debugging output off.
  virtual void DebugOff();
  // Get the value of the debug flag.
  bool GetDebug();
  // Set the value of the debug flag. A true value turns debugging on.
  void SetDebug(bool debugFlag);

  // 执行vtkErrorMacro时调用此方法。它允许调试器在出错时中断。
  static void BreakOnError();

  // 更新对象的时间戳--修改时间;
  // 许多过滤器依靠修改时间来确定是否需要重新计算数据。
  // 修改时间是唯一的单调递增无符号长整数。
  virtual void Modified();

  // 返回对象的修改次数
  virtual vtkMTimeType GetMTime();

  // print调用的方法,用于打印有关对象(包括超类)的信息。
  // 通常不由用户调用(改为使用Print()),而是在分层打印过程中用于组合多个类的输出。
  void PrintSelf(ostream& os, vtkIndent indent) override;

  // 这是一个全局标志,用于控制是否显示任何调试、警告或错误消息。
  static void SetGlobalWarningDisplay(int val);
  static void GlobalWarningDisplayOn() { vtkObject::SetGlobalWarningDisplay(1); }
  static void GlobalWarningDisplayOff() { vtkObject::SetGlobalWarningDisplay(0); }
  static int GetGlobalWarningDisplay();

  // 允许用户对任意的VTK对象添加、删除以及调用观察者的回调函数;
  // 是观察者模式的实例;
  // 当需要通过指定要响应的事件和要执行的vtkCommand时,可以添加一个观察者。
  // 它返回一个unsigned long的tag,可在以后用于删除event或检索command。
  // 在调用events时,将按照events添加的顺序调用观察者。
  // 如果指定了优先级值,则优先级高的commands先被调用。
  // 一个command可以设置一个跳出abort标识flag,用于停止event的执行;
  unsigned long AddObserver(unsigned long event, vtkCommand*, float priority = 0.0f);
  unsigned long AddObserver(const char* event, vtkCommand*, float priority = 0.0f);
  vtkCommand* GetCommand(unsigned long tag);
  void RemoveObserver(vtkCommand*);
  void RemoveObservers(unsigned long event, vtkCommand*);
  void RemoveObservers(const char* event, vtkCommand*);
  vtkTypeBool HasObserver(unsigned long event, vtkCommand*);
  vtkTypeBool HasObserver(const char* event, vtkCommand*);

  void RemoveObserver(unsigned long tag);
  void RemoveObservers(unsigned long event);
  void RemoveObservers(const char* event);
  void RemoveAllObservers(); // remove every last one of them
  vtkTypeBool HasObserver(unsigned long event);
  vtkTypeBool HasObserver(const char* event);

  // AddObserver的重载,允许开发人员添加类成员函数作为事件的回调。
  // 回调函数有两种类型:
  //    1. void foo(void);
  //    2. void foo(vtkObject*, unsigned long, void*);
  // 如果回调函数是vtkObjectBase派生对象的成员函数,那么如果对象被析构,回调将自动禁用(但观察者不会自动删除)。
  // 如果回调函数是任何其他类型对象的成员,则必须在对象销毁之前删除观察者,否则下次事件发生时将使用其死指针。
  // 这些函数的典型用法如下:
  //    SomeClassOfMine* observer = SomeClassOfMine::New();
  //    to_observe->AddObserver(event, observer, &SomeClassOfMine::SomeMethod);
  // 返回值是一个tag,可以根据tag删除观察者。
  // 请注意,这不会影响vtkObjectBase派生的观察者的参考计数,在观察者仍在原位的情况下,可以安全地删除这些参考计数。
  // 对于非vtkObjectBase观察者,在移除观察者之前,不应删除该观察者。
  template <class U, class T>
  unsigned long AddObserver(
    unsigned long event, U observer, void (T::*callback)(), float priority = 0.0f)
  {
    vtkClassMemberCallback<T>* callable = new vtkClassMemberCallback<T>(observer, callback);
    // 当观察者被清理后,callable也将被删除(look at vtkObjectCommandInternal)
    return this->AddTemplatedObserver(event, callable, priority);
  }
  template <class U, class T>
  unsigned long AddObserver(unsigned long event, U observer,
    void (T::*callback)(vtkObject*, unsigned long, void*), float priority = 0.0f)
  {
    vtkClassMemberCallback<T>* callable = new vtkClassMemberCallback<T>(observer, callback);
    // 当观察者被清理后,callable也将被删除(look at vtkObjectCommandInternal)
    return this->AddTemplatedObserver(event, callable, priority);
  }

  // 允许用户使用回调方法的返回值设置AbortFlagOn
  template <class U, class T>
  unsigned long AddObserver(unsigned long event, U observer,
    bool (T::*callback)(vtkObject*, unsigned long, void*), float priority = 0.0f)
  {
    vtkClassMemberCallback<T>* callable = new vtkClassMemberCallback<T>(observer, callback);

    // 当观察者被清理后,callable也将被删除(look at vtkObjectCommandInternal)
    return this->AddTemplatedObserver(event, callable, priority);
  }

  // 此方法调用一个事件,并返回该事件是否已被中止。
  // 如果事件被中止,则返回值为1,否则为0。
  int InvokeEvent(unsigned long event, void* callData);
  int InvokeEvent(const char* event, void* callData);

  int InvokeEvent(unsigned long event) { return this->InvokeEvent(event, nullptr); }
  int InvokeEvent(const char* event) { return this->InvokeEvent(event, nullptr); }

protected:
  vtkObject();
  ~vtkObject() override;

  void RegisterInternal(vtkObjectBase*, vtkTypeBool check) override;
  void UnRegisterInternal(vtkObjectBase*, vtkTypeBool check) override;

  bool Debug;                      // 开启debug消息开关
  vtkTimeStamp MTime;              // 跟踪对象的修改时间
  vtkSubjectHelper* SubjectHelper; // 观察者列表

  // 这些方法允许一个命令独占地获取所有事件。
  // 一旦事件序列开始,小部件通常会使用这种方法来获取事件。
  // 提供这些方法是为了支持vtkInteractorObserver类中的公共方法。
  // 请注意,这些方法旨在支持vtkInteractorObserver,因为它们使用两个单独的vtkCommand来监视鼠标和按键事件。
  void InternalGrabFocus(vtkCommand* mouseEvents, vtkCommand* keypressEvents = nullptr);
  void InternalReleaseFocus();

private:
  vtkObject(const vtkObject&) = delete;
  void operator=(const vtkObject&) = delete;

  // 以下类(vtkClassMemberCallbackBase、
  // vtkClassMemberCallback和vtkClassMemberHanderPointer)
  // 以及vtkObjectCommandInternal用于支持模板化的AddObserver()重载,
  // 这些重载允许开发人员添加属于类成员函数的事件回调;
  class vtkClassMemberCallbackBase
  {
  public:
    // 回调函数,当事件发生时,被调用;
    virtual bool operator()(vtkObject*, unsigned long, void*) = 0;
    virtual ~vtkClassMemberCallbackBase() {}
  };

  // 这是vtkObjectBase的弱指针,是其他所有对象的常规空指针
  template <class T>
  class vtkClassMemberHandlerPointer
  {
  public:
    void operator=(vtkObjectBase* o)
    {
      // The cast is needed in case "o" has multi-inheritance,
      // to offset the pointer to get the vtkObjectBase.
      if ((this->VoidPointer = dynamic_cast<T*>(o)) == nullptr) {
        // fallback to just using its vtkObjectBase as-is.
        this->VoidPointer = o;
      }
      this->WeakPointer = o;
      this->UseWeakPointer = true;
    }
    void operator=(void* o)
    {
      this->VoidPointer = o;
      this->WeakPointer = nullptr;
      this->UseWeakPointer = false;
    }
    T* GetPointer()
    {
      if (this->UseWeakPointer && !this->WeakPointer.GetPointer()) {
        return nullptr;
      }
      return static_cast<T*>(this->VoidPointer);
    }

  private:
    vtkWeakPointerBase WeakPointer;
    void* VoidPointer;
    bool UseWeakPointer;
  };
  // 支持三种函数类型的回调函数:
  // void function();
  // void function(vtkObject*, unsigned long, void*);
  // bool function(vtkObject*, unsigned long, void*);
  template <class T>
  class vtkClassMemberCallback : public vtkClassMemberCallbackBase
  {
    vtkClassMemberHandlerPointer<T> Handler;
    void (T::*Method1)();
    void (T::*Method2)(vtkObject*, unsigned long, void*);
    bool (T::*Method3)(vtkObject*, unsigned long, void*);
  public:
    vtkClassMemberCallback(T* handler, void (T::*method)())
    {
      this->Handler = handler;
      this->Method1 = method;
      this->Method2 = nullptr;
      this->Method3 = nullptr;
    }

    vtkClassMemberCallback(T* handler, void (T::*method)(vtkObject*, unsigned long, void*))
    {
      this->Handler = handler;
      this->Method1 = nullptr;
      this->Method2 = method;
      this->Method3 = nullptr;
    }

    vtkClassMemberCallback(T* handler, bool (T::*method)(vtkObject*, unsigned long, void*))
    {
      this->Handler = handler;
      this->Method1 = nullptr;
      this->Method2 = nullptr;
      this->Method3 = method;
    }
    ~vtkClassMemberCallback() override {}

    // 当event被调用时,被执行;
    bool operator()(vtkObject* caller, unsigned long event, void* calldata) override
    {
      T* handler = this->Handler.GetPointer();
      if (handler) {
        if (this->Method1) {
          (handler->*this->Method1)();
        }
        else if (this->Method2) {
          (handler->*this->Method2)(caller, event, calldata);
        }
        else if (this->Method3) {
          return (handler->*this->Method3)(caller, event, calldata);
        }
      }
      return false;
    }
  };

  // 由AddObserver的模板类型的变量调用
  unsigned long AddTemplatedObserver(
    unsigned long event, vtkClassMemberCallbackBase* callable, float priority);
  // vtkObjectCommandInternal类对象需要调用AddTemplatedObserver().
  friend class vtkObjectCommandInternal;
};

#endif

clase vtkObserver

        La declaración de la clase vtkObserver se define en el archivo vtkObject.cxx;

// 命令与观察模式被用于调用和分发事件;
// vtkSubjectHelper类持有了一个观察者列表(列表中有实例化的vtkCommand对象)用于响应事件;
class vtkObserver
{
public:
  vtkObserver()
    : Command(nullptr)
    , Event(0)
    , Tag(0)
    , Next(nullptr)
    , Priority(0.0)
  {
  }
  ~vtkObserver()
  {
    this->Command->UnRegister(nullptr);
  }
  // 打印对象内的属性
  void PrintSelf(ostream& os, vtkIndent indent);
  // 与当前观察者关联的命令
  vtkCommand* Command;
  // 事件ID
  unsigned long Event;
  // Tag ID
  unsigned long Tag;
  // 下一个观察者指针,用于构成一个单链表
  vtkObserver* Next;
  // 优先级
  float Priority;
};

clase vtkCommand

        La clase vtkCommand es una implementación del patrón de diseño observador/comando.
        En este patrón de diseño, cualquier instancia de vtkObject puede ser "observada" para cualquier evento que pueda invocar.
        Por ejemplo, vtkRenderer llama a StartEvent cuando comienza a renderizarse y a EndEvent cuando termina de renderizarse. Los filtros (subclases de vtkProcessObject) llaman a StartEvent, ProgressEvent y EndEvent cuando el filtro procesa los datos.
        Utilice el método AddObserver() en vtkObject para agregar observadores de eventos. AddObserver() necesita una instancia (o subclase) de vtkCommand además del ID o nombre del evento. Tenga en cuenta que vtkCommand está destinado a ser subclasificado para que la información necesaria para admitir devoluciones de llamadas pueda empaquetarse.

        El procesamiento de eventos se puede organizar en listas de prioridad, por lo que el procesamiento de eventos específicos se puede truncar configurando la variable AbortFlag. Utilice el método AddObserver() para establecer la prioridad. De forma predeterminada, la prioridad es 0 y los eventos con la misma prioridad se procesan en orden de procesamiento posterior. La secuenciación o cancelación de eventos es importante para cosas como los widgets 3D, que procesan un evento (y luego cancelan el procesamiento posterior de ese evento) si se seleccionan. Aparte de eso. El evento se transmite para su posterior procesamiento.

        Cuando una instancia de vtkObject llama a un evento, también pasa un puntero nulo opcional a callData. Este callData es nullptr la mayor parte del tiempo. callData no es específico del tipo de evento, sino del tipo de vtkObject que llamó al evento específico. Por ejemplo, vtkProp llama a vtkCommand::PickEvent con nullptr callData, pero lo llama vtkInteractorStyleImage con un puntero al propio objeto vtkInteractorStyleImage.

#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(RightButtonDoubleClickEvent)
// clang-format on

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

// 是所有的command类的基类
class VTKCOMMONCORE_EXPORT vtkCommand : public vtkObjectBase
{
public:
  vtkBaseTypeMacro(vtkCommand, vtkObjectBase);

  // 减少对象的引用计数,效果等同于Delete(),每次减少引用计数1;
  void UnRegister();
  void UnRegister(vtkObjectBase*) override { this->UnRegister(); }
   
  // 所有继承vtkCommand的派生类必须实现Execute;
  // 这其实是实际上执行回调函数工作的方法。
  // caller:调用事件的对象;
  // eventId:事件ID;
  // callData:传入回调函数的参数结构体;
  // 注意:vtkObject::InvokeEvent()接受两个参数:事件ID和传入回调函数的参数结构体;
  //     通常,调用数据callData是nullptr,但用户可以打包数据并以这种方式传递到回调函数中。
  //     或者,可以使用派生的命令类来传递数据。
  virtual void Execute(vtkObject* caller, unsigned long eventId, void* callData) = 0;

  // 在事件名称和事件ID之间转换的方便方法。
  static const char* GetStringFromEventId(unsigned long event);
  static unsigned long GetEventIdFromString(const char* event);

  // 判断event类型事件中是否包含vtkEventData
  static bool EventHasData(unsigned long event);

  // 设置/获取中止标志。
  // 如果设置为true,则不会执行其他命令。
  void SetAbortFlag(int f) { this->AbortFlag = f; }
  int GetAbortFlag() { return this->AbortFlag; }
  void AbortFlagOn() { this->SetAbortFlag(1); }
  void AbortFlagOff() { this->SetAbortFlag(0); }

  // 设置/获取被动观察者标志。
  // 如果标志被设置为true,则表示此command不会以任何方式更改系统的状态。(真.被动也)
  // 被动观察者首先被处理,即使另一个命令有焦点,也不会被调用。
  void SetPassiveObserver(int f) { this->PassiveObserver = f; }
  int GetPassiveObserver() { return this->PassiveObserver; }
  void PassiveObserverOn() { this->SetPassiveObserver(1); }
  void PassiveObserverOff() { this->SetPassiveObserver(0); }

  // 定义了一个Event事件的枚举
  // 用户定义的事件类型从vtkCommand::UserEvent开始,UserEvent+int表示自己的事件ID;
  // vtkAllEventsMacro中使用_vtk_add_event增加新事件;
#define _vtk_add_event(Enum) Enum,
  vtkEventDeclarationMacro(EventIds);
#undef _vtk_add_event

protected:
  // 中断类型
  int AbortFlag;
  // 被动观察者标识
  int PassiveObserver;

  vtkCommand();
  ~vtkCommand() override {}
  
  friend class vtkSubjectHelper;
  vtkCommand(const vtkCommand& c) : vtkObjectBase(c) {}
  void operator=(const vtkCommand&) {}
};

#endif /* vtkCommand_h */

 

 

#include "vtkCommand.h"
#include "vtkDebugLeaks.h"

#ifdef VTK_DEBUG_LEAKS
static const char* leakname = "vtkCommand or subclass";
#endif

vtkCommand::vtkCommand()
  : AbortFlag(0)
  , PassiveObserver(0)
{
#ifdef VTK_DEBUG_LEAKS
  vtkDebugLeaks::ConstructClass(leakname);
#endif
}

void vtkCommand::UnRegister()
{
  int refcount = this->GetReferenceCount() - 1;
  this->SetReferenceCount(refcount);
  if (refcount <= 0) {
#ifdef VTK_DEBUG_LEAKS
    vtkDebugLeaks::DestructClass(leakname);
#endif
    delete this;
  }
}

const char* vtkCommand::GetStringFromEventId(unsigned long event)
{
  switch (event)  {
#define _vtk_add_event(Enum)                                                                       \
  case Enum:                                                                                       \
    return #Enum;

  vtkAllEventsMacro()

#undef _vtk_add_event
    case UserEvent : return "UserEvent";
    case NoEvent:
      return "NoEvent";
  }
  
  // Unknown event. 
  return "NoEvent";
}

unsigned long vtkCommand::GetEventIdFromString(const char* event)
{
  if (event) {

#define _vtk_add_event(Enum)                                                                       \
  if (strcmp(event, #Enum) == 0)                                                                   \
  {                                                                                                \
    return Enum;                                                                                   \
  }

    vtkAllEventsMacro()

#undef _vtk_add_event

    if (strcmp("UserEvent",event) == 0) {
      return vtkCommand::UserEvent;
    }
  }

  return vtkCommand::NoEvent;
}

bool vtkCommand::EventHasData(unsigned long event)
{
  switch (event) {
    // 只有两个事件Button3DEvent和Move3DEvent事件才有Data;
    case vtkCommand::Button3DEvent:
    case vtkCommand::Move3DEvent:
      return true;
    default:
      return false;
  }
}

clase vtkSubjectHelper

        La clase vtkSubjectHelper es una clase interna de vtkObject.Guarda una lista de observadores (observadores), les distribuye eventos y llama al vtkCommand asociado con los observadores.

        La clase vtkSubjectHelper se encuentra en el archivo vtkObject.cxx;

        Declaración de la clase vtkSubjectHelper:

// vtkSubjectHelper类,是vtkObject的内部类,它保存了一个观察者(observers)列表,并向他们分发事件,还会调用与观察者关联的vtkCommand。
class vtkSubjectHelper
{
public:
  vtkSubjectHelper()
    : ListModified(0)
    , Focus1(nullptr)
    , Focus2(nullptr)
    , Start(nullptr)
    , Count(1)
  {
  }
  // 重置成员变量,释放观察者列表内存空间;
  ~vtkSubjectHelper();
  // 增加观察者
  unsigned long AddObserver(unsigned long event, vtkCommand* cmd, float p);
  // 根据tag,从列表中删除一些观察者
  void RemoveObserver(unsigned long tag);
  // 根据事件id,从列表中删除一些观察者
  void RemoveObservers(unsigned long event);
  // 根据事件id和命令,从列表中删除一些观察者
  void RemoveObservers(unsigned long event, vtkCommand* cmd);
  // 删除列表中所有观察者
  void RemoveAllObservers();
  // 调用一个Event对应的Command;
  int InvokeEvent(unsigned long event, void* callData, vtkObject* self);
  // 根据tag,从列表中获取对应的命令信息
  vtkCommand* GetCommand(unsigned long tag);
  unsigned long GetTag(vtkCommand*);
  // 判断观察者列表中是否含有相同的event
  vtkTypeBool HasObserver(unsigned long event);
  // 判断观察者列表中是否含有相同的event和vtkCommand的记录
  vtkTypeBool HasObserver(unsigned long event, vtkCommand* cmd);
  void GrabFocus(vtkCommand* c1, vtkCommand* c2)
  {
    this->Focus1 = c1;
    this->Focus2 = c2;
  }
  void ReleaseFocus()
  {
    this->Focus1 = nullptr;
    this->Focus2 = nullptr;
  }
  // 打印成员属性
  void PrintSelf(ostream& os, vtkIndent indent);
  // 列表改动状态
  int ListModified;

  // This is to support the GrabFocus() methods found in vtkInteractorObserver.
  vtkCommand* Focus1;
  vtkCommand* Focus2;

protected:
  vtkObserver* Start;
  // 用于tag的生成,只用于单调递增,不是Start列表中元素个数;
  unsigned long Count;
};

        Implementación de la clase vtkSubjectHelper:

vtkSubjectHelper::~vtkSubjectHelper()
{
  vtkObserver* elem = this->Start;
  vtkObserver* next;
  while (elem){
    next = elem->Next;
    delete elem;
    elem = next;
  }
  this->Start = nullptr;
  this->Focus1 = nullptr;
  this->Focus2 = nullptr;
}

unsigned long vtkSubjectHelper::AddObserver(unsigned long event, vtkCommand* cmd, float p)
{
  vtkObserver* elem;

  // initialize the new observer element
  // 初始化一个新的观察者节点
  elem = new vtkObserver;
  elem->Priority = p;
  elem->Next = nullptr;
  elem->Event = event;
  elem->Command = cmd;
  cmd->Register(nullptr);
  // Tag是列表的元素个数
  elem->Tag = this->Count;
  this->Count++;

  // now insert into the list
  // if no other elements in the list then this is Start
  // 将elem插入到列表中
  // 如果列表为空,那么elem就是Start,即单链表的首指针
  if (!this->Start) {
    this->Start = elem;
  }
  else {
    // insert high priority first
    vtkObserver* prev = nullptr;
    vtkObserver* pos = this->Start;
    // 列表中根据vtkObserver的优先级排序,前面是高优先级,后面是低优先级;
    // 先找到比elem优先级低的节点位置prev,此时prev的优先级大于等于elem,pos优先级小于elem;
    // 如果没有找到prev位置,那么pos的优先级会高于elem的优先级
    while (pos->Priority >= elem->Priority && pos->Next) {
      prev = pos;
      pos = pos->Next;
    }
    // pos is Start and elem should not be start
    // 如果列表中只有一个节点,或者是链表中所有节点的优先级都大于elem,则elem放到链尾即可;
    if (pos->Priority > elem->Priority) {
      pos->Next = elem;
    }
    else {
      // 如果prev不为空,此时prev应该是中间节点了,这里就是一个单链表插入的步骤了;
      if (prev) {
        prev->Next = elem;
      }
      elem->Next = pos;
      // check to see if the new element is the start
      // 如果elem的优先级比链表首指针还大,那么就是一个头插法;
      // 将Start设置为elem;
      if (pos == this->Start) {
        this->Start = elem;
      }
    }
  }
  return elem->Tag;
}

void vtkSubjectHelper::RemoveObserver(unsigned long tag)
{
  vtkObserver* elem;
  vtkObserver* prev;
  vtkObserver* next;

  elem = this->Start;
  prev = nullptr;
  // 遍历观察者列表,将Tag等于tag的节点全部删除
  while (elem) {
    if (elem->Tag == tag) {
      if (prev) {
        prev->Next = elem->Next;
        next = prev->Next;
      }
      else {
        this->Start = elem->Next;
        next = this->Start;
      }
      delete elem;
      elem = next;
    }
    else {
      prev = elem;
      elem = elem->Next;
    }
  }
  // 更改链表的修改标识:true;
  this->ListModified = 1;
}

void vtkSubjectHelper::RemoveObservers(unsigned long event)
{
  vtkObserver* elem;
  vtkObserver* prev;
  vtkObserver* next;

  elem = this->Start;
  prev = nullptr;
  while (elem) {
    // 遍历观察者列表,将节点内Event等于event的节点全部删除
    if (elem->Event == event)
    {
      if (prev) {
        prev->Next = elem->Next;
        next = prev->Next;
      }
      else {
        this->Start = elem->Next;
        next = this->Start;
      }
      delete elem;
      elem = next;
    }
    else {
      prev = elem;
      elem = elem->Next;
    }
  }

  // 更改链表的修改标识:true;
  this->ListModified = 1;
}

void vtkSubjectHelper::RemoveObservers(unsigned long event, vtkCommand* cmd)
{
  vtkObserver* elem;
  vtkObserver* prev;
  vtkObserver* next;

  elem = this->Start;
  prev = nullptr;
  while (elem) {
    // 遍历观察者列表,将节点内Event等于event且Command等于cmd的节点全部删除
    if (elem->Event == event && elem->Command == cmd) {
      if (prev) {
        prev->Next = elem->Next;
        next = prev->Next;
      }
      else {
        this->Start = elem->Next;
        next = this->Start;
      }
      delete elem;
      elem = next;
    }
    else {
      prev = elem;
      elem = elem->Next;
    }
  }

  // 更改链表的修改标识:true;
  this->ListModified = 1;
}

void vtkSubjectHelper::RemoveAllObservers()
{
  vtkObserver* elem = this->Start;
  vtkObserver* next;
  while (elem) {
    next = elem->Next;
    delete elem;
    elem = next;
  }
  this->Start = nullptr;
}

vtkTypeBool vtkSubjectHelper::HasObserver(unsigned long event)
{
  vtkObserver* elem = this->Start;
  while (elem) {
    if (elem->Event == event || elem->Event == vtkCommand::AnyEvent) {
      return 1;
    }
    elem = elem->Next;
  }
  return 0;
}

vtkTypeBool vtkSubjectHelper::HasObserver(unsigned long event, vtkCommand* cmd)
{
  vtkObserver* elem = this->Start;
  while (elem) {
    if ((elem->Event == event || elem->Event == vtkCommand::AnyEvent) 
        && elem->Command == cmd) {
      return 1;
    }
    elem = elem->Next;
  }
  return 0;
}

int vtkSubjectHelper::InvokeEvent(unsigned long event, void* callData, vtkObject* self)
{
  int focusHandled = 0;

  // 当我们调用事件时,观察者可以添加或删除观察者。
  // 为了确保观察者的迭代顺利进行,我们使用ListModified标识捕捉列表的任何更改。
  // 然而,观察者也可能会做一些事情,导致在这个对象中调用另一个事件。
  // 这意味着这个方法将被递归调用,这意味着我们将删除第一个调用所依赖的ListModified标志。
  // 要解决这个问题,请在栈上保存上一个ListModified值,然后在离开前将其还原。
  int saveListModified = this->ListModified;
  this->ListModified = 0;

  // 我们还需要保存在堆栈上调用的观察器(以免在事件调用中被重写)。
  // 还要确保我们不会调用(在另一个观察者调用期间添加的)任何新观察者。
  typedef std::vector<unsigned long> VisitedListType;
  VisitedListType visited;
  vtkObserver* elem = this->Start;

  // 如果找到了tag大于maxTag的element,这意味着它是在调用InvokeEvent后添加的(作为调用element command的副作用)。
  // 在这种情况下,该element将被丢弃而不执行。
  const unsigned long maxTag = this->Count;

  // 循环两三次,优先选择被动观察者和焦点持有者(如果有的话)。
  // 0.被动观察者循环
  //    循环所有观察者并执行那些被动观察者。
  //    这些观察者不应以任何方式影响系统的状态,也不应被允许中止事件。
  // 1.焦点循环
  //    如果有焦点持有者,循环所有观察者并执行与任一焦点持有者相关的。
  //    将焦点设置为表明焦点持有者处理了事件。
  // 2.剩余循环
  //    如果没有焦点持有者已经处理了该事件,则绕过其余的观察者。
  //    当没有焦点保持器时,该循环将始终执行。

  // 0.被动观察者循环
  // 被动观察者首先被处理,即使另一个命令有焦点,也不会被调用。
  vtkObserver* next;
  while (elem) {
    // 存储下一个指针,因为elem可能会因Command而消失
    next = elem->Next;
    // 获取Command的Passive标识;
    if (elem->Command->GetPassiveObserver() 
        && (elem->Event == event || elem->Event == vtkCommand::AnyEvent) 
        && elem->Tag < maxTag) {
      // lower_bound返回有序序列中可以插入的位置
      VisitedListType::iterator vIter = std::lower_bound(visited.begin(), visited.end(), elem->Tag);
      if (vIter == visited.end() || *vIter != elem->Tag) {
        // 按标签排序插入,以有限的插入成本加快未来的搜索,因为它重用了已经在正确位置的搜索迭代器
        visited.insert(vIter, elem->Tag);
        vtkCommand* command = elem->Command;
        command->Register(command);
        elem->Command->Execute(self, event, callData);
        command->UnRegister();
      }
    }
    if (this->ListModified) {
      vtkGenericWarningMacro(
        << "Passive observer should not call AddObserver or RemoveObserver in callback.");
      elem = this->Start;
      this->ListModified = 0;
    }
    else {
      elem = next;
    }
  }

  // 1.焦点循环
  if (this->Focus1 || this->Focus2) {
    elem = this->Start;
    while (elem) {
      // 存储下一个指针,因为elem可能会因Command而消失
      next = elem->Next;
      if (((this->Focus1 == elem->Command) || (this->Focus2 == elem->Command))
          && (elem->Event == event || elem->Event == vtkCommand::AnyEvent) 
          && elem->Tag < maxTag)
      {
        VisitedListType::iterator vIter =
          std::lower_bound(visited.begin(), visited.end(), elem->Tag);
        if (vIter == visited.end() || *vIter != elem->Tag) {
          // 不执行remainder loop
          focusHandled = 1;
          // 按标签排序插入,以有限的插入成本加快未来的搜索,因为它重用了已经在正确位置的搜索迭代器
          visited.insert(vIter, elem->Tag);
          vtkCommand* command = elem->Command;
          command->Register(command);
          command->SetAbortFlag(0);
          elem->Command->Execute(self, event, callData);
          // if the command set the abort flag, then stop firing events and return
          // 如果命令设置了中止标志,则停止触发事件并返回
          if (command->GetAbortFlag()) {
            command->UnRegister();
            this->ListModified = saveListModified;
            return 1;
          }
          command->UnRegister();
        }
      }
      if (this->ListModified) {
        elem = this->Start;
        this->ListModified = 0;
      }
      else {
        elem = next;
      }
    }
  }

  // 2.剩余循环
  if (!focusHandled) {
    elem = this->Start;
    while (elem) {
      // store the next pointer because elem could disappear due to Command
      next = elem->Next;
      if ((elem->Event == event || elem->Event == vtkCommand::AnyEvent) 
          && elem->Tag < maxTag) {
        VisitedListType::iterator vIter = std::lower_bound(visited.begin(), visited.end(), elem->Tag);
        if (vIter == visited.end() || *vIter != elem->Tag) {
          // Sorted insertion by tag to speed-up future searches at limited
          // insertion cost because it reuses the search iterator already at the
          // correct location
          visited.insert(vIter, elem->Tag);
          vtkCommand* command = elem->Command;
          command->Register(command);
          command->SetAbortFlag(0);
          elem->Command->Execute(self, event, callData);
          // if the command set the abort flag, then stop firing events and return
          if (command->GetAbortFlag()) {
            command->UnRegister();
            this->ListModified = saveListModified;
            return 1;
          }
          command->UnRegister();
        }
      }
      if (this->ListModified) {
        elem = this->Start;
        this->ListModified = 0;
      }
      else {
        elem = next;
      }
    }
  }

  this->ListModified = saveListModified;
  return 0;
}

unsigned long vtkSubjectHelper::GetTag(vtkCommand* cmd)
{
  vtkObserver* elem = this->Start;
  while (elem) {
    if (elem->Command == cmd) {
      return elem->Tag;
    }
    elem = elem->Next;
  }
  return 0;
}

vtkCommand* vtkSubjectHelper::GetCommand(unsigned long tag)
{
  vtkObserver* elem = this->Start;
  while (elem) {
    if (elem->Tag == tag) {
      return elem->Command;
    }
    elem = elem->Next;
  }
  return nullptr;
}

void vtkSubjectHelper::PrintSelf(ostream& os, vtkIndent indent)
{
  os << indent << "Registered Observers:\n";
  indent = indent.GetNextIndent();
  vtkObserver* elem = this->Start;
  if (!elem) {
    os << indent << "(none)\n";
    return;
  }

  for (; elem; elem = elem->Next) {
    elem->PrintSelf(os, indent);
  }
}

Supongo que te gusta

Origin blog.csdn.net/liushao1031177/article/details/124527250
Recomendado
Clasificación