[vtk-developers] [Paraview-developers] Moving vtkMemberFunctionCommand to VTK

Utkarsh Ayachit utkarsh.ayachit at kitware.com
Mon Oct 4 12:29:45 EDT 2010


Folks,

Attached is an possible implementation for the same.

Any comments?

Utkarsh

On Mon, Sep 27, 2010 at 9:14 AM, Utkarsh Ayachit
<utkarsh.ayachit at kitware.com> wrote:
> Not a bad idea at all. Internally, we can still do what we do
> currently to avoid making any dramatic changes. But, API-wise will
> make our lives much easier. Let's hope some of the VTK veterans
> comment :).
>
> Utkarsh
>
> On Sun, Sep 26, 2010 at 7:04 PM, David Doria <daviddoria at gmail.com> wrote:
>> On Fri, Sep 24, 2010 at 12:38 PM, Utkarsh Ayachit
>> <utkarsh.ayachit at kitware.com> wrote:
>>>
>>> Couple of suggestions:
>>>
>>> 1> I think we should change the API to be:
>>>
>>> SetCallback(ClassT* ...) rather than SetCallback(ClassT& ..)
>>>
>>> That makes the mode more VTK-like when reading:
>>>
>>> I'd prefer:
>>>
>>> obs->SetCallback(this, &vtkMySelf::CallbackHandler);
>>>
>>> to the current implementation i.e.:
>>>
>>> obs->SetCallback(*this, &vtkMySelf::CallbackHandler);
>>>
>>> 2> We should use vtkWeakPointer for the Object ptr, to avoid dangling
>>> pointers.
>>>
>>> 3> The documentation needs to be fixed. Currently there are errors in
>>> it, the usage described does not really match the real usage :).
>>>
>>> 4> Another possibility is simply moving the code to vtkCommand.h.
>>>
>>> Like David said, let's wait a week to see if people respond, otherwise
>>> I will make those changes and move the header to VTK/Common.
>>>
>>> Utkarsh
>>>
>>
>> Is there a way to skip the adapter all together? That is, rather than:
>> adapter = vtkMemberFunctionCommand<CustomStyle>::New();
>> adapter->SetCallback(*this, &CustomStyle::CatchWidgetEvent);
>> tracer->AddObserver(vtkCommand::EndInteractionEvent, this->Adapter);
>> could we just do something like:
>> tracer->AddClassObserver(vtkCommand::EndInteractionEvent, CatchWidgetEvent);
>> and have it automatically deal with the 'this' pointer and the name of the
>> class?
>> David
>
-------------- next part --------------
commit 22aace7564a8b1b1cf44c99f52be45f96d956078
Author: Utkarsh Ayachit <utkarsh.ayachit at kitware.com>
Date:   Mon Oct 4 12:27:01 2010 -0400

    Added API to vtkObject to directly add class member as a event callback.
    
    Added new API to vtkObject to add a class' member function as a callback to
    call when a event is triggered.

diff --git a/Common/vtkObject.cxx b/Common/vtkObject.cxx
index 34cc181..7617a08 100644
--- a/Common/vtkObject.cxx
+++ b/Common/vtkObject.cxx
@@ -18,6 +18,7 @@
 #include "vtkDebugLeaks.h"
 #include "vtkGarbageCollector.h"
 #include "vtkTimeStamp.h"
+#include "vtkWeakPointer.h"
 
 #include <vtkstd/map>
 
@@ -673,6 +674,79 @@ void vtkSubjectHelper::PrintSelf(ostream& os, vtkIndent indent)
     }  
 }
 
