Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RProvider.cxx
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. *
3 * All rights reserved. *
4 * *
5 * For the licensing terms see $ROOTSYS/LICENSE. *
6 * For the list of contributors see $ROOTSYS/README/CREDITS. *
7 *************************************************************************/
8
10
11#include <ROOT/RLogger.hxx>
12
13#include "TBaseClass.h"
14#include "TList.h"
15#include "TClass.h"
16#include "TSystem.h"
17
18using namespace ROOT::Experimental::Browsable;
19using namespace std::string_literals;
20
22
23//////////////////////////////////////////////////////////////////////////////////
24// Provide map of browsing for different classes
25
27{
28 static RProvider::BrowseMap_t sMap;
29 return sMap;
30}
31
32//////////////////////////////////////////////////////////////////////////////////
33// Provide map of files opening
34
36{
37 static RProvider::FileMap_t sMap;
38 return sMap;
39}
40
41//////////////////////////////////////////////////////////////////////////////////
42// Returns map of registered drawing functions for v6 canvas
43
45{
46 static RProvider::Draw6Map_t sMap;
47 return sMap;
48}
49
50//////////////////////////////////////////////////////////////////////////////////
51// Returns map of registered drawing functions for v7 canvas
52
54{
55 static RProvider::Draw7Map_t sMap;
56 return sMap;
57}
58
59//////////////////////////////////////////////////////////////////////////////////
60// Returns map of registered icons base on class pointer
61
63{
64 static RProvider::ClassMap_t sMap;
65 return sMap;
66}
67
68//////////////////////////////////////////////////////////////////////////////////
69// Returns map of registered icons base on class name
70
71//////////////////////////////////////////////////////////////////////////////////
72// Destructor
73/// Automatically unregister provider from all maps
74
76{
77 // here to remove all correspondent entries
83}
84
85//////////////////////////////////////////////////////////////////////////////////
86// Register file open function for specified extension
87
88void RProvider::RegisterFile(const std::string &extension, FileFunc_t func)
89{
90 auto &fmap = GetFileMap();
91
92 if ((extension != "*") && (fmap.find(extension) != fmap.end()))
93 R__LOG_ERROR(BrowsableLog()) << "Provider for file extension " << extension << " already exists";
94
95 fmap.emplace(extension, StructFile{this,func});
96}
97
98//////////////////////////////////////////////////////////////////////////////////
99// Register browse function for specified class
100
102{
103 auto &bmap = GetBrowseMap();
104
105 if (cl && (bmap.find(cl) != bmap.end()))
106 R__LOG_ERROR(BrowsableLog()) << "Browse provider for class " << cl->GetName() << " already exists";
107
108 bmap.emplace(cl, StructBrowse{this,func});
109}
110
111
112//////////////////////////////////////////////////////////////////////////////////
113// Register drawing function for v6 canvas
114
116{
117 auto &bmap = GetDraw6Map();
118
119 if (cl && (bmap.find(cl) != bmap.end()))
120 R__LOG_ERROR(BrowsableLog()) << "Draw v6 handler for class " << cl->GetName() << " already exists";
121
122 bmap.emplace(cl, StructDraw6{this, func});
123}
124
125//////////////////////////////////////////////////////////////////////////////////
126// Register drawing function for v7 canvas
127
129{
130 auto &bmap = GetDraw7Map();
131
132 if (cl && (bmap.find(cl) != bmap.end()))
133 R__LOG_ERROR(BrowsableLog()) << "Draw v7 handler for class " << cl->GetName() << " already exists";
134
135 bmap.emplace(cl, StructDraw7{this, func});
136}
137
138//////////////////////////////////////////////////////////////////////////////////
139// Register function for browsing RNTuple
140
142{
143 gNTupleFunc = func;
144}
145
146
147//////////////////////////////////////////////////////////////////////////////////
148// Register class with supported libs (if any)
149
150void RProvider::RegisterClass(const std::string &clname, const std::string &iconname,
151 const std::string &browselib, const std::string &draw6lib, const std::string &draw7lib)
152{
153 auto &bmap = GetClassMap();
154
155 if (!clname.empty() && (bmap.find(clname) != bmap.end()))
156 R__LOG_ERROR(BrowsableLog()) << "Entry for class " << clname << " already exists";
157
158 std::string blib = browselib;
159 bool can_have_childs = !browselib.empty();
160 if ((blib == "dflt") || (blib == "TObject")) blib = ""; // just use as indicator that browsing is possible
161
162 bmap.emplace(clname, StructClass{this, can_have_childs, iconname, blib, draw6lib, draw7lib});
163}
164
165//////////////////////////////////////////////////////////////////////////////////
166// Returns entry for the requested class
168{
169 if (!cl.empty()) {
170 auto &bmap = GetClassMap();
171 auto iter = bmap.find(cl.cl ? cl.cl->GetName() : cl.name.c_str());
172 if (iter != bmap.end())
173 return iter->second;
174
175 if (!cl.name.empty()) {
176 for (auto &elem : bmap)
177 if (cl.name.compare(0, elem.first.length(), elem.first) == 0)
178 return elem.second;
179 } else if (cl.cl) {
180 auto bases = const_cast<TClass *>(cl.cl)->GetListOfBases();
181 const TClass *basecl = bases && (bases->GetSize() > 0) ? dynamic_cast<TBaseClass *>(bases->First())->GetClassPointer() : nullptr;
182 if (basecl) return RProvider::GetClassEntry(basecl);
183 }
184 }
185
186 static StructClass dummy;
187 return dummy;
188}
189
190//////////////////////////////////////////////////////////////////////////////////
191// Returns true if file extension is supported
192
194{
195 if (extension.empty())
196 return false;
197
198 auto &fmap = GetFileMap();
199
200 return fmap.find(extension) != fmap.end();
201}
202
203//////////////////////////////////////////////////////////////////////////////////
204// Try to open file using provided extension.
205
206std::shared_ptr<RElement> RProvider::OpenFile(const std::string &extension, const std::string &fullname)
207{
208 auto &fmap = GetFileMap();
209
210 auto iter = fmap.find(extension);
211
212 if (iter != fmap.end())
213 return iter->second.func(fullname);
214
215 return nullptr;
216}
217
218//////////////////////////////////////////////////////////////////////////////////
219// Template function to scan class entries, including parent object classes
220
221template<class Map_t, class Func_t>
222bool ScanProviderMap(Map_t &fmap, const RProvider::ClassArg &cl, bool test_all = false, std::function<bool(Func_t &)> check_func = nullptr)
223{
224 if (cl.empty())
225 return false;
226
227 if (cl.GetClass()) {
228 TClass *testcl = const_cast<TClass *>(cl.GetClass());
229 while (testcl) {
230 auto iter = fmap.find(testcl);
231 if (iter != fmap.end())
232 if (!check_func || check_func(iter->second.func))
233 return true;
234
235 auto bases = testcl->GetListOfBases();
236
237 testcl = bases && (bases->GetSize() > 0) ? dynamic_cast<TBaseClass *>(bases->First())->GetClassPointer() : nullptr;
238 }
239 } else {
240 for (auto &entry : fmap) {
241 if (!entry.first) continue;
242 std::string name = entry.first->GetName();
243 if (!check_func) {
244 // when check_func not specified, just try to guess if class can match
245 if ((cl.GetName() == name) || (cl.GetName().compare(0, name.length(), name) == 0))
246 return true;
247 } else if (cl.GetName() == name) {
248 if (check_func(entry.second.func))
249 return true;
250 }
251 }
252 }
253
254 if (test_all && check_func) {
255 for (auto &entry : fmap)
256 if (!entry.first && check_func(entry.second.func))
257 return true;
258 }
259
260 return false;
261}
262
263
264/////////////////////////////////////////////////////////////////////////
265/// Create browsable element for the object
266/// Created element may take ownership over the object
267
268std::shared_ptr<RElement> RProvider::Browse(std::unique_ptr<RHolder> &object)
269{
270 std::shared_ptr<RElement> res;
271
272 if (!object) return res;
273
274 auto browse_func = [&res, &object] (BrowseFunc_t &func) -> bool {
275 res = func(object);
276 return (res || !object) ? true : false;
277 };
278
279 // check only class entries
280 if (ScanProviderMap<BrowseMap_t,BrowseFunc_t>(GetBrowseMap(), object->GetClass(), false, browse_func))
281 return res;
282
283 auto &entry = GetClassEntry(object->GetClass());
284 if (!entry.dummy() && !entry.browselib.empty())
285 gSystem->Load(entry.browselib.c_str());
286
287 // let call also generic browse functions (multicast)
288 ScanProviderMap<BrowseMap_t,BrowseFunc_t>(GetBrowseMap(), object->GetClass(), true, browse_func);
289
290 return res;
291}
292
293/////////////////////////////////////////////////////////////////////////////////
294/// Start browsing of RNTuple
295
296std::shared_ptr<RElement> RProvider::BrowseNTuple(const std::string &tuplename, const std::string &filename)
297{
298 if (!gNTupleFunc) {
299 auto &entry = GetClassEntry("ROOT::Experimental::RNTuple");
300
301 if (entry.browselib.empty())
302 return nullptr;
303
304 gSystem->Load(entry.browselib.c_str());
305 }
306
307 if (!gNTupleFunc)
308 return nullptr;
309
310 return gNTupleFunc(tuplename, filename);
311}
312
313/////////////////////////////////////////////////////////////////////////////////
314/// Invoke drawing of object on TCanvas sub-pad
315/// All existing providers are checked, first checked are class matches (including direct parents)
316
317bool RProvider::Draw6(TVirtualPad *subpad, std::unique_ptr<RHolder> &object, const std::string &opt)
318{
319 if (!object || !object->GetClass())
320 return false;
321
322 auto draw_func = [subpad, &object, &opt](Draw6Func_t &func) -> bool {
323 return func(subpad, object, opt);
324 };
325
326 if (ScanProviderMap<Draw6Map_t,Draw6Func_t>(GetDraw6Map(), object->GetClass(), false, draw_func))
327 return true;
328
329 auto &entry = GetClassEntry(object->GetClass());
330 if (!entry.dummy() && !entry.draw6lib.empty())
331 gSystem->Load(entry.draw6lib.c_str());
332
333 return ScanProviderMap<Draw6Map_t,Draw6Func_t>(GetDraw6Map(), object->GetClass(), true, draw_func);
334}
335
336/////////////////////////////////////////////////////////////////////////////////
337/// Invoke drawing of object on RCanvas sub-pad
338/// All existing providers are checked, first checked are class matches (including direct parents)
339
340bool RProvider::Draw7(std::shared_ptr<ROOT::Experimental::RPadBase> &subpad, std::unique_ptr<RHolder> &object, const std::string &opt)
341{
342 if (!object || !object->GetClass())
343 return false;
344
345 auto draw_func = [&subpad, &object, &opt](Draw7Func_t &func) -> bool {
346 return func(subpad, object, opt);
347 };
348
349 if (ScanProviderMap<Draw7Map_t,Draw7Func_t>(GetDraw7Map(), object->GetClass(), false, draw_func))
350 return true;
351
352 auto &entry = GetClassEntry(object->GetClass());
353 if (!entry.dummy() && !entry.draw7lib.empty())
354 gSystem->Load(entry.draw7lib.c_str());
355
356 return ScanProviderMap<Draw7Map_t,Draw7Func_t>(GetDraw7Map(), object->GetClass(), true, draw_func);
357}
358
359/////////////////////////////////////////////////////////////////////
360/// Return icon name for the given class - either class name or TClass *
361
362std::string RProvider::GetClassIcon(const ClassArg &arg, bool is_folder)
363{
364 auto &entry = GetClassEntry(arg);
365 if (!entry.iconname.empty())
366 return entry.iconname;
367
368 return is_folder ? "sap-icon://folder-blank"s : "sap-icon://electronic-medical-record"s;
369}
370
371
372/////////////////////////////////////////////////////////////////////
373/// Return true if provided class can have childs
374
376{
377 return GetClassEntry(arg).can_have_childs;
378}
379
380/////////////////////////////////////////////////////////////////////
381/// Return true if provided class can be drawn on the TCanvas
382
384{
385 if (ScanProviderMap<Draw6Map_t,Draw6Func_t>(GetDraw6Map(), arg))
386 return true;
387
388 if (!GetClassEntry(arg).draw6lib.empty())
389 return true;
390
391 return false;
392}
393
394/////////////////////////////////////////////////////////////////////
395/// Return true if provided class can be drawn on the RCanvas
396
398{
399 if (ScanProviderMap<Draw7Map_t,Draw7Func_t>(GetDraw7Map(), arg))
400 return true;
401
402 if (!GetClassEntry(arg).draw7lib.empty())
403 return true;
404
405 return false;
406}
407
408
409// ==============================================================================================
410
412
413public:
415 {
416 // TODO: let read from rootrc or any other files
417 RegisterClass("ROOT::Experimental::RH1D", "sap-icon://bar-chart", "", "", "libROOTHistDrawProvider");
418 RegisterClass("ROOT::Experimental::RH2D", "sap-icon://pixelate", "", "", "libROOTHistDrawProvider");
419 RegisterClass("ROOT::Experimental::RH3D", "sap-icon://product", "", "", "libROOTHistDrawProvider");
420 RegisterClass("ROOT::Experimental::RCanvas", "sap-icon://business-objects-experience", "", "", "libROOTHistDrawProvider");
421 RegisterClass("ROOT::Experimental::RNTuple", "sap-icon://table-chart", "libROOTNTupleBrowseProvider", "libROOTNTupleDraw6Provider", "libROOTNTupleDraw7Provider");
422 }
423
425
#define R__LOG_ERROR(...)
Definition RLogger.hxx:362
RDefaultProvider newRDefaultProvider
bool ScanProviderMap(Map_t &fmap, const RProvider::ClassArg &cl, bool test_all=false, std::function< bool(Func_t &)> check_func=nullptr)
char name[80]
Definition TGX11.cxx:110
void(* Func_t)()
Definition TSystem.h:238
R__EXTERN TSystem * gSystem
Definition TSystem.h:559
const char * extension
Definition civetweb.c:7793
Provider of different browsing methods for supported classes.
Definition RProvider.hxx:36
void RegisterDraw7(const TClass *cl, Draw7Func_t func)
static std::shared_ptr< RElement > BrowseNTuple(const std::string &tuplename, const std::string &filename)
Start browsing of RNTuple.
std::function< bool(std::shared_ptr< ROOT::Experimental::RPadBase > &, std::unique_ptr< RHolder > &, const std::string &)> Draw7Func_t
Definition RProvider.hxx:75
static bool CanDraw6(const ClassArg &)
Return true if provided class can be drawn on the TCanvas.
void RegisterDraw6(const TClass *cl, Draw6Func_t func)
static std::shared_ptr< RElement > Browse(std::unique_ptr< RHolder > &obj)
Create browsable element for the object Created element may take ownership over the object.
static bool CanDraw7(const ClassArg &)
Return true if provided class can be drawn on the RCanvas.
static BrowseNTupleFunc_t gNTupleFunc
static bool Draw6(TVirtualPad *subpad, std::unique_ptr< RHolder > &obj, const std::string &opt="")
Invoke drawing of object on TCanvas sub-pad All existing providers are checked, first checked are cla...
virtual ~RProvider()
Automatically unregister provider from all maps.
Definition RProvider.cxx:75
std::multimap< std::string, StructClass > ClassMap_t
static std::string GetClassIcon(const ClassArg &, bool=false)
Return icon name for the given class - either class name or TClass *.
std::multimap< std::string, StructFile > FileMap_t
static bool Draw7(std::shared_ptr< ROOT::Experimental::RPadBase > &subpad, std::unique_ptr< RHolder > &obj, const std::string &opt="")
Invoke drawing of object on RCanvas sub-pad All existing providers are checked, first checked are cla...
void RegisterFile(const std::string &extension, FileFunc_t func)
Definition RProvider.cxx:88
static bool IsFileFormatSupported(const std::string &extension)
std::function< std::shared_ptr< RElement >(const std::string &, const std::string &)> BrowseNTupleFunc_t
Definition RProvider.hxx:73
std::function< std::shared_ptr< RElement >(std::unique_ptr< RHolder > &)> BrowseFunc_t
Definition RProvider.hxx:72
std::multimap< const TClass *, StructBrowse > BrowseMap_t
void RegisterBrowse(const TClass *cl, BrowseFunc_t func)
void RegisterNTupleFunc(BrowseNTupleFunc_t func)
void RegisterClass(const std::string &clname, const std::string &iconname, const std::string &browselib="", const std::string &draw6lib="", const std::string &draw7lib="")
std::function< std::shared_ptr< RElement >(const std::string &)> FileFunc_t
Definition RProvider.hxx:71
static bool CanHaveChilds(const ClassArg &)
Return true if provided class can have childs.
std::function< bool(TVirtualPad *, std::unique_ptr< RHolder > &, const std::string &)> Draw6Func_t
Definition RProvider.hxx:74
static std::shared_ptr< RElement > OpenFile(const std::string &extension, const std::string &fullname)
std::multimap< const TClass *, StructDraw7 > Draw7Map_t
std::multimap< const TClass *, StructDraw6 > Draw6Map_t
static const StructClass & GetClassEntry(const ClassArg &)
Each class (see TClass) has a linked list of its base class(es).
Definition TBaseClass.h:33
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition TClass.h:80
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition TClass.cxx:3622
virtual const char * GetName() const
Returns name of object.
Definition TNamed.h:47
virtual int Load(const char *module, const char *entry="", Bool_t system=kFALSE)
Load a shared library.
Definition TSystem.cxx:1855
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
RLogChannel & BrowsableLog()
Log channel for Browsable diagnostics.
Definition RElement.cxx:18