vtkObject类
????????vtkObject类是VTK中大多数类的基类; ????????vtkObject类提供了很多API用于跟踪对象修改时间,debug消息,打印类堆栈,以及事件回调; ????????vtkObject类和它众多派生类构成了VTK框架; ????????少数例外情况往往是非常小的帮助器类,它们通常永远不会被实例化,或者是在多重继承妨碍的情况下。 ????????vtkObject还执行引用计数:引用计数的对象存在,只要其他对象使用它们。 ???????? 一旦删除对引用计数对象的最后一个引用,该对象将自动销毁。] ????????注意:1.VTK中的对象应该使用New和Delete申请和释放; ???????????????????2.VTK对象不会被分配在栈空间内,是因为构造函数被设置为protected方法;
#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
vtkObserver类
? ? ? ? vtkObserver类声明定义在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;
};
vtkCommand类
????????vtkCommand类是观察者/命令设计模式的实现。 ????????在这种设计模式中,任何vtkObject实例都可以被“观察”到它可能调用的任何事件。 ????????例如,vtkRenderer在开始渲染时调用 StartEvent,在完成渲染时调用 EndEvent。过滤器(vtkProcessObject 的子类)在过滤器处理数据时调用 StartEvent、ProgressEvent 和 EndEvent。 ????????使用vtkObject中的 AddObserver()方法添加事件的观察者。AddObserver()除了需要事件 id 或名称外,还需要一个vtkCommand实例(或子类)。注意vtkCommand旨在被子类化,以便可以打包支持回调所需的信息。
????????事件处理可以组织在优先级列表中,因此可以通过设置AbortFlag变量来截断特定事件的处理。使用AddObserver()方法设置优先级。默认情况下优先级为0,相同优先级的事件按后处理顺序处理。事件的排序或中止对于诸如3D小部件之类的事情很重要,如果选择了小部件,它们会处理一个事件(然后中止对该事件的进一步处理)。除此以外。该事件被传递以进行进一步处理。
????????当vtkObject的实例调用事件时,它还将一个可选的void指针传递给callData。这个callData大多数时候是nullptr。callData不是特定于事件类型,而是特定于调用特定事件的vtkObject类型。例如,vtkCommand::PickEvent由vtkProp调用,带有nullptr callData,但由vtkInteractorStyleImage调用,并带有指向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;
}
}
vtkSubjectHelper类
????????vtkSubjectHelper类,是vtkObject的内部类,它保存了一个观察者(observers)列表,并向他们分发事件,还会调用与观察者关联的vtkCommand。
????????vtkSubjectHelper类位于vtkObject.cxx文件中;
????????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;
};
????????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);
}
}
|