// @(#)root/tree:$Name:  $:$Id: TMethodBrowsable.cxx,v 1.5 2004/12/17 07:20:54 brun Exp $
// Author: Axel Naumann   14/10/2004

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TMethodBrowsable                                                     //
//                                                                      //
// A helper object to browse methods (see                               //
// TBranchElement::GetBrowsableMethods)                                 //
//////////////////////////////////////////////////////////////////////////

#include "TMethodBrowsable.h"
#include "TBranchElement.h"
#include "TMethod.h"
#include "TBrowser.h"
#include "TTree.h"
#include "TPad.h"
#include "TClass.h"
#include "TBaseClass.h"
#include "TDataMember.h"

ClassImp(TMethodBrowsable);

//______________________________________________________________________________
 TMethodBrowsable::TMethodBrowsable(TBranchElement* be, TMethod* m,
                                   TMethodBrowsable* parent /* =0 */):
      fBranchElement(be), fParent(parent), fMethod(m), 
      fReturnClass(0), fReturnLeafs(0), fReturnIsPointer(kFALSE) {
// standard constructor.
// Links a TBranchElement with a TMethod, allowing the TBrowser to
// Browser simple methods.
//
// The c'tor sets the name for a method "Class::Method(params) const"
// to "Method(params)", title to TMethod::GetPrototype
   TString name(m->GetName());
   name+="()";
   if (name.EndsWith(" const")) name.Remove(name.Length()-6);
   SetName(name);

   name=m->GetPrototype();
   if (m->GetCommentString() && strlen(m->GetCommentString()))
      name.Append(" // ").Append(m->GetCommentString());
   SetTitle(name);

   TString plainReturnType(m->GetReturnTypeName());
   if (plainReturnType.EndsWith("*")) {
      fReturnIsPointer=kTRUE;
      plainReturnType.Remove(plainReturnType.Length()-1);
      plainReturnType.Strip();
      if(plainReturnType.BeginsWith("const")) {
        plainReturnType.Remove(0,5);
        plainReturnType.Strip();
      }   
   }
   fReturnClass=gROOT->GetClass(plainReturnType);
}

//______________________________________________________________________________
 void TMethodBrowsable::Browse(TBrowser *b) {
// Calls TTree::Draw on the method if return type is not a class;
// otherwise expands returned object's "folder"

   if (!fReturnClass) {
      TString name;
      GetScope(name);
      fBranchElement->GetTree()->Draw(name, "", b ? b->GetDrawOption() : "");
      if (gPad) gPad->Update();
   } else {
      if (!fReturnLeafs)
         fReturnLeafs=GetMethodBrowsables(fBranchElement, fReturnClass, this);
      if (fReturnLeafs)
         fReturnLeafs->Browse(b);
   }
}

//______________________________________________________________________________
 TList* TMethodBrowsable::GetMethodBrowsables(TBranchElement* be, TClass* cl,
                                             TMethodBrowsable* parent /* =0 */) {
// Given a class, this methods returns a list of TMethodBrowsables
// for the class and its base classes.
// This list has to be deleted by the caller!

   if (!cl) return 0;

   TList allClasses;
   allClasses.Add(cl);
   
   for(TObjLink* lnk=allClasses.FirstLink();
       lnk; lnk=lnk->Next()){
      cl=(TClass*)lnk->GetObject();
      TList* bases=cl->GetListOfBases();
      TBaseClass* base;
      TIter iB(bases);
      while ((base=(TBaseClass*)iB())) {
         TClass* bc=base->GetClassPointer();
         if (bc) allClasses.Add(bc);
      }
   }

   TList allMethods;
   TIter iC(&allClasses);
   while ((cl=(TClass*)iC())) {
      TList* methods=cl->GetListOfMethods();
      if (!methods) continue;
      TMethod* method=0;
      TIter iM(methods);
      while ((method=(TMethod*)iM()))
         if (method && !allMethods.FindObject(method->GetName()))
             allMethods.Add(method);
   }

   TIter iM(&allMethods);
   TMethod* m=0;
   TList* browsableMethods=new TList();
   browsableMethods->SetOwner();
   while ((m=(TMethod*)iM()))
      if (TMethodBrowsable::IsMethodBrowsable(m))
         browsableMethods->Add(new TMethodBrowsable(be, m, parent));

   return browsableMethods;
}

