Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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 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=nullptr;
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=nullptr;
165 TClass* type=nullptr;
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=nullptr;
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=nullptr;
204 if (!clonesname || !clonesname[0]) return nullptr;
205 type=TClass::GetClass(clonesname);
206 }
207 } else {
208 ::Warning("TVirtualBranchBrowsable::GetCollectionContainedType", "Neither branch nor parent given!");
209 return nullptr;
210 }
211
212 if (!type) return nullptr;
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 nullptr;
264 else contained=type;
265 return nullptr;
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.
348 fgGeneratorsSet=true;
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, nullptr, false, 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=nullptr;
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=nullptr;
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=nullptr;
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 const char* baseName=m->GetName();
534 if (m->GetNargs() - m->GetNargsOpt() == 0
535 && (property & kIsConstant)
537 && m->GetReturnTypeName()
538 && strcmp("void",m->GetReturnTypeName())
539 && !strstr(baseName,"DeclFile")
540 && !strstr(baseName,"ImplFile")
541 && !strstr(baseName,"operator")
542 && strcmp(baseName,"IsA")
543 && strcmp(baseName,"Class")
544 && strcmp(baseName,"CanBypassStreamer")
545 && strcmp(baseName,"Class_Name")
546 && strcmp(baseName,"ClassName")
547 && strcmp(baseName,"Clone")
548 && strcmp(baseName,"DrawClone")
549 && strcmp(baseName,"GetName")
550 && strcmp(baseName,"GetDrawOption")
551 && strcmp(baseName,"GetIconName")
552 && strcmp(baseName,"GetOption")
553 && strcmp(baseName,"GetTitle")
554 && strcmp(baseName,"GetUniqueID")
555 && strcmp(baseName,"Hash")
556 && strcmp(baseName,"IsFolder")
557 && strcmp(baseName,"IsOnHeap")
558 && strcmp(baseName,"IsSortable")
559 && strcmp(baseName,"IsZombie")) {
560
561 // look for matching data member
562 TClass* cl=m->GetClass();
563 if (!cl) return true;
564 TList* members=cl->GetListOfDataMembers();
565 if (!members) return true;
566 if (!strncmp(baseName, "Get", 3) ||
567 !strncmp(baseName, "get", 3))
568 baseName+=3;
569 if (!baseName[0]) return true;
570
571 TObject* mem=nullptr;
572 const char* arrMemberNames[3]={"f%s","_%s","m%s"};
573 for (Int_t i=0; !mem && i<3; i++)
574 mem=members->FindObject(TString::Format(arrMemberNames[i],baseName));
575 return (!mem ||! ((TDataMember*)mem)->IsPersistent());
576 };
577 return false;
578}
579
580////////////////////////////////////////////////////////////////////////////////
581/// Wrapper for the registration method. Needed against MSVC, which
582/// assigned different addr to the same method, depending on what
583/// translation unit you're in...
584
586{
588}
589
590////////////////////////////////////////////////////////////////////////////////
591/// Wrapper for the registration method. Needed against MSVC, which
592/// assigned different addr to the same method, depending on what
593/// translation unit you're in...
594
596{
598}
599
601
602////////////////////////////////////////////////////////////////////////////////
603/// \class TNonSplitBrowsable
604/// \ingroup tree
605///
606/// Allows a TBrowser to browse non-split branches as if they were split. The
607/// generator extracts the necessary information from the streamer info in
608/// memory (which does not have to be the same as the one on file, in case
609/// a library was loaded containing the dictionary for this type), i.e. it
610/// also works without loading the class's library.
611///
612/// Just as with TMethodBrowsables, if the generator finds a collection it
613/// only takes the contained objects into account, not the collections. If
614/// it identifies a collection, but cannot extract the contained type, or the
615/// contained type can be anything deriving from a TObject (like for TObjArray)
616/// or is not limited at all, no browser helper objects are created.
617
618////////////////////////////////////////////////////////////////////////////////
619/// Constructor. Creates a TNonSplitBrowsable from a TStreamerElement, containing branch
620/// and (if applicable) parent TVirtualBranchBrowsable.
621
623 const TVirtualBranchBrowsable* parent /* =0 */):
624 TVirtualBranchBrowsable(branch, element->GetClassPointer(),
625 element->IsaPointer(), parent)
626{
627 SetNameTitle(element->GetName(), element->GetTitle());
628}
629
630////////////////////////////////////////////////////////////////////////////////
631/// Given either a branch "branch" or a "parent" TVirtualBranchBrowsable, we fill
632/// "list" with objects of type TNonSplitBrowsable which represent the members
633/// of class "cl" (and its base classes' members).
634
636 const TVirtualBranchBrowsable* parent /* =0 */)
637{
638 // branch has to be unsplit, i.e. without sub-branches
639 if (parent==nullptr
640 && (branch==nullptr ||
641 (const_cast<TBranch*>(branch)->GetListOfBranches()
642 && const_cast<TBranch*>(branch)->GetListOfBranches()->GetEntries()!=0)
643 )
644 ) {
645 return 0;
646 }
647 // we only expand our own parents
648 //if (parent && parent->IsA()!=TNonSplitBrowsable::Class()) return 0;
649
650 TClass* clContained=nullptr;
651 GetCollectionContainedType(branch, parent, clContained);
652 TVirtualStreamerInfo* streamerInfo= clContained?clContained->GetStreamerInfo():nullptr;
653 if (!streamerInfo
654 || !streamerInfo->GetElements()
655 || !streamerInfo->GetElements()->GetSize()) return 0;
656
657 if (!branch && parent) branch=parent->GetBranch();
658
659 // we simply add all of our and the bases' members into one big list
660 TList myStreamerElementsToCheck;
661 myStreamerElementsToCheck.AddAll(streamerInfo->GetElements());
662
663 Int_t numAdded=0;
664 TStreamerElement* streamerElement=nullptr;
665 for (TObjLink *link = myStreamerElementsToCheck.FirstLink();
666 link;
667 link = link->Next() ) {
668 streamerElement = (TStreamerElement*)link->GetObject();
669 if (streamerElement->IsBase()) {
670 // this is a base class place holder
671 // continue with the base class's streamer info
672 TClass* base=streamerElement->GetClassPointer();
673 if (!base || !base->GetStreamerInfo()) continue;
674
675 // add all of the base class's streamer elements
676 // (which in turn can be a base, which will be
677 // unfolded in a later iteration) to the list
678 TObjArray* baseElements=base->GetStreamerInfo()->GetElements();
679 if (!baseElements) continue;
680 TIter iBaseSE(baseElements);
681 TStreamerElement* baseSE=nullptr;
682 while ((baseSE=(TStreamerElement*)iBaseSE()))
683 // we should probably check whether we're replacing something here...
684 myStreamerElementsToCheck.Add(baseSE);
685 } else if (!strcmp(streamerElement->GetName(),"This")
686 && !strcmp(clContained->GetName(), streamerElement->GetTypeName())) {
687 // this is a collection of the real elements.
688 // So get the class ptr for these elements...
689 TClass* clElements=streamerElement->GetClassPointer();
690 TVirtualCollectionProxy* collProxy=clElements?clElements->GetCollectionProxy():nullptr;
691 clElements=collProxy?collProxy->GetValueClass():nullptr;
692 if (!clElements) continue;
693
694 // now loop over the class's streamer elements
695 streamerInfo = clElements->GetStreamerInfo();
696 if (streamerInfo) {
697 TIter iElem(streamerInfo->GetElements());
698 TStreamerElement* elem=nullptr;
699 while ((elem=(TStreamerElement*)iElem())) {
700 TNonSplitBrowsable* nsb=new TNonSplitBrowsable(elem, branch, parent);
701 li.Add(nsb);
702 numAdded++;
703 }
704 } else {
705 ::Error("TNonSplitBrowsable::GetBrowsables",
706 "Missing the StreamerInfo for the class \"%s\" for the branch \"%s\" in the TTree \"%s\".",
707 clElements->GetName(), branch->GetName(), branch->GetTree()->GetName());
708 }
709 } else {
710 // we have a basic streamer element
711 TNonSplitBrowsable* nsb=new TNonSplitBrowsable(streamerElement, branch, parent);
712 li.Add(nsb);
713 numAdded++;
714 }
715 }
716 return numAdded;
717}
718
719////////////////////////////////////////////////////////////////////////////////
720/// Wrapper for the registration method. Needed against MSVC, which
721/// assigned different addr to the same method, depending on what
722/// translation unit you're in...
723
725{
727}
728
729////////////////////////////////////////////////////////////////////////////////
730/// Wrapper for the registration method. Needed against MSVC, which
731/// assigned different addr to the same method, depending on what
732/// translation unit you're in...
733
735{
737}
738
740
741////////////////////////////////////////////////////////////////////////////////
742/// \class TCollectionPropertyBrowsable
743/// \ingroup tree
744///
745/// A tiny browser helper object (and its generator) for adding a virtual
746/// (as in "not actually part of the class", not in C++ virtual) "@size()"
747/// method to a collection. For all collections that derive from
748/// TCollection, or have a TVirtualCollectionProxy associated with them,
749/// a leaf is created that allows access to the number of elements in the
750/// collection. For TClonesArrays and types with an associated
751/// TVirtualCollectionProxy, this forwards to TTreeFormula's
752/// "@branch.size()" functionality. For all other collections, a method call
753/// to the appropriate collection's member function is executed when drawing.
754///
755/// These objects are of course only created for elements containing a
756/// collection; the generator has no effect on any other elements.
757
758////////////////////////////////////////////////////////////////////////////////
759/// Browses a TCollectionPropertyBrowsable. The only difference to
760/// the generic TVirtualBranchBrowsable::Browse is our fDraw
761
763{
764 GetBranch()->GetTree()->Draw(GetDraw(), "", b ? b->GetDrawOption() : "");
765 if (gPad) gPad->Update();
766}
767
768////////////////////////////////////////////////////////////////////////////////
769/// If the element to browse (given by either parent of branch) contains
770/// a collection (TClonesArray or something for which a TVirtualCollectionProxy
771/// exists), we will add some special objects to the browser. For now there is
772/// just one object "@size", returning the size of the collection (as in
773/// std::list::size(), or TClonesArray::GetEntries()).
774/// The objects we create are simply used to forward strings (like "@size") to
775/// TTreeFormula via our Browse method. These strings are stored in fName.
776
778 const TVirtualBranchBrowsable* parent /* =0 */)
779{
780 TClass* clContained=nullptr;
781 TClass* clCollection=GetCollectionContainedType(branch, parent, clContained);
782 if (!clCollection || !clContained) return 0;
783
784 // Build the fDraw string. Start with our scope.
785 TString scope;
786 if (parent) {
787 parent->GetScope(scope);
788 branch=parent->GetBranch();
789 } else if (branch){
790 scope=branch->GetName();
791 scope+=".";
792 const TBranch* mother=branch;
793 while (mother != mother->GetMother() && (mother=mother->GetMother())) {
794 TString nameMother(mother->GetName());
795 if (!nameMother.EndsWith(".")) {
796 scope.Prepend(".");
797 scope.Prepend(nameMother);
798 } else {
799 if (mother != mother->GetMother()) {
800 // If the mother is the top level mother
801 // and its ends ends with a ., the name is already
802 // embedded!
803 scope.Prepend(nameMother);
804 }
805 }
806 }
807 } else {
808 ::Warning("TCollectionPropertyBrowsable::GetBrowsables", "Neither branch nor parent is set!");
809 return 0;
810 }
811
812 // remove trailing delimiters
813 if (scope.EndsWith(".")) scope.Remove(scope.Length()-1, 1);
814 else if (scope.EndsWith("->")) scope.Remove(scope.Length()-2, 2);
815
816 // now prepend "@" to the last element of the scope,
817 // to access the collection and not its containees
818 Ssiz_t lastDot=scope.Last('.');
819 Ssiz_t lastArrow=scope.Last('>'); // assuming there's no branch name containing ">"...
820 Ssiz_t lastPart=lastDot;
821 if (lastPart==kNPOS || (lastArrow!=kNPOS && lastPart<lastArrow))
822 lastPart=lastArrow;
823 if (lastPart==kNPOS) lastPart=0;
824 else lastPart++;
825
826 TString size_title("size of ");
827 size_title += clCollection->GetName();
828 if (clContained) {
829 size_title += " of ";
830 size_title += clContained->GetName();
831 }
832
833 if (clCollection->GetCollectionProxy() || clCollection==TClonesArray::Class()) {
834 // the collection is one for which TTree::Draw supports @coll.size()
835
837 if ( clCollection->GetCollectionProxy() &&
838 ( (clCollection->GetCollectionProxy()->GetValueClass()==nullptr)
839 ||(clCollection->GetCollectionProxy()->GetValueClass()->GetCollectionProxy()!=nullptr
840 && clCollection->GetCollectionProxy()->GetValueClass()->GetCollectionProxy()->GetValueClass()==nullptr)
841 )) {
842 // If the contained type is not a class, we need an explicit handle to get to the data.
843 cpb = new TCollectionPropertyBrowsable("values", "values in the container",
844 scope, branch, parent);
845 li.Add(cpb);
846 }
847 scope.Insert(lastPart, "@");
848 cpb = new TCollectionPropertyBrowsable("@size", size_title,
849 scope+".size()", branch, parent);
850 li.Add(cpb);
851 return 1;
852 } // if a collection proxy or TClonesArray
853 else if (clCollection->InheritsFrom(TCollection::Class())) {
854 // generic TCollection - we'll build size() ourselves, by mapping
855 // it to the proper member function of the collection
856 if (clCollection->InheritsFrom(TObjArray::Class()))
857 scope+="@.GetEntries()";
858 else scope+="@.GetSize()";
860 new TCollectionPropertyBrowsable("@size", size_title, scope, branch, parent);
861 li.Add(cpb);
862 return 1;
863 }
864 return 0;
865}
866
867////////////////////////////////////////////////////////////////////////////////
868/// Wrapper for the registration method. Needed against MSVC, which
869/// assigned different addr to the same method, depending on what
870/// translation unit you're in...
871
873{
875}
876
877////////////////////////////////////////////////////////////////////////////////
878/// Wrapper for the registration method. Needed against MSVC, which
879/// assigned different addr to the same method, depending on what
880/// translation unit you're in...
881
883{
885}
886
888
889////////////////////////////////////////////////////////////////////////////////
890/// \class TCollectionMethodBrowsable
891/// \ingroup tree
892///
893/// TCollectionMethodBrowsable extends TCollectionPropertyBrowsable by showing
894/// all methods of the collection itself. If none are available - e.g. for STL
895/// classes like std::list, a TVirtualBranchBrowsable object is created instead.
896/// The methods' names will have a "@" prepended, to distinguish them from the
897/// contained elements' methods.
898///
899/// This browser helper object is not part of the default list of registered
900/// generators (see TVirtualBranchBrowsable::RegisterDefaultGenerators()).
901/// If you want to use it, you should call
902/// TCollectionMethodBrowsable::Register();
903/// As it extends the functionality of TVirtualBranchBrowsable, one might want
904/// to unregister the generator of the "@size()" method by calling
905/// TCollectionPropertyBrowsable::Unregister();
906
907////////////////////////////////////////////////////////////////////////////////
908/// Constructor, see TMethodBrowsable's constructor.
909/// Prepends "@" to the name to make this method work on the container.
910
912 const TVirtualBranchBrowsable* parent /*=0*/):
913TMethodBrowsable(branch, m, parent)
914{
915 SetName(TString("@")+GetName());
916}
917
918////////////////////////////////////////////////////////////////////////////////
919/// This methods fills list with TMethodBrowsables
920/// for the branch's or parent's collection class and its base classes,
921/// and returns the number of added elements. If called from a TBranch::Browse
922/// overload, "branch" should be set to the calling TBranch, otherwise
923/// "parent" should be set to the TVirtualBranchBrowsable being browsed.
924
926 const TVirtualBranchBrowsable* parent /*=0*/)
927{
928 TClass* clContained=nullptr;
929 // we don't care about the contained class, but only about the collections,
930 TClass* clContainer=GetCollectionContainedType(branch, parent, clContained);
931 if (!clContainer || !clContained) return 0;
932
933 TList listMethods;
934 GetBrowsableMethodsForClass(clContainer, listMethods);
935 TMethod* method=nullptr;
936 TIter iMethods(&listMethods);
937 while ((method=(TMethod*)iMethods()))
938 li.Add(new TCollectionMethodBrowsable(branch, method, parent));
939
940 // if we have no methods, and if the class has a collection proxy, just add
941 // the corresponding TCollectionPropertyBrowsable instead.
942 // But only do that if TCollectionPropertyBrowsable is not generated anyway
943 // - we don't need two of them.
944 if (!listMethods.GetSize() && clContainer->GetCollectionProxy()) {
945 std::list<MethodCreateListOfBrowsables_t>& listGenerators=GetRegisteredGenerators();
946 std::list<MethodCreateListOfBrowsables_t>::iterator iIsRegistered
947 = std::find(listGenerators.begin(), listGenerators.end(), &TCollectionPropertyBrowsable::GetBrowsables);
948 if (iIsRegistered==listGenerators.end()) {
950 return 1;
951 }
952 }
953 return listMethods.GetSize();
954}
955
956////////////////////////////////////////////////////////////////////////////////
957/// Wrapper for the registration method. Needed against MSVC, which
958/// assigned different addr to the same method, depending on what
959/// translation unit you're in...
960
962{
964}
965
966////////////////////////////////////////////////////////////////////////////////
967/// Wrapper for the registration method. Needed against MSVC, which
968/// assigned different addr to the same method, depending on what
969/// translation unit you're in...
970
972{
974}
Cppyy::TCppType_t fClass
#define b(i)
Definition RSha256.hxx:100
constexpr Ssiz_t kNPOS
Definition RtypesCore.h:124
#define ClassImp(name)
Definition Rtypes.h:377
@ kIsConstant
Definition TDictionary.h:88
@ kIsPrivate
Definition TDictionary.h:77
@ kIsProtected
Definition TDictionary.h:76
@ kIsPureVirtual
Definition TDictionary.h:73
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t property
char name[80]
Definition TGX11.cxx:110
#define gPad
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.
A Branch for the case of an object.
static TClass * Class()
Int_t GetID() const
const char * GetClassName() const override
Return the name of the user class whose content is stored in this branch, if any.
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
virtual const char * GetClonesName() const
A Branch for the case of an object.
const char * GetClassName() const override
Return the name of the user class whose content is stored in this branch, if any.
static TClass * Class()
A TTree is a list of TBranches.
Definition TBranch.h:93
TTree * GetTree() const
Definition TBranch.h:252
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:1706
TClass * IsA() const override
Definition TBranch.h:295
Long64_t GetReadEntry() const
Definition TBranch.h:237
TObjArray * GetListOfLeaves()
Definition TBranch.h:247
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition TBranch.cxx:2127
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:81
TList * GetListOfMethods(Bool_t load=kTRUE)
Return list containing the TMethods of a class.
Definition TClass.cxx:3812
TList * GetListOfDataMembers(Bool_t load=kTRUE)
Return list containing the TDataMembers of a class.
Definition TClass.cxx:3770
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition TClass.cxx:3636
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition TClass.cxx:5912
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:4599
Bool_t InheritsFrom(const char *cl) const override
Return kTRUE if this class inherits from a class with name "classname".
Definition TClass.cxx:4874
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition TClass.cxx:2897
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:2968
An array of clone (identical) objects.
static TClass * Class()
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.
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.
const char * GetDraw() const
return the string passed to TTree::Draw
void Browse(TBrowser *b) override
Browses a TCollectionPropertyBrowsable.
static TClass * Class()
virtual void AddAll(const TCollection *col)
Add all objects from collection col to this collection.
virtual void SetOwner(Bool_t enable=kTRUE)
Set whether this collection is the owner (enable==true) of its content.
void Browse(TBrowser *b) override
Browse this collection (called by TBrowser).
virtual Int_t GetSize() const
Return the capacity of the collection, i.e.
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:38
TObject * FindObject(const char *name) const override
Find an object in this list using its name.
Definition TList.cxx:576
void Add(TObject *obj) override
Definition TList.h:83
virtual TObjLink * FirstLink() const
Definition TList.h:104
This helper object allows the browsing of methods of objects stored in branches.
static bool 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 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,...
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 void SetTitle(const char *title="")
Set the title of the TNamed.
Definition TNamed.cxx:164
const char * GetName() const override
Returns name of object.
Definition TNamed.h:47
const char * GetTitle() const override
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:31
Int_t GetEntriesFast() const
Definition TObjArray.h:58
TObject * UncheckedAt(Int_t i) const
Definition TObjArray.h:84
TObject * First() const override
Return the object in the first slot.
static TClass * Class()
Mother of all ROOT objects.
Definition TObject.h:41
virtual const char * GetName() const
Returns name of object.
Definition TObject.cxx:439
virtual void Warning(const char *method, const char *msgfmt,...) const
Issue warning message.
Definition TObject.cxx:973
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition TObject.cxx:987
virtual TClass * IsA() const
Definition TObject.h:243
static TClass * Class()
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.
TStreamerElement * GetElement(Int_t id) const override
Int_t GetNelement() const
Basic string class.
Definition TString.h:139
Ssiz_t Length() const
Definition TString.h:417
TString & Insert(Ssiz_t pos, const char *s)
Definition TString.h:661
Bool_t EndsWith(const char *pat, ECaseCompare cmp=kExact) const
Return true if string ends with the specified string.
Definition TString.cxx:2244
TSubString Strip(EStripType s=kTrailing, char c=' ') const
Return a substring of self stripped at beginning and/or end.
Definition TString.cxx:1163
Ssiz_t First(char c) const
Find first occurrence of a character c.
Definition TString.cxx:538
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition TString.cxx:931
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition TString.h:623
TString & Prepend(const char *cs)
Definition TString.h:673
TString & Remove(Ssiz_t pos)
Definition TString.h:685
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:2378
A TTree represents a columnar dataset.
Definition TTree.h:79
void Draw(Option_t *opt) override
Default Draw method for all objects.
Definition TTree.h:431
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
const TBranch * GetBranch() const
return the parent branch (might be many levels up)
static TClass * GetCollectionContainedType(const TBranch *b, const TVirtualBranchBrowsable *parent, TClass *&contained)
Check whether the branch (or the parent) contains a collection.
void SetTypeIsPointer(bool set=true)
sets whether the type of this browsable object is a pointer
TList * GetLeaves() const
Return list of leaves. If not set up yet we'll create them.
~TVirtualBranchBrowsable() override
Destructor. Delete our leaves.
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
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.
TVirtualBranchBrowsable(const TBranch *b, TClass *type, bool typeIsPointer, const TVirtualBranchBrowsable *parent=nullptr)
Constructor setting all members according to parameters.
void Browse(TBrowser *b) override
Calls TTree::Draw on the method if return type is not a class; otherwise expands returned object's "f...
static bool fgGeneratorsSet
have we set the generators yet? empty is not good enough - user might have removed them
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.
bool fTypeIsPointer
return type is pointer to class
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
return the type of this browsable object
Defines a common interface to inspect/change the contents of an object that represents a collection.
virtual EDataType GetType() const =0
If the value type is a fundamental data type, return its type (see enumeration EDataType).
virtual TClass * GetValueClass() const =0
If the value type is a user-defined class, return a pointer to the TClass representing the value type...
Abstract Interface class describing Streamer information for one class.
virtual TObjArray * GetElements() const =0
TMarker m
Definition textangle.C:8