TInspectCanvas.cxx

Go to the documentation of this file.
00001 // @(#)root/gpad:$Id: TInspectCanvas.cxx 36264 2010-10-11 07:15:16Z brun $
00002 // Author: Rene Brun   08/01/2000
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, 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 "TROOT.h"
00013 #include "TGuiFactory.h"
00014 #include "TInspectCanvas.h"
00015 #include "TButton.h"
00016 #include "TClass.h"
00017 #include "TLine.h"
00018 #include "TLink.h"
00019 #include "TDataMember.h"
00020 #include "TDataType.h"
00021 #include "TRealData.h"
00022 #include "TLatex.h"
00023 
00024 ClassImp(TInspectCanvas)
00025 
00026 //////////////////////////////////////////////////////////////////////////
00027 //                                                                      //
00028 // TInspectorObject                                                     //
00029 //                                                                      //
00030 //////////////////////////////////////////////////////////////////////////
00031 
00032 class TInspectorObject : public TObject
00033 {
00034    // This class is designed to wrap a Foreign object in order to
00035    // inject it into the Browse sub-system.
00036 
00037 public:
00038 
00039    TInspectorObject(void *obj, TClass *cl) : fObj(obj),fClass(cl) {};
00040    ~TInspectorObject(){;}
00041 
00042    void   *GetObject() const { return fObj; };
00043    void    Inspect() const {
00044       gGuiFactory->CreateInspectorImp(this, 400, 200);
00045    };
00046    TClass *IsA() const { return fClass; }
00047 
00048 private:
00049    void     *fObj;   //! pointer to the foreign object
00050    TClass   *fClass; //! pointer to class of the foreign object
00051 
00052 };
00053 
00054 
00055 //______________________________________________________________________________//*-*
00056 //*-*   A InspectCanvas is a canvas specialized to inspect Root objects.
00057 //
00058 //Begin_Html
00059 /*
00060 <img src="gif/InspectCanvas.gif">
00061 */
00062 //End_Html
00063 //
00064 
00065 
00066 //______________________________________________________________________________
00067 TInspectCanvas::TInspectCanvas() : TCanvas()
00068 {
00069    // InspectCanvas default constructor.
00070 
00071    fBackward   = 0;
00072    fForward    = 0;
00073    fCurObject  = 0;
00074    fObjects    = 0;
00075    fLogx       = kFALSE;
00076    fLogy       = kFALSE;
00077 }
00078 
00079 
00080 //_____________________________________________________________________________
00081 TInspectCanvas::TInspectCanvas(UInt_t ww, UInt_t wh)
00082             : TCanvas("inspect","ROOT Object Inspector",ww,wh)
00083 {
00084    // InspectCanvas constructor.
00085 
00086    fBackward   = 0;
00087    fForward    = 0;
00088    fCurObject  = 0;
00089    fObjects    = new TList;
00090    fLogx       = kFALSE;
00091    fLogy       = kFALSE;
00092 }
00093 
00094 
00095 //______________________________________________________________________________
00096 TInspectCanvas::~TInspectCanvas()
00097 {
00098    // InspectCanvas default destructor.
00099 
00100    if (fObjects) {
00101       fObjects->Clear("nodelete");
00102       delete fObjects;
00103    }
00104 }
00105 
00106 
00107 //______________________________________________________________________________
00108 void TInspectCanvas::InspectObject(TObject *obj)
00109 {
00110    // Dump contents of obj in a graphics canvas.
00111    // Same action as TObject::Dump but in a graphical form.
00112    // In addition pointers to other objects can be followed.
00113    //
00114    // The following picture is the Inspect of a histogram object:
00115    //Begin_Html
00116    /*
00117    <img src="gif/hpxinspect.gif">
00118    */
00119    //End_Html
00120 
00121    Int_t cdate = 0;
00122    Int_t ctime = 0;
00123    UInt_t *cdatime = 0;
00124    Bool_t isdate = kFALSE;
00125    Bool_t isbits = kFALSE;
00126    const Int_t kname  = 1;
00127    const Int_t kvalue = 25;
00128    const Int_t ktitle = 37;
00129    const Int_t kline  = 1024;
00130    char line[kline];
00131    char *pname;
00132 
00133    TClass *cl = obj->IsA();
00134    if (cl == 0) return;
00135    TInspectorObject *proxy=0;
00136    if (!cl->InheritsFrom(TObject::Class())) {
00137       // This is possible only if obj is actually a TInspectorObject
00138       // wrapping a non-TObject.
00139       proxy = (TInspectorObject*)obj;
00140       obj = (TObject*)proxy->GetObject();
00141    }
00142 
00143    if (!cl->GetListOfRealData()) cl->BuildRealData(obj);
00144 
00145    // Count number of data members in order to resize the canvas
00146    TRealData *rd;
00147    TIter      next(cl->GetListOfRealData());
00148    Int_t nreal = cl->GetListOfRealData()->GetSize();
00149    if (nreal == 0) return;
00150 
00151    Int_t nrows = 33;
00152    if (nreal+7 > nrows) nrows = nreal+7;
00153    Int_t nh = nrows*15;
00154    Int_t nw = 700;
00155    TVirtualPad *canvas = GetVirtCanvas();
00156    canvas->Clear();                // remove primitives from canvas
00157    canvas->SetCanvasSize(nw, nh);  // set new size of drawing area
00158    canvas->Range(0,-3,20,nreal+4);
00159 
00160    Float_t xvalue = 5;
00161    Float_t xtitle = 8;
00162    Float_t dy     = 1;
00163    Float_t ytext  = Float_t(nreal) - 1.5;
00164    Float_t tsize  = 0.99/ytext;
00165    if (tsize < 0.02) tsize = 0.02;
00166    if (tsize > 0.03) tsize = 0.03;
00167 
00168    // Create text objects
00169    TText tname, tvalue, ttitle;
00170    TText *tval;
00171    tname.SetTextFont(61);
00172    tname.SetTextAngle(0);
00173    tname.SetTextAlign(12);
00174    tname.SetTextColor(1);
00175    tname.SetTextSize(tsize);
00176    tvalue.SetTextFont(61);
00177    tvalue.SetTextAngle(0);
00178    tvalue.SetTextAlign(12);
00179    tvalue.SetTextColor(1);
00180    tvalue.SetTextSize(tsize);
00181    ttitle.SetTextFont(62);
00182    ttitle.SetTextAngle(0);
00183    ttitle.SetTextAlign(12);
00184    ttitle.SetTextColor(1);
00185    ttitle.SetTextSize(tsize);
00186 
00187    Float_t x1 = 0.2;
00188    Float_t x2 = 19.8;
00189    Float_t y1 = -0.5;
00190    Float_t y2 = Float_t(nreal) - 0.5;
00191    Float_t y3 = y2 + 1;
00192    Float_t y4 = y3 + 1.5;
00193    Float_t db = 25./GetWh();
00194    Float_t btop = 0.999;
00195 
00196    // Draw buttons
00197    fBackward = new TButton("backward","TInspectCanvas::GoBackward();",.01,btop-db,.15,btop);
00198    fBackward->Draw();
00199    fBackward->SetToolTipText("Inspect previous object");
00200    fForward  = new TButton("forward", "TInspectCanvas::GoForward();", .21,btop-db,.35,btop);
00201    fForward->Draw();
00202    fForward->SetToolTipText("Inspect next object");
00203 
00204    // Draw surrounding box and title areas
00205    TLine frame;
00206    frame.SetLineColor(1);
00207    frame.SetLineStyle(1);
00208    frame.SetLineWidth(1);
00209    frame.DrawLine(x1, y1, x2, y1);
00210    frame.DrawLine(x2, y1, x2, y4);
00211    frame.DrawLine(x2, y4, x1, y4);
00212    frame.DrawLine(x1, y4, x1, y1);
00213    frame.DrawLine(x1, y2, x2, y2);
00214    frame.DrawLine(x1, y3, x2, y3);
00215    frame.DrawLine(xvalue, y1, xvalue, y3);
00216    frame.DrawLine(xtitle, y1, xtitle, y3);
00217    ttitle.SetTextSize(0.8*tsize);
00218    ttitle.SetTextAlign(21);
00219    ttitle.DrawText(0.5*(x1+xvalue), y2+0.1, "Member Name");
00220    ttitle.DrawText(0.5*(xvalue+xtitle), y2+0.1, "Value");
00221    ttitle.DrawText(0.5*(xtitle+x2), y2+0.1, "Title");
00222    ttitle.SetTextSize(1.2*tsize);
00223    ttitle.SetTextColor(2);
00224    ttitle.SetTextAlign(11);
00225    ttitle.DrawText(x1+0.2, y3+0.1, cl->GetName());
00226    if (proxy==0) {
00227       ttitle.SetTextColor(4);
00228       strlcpy(line,obj->GetName(),kline);
00229       ttitle.DrawText(xvalue+0.2, y3+0.1, line);
00230       ttitle.SetTextColor(6);
00231       ttitle.DrawText(xtitle+2, y3+0.1, obj->GetTitle());
00232    } else {
00233       ttitle.SetTextColor(4);
00234       snprintf(line,1023,"%s:%d","Foreign object",0);
00235       ttitle.DrawText(xvalue+0.2, y3+0.1, line);
00236       ttitle.SetTextColor(6);
00237       ttitle.DrawText(xtitle+2, y3+0.1, "no title given");
00238    }
00239    ttitle.SetTextSize(tsize);
00240    ttitle.SetTextColor(1);
00241    ttitle.SetTextFont(11);
00242    ttitle.SetTextAlign(12);
00243 
00244    //---Now loop on data members-----------------------
00245    // We make 3 passes. Faster than one single pass because changing
00246    // font parameters is time consuming
00247    for (Int_t pass = 0; pass < 3; pass++) {
00248       ytext  = y2 - 0.5;
00249       next.Reset();
00250       while ((rd = (TRealData*) next())) {
00251          TDataMember *member = rd->GetDataMember();
00252          if (!member) continue;
00253          TDataType *membertype = member->GetDataType();
00254          isdate = kFALSE;
00255          if (strcmp(member->GetName(),"fDatime") == 0 && strcmp(member->GetTypeName(),"UInt_t") == 0) {
00256             isdate = kTRUE;
00257          }
00258          isbits = kFALSE;
00259          if (strcmp(member->GetName(),"fBits") == 0 && strcmp(member->GetTypeName(),"UInt_t") == 0) {
00260             isbits = kTRUE;
00261          }
00262 
00263          // Encode data member name
00264          pname = &line[kname];
00265          for (Int_t i=0;i<kline;i++) line[i] = ' ';
00266          line[kline-1] = 0;
00267          strlcpy(pname,rd->GetName(),kline-kname);
00268          if (strstr(member->GetFullTypeName(),"**")) strlcat(pname,"**",kline-kname);
00269 
00270          // Encode data value or pointer value
00271          tval = &tvalue;
00272          Int_t offset = rd->GetThisOffset();
00273          char *pointer = (char*)obj + offset;
00274          char **ppointer = (char**)(pointer);
00275          TLink *tlink = 0;
00276 
00277          TClass *clm=0;
00278          if (!membertype) {
00279             clm = member->GetClass();
00280          }
00281 
00282          if (member->IsaPointer()) {
00283             char **p3pointer = (char**)(*ppointer);
00284             if (clm && !clm->IsStartingWithTObject() ) {
00285                //NOTE: memory leak!
00286                p3pointer = (char**)new TInspectorObject(p3pointer,clm);
00287             }
00288 
00289             if (!p3pointer) {
00290                snprintf(&line[kvalue],kline-kvalue,"->0");
00291             } else if (!member->IsBasic()) {
00292                if (pass == 1) {
00293                   tlink = new TLink(xvalue+0.1, ytext, p3pointer);
00294                }
00295             } else if (membertype) {
00296                if (!strcmp(membertype->GetTypeName(), "char"))
00297                   strlcpy(&line[kvalue], *ppointer,kline-kvalue);
00298                else
00299                   strlcpy(&line[kvalue], membertype->AsString(p3pointer),kline-kvalue);
00300             } else if (!strcmp(member->GetFullTypeName(), "char*") ||
00301                      !strcmp(member->GetFullTypeName(), "const char*")) {
00302                strlcpy(&line[kvalue], *ppointer,kline-kvalue);
00303             } else {
00304                if (pass == 1) tlink = new TLink(xvalue+0.1, ytext, p3pointer);
00305             }
00306          } else if (membertype)
00307             if (isdate) {
00308                cdatime = (UInt_t*)pointer;
00309                TDatime::GetDateTime(cdatime[0],cdate,ctime);
00310                snprintf(&line[kvalue],kline-kvalue,"%d/%d",cdate,ctime);
00311             } else if (isbits) {
00312                snprintf(&line[kvalue],kline-kvalue,"0x%08x", *(UInt_t*)pointer);
00313             } else {
00314                strlcpy(&line[kvalue], membertype->AsString(pointer),kline-kvalue);
00315             }
00316          else
00317             snprintf(&line[kvalue],kline-kvalue,"->%lx ", (Long_t)pointer);
00318 
00319          // Encode data member title
00320          Int_t ltit = 0;
00321          if (isdate == kFALSE && strcmp(member->GetFullTypeName(), "char*") &&
00322              strcmp(member->GetFullTypeName(), "const char*")) {
00323             Int_t lentit = strlen(member->GetTitle());
00324             if (lentit >= kline-ktitle) lentit = kline-ktitle-1;
00325             strlcpy(&line[ktitle],member->GetTitle(),kline-ktitle);
00326             line[ktitle+lentit] = 0;
00327             ltit = ktitle;
00328          }
00329 
00330          // Ready to draw the name, value and title columns
00331          if (pass == 0)tname.DrawText( x1+0.1,  ytext, &line[kname]);
00332          if (pass == 1) {
00333             if (tlink) {
00334                tlink->SetTextFont(61);
00335                tlink->SetTextAngle(0);
00336                tlink->SetTextAlign(12);
00337                tlink->SetTextColor(2);
00338                tlink->SetTextSize(tsize);
00339                tlink->SetBit(kCanDelete);
00340                tlink->Draw();
00341                if (strstr(member->GetFullTypeName(),"**")) tlink->SetBit(TLink::kIsStarStar);
00342                tlink->SetName(member->GetTypeName());
00343             } else {
00344                tval->DrawText(xvalue+0.1, ytext, &line[kvalue]);
00345             }
00346          }
00347          if (pass == 2 && ltit) ttitle.DrawText(xtitle+0.3, ytext, &line[ltit]);
00348          ytext -= dy;
00349       }
00350    }
00351    Update();
00352    fCurObject = obj;
00353 }
00354 
00355 
00356 //______________________________________________________________________________
00357 void TInspectCanvas::GoBackward()
00358 {
00359    // static function , inspect previous object
00360 
00361    TInspectCanvas *inspect = (TInspectCanvas*)(gROOT->GetListOfCanvases())->FindObject("inspect");
00362    TObject *cur = inspect->GetCurObject();
00363    TObject *obj = inspect->GetObjects()->Before(cur);
00364    if (obj)       inspect->InspectObject(obj);
00365 }
00366 
00367 
00368 //______________________________________________________________________________
00369 void TInspectCanvas::GoForward()
00370 {
00371    // static function , inspect next object
00372 
00373    TInspectCanvas *inspect = (TInspectCanvas*)(gROOT->GetListOfCanvases())->FindObject("inspect");
00374    TObject *cur = inspect->GetCurObject();
00375    TObject *obj = inspect->GetObjects()->After(cur);
00376    if (obj)       inspect->InspectObject(obj);
00377 }
00378 
00379 
00380 //______________________________________________________________________________
00381 void TInspectCanvas::Inspector(TObject *obj)
00382 {
00383    // static function , interface to InspectObject.
00384    // Create the InspectCanvas if it does not exist yet.
00385 
00386    TVirtualPad *padsav = gPad;
00387    TInspectCanvas *inspect = (TInspectCanvas*)(gROOT->GetListOfCanvases())->FindObject("inspect");
00388    if (!inspect) inspect = new TInspectCanvas(700,600);
00389    else          inspect->cd();
00390 
00391    inspect->InspectObject(obj);
00392    inspect->GetObjects()->Add(obj);
00393    //obj->SetBit(kMustCleanup);
00394 
00395    if (padsav) padsav->cd();
00396 }
00397 
00398 
00399 //______________________________________________________________________________
00400 void TInspectCanvas::RecursiveRemove(TObject *obj)
00401 {
00402    // Recursively remove object from the list of objects.
00403 
00404    fObjects->Remove(obj);
00405    TPad::RecursiveRemove(obj);
00406 }

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