From e436f23b34c10aee871538b3b4894fdf5ede8f2f Mon Sep 17 00:00:00 2001
From: Rene Brun <Rene.Brun@cern.ch>
Date: Wed, 2 Sep 2009 17:57:16 +0000
Subject: [PATCH] From Tomasz: New version of the viewer

git-svn-id: http://root.cern.ch/svn/root/trunk@30023 27541ba8-7e3a-0410-8455-c3a389f83636
---
 graf3d/gviz3d/inc/TStructNodeEditor.h   |   9 +
 graf3d/gviz3d/inc/TStructViewer.h       |  11 +-
 graf3d/gviz3d/inc/TStructViewerGUI.h    |   2 +-
 graf3d/gviz3d/src/TStructNodeEditor.cxx | 111 +++++++++--
 graf3d/gviz3d/src/TStructViewer.cxx     | 246 +++++++++++++++---------
 graf3d/gviz3d/src/TStructViewerGUI.cxx  |  11 +-
 tutorials/gl/gviz3d.C                   |   3 +-
 7 files changed, 269 insertions(+), 124 deletions(-)

diff --git a/graf3d/gviz3d/inc/TStructNodeEditor.h b/graf3d/gviz3d/inc/TStructNodeEditor.h
index bbef2973941..3c556d5fa27 100644
--- a/graf3d/gviz3d/inc/TStructNodeEditor.h
+++ b/graf3d/gviz3d/inc/TStructNodeEditor.h
@@ -21,6 +21,7 @@ class TGNumberEntry;
 class TGLabel;
 class TGTextEntry;
 class TGColorSelect;
