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// Register drawing function for v6 canvas
113
115{
116 auto &bmap = GetDraw6Map();
117
118 if (cl && (bmap.find(cl) != bmap.end()))
119 R__LOG_ERROR(BrowsableLog()) << "Draw v6 handler for class " << cl->GetName() << " already exists";
120
121 bmap.emplace(cl, StructDraw6{this, func});
122}
123
124//////////////////////////////////////////////////////////////////////////////////
125// Register drawing function for v7 canvas
126
128{
129 auto &bmap = GetDraw7Map();
130
131 if (cl && (bmap.find(cl) != bmap.end()))
132 R__LOG_ERROR(BrowsableLog()) << "Draw v7 handler for class " << cl->GetName() << " already exists";
133
134 bmap.emplace(cl, StructDraw7{this, func});
135}
136
137//////////////////////////////////////////////////////////////////////////////////
138// Register function for browsing RNTuple
139
141{
142 gNTupleFunc = func;
143}
144
145//////////////////////////////////////////////////////////////////////////////////
146// Register class with supported libs (if any)
147
148void RProvider::RegisterClass(const std::string &clname, const std::string &iconname,
149 const std::string &browselib, const std::string &draw6lib,
150 const std::string &draw7lib, const std::string &drawopt)
151{
152 auto &bmap = GetClassMap();
153
154 if (!clname.empty() && (bmap.find(clname) != bmap.end()))
155 R__LOG_ERROR(BrowsableLog()) << "Entry for class " << clname << " already exists";
156
157 std::string blib = browselib;
158 bool can_have_childs = !browselib.empty();
159 if ((blib == "dflt") || (blib == "TObject")) blib = ""; // just use as indicator that browsing is possible
160
161 bmap.emplace(clname, StructClass{this, can_have_childs, iconname, blib, draw6lib, draw7lib, drawopt});
162}
163
164//////////////////////////////////////////////////////////////////////////////////
165// Returns entry for the requested class
167{
168 if (!cl.empty()) {
169 auto &bmap = GetClassMap();
170 auto iter = bmap.find(cl.cl ? cl.cl->GetName() : cl.name.c_str());
171 if (iter != bmap.end())
172 return iter->second;
173
174 if (!cl.name.empty()) {
175 for (auto &elem : bmap)
176 if (cl.name.compare(0, elem.first.length(), elem.first) == 0)
177 return elem.second;
178 } else if (cl.cl) {
179 auto bases = const_cast<TClass *>(cl.cl)->GetListOfBases();
180 const TClass *basecl = bases && (bases->GetSize() > 0) ? dynamic_cast<TBaseClass *>(bases->First())->GetClassPointer() : nullptr;
181 if (basecl) return RProvider::GetClassEntry(basecl);
182 }
183 }
184
185 static StructClass dummy;
186 return dummy;
187}
188
189//////////////////////////////////////////////////////////////////////////////////
190// Returns true if file extension is supported
191
193{
194 if (extension.empty())
195 return false;
196
197 auto &fmap = GetFileMap();
198
199 return fmap.find(extension) != fmap.end();
200}
201
202//////////////////////////////////////////////////////////////////////////////////
203// Try to open file using provided extension.
204
205std::shared_ptr<RElement> RProvider::OpenFile(const std::string &extension, const std::string &fullname)
206{
207 auto &fmap = GetFileMap();
208
209 auto iter = fmap.find(extension);
210
211 if (iter != fmap.end())
212 return iter->second.func(fullname);
213
214 return nullptr;
215}
216
217//////////////////////////////////////////////////////////////////////////////////
218// Template function to scan class entries, including parent object classes
219
220template<class Map_t, class Func_t>
221bool ScanProviderMap(Map_t &fmap, const RProvider::ClassArg &cl, bool test_all = false, std::function<bool(Func_t &)> check_func = nullptr)
222{
223 if (cl.empty())
224 return false;
225
226 if (cl.GetClass()) {
227 TClass *testcl = const_cast<TClass *>(cl.GetClass());
228 while (testcl) {
229 auto iter = fmap.find(testcl);
230 if (iter != fmap.end())
231 if (!check_func || check_func(iter->second.func))
232 return true;
233
234 auto bases = testcl->GetListOfBases();
235
236 testcl = bases && (bases->GetSize() > 0) ? dynamic_cast<TBaseClass *>(bases->First())->GetClassPointer() : nullptr;
237 }
238 } else {
239 for (auto &entry : fmap) {
240 if (!entry.first) continue;
241 std::string name = entry.first->GetName();
242 if (!check_func) {
243 // when check_func not specified, just try to guess if class can match
244 if ((cl.GetName() == name) || (cl.GetName().compare(0, name.length(), name) == 0))
245 return true;
246 } else if (cl.GetName() == name) {
247 if (check_func(entry.second.func))
248 return true;
249 }
250 }
251 }
252
253 if (test_all && check_func) {
254 for (auto &entry : fmap)
255 if (!entry.first && check_func(entry.second.func))
256 return true;
257 }
258
259 return false;
260}
261
262/////////////////////////////////////////////////////////////////////////
263/// Create browsable element for the object
264/// Created element may take ownership over the object
265
266std::shared_ptr<RElement> RProvider::Browse(std::unique_ptr<RHolder> &object)
267{
268 std::shared_ptr<RElement> res;
269
270 if (!object) return res;
271
272 auto browse_func = [&res, &object] (BrowseFunc_t &func) -> bool {
273 res = func(object);
274 return (res || !object) ? true : false;
275 };
276
277 // check only class entries
278 if (ScanProviderMap<BrowseMap_t,BrowseFunc_t>(GetBrowseMap(), object->GetClass(), false, browse_func))
279 return res;
280
281 auto &entry = GetClassEntry(object->GetClass());
282 if (!entry.dummy() && !entry.browselib.empty())
283 gSystem->Load(entry.browselib.c_str());
284
285 // let call also generic browse functions (multicast)
286 ScanProviderMap<BrowseMap_t,BrowseFunc_t>(GetBrowseMap(), object->GetClass(), true, browse_func);
287
288 return res;
289}
290
291/////////////////////////////////////////////////////////////////////////////////
292/// Start browsing of RNTuple
293
294std::shared_ptr<RElement> RProvider::BrowseNTuple(const std::string &tuplename, const std::string &filename)
295{
296 if (!gNTupleFunc) {
297 auto &entry = GetClassEntry("ROOT::Experimental::RNTuple");
298
299 if (entry.browselib.empty())
300 return nullptr;
301
302 gSystem->Load(entry.browselib.c_str());
303 }
304
305 if (!gNTupleFunc)
306 return nullptr;
307
308 return gNTupleFunc(tuplename, filename);
309}
310
311/////////////////////////////////////////////////////////////////////////////////
312/// Invoke drawing of object on TCanvas sub-pad
313/// All existing providers are checked, first checked are class matches (including direct parents)
314
315bool RProvider::Draw6(TVirtualPad *subpad, std::unique_ptr<RHolder> &object, const std::string &opt)
316{
317 if (!object || !object->GetClass())
318 return false;
319
320 auto draw_func = [subpad, &object, &opt](Draw6Func_t &func) -> bool {
321 return func(subpad, object, opt);
322 };
323
324 if (ScanProviderMap<Draw6Map_t,Draw6Func_t>(GetDraw6Map(), object->GetClass(), false, draw_func))
325 return true;
326
327 auto &entry = GetClassEntry(object->GetClass());
328 if (!entry.dummy() && !entry.draw6lib.empty())
329 gSystem->Load(entry.draw6lib.c_str());
330
331 return ScanProviderMap<Draw6Map_t,Draw6Func_t>(GetDraw6Map(), object->GetClass(), true, draw_func);
332}
333
334/////////////////////////////////////////////////////////////////////////////////
335/// Invoke drawing of object on RCanvas sub-pad
336/// All existing providers are checked, first checked are class matches (including direct parents)
337
338bool RProvider::Draw7(std::shared_ptr<ROOT::Experimental::RPadBase> &subpad, std::unique_ptr<RHolder> &object, const std::string &opt)
339{
340 if (!object || !object->GetClass())
341 return false;
342
343 auto draw_func = [&subpad, &object, &opt](Draw7Func_t &func) -> bool {
344 return func(subpad, object, opt);
345 };
346
347 if (ScanProviderMap<Draw7Map_t,Draw7Func_t>(GetDraw7Map(), object->GetClass(), false, draw_func))
348 return true;
349
350 auto &entry = GetClassEntry(object->GetClass());
351 if (!entry.dummy() && !entry.draw7lib.empty())
352 gSystem->Load(entry.draw7lib.c_str());
353
354 return ScanProviderMap<Draw7Map_t,Draw7Func_t>(GetDraw7Map(), object->GetClass(), true, draw_func);
355}
356
357/////////////////////////////////////////////////////////////////////
358/// Return icon name for the given class - either class name or TClass *
359
360std::string RProvider::GetClassIcon(const ClassArg &arg, bool is_folder)
361{
362 auto &entry = GetClassEntry(arg);
363 if (!entry.iconname.empty())
364 return entry.iconname;
365
366 return is_folder ? "sap-icon://folder-blank"s : "sap-icon://electronic-medical-record"s;
367}
368
369/////////////////////////////////////////////////////////////////////
370/// Return configured draw option for the class
371
373{
374 return GetClassEntry(arg).drawopt;
375}
376
377/////////////////////////////////////////////////////////////////////
378/// Set draw option for the class
379/// Return true if entry for the class exists
380
381bool RProvider::SetClassDrawOption(const ClassArg &arg, const std::string &opt)
382{
383 auto &entry = GetClassEntry(arg);
384 if (entry.dummy())
385 return false;
386
387 entry.drawopt = opt;
388 return true;
389}
390
391/////////////////////////////////////////////////////////////////////
392/// Return true if provided class can have childs
393
395{
396 return GetClassEntry(arg).can_have_childs;
397}
398
399/////////////////////////////////////////////////////////////////////
400/// Check if showing of sub-elements was disabled
401
403{
404 auto &entry = GetClassEntry(arg);
405 return !entry.dummy() && !entry.can_have_childs;
406}
407
408/////////////////////////////////////////////////////////////////////
409/// Return true if provided class can be drawn on the TCanvas
410
412{
413 if (ScanProviderMap<Draw6Map_t,Draw6Func_t>(GetDraw6Map(), arg))
414 return true;
415
416 if (!GetClassEntry(arg).draw6lib.empty())
417 return true;
418
419 return false;
420}
421
422/////////////////////////////////////////////////////////////////////
423/// Return true if provided class can be drawn on the RCanvas
424
426{
427 if (ScanProviderMap<Draw7Map_t,Draw7Func_t>(GetDraw7Map(), arg))
428 return true;
429
430 if (!GetClassEntry(arg).draw7lib.empty())
431 return true;
432
433 return false;
434}
435
436
437// ==============================================================================================
438
440
441public:
443 {
444 // TODO: let read from rootrc or any other files
445 RegisterClass("ROOT::Experimental::RH1D", "sap-icon://bar-chart", "", "", "libROOTHistDrawProvider");
446 RegisterClass("ROOT::Experimental::RH2D", "sap-icon://pixelate", "", "", "libROOTHistDrawProvider");
447 RegisterClass("ROOT::Experimental::RH3D", "sap-icon://product", "", "", "libROOTHistDrawProvider");
448 RegisterClass("ROOT::Experimental::RCanvas", "sap-icon://business-objects-experience", "", "", "libROOTHistDrawProvider");
449 RegisterClass("ROOT::Experimental::RNTuple", "sap-icon://table-chart", "libROOTNTupleBrowseProvider", "libROOTNTupleDraw6Provider", "libROOTNTupleDraw7Provider");
450 }
451
453
#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)
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 filename
char name[80]
Definition TGX11.cxx:110
void(* Func_t)()
Definition TSystem.h:238
R__EXTERN TSystem * gSystem
Definition TSystem.h:560
const char * extension
Definition civetweb.c:8024
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.
void RegisterClass(const std::string &clname, const std::string &iconname, const std::string &browselib="", const std::string &draw6lib="", const std::string &draw7lib="", const std::string &drawopt="")
std::function< bool(std::shared_ptr< ROOT::Experimental::RPadBase > &, std::unique_ptr< RHolder > &, const std::string &)> Draw7Func_t
Definition RProvider.hxx:79
static bool CanDraw6(const ClassArg &)
Return true if provided class can be drawn on the TCanvas.
static bool SetClassDrawOption(const ClassArg &, const std::string &)
Set draw option for the class Return true if entry for the class exists.
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:77
std::function< std::shared_ptr< RElement >(std::unique_ptr< RHolder > &)> BrowseFunc_t
Definition RProvider.hxx:76
std::multimap< const TClass *, StructBrowse > BrowseMap_t
void RegisterBrowse(const TClass *cl, BrowseFunc_t func)
void RegisterNTupleFunc(BrowseNTupleFunc_t func)
std::function< std::shared_ptr< RElement >(const std::string &)> FileFunc_t
Definition RProvider.hxx:75
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:78
static StructClass & GetClassEntry(const ClassArg &)
static std::shared_ptr< RElement > OpenFile(const std::string &extension, const std::string &fullname)
std::multimap< const TClass *, StructDraw7 > Draw7Map_t
static bool NotShowChilds(const ClassArg &)
Check if showing of sub-elements was disabled.
static std::string GetClassDrawOption(const ClassArg &)
Return configured draw option for the class.
std::multimap< const TClass *, StructDraw6 > Draw6Map_t
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:81
TList * GetListOfBases()
Return list containing the TBaseClass(es) of a class.
Definition TClass.cxx:3636
const char * GetName() const override
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:1858
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:20