+
+//----------------------------------------------------------------------------
+namespace
+{
+  template<class T>
+    class VTK_EXPORT vtkClassMemberCallbackHelper : public vtkCommand
+    {
+    typedef vtkClassMemberCallbackHelper<T> ThisT;
+
+  public:
+    typedef vtkCommand Superclass;
+
+    virtual const char* GetClassNameInternal() const { return "vtkClassMemberCallbackHelper"; }
+
+    static ThisT* SafeDownCast(vtkObjectBase* o)
+      {
+      return dynamic_cast<ThisT*>(o);
+      }
+
+    static ThisT* New()
+      {
+      return new ThisT();
+      }
+
+    // Description:
+    // Set which class instance and member function will be called when a VTK
+    // event is received.
+    void SetCallback(T& object, void (T::*method)())
+      {
+      this->Object = &object;
+      this->Method = method;
+      }
+
+    void SetCallback(T& object,
+      void (T::*method2)(vtkObject*, unsigned long, void*))
+      {
+      this->Object = &object;
+      this->Method2 = method2;
+      }
+
+    virtual void Execute(vtkObject* caller, unsigned long event, void* calldata)
+      {
+      if (this->Object && this->Method)
+        {
+        (this->Object->*this->Method)();
+        }
+      if (this->Object && this->Method2)
+        {
+        (this->Object->*this->Method2)(caller, event, calldata);
+        }
+      }
+  private:
+    vtkClassMemberCallbackHelper()
+      {
+      this->Object = 0;
+      this->Method = 0;
+      this->Method2 = 0;
+      }
+
+    ~vtkClassMemberCallbackHelper()
+      {
+      }
+
+    vtkWeakPointer<T> Object;
+    void (T::*Method)();
+    void (T::*Method2)(
+      vtkObject* caller, unsigned long event, void* calldata);
+
+    vtkClassMemberCallbackHelper(const vtkClassMemberCallbackHelper&); // Not implemented
+    void operator=(const vtkClassMemberCallbackHelper&); // Not implemented
+    };
+}
+
 //--------------------------------vtkObject observer-----------------------
 unsigned long vtkObject::AddObserver(unsigned long event, vtkCommand *cmd, float p)
 {
@@ -684,6 +758,33 @@ unsigned long vtkObject::AddObserver(unsigned long event, vtkCommand *cmd, float
 }
 
 //----------------------------------------------------------------------------
+template <class T>
+unsigned long vtkObject::AddObserver(unsigned long event,
+  T* observer, void (T::*callback)(), float priority)
+{
+  vtkClassMemberCallbackHelper<T> helper =
+    vtkClassMemberCallbackHelper<T>::New();
+  helper->SetCallback(*observer, callback);
+  unsigned long id = this->AddObserver(event, helper, priority);
+  helper->Delete();
+  return id;
+}
+
+//----------------------------------------------------------------------------
+template <class T>
+unsigned long vtkObject::AddObserver(unsigned long event,
+  T* observer, void (T::*callback)(vtkObject*, unsigned long, void*),
+  float priority)
+{
+  vtkClassMemberCallbackHelper<T> helper =
+    vtkClassMemberCallbackHelper<T>::New();
+  helper->SetCallback(*observer, callback);
+  unsigned long id = this->AddObserver(event, helper, priority);
+  helper->Delete();
+  return id;
+}
+
+//----------------------------------------------------------------------------
 unsigned long vtkObject::AddObserver(const char *event,vtkCommand *cmd, float p)
 {
   return this->AddObserver(vtkCommand::GetEventIdFromString(event), cmd, p);
diff --git a/Common/vtkObject.h b/Common/vtkObject.h
index 3e15587..bb09192 100644
--- a/Common/vtkObject.h
+++ b/Common/vtkObject.h
@@ -125,6 +125,14 @@ public:
                             float priority=0.0f);
   unsigned long AddObserver(const char *event, vtkCommand *, 
                             float priority=0.0f);
+
+  template <class T>
+  unsigned long AddObserver(unsigned long event,
+    T* observer, void (T::*callback)(), float priority=0.0f);
+  template <class T>
+  unsigned long AddObserver(unsigned long event,
+    T* observer, void (T::*callback)(vtkObject*, unsigned long, void*),
+    float priority=0.0f);
   vtkCommand *GetCommand(unsigned long tag);
   void RemoveObserver(vtkCommand*);
   void RemoveObservers(unsigned long event, vtkCommand *);


More information about the vtk-developers mailing list