TStructViewer.cxx

Go to the documentation of this file.
00001 // @(#)root/gviz3d:$Id: TStructViewer.cxx 34883 2010-08-20 13:32:33Z matevz $
00002 // Author: Tomasz Sosnicki   18/09/09
00003 
00004 /************************************************************************
00005 * Copyright (C) 1995-2009, Rene Brun and Fons Rademakers.               *
00006 * All rights reserved.                                                  *
00007 *                                                                       *
00008 * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010 *************************************************************************/
00011 
00012 #include "TStructViewer.h"
00013 #include "TStructNodeProperty.h"
00014 #include "TStructViewerGUI.h"
00015 #include "TStructNode.h"
00016 
00017 #include <TDataMember.h>
00018 #include <TVirtualCollectionProxy.h>
00019 #include <TClassEdit.h>
00020 #include <vector>
00021 
00022 ClassImp(TStructViewer);
00023 
00024 class TA {
00025 public:
00026    virtual ~TA() {}
00027 };
00028 
00029 //________________________________________________________________________
00030 //////////////////////////////////////////////////////////////////////////
00031 //
00032 // TStructViewer viewer represents class, struct or other type as an object in 3D space.
00033 // At the top of the scene we can see objects which is our pointer. Under it we see 
00034 // pointers and collection elements. Collection must inherit from TCollection 
00035 // or be STL collecion. 
00036 // 
00037 // We can change the number of visible levels or objects on the scene with the  GUI or 
00038 // methods. The size of geometry objects is proportional to the memory taken by this object
00039 // or to the number of members inside this object. 
00040 // 
00041 // An easy way to find some class in the viewer is to change the color of the type.
00042 // We can connect for example a TF2 class with red color or connect all classes 
00043 // inheriting from TF2 by adding plus to name. For example typename "TF2+" tells us 
00044 // that all classes inheriting from TF2 will be red.
00045 // 
00046 // Navigation in viewer is very simple like in usual GLViewer. When you put the mouse over 
00047 // some object you can see some information about it (e.g. name, size, actual level).
00048 // When you double click this object, it becames top object on scene.
00049 // Undo and redo operation are supported. 
00050 // 
00051 // Begin_Html
00052 // <p> In this picture we can see TStructViewer with pointer to TList which contains
00053 // other collections and objects of various classes</p>
00054 // <img src="gif/TStructViewer1.jpg">
00055 // End_Html
00056 // 
00057 // Begin_Html
00058 // <p> Other screenshot presents opened TStructNodeEditor</p>
00059 // <img src="gif/TStructViewer2.jpg">
00060 // End_Html
00061 //
00062 //
00063 //////////////////////////////////////////////////////////////////////////
00064 
00065 
00066 //________________________________________________________________________
00067 TStructViewer::TStructViewer(void* ptr, const char * clname)
00068 {
00069    // Default constructor. An argument "ptr" is a main pointer of type "clname", which should be shown in the viewer
00070 
00071    fPointer = NULL;
00072    fPointerClass = NULL;
00073    fTopNode = NULL;
00074 
00075    // add default color 
00076    fColors.Add(new TStructNodeProperty("+", 17));
00077 
00078    // creating GUI
00079    fGUI = new TStructViewerGUI(this, NULL, &fColors);
00080    
00081    SetPointer(ptr, clname);
00082 }
00083 
00084 //________________________________________________________________________
00085 TStructViewer::~TStructViewer()
00086 {
00087    // Destructor. Clean all object after closing the viewer
00088 
00089    Reset();
00090    fColors.SetOwner();
00091    fColors.Clear();
00092 }
00093 
00094 //________________________________________________________________________
00095 void TStructViewer::AddNode(TStructNode* node, ULong_t size)
00096 {
00097    // Find list with nodes on specified level and add node to this list and increment list of sizes and list of members
00098 
00099    TList* list = (TList*)fLevelArray[node->GetLevel()];
00100    // if list doesn't exist -> create one
00101    if(!list) {
00102       fLevelArray[node->GetLevel()] = list = new TList();
00103    }
00104    list->Add(node);
00105 
00106    // increase number of members on this level
00107    fLevelMembersCount(node->GetLevel())++;
00108    // increase size of this level
00109    fLevelSize(node->GetLevel()) += size;
00110 }
00111 
00112 //________________________________________________________________________
00113 void TStructViewer::CountMembers(TClass* cl, TStructNode* parent, void* pointer)
00114 {
00115    // Count allocated memory, increase member counters, find child nodes
00116 
00117    if(!cl) {
00118       return;
00119    }
00120 
00121    if (cl->InheritsFrom(TClass::Class())) {
00122       return;
00123    }
00124 
00125    //////////////////////////////////////////////////////////////////////////
00126    // DATA MEMBERS
00127    //////////////////////////////////////////////////////////////////////////
00128    // Set up list of RealData so TClass doesn't create a new object itself
00129    cl->BuildRealData(parent->GetPointer());
00130    TIter it(cl->GetListOfDataMembers());
00131    TDataMember* dm;
00132    while ((dm = (TDataMember*) it() ))
00133    {
00134       // increase counters in parent node
00135       parent->SetAllMembersCount(parent->GetAllMembersCount() + 1);
00136       parent->SetMembersCount(parent->GetMembersCount() + 1);
00137 
00138       if (dm->Property() & kIsStatic) {
00139          continue;
00140       }
00141 
00142 
00143       void* ptr = NULL;
00144 
00145       if(dm->IsaPointer()) {
00146          TString trueTypeName = dm->GetTrueTypeName();
00147 
00148          // skip if pointer to pointer
00149          if(trueTypeName.EndsWith("**")) {
00150             continue;
00151          }
00152 
00153          if (!pointer) {
00154             continue;
00155          }
00156 
00157          void** pptr = (void**)((ULong_t)pointer + dm->GetOffset());
00158          ptr = *pptr;
00159 
00160          if (!ptr) {
00161             continue;
00162          }
00163 
00164          if(fPointers.GetValue((ULong_t)ptr)) {
00165             continue;
00166          } else {
00167             fPointers.Add((ULong_t)ptr, (ULong_t)ptr);
00168          }
00169 
00170          ULong_t size = 0;
00171          if (TClass* cl2 = TClass::GetClass(dm->GetTypeName())) {
00172             size = cl2->Size();
00173          }
00174 
00175          if(size == 0) {
00176             size = dm->GetUnitSize();
00177          }
00178 
00179          ENodeType type;
00180          if(dm->GetDataType()) {   // pointer to basic type
00181             type = kBasic;
00182          } else {
00183             type = kClass;
00184          }
00185             
00186          // creating TStructNode
00187          TStructNode* node = new TStructNode(dm->GetName(), dm->GetTypeName(), ptr, parent, size, type);
00188          AddNode(node, size);
00189          
00190          CountMembers(TClass::GetClass(dm->GetTypeName()), node, ptr);
00191 
00192          // total size = size of parent + size of nodes daughters
00193          parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize() - size);
00194          // all members of node = all nodes of parent + nodes of daughter - 1 because node is added twice
00195          parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount() - 1);
00196       } else {
00197          ptr = (void*)((ULong_t)pointer + dm->GetOffset());
00198 
00199          if (!ptr) {
00200             continue;
00201          }
00202          CountMembers(TClass::GetClass(dm->GetTypeName()), parent, ptr);
00203       }
00204          
00205       //////////////////////////////////////////////////////////////////////////
00206       // STL COLLECTION
00207       //////////////////////////////////////////////////////////////////////////
00208       if (dm->IsSTLContainer()) {
00209          parent->SetNodeType(kSTLCollection);
00210 
00211          //it works only for pointer in std object (not pointer)
00212          TClass* stlClass = TClass::GetClass(dm->GetTypeName());
00213          if (!stlClass) {
00214             continue;
00215          }
00216 
00217          TVirtualCollectionProxy* proxy = stlClass->GetCollectionProxy();
00218          if (!proxy) {
00219             continue;
00220          }
00221          TVirtualCollectionProxy::TPushPop helper(proxy, ptr);
00222 
00223          UInt_t count = proxy->Size();
00224          parent->SetMembersCount(parent->GetMembersCount() + count);
00225 
00226          if (!proxy->HasPointers() || proxy->GetType() != kNoType_t) { // only objects or pointers to basic type
00227             parent->SetTotalSize(parent->GetTotalSize() + count * proxy->Sizeof());
00228             parent->SetAllMembersCount(parent->GetAllMembersCount() + count);
00229          } else {
00230             TClass* clProxy = proxy->GetValueClass();
00231             TString name;
00232             TString typeName;
00233             // get size of element
00234             ULong_t size = 0;
00235             if (clProxy) {
00236                name = clProxy->GetName();
00237                typeName = clProxy->GetName();
00238                size = clProxy->Size();
00239             } else {
00240                continue;
00241             }
00242 
00243             // if there is no dictionary
00244             if (size == 0) {
00245                size = proxy->Sizeof();
00246             }
00247 
00248             // searching pointer to pointer
00249             Bool_t ptp = kFALSE;
00250             std::vector<std::string> parts;
00251             int loc;
00252             TClassEdit::GetSplit(dm->GetTypeName(), parts, loc);
00253             std::vector<std::string>::const_iterator iPart = parts.begin();
00254             while (iPart != parts.end() && *iPart == "")
00255                ++iPart;
00256             if (iPart != parts.end() && *iPart != dm->GetTypeName()) {
00257                for (std::vector<std::string>::const_iterator iP = iPart,
00258                   iPE = parts.end(); iP != iPE; ++iP) {
00259                      if (TString(TClassEdit::ResolveTypedef(iP->c_str(), true).c_str()).EndsWith("**")){
00260                         ptp = kTRUE;
00261                         break;
00262                      }
00263                }
00264             }
00265             if (ptp) {
00266                continue;
00267             }
00268 
00269 
00270             void* element;
00271             for (UInt_t i = 0; i < count ; i++) {
00272                element = *(void**)proxy->At(i);
00273 
00274                if (!element) {
00275                   continue;
00276                }
00277                if (clProxy->InheritsFrom(TObject::Class())) {
00278                   name = ((TObject*) element)->GetName();
00279                }
00280                
00281                // create node
00282                TStructNode* node = new TStructNode(name, typeName, element, parent, size, kClass);
00283                // add addition information
00284                AddNode(node, size);
00285                // increase parents counter
00286                parent->SetMembersCount(parent->GetMembersCount() + 1);
00287 
00288                CountMembers(clProxy, node, element);
00289                parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize());
00290                parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount());
00291             }
00292          }
00293       } 
00294    }
00295 
00296    //////////////////////////////////////////////////////////////////////////
00297    // COLLECTION
00298    //////////////////////////////////////////////////////////////////////////
00299    // if our parent node is collection
00300    if(cl->InheritsFrom(TCollection::Class())) {
00301       // we change type of node to collection
00302       parent->SetNodeType(kCollection);
00303    
00304       // return if invalid pointer to collection
00305       if (!pointer) {
00306          return;
00307       }
00308 
00309       TIter it2((TCollection*)pointer);
00310       TObject* item;
00311       // loop through all elements in collection
00312       while((item = it2())) {
00313          // get size of element
00314          ULong_t size = 0;
00315          if (TClass* cl3 = item->IsA()){
00316             size = cl3->Size();
00317          }
00318          
00319          // if there is no dictionary
00320          if (size == 0) {
00321             size = sizeof(item);
00322          }
00323 
00324          // create node
00325          TStructNode* node = new TStructNode(item->GetName(), item->ClassName(), item, parent, size, kClass);
00326          // add addition information
00327          AddNode(node, size);
00328          // increase parents counter
00329          parent->SetMembersCount(parent->GetMembersCount() + 1);
00330          
00331          CountMembers(item->IsA(), node, item);
00332          
00333          parent->SetTotalSize(parent->GetTotalSize() + node->GetTotalSize());
00334          parent->SetAllMembersCount(parent->GetAllMembersCount() + node->GetAllMembersCount());
00335       }
00336    }
00337 }
00338 
00339 //________________________________________________________________________
00340 void TStructViewer::Draw(Option_t *option)
00341 {
00342    // Draw object if there is valid pointer
00343 
00344    TString opt(option);
00345    if(opt == "count") {
00346       
00347    } else if (opt == "size") {
00348 
00349    }
00350 
00351 
00352    if (fTopNode) {
00353       fGUI->SetNodePtr(fTopNode);
00354    } else {
00355       
00356    }
00357 }
00358 
00359 //________________________________________________________________________
00360 TCanvas* TStructViewer::GetCanvas()
00361 {
00362    // Returns canvas used to keep TGeoVolumes
00363 
00364    return fGUI->GetCanvas();
00365 }
00366 
00367 //________________________________________________________________________
00368 TGMainFrame* TStructViewer::GetFrame()
00369 {
00370    // Returns pointer to main window
00371   
00372    return fGUI;
00373 }
00374 //________________________________________________________________________
00375 void* TStructViewer::GetPointer() const
00376 {
00377    // Return main pointer
00378 
00379    return fPointer;
00380 }
00381 
00382 //________________________________________________________________________
00383 TExMap TStructViewer::GetLevelMembersCount() const
00384 {
00385    // Returns TExMap with pairs <level number, number of objects>
00386 
00387    return fLevelMembersCount;
00388 }
00389 
00390 //________________________________________________________________________
00391 TExMap TStructViewer::GetLevelSize() const
00392 {
00393    // Returns TExMap with pairs <level number, size of level in bytes>
00394 
00395    return fLevelSize;
00396 }
00397 
00398 //________________________________________________________________________
00399 Bool_t TStructViewer::GetLinksVisibility() const
00400 {
00401    // Get visibility of links between objects
00402 
00403    return fGUI->GetLinksVisibility();
00404 }
00405 
00406 //________________________________________________________________________
00407 void TStructViewer::Prepare()
00408 {
00409    // Create top node and find all member nodes
00410    if (fTopNode) {
00411       Reset();
00412    }
00413 
00414    ULong_t size = fPointerClass->Size();
00415 
00416    TString name = "Main pointer";
00417    if (fPointerClass->InheritsFrom(TObject::Class())) {
00418       name = ((TObject*) fPointer)->GetName();
00419    }
00420    fTopNode = new TStructNode(name, fPointerClass->GetName(), fPointer, NULL, size, kClass);
00421    AddNode(fTopNode, size);
00422    CountMembers(fPointerClass, fTopNode, fPointer);
00423 }
00424 
00425 //________________________________________________________________________
00426 void TStructViewer::Reset()
00427 {
00428    // Deleting nodes, maps and array
00429 
00430    TList* lst;
00431    TIter it(&fLevelArray);
00432    while ((lst = (TList*) it() )) {
00433       lst->SetOwner();
00434       lst->Clear();
00435    }
00436 
00437    // deleting maps and array
00438    fLevelMembersCount.Clear();
00439    fLevelSize.Clear();
00440    fPointers.Clear();
00441    fLevelArray.Clear();
00442    
00443    fTopNode = NULL;
00444 }
00445 
00446 //________________________________________________________________________
00447 void TStructViewer::SetColor(TString name, Int_t color)
00448 {
00449    // Sets color for the class "name" to color "color"
00450 
00451    TIter it(&fColors);
00452    TStructNodeProperty* prop;
00453    while ((prop = (TStructNodeProperty*) it() )) {
00454       if (name == prop->GetName()) {
00455          prop->SetColor(TColor::GetColor(color));
00456          fGUI->Update();
00457          
00458          return;
00459       }
00460    }
00461 
00462    // add color
00463    prop = new TStructNodeProperty(name.Data(), color);
00464    fColors.Add(prop);
00465    fColors.Sort();
00466 }
00467 
00468 //________________________________________________________________________
00469 void TStructViewer::SetLinksVisibility(Bool_t val)
00470 {
00471    // ISets links visibility
00472 
00473    fGUI->SetLinksVisibility(val);
00474 }
00475 
00476 //________________________________________________________________________
00477 void TStructViewer::SetPointer(void* ptr, const char* clname)
00478 {
00479    // Set main pointer of class "clname"
00480 
00481    if (ptr) {
00482       TA* a = (TA*) ptr;
00483       if (clname) {
00484          fPointerClass = TClass::GetClass(clname);
00485       } else {
00486          fPointerClass = TClass::GetClass(typeid(*a));
00487       }
00488 
00489       if (!fPointerClass) {
00490          return;
00491       }
00492 
00493       fPointer = ptr;
00494       Prepare();
00495       fGUI->SetNodePtr(fTopNode);
00496    }
00497 }
00498 
00499 //________________________________________________________________________
00500 TColor TStructViewer::GetColor(const char* typeName)
00501 {
00502    // Returns color associated with type "typeName"
00503 
00504    TIter it(&fColors);
00505    TStructNodeProperty* prop;
00506    while((prop = (TStructNodeProperty*) it())) {
00507       if (!strcmp(prop->GetName(), typeName)) {
00508          return prop->GetColor();
00509       }
00510    }
00511 
00512    return TColor();
00513 }

Generated on Tue Jul 5 14:19:17 2011 for ROOT_528-00b_version by  doxygen 1.5.1