Logo ROOT   6.16/01
Reference Guide
TBranchBrowsable.cxx
Go to the documentation of this file.
1// @(#)root/tree:$Id: c5d87ada87b506444a9d0bc027d622273440b891 $
2// Author: Axel Naumann 14/10/2004
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "TBranchBrowsable.h"
13#include "TBranchElement.h"
14#include "TBranchObject.h"
15#include "TMethod.h"
16#include "TBrowser.h"
17#include "TTree.h"
18#include "TLeafObject.h"
19#include "TClonesArray.h"
20#include "TVirtualPad.h"
21#include "TClass.h"
22#include "TBaseClass.h"
23#include "TDataMember.h"
24#include "TStreamerInfo.h"
25#include "TStreamerElement.h"
27#include "TRef.h"
28#include <algorithm>
29
31
32/** \class TVirtualBranchBrowsable
33\ingroup tree
34
35TVirtualBranchBrowsable is a base class (not really abstract, but useless
36by itself) for helper objects that extend TBranch's browsing support.
37Each registered derived class's generator method is called, which fills
38all created helper objects into a list which can then be browsed.
39For details of what these browser helper objects can do, see e.g.
40TMethodBrowsable, which allows methods to show up in the TBrowser.
41
42Only registered helper objects are created. By default, only
43TMethodBrowsable, TNonSplitBrowsable, and TCollectionPropertyBrowsable
44are registered (see RegisterDefaultGenerators). You can prevent any of
45their objects to show up in the browser by unregistering the generator:
46~~~ {.cpp}
47 TMethodBrowsable::Unregister()
48~~~
49will stop creating browsable method helper objects from that call on.
50Note that these helper objects are cached (in TBranch::fBrowsables);
51already created (and thus cached) browsables will still appear in the
52browser even after unregistering the corresponding generator.
53
54You can implement your own browsable objects and thier generator; see
55e.g. the simple TCollectionPropertyBrowsable. Note that you will have
56to register your generator just like any other, and that you should
57implement the following methods for your own class, mainly for
58consistency reasons:
59~~~ {.cpp}
60 static void Register() {
61 TVirtualBranchBrowsable::RegisterGenerator(GetBrowsables); }
62 static void Unregister() {
63 TVirtualBranchBrowsable::UnregisterGenerator(GetBrowsables); }
64~~~
65where GetBrowsables is a static member function of your class, that
66creates the browsable helper objects, and has the signature
67~~~ {.cpp}
68 static Int_t GetBrowsables(TList& list, const TBranch* branch,
69 const TVirtualBranchBrowsable* parent=0);
70~~~
71
72It has to return the number of browsable helper objects for parent
73(or, if NULL, for branch) which are added to the list.
74*/
75
76std::list<TVirtualBranchBrowsable::MethodCreateListOfBrowsables_t>
79
80////////////////////////////////////////////////////////////////////////////////
81/// Constructor setting all members according to parameters.
82
84 Bool_t typeIsPointer,
85 const TVirtualBranchBrowsable* parent /*=0*/):
86fBranch(branch), fParent(parent), fLeaves(0), fClass(type), fTypeIsPointer(typeIsPointer)
87{
89 if (!branch)
90 Warning("TVirtualBranchBrowsable", "branch is NULL!");
91}
92
93////////////////////////////////////////////////////////////////////////////////
94/// Destructor. Delete our leaves.
95
97{
98 delete fLeaves;
99}
100
101////////////////////////////////////////////////////////////////////////////////
102/// Calls TTree::Draw on the method if return type is not a class;
103/// otherwise expands returned object's "folder"
104
106{
107 if (!fClass
109 && fClass->GetCollectionProxy()->GetType() > 0)) {
111 GetScope(name);
112
113 // If this is meant to be run on the collection
114 // we need to "move" the "@" from branch.@member
115 // to branch@.member
116 name.ReplaceAll(".@","@.");
117 name.ReplaceAll("->@","@->");
118
119 TTree* tree=0;
120 if (!fBranch) {
121 Error("Browse", "branch not set - might access wrong tree!");
122 return;
123 } else tree=fBranch->GetTree();
124 tree->Draw(name, "", b ? b->GetDrawOption() : "");
125 if (gPad) gPad->Update();
126 } else
127 if (GetLeaves()) GetLeaves()->Browse(b);
128}
129
130////////////////////////////////////////////////////////////////////////////////
131/// Askes all registered generators to fill their browsables into
132/// the list. The browsables are generated for a given parent,
133/// or (if 0), for a given branch. The branch is passed down to
134/// leaves of TVirtualBranchBrowsable, too, as we need to access
135/// the branch's TTree to be able to traw.
136
138 const TVirtualBranchBrowsable* parent /* =0 */)
139{
141 std::list<MethodCreateListOfBrowsables_t>::iterator iGenerator;
142 Int_t numCreated=0;
143 for (iGenerator=fgGenerators.begin(); iGenerator!=fgGenerators.end(); ++iGenerator)
144 numCreated+=(*(*iGenerator))(li, branch, parent);
145 return numCreated;
146}
147
148////////////////////////////////////////////////////////////////////////////////
149/// Check whether the branch (or the parent) contains a collection.
150/// If it does, set "contained" to the contained type (if we can
151/// retrieve it) and return the TClass for the collection. Set
152/// "contained" to the branch's (or parent's) contained object's
153/// class for non-collections, returning 0.
154///
155/// Only one of "branch" or "parent" can ge given (depending on whether
156/// we are creating browsable objects for a branch or for another
157/// browsable object)
158
160 const TVirtualBranchBrowsable* parent,
161 TClass* &contained)
162{
163 contained=0;
164 TClass* type=0;
165 if (parent)
166 type=parent->GetClassType();
167 else if (branch) {
168 if (branch->IsA()==TBranchElement::Class()) {
169 // could be a split TClonesArray
170 TBranchElement* be=(TBranchElement*) branch;
171
172 // this is the contained type - if !=0
173 const char* clonesname=be->GetClonesName();
174 if (clonesname && strlen(clonesname))
175 contained=TClass::GetClass(clonesname);
176
177 // check if we're in a sub-branch of this class
178 // we can only find out asking the streamer given our ID
179 TStreamerElement *element=0;
180 if (be->GetID()>=0 && be->GetInfo()
181 && (be->GetID() < be->GetInfo()->GetNelement())
182 && be->GetInfo()->IsCompiled()
183 && (element=be->GetInfo()->GetElement(be->GetID()))) {
184 // if contained is set (i.e. GetClonesName was successful),
185 // this element containes the container, otherwise it's the
186 // contained
187 if (contained)
188 // we have all we need
189 return element->GetClassPointer();
190 else
191 type=element->GetClassPointer();
192 } else if (clonesname && strlen(clonesname)) {
193 // we have a clones name, and the TCA is not split:
194 contained=TClass::GetClass(clonesname);
195 return TClass::GetClass(be->GetClassName());
196 } else
198 } else if (branch->IsA()==TBranchObject::Class()) {
199 // could be an unsplit TClonesArray
200 TBranchObject* bo=(TBranchObject*)branch;
201 const char* clonesname=bo->GetClassName();
202 contained=0;
203 if (!clonesname || !clonesname[0]) return 0;
204 type=TClass::GetClass(clonesname);
205 }
206 } else {
207 ::Warning("TVirtualBranchBrowsable::GetCollectionContainedType", "Neither branch nor parent given!");
208 return 0;
209 }
210
211 if (!type) return 0;
212
213 TBranch* branchNonCost=const_cast<TBranch*>(branch);
214 if (type->InheritsFrom(TClonesArray::Class())
215 && branch->IsA()==TBranchObject::Class()
216 && branchNonCost->GetListOfLeaves()
217 && branchNonCost->GetListOfLeaves()->GetEntriesFast()==1) {
218 // load first entry of the branch. Yes, this is bad, and might have
219 // unexpected side effects for the user, esp as already looking at
220 // (and not just drawing) a branch triggeres it.
221 // To prove just how ugly it is, we'll also have to const_cast the
222 // branch...
223 if (branch->GetReadEntry()==-1) branchNonCost->GetEntry(0);
224 // now get element
225 TLeafObject* lo = (TLeafObject*)branchNonCost->GetListOfLeaves()->First();
226 if (lo) {
227 TObject* objContainer = lo->GetObject();
228 if (objContainer && objContainer->IsA()==TClonesArray::Class()) {
229 contained = ((TClonesArray*)objContainer)->GetClass();
230 }
231 }
232 return type;
233 } else if (type->InheritsFrom(TClonesArray::Class())
234 && branch->IsA()==TBranchElement::Class()
235 && branchNonCost->GetListOfLeaves()
236 && branchNonCost->GetListOfLeaves()->GetEntriesFast()==1) {
237 // load first entry of the branch. Yes, this is bad, and might have
238 // unexpected side effects for the user, esp as already looking at
239 // (and not just drawing) a branch triggeres it.
240 // To prove just how ugly it is, we'll also have to const_cast the
241 // branch...
242
243 //if (branch->GetReadEntry()==-1) branchNonCost->GetEntry(0);
244 // now get element
245 //TLeafObject* lo=(TLeafElement*)branchNonCost->GetListOfLeaves()->First();
246 //TObject* objContainer=(TObject*)((TBranchElement*)branch)->GetValuePointer();
247
248 //if (objContainer && objContainer->IsA()==TClonesArray::Class())
249 // contained=((TClonesArray*)objContainer)->GetClass();
250
251 // Currently we can peer into the nested TClonesArray, we need
252 // to update TBranchElement::GetValuePointer.
253 return type;
254 } else if (type->InheritsFrom(TCollection::Class())) {
255 // some other container, and we don't know what the contained type is
256 return type;
257 } else if (type->GetCollectionProxy()) {
258 contained=type->GetCollectionProxy()->GetValueClass();
259 return type;
260 } else if (type->InheritsFrom(TRef::Class()))
261 // we don't do TRefs, so return contained and container as 0
262 return 0;
263 else contained=type;
264 return 0;
265}
266
267////////////////////////////////////////////////////////////////////////////////
268/// Return list of leaves. If not set up yet we'll create them.
269
271{
272 if (!fLeaves) {
273 TList* leaves=new TList();
274 leaves->SetOwner();
275 FillListOfBrowsables(*leaves, GetBranch(), this);
276 const_cast<TVirtualBranchBrowsable*>(this)->fLeaves=leaves;
277 }
278 return fLeaves;
279}
280
281////////////////////////////////////////////////////////////////////////////////
282/// returns the list of registered generator methods
283
284std::list<TVirtualBranchBrowsable::MethodCreateListOfBrowsables_t>& TVirtualBranchBrowsable::GetRegisteredGenerators()
285{
286 return fgGenerators;
287}
288
289////////////////////////////////////////////////////////////////////////////////
290/// Returns the full name for TTree::Draw to draw *this.
291/// Recursively appends, starting at the top TBranch,
292/// all method / object names with proper reference operators (->, .)
293/// depending on fTypeIsPointer.
294
296{
297 if (fParent)
298 fParent->GetScope(scope);
299 else {
300 scope=fBranch->GetName();
301 Ssiz_t pos = scope.First('[');
302 if (pos != kNPOS) {
303 scope.Remove(pos);
304 }
305 if (!scope.EndsWith(".")) scope+=".";
306 const TBranch* mother=fBranch;
307 while (mother != mother->GetMother() && (mother=mother->GetMother())) {
308 TString nameMother(mother->GetName());
309 if (!nameMother.EndsWith(".")) {
310 scope.Prepend(".");
311 scope.Prepend(nameMother);
312 } else {
313 if (mother != mother->GetMother()) {
314 // If the mother is the top level mother
315 // and its ends ends with a ., the name is already
316 // embedded!
317 scope.Prepend(nameMother);
318 }
319 }
320 }
321 }
322 if (GetName() && GetName()[0]=='.')
323 scope+=(GetName()+1);
324 else
325 scope+=GetName();
326 if (fClass && !scope.EndsWith(".")) { // otherwise we're a leaf, and no delimiter is appended
327 if (fTypeIsPointer)
328 scope+="->";
329 else scope+=".";
330 }
331}
332
333////////////////////////////////////////////////////////////////////////////////
334/// Adds the default generators. The user can remove any of them as follows:
335///
336/// TMethodBrowsable::Unregister();
337///
338/// which will cause the browser not to show any methods.
339
341{
342 if (fgGeneratorsSet) return;
343 // can't call RegisterGenerator - would be recusive infite loop
348}
349
350////////////////////////////////////////////////////////////////////////////////
351/// Adds a generator to be called when browsing branches.
352/// Called by the Register method, which should be implemented
353/// for all derived classes (see e.g. TMethodBrowsable::Register())
354
355void TVirtualBranchBrowsable::RegisterGenerator(MethodCreateListOfBrowsables_t generator)
356{
358 // make sure we're not adding another copy
359 fgGenerators.remove(generator);
360 fgGenerators.push_back(generator);
361}
362
363////////////////////////////////////////////////////////////////////////////////
364/// Removes a generator from the list of generators to be called when
365/// browsing branches. The user can remove any of the generators as follows:
366///
367/// TMethodBrowsable::Unregister();
368///
369/// which will cause the browser not to show any methods.
370
371void TVirtualBranchBrowsable::UnregisterGenerator(MethodCreateListOfBrowsables_t generator)
372{
374 fgGenerators.remove(generator);
375}
376
378
379////////////////////////////////////////////////////////////////////////////////
380/// \class TMethodBrowsable
381/// \ingroup tree
382///
383/// This helper object allows the browsing of methods of objects stored in
384/// branches. They will be depicted by a leaf (or a branch, in case the method
385/// returns an object) with a red exclamation mark. Only a subset of all
386/// methods will be shown in the browser (see IsMethodBrowsable for the
387/// criteria a method has to satisfy).
388///
389/// Obviously, methods are only available if the library is loaded which
390/// contains the dictionary for the class to be browsed!
391///
392/// If a branch contains a collection, TMethodBrowsable tries to find out
393/// what the contained element is (it will only create methods for the
394/// contained elements, but never for the collection). If it fails to extract
395/// the type of the contained elements, or if there is no guarantee that the
396/// type has any other common denominator than TObject (e.g. in the case of
397/// a TObjArray, which can hold any object deriving from TObject) no methods
398/// will be added.
399
400////////////////////////////////////////////////////////////////////////////////
401/// Constructor.
402/// Links a TBranchElement to a TMethod, allowing the TBrowser to
403/// browse simple methods.
404///
405/// The c'tor sets the name for a method "Class::Method(params) const"
406/// to "Method(params)", title to TMethod::GetPrototype
407
409 const TVirtualBranchBrowsable* parent /* =0 */):
410 TVirtualBranchBrowsable(branch, 0, kFALSE, parent), fMethod(m)
411{
412 TString name(m->GetName());
413 name+="()";
414 if (name.EndsWith(" const")) name.Remove(name.Length()-6);
415 SetName(name);
416
417 name=m->GetPrototype();
418 if (m->GetCommentString() && strlen(m->GetCommentString()))
419 name.Append(" // ").Append(m->GetCommentString());
420 SetTitle(name);
421
422 TString plainReturnType(m->GetReturnTypeName());
423 if (plainReturnType.EndsWith("*")) {
425 plainReturnType.Remove(plainReturnType.Length()-1);
426 plainReturnType.Strip();
427 if(plainReturnType.BeginsWith("const")) {
428 plainReturnType.Remove(0,5);
429 plainReturnType.Strip();
430 }
431 }
432 SetType(TClass::GetClass(plainReturnType));
433}
434
435////////////////////////////////////////////////////////////////////////////////
436/// Given a class, this methods fills list with TMethodBrowsables
437/// for the class and its base classes, and returns the number of
438/// added elements. If called from a TBranch::Browse overload, "branch"
439/// should be set to the calling TBranch, otherwise "parent" should
440/// be set to the TVirtualBranchBrowsable being browsed, and branch
441/// should be the branch of the parent.
442
444{
445 if (!cl) return;
446 TList allClasses;
447 allClasses.Add(cl);
448
449 if (cl->IsLoaded()) {
450 for(TObjLink* lnk=allClasses.FirstLink();
451 lnk; lnk=lnk->Next()) {
452 cl=(TClass*)lnk->GetObject();
453 TList* bases=cl->GetListOfBases();
454 TBaseClass* base;
455 TIter iB(bases);
456 while ((base=(TBaseClass*)iB())) {
457 TClass* bc=base->GetClassPointer();
458 if (bc) allClasses.Add(bc);
459 }
460 }
461 } else {
463 for(int el = 0; el < info->GetElements()->GetEntries(); ++el) {
464 TStreamerElement *element = (TStreamerElement *)info->GetElements()->UncheckedAt(el);
465 if (element->IsBase()) {
466 TClass *bc = element->GetClassPointer();
467 if (bc) allClasses.Add(bc);
468 }
469 }
470 }
471
472 TList allMethods;
473 TIter iC(&allClasses);
474 while ((cl=(TClass*)iC())) {
475 TList* methods=cl->GetListOfMethods();
476 if (!methods) continue;
477 TMethod* method=0;
478 TIter iM(methods);
479 while ((method=(TMethod*)iM()))
480 if (method && !allMethods.FindObject(method->GetName()))
481 allMethods.Add(method);
482 }
483
484 TIter iM(&allMethods);
485 TMethod* m=0;
486 while ((m=(TMethod*)iM())) {
488 li.Add(m);
489 }
490 }
491}
492
493////////////////////////////////////////////////////////////////////////////////
494/// This methods fills list with TMethodBrowsables
495/// for the branch's or parent's class and its base classes, and returns
496/// the number of added elements. If called from a TBranch::Browse
497/// overload, "branch" should be set to the calling TBranch, otherwise
498/// "parent" should be set to the TVirtualBranchBrowsable being browsed.
499
501 const TVirtualBranchBrowsable* parent /*=0*/)
502{
503 TClass* cl;
504 // we don't care about collections, so only use the TClass argument,
505 // and not the return value
506 GetCollectionContainedType(branch, parent, cl);
507 if (!cl) return 0;
508
509 TList listMethods;
510 GetBrowsableMethodsForClass(cl, listMethods);
511 TMethod* method=0;
512 TIter iMethods(&listMethods);
513 while ((method=(TMethod*)iMethods())) {
514 li.Add(new TMethodBrowsable(branch, method, parent));
515 }
516 return listMethods.GetSize();
517}
518
519////////////////////////////////////////////////////////////////////////////////
520/// A TMethod is browsable if it is const, public and not pure virtual,
521/// if does not have any parameter without default value, and if it has
522/// a (non-void) return value.
523/// A method called *, Get*, or get* will not be browsable if there is a
524/// persistent data member called f*, _*, or m*, as data member access is
525/// faster than method access. Examples: if one of fX, _X, or mX is a
526/// persistent data member, the methods GetX(), getX(), and X() will not
527/// be browsable.
528
530{
531 long property = m->Property();
532 if (m->GetNargs() - m->GetNargsOpt() == 0
533 && (property & kIsConstant)
534 && !(property & (kIsPrivate | kIsProtected | kIsPureVirtual) )
535 && m->GetReturnTypeName()
536 && strcmp("void",m->GetReturnTypeName())
537 && !strstr(m->GetName(),"DeclFile")
538 && !strstr(m->GetName(),"ImplFile")
539 && strcmp(m->GetName(),"IsA")
540 && strcmp(m->GetName(),"Class")
541 && strcmp(m->GetName(),"CanBypassStreamer")
542 && strcmp(m->GetName(),"Class_Name")
543 && strcmp(m->GetName(),"ClassName")
544 && strcmp(m->GetName(),"Clone")
545 && strcmp(m->GetName(),"DrawClone")
546 && strcmp(m->GetName(),"GetName")
547 && strcmp(m->GetName(),"GetDrawOption")
548 && strcmp(m->GetName(),"GetIconName")
549 && strcmp(m->GetName(),"GetOption")
550 && strcmp(m->GetName(),"GetTitle")
551 && strcmp(m->GetName(),"GetUniqueID")
552 && strcmp(m->GetName(),"Hash")
553 && strcmp(m->GetName(),"IsFolder")
554 && strcmp(m->GetName(),"IsOnHeap")
555 && strcmp(m->GetName(),"IsSortable")
556 && strcmp(m->GetName(),"IsZombie")) {
557
558 // look for matching data member
559 TClass* cl=m->GetClass();
560 if (!cl) return kTRUE;
561 TList* members=cl->GetListOfDataMembers();
562 if (!members) return kTRUE;
563 const char* baseName=m->GetName();
564 if (!strncmp(m->GetName(), "Get", 3) ||
565 !strncmp(m->GetName(), "get", 3))
566 baseName+=3;
567 if (!baseName[0]) return kTRUE;
568
569 TObject* mem=0;
570 const char* arrMemberNames[3]={"f%s","_%s","m%s"};
571 for (Int_t i=0; !mem && i<3; i++)
572 mem=members->FindObject(TString::Format(arrMemberNames[i],baseName));
573 return (!mem ||! ((TDataMember*)mem)->IsPersistent());
574 };
575 return kFALSE;
576}
577
578////////////////////////////////////////////////////////////////////////////////
579/// Wrapper for the registration method. Needed against MSVC, which
580/// assigned different addr to the same method, depending on what
581/// translation unit you're in...
582
584{
586}
587
588////////////////////////////////////////////////////////////////////////////////
589/// Wrapper for the registration method. Needed against MSVC, which
590/// assigned different addr to the same method, depending on what
591/// translation unit you're in...
592
594{
596}
597
599
600////////////////////////////////////////////////////////////////////////////////
601/// \class TNonSplitBrowsable
602/// \ingroup tree
603///
604/// Allows a TBrowser to browse non-split branches as if they were split. The
605/// generator extracts the necessary information from the streamer info in
606/// memory (which does not have to be the same as the one on file, in case
607/// a library was loaded containing the dictionary for this type), i.e. it
608/// also works without loading the class's library.
609///
610/// Just as with TMethodBrowsables, if the generator finds a collection it
611/// only takes the contained objects into account, not the collections. If
612/// it identifies a collection, but cannot extract the contained type, or the
613/// contained type can be anything deriving from a TObject (like for TObjArray)
614/// or is not limited at all, no browser helper objects are created.
615
616////////////////////////////////////////////////////////////////////////////////
617/// Constructor. Creates a TNonSplitBrowsable from a TStreamerElement, containing branch
618/// and (if applicable) parent TVirtualBranchBrowsable.
619
621 const TVirtualBranchBrowsable* parent /* =0 */):
622 TVirtualBranchBrowsable(branch, element->GetClassPointer(),
623 element->IsaPointer(), parent)
624{
625 SetNameTitle(element->GetName(), element->GetTitle());
626}
627
628////////////////////////////////////////////////////////////////////////////////
629/// Given either a branch "branch" or a "parent" TVirtualBranchBrowsable, we fill
630/// "list" with objects of type TNonSplitBrowsable which represent the members
631/// of class "cl" (and its base classes' members).
632
634 const TVirtualBranchBrowsable* parent /* =0 */)
635{
636 // branch has to be unsplit, i.e. without sub-branches
637 if (parent==0
638 && (branch==0 ||
639 (const_cast<TBranch*>(branch)->GetListOfBranches()
640 && const_cast<TBranch*>(branch)->GetListOfBranches()->GetEntries()!=0)
641 )
642 ) {
643 return 0;
644 }
645 // we only expand our own parents
646 //if (parent && parent->IsA()!=TNonSplitBrowsable::Class()) return 0;
647
648 TClass* clContained=0;
649 GetCollectionContainedType(branch, parent, clContained);
650 TVirtualStreamerInfo* streamerInfo= clContained?clContained->GetStreamerInfo():0;
651 if (!streamerInfo
652 || !streamerInfo->GetElements()
653 || !streamerInfo->GetElements()->GetSize()) return 0;
654
655 if (!branch && parent) branch=parent->GetBranch();
656
657 // we simply add all of our and the bases' members into one big list
658 TList myStreamerElementsToCheck;
659 myStreamerElementsToCheck.AddAll(streamerInfo->GetElements());
660
661 Int_t numAdded=0;
662 TStreamerElement* streamerElement=0;
663 for (TObjLink *link = myStreamerElementsToCheck.FirstLink();
664 link;
665 link = link->Next() ) {
666 streamerElement = (TStreamerElement*)link->GetObject();
667 if (streamerElement->IsBase()) {
668 // this is a base class place holder
669 // continue with the base class's streamer info
670 TClass* base=streamerElement->GetClassPointer();
671 if (!base || !base->GetStreamerInfo()) continue;
672
673 // add all of the base class's streamer elements
674 // (which in turn can be a base, which will be
675 // unfolded in a later iteration) to the list
676 TObjArray* baseElements=base->GetStreamerInfo()->GetElements();
677 if (!baseElements) continue;
678 TIter iBaseSE(baseElements);
679 TStreamerElement* baseSE=0;
680 while ((baseSE=(TStreamerElement*)iBaseSE()))
681 // we should probably check whether we're replacing something here...
682 myStreamerElementsToCheck.Add(baseSE);
683 } else if (!strcmp(streamerElement->GetName(),"This")
684 && !strcmp(clContained->GetName(), streamerElement->GetTypeName())) {
685 // this is a collection of the real elements.
686 // So get the class ptr for these elements...
687 TClass* clElements=streamerElement->GetClassPointer();
688 TVirtualCollectionProxy* collProxy=clElements?clElements->GetCollectionProxy():0;
689 clElements=collProxy?collProxy->GetValueClass():0;
690 if (!clElements) continue;
691
692 // now loop over the class's streamer elements
693 streamerInfo = clElements->GetStreamerInfo();
694 if (streamerInfo) {
695 TIter iElem(streamerInfo->GetElements());
696 TStreamerElement* elem=0;
697 while ((elem=(TStreamerElement*)iElem())) {
698 TNonSplitBrowsable* nsb=new TNonSplitBrowsable(elem, branch, parent);
699 li.Add(nsb);
700 numAdded++;
701 }
702 } else {
703 ::Error("TNonSplitBrowsable::GetBrowsables",
704 "Missing the StreamerInfo for the class \"%s\" for the branch \"%s\" in the TTree \"%s\".",
705 clElements->GetName(), branch->GetName(), branch->GetTree()->GetName());
706 }
707 } else {
708 // we have a basic streamer element
709 TNonSplitBrowsable* nsb=new TNonSplitBrowsable(streamerElement, branch, parent);
710 li.Add(nsb);
711 numAdded++;
712 }
713 }
714 return numAdded;
715}
716
717////////////////////////////////////////////////////////////////////////////////
718/// Wrapper for the registration method. Needed against MSVC, which
719/// assigned different addr to the same method, depending on what
720/// translation unit you're in...
721
723{
725}
726
727////////////////////////////////////////////////////////////////////////////////
728/// Wrapper for the registration method. Needed against MSVC, which
729/// assigned different addr to the same method, depending on what
730/// translation unit you're in...
731
733{
735}
736
738
739////////////////////////////////////////////////////////////////////////////////
740/// \class TCollectionPropertyBrowsable
741/// \ingroup tree
742///
743/// A tiny browser helper object (and its generator) for adding a virtual
744/// (as in "not actually part of the class", not in C++ virtual) "@size()"
745/// method to a collection. For all collections that derive from
746/// TCollection, or have a TVirtualCollectionProxy associated with them,
747/// a leaf is created that allows access to the number of elements in the
748/// collection. For TClonesArrays and types with an associated
749/// TVirtualCollectionProxy, this forwards to TTreeFormula's
750/// "@branch.size()" functionality. For all other collections, a method call
751/// to the appropriate collection's member function is executed when drawing.
752///
753/// These objects are of course only created for elements containing a
754/// collection; the generator has no effect on any other elements.
755
756////////////////////////////////////////////////////////////////////////////////
757/// Browses a TCollectionPropertyBrowsable. The only difference to
758/// the generic TVirtualBranchBrowsable::Browse is our fDraw
759
761{
762 GetBranch()->GetTree()->Draw(GetDraw(), "", b ? b->GetDrawOption() : "");
763 if (gPad) gPad->Update();
764}
765
766////////////////////////////////////////////////////////////////////////////////
767/// If the element to browse (given by either parent of branch) contains
768/// a collection (TClonesArray or something for which a TVirtualCollectionProxy
769/// exists), we will add some special objects to the browser. For now there is
770/// just one object "@size", returning the size of the collection (as in
771/// std::list::size(), or TClonesArray::GetEntries()).
772/// The objects we create are simply used to forward strings (like "@size") to
773/// TTreeFormula via our Browse method. These strings are stored in fName.
774
776 const TVirtualBranchBrowsable* parent /* =0 */)
777{
778 TClass* clContained=0;
779 TClass* clCollection=GetCollectionContainedType(branch, parent, clContained);
780 if (!clCollection || !clContained) return 0;
781
782 // Build the fDraw string. Start with our scope.
783 TString scope;
784 if (parent) {
785 parent->GetScope(scope);
786 branch=parent->GetBranch();
787 } else if (branch){
788 scope=branch->GetName();
789 scope+=".";
790 const TBranch* mother=branch;
791 while (mother != mother->GetMother() && (mother=mother->GetMother())) {
792 TString nameMother(mother->GetName());
793 if (!nameMother.EndsWith(".")) {
794 scope.Prepend(".");
795 scope.Prepend(nameMother);
796 } else {
797 if (mother != mother->GetMother()) {
798 // If the mother is the top level mother
799 // and its ends ends with a ., the name is already
800 // embedded!
801 scope.Prepend(nameMother);
802 }
803 }
804 }
805 } else {
806 ::Warning("TCollectionPropertyBrowsable::GetBrowsables", "Neither branch nor parent is set!");
807 return 0;
808 }
809
810 // remove trailing delimiters
811 if (scope.EndsWith(".")) scope.Remove(scope.Length()-1, 1);
812 else if (scope.EndsWith("->")) scope.Remove(scope.Length()-2, 2);
813
814 // now prepend "@" to the last element of the scope,
815 // to access the collection and not its containees
816 Ssiz_t lastDot=scope.Last('.');
817 Ssiz_t lastArrow=scope.Last('>'); // assuming there's no branch name containing ">"...
818 Ssiz_t lastPart=lastDot;
819 if (lastPart==kNPOS || (lastArrow!=kNPOS && lastPart<lastArrow))
820 lastPart=lastArrow;
821 if (lastPart==kNPOS) lastPart=0;
822 else lastPart++;
823
824 TString size_title("size of ");
825 size_title += clCollection->GetName();
826 if (clContained) {
827 size_title += " of ";
828 size_title += clContained->GetName();
829 }
830
831 if (clCollection->GetCollectionProxy() || clCollection==TClonesArray::Class()) {
832 // the collection is one for which TTree::Draw supports @coll.size()
833
835 if ( clCollection->GetCollectionProxy() &&
836 ( (clCollection->GetCollectionProxy()->GetValueClass()==0)
837 ||(clCollection->GetCollectionProxy()->GetValueClass()->GetCollectionProxy()!=0
839 )) {
840 // If the contained type is not a class, we need an explitcit handle to get to the data.
841 cpb = new TCollectionPropertyBrowsable("values", "values in the container",
842 scope, branch, parent);
843 li.Add(cpb);
844 }
845 scope.Insert(lastPart, "@");
846 cpb = new TCollectionPropertyBrowsable("@size", size_title,
847 scope+".size()", branch, parent);
848 li.Add(cpb);
849 return 1;
850 } // if a collection proxy or TClonesArray
851 else if (clCollection->InheritsFrom(TCollection::Class())) {
852 // generic TCollection - we'll build size() ourselves, by mapping
853 // it to the proper member function of the collection
854 if (clCollection->InheritsFrom(TObjArray::Class()))
855 scope+="@.GetEntries()";
856 else scope+="@.GetSize()";
858 new TCollectionPropertyBrowsable("@size", size_title, scope, branch, parent);
859 li.Add(cpb);
860 return 1;
861 }
862 return 0;
863}
864
865////////////////////////////////////////////////////////////////////////////////
866/// Wrapper for the registration method. Needed against MSVC, which
867/// assigned different addr to the same method, depending on what
868/// translation unit you're in...
869
871{
873}
874
875////////////////////////////////////////////////////////////////////////////////
876/// Wrapper for the registration method. Needed against MSVC, which
877/// assigned different addr to the same method, depending on what
878/// translation unit you're in...
879
881{
883}
884
886
887////////////////////////////////////////////////////////////////////////////////
888/// \class TCollectionMethodBrowsable
889/// \ingroup tree
890///
891/// TCollectionMethodBrowsable extends TCollectionPropertyBrowsable by showing
892/// all methods of the collection itself. If none are available - e.g. for STL
893/// classes like std::list, a TVirtualBranchBrowsable object is reated instead.
894/// The methods' names will have a "@" prepended, to distinguish them from the
895/// contained elements' methods.
896///
897/// This browser helper object is not part of the default list of registered
898/// generators (see TVirtualBranchBrowsable::RegisterDefaultGenerators()).
899/// If you want to use it, you should call
900/// TCollectionMethodBrowsable::Register();
901/// As it extends the functionality of TVirtualBranchBrowsable, one might want
902/// to unregister the generator of the "@size()" method by calling
903/// TCollectionPropertyBrowsable::Unregister();
904
905////////////////////////////////////////////////////////////////////////////////
906/// Contructor, see TMethodBrowsable's constructor.
907/// Prepends "@" to the name to make this method work on the container.
908
910 const TVirtualBranchBrowsable* parent /*=0*/):
911TMethodBrowsable(branch, m, parent)
912{
913 SetName(TString("@")+GetName());
914}
915
916////////////////////////////////////////////////////////////////////////////////
917/// This methods fills list with TMethodBrowsables
918/// for the branch's or parent's collection class and its base classes,
919/// and returns the number of added elements. If called from a TBranch::Browse
920/// overload, "branch" should be set to the calling TBranch, otherwise
921/// "parent" should be set to the TVirtualBranchBrowsable being browsed.
922
924 const TVirtualBranchBrowsable* parent /*=0*/)
925{
926 TClass* clContained=0;
927 // we don't care about the contained class, but only about the collections,
928 TClass* clContainer=GetCollectionContainedType(branch, parent, clContained);
929 if (!clContainer || !clContained) return 0;
930
931 TList listMethods;
932 GetBrowsableMethodsForClass(clContainer, listMethods);
933 TMethod* method=0;
934 TIter iMethods(&listMethods);
935 while ((method=(TMethod*)iMethods()))
936 li.Add(new TCollectionMethodBrowsable(branch, method, parent));
937
938 // if we have no methods, and if the class has a collection proxy, just add
939 // the corresponding TCollectionPropertyBrowsable instead.
940 // But only do that if TCollectionPropertyBrowsable is not generatated anyway
941 // - we don't need two of them.
942 if (!listMethods.GetSize() && clContainer->GetCollectionProxy()) {
943 std::list<MethodCreateListOfBrowsables_t>& listGenerators=GetRegisteredGenerators();
944 std::list<MethodCreateListOfBrowsables_t>::iterator iIsRegistered
945 = std::find(listGenerators.begin(), listGenerators.end(), &TCollectionPropertyBrowsable::GetBrowsables);
946 if (iIsRegistered==listGenerators.end()) {
948 return 1;
949 }
950 }
951 return listMethods.GetSize();
952}
953
954////////////////////////////////////////////////////////////////////////////////
955/// Wrapper for the registration method. Needed against MSVC, which
956/// assigned different addr to the same method, depending on what
957/// translation unit you're in...
958
960{
962}
963
964////////////////////////////////////////////////////////////////////////////////
965/// Wrapper for the registration method. Needed against MSVC, which
966/// assigned different addr to the same method, depending on what
967/// translation unit you're in...
968
970{
972}
void Class()
Definition: Class.C:29
#define b(i)
Definition: RSha256.hxx:100
const Ssiz_t kNPOS
Definition: RtypesCore.h:111
int Int_t
Definition: RtypesCore.h:41
int Ssiz_t
Definition: RtypesCore.h:63
const Bool_t kFALSE
Definition: RtypesCore.h:88
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kTRUE
Definition: RtypesCore.h:87
#define ClassImp(name)
Definition: Rtypes.h:363
@ kIsConstant
Definition: TDictionary.h:86
@ kIsPrivate
Definition: TDictionary.h:76
@ kIsProtected
Definition: TDictionary.h:75
@ kIsPureVirtual
Definition: TDictionary.h:73
int type
Definition: TGX11.cxx:120
#define gPad
Definition: TVirtualPad.h:286
Each class (see TClass) has a linked list of its base class(es).
Definition: TBaseClass.h:33
TClass * GetClassPointer(Bool_t load=kTRUE)
Get pointer to the base class TClass.
Definition: TBaseClass.cxx:63
A Branch for the case of an object.
Int_t GetID() const
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
virtual const char * GetClonesName() const
A Branch for the case of an object.
Definition: TBranchObject.h:26
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
Definition: TBranchObject.h:54
A TTree is a list of TBranches.
Definition: TBranch.h:64
TTree * GetTree() const
Definition: TBranch.h:209
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all leaves of entry and return total number of bytes read.
Definition: TBranch.cxx:1317
Long64_t GetReadEntry() const
Definition: TBranch.h:194
TObjArray * GetListOfLeaves()
Definition: TBranch.h:204
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1725
Using a TBrowser one can browse all ROOT objects.
Definition: TBrowser.h:37
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:75
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition: TClass.cxx:4452
TList * GetListOfMethods(Bool_t load=kTRUE)
Return list containing the TMethods of a class.
Definition: TClass.cxx:3664
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition: TClass.cxx:3615
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition: TClass.cxx:3505
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition: TClass.cxx:5674
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2814
Bool_t InheritsFrom(const char *cl) const
Return kTRUE if this class inherits from a class with name "classname".
Definition: TClass.cxx:4720
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2885
An array of clone (identical) objects.
Definition: TClonesArray.h:32
TCollectionMethodBrowsable extends TCollectionPropertyBrowsable by showing all methods of the collect...
static void Register()
Wrapper for the registration method.
static void Unregister()
Wrapper for the registration method.
TCollectionMethodBrowsable(const TBranch *branch, TMethod *m, const TVirtualBranchBrowsable *parent=0)
Contructor, see TMethodBrowsable's constructor.
static Int_t GetBrowsables(TList &list, const TBranch *branch, const TVirtualBranchBrowsable *parent=0)
This methods fills list with TMethodBrowsables for the branch's or parent's collection class and its ...
A tiny browser helper object (and its generator) for adding a virtual (as in "not actually part of th...
static void Register()
Wrapper for the registration method.
static Int_t GetBrowsables(TList &list, const TBranch *branch, const TVirtualBranchBrowsable *parent=0)
If the element to browse (given by either parent of branch) contains a collection (TClonesArray or so...
void Browse(TBrowser *b)
Browses a TCollectionPropertyBrowsable.
static void Unregister()
Wrapper for the registration method.
TCollectionPropertyBrowsable(const char *name, const char *title, const char *draw, const TBranch *branch, const TVirtualBranchBrowsable *parent=0)
const char * GetDraw() const
virtual void AddAll(const TCollection *col)
Add all objects from collection col to this collection.
void Browse(TBrowser *b)
Browse this collection (called by TBrowser).
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
Definition: TCollection.h:182
All ROOT classes may have RTTI (run time type identification) support added.
Definition: TDataMember.h:31
A TLeaf for a general object derived from TObject.
Definition: TLeafObject.h:31
TObject * GetObject() const
Definition: TLeafObject.h:61
A doubly linked list.
Definition: TList.h:44
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * FindObject(const char *name) const
Delete a TObjLink object.
Definition: TList.cxx:574
virtual TObjLink * FirstLink() const
Definition: TList.h:108
This helper object allows the browsing of methods of objects stored in branches.
TMethodBrowsable(const TBranch *branch, TMethod *m, const TVirtualBranchBrowsable *parent=0)
Constructor.
static void GetBrowsableMethodsForClass(TClass *cl, TList &list)
Given a class, this methods fills list with TMethodBrowsables for the class and its base classes,...
static Bool_t IsMethodBrowsable(const TMethod *m)
A TMethod is browsable if it is const, public and not pure virtual, if does not have any parameter wi...
static void Unregister()
Wrapper for the registration method.
static void Register()
Wrapper for the registration method.
static Int_t GetBrowsables(TList &list, const TBranch *branch, const TVirtualBranchBrowsable *parent=0)
This methods fills list with TMethodBrowsables for the branch's or parent's class and its base classe...
Each ROOT class (see TClass) has a linked list of methods.
Definition: TMethod.h:38
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual void SetNameTitle(const char *name, const char *title)
Set all the TNamed parameters (name and title).
Definition: TNamed.cxx:154
Allows a TBrowser to browse non-split branches as if they were split.
static Int_t GetBrowsables(TList &list, const TBranch *branch, const TVirtualBranchBrowsable *parent=0)
Given either a branch "branch" or a "parent" TVirtualBranchBrowsable, we fill "list" with objects of ...
static void Unregister()
Wrapper for the registration method.
TNonSplitBrowsable(const TStreamerElement *element, const TBranch *branch, const TVirtualBranchBrowsable *parent=0)
Constructor.
static void Register()
Wrapper for the registration method.
An array of TObjects.
Definition: TObjArray.h:37
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
TObject * First() const
Return the object in the first slot.
Definition: TObjArray.cxx:495
Mother of all ROOT objects.
Definition: TObject.h:37
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition: TObject.cxx:866
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:880
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
const char * GetTypeName() const
virtual Bool_t IsBase() const
Return kTRUE if the element represent a base class.
Int_t GetNelement() const
TStreamerElement * GetElement(Int_t id) const
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
TString & Insert(Ssiz_t pos, const char *s)
Definition: TString.h:644
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition: TString.cxx:2152
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition: TString.cxx:1081
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition: TString.cxx:487
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:876
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:610
TString & Prepend(const char *cs)
Definition: TString.h:656
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition: TString.cxx:2286
A TTree object has a header with a name and a title.
Definition: TTree.h:71
virtual void Draw(Option_t *opt)
Default Draw method for all objects.
Definition: TTree.h:371
TVirtualBranchBrowsable is a base class (not really abstract, but useless by itself) for helper objec...
void SetType(TClass *type)
const TBranch * fBranch
pointer to the branch element representing the top object
const TBranch * GetBranch() const
static TClass * GetCollectionContainedType(const TBranch *b, const TVirtualBranchBrowsable *parent, TClass *&contained)
Check whether the branch (or the parent) contains a collection.
TVirtualBranchBrowsable(const TBranch *b, TClass *type, Bool_t typeIsPointer, const TVirtualBranchBrowsable *parent=0)
Constructor setting all members according to parameters.
~TVirtualBranchBrowsable()
Destructor. Delete our leaves.
TList * GetLeaves() const
Return list of leaves. If not set up yet we'll create them.
static void RegisterGenerator(MethodCreateListOfBrowsables_t generator)
Adds a generator to be called when browsing branches.
void GetScope(TString &scope) const
Returns the full name for TTree::Draw to draw *this.
static std::list< MethodCreateListOfBrowsables_t > fgGenerators
list of MethodCreateListOfBrowsables_t called by CreateListOfBrowsables
void SetTypeIsPointer(Bool_t set=kTRUE)
TList * fLeaves
pointer to leaves
void Browse(TBrowser *b)
Calls TTree::Draw on the method if return type is not a class; otherwise expands returned object's "f...
Bool_t fTypeIsPointer
return type is pointer to class
static std::list< MethodCreateListOfBrowsables_t > & GetRegisteredGenerators()
returns the list of registered generator methods
static void UnregisterGenerator(MethodCreateListOfBrowsables_t generator)
Removes a generator from the list of generators to be called when browsing branches.
static void RegisterDefaultGenerators()
Adds the default generators.
static Bool_t fgGeneratorsSet
have we set the generators yet? empty is not good enough - user might have removed them
static Int_t FillListOfBrowsables(TList &list, const TBranch *branch, const TVirtualBranchBrowsable *parent=0)
Askes all registered generators to fill their browsables into the list.
const TVirtualBranchBrowsable * fParent
parent method if this method is member of a returned class
TClass * fClass
pointer to TClass representing our type (i.e. return type for methods), 0 if basic type
TClass * GetClassType() const
virtual EDataType GetType() const =0
virtual TClass * GetValueClass() const =0
Abstract Interface class describing Streamer information for one class.
virtual TObjArray * GetElements() const =0
Definition: tree.py:1
auto * m
Definition: textangle.C:8