Logo ROOT   6.16/01
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
24class TA {
25public:
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
69TStructViewer::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();
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
115void 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
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()) {
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();
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
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 }
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
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{
475}
476
477////////////////////////////////////////////////////////////////////////////////
478/// Set main pointer of class "clname"
479
480void 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
503TColor 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}
void Class()
Definition: Class.C:29
int Int_t
Definition: RtypesCore.h:41
unsigned int UInt_t
Definition: RtypesCore.h:42
const Bool_t kFALSE
Definition: RtypesCore.h:88
unsigned long ULong_t
Definition: RtypesCore.h:51
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:87
const char Option_t
Definition: RtypesCore.h:62
#define ClassImp(name)
Definition: Rtypes.h:363
@ kNoType_t
Definition: TDataType.h:33
@ kIsStatic
Definition: TDictionary.h:79
int type
Definition: TGX11.cxx:120
ENodeType
Definition: TStructNode.h:18
@ kSTLCollection
Definition: TStructNode.h:23
@ kClass
Definition: TStructNode.h:20
@ kCollection
Definition: TStructNode.h:21
@ kBasic
Definition: TStructNode.h:22
The Canvas class.
Definition: TCanvas.h:31
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
void BuildRealData(void *pointer=0, Bool_t isTransient=kFALSE)
Build a full list of persistent data members.
Definition: TClass.cxx:1940
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3615
Int_t Size() const
Return size of object of this class.
Definition: TClass.cxx:5466
Bool_t IsTObject() const
Return kTRUE is the class inherits from TObject.
Definition: TClass.cxx:5700
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2814
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4720
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
Collection abstract base class.
Definition: TCollection.h:63
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
The color creation and management class.
Definition: TColor.h:19
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:1758
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
const char * GetTrueTypeName() const
Get full type description of data member, e,g.: "class TDirectory*".
Long_t GetOffset() const
Get offset from "this".
Int_t GetUnitSize() const
Get the sizeof the underlying type of the data member (i.e.
Int_t IsSTLContainer()
The return type is defined in TDictionary (kVector, kList, etc.)
Bool_t IsaPointer() const
Return true if data member is a pointer.
TDataType * GetDataType() const
Definition: TDataMember.h:74
const char * GetTypeName() const
Get type of data member, e,g.: "class TDirectory*" -> "TDirectory".
Long_t Property() const
Get property description word. For meaning of bits see EProperty.
This class stores a (key,value) pair using an external hash.
Definition: TExMap.h:33
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:87
Long64_t GetValue(ULong64_t hash, Long64_t key)
Return the value belonging to specified key and hash value.
Definition: TExMap.cxx:173
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual void Clear(Option_t *option="")
Remove all objects from the list.
Definition: TList.cxx:399
virtual void Sort(Bool_t order=kSortAscending)
Sort linked list.
Definition: TList.cxx:933
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual void Clear(Option_t *option="")
Remove all objects from the array.
Definition: TObjArray.cxx:320
Mother of all ROOT objects.
Definition: TObject.h:37
virtual void Clear(Option_t *="")
Definition: TObject.h:100
virtual const char * GetName() const
Returns name of object.
Definition: TObject.cxx:357
virtual const char * ClassName() const
Returns name of class to which the object belongs.
Definition: TObject.cxx:128
Basic string class.
Definition: TString.h:131
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2152
TColor GetColor() const
Returns color of class.
void SetColor(const TColor &color)
Sets the color to "color".
void SetNodeType(ENodeType type)
Sets type of node to "type".
ULong_t GetAllMembersCount() const
Returns number of all members in node.
Definition: TStructNode.cxx:95
ULong_t GetMembersCount() const
Returns numbers of members of node.
void SetMembersCount(ULong_t count)
Sets number of members to "number".
void * GetPointer() const
Returns main pointer.
void SetTotalSize(ULong_t size)
Sets total size of allocated memory in bytes to value "size".
void SetAllMembersCount(ULong_t count)
Sets numbers of all members to "number".
UInt_t GetLevel() const
Returns actual level of node.
ULong_t GetTotalSize() const
Returns total size of allocated memory in bytes.
void SetNodePtr(TStructNode *val)
Sets top node pointer and updates view.
Bool_t GetLinksVisibility() const
Returns true if links are visible, otherwise return false.
void SetLinksVisibility(Bool_t val)
Sets links visibility to "visible".
void Update(Bool_t resetCamera=false)
Updates view. Clear all the nodes, call draw function and update scene. Doesn't reset camera.
TExMap fLevelMembersCount
Definition: TStructViewer.h:32
void Draw(Option_t *option="")
Draw object if there is valid pointer.
TCanvas * GetCanvas()
Returns canvas used to keep TGeoVolumes.
TGMainFrame * GetFrame()
Returns pointer to main window.
void SetLinksVisibility(Bool_t val)
ISets links visibility.
TExMap fLevelSize
Definition: TStructViewer.h:33
TObjArray fLevelArray
Definition: TStructViewer.h:35
~TStructViewer()
Destructor. Clean all object after closing the viewer.
void CountMembers(TClass *cl, TStructNode *parent, void *pointer)
Count allocated memory, increase member counters, find child nodes.
void SetColor(TString name, Int_t color)
Sets color for the class "name" to color "color".
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...
TExMap fPointers
Definition: TStructViewer.h:34
TColor GetColor(const char *typeName)
Returns color associated with type "typeName".
void SetPointer(void *ptr, const char *clname=NULL)
Set main pointer of class "clname".
void Reset()
Deleting nodes, maps and array.
TStructNode * fTopNode
Definition: TStructViewer.h:36
Bool_t GetLinksVisibility() const
Get visibility of links between objects.
void Prepare()
Create top node and find all member nodes.
void * GetPointer() const
Return main pointer.
TStructViewerGUI * fGUI
Definition: TStructViewer.h:31
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...
TClass * fPointerClass
Definition: TStructViewer.h:30
TExMap GetLevelMembersCount() const
Returns TExMap with pairs <level number, number of objects>
TExMap GetLevelSize() const
Returns TExMap with pairs <level number, size of level in bytes>
virtual UInt_t Sizeof() const =0
virtual EDataType GetType() const =0
virtual TClass * GetValueClass() const =0
virtual void * At(UInt_t idx)=0
virtual UInt_t Size() const =0
virtual Bool_t HasPointers() const =0
std::string ResolveTypedef(const char *tname, bool resolveAll=false)
int GetSplit(const char *type, std::vector< std::string > &output, int &nestedLoc, EModType mode=TClassEdit::kNone)
Stores in output (after emptying it) the split type.
Definition: TClassEdit.cxx:948
auto * a
Definition: textangle.C:12