00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "RConfigure.h"
00013
00014 #include "TROOT.h"
00015 #include "TClassTree.h"
00016 #include "TClassTable.h"
00017 #include "TClass.h"
00018 #include "TBaseClass.h"
00019 #include "TDataMember.h"
00020 #include "TDataType.h"
00021 #include "TRealData.h"
00022 #include "TMethod.h"
00023 #include "TMethodArg.h"
00024 #include "TPad.h"
00025 #include "TPaveClass.h"
00026 #include "TArrow.h"
00027 #include "TText.h"
00028 #include "TSystem.h"
00029 #include "TObjString.h"
00030 #include "Riostream.h"
00031
00032 const Int_t kIsClassTree = BIT(7);
00033 const Int_t kUsedByData = BIT(11);
00034 const Int_t kUsedByFunc = BIT(12);
00035 const Int_t kUsedByCode = BIT(13);
00036 const Int_t kUsedByClass = BIT(14);
00037 const Int_t kUsingData = BIT(15);
00038 const Int_t kUsingFunc = BIT(16);
00039 const Int_t kUsingCode = BIT(17);
00040 const Int_t kUsingClass = BIT(18);
00041 const Int_t kUsedByCode1 = BIT(19);
00042 const Int_t kIsaPointer = BIT(20);
00043 const Int_t kIsBasic = BIT(21);
00044
00045 static Float_t gXsize, gYsize, gDx, gDy, gLabdx, gLabdy, gDxx, gCsize;
00046 static Int_t *gNtsons, *gNsons;
00047
00048 ClassImp(TClassTree)
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173 TClassTree::TClassTree()
00174 {
00175
00176
00177 fShowCod = 0;
00178 fShowHas = 0;
00179 fShowMul = 0;
00180 fShowRef = 0;
00181 fNclasses = 0;
00182 fCstatus = 0;
00183 fParents = 0;
00184 fCparent = 0;
00185 fCpointer = 0;
00186 fCnames = 0;
00187 fCtitles = 0;
00188 fOptions = 0;
00189 fLinks = 0;
00190 fDerived = 0;
00191 fNdata = 0;
00192 SetLabelDx();
00193 SetYoffset(0);
00194 #ifdef ROOTSRCDIR
00195 SetSourceDir(".:src:" ROOTSRCDIR);
00196 #else
00197 SetSourceDir(".:src:$ROOTSYS/src");
00198 #endif
00199 }
00200
00201
00202
00203 TClassTree::TClassTree(const char *name, const char *classes)
00204 :TNamed(name,classes)
00205 {
00206
00207
00208 fShowCod = 0;
00209 fShowHas = 0;
00210 fShowMul = 0;
00211 fShowRef = 0;
00212 fNclasses = 0;
00213 fCstatus = 0;
00214 fParents = 0;
00215 fCparent = 0;
00216 fCpointer = 0;
00217 fCnames = 0;
00218 fCtitles = 0;
00219 fOptions = 0;
00220 fLinks = 0;
00221 fDerived = 0;
00222 fNdata = 0;
00223 SetLabelDx();
00224 SetYoffset(0);
00225 #ifdef ROOTSRCDIR
00226 SetSourceDir(".:src:" ROOTSRCDIR);
00227 #else
00228 SetSourceDir(".:src:$ROOTSYS/src");
00229 #endif
00230
00231
00232 if (classes && strlen(classes)) {
00233 fClasses = classes;
00234 Draw();
00235 }
00236 }
00237
00238
00239
00240 TClassTree::~TClassTree()
00241 {
00242
00243
00244 for (Int_t i=0;i<fNclasses;i++) {
00245
00246 if (fLinks[i]) fLinks[i]->Delete();
00247
00248
00249 }
00250 delete [] fCnames;
00251 delete [] fCtitles;
00252 delete [] fCstatus;
00253 delete [] fParents;
00254 delete [] fCparent;
00255 delete [] fCpointer;
00256 delete [] fOptions;
00257 delete [] fLinks;
00258 delete [] fDerived;
00259 delete [] fNdata;
00260 }
00261
00262
00263
00264 void TClassTree::Draw(const char *classes)
00265 {
00266
00267
00268
00269 if (!gPad) {
00270 gROOT->MakeDefCanvas();
00271 }
00272 Init();
00273 if (classes && strlen(classes)) fClasses = classes;
00274 for (Int_t i=0;i<fNclasses;i++) {
00275 fCstatus[i] = 0;
00276 fCparent[i] = -1;
00277 }
00278 Paint();
00279 }
00280
00281
00282
00283 Int_t TClassTree::FindClass(const char *classname)
00284 {
00285
00286
00287 for (Int_t i=0;i<fNclasses;i++) {
00288 if(!fCnames[i]->CompareTo(classname)) return i;
00289 }
00290 return -1;
00291 }
00292
00293
00294
00295 void TClassTree::FindClassesUsedBy(Int_t iclass)
00296 {
00297
00298
00299 fCstatus[iclass] = 1;
00300 Int_t i;
00301 TObjString *os;
00302 TList *los = fLinks[iclass];
00303 TIter next(los);
00304 while ((os = (TObjString*)next())) {
00305 i = FindClass(os->GetName());
00306 if (i < 0) continue;
00307 if (fCstatus[i]) continue;
00308 Int_t udata = os->TestBit(kUsedByData);
00309 Int_t ufunc = os->TestBit(kUsedByFunc);
00310 Int_t ucode = os->TestBit(kUsedByCode);
00311 Int_t uclass = os->TestBit(kUsedByClass);
00312 if (udata || ufunc || ucode || uclass) {
00313 fCstatus[i] = 1;
00314 }
00315 }
00316 }
00317
00318
00319
00320 void TClassTree::FindClassesUsing(Int_t iclass)
00321 {
00322
00323
00324
00325 fCstatus[iclass] = 1;
00326 Int_t i;
00327 TObjString *os;
00328 TList *los = fLinks[iclass];
00329 TIter next(los);
00330 while ((os = (TObjString*)next())) {
00331 i = FindClass(os->GetName());
00332 if (i < 0) continue;
00333 if (fCstatus[i]) continue;
00334 Int_t udata = os->TestBit(kUsingData);
00335 Int_t ufunc = os->TestBit(kUsingFunc);
00336 Int_t ucode = os->TestBit(kUsingCode);
00337 Int_t uclass = os->TestBit(kUsingClass);
00338 if (udata || ufunc || ucode || uclass) {
00339 fCstatus[i] = 1;
00340 }
00341 }
00342 }
00343
00344
00345
00346 void TClassTree::FindClassPosition(const char *classname, Float_t &x, Float_t &y)
00347 {
00348
00349
00350
00351 TIter next(gPad->GetListOfPrimitives());
00352 TObject *obj;
00353 TPaveClass *pave;
00354 while((obj=next())) {
00355 if (obj->InheritsFrom(TPaveClass::Class())) {
00356 pave = (TPaveClass*)obj;
00357 if (!strcmp(pave->GetLabel(),classname)) {
00358 x = 0.5*(pave->GetX1() + pave->GetX2());
00359 y = 0.5*(pave->GetY1() + pave->GetY2());
00360 return;
00361 }
00362 }
00363 }
00364 x = y = 0;
00365 }
00366
00367
00368
00369 void TClassTree::Init()
00370 {
00371
00372
00373 if (fNclasses) return;
00374
00375
00376 gClassTable->Init();
00377 fNclasses = gClassTable->Classes();
00378 fCnames = new TString*[fNclasses];
00379 fCtitles = new TString*[fNclasses];
00380 fCstatus = new Int_t[fNclasses];
00381 fParents = new Int_t[fNclasses];
00382 fCparent = new Int_t[fNclasses];
00383 fNdata = new Int_t[fNclasses];
00384 fCpointer = new TClass*[fNclasses];
00385 fOptions = new TString*[fNclasses];
00386 fLinks = new TList*[fNclasses];
00387 fDerived = new char*[fNclasses];
00388
00389 Int_t i,j;
00390 for (i=0;i<fNclasses;i++) {
00391 fCnames[i] = new TString(gClassTable->Next());
00392 fCpointer[i] = TClass::GetClass(fCnames[i]->Data());
00393 fCtitles[i] = new TString(fCpointer[i]->GetTitle());
00394 fCstatus[i] = 0;
00395 fOptions[i] = new TString("ID");
00396 fLinks[i] = new TList();
00397 fDerived[i] = new char[fNclasses];
00398 }
00399 TBaseClass *clbase;
00400 TClass *cl;
00401 for (i=0;i<fNclasses;i++) {
00402 TList *lm = fCpointer[i]->GetListOfDataMembers();
00403 if (lm) fNdata[i] = lm->GetSize();
00404 else fNdata[i] = 0;
00405
00406 char *derived = fDerived[i];
00407 for (j=0;j<fNclasses;j++) {
00408 derived[j] = 0;
00409 if (fCpointer[i]->InheritsFrom(fCpointer[j])) {
00410 derived[j] = 1;
00411 }
00412 }
00413
00414 fParents[i] = -1;
00415 TList *lb = fCpointer[i]->GetListOfBases();
00416 if (!lb) continue;
00417 clbase = (TBaseClass*)lb->First();
00418 if (clbase == 0) continue;
00419 cl = (TClass*)clbase->GetClassPointer();
00420 for (j=0;j<fNclasses;j++) {
00421 if(cl == fCpointer[j]) {
00422 fParents[i] = j;
00423 break;
00424 }
00425 }
00426 }
00427
00428 for (i=0;i<fNclasses;i++) {
00429 ScanClasses(i);
00430 }
00431 }
00432
00433
00434
00435 void TClassTree::ls(Option_t *) const
00436 {
00437
00438
00439 char line[500];
00440 for (Int_t i=0;i<fNclasses;i++) {
00441 snprintf(line,500,"%s%s",fCnames[i]->Data(),"...........................");
00442 snprintf(&line[30],460,"%s",fCtitles[i]->Data());
00443 line[79] = 0;
00444 printf("%5d %s\n",i,line);
00445 }
00446 }
00447
00448
00449
00450 TObjString *TClassTree::Mark(const char *classname, TList *los, Int_t abit)
00451 {
00452
00453
00454 if (!los) return 0;
00455 TObjString *os = (TObjString*)los->FindObject(classname);
00456 if (!os) {
00457 os = new TObjString(classname);
00458 los->Add(os);
00459 }
00460 os->SetBit(abit);
00461 return os;
00462 }
00463
00464
00465
00466 void TClassTree::Paint(Option_t *)
00467 {
00468
00469
00470
00471 if (gPad) {
00472 TIter next(gPad->GetListOfPrimitives());
00473 TObject *obj;
00474 while((obj=next())) {
00475 if (obj->TestBit(kIsClassTree)) delete obj;
00476 }
00477 }
00478
00479 Int_t nch = strlen(GetClasses());
00480 if (nch == 0) return;
00481 char *classes = new char[nch+1];
00482 gNsons = new Int_t[fNclasses];
00483 gNtsons = new Int_t[fNclasses];
00484 strlcpy(classes,GetClasses(),nch+1);
00485 Int_t i,j;
00486 char *derived;
00487 char *ptr = strtok(classes,":");
00488
00489 while (ptr) {
00490 nch = strlen(ptr);
00491 if (ptr[0] == '*') {
00492 j = FindClass(&ptr[1]);
00493 if (j >= 0) {
00494 for (i=0;i<fNclasses;i++) {
00495 derived = fDerived[i];
00496 if(derived[j]) fCstatus[i] = 1;
00497 }
00498 }
00499 } else if (ptr[0] == '>') {
00500 for (i=0;i<fNclasses;i++) {
00501 if(fCnames[i]->Contains(&ptr[1])) {
00502 FindClassesUsing(i);
00503 fCstatus[i] = 2;
00504 break;
00505 }
00506 }
00507 } else if (ptr[nch-1] == '<') {
00508 ptr[nch-1] = 0;
00509 for (i=0;i<fNclasses;i++) {
00510 if(fCnames[i]->Contains(ptr)) {
00511 FindClassesUsedBy(i);
00512 FindClassesUsing(i);
00513 fCstatus[i] = 2;
00514 break;
00515 }
00516 }
00517 } else if (ptr[nch-1] == '*') {
00518 ptr[nch-1] = 0;
00519 for (i=0;i<fNclasses;i++) {
00520 if(fCnames[i]->Contains(ptr)) fCstatus[i] = 1;
00521 }
00522 } else {
00523 for (i=0;i<fNclasses;i++) {
00524 if(!fCnames[i]->CompareTo(ptr)) {
00525 FindClassesUsedBy(i);
00526 fCstatus[i] = 2;
00527 break;
00528 }
00529 }
00530 }
00531 ptr = strtok(0,":");
00532 }
00533
00534 for (i=0;i<fNclasses;i++) {
00535 gNsons[i] = gNtsons[i] = 0;
00536 }
00537 for (i=0;i<fNclasses;i++) {
00538 if (fCstatus[i] == 0) continue;
00539 derived = fDerived[i];
00540 for (j=0;j<fNclasses;j++) {
00541 if (j == i) continue;
00542 if(derived[j]) {
00543 fCstatus[j] = 1;
00544 }
00545 }
00546 }
00547
00548 for (i=0;i<fNclasses;i++) {
00549 if (fCstatus[i] == 0) continue;
00550 j = fParents[i];
00551 if (j >=0 ) {
00552 fCparent[i] = j;
00553 gNsons[j]++;
00554 }
00555 }
00556
00557 Int_t maxlev = 1;
00558 Int_t icl,ip;
00559 for (i=0;i<fNclasses;i++) {
00560 if (fCstatus[i] == 0) continue;
00561 if (gNsons[i] != 0) continue;
00562 icl = i;
00563 Int_t nlevel = 1;
00564 while (fCparent[icl] >= 0) {
00565 nlevel++;
00566 if (nlevel > maxlev) maxlev = nlevel;
00567 ip = fCparent[icl];
00568 gNtsons[ip]++;
00569 icl = ip;
00570 }
00571 }
00572
00573
00574 Int_t ndiv=0;
00575 Int_t nmore = 0;
00576 for (i=0;i<fNclasses;i++) {
00577 if (fCstatus[i] == 0) continue;
00578 if (fCparent[i] < 0) {
00579 ndiv += gNtsons[i]+1;
00580 nmore++;
00581 }
00582 }
00583 ndiv++;
00584
00585
00586 Float_t xmin = gPad->GetX1();
00587 Float_t xmax = gPad->GetX2();
00588 Float_t ymin = gPad->GetY1();
00589 Float_t ymax = gPad->GetY2();
00590 Float_t ytop = gYsize/20;
00591 gXsize = xmax - xmin;
00592 gYsize = ymax - ymin;
00593 gDy = (gYsize-ytop)/(ndiv);
00594 if (gDy > gYsize/10.) gDy = gYsize/10.;
00595 gDx = 0.9*gXsize/5;
00596 if (maxlev > 5) gDx = 0.97*gXsize/maxlev;
00597 Float_t y = ymax -ytop;
00598 gLabdx = fLabelDx*gXsize;
00599 if (gLabdx > 0.95*gDx) gLabdx = 0.95*gDx;
00600 gLabdy = 0.3*gDy;
00601 gDxx = 0.5*gXsize/26.;
00602 Float_t xleft = xmin +gDxx;
00603 Float_t ymore = 0.5*nmore*gDy+fYoffset*gYsize;
00604 Int_t dxpixels = gPad->XtoAbsPixel(gLabdx) - gPad->XtoAbsPixel(0);
00605 Int_t dypixels = gPad->YtoAbsPixel(0) - gPad->YtoAbsPixel(gLabdy);
00606 gCsize = dxpixels/(10.*dypixels);
00607 gCsize = std::max(gCsize,Float_t(0.75));
00608 gCsize = std::min(gCsize,Float_t(1.1));
00609
00610 for (i=0;i<fNclasses;i++) {
00611 if (fCstatus[i] == 0) continue;
00612 if (fCparent[i] < 0) {
00613 y -= gDy+0.5*gNtsons[i]*gDy;
00614 if (!fCnames[i]->CompareTo("TObject")) y += ymore;
00615 PaintClass(i,xleft,y);
00616 y -= 0.5*gNtsons[i]*gDy;
00617 }
00618 }
00619
00620
00621 if (fShowCod) ShowCod();
00622 if (fShowHas) ShowHas();
00623 if (fShowMul) ShowMul();
00624 if (fShowRef) ShowRef();
00625
00626 nch = strlen(GetClasses());
00627 xmax = 0.3;
00628 if (nch > 20) xmax = 0.5;
00629 if (nch > 50) xmax = 0.7;
00630 if (nch > 70) xmax = 0.9;
00631 TPaveClass *ptitle = new TPaveClass(xmin +0.1*gXsize/26.
00632 ,ymin+gYsize-0.9*gYsize/20.
00633 ,xmin+xmax*gXsize
00634 ,ymin+gYsize-0.1*gYsize/26.
00635 ,GetClasses(),this);
00636 ptitle->SetFillColor(42);
00637 ptitle->SetBit(kIsClassTree);
00638 ptitle->Draw();
00639
00640
00641 delete [] classes;
00642 delete [] gNsons;
00643 delete [] gNtsons;
00644 }
00645
00646
00647
00648 void TClassTree::PaintClass(Int_t iclass, Float_t xleft, Float_t y)
00649 {
00650
00651
00652 Float_t u[2],yu=0,yl=0;
00653 Int_t ns = gNsons[iclass];
00654 u[0] = xleft;
00655 u[1] = u[0]+gDxx;
00656 if(ns != 0) u[1] = u[0]+gDx;
00657 TLine *line = new TLine(u[0],y,u[1],y);
00658 line->SetBit(kIsClassTree);
00659 line->Draw();
00660 Int_t icobject = FindClass("TObject");
00661 TPaveClass *label = new TPaveClass(xleft+gDxx,y-gLabdy,xleft+gLabdx,y+gLabdy,fCnames[iclass]->Data(),this);
00662 char *derived = fDerived[iclass];
00663 if (icobject >= 0 && !derived[icobject]) label->SetFillColor(30);
00664 if (fCstatus[iclass] > 1) label->SetFillColor(kYellow);
00665 label->SetTextSize(gCsize);
00666 label->SetBit(kIsClassTree);
00667 label->SetToolTipText(fCtitles[iclass]->Data(),500);
00668 label->Draw();
00669 if (ns == 0) return;
00670
00671
00672 y += 0.5*gNtsons[iclass]*gDy;
00673 Int_t first =0;
00674 for (Int_t i=0;i<fNclasses;i++) {
00675 if(fCparent[i] != iclass) continue;
00676 if (gNtsons[i] > 1) y -= 0.5*gNtsons[i]*gDy;
00677 else y -= 0.5*gDy;
00678 if (!first) {first=1; yu = y;}
00679 PaintClass(i,u[1],y);
00680 yl = y;
00681 if (gNtsons[i] > 1) y -= 0.5*gNtsons[i]*gDy;
00682 else y -= 0.5*gDy;
00683 }
00684 if (ns == 1) return;
00685 line = new TLine(u[1],yl,u[1],yu);
00686 line->SetBit(kIsClassTree);
00687 line->Draw();
00688 }
00689
00690
00691
00692 void TClassTree::SaveAs(const char *filename, Option_t *option) const
00693 {
00694
00695
00696
00697
00698
00699
00700
00701 if (gDirectory) gDirectory->SaveObjectAs(this,filename,option);
00702 }
00703
00704
00705
00706 void TClassTree::ScanClasses(Int_t iclass)
00707 {
00708
00709
00710
00711 Int_t ic, icl;
00712 TList *los = fLinks[iclass];
00713 TList *losref = 0;
00714 TObjString *os;
00715
00716
00717
00718 TClass *cl = fCpointer[iclass];
00719 TDataMember *dm;
00720 TList *lm = cl->GetListOfDataMembers();
00721 if (lm) {
00722 TIter next(lm);
00723 Int_t imember = 0;
00724 while ((dm = (TDataMember *) next())) {
00725 imember++;
00726 ic = FindClass(dm->GetTypeName());
00727 if (ic < 0 || ic == iclass) continue;
00728 losref = fLinks[ic];
00729 os = Mark(fCnames[ic]->Data(),los,kUsedByData);
00730 os->SetBit(kIsaPointer,dm->IsaPointer());
00731 os->SetBit(kIsBasic,dm->IsBasic());
00732 os->SetUniqueID(imember);
00733 Mark(fCnames[iclass]->Data(),losref,kUsingData);
00734 }
00735 }
00736
00737
00738
00739 char *derived = fDerived[iclass];
00740 TBaseClass *clbase;
00741 Int_t numb = 0;
00742 TList *lb = fCpointer[iclass]->GetListOfBases();
00743 if (lb) {
00744 TIter nextb(lb);
00745 while ((clbase = (TBaseClass*)nextb())) {
00746 numb++;
00747 if (numb == 1) continue;
00748 ic = FindClass(clbase->GetName());
00749 derived[ic] = 2;
00750 }
00751 for (ic=0;ic<fNclasses;ic++) {
00752 if (ic == iclass) continue;
00753 if (derived[ic]) {
00754 losref = fLinks[ic];
00755 Mark(fCnames[ic]->Data(),los,kUsedByClass);
00756 Mark(fCnames[iclass]->Data(),losref,kUsingClass);
00757 }
00758 }
00759 }
00760
00761
00762
00763 char *star, *cref;
00764 TMethod *method;
00765 TMethodArg *methodarg;
00766 TList *lf = cl->GetListOfMethods();
00767 if (lf) {
00768 TIter nextm(lf);
00769 TString name;
00770 while ((method = (TMethod*) nextm())) {
00771
00772 name = method->GetReturnTypeName();
00773 star = strstr((char*)name.Data(),"*");
00774 if (star) *star = 0;
00775 cref = strstr((char*)name.Data(),"&");
00776 if (cref) *cref = 0;
00777 ic = FindClass(name);
00778 if (ic < 0 || ic == iclass) continue;
00779 losref = fLinks[ic];
00780 Mark(fCnames[ic]->Data(),los,kUsedByFunc);
00781 Mark(fCnames[iclass]->Data(),losref,kUsingFunc);
00782
00783
00784
00785 TIter nexta(method->GetListOfMethodArgs());
00786 while ((methodarg = (TMethodArg*) nexta())) {
00787 name = methodarg->GetTypeName();
00788 star = strstr((char*)name.Data(),"*");
00789 if (star) *star = 0;
00790 cref = strstr((char*)name.Data(),"&");
00791 if (cref) *cref = 0;
00792 ic = FindClass(name);
00793 if (ic < 0 || ic == iclass) continue;
00794 losref = fLinks[ic];
00795 Mark(fCnames[ic]->Data(),los,kUsedByFunc);
00796 Mark(fCnames[iclass]->Data(),losref,kUsingFunc);
00797 }
00798 }
00799 }
00800
00801
00802
00803
00804
00805
00806 if (!cl->GetImplFileName() || !cl->GetImplFileName()[0])
00807 return;
00808
00809 const char *source = gSystem->BaseName( gSystem->UnixPathName(cl->GetImplFileName()));
00810 char *sourceName = gSystem->Which( fSourceDir.Data(), source , kReadPermission );
00811 if (!sourceName) return;
00812 Int_t ncn = strlen(fCnames[iclass]->Data())+2;
00813 char *cname = new char[ncn+1];
00814 snprintf(cname,ncn,"%s::",fCnames[iclass]->Data());
00815
00816 ifstream sourceFile;
00817 sourceFile.open( sourceName, ios::in );
00818 Int_t nlines = 0;
00819 if( sourceFile.good() ) {
00820 const Int_t kMAXLEN=1500;
00821 char line[kMAXLEN];
00822 while( !sourceFile.eof() ) {
00823 sourceFile.getline( line, kMAXLEN-1 );
00824 if( sourceFile.eof() ) break;
00825 Int_t nblank = strspn(line," ");
00826 if (!strncmp(&line[nblank],"//",2)) continue;
00827 char *cc = strstr(line,"::");
00828 if (cc) {
00829 *cc = 0;
00830 if (!strncmp(&line[nblank],cname,ncn)) break;
00831 Int_t nl = strlen(&line[nblank]);
00832 if (!strncmp(&line[nblank],cc+2,nl)) break;
00833 }
00834 nlines++; if (nlines > 1000) break;
00835 char *inc = strstr(line,"#include");
00836 if (inc) {
00837 char *ch = strstr(line,".h");
00838 if (!ch) continue;
00839 *ch = 0;
00840 char *start = strstr(line,"<");
00841 if (!start) start = strstr(line,"\"");
00842 if (!start) continue;
00843 start++;
00844 while ((start < ch) && (*start == ' ')) start++;
00845 icl = FindClass(start);
00846 if (icl < 0 || icl == iclass) continue;
00847
00848 losref = fLinks[icl];
00849 Mark(fCnames[icl]->Data(),los,kUsedByCode1);
00850 Mark(fCnames[icl]->Data(),los,kUsedByCode);
00851 Mark(fCnames[iclass]->Data(),losref,kUsingCode);
00852
00853 derived = fDerived[icl];
00854 for (ic=0;ic<fNclasses;ic++) {
00855 if (ic == icl) continue;
00856 if (derived[ic]) {
00857 losref = fLinks[ic];
00858 Mark(fCnames[ic]->Data(),los,kUsedByCode);
00859 Mark(fCnames[iclass]->Data(),losref,kUsingCode);
00860 }
00861 }
00862 }
00863 }
00864 }
00865 delete [] cname;
00866 sourceFile.close();
00867 }
00868
00869
00870
00871 void TClassTree::SetClasses(const char *classes, Option_t *)
00872 {
00873
00874
00875
00876 if (classes == 0) return;
00877 fClasses = classes;
00878 for (Int_t i=0;i<fNclasses;i++) {
00879 fCstatus[i] = 0;
00880 fCparent[i] = -1;
00881 }
00882 if (gPad) Paint();
00883 }
00884
00885
00886
00887 void TClassTree::SetLabelDx(Float_t labeldx)
00888 {
00889
00890
00891 fLabelDx = labeldx;
00892 if (gPad) Paint();
00893 }
00894
00895
00896
00897 void TClassTree::SetYoffset(Float_t offset)
00898 {
00899
00900
00901
00902
00903 fYoffset = offset;
00904 if (gPad) Paint();
00905 }
00906
00907
00908
00909 void TClassTree::ShowClassesUsedBy(const char *classes)
00910 {
00911
00912
00913 Int_t i,j;
00914 Int_t nch = strlen(classes);
00915 char *ptr = new char[nch+1];
00916 strlcpy(ptr,classes,nch+1);
00917 if (ptr[0] == '*') {
00918 i = FindClass(&ptr[1]);
00919 if (i >= 0) {
00920 char *derived = fDerived[i];
00921 for (j=0;j<fNclasses;j++) {
00922 if(derived[j]) FindClassesUsedBy(j);
00923 }
00924 }
00925 } else if (ptr[nch-1] == '*') {
00926 ptr[nch-1] = 0;
00927 for (j=0;j<fNclasses;j++) {
00928 if(fCnames[j]->Contains(ptr)) FindClassesUsedBy(j);
00929 }
00930 } else {
00931 for (j=0;j<fNclasses;j++) {
00932 if(!fCnames[j]->CompareTo(ptr)) FindClassesUsedBy(j);
00933 }
00934 }
00935 delete [] ptr;
00936 if (gPad) Paint();
00937 }
00938
00939
00940
00941 void TClassTree::ShowClassesUsing(const char *classes)
00942 {
00943
00944
00945 Int_t i,j;
00946 Int_t nch = strlen(classes);
00947 char *ptr = new char[nch+1];
00948 strlcpy(ptr,classes,nch+1);
00949 if (ptr[0] == '*') {
00950 i = FindClass(&ptr[1]);
00951 if (i >= 0) {
00952 char *derived = fDerived[i];
00953 for (j=0;j<fNclasses;j++) {
00954 if(derived[j]) FindClassesUsing(j);
00955 }
00956 }
00957 } else if (ptr[nch-1] == '*') {
00958 ptr[nch-1] = 0;
00959 for (j=0;j<fNclasses;j++) {
00960 if(fCnames[j]->Contains(ptr)) FindClassesUsing(j);
00961 }
00962 } else {
00963 for (j=0;j<fNclasses;j++) {
00964 if(!fCnames[j]->CompareTo(ptr)) FindClassesUsing(j);
00965 }
00966 }
00967 delete [] ptr;
00968 if (gPad) Paint();
00969 }
00970
00971
00972
00973 void TClassTree::ShowCod()
00974 {
00975
00976
00977 TIter next(gPad->GetListOfPrimitives());
00978 TObject *obj;
00979 TObjString *os;
00980 TPaveClass *pave;
00981 Int_t ic,icl;
00982 Float_t x,y,x1,y1;
00983
00984 while((obj=next())) {
00985 if (obj->InheritsFrom(TPaveClass::Class())) {
00986 pave = (TPaveClass*)obj;
00987 icl = FindClass(pave->GetLabel());
00988 if (icl < 0) continue;
00989 char *derived = fDerived[icl];
00990 x = 0.5*(pave->GetX1() + pave->GetX2());
00991 y = 0.5*(pave->GetY1() + pave->GetY2());
00992 TIter nextos(fLinks[icl]);
00993
00994 while((os=(TObjString*)nextos())) {
00995 if (!os->TestBit(kUsedByCode1)) continue;
00996 ic = FindClass(os->GetName());
00997 if (derived[ic]) continue;
00998 FindClassPosition(os->GetName(),x1,y1);
00999 if (x1 == 0 || y1 == 0) continue;
01000 TArrow *arrow = new TArrow(x,y,x1,y1,0.008,"|>");
01001 arrow->SetLineColor(kGreen);
01002 arrow->SetFillColor(kGreen);
01003 arrow->SetBit(kIsClassTree);
01004 arrow->Draw();
01005 }
01006 }
01007 }
01008 }
01009
01010
01011
01012 void TClassTree::ShowHas()
01013 {
01014
01015
01016 TIter next(gPad->GetListOfPrimitives());
01017 TObject *obj;
01018 TObjString *os;
01019 TPaveClass *pave;
01020 Int_t icl;
01021 Float_t y,x1,y1,dx;
01022
01023 while((obj=next())) {
01024 if (obj->InheritsFrom(TPaveClass::Class())) {
01025 pave = (TPaveClass*)obj;
01026 icl = FindClass(pave->GetLabel());
01027 if (icl < 0) continue;
01028 y = 0.5*(pave->GetY1() + pave->GetY2());
01029 Int_t nmembers = fNdata[icl];
01030 if (nmembers == 0) continue;
01031 dx = (pave->GetX2() - pave->GetX1())/nmembers;
01032 TIter nextos(fLinks[icl]);
01033
01034 while((os=(TObjString*)nextos())) {
01035 if (!os->TestBit(kUsedByData)) continue;
01036 if (os->TestBit(kIsaPointer)) continue;
01037 if (os->TestBit(kIsBasic)) continue;
01038 FindClassPosition(os->GetName(),x1,y1);
01039 if (x1 == 0 || y1 == 0) continue;
01040 Int_t imember = os->GetUniqueID();
01041 TLine *line = new TLine(pave->GetX1()+(imember+0.5)*dx,y,x1,y1);
01042 line->SetLineStyle(3);
01043 line->SetLineColor(6);
01044 line->SetBit(kIsClassTree);
01045 line->Draw();
01046 }
01047 }
01048 }
01049 }
01050
01051
01052
01053 void TClassTree::ShowLinks(Option_t *option)
01054 {
01055
01056
01057
01058
01059
01060
01061
01062 TString opt = option;
01063 opt.ToUpper();
01064 fShowCod = fShowHas = fShowMul = fShowRef = 0;
01065 if (opt.Contains("C")) fShowCod = 1;
01066 if (opt.Contains("H")) fShowHas = 1;
01067 if (opt.Contains("M")) fShowMul = 1;
01068 if (opt.Contains("R")) fShowRef = 1;
01069 if (gPad) Paint();
01070 }
01071
01072
01073
01074 void TClassTree::ShowMul()
01075 {
01076
01077
01078 TIter next(gPad->GetListOfPrimitives());
01079 TObject *obj;
01080 TObjString *os;
01081 TPaveClass *pave;
01082 Int_t ic,icl;
01083 Float_t x,y,x1,y1;
01084
01085 while((obj=next())) {
01086 if (obj->InheritsFrom(TPaveClass::Class())) {
01087 pave = (TPaveClass*)obj;
01088 icl = FindClass(pave->GetLabel());
01089 if (icl < 0) continue;
01090 char *derived = fDerived[icl];
01091 x = 0.5*(pave->GetX1() + pave->GetX2());
01092 y = 0.5*(pave->GetY1() + pave->GetY2());
01093 TIter nextos(fLinks[icl]);
01094
01095 while((os=(TObjString*)nextos())) {
01096 if (!os->TestBit(kUsedByClass)) continue;
01097 ic = FindClass(os->GetName());
01098 if (derived[ic] != 2) continue;
01099 FindClassPosition(os->GetName(),x1,y1);
01100 if (x1 == 0 || y1 == 0) continue;
01101 TLine *line = new TLine(x,y,x1,y1);
01102 line->SetBit(kIsClassTree);
01103 line->SetLineStyle(2);
01104 line->SetLineColor(kBlue);
01105 line->Draw();
01106 }
01107 }
01108 }
01109 }
01110
01111
01112
01113 void TClassTree::ShowRef()
01114 {
01115
01116
01117 TIter next(gPad->GetListOfPrimitives());
01118 TObject *obj;
01119 TObjString *os;
01120 TPaveClass *pave;
01121 Int_t ic,icl;
01122 Float_t y,x1,y1,dx;
01123 Int_t icc = FindClass("TClass");
01124
01125 while((obj=next())) {
01126 if (obj->InheritsFrom(TPaveClass::Class())) {
01127 pave = (TPaveClass*)obj;
01128 icl = FindClass(pave->GetLabel());
01129 if (icl < 0) continue;
01130 y = 0.5*(pave->GetY1() + pave->GetY2());
01131 Int_t nmembers = fNdata[icl];
01132 if (nmembers == 0) continue;
01133 dx = (pave->GetX2() - pave->GetX1())/nmembers;
01134 TIter nextos(fLinks[icl]);
01135
01136 while((os=(TObjString*)nextos())) {
01137 if (!os->TestBit(kUsedByData)) continue;
01138 ic = FindClass(os->GetName());
01139 if (!os->TestBit(kIsaPointer)) continue;
01140 if (os->TestBit(kIsBasic)) continue;
01141 if (ic == icc) continue;
01142 FindClassPosition(os->GetName(),x1,y1);
01143 if (x1 == 0 || y1 == 0) continue;
01144 Int_t imember = os->GetUniqueID();
01145 TArrow *arrow = new TArrow(pave->GetX1()+(imember+0.5)*dx,y,x1,y1,0.008,"|>");
01146 arrow->SetLineColor(kRed);
01147 arrow->SetFillColor(kRed);
01148 arrow->SetBit(kIsClassTree);
01149 arrow->Draw();
01150 }
01151 }
01152 }
01153 }
01154
01155
01156
01157 void TClassTree::Streamer(TBuffer &R__b)
01158 {
01159
01160
01161
01162 Int_t i;
01163 if (R__b.IsReading()) {
01164 Version_t R__v = R__b.ReadVersion(); if (R__v) { }
01165 TNamed::Streamer(R__b);
01166 fClasses.Streamer(R__b);
01167 R__b >> fYoffset;
01168 R__b >> fLabelDx;
01169 R__b >> fNclasses;
01170 R__b >> fShowCod;
01171 R__b >> fShowMul;
01172 R__b >> fShowHas;
01173 R__b >> fShowRef;
01174 fCnames = new TString*[fNclasses];
01175 fCtitles = new TString*[fNclasses];
01176 fCstatus = new Int_t[fNclasses];
01177 fParents = new Int_t[fNclasses];
01178 fCparent = new Int_t[fNclasses];
01179 fNdata = new Int_t[fNclasses];
01180 fCpointer = new TClass*[fNclasses];
01181 fOptions = new TString*[fNclasses];
01182 fLinks = new TList*[fNclasses];
01183 fDerived = new char*[fNclasses];
01184 for (i=0;i<fNclasses;i++) {
01185 R__b >> fCstatus[i];
01186 R__b >> fParents[i];
01187 R__b >> fNdata[i];
01188 fCnames[i] = new TString();
01189 fCtitles[i] = new TString();
01190 fOptions[i] = new TString();
01191 fCnames[i]->Streamer(R__b);
01192 fCtitles[i]->Streamer(R__b);
01193 fOptions[i]->Streamer(R__b);
01194 fLinks[i] = new TList();
01195 fLinks[i]->Streamer(R__b);
01196 fDerived[i] = new char[fNclasses];
01197 R__b.ReadFastArray(fDerived[i],fNclasses);
01198 }
01199 fSourceDir.Streamer(R__b);
01200 } else {
01201 R__b.WriteVersion(TClassTree::IsA());
01202 TNamed::Streamer(R__b);
01203 fClasses.Streamer(R__b);
01204 R__b << fYoffset;
01205 R__b << fLabelDx;
01206 R__b << fNclasses;
01207 R__b << fShowCod;
01208 R__b << fShowMul;
01209 R__b << fShowHas;
01210 R__b << fShowRef;
01211 for (i=0;i<fNclasses;i++) {
01212 R__b << fCstatus[i];
01213 R__b << fParents[i];
01214 R__b << fNdata[i];
01215 fCnames[i]->Streamer(R__b);
01216 fCtitles[i]->Streamer(R__b);
01217 fOptions[i]->Streamer(R__b);
01218 fLinks[i]->Streamer(R__b);
01219 R__b.WriteFastArray(fDerived[i],fNclasses);
01220 }
01221 fSourceDir.Streamer(R__b);
01222 }
01223 }