Logo ROOT   6.10/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;
72  fPointerClass = 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) {
353  fGUI->SetNodePtr(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);
423  CountMembers(fPointerClass, fTopNode, fPointer);
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
439  fLevelMembersCount.Clear();
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);
453  TStructNodeProperty* prop;
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) {
485  fPointerClass = TClass::GetClass(clname);
486  } else {
487  fPointerClass = TClass::GetClass(typeid(*a));
488  }
489 
490  if (!fPointerClass) {
491  return;
492  }
493 
494  fPointer = ptr;
495  Prepare();
496  fGUI->SetNodePtr(fTopNode);
497  }
498 }
499 
500 ////////////////////////////////////////////////////////////////////////////////
501 /// Returns color associated with type "typeName"
502 
503 TColor TStructViewer::GetColor(const char* typeName)
504 {
505  TIter it(&fColors);
506  TStructNodeProperty* prop;
507  while((prop = (TStructNodeProperty*) it())) {
508  if (!strcmp(prop->GetName(), typeName)) {
509  return prop->GetColor();
510  }
511  }
512 
513  return TColor();
514 }
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
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 Prepare()
Create top node and find all member nodes.
void SetNodeType(ENodeType type)
Sets type of node to "type".
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:31
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
TColor GetColor() const
Returns color of class.
TExMap GetLevelSize() const
Returns TExMap with pairs <level number, size of level in bytes>
void Draw(Option_t *option="")
Draw object if there is valid pointer.
Bool_t GetLinksVisibility() const
Get visibility of links between objects.
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3562
TGMainFrame * GetFrame()
Returns pointer to main window.
Basic string class.
Definition: TString.h:129
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2814
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
#define NULL
Definition: RtypesCore.h:88
virtual EDataType GetType() const =0
void SetLinksVisibility(Bool_t val)
ISets links visibility.
void SetAllMembersCount(ULong_t count)
Sets numbers of all members to "number".
void * GetPointer() const
Returns main pointer.
void * GetPointer() const
Return main pointer.
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:135
void Class()
Definition: Class.C:29
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2231
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".
void Reset()
Deleting nodes, maps and array.
A doubly linked list.
Definition: TList.h:43
~TStructViewer()
Destructor. Clean all object after closing the viewer.
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1943
virtual Bool_t HasPointers() const =0
Collection abstract base class.
Definition: TCollection.h:42
unsigned int UInt_t
Definition: RtypesCore.h:42
UInt_t GetLevel() const
Returns actual level of node.
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5348
ULong_t GetTotalSize() const
Returns total size of allocated memory in bytes.
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:1707
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:71
ENodeType
Definition: TStructNode.h:18
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4602
virtual TCanvas * GetCanvas() const
Definition: TPad.h:253
void Reset(Detail::TBranchProxy *x)
const Bool_t kFALSE
Definition: RtypesCore.h:92
The Canvas class.
Definition: TCanvas.h:31
#define ClassImp(name)
Definition: Rtypes.h:336
virtual UInt_t Sizeof() const =0
TExMap GetLevelMembersCount() const
Returns TExMap with pairs <level number, number of objects>
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:19
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:2885
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:353
void SetColor(const TColor &color)
Sets the color to "color".
Mother of all ROOT objects.
Definition: TObject.h:37
virtual UInt_t Size() const =0
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5575
virtual void Add(TObject *obj)
Definition: TList.h:77
void CountMembers(TClass *cl, TStructNode *parent, void *pointer)
Count allocated memory, increase member counters, find child nodes.
ULong_t GetAllMembersCount() const
Returns number of all members in node.
Definition: TStructNode.cxx:95
void SetPointer(void *ptr, const char *clname=NULL)
Set main pointer of class "clname".
TCanvas * GetCanvas()
Returns canvas used to keep TGeoVolumes.
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:364
const Bool_t kTRUE
Definition: RtypesCore.h:91
ULong_t GetMembersCount() const
Returns numbers of members of node.
TColor GetColor(const char *typeName)
Returns color associated with type "typeName".
This class stores a (key,value) pair using an external hash.
Definition: TExMap.h:33
const char * Data() const
Definition: TString.h:347