+class TGCheckButton;
 
 class TStructNodeEditor : public TGedFrame {
 
@@ -30,12 +31,17 @@ protected:
    TGNumberEntry       *fMaxObjectsNumberEntry; // Sets maximum number of nodes on scene
    TGNumberEntry       *fMaxLevelsNumberEntry;  // Sets maximum number of visible levels on scene
    TGLabel             *fTypeName;              // Label with name of type
+   TGLabel             *fNodeNameLabel;         // Label with name of node
    TGTextEntry         *fNameEntry;             // Text entry with name of property
    TGColorSelect       *fColorSelect;           // Control to selec a color
    TStructNodeProperty *fSelectedPropert;       // Pointer to property associated with node
+   TGTextButton        *fDefaultButton;         // Resets color to default
+   TGTextButton        *fApplyButton;           // Apply changes button
+   TGCheckButton       *fAutoRefesh;           // Condition for auto update
 
    TStructNodeProperty* FindNodeProperty(TStructNode* node);
    TStructNodeProperty* GetDefaultProperty();
+   void                 Init();
 
 public:
    TStructNodeEditor(TList* colors, const TGWindow *p = 0, Int_t width = 140, Int_t height = 30,
@@ -43,8 +49,11 @@ public:
    ~TStructNodeEditor(); 
 
    void  ApplyButtonSlot();
+   void  AutoRefreshButtonSlot(Bool_t on);
    void  ColorSelectedSlot(Pixel_t color);
    void  DefaultButtonSlot();
+   void  MaxLevelsValueSetSlot(Long_t);
+   void  MaxObjectsValueSetSlot(Long_t);
    void  SetModel(TObject* obj);
    void  Update(Bool_t resetCamera);
    void  Update();
diff --git a/graf3d/gviz3d/inc/TStructViewer.h b/graf3d/gviz3d/inc/TStructViewer.h
index a542ae9b953..85e027ddc49 100644
--- a/graf3d/gviz3d/inc/TStructViewer.h
+++ b/graf3d/gviz3d/inc/TStructViewer.h
@@ -26,7 +26,8 @@ class TGMainFrame;
 class TStructViewer : public TObject {
 
 private:
-   TObject          *fPointer;            // Main pointer to represented object
+   void             *fPointer;            // Main pointer to represented object
+   TClass           *fPointerClass;       // TClass of a main pointer
    TStructViewerGUI *fGUI;                // Pointer to GUI class
    TExMap            fLevelMembersCount;  // Contains number of objects on each level
    TExMap            fLevelSize;          // Contains total size in bytes of a level
@@ -43,7 +44,7 @@ private:
    void     Reset();
 
 public:
-   TStructViewer(TObject* ptr = NULL);
+   TStructViewer(void* ptr = NULL, const char * clname = NULL);
    ~TStructViewer();
 
    void     Draw(Option_t *option = "");
@@ -53,12 +54,12 @@ public:
    TExMap   GetLevelMembersCount() const;
    TExMap   GetLevelSize() const;
    Bool_t   GetLinksVisibility() const;
-   TObject *GetPointer() const;
+   void    *GetPointer() const;
    void     SetColor(TString name, Int_t color);
    void     SetLinksVisibility(Bool_t val);
-   void     SetPointer(TObject* ptr);
+   void     SetPointer(void* ptr, const char* clname = NULL);
 
-   ClassDef(TStructViewer, 1); // A 3D struct viewer
+   ClassDef(TStructViewer, 0); // A 3D struct viewer
 };
 
 #endif
diff --git a/graf3d/gviz3d/inc/TStructViewerGUI.h b/graf3d/gviz3d/inc/TStructViewerGUI.h
index df01875383e..6243288ea47 100644
--- a/graf3d/gviz3d/inc/TStructViewerGUI.h
+++ b/graf3d/gviz3d/inc/TStructViewerGUI.h
@@ -73,7 +73,7 @@ private:
    TGTextEntry         *fPointerTypeTextEntry;  // Sets type of pointer
    TStructNodeEditor   *fEditor;                // Frame with a node editor
    TGNumberEntry       *fBoxHeightEntry;        // Height of boxes
-   TGCheckButton       *fAutoRefesh;            // Automatic redraw of the scene
+   TGCheckButton       *fAutoRefesh;            // Automatic redraw the scene
    TGNumberEntry       *fLevelDistanceEntry;    // Distance between levels
    
 private:
diff --git a/graf3d/gviz3d/src/TStructNodeEditor.cxx b/graf3d/gviz3d/src/TStructNodeEditor.cxx
index fce5d8aeb0c..cbf94e6d0b0 100644
--- a/graf3d/gviz3d/src/TStructNodeEditor.cxx
+++ b/graf3d/gviz3d/src/TStructNodeEditor.cxx
@@ -40,10 +40,14 @@ TStructNodeEditor::TStructNodeEditor(TList* colors, const TGWindow *p, Int_t wid
    // Constructor of node attributes GUI.
 
    MakeTitle("TStructNode");
-   fAvoidSignal = kTRUE;
+   fInit = kFALSE;
 
-   fTypeName = new TGLabel(this);
    TGLayoutHints* expandX = new TGLayoutHints(kLHintsLeft | kLHintsExpandX, 5,5,5,5);
+   fNodeNameLabel = new TGLabel(this, "No node selected");
+   this->AddFrame(fNodeNameLabel, expandX);
+
+   fTypeName = new TGLabel(this);
+   
    this->AddFrame(fTypeName, expandX);
 
    TGHorizontalFrame* maxObjectsFrame = new TGHorizontalFrame(this);
@@ -53,6 +57,8 @@ TStructNodeEditor::TStructNodeEditor(TList* colors, const TGWindow *p, Int_t wid
    fMaxObjectsNumberEntry = new TGNumberEntry(maxObjectsFrame, 0);
    fMaxObjectsNumberEntry->SetFormat(TGNumberEntry::kNESInteger);
    fMaxObjectsNumberEntry->SetLimits(TGNumberEntry::kNELLimitMin, 1);
+   fMaxObjectsNumberEntry->SetState(kFALSE);
+   fMaxObjectsNumberEntry->Connect("ValueSet(Long_t)", "TStructNodeEditor", this, "MaxObjectsValueSetSlot(Long_t)");
    maxObjectsFrame->AddFrame(fMaxObjectsNumberEntry);
    this->AddFrame(maxObjectsFrame, expandX);
 
@@ -62,23 +68,36 @@ TStructNodeEditor::TStructNodeEditor(TList* colors, const TGWindow *p, Int_t wid
    fMaxLevelsNumberEntry = new TGNumberEntry(maxLevelFrame, 0);
    fMaxLevelsNumberEntry->SetLimits(TGNumberEntry::kNELLimitMin, 1);
    fMaxLevelsNumberEntry->SetFormat(TGNumberEntry::kNESInteger);
+   fMaxLevelsNumberEntry->SetState(kFALSE);
+   fMaxLevelsNumberEntry->Connect("ValueSet(Long_t)", "TStructNodeEditor", this, "MaxLevelsValueSetSlot(Long_t)");
    maxLevelFrame->AddFrame(fMaxLevelsNumberEntry);
    this->AddFrame(maxLevelFrame, expandX);
 
    fNameEntry = new TGTextEntry(this, fName.Data());
    this->AddFrame(fNameEntry, expandX);
+   fNameEntry->SetState(kFALSE);
 
    fColorSelect = new TGColorSelect(this);
    fColorSelect->Connect("ColorSelected(Pixel_t)", "TStructNodeEditor", this, "ColorSelectedSlot(Pixel_t)");
    this->AddFrame(fColorSelect, expandX);
+   fColorSelect->SetEnabled(kFALSE);
+
+   fAutoRefesh = new TGCheckButton(this, "Auto refesh");
+   fAutoRefesh->SetOn();
+   fAutoRefesh->Connect("Toggled(Bool_t)", "TStructNodeEditor", this, "AutoRefreshButtonSlot(Bool_t)");
+   fAutoRefesh->SetEnabled(kFALSE);
+   this->AddFrame(fAutoRefesh, expandX);
 
-   TGTextButton* defaultButton = new TGTextButton(this, "Default color");
-   defaultButton->Connect("Clicked()", "TStructNodeEditor", this, "DefaultButtonSlot()");
-   this->AddFrame(defaultButton, expandX);
+   fDefaultButton = new TGTextButton(this, "Default color");
+   fDefaultButton->Connect("Clicked()", "TStructNodeEditor", this, "DefaultButtonSlot()");
+   this->AddFrame(fDefaultButton, expandX);
+   fDefaultButton->SetEnabled(kFALSE);
 
-   TGTextButton* applyButton = new TGTextButton(this, "Apply");
-   applyButton->Connect("Clicked()", "TStructNodeEditor", this, "ApplyButtonSlot()");
-   this->AddFrame(applyButton, expandX);
+
+   fApplyButton = new TGTextButton(this, "Apply");
+   fApplyButton->Connect("Clicked()", "TStructNodeEditor", this, "ApplyButtonSlot()");
+   fApplyButton->SetEnabled(kFALSE);
+   this->AddFrame(fApplyButton, expandX);
 }
 
 //______________________________________________________________________________
@@ -112,6 +131,16 @@ void TStructNodeEditor::ApplyButtonSlot()
    Update(needReset);
 }
 
+//________________________________________________________________________
+void TStructNodeEditor::AutoRefreshButtonSlot(Bool_t on)
+{
+   // Activated when user chage condition
+
+   if (on) {
+      Update(kTRUE);
+   }
+}
+
 //______________________________________________________________________________
 void TStructNodeEditor::ColorSelectedSlot(Pixel_t color)
 {
@@ -149,20 +178,12 @@ void TStructNodeEditor::DefaultButtonSlot()
    }
 }
 
-//________________________________________________________________________
-TStructNodeProperty* TStructNodeEditor::GetDefaultProperty()
-{
-   // Returns property with default color 
-
-   return (TStructNodeProperty*)fColors->Last();
-}
-
 //________________________________________________________________________
 TStructNodeProperty* TStructNodeEditor::FindNodeProperty(TStructNode* node)
 {
    // Retruns property associated to the class of given node "node". If property isn't found
    // then returns NULL
-      
+
    TIter it(fColors);
    TStructNodeProperty* prop;
    while ((prop = (TStructNodeProperty*) it() )) {
@@ -185,7 +206,54 @@ TStructNodeProperty* TStructNodeEditor::FindNodeProperty(TStructNode* node)
    return NULL;
 }
 
-//______________________________________________________________________________
+//________________________________________________________________________
+TStructNodeProperty* TStructNodeEditor::GetDefaultProperty()
+{
+   // Returns property with default color 
+
+   return (TStructNodeProperty*)fColors->Last();
+}
+
+//________________________________________________________________________
+void TStructNodeEditor::Init()
+{
+   // Enables button and fields
+
+   fMaxObjectsNumberEntry->SetState(kTRUE);
+   fMaxLevelsNumberEntry->SetState(kTRUE);
+   fNameEntry->SetState(kTRUE);
+   fColorSelect->SetEnabled(kTRUE);
+   fDefaultButton->SetEnabled(kTRUE);
+   fApplyButton->SetEnabled(kTRUE);
+   fAutoRefesh->SetEnabled(kTRUE);
+   fInit = kTRUE;
+}
+
+//________________________________________________________________________
+void TStructNodeEditor::MaxLevelsValueSetSlot(Long_t)
+{
+   // Emmited when user changes maximum number of levels
+
+   fNode->SetMaxLevel(fMaxLevelsNumberEntry->GetIntNumber());
+
+   if(fAutoRefesh->IsOn()) {
+      Update(kTRUE);
+   }
+}
+
+//________________________________________________________________________
+void TStructNodeEditor::MaxObjectsValueSetSlot(Long_t)
+{
+   // Emmited when user changes maximum number of objects
+
+   fNode->SetMaxObjects(fMaxObjectsNumberEntry->GetIntNumber());
+
+   if(fAutoRefesh->IsOn()) {
+      Update(kTRUE);
+   }
+}
+
+//________________________________________________________________________
 void TStructNodeEditor::SetModel(TObject* obj)
 {
    // Pick up the used node attributes.
@@ -201,6 +269,9 @@ void TStructNodeEditor::SetModel(TObject* obj)
    // Type label
    fTypeName->SetText(fNode->GetTypeName());
 
+   // name label
+   fNodeNameLabel->SetText(fNode->GetName());
+
    // Add color property
    fSelectedPropert = FindNodeProperty(fNode);
    if (!fSelectedPropert)
@@ -210,7 +281,9 @@ void TStructNodeEditor::SetModel(TObject* obj)
    fNameEntry->SetText(fSelectedPropert->GetName());
    fColorSelect->SetColor(fSelectedPropert->GetPixel(), kFALSE);
 
-   fAvoidSignal = kFALSE;
+   if (!fInit) {
+      Init();
+   }
 }
 
 //________________________________________________________________________
diff --git a/graf3d/gviz3d/src/TStructViewer.cxx b/graf3d/gviz3d/src/TStructViewer.cxx
index 5fab5fc644c..f0fbf80260b 100644
--- a/graf3d/gviz3d/src/TStructViewer.cxx
+++ b/graf3d/gviz3d/src/TStructViewer.cxx
@@ -16,9 +16,16 @@
 
 #include <TDataMember.h>
 #include <TVirtualCollectionProxy.h>
+#include <TClassEdit.h>
+#include <vector>
 
 ClassImp(TStructViewer);
 
+class A {
+public:
+   virtual ~A() {}
+};
+
 //________________________________________________________________________
 //////////////////////////////////////////////////////////////////////////
 //
@@ -40,26 +47,38 @@ ClassImp(TStructViewer);
 // some object you can see some information about it (e.g. name, size, actual level).
 // When you double click this object, it becames top object on scene.
 // Undo and redo operation are supported. 
+// 
+// Begin_Html
+// <p> In this picture we can see TStructViewer with pointer to TList which contains
+// other collections and objects of various classes</p>
+// <img src="gif/TStructViewer1.jpg">
+// End_Html
+// 
+// Begin_Html
+// <p> Other screenshot presents opened TStructNodeEditor</p>
+// <img src="gif/TStructViewer2.jpg">
+// End_Html
 //
 //
 //////////////////////////////////////////////////////////////////////////
 
 
 //________________________________________________________________________
-TStructViewer::TStructViewer(TObject* ptr)
+TStructViewer::TStructViewer(void* ptr, const char * clname)
 {
-   // Default constructor. An argument "ptr" is a main pointer to TObject, which should be shown in the viewer
+   // Default constructor. An argument "ptr" is a main pointer of type "clname", which should be shown in the viewer
 
+   fPointer = NULL;
+   fPointerClass = NULL;
    fTopNode = NULL;
 
    // add default color 
    fColors.Add(new TStructNodeProperty("+", 17));
 
-   fPointer = ptr;
-   Prepare();
-
    // creating GUI
-   fGUI = new TStructViewerGUI(this, fTopNode, &fColors);
+   fGUI = new TStructViewerGUI(this, NULL, &fColors);
+   
+   SetPointer(ptr, clname);
 }
 
 //________________________________________________________________________
@@ -68,6 +87,8 @@ TStructViewer::~TStructViewer()
    // Destructor. Clean all object after closing the viewer
 
    Reset();
+   fColors.SetOwner();
+   fColors.Clear();
 }
 
 //________________________________________________________________________
@@ -118,82 +139,14 @@ void TStructViewer::CountMembers(TClass* cl, TStructNode* parent, void* pointer)
          continue;
       }
 
-      ENodeType type;
-      if(dm->GetDataType()) {   // pointer to basic type
-         type = kBasic;
-      } else if (dm->IsSTLContainer() == TDataMember::kVector) {
-         type = kSTLCollection;
-
-//             it works only for pointer in std object (not pointer)
-//             TClass* stlClass = TClass::GetClass(dm->GetTypeName());
-//             if (!stlClass) {
-//                continue;
-//             }
-//             
-//             TVirtualCollectionProxy* proxy = stlClass->GetCollectionProxy();
-//             if (!proxy) {
-//                continue;
-//             }
-//             void* ptr = (void*)((ULong_t)pointer + dm->GetOffset());
-//             TVirtualCollectionProxy::TPushPop helper(proxy, ptr);
-// 
-//             UInt_t count = proxy->Size();
-//             parent->SetMembersCount(parent->GetMembersCount() + count);
-//    
-//             if(!proxy->HasPointers() || proxy->GetType()) { // only objects or pointers to basic type
-//                parent->SetTotalSize(parent->GetTotalSize() + count * proxy->Sizeof());
-//                parent->SetAllMembersCount(parent->GetAllMembersCount() + count);
-//             } else {
-//                void* element;
-//                for (UInt_t i = 0; i < count ; i++) {
-//                   element = *(void**)proxy->At(i);
-//    
-//                   if (!element) {
-//                      continue;
-//                   }
-//    
-//                   // get size of element
-//                   ULong_t size = 0;
-//                   TClass* clProxy = proxy->GetValueClass();
-//                   const char * name = "name";
-//                   if (clProxy) {
-//                      if (clProxy->InheritsFrom("TNamed")) {
-//                         name = ((TNamed*) element)->GetName();
-//                      } else {
-//                         name = clProxy->GetName();
-//                      }
-//                      
-//                      size = clProxy->Size();
-//                      
-//                   }
-//    
-//                   // if there is no dictionary
-//                   if (size == 0) {
-//                      size = proxy->Sizeof();
-//                   }
-//    
-//                   // create node
-//                   TStructNode* node = new TStructNode(name, name, element, parent, size, kClass);
-//                   // add addition information
-//                   AddNode(node, size);
-//                   // increase parents counter
-//                   parent->SetMembersCount(parent->GetMembersCount() + 1);
-//    
-//                   //CountMembers(clProxy, node);
-//    
-//                   parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize());
-//                   parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount());
-//                }
-//             }
-      } else {
-         type = kClass;
-      }
+
+      void* ptr = NULL;
 
       if(dm->IsaPointer()) {
          TString trueTypeName = dm->GetTrueTypeName();
 
          // skip if pointer to pointer
-         if(trueTypeName.CountChar('*') > 1) {
+         if(trueTypeName.EndsWith("**")) {
             continue;
          }
 
@@ -202,7 +155,7 @@ void TStructViewer::CountMembers(TClass* cl, TStructNode* parent, void* pointer)
          }
 
          void** pptr = (void**)((ULong_t)pointer + dm->GetOffset());
-         void* ptr = *pptr;
+         ptr = *pptr;
 
          if (!ptr) {
             continue;
@@ -222,6 +175,13 @@ void TStructViewer::CountMembers(TClass* cl, TStructNode* parent, void* pointer)
          if(size == 0) {
             size = dm->GetUnitSize();
          }
+
+         ENodeType type;
+         if(dm->GetDataType()) {   // pointer to basic type
+            type = kBasic;
+         } else {
+            type = kClass;
+         }
             
          // creating TStructNode
          TStructNode* node = new TStructNode(dm->GetName(), dm->GetTypeName(), ptr, parent, size, type);
@@ -234,13 +194,104 @@ void TStructViewer::CountMembers(TClass* cl, TStructNode* parent, void* pointer)
          // all members of node = all nodes of parent + nodes of daughter - 1 because node is added twice
          parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount() - 1);
       } else {
-         void* ptr = (void*)((ULong_t)pointer + dm->GetOffset());
+         ptr = (void*)((ULong_t)pointer + dm->GetOffset());
 
          if (!ptr) {
             continue;
          }
          CountMembers(TClass::GetClass(dm->GetTypeName()), parent, ptr);
       }
+         
+      //////////////////////////////////////////////////////////////////////////
+      // STL COLLECTION
+      //////////////////////////////////////////////////////////////////////////
+      if (dm->IsSTLContainer()) {
+         parent->SetNodeType(kSTLCollection);
+
+         //it works only for pointer in std object (not pointer)
+         TClass* stlClass = TClass::GetClass(dm->GetTypeName());
+         if (!stlClass) {
+            continue;
+         }
+
+         TVirtualCollectionProxy* proxy = stlClass->GetCollectionProxy();
+         if (!proxy) {
+            continue;
+         }
+         TVirtualCollectionProxy::TPushPop helper(proxy, ptr);
+
+         UInt_t count = proxy->Size();
+         parent->SetMembersCount(parent->GetMembersCount() + count);
+
+         if(!proxy->HasPointers() || proxy->GetType()) { // only objects or pointers to basic type
+            parent->SetTotalSize(parent->GetTotalSize() + count * proxy->Sizeof());
+            parent->SetAllMembersCount(parent->GetAllMembersCount() + count);
+         } else {
+            
+            TClass* clProxy = proxy->GetValueClass();
+            TString name;
+            TString typeName;
+            // get size of element
+            ULong_t size = 0;
+            if (clProxy) {
+               name = clProxy->GetName();
+               typeName = clProxy->GetName();
+               size = clProxy->Size();
+            } else {
+               continue;
+            }
+
+            // if there is no dictionary
+            if (size == 0) {
+               size = proxy->Sizeof();
+            }
+
+            // searching pointer to pointer
+            Bool_t ptp = kFALSE;
+            std::vector<std::string> parts;
+            int loc;
+            TClassEdit::GetSplit(dm->GetTypeName(), parts, loc);
+            std::vector<std::string>::const_iterator iPart = parts.begin();
+            while (iPart != parts.end() && *iPart == "")
+               ++iPart;
+            if (iPart != parts.end() && *iPart != dm->GetTypeName()) {
+               for (std::vector<std::string>::const_iterator iP = iPart,
+                  iPE = parts.end(); iP != iPE; ++iP) {
+                     if (TString(TClassEdit::ResolveTypedef(iP->c_str(), true).c_str()).EndsWith("**")){
+                        ptp = kTRUE;
+                        break;
+                     }
+               }
+            }
+            if (ptp) {
+               continue;
+            }
+
+
+            void* element;
+            for (UInt_t i = 0; i < count ; i++) {
+               element = *(void**)proxy->At(i);
+
+               if (!element) {
+                  continue;
+               }
+               if (clProxy->InheritsFrom("TObject")) {
+                  name = ((TObject*) element)->GetName();
+               }
+               
+               // create node
+               TStructNode* node = new TStructNode(name, typeName, element, parent, size, kClass);
+               // add addition information
+               AddNode(node, size);
+               // increase parents counter
+               parent->SetMembersCount(parent->GetMembersCount() + 1);
+
+               CountMembers(clProxy, node, element);
+               parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize());
+               parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount());
+            }
+         }
+      } 
    }
 
    //////////////////////////////////////////////////////////////////////////
