#include "RConfigure.h"
#include "TROOT.h"
#include "TClassTree.h"
#include "TClassTable.h"
#include "TClass.h"
#include "TBaseClass.h"
#include "TDataMember.h"
#include "TDataType.h"
#include "TRealData.h"
#include "TMethod.h"
#include "TMethodArg.h"
#include "TPad.h"
#include "TPaveClass.h"
#include "TArrow.h"
#include "TText.h"
#include "TSystem.h"
#include "TObjString.h"
#include "Riostream.h"
#include <algorithm>
const Int_t kIsClassTree = BIT(7);
const Int_t kUsedByData = BIT(11);
const Int_t kUsedByFunc = BIT(12);
const Int_t kUsedByCode = BIT(13);
const Int_t kUsedByClass = BIT(14);
const Int_t kUsingData = BIT(15);
const Int_t kUsingFunc = BIT(16);
const Int_t kUsingCode = BIT(17);
const Int_t kUsingClass = BIT(18);
const Int_t kUsedByCode1 = BIT(19);
const Int_t kIsaPointer = BIT(20);
const Int_t kIsBasic = BIT(21);
static Float_t gXsize, gYsize, gDx, gDy, gLabdx, gLabdy, gDxx, gCsize;
static Int_t *gNtsons, *gNsons;
ClassImp(TClassTree)
/*
<img src="gif/th1_classtree.gif">
*/
//End_Html
/*
<img src="gif/tobject_classtree.gif">
*/
//End_Html
TClassTree::TClassTree()
{
fShowCod = 0;
fShowHas = 0;
fShowMul = 0;
fShowRef = 0;
fNclasses = 0;
fCstatus = 0;
fParents = 0;
fCparent = 0;
fCpointer = 0;
fCnames = 0;
fCtitles = 0;
fOptions = 0;
fLinks = 0;
fDerived = 0;
fNdata = 0;
SetLabelDx();
SetYoffset(0);
#ifdef ROOTSRCDIR
SetSourceDir(".:src:" ROOTSRCDIR);
#else
SetSourceDir(".:src:$ROOTSYS/src");
#endif
}
TClassTree::TClassTree(const char *name, const char *classes)
:TNamed(name,classes)
{
fShowCod = 0;
fShowHas = 0;
fShowMul = 0;
fShowRef = 0;
fNclasses = 0;
fCstatus = 0;
fParents = 0;
fCparent = 0;
fCpointer = 0;
fCnames = 0;
fCtitles = 0;
fOptions = 0;
fLinks = 0;
fDerived = 0;
fNdata = 0;
SetLabelDx();
SetYoffset(0);
#ifdef ROOTSRCDIR
SetSourceDir(".:src:" ROOTSRCDIR);
#else
SetSourceDir(".:src:$ROOTSYS/src");
#endif
if (classes && strlen(classes)) {
fClasses = classes;
Draw();
}
}
TClassTree::~TClassTree()
{
for (Int_t i=0;i<fNclasses;i++) {
if (fLinks[i]) fLinks[i]->Delete();
}
delete [] fCnames;
delete [] fCtitles;
delete [] fCstatus;
delete [] fParents;
delete [] fCparent;
delete [] fCpointer;
delete [] fOptions;
delete [] fLinks;
delete [] fDerived;
delete [] fNdata;
}
void TClassTree::Draw(const char *classes)
{
if (!gPad) {
gROOT->MakeDefCanvas();
}
Init();
if (classes && strlen(classes)) fClasses = classes;
for (Int_t i=0;i<fNclasses;i++) {
fCstatus[i] = 0;
fCparent[i] = -1;
}
Paint();
}
Int_t TClassTree::FindClass(const char *classname)
{
for (Int_t i=0;i<fNclasses;i++) {
if(!fCnames[i]->CompareTo(classname)) return i;
}
return -1;
}
void TClassTree::FindClassesUsedBy(Int_t iclass)
{
fCstatus[iclass] = 1;
Int_t i;
TObjString *os;
TList *los = fLinks[iclass];
TIter next(los);
while ((os = (TObjString*)next())) {
i = FindClass(os->GetName());
if (i < 0) continue;
if (fCstatus[i]) continue;
Int_t udata = os->TestBit(kUsedByData);
Int_t ufunc = os->TestBit(kUsedByFunc);
Int_t ucode = os->TestBit(kUsedByCode);
Int_t uclass = os->TestBit(kUsedByClass);
if (udata || ufunc || ucode || uclass) {
fCstatus[i] = 1;
}
}
}
void TClassTree::FindClassesUsing(Int_t iclass)
{
fCstatus[iclass] = 1;
Int_t i;
TObjString *os;
TList *los = fLinks[iclass];
TIter next(los);
while ((os = (TObjString*)next())) {
i = FindClass(os->GetName());
if (i < 0) continue;
if (fCstatus[i]) continue;
Int_t udata = os->TestBit(kUsingData);
Int_t ufunc = os->TestBit(kUsingFunc);
Int_t ucode = os->TestBit(kUsingCode);
Int_t uclass = os->TestBit(kUsingClass);
if (udata || ufunc || ucode || uclass) {
fCstatus[i] = 1;
}
}
}
void TClassTree::FindClassPosition(const char *classname, Float_t &x, Float_t &y)
{
TIter next(gPad->GetListOfPrimitives());
TObject *obj;
TPaveClass *pave;
while((obj=next())) {
if (obj->InheritsFrom(TPaveClass::Class())) {
pave = (TPaveClass*)obj;
if (!strcmp(pave->GetLabel(),classname)) {
x = 0.5*(pave->GetX1() + pave->GetX2());
y = 0.5*(pave->GetY1() + pave->GetY2());
return;
}
}
}
x = y = 0;
}
void TClassTree::Init()
{
if (fNclasses) return;
gClassTable->Init();
fNclasses = gClassTable->Classes();
fCnames = new TString*[fNclasses];
fCtitles = new TString*[fNclasses];
fCstatus = new Int_t[fNclasses];
fParents = new Int_t[fNclasses];
fCparent = new Int_t[fNclasses];
fNdata = new Int_t[fNclasses];
fCpointer = new TClass*[fNclasses];
fOptions = new TString*[fNclasses];
fLinks = new TList*[fNclasses];
fDerived = new char*[fNclasses];
Int_t i,j;
for (i=0;i<fNclasses;i++) {
fCnames[i] = new TString(gClassTable->Next());
fCpointer[i] = TClass::GetClass(fCnames[i]->Data());
fCtitles[i] = new TString(fCpointer[i]->GetTitle());
fCstatus[i] = 0;
fOptions[i] = new TString("ID");
fLinks[i] = new TList();
fDerived[i] = new char[fNclasses];
}
TBaseClass *clbase;
TClass *cl;
for (i=0;i<fNclasses;i++) {
TList *lm = fCpointer[i]->GetListOfDataMembers();
if (lm) fNdata[i] = lm->GetSize();
else fNdata[i] = 0;
char *derived = fDerived[i];
for (j=0;j<fNclasses;j++) {
derived[j] = 0;
if (fCpointer[i]->InheritsFrom(fCpointer[j])) {
derived[j] = 1;
}
}
fParents[i] = -1;
TList *lb = fCpointer[i]->GetListOfBases();
if (!lb) continue;
clbase = (TBaseClass*)lb->First();
if (clbase == 0) continue;
cl = (TClass*)clbase->GetClassPointer();
for (j=0;j<fNclasses;j++) {
if(cl == fCpointer[j]) {
fParents[i] = j;
break;
}
}
}
for (i=0;i<fNclasses;i++) {
ScanClasses(i);
}
}
void TClassTree::ls(Option_t *) const
{
char line[500];
for (Int_t i=0;i<fNclasses;i++) {
snprintf(line,500,"%s%s",fCnames[i]->Data(),"...........................");
snprintf(&line[30],460,"%s",fCtitles[i]->Data());
line[79] = 0;
printf("%5d %s\n",i,line);
}
}
TObjString *TClassTree::Mark(const char *classname, TList *los, Int_t abit)
{
if (!los) return 0;
TObjString *os = (TObjString*)los->FindObject(classname);
if (!os) {
os = new TObjString(classname);
los->Add(os);
}
os->SetBit(abit);
return os;
}
void TClassTree::Paint(Option_t *)
{
if (gPad) {
TIter next(gPad->GetListOfPrimitives());
TObject *obj;
while((obj=next())) {
if (obj->TestBit(kIsClassTree)) delete obj;
}
}
Int_t nch = strlen(GetClasses());
if (nch == 0) return;
char *classes = new char[nch+1];
gNsons = new Int_t[fNclasses];
gNtsons = new Int_t[fNclasses];
strlcpy(classes,GetClasses(),nch+1);
Int_t i,j;
char *derived;
char *ptr = strtok(classes,":");
while (ptr) {
nch = strlen(ptr);
if (ptr[0] == '*') {
j = FindClass(&ptr[1]);
if (j >= 0) {
for (i=0;i<fNclasses;i++) {
derived = fDerived[i];
if(derived[j]) fCstatus[i] = 1;
}
}
} else if (ptr[0] == '>') {
for (i=0;i<fNclasses;i++) {
if(fCnames[i]->Contains(&ptr[1])) {
FindClassesUsing(i);
fCstatus[i] = 2;
break;
}
}
} else if (ptr[nch-1] == '<') {
ptr[nch-1] = 0;
for (i=0;i<fNclasses;i++) {
if(fCnames[i]->Contains(ptr)) {
FindClassesUsedBy(i);
FindClassesUsing(i);
fCstatus[i] = 2;
break;
}
}
} else if (ptr[nch-1] == '*') {
ptr[nch-1] = 0;
for (i=0;i<fNclasses;i++) {
if(fCnames[i]->Contains(ptr)) fCstatus[i] = 1;
}
} else {
for (i=0;i<fNclasses;i++) {
if(!fCnames[i]->CompareTo(ptr)) {
FindClassesUsedBy(i);
fCstatus[i] = 2;
break;
}
}
}
ptr = strtok(0,":");
}
for (i=0;i<fNclasses;i++) {
gNsons[i] = gNtsons[i] = 0;
}
for (i=0;i<fNclasses;i++) {
if (fCstatus[i] == 0) continue;
derived = fDerived[i];
for (j=0;j<fNclasses;j++) {
if (j == i) continue;
if(derived[j]) {
fCstatus[j] = 1;
}
}
}
for (i=0;i<fNclasses;i++) {
if (fCstatus[i] == 0) continue;
j = fParents[i];
if (j >=0 ) {
fCparent[i] = j;
gNsons[j]++;
}
}
Int_t maxlev = 1;
Int_t icl,ip;
for (i=0;i<fNclasses;i++) {
if (fCstatus[i] == 0) continue;
if (gNsons[i] != 0) continue;
icl = i;
Int_t nlevel = 1;
while (fCparent[icl] >= 0) {
nlevel++;
if (nlevel > maxlev) maxlev = nlevel;
ip = fCparent[icl];
gNtsons[ip]++;
icl = ip;
}
}
Int_t ndiv=0;
Int_t nmore = 0;
for (i=0;i<fNclasses;i++) {
if (fCstatus[i] == 0) continue;
if (fCparent[i] < 0) {
ndiv += gNtsons[i]+1;
nmore++;
}
}
ndiv++;
Float_t xmin = gPad->GetX1();
Float_t xmax = gPad->GetX2();
Float_t ymin = gPad->GetY1();
Float_t ymax = gPad->GetY2();
Float_t ytop = gYsize/20;
gXsize = xmax - xmin;
gYsize = ymax - ymin;
gDy = (gYsize-ytop)/(ndiv);
if (gDy > gYsize/10.) gDy = gYsize/10.;
gDx = 0.9*gXsize/5;
if (maxlev > 5) gDx = 0.97*gXsize/maxlev;
Float_t y = ymax -ytop;
gLabdx = fLabelDx*gXsize;
if (gLabdx > 0.95*gDx) gLabdx = 0.95*gDx;
gLabdy = 0.3*gDy;
gDxx = 0.5*gXsize/26.;
Float_t xleft = xmin +gDxx;
Float_t ymore = 0.5*nmore*gDy+fYoffset*gYsize;
Int_t dxpixels = gPad->XtoAbsPixel(gLabdx) - gPad->XtoAbsPixel(0);
Int_t dypixels = gPad->YtoAbsPixel(0) - gPad->YtoAbsPixel(gLabdy);
gCsize = dxpixels/(10.*dypixels);
gCsize = std::max(gCsize,Float_t(0.75));
gCsize = std::min(gCsize,Float_t(1.1));
for (i=0;i<fNclasses;i++) {
if (fCstatus[i] == 0) continue;
if (fCparent[i] < 0) {
y -= gDy+0.5*gNtsons[i]*gDy;
if (!fCnames[i]->CompareTo("TObject")) y += ymore;
PaintClass(i,xleft,y);
y -= 0.5*gNtsons[i]*gDy;
}
}
if (fShowCod) ShowCod();
if (fShowHas) ShowHas();
if (fShowMul) ShowMul();
if (fShowRef) ShowRef();
nch = strlen(GetClasses());
xmax = 0.3;
if (nch > 20) xmax = 0.5;
if (nch > 50) xmax = 0.7;
if (nch > 70) xmax = 0.9;
TPaveClass *ptitle = new TPaveClass(xmin +0.1*gXsize/26.
,ymin+gYsize-0.9*gYsize/20.
,xmin+xmax*gXsize
,ymin+gYsize-0.1*gYsize/26.
,GetClasses(),this);
ptitle->SetFillColor(42);
ptitle->SetBit(kIsClassTree);
ptitle->Draw();
delete [] classes;
delete [] gNsons;
delete [] gNtsons;
}
void TClassTree::PaintClass(Int_t iclass, Float_t xleft, Float_t y)
{
Float_t u[2],yu=0,yl=0;
Int_t ns = gNsons[iclass];
u[0] = xleft;
u[1] = u[0]+gDxx;
if(ns != 0) u[1] = u[0]+gDx;
TLine *line = new TLine(u[0],y,u[1],y);
line->SetBit(kIsClassTree);
line->Draw();
Int_t icobject = FindClass("TObject");
TPaveClass *label = new TPaveClass(xleft+gDxx,y-gLabdy,xleft+gLabdx,y+gLabdy,fCnames[iclass]->Data(),this);
char *derived = fDerived[iclass];
if (icobject >= 0 && !derived[icobject]) label->SetFillColor(30);
if (fCstatus[iclass] > 1) label->SetFillColor(kYellow);
label->SetTextSize(gCsize);
label->SetBit(kIsClassTree);
label->SetToolTipText(fCtitles[iclass]->Data(),500);
label->Draw();
if (ns == 0) return;
y += 0.5*gNtsons[iclass]*gDy;
Int_t first =0;
for (Int_t i=0;i<fNclasses;i++) {
if(fCparent[i] != iclass) continue;
if (gNtsons[i] > 1) y -= 0.5*gNtsons[i]*gDy;
else y -= 0.5*gDy;
if (!first) {first=1; yu = y;}
PaintClass(i,u[1],y);
yl = y;
if (gNtsons[i] > 1) y -= 0.5*gNtsons[i]*gDy;
else y -= 0.5*gDy;
}
if (ns == 1) return;
line = new TLine(u[1],yl,u[1],yu);
line->SetBit(kIsClassTree);
line->Draw();
}
void TClassTree::SaveAs(const char *filename, Option_t *option) const
{
if (gDirectory) gDirectory->SaveObjectAs(this,filename,option);
}
void TClassTree::ScanClasses(Int_t iclass)
{
Int_t ic, icl;
TList *los = fLinks[iclass];
TList *losref = 0;
TObjString *os;
TClass *cl = fCpointer[iclass];
TDataMember *dm;
TList *lm = cl->GetListOfDataMembers();
if (lm) {
TIter next(lm);
Int_t imember = 0;
while ((dm = (TDataMember *) next())) {
imember++;
ic = FindClass(dm->GetTypeName());
if (ic < 0 || ic == iclass) continue;
losref = fLinks[ic];
os = Mark(fCnames[ic]->Data(),los,kUsedByData);
if (os) {
os->SetBit(kIsaPointer,dm->IsaPointer());
os->SetBit(kIsBasic,dm->IsBasic());
os->SetUniqueID(imember);
}
Mark(fCnames[iclass]->Data(),losref,kUsingData);
}
}
char *derived = fDerived[iclass];
TBaseClass *clbase;
Int_t numb = 0;
TList *lb = fCpointer[iclass]->GetListOfBases();
if (lb) {
TIter nextb(lb);
while ((clbase = (TBaseClass*)nextb())) {
numb++;
if (numb == 1) continue;
ic = FindClass(clbase->GetName());
derived[ic] = 2;
}
for (ic=0;ic<fNclasses;ic++) {
if (ic == iclass) continue;
if (derived[ic]) {
losref = fLinks[ic];
Mark(fCnames[ic]->Data(),los,kUsedByClass);
Mark(fCnames[iclass]->Data(),losref,kUsingClass);
}
}
}
char *star, *cref;
TMethod *method;
TMethodArg *methodarg;
TList *lf = cl->GetListOfMethods();
if (lf) {
TIter nextm(lf);
TString name;
while ((method = (TMethod*) nextm())) {
name = method->GetReturnTypeName();
star = strstr((char*)name.Data(),"*");
if (star) *star = 0;
cref = strstr((char*)name.Data(),"&");
if (cref) *cref = 0;
ic = FindClass(name);
if (ic < 0 || ic == iclass) continue;
losref = fLinks[ic];
Mark(fCnames[ic]->Data(),los,kUsedByFunc);
Mark(fCnames[iclass]->Data(),losref,kUsingFunc);
TIter nexta(method->GetListOfMethodArgs());
while ((methodarg = (TMethodArg*) nexta())) {
name = methodarg->GetTypeName();
star = strstr((char*)name.Data(),"*");
if (star) *star = 0;
cref = strstr((char*)name.Data(),"&");
if (cref) *cref = 0;
ic = FindClass(name);
if (ic < 0 || ic == iclass) continue;
losref = fLinks[ic];
Mark(fCnames[ic]->Data(),los,kUsedByFunc);
Mark(fCnames[iclass]->Data(),losref,kUsingFunc);
}
}
}
if (!cl->GetImplFileName() || !cl->GetImplFileName()[0])
return;
const char *source = gSystem->BaseName( gSystem->UnixPathName(cl->GetImplFileName()));
char *sourceName = gSystem->Which( fSourceDir.Data(), source , kReadPermission );
if (!sourceName) return;
Int_t ncn = strlen(fCnames[iclass]->Data())+2;
char *cname = new char[ncn+1];
snprintf(cname,ncn,"%s::",fCnames[iclass]->Data());
ifstream sourceFile;
sourceFile.open( sourceName, ios::in );
Int_t nlines = 0;
if( sourceFile.good() ) {
const Int_t kMAXLEN=1500;
char line[kMAXLEN];
while( !sourceFile.eof() ) {
sourceFile.getline( line, kMAXLEN-1 );
if( sourceFile.eof() ) break;
Int_t nblank = strspn(line," ");
if (!strncmp(&line[nblank],"//",2)) continue;
char *cc = strstr(line,"::");
if (cc) {
*cc = 0;
if (!strncmp(&line[nblank],cname,ncn)) break;
Int_t nl = strlen(&line[nblank]);
if (!strncmp(&line[nblank],cc+2,nl)) break;
}
nlines++; if (nlines > 1000) break;
char *inc = strstr(line,"#include");
if (inc) {
char *ch = strstr(line,".h");
if (!ch) continue;
*ch = 0;
char *start = strstr(line,"<");
if (!start) start = strstr(line,"\"");
if (!start) continue;
start++;
while ((start < ch) && (*start == ' ')) start++;
icl = FindClass(start);
if (icl < 0 || icl == iclass) continue;
losref = fLinks[icl];
Mark(fCnames[icl]->Data(),los,kUsedByCode1);
Mark(fCnames[icl]->Data(),los,kUsedByCode);
Mark(fCnames[iclass]->Data(),losref,kUsingCode);
derived = fDerived[icl];
for (ic=0;ic<fNclasses;ic++) {
if (ic == icl) continue;
if (derived[ic]) {
losref = fLinks[ic];
Mark(fCnames[ic]->Data(),los,kUsedByCode);
Mark(fCnames[iclass]->Data(),losref,kUsingCode);
}
}
}
}
}
delete [] cname;
sourceFile.close();
}
void TClassTree::SetClasses(const char *classes, Option_t *)
{
if (classes == 0) return;
fClasses = classes;
for (Int_t i=0;i<fNclasses;i++) {
fCstatus[i] = 0;
fCparent[i] = -1;
}
if (gPad) Paint();
}
void TClassTree::SetLabelDx(Float_t labeldx)
{
fLabelDx = labeldx;
if (gPad) Paint();
}
void TClassTree::SetYoffset(Float_t offset)
{
fYoffset = offset;
if (gPad) Paint();
}
void TClassTree::ShowClassesUsedBy(const char *classes)
{
Int_t i,j;
Int_t nch = strlen(classes);
char *ptr = new char[nch+1];
strlcpy(ptr,classes,nch+1);
if (ptr[0] == '*') {
i = FindClass(&ptr[1]);
if (i >= 0) {
char *derived = fDerived[i];
for (j=0;j<fNclasses;j++) {
if(derived[j]) FindClassesUsedBy(j);
}
}
} else if (ptr[nch-1] == '*') {
ptr[nch-1] = 0;
for (j=0;j<fNclasses;j++) {
if(fCnames[j]->Contains(ptr)) FindClassesUsedBy(j);
}
} else {
for (j=0;j<fNclasses;j++) {
if(!fCnames[j]->CompareTo(ptr)) FindClassesUsedBy(j);
}
}
delete [] ptr;
if (gPad) Paint();
}
void TClassTree::ShowClassesUsing(const char *classes)
{
Int_t i,j;
Int_t nch = strlen(classes);
char *ptr = new char[nch+1];
strlcpy(ptr,classes,nch+1);
if (ptr[0] == '*') {
i = FindClass(&ptr[1]);
if (i >= 0) {
char *derived = fDerived[i];
for (j=0;j<fNclasses;j++) {
if(derived[j]) FindClassesUsing(j);
}
}
} else if (ptr[nch-1] == '*') {
ptr[nch-1] = 0;
for (j=0;j<fNclasses;j++) {
if(fCnames[j]->Contains(ptr)) FindClassesUsing(j);
}
} else {
for (j=0;j<fNclasses;j++) {
if(!fCnames[j]->CompareTo(ptr)) FindClassesUsing(j);
}
}
delete [] ptr;
if (gPad) Paint();
}
void TClassTree::ShowCod()
{
TIter next(gPad->GetListOfPrimitives());
TObject *obj;
TObjString *os;
TPaveClass *pave;
Int_t ic,icl;
Float_t x,y,x1,y1;
while((obj=next())) {
if (obj->InheritsFrom(TPaveClass::Class())) {
pave = (TPaveClass*)obj;
icl = FindClass(pave->GetLabel());
if (icl < 0) continue;
char *derived = fDerived[icl];
x = 0.5*(pave->GetX1() + pave->GetX2());
y = 0.5*(pave->GetY1() + pave->GetY2());
TIter nextos(fLinks[icl]);
while((os=(TObjString*)nextos())) {
if (!os->TestBit(kUsedByCode1)) continue;
ic = FindClass(os->GetName());
if (derived[ic]) continue;
FindClassPosition(os->GetName(),x1,y1);
if (x1 == 0 || y1 == 0) continue;
TArrow *arrow = new TArrow(x,y,x1,y1,0.008,"|>");
arrow->SetLineColor(kGreen);
arrow->SetFillColor(kGreen);
arrow->SetBit(kIsClassTree);
arrow->Draw();
}
}
}
}
void TClassTree::ShowHas()
{
TIter next(gPad->GetListOfPrimitives());
TObject *obj;
TObjString *os;
TPaveClass *pave;
Int_t icl;
Float_t y,x1,y1,dx;
while((obj=next())) {
if (obj->InheritsFrom(TPaveClass::Class())) {
pave = (TPaveClass*)obj;
icl = FindClass(pave->GetLabel());
if (icl < 0) continue;
y = 0.5*(pave->GetY1() + pave->GetY2());
Int_t nmembers = fNdata[icl];
if (nmembers == 0) continue;
dx = (pave->GetX2() - pave->GetX1())/nmembers;
TIter nextos(fLinks[icl]);
while((os=(TObjString*)nextos())) {
if (!os->TestBit(kUsedByData)) continue;
if (os->TestBit(kIsaPointer)) continue;
if (os->TestBit(kIsBasic)) continue;
FindClassPosition(os->GetName(),x1,y1);
if (x1 == 0 || y1 == 0) continue;
Int_t imember = os->GetUniqueID();
TLine *line = new TLine(pave->GetX1()+(imember+0.5)*dx,y,x1,y1);
line->SetLineStyle(3);
line->SetLineColor(6);
line->SetBit(kIsClassTree);
line->Draw();
}
}
}
}
void TClassTree::ShowLinks(Option_t *option)
{
TString opt = option;
opt.ToUpper();
fShowCod = fShowHas = fShowMul = fShowRef = 0;
if (opt.Contains("C")) fShowCod = 1;
if (opt.Contains("H")) fShowHas = 1;
if (opt.Contains("M")) fShowMul = 1;
if (opt.Contains("R")) fShowRef = 1;
if (gPad) Paint();
}
void TClassTree::ShowMul()
{
TIter next(gPad->GetListOfPrimitives());
TObject *obj;
TObjString *os;
TPaveClass *pave;
Int_t ic,icl;
Float_t x,y,x1,y1;
while((obj=next())) {
if (obj->InheritsFrom(TPaveClass::Class())) {
pave = (TPaveClass*)obj;
icl = FindClass(pave->GetLabel());
if (icl < 0) continue;
char *derived = fDerived[icl];
x = 0.5*(pave->GetX1() + pave->GetX2());
y = 0.5*(pave->GetY1() + pave->GetY2());
TIter nextos(fLinks[icl]);
while((os=(TObjString*)nextos())) {
if (!os->TestBit(kUsedByClass)) continue;
ic = FindClass(os->GetName());
if (derived[ic] != 2) continue;
FindClassPosition(os->GetName(),x1,y1);
if (x1 == 0 || y1 == 0) continue;
TLine *line = new TLine(x,y,x1,y1);
line->SetBit(kIsClassTree);
line->SetLineStyle(2);
line->SetLineColor(kBlue);
line->Draw();
}
}
}
}
void TClassTree::ShowRef()
{
TIter next(gPad->GetListOfPrimitives());
TObject *obj;
TObjString *os;
TPaveClass *pave;
Int_t ic,icl;
Float_t y,x1,y1,dx;
Int_t icc = FindClass("TClass");
while((obj=next())) {
if (obj->InheritsFrom(TPaveClass::Class())) {
pave = (TPaveClass*)obj;
icl = FindClass(pave->GetLabel());
if (icl < 0) continue;
y = 0.5*(pave->GetY1() + pave->GetY2());
Int_t nmembers = fNdata[icl];
if (nmembers == 0) continue;
dx = (pave->GetX2() - pave->GetX1())/nmembers;
TIter nextos(fLinks[icl]);
while((os=(TObjString*)nextos())) {
if (!os->TestBit(kUsedByData)) continue;
ic = FindClass(os->GetName());
if (!os->TestBit(kIsaPointer)) continue;
if (os->TestBit(kIsBasic)) continue;
if (ic == icc) continue;
FindClassPosition(os->GetName(),x1,y1);
if (x1 == 0 || y1 == 0) continue;
Int_t imember = os->GetUniqueID();
TArrow *arrow = new TArrow(pave->GetX1()+(imember+0.5)*dx,y,x1,y1,0.008,"|>");
arrow->SetLineColor(kRed);
arrow->SetFillColor(kRed);
arrow->SetBit(kIsClassTree);
arrow->Draw();
}
}
}
}
void TClassTree::Streamer(TBuffer &R__b)
{
Int_t i;
if (R__b.IsReading()) {
Version_t R__v = R__b.ReadVersion(); if (R__v) { }
TNamed::Streamer(R__b);
fClasses.Streamer(R__b);
R__b >> fYoffset;
R__b >> fLabelDx;
R__b >> fNclasses;
R__b >> fShowCod;
R__b >> fShowMul;
R__b >> fShowHas;
R__b >> fShowRef;
fCnames = new TString*[fNclasses];
fCtitles = new TString*[fNclasses];
fCstatus = new Int_t[fNclasses];
fParents = new Int_t[fNclasses];
fCparent = new Int_t[fNclasses];
fNdata = new Int_t[fNclasses];
fCpointer = new TClass*[fNclasses];
fOptions = new TString*[fNclasses];
fLinks = new TList*[fNclasses];
fDerived = new char*[fNclasses];
for (i=0;i<fNclasses;i++) {
R__b >> fCstatus[i];
R__b >> fParents[i];
R__b >> fNdata[i];
fCnames[i] = new TString();
fCtitles[i] = new TString();
fOptions[i] = new TString();
fCnames[i]->Streamer(R__b);
fCtitles[i]->Streamer(R__b);
fOptions[i]->Streamer(R__b);
fLinks[i] = new TList();
fLinks[i]->Streamer(R__b);
fDerived[i] = new char[fNclasses];
R__b.ReadFastArray(fDerived[i],fNclasses);
}
fSourceDir.Streamer(R__b);
} else {
R__b.WriteVersion(TClassTree::IsA());
TNamed::Streamer(R__b);
fClasses.Streamer(R__b);
R__b << fYoffset;
R__b << fLabelDx;
R__b << fNclasses;
R__b << fShowCod;
R__b << fShowMul;
R__b << fShowHas;
R__b << fShowRef;
for (i=0;i<fNclasses;i++) {
R__b << fCstatus[i];
R__b << fParents[i];
R__b << fNdata[i];
fCnames[i]->Streamer(R__b);
fCtitles[i]->Streamer(R__b);
fOptions[i]->Streamer(R__b);
fLinks[i]->Streamer(R__b);
R__b.WriteFastArray(fDerived[i],fNclasses);
}
fSourceDir.Streamer(R__b);
}
}