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