//______________________________________________________________________________
 void TMethodBrowsable::GetScope(TString & scope) {
// Returns the full name for TTree::Draw to draw *this.
// Recursively appends, starting form the top TBranchElement,
// all method names with proper reference operators (->, .)
// depending on fReturnIsPointer.

   if (fParent)
      fParent->GetScope(scope);
   else {
      scope=fBranchElement->GetName();
      scope+=".";
      TBranch* mother=fBranchElement;
      while (mother != mother->GetMother() && (mother=mother->GetMother()))
         scope.Prepend(".").Prepend(mother->GetName());
   }
   scope+=GetName();
   if (fReturnClass) // otherwise we're a leaf, and we are the one drawn
      if (fReturnIsPointer)
         scope+="->";
      else scope+=".";
}

//______________________________________________________________________________
 Bool_t TMethodBrowsable::IsMethodBrowsable(TMethod* m) {
// A TMethod is browsable if it is const, public and not pure virtual,
// if does not have any parameter without default value, and if it has 
// a (non-void) return value.
// A method called *, Get*, or get* will not be browsable if there is a 
// persistent data member called f*, _*, or m*, as data member access is 
// faster than method access. Examples: if one of fX, _X, or mX is a 
// persistent data member, the methods GetX(), getX(), and X() will not 
// be browsable.

   if (m->GetNargs()-m->GetNargsOpt()==0
       && (m->Property() & kIsConstant 
           & ~kIsPrivate & ~kIsProtected & ~kIsPureVirtual )
       && m->GetReturnTypeName()
       && strcmp("void",m->GetReturnTypeName())
       && !strstr(m->GetName(),"DeclFile")
       && !strstr(m->GetName(),"ImplFile")
       && strcmp(m->GetName(),"IsA")
       && strcmp(m->GetName(),"Class")
       && strcmp(m->GetName(),"CanBypassStreamer")
       && strcmp(m->GetName(),"Class_Name")
       && strcmp(m->GetName(),"ClassName")
       && strcmp(m->GetName(),"Clone")
       && strcmp(m->GetName(),"DrawClone")
       && strcmp(m->GetName(),"GetName")
       && strcmp(m->GetName(),"GetDrawOption")
       && strcmp(m->GetName(),"GetIconName")
       && strcmp(m->GetName(),"GetOption")
       && strcmp(m->GetName(),"GetTitle")
       && strcmp(m->GetName(),"GetUniqueID")
       && strcmp(m->GetName(),"Hash")
       && strcmp(m->GetName(),"IsFolder")
       && strcmp(m->GetName(),"IsOnHeap")
       && strcmp(m->GetName(),"IsSortable")
       && strcmp(m->GetName(),"IsZombie")) {
         // look for matching data member
         TClass* cl=m->GetClass();
         if (!cl) return kTRUE;
         TList* members=cl->GetListOfDataMembers();
         if (!members) return kTRUE;
         const char* baseName=m->GetName();
         if (!strncmp(m->GetName(), "Get", 3) ||
             !strncmp(m->GetName(), "get", 3))
            baseName+=3;
         if (!baseName[0]) return kTRUE;

         TObject* mem=0;
         const char* arrMemberNames[3]={"f%s","_%s","m%s"};
         for (Int_t i=0; !mem && i<3; i++)
            mem=members->FindObject(Form(arrMemberNames[i],baseName));
         return (!mem ||! ((TDataMember*)mem)->IsPersistent());
   };
   return kFALSE;
}


ROOT page - Class index - Class Hierarchy - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.