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