@@ -290,6 +341,7 @@ void TStructViewer::CountMembers(TClass* cl, TStructNode* parent, void* pointer)
 void TStructViewer::Draw(Option_t *option)
 {
    // Draw object if there is valid pointer
+
    TString opt(option);
    if(opt == "count") {
       
@@ -321,7 +373,7 @@ TGMainFrame* TStructViewer::GetFrame()
    return fGUI;
 }
 //________________________________________________________________________
-TObject* TStructViewer::GetPointer() const
+void* TStructViewer::GetPointer() const
 {
    // Return main pointer
 
@@ -360,18 +412,15 @@ void TStructViewer::Prepare()
       Reset();
    }
 
-   ULong_t size = 0;
-   if (TClass * cl = fPointer->IsA()) {
-      size = cl->Size();
-   }
-   
-   if(size == 0) {
-      size = sizeof(fPointer);
-   }
+   ULong_t size = fPointerClass->Size();
 
-   fTopNode = new TStructNode(fPointer->GetName(), fPointer->ClassName(), fPointer, NULL, size, kClass);
+   TString name = "Main pointer";
+   if (fPointerClass->InheritsFrom("TObject")) {
+      name = ((TObject*) fPointer)->GetName();
+   }
+   fTopNode = new TStructNode(name, fPointerClass->GetName(), fPointer, NULL, size, kClass);
    AddNode(fTopNode, size);
-   CountMembers(fPointer->IsA(), fTopNode, fPointer);
+   CountMembers(fPointerClass, fTopNode, fPointer);
 }
 
 //________________________________________________________________________
