ROOT  6.06/09
Reference Guide
TStructViewer.cxx
Go to the documentation of this file.
1 // @(#)root/gviz3d:$Id$
2 // Author: Tomasz Sosnicki 18/09/09
3 
4 /************************************************************************
5 * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11 
12 #include "TStructViewer.h"
13 #include "TStructNodeProperty.h"
14 #include "TStructViewerGUI.h"
15 #include "TStructNode.h"
16 
17 #include <TDataMember.h>
19 #include <TClassEdit.h>
20 #include <vector>
21 
23 
24 class TA {
25 public:
26  virtual ~TA() {}
27 };
28 
29 //________________________________________________________________________
30 //////////////////////////////////////////////////////////////////////////
31 //
32 // TStructViewer viewer represents class, struct or other type as an object in 3D space.
33 // At the top of the scene we can see objects which is our pointer. Under it we see
34 // pointers and collection elements. Collection must inherit from TCollection
35 // or be STL collecion.
36 //
37 // We can change the number of visible levels or objects on the scene with the GUI or
38 // methods. The size of geometry objects is proportional to the memory taken by this object
39 // or to the number of members inside this object.
40 //
41 // An easy way to find some class in the viewer is to change the color of the type.
42 // We can connect for example a TF2 class with red color or connect all classes
43 // inheriting from TF2 by adding plus to name. For example typename "TF2+" tells us
44 // that all classes inheriting from TF2 will be red.
45 //
46 // Navigation in viewer is very simple like in usual GLViewer. When you put the mouse over
47 // some object you can see some information about it (e.g. name, size, actual level).
48 // When you double click this object, it becames top object on scene.
49 // Undo and redo operation are supported.
50 //
51 // Begin_Html
52 // <p> In this picture we can see TStructViewer with pointer to TList which contains
53 // other collections and objects of various classes</p>
54 // <img src="gif/TStructViewer1.jpg">
55 // End_Html
56 //
57 // Begin_Html
58 // <p> Other screenshot presents opened TStructNodeEditor</p>
59 // <img src="gif/TStructViewer2.jpg">
60 // End_Html
61 //
62 //
63 //////////////////////////////////////////////////////////////////////////
64 
65 
66 ////////////////////////////////////////////////////////////////////////////////
67 /// Default constructor. An argument "ptr" is a main pointer of type "clname", which should be shown in the viewer
68 
69 TStructViewer::TStructViewer(void* ptr, const char * clname)
70 {
71  fPointer = NULL;
73  fTopNode = NULL;
74 
75  // add default color
76  fColors.Add(new TStructNodeProperty("+", 17));
77 
78  // creating GUI
79  fGUI = new TStructViewerGUI(this, NULL, &fColors);
80 
81  SetPointer(ptr, clname);
82 }
83 
84 ////////////////////////////////////////////////////////////////////////////////
85 /// Destructor. Clean all object after closing the viewer
86 
88 {
89  Reset();
90  fColors.SetOwner();
91  fColors.Clear();
92 }
93 
94 ////////////////////////////////////////////////////////////////////////////////
95 /// Find list with nodes on specified level and add node to this list and increment list of sizes and list of members
96 
98 {
99  TList* list = (TList*)fLevelArray[node->GetLevel()];
100  // if list doesn't exist -> create one
101  if(!list) {
102  fLevelArray[node->GetLevel()] = list = new TList();
103  }
104  list->Add(node);
105 
106  // increase number of members on this level
107  fLevelMembersCount(node->GetLevel())++;
108  // increase size of this level
109  fLevelSize(node->GetLevel()) += size;
110 }
111 
112 ////////////////////////////////////////////////////////////////////////////////
113 /// Count allocated memory, increase member counters, find child nodes
114 
115 void TStructViewer::CountMembers(TClass* cl, TStructNode* parent, void* pointer)
116 {
117  if(!cl) {
118  return;
119  }
120 
121  if (cl->InheritsFrom(TClass::Class())) {
122  return;
123  }
124 
125  //////////////////////////////////////////////////////////////////////////
126  // DATA MEMBERS
127  //////////////////////////////////////////////////////////////////////////
128  // Set up list of RealData so TClass doesn't create a new object itself
129  cl->BuildRealData(parent->GetPointer());
130  TIter it(cl->GetListOfDataMembers());
131  TDataMember* dm;
132  while ((dm = (TDataMember*) it() ))
133  {
134  // increase counters in parent node
135  parent->SetAllMembersCount(parent->GetAllMembersCount() + 1);
136  parent->SetMembersCount(parent->GetMembersCount() + 1);
137 
138  if (dm->Property() & kIsStatic) {
139  continue;
140  }
141 
142 
143  void* ptr = NULL;
144 
145  if(dm->IsaPointer()) {
146  TString trueTypeName = dm->GetTrueTypeName();
147 
148  // skip if pointer to pointer
149  if(trueTypeName.EndsWith("**")) {
150  continue;
151  }
152 
153  if (!pointer) {
154  continue;
155  }
156 
157  void** pptr = (void**)((ULong_t)pointer + dm->GetOffset());
158  ptr = *pptr;
159 
160  if (!ptr) {
161  continue;
162  }
163 
164  if(fPointers.GetValue((ULong_t)ptr)) {
165  continue;
166  } else {
167  fPointers.Add((ULong_t)ptr, (ULong_t)ptr);
168  }
169 
170  ULong_t size = 0;
171  if (TClass* cl2 = TClass::GetClass(dm->GetTypeName())) {
172  size = cl2->Size();
173  }
174 
175  if(size == 0) {
176  size = dm->GetUnitSize();
177  }
178 
179  ENodeType type;
180  if(dm->GetDataType()) { // pointer to basic type
181  type = kBasic;
182  } else {
183  type = kClass;
184  }
185 
186  // creating TStructNode
187  TStructNode* node = new TStructNode(dm->GetName(), dm->GetTypeName(), ptr, parent, size, type);
188  AddNode(node, size);
189 
190  CountMembers(TClass::GetClass(dm->GetTypeName()), node, ptr);
191 
192  // total size = size of parent + size of nodes daughters
193  parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize() - size);
194  // all members of node = all nodes of parent + nodes of daughter - 1 because node is added twice
195  parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount() - 1);
196  } else {
197  ptr = (void*)((ULong_t)pointer + dm->GetOffset());
198 
199  if (!ptr) {
200  continue;
201  }
202  CountMembers(TClass::GetClass(dm->GetTypeName()), parent, ptr);
203  }
204 
205  //////////////////////////////////////////////////////////////////////////
206  // STL COLLECTION
207  //////////////////////////////////////////////////////////////////////////
208  if (dm->IsSTLContainer()) {
209  parent->SetNodeType(kSTLCollection);
210 
211  //it works only for pointer in std object (not pointer)
212  TClass* stlClass = TClass::GetClass(dm->GetTypeName());
213  if (!stlClass) {
214  continue;
215  }
216 
217  TVirtualCollectionProxy* proxy = stlClass->GetCollectionProxy();
218  if (!proxy) {
219  continue;
220  }
221  TVirtualCollectionProxy::TPushPop helper(proxy, ptr);
222 
223  UInt_t count = proxy->Size();
224  parent->SetMembersCount(parent->GetMembersCount() + count);
225 
226  if (!proxy->HasPointers() || proxy->GetType() != kNoType_t) { // only objects or pointers to basic type
227  parent->SetTotalSize(parent->GetTotalSize() + count * proxy->Sizeof());
228  parent->SetAllMembersCount(parent->GetAllMembersCount() + count);
229  } else {
230  TClass* clProxy = proxy->GetValueClass();
231  TString name;
232  TString typeName;
233  // get size of element
234  ULong_t size = 0;
235  if (clProxy) {
236  name = clProxy->GetName();
237  typeName = clProxy->GetName();
238  size = clProxy->Size();
239  } else {
240  continue;
241  }
242 
243  // if there is no dictionary
244  if (size == 0) {
245  size = proxy->Sizeof();
246  }
247 
248  // searching pointer to pointer
249  Bool_t ptp = kFALSE;
250  std::vector<std::string> parts;
251  int loc;
252  TClassEdit::GetSplit(dm->GetTypeName(), parts, loc);
253  std::vector<std::string>::const_iterator iPart = parts.begin();
254  while (iPart != parts.end() && *iPart == "")
255  ++iPart;
256  if (iPart != parts.end() && *iPart != dm->GetTypeName()) {
257  for (std::vector<std::string>::const_iterator iP = iPart,
258  iPE = parts.end(); iP != iPE; ++iP) {
259  if (TString(TClassEdit::ResolveTypedef(iP->c_str(), true).c_str()).EndsWith("**")){
260  ptp = kTRUE;
261  break;
262  }
263  }
264  }
265  if (ptp) {
266  continue;
267  }
268 
269 
270  void* element;
271  for (UInt_t i = 0; i < count ; i++) {
272  element = *(void**)proxy->At(i);
273 
274  if (!element) {
275  continue;
276  }
277  if (clProxy->IsTObject()) {
278  name = ((TObject*) element)->GetName();
279  }
280 
281  // create node
282  TStructNode* node = new TStructNode(name, typeName, element, parent, size, kClass);
283  // add addition information
284  AddNode(node, size);
285  // increase parents counter
286  parent->SetMembersCount(parent->GetMembersCount() + 1);
287 
288  CountMembers(clProxy, node, element);
289  parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize());
290  parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount());
291  }
292  }
293  }
294  }
295 
296  //////////////////////////////////////////////////////////////////////////
297  // COLLECTION
298  //////////////////////////////////////////////////////////////////////////
299  // if our parent node is collection
300  if(cl->InheritsFrom(TCollection::Class())) {
301  // we change type of node to collection
302  parent->SetNodeType(kCollection);
303 
304  // return if invalid pointer to collection
305  if (!pointer) {
306  return;
307  }
308 
309  TIter it2((TCollection*)pointer);
310  TObject* item;
311  // loop through all elements in collection
312  while((item = it2())) {
313  // get size of element
314  ULong_t size = 0;
315  if (TClass* cl3 = item->IsA()){
316  size = cl3->Size();
317  }
318 
319  // if there is no dictionary
320  if (size == 0) {
321  size = sizeof(item);
322  }
323 
324  // create node
325  TStructNode* node = new TStructNode(item->GetName(), item->ClassName(), item, parent, size, kClass);
326  // add addition information
327  AddNode(node, size);
328  // increase parents counter
329  parent->SetMembersCount(parent->GetMembersCount() + 1);
330 
331  CountMembers(item->IsA(), node, item);
332 
333  parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize());
334  parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount());
335  }
336  }
337 }
338 
339 ////////////////////////////////////////////////////////////////////////////////
340 /// Draw object if there is valid pointer
341 
343 {
344  TString opt(option);
345  if(opt == "count") {
346 
347  } else if (opt == "size") {
348 
349  }
350 
351 
352  if (fTopNode) {
354  } else {
355 
356  }
357 }
358 
359 ////////////////////////////////////////////////////////////////////////////////
360 /// Returns canvas used to keep TGeoVolumes
361 
363 {
364  return fGUI->GetCanvas();
365 }
366 
367 ////////////////////////////////////////////////////////////////////////////////
368 /// Returns pointer to main window
369 
371 {
372  return fGUI;
373 }
374 ////////////////////////////////////////////////////////////////////////////////
375 /// Return main pointer
376 
378 {
379  return fPointer;
380 }
381 
382 ////////////////////////////////////////////////////////////////////////////////
383 /// Returns TExMap with pairs <level number, number of objects>
384 
386 {
387  return fLevelMembersCount;
388 }
389 
390 ////////////////////////////////////////////////////////////////////////////////
391 /// Returns TExMap with pairs <level number, size of level in bytes>
392 
394 {
395  return fLevelSize;
396 }
397 
398 ////////////////////////////////////////////////////////////////////////////////
399 /// Get visibility of links between objects
400 
402 {
403  return fGUI->GetLinksVisibility();
404 }
405 
406 ////////////////////////////////////////////////////////////////////////////////
407 /// Create top node and find all member nodes
408 
410 {
411  if (fTopNode) {
412  Reset();
413  }
414 
415  ULong_t size = fPointerClass->Size();
416 
417  TString name = "Main pointer";
418  if (fPointerClass->IsTObject()) {
419  name = ((TObject*) fPointer)->GetName();
420  }
421  fTopNode = new TStructNode(name, fPointerClass->GetName(), fPointer, NULL, size, kClass);
422  AddNode(fTopNode, size);
424 }
425 
426 ////////////////////////////////////////////////////////////////////////////////
427 /// Deleting nodes, maps and array
428 
430 {
431  TList* lst;
432  TIter it(&fLevelArray);
433  while ((lst = (TList*) it() )) {
434  lst->SetOwner();
435  lst->Clear();
436  }
437 
438  // deleting maps and array
440  fLevelSize.Clear();
441  fPointers.Clear();
442  fLevelArray.Clear();
443 
444  fTopNode = NULL;
445 }
446 
447 ////////////////////////////////////////////////////////////////////////////////
448 /// Sets color for the class "name" to color "color"
449 
451 {
452  TIter it(&fColors);
454  while ((prop = (TStructNodeProperty*) it() )) {
455  if (name == prop->GetName()) {
456  prop->SetColor(TColor::GetColor(color));
457  fGUI->Update();
458 
459  return;
460  }
461  }
462 
463  // add color
464  prop = new TStructNodeProperty(name.Data(), color);
465  fColors.Add(prop);
466  fColors.Sort();
467 }
468 
469 ////////////////////////////////////////////////////////////////////////////////
470 /// ISets links visibility
471 
473 {
474  fGUI->SetLinksVisibility(val);
475 }
476 
477 ////////////////////////////////////////////////////////////////////////////////
478 /// Set main pointer of class "clname"
479 
480 void TStructViewer::SetPointer(void* ptr, const char* clname)
481 {
482  if (ptr) {
483  TA* a = (TA*) ptr;
484  if (clname) {
486  } else {
487  fPointerClass = TClass::GetClass(typeid(*a));
488  }
489 
490  if (!fPointerClass) {
491  return;
492  }
493 
494  fPointer = ptr;
495  Prepare();
497  }
498 }
499 
500 ////////////////////////////////////////////////////////////////////////////////
501 /// Returns color associated with type "typeName"
502 
503 TColor TStructViewer::GetColor(const char* typeName)
504 {
505  TIter it(&fColors);
507  while((prop = (TStructNodeProperty*) it())) {
508  if (!strcmp(prop->GetName(), typeName)) {
509  return prop->GetColor();
510  }
511  }
512 
513  return TColor();
514 }
virtual void Clear(Option_t *="")
Definition: TObject.h:110
void Add(ULong64_t hash, Long64_t key, Long64_t value)
Add an (key,value) pair to the table. The key should be unique.
Definition: TExMap.cxx:85
TStructViewer(void *ptr=NULL, const char *clname=NULL)
Default constructor. An argument "ptr" is a main pointer of type "clname", which should be shown in t...
void SetNodePtr(TStructNode *val)
Sets top node pointer and updates view.
void Prepare()
Create top node and find all member nodes.
void Update(Bool_t resetCamera=false)
Updates view. Clear all the nodes, call draw function and update scene. Doesn't reset camera...
void SetLinksVisibility(Bool_t val)
Sets links visibility to "visible".
void SetNodeType(ENodeType type)
Sets type of node to "type".
TExMap GetLevelMembersCount() const
Returns TExMap with pairs
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TObjArray.cxx:297
const char Option_t
Definition: RtypesCore.h:62
virtual TClass * GetValueClass() const =0
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:33
int GetSplit(const char *type, std::vector< std::string > &output, int &nestedLoc, EModType mode=TClassEdit::kNone)
Stores in output (after emptying it) the splited type.
Definition: TClassEdit.cxx:937
TStructNode * fTopNode
Definition: TStructViewer.h:36
void * GetPointer() const
Returns main pointer.
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5552
void Draw(Option_t *option="")
Draw object if there is valid pointer.
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3539
TGMainFrame * GetFrame()
Returns pointer to main window.
Basic string class.
Definition: TString.h:137
void SetMembersCount(ULong_t count)
Sets number of members to "number".
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
TArc * a
Definition: textangle.C:12
const Bool_t kFALSE
Definition: Rtypes.h:92
Bool_t GetLinksVisibility() const
Returns true if links are visible, otherwise return false.
virtual EDataType GetType() const =0
TExMap fPointers
Definition: TStructViewer.h:34
void SetLinksVisibility(Bool_t val)
ISets links visibility.
virtual void Sort(Bool_t order=kSortAscending)
Sort linked list.
Definition: TList.cxx:770
void SetAllMembersCount(ULong_t count)
Sets numbers of all members to "number".
const char * Data() const
Definition: TString.h:349
TStructViewerGUI * fGUI
Definition: TStructViewer.h:31
void Class()
Definition: Class.C:29
ClassImp(TStructViewer)
UInt_t GetLevel() const
Returns actual level of node.
ULong_t GetMembersCount() const
Returns numbers of members of node.
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
void AddNode(TStructNode *node, ULong_t size)
Find list with nodes on specified level and add node to this list and increment list of sizes and lis...
void SetColor(TString name, Int_t color)
Sets color for the class "name" to color "color".
TColor GetColor() const
Returns color of class.
void Reset()
Deleting nodes, maps and array.
A doubly linked list.
Definition: TList.h:47
~TStructViewer()
Destructor. Clean all object after closing the viewer.
ULong_t GetTotalSize() const
Returns total size of allocated memory in bytes.
TClass * fPointerClass
Definition: TStructViewer.h:30
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1937
TExMap fLevelMembersCount
Definition: TStructViewer.h:32
Long64_t GetValue(ULong64_t hash, Long64_t key)
Return the value belonging to specified key and hash value.
Definition: TExMap.cxx:171
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2220
Bool_t GetLinksVisibility() const
Get visibility of links between objects.
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:187
virtual Bool_t HasPointers() const =0
Collection abstract base class.
Definition: TCollection.h:48
unsigned int UInt_t
Definition: RtypesCore.h:42
ULong_t GetAllMembersCount() const
Returns number of all members in node.
Definition: TStructNode.cxx:95
static Int_t GetColor(const char *hexcolor)
Static method returning color number for color specified by hex color string of form: "#rrggbb"...
Definition: TColor.cxx:1666
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:51
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:81
ENodeType
Definition: TStructNode.h:18
The Canvas class.
Definition: TCanvas.h:48
virtual UInt_t Sizeof() const =0
TObjArray fLevelArray
Definition: TStructViewer.h:35
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:415
TExMap GetLevelSize() const
Returns TExMap with pairs
int type
Definition: TGX11.cxx:120
void SetTotalSize(ULong_t size)
Sets total size of allocated memory in bytes to value "size".
unsigned long ULong_t
Definition: RtypesCore.h:51
virtual void * At(UInt_t idx)=0
The color creation and management class.
Definition: TColor.h:23
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2881
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:348
TExMap fLevelSize
Definition: TStructViewer.h:33
bool EndsWith(const std::string &theString, const std::string &theSubstring)
void SetColor(const TColor &color)
Sets the color to "color".
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2810
#define name(a, b)
Definition: linkTestLib0.cpp:5
Mother of all ROOT objects.
Definition: TObject.h:58
virtual UInt_t Size() const =0
virtual void Add(TObject *obj)
Definition: TList.h:81
void CountMembers(TClass *cl, TStructNode *parent, void *pointer)
Count allocated memory, increase member counters, find child nodes.
void SetPointer(void *ptr, const char *clname=NULL)
Set main pointer of class "clname".
#define NULL
Definition: Rtypes.h:82
TCanvas * GetCanvas()
Returns canvas used to keep TGeoVolumes.
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4579
const Bool_t kTRUE
Definition: Rtypes.h:91
void * GetPointer() const
Return main pointer.
TColor GetColor(const char *typeName)
Returns color associated with type "typeName".
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5325
This class stores a (key,value) pair using an external hash.
Definition: TExMap.h:35