@@ -391,8 +440,6 @@ void TStructViewer::Reset()
    fLevelSize.Clear();
    fPointers.Clear();
    fLevelArray.Clear();
-   fColors.SetOwner();
-   fColors.Clear();
    
    fTopNode = NULL;
 }
@@ -428,11 +475,22 @@ void TStructViewer::SetLinksVisibility(Bool_t val)
 }
 
 //________________________________________________________________________
-void TStructViewer::SetPointer(TObject* ptr)
+void TStructViewer::SetPointer(void* ptr, const char* clname)
 {
-   // Set main pointer
+   // Set main pointer of class "clname"
 
    if (ptr) {
+      A* a = (A*) ptr;
+      if (clname) {
+         fPointerClass = TClass::GetClass(clname);
+      } else {
+         fPointerClass = TClass::GetClass(typeid(*a));
+      }
+
+      if (!fPointerClass) {
+         return;
+      }
+
       fPointer = ptr;
       Prepare();
       fGUI->SetNodePtr(fTopNode);
diff --git a/graf3d/gviz3d/src/TStructViewerGUI.cxx b/graf3d/gviz3d/src/TStructViewerGUI.cxx
index cac61143289..19497303bd2 100644
--- a/graf3d/gviz3d/src/TStructViewerGUI.cxx
+++ b/graf3d/gviz3d/src/TStructViewerGUI.cxx
@@ -674,11 +674,10 @@ void TStructViewerGUI::MouseOverSlot(TGLPhysicalShape* shape)
             fSelectedObject = NULL;
             return;
          }
-         // + 16 skips "represents node "
-         //fSelectedObject = (TStructNode*)(TString(fSelectedObject->GetTitle() + 16).Atoll()); 
          Long_t shapeID  = (Long_t)(shape->GetLogical()->ID());
          Long_t volValue = (Long_t)fVolumes.GetValue(shapeID);
          fSelectedObject = (TStructNode*)volValue;
+         
          fToolTip->SetText(TString(fSelectedObject->GetName()) + "\n" + fSelectedObject->GetTypeName());
          fToolTip->SetPosition(fMouseX, fMouseY);
          fToolTip->Reset();
@@ -780,8 +779,8 @@ void TStructViewerGUI::SetPointerButtonSlot()
 {
    // Sets pointer given in fPointerTestEntry to the main pointer
 
-   TObject* obj = (TObject*)gROOT->ProcessLine(fPointerTextEntry->GetText());
-   fParent->SetPointer(obj);
+   void* obj = (void*)gROOT->ProcessLine(fPointerTextEntry->GetText());
+   fParent->SetPointer(obj, fPointerTypeTextEntry->GetText());
 }
 
 //________________________________________________________________________
@@ -815,6 +814,10 @@ void TStructViewerGUI::Update(Bool_t resetCamera)
 {
    // Updates view. Clear all the nodes, call draw function and update scene. Doesn't reset camera.
 
+   if (!fNodePtr) {
+      return;
+   }
+
    fCanvas->GetListOfPrimitives()->Clear();
    fTopVolume->ClearNodes();
    Draw();
diff --git a/tutorials/gl/gviz3d.C b/tutorials/gl/gviz3d.C
index 856712097a4..3df27f4219f 100644
--- a/tutorials/gl/gviz3d.C
+++ b/tutorials/gl/gviz3d.C
@@ -1,5 +1,4 @@
 // Simple TStructViewer tutorial 
-//Authors: Rene Brun , Tomasz Sosnicki
 
 #include <TRandom.h>
 #include <TList.h>
@@ -50,6 +49,8 @@ void FillColorsMap(TStructViewer* sv)
 
 void gviz3d()
 {
+   // Loading library needed by TStructViewer
+   gSystem->Load("libGviz3d");
    // Creating a pointer to list
    TList* pointer = crazy(2,10);
    // Creating a viewer
-- 
GitLab