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::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 vector of registered progress functions
70
72{
73 static RProvider::ProgressVect_t sVect;
74 return sVect;
75}
76
77
78//////////////////////////////////////////////////////////////////////////////////
79// Destructor
80/// Automatically unregister provider from all maps
81
83{
84 // here to remove all correspondent entries
90}
91
92//////////////////////////////////////////////////////////////////////////////////
93// Register file open function for specified extension
94
95void RProvider::RegisterFile(const std::string &extension, FileFunc_t func)
96{
97 auto &fmap = GetFileMap();
98
99 if ((extension != "*") && (fmap.find(extension) != fmap.end()))
100 R__LOG_ERROR(BrowsableLog()) << "Provider for file extension " << extension << " already exists";
101
102 fmap.emplace(extension, StructFile{this,func});
103}
104
105//////////////////////////////////////////////////////////////////////////////////
106// Register browse function for specified class
107
109{
110 auto &bmap = GetBrowseMap();
111
112 if (cl && (bmap.find(cl) != bmap.end()))
113 R__LOG_ERROR(BrowsableLog()) << "Browse provider for class " << cl->GetName() << " already exists";
114
115 bmap.emplace(cl, StructBrowse{this,func});
116}
117
118//////////////////////////////////////////////////////////////////////////////////
119// Register drawing function for v6 canvas
120
122{
123 auto &bmap = GetDraw6Map();
124
125 if (cl && (bmap.find(cl) != bmap.end()))
126 R__LOG_ERROR(BrowsableLog()) << "Draw v6 handler for class " << cl->GetName() << " already exists";
127
128 bmap.emplace(cl, StructDraw6{this, func});
129}
130
131//////////////////////////////////////////////////////////////////////////////////
132// Register drawing function for v7 canvas
133
135{
136 auto &bmap = GetDraw7Map();
137
138 if (cl && (bmap.find(cl) != bmap.end()))
139 R__LOG_ERROR(BrowsableLog()) << "Draw v7 handler for class " << cl->GetName() << " already exists";
140
141 bmap.emplace(cl, StructDraw7{this, func});
142}
143
144//////////////////////////////////////////////////////////////////////////////////
145// Register function for browsing RNTuple
146
148{
149 gNTupleFunc = func;
150}
151
152//////////////////////////////////////////////////////////////////////////////////
153// Register class with supported libs (if any)
154
155void RProvider::RegisterClass(const std::string &clname, const std::string &iconname,
156 const std::string &browselib, const std::string &draw6lib,
157 const std::string &draw7lib, const std::string &drawopt)
158{
159 auto &bmap = GetClassMap();
160
161 if (!clname.empty() && (bmap.find(clname) != bmap.end()))
162 R__LOG_ERROR(BrowsableLog()) << "Entry for class " << clname << " already exists";
163
164 std::string blib = browselib;
165 bool can_have_childs = !browselib.empty();
166 if ((blib == "dflt") || (blib == "TObject")) blib = ""; // just use as indicator that browsing is possible
167
168 bmap.emplace(clname, StructClass{this, can_have_childs, iconname, blib, draw6lib, draw7lib, drawopt});
169}
170
171//////////////////////////////////////////////////////////////////////////////////
172// Returns entry for the requested class
174{
175 if (!cl.empty()) {
176 auto &bmap = GetClassMap();
177 auto iter = bmap.find(cl.cl ? cl.cl->GetName() : cl.name.c_str());
178 if (iter != bmap.end())
179 return iter->second;
180
181 if (!cl.name.empty()) {
182 for (auto &elem : bmap)
183 if (cl.name.compare(0, elem.first.length(), elem.first) == 0)
184 return elem.second;
185 } else if (cl.cl) {
186 auto bases = const_cast<TClass *>(cl.cl)->GetListOfBases();
187 const TClass *basecl = bases && (bases->GetSize() > 0) ? dynamic_cast<TBaseClass *>(bases->First())->GetClassPointer() : nullptr;
188 if (basecl) return RProvider::GetClassEntry(basecl);
189 }
190 }
191
192 static StructClass dummy;
193 return dummy;
194}
195
196//////////////////////////////////////////////////////////////////////////////////
197// Returns true if file extension is supported
198
200{
201 if (extension.empty())
202 return false;
203
204 auto &fmap = GetFileMap();
205
206 return fmap.find(extension) != fmap.end();
207}
208
209//////////////////////////////////////////////////////////////////////////////////
210// Try to open file using provided extension.
211
212std::shared_ptr<RElement> RProvider::OpenFile(const std::string &extension, const std::string &fullname)
213{
214 auto &fmap = GetFileMap();
215
216 auto iter = fmap.find(extension);
217
218 if (iter != fmap.end())
219 return iter->second.func(fullname);
220
221 return nullptr;
222}
223
224//////////////////////////////////////////////////////////////////////////////////
225// Template function to scan class entries, including parent object classes
226
227template<class Map_t, class Func_t>
228bool ScanProviderMap(Map_t &fmap, const RProvider::ClassArg &cl, bool test_all = false, std::function<bool(Func_t &)> check_func = nullptr)
229{
230 if (cl.empty())
231 return false;
232
233 if (cl.GetClass()) {
234 TClass *testcl = const_cast<TClass *>(cl.GetClass());
235 while (testcl) {
236 auto iter = fmap.find(testcl);
237 if (iter != fmap.end())
238 if (!check_func || check_func(iter->second.func))
239 return true;
240
241 auto bases = testcl->GetListOfBases();
242
243 testcl = bases && (bases->GetSize() > 0) ? dynamic_cast<TBaseClass *>(bases->First())->GetClassPointer() : nullptr;
244 }
245 } else {
246 for (auto &entry : fmap) {
247 if (!entry.first) continue;
248 std::string name = entry.first->GetName();
249 if (!check_func) {
250 // when check_func not specified, just try to guess if class can match
251 if ((cl.GetName() == name) || (cl.GetName().compare(0, name.length(), name) == 0))
252 return true;
253 } else if (cl.GetName() == name) {
254 if (check_func(entry.second.func))
255 return true;
256 }
257 }
258 }
259
260 if (test_all && check_func) {
261 for (auto &entry : fmap)
262 if (!entry.first && check_func(entry.second.func))
263 return true;
264 }
265
266 return false;
267}
268
269/////////////////////////////////////////////////////////////////////////
270/// Create browsable element for the object
271/// Created element may take ownership over the object
272
273std::shared_ptr<RElement> RProvider::Browse(std::unique_ptr<RHolder> &object)
274{
275 std::shared_ptr<RElement> res;
276
277 if (!object) return res;
278
279 auto browse_func = [&res, &object] (BrowseFunc_t &func) -> bool {
280 res = func(object);
281 return (res || !object) ? true : false;
282 };
283
284 // check only class entries
285 if (ScanProviderMap<BrowseMap_t,BrowseFunc_t>(GetBrowseMap(), object->GetClass(), false, browse_func))
286 return res;
287
288 auto &entry = GetClassEntry(object->GetClass());
289 if (!entry.dummy() && !entry.browselib.empty())
290 gSystem->Load(entry.browselib.c_str());
291
292 // let call also generic browse functions (multicast)
293 ScanProviderMap<BrowseMap_t,BrowseFunc_t>(GetBrowseMap(), object->GetClass(), true, browse_func);
294
295 return res;
296}
297
298/////////////////////////////////////////////////////////////////////////////////
299/// Start browsing of RNTuple
300
301std::shared_ptr<RElement> RProvider::BrowseNTuple(const std::string &tuplename, const std::string &filename)
302{
303 if (!gNTupleFunc) {
304 auto &entry = GetClassEntry("ROOT::Experimental::RNTuple");
305
306 if (entry.browselib.empty())
307 return nullptr;
308
309 gSystem->Load(entry.browselib.c_str());
310 }
311
312 if (!gNTupleFunc)
313 return nullptr;
314
315 return gNTupleFunc(tuplename, filename);
316}
317
318/////////////////////////////////////////////////////////////////////////////////
319/// Invoke drawing of object on TCanvas sub-pad
320/// All existing providers are checked, first checked are class matches (including direct parents)
321
322bool RProvider::Draw6(TVirtualPad *subpad, std::unique_ptr<RHolder> &object, const std::string &opt)
323{
324 if (!object || !object->GetClass())
325 return false;
326
327 auto draw_func = [subpad, &object, &opt](Draw6Func_t &func) -> bool {
328 return func(subpad, object, opt);
329 };
330
331 if (ScanProviderMap<Draw6Map_t,Draw6Func_t>(GetDraw6Map(), object->GetClass(), false, draw_func))
332 return true;
333
334 auto &entry = GetClassEntry(object->GetClass());
335 if (!entry.dummy() && !entry.draw6lib.empty())
336 gSystem->Load(entry.draw6lib.c_str());
337
338 return ScanProviderMap<Draw6Map_t,Draw6Func_t>(GetDraw6Map(), object->GetClass(), true, draw_func);
339}
340
341/////////////////////////////////////////////////////////////////////////////////
342/// Invoke drawing of object on RCanvas sub-pad
343/// All existing providers are checked, first checked are class matches (including direct parents)
344
345bool RProvider::Draw7(std::shared_ptr<ROOT::Experimental::RPadBase> &subpad, std::unique_ptr<RHolder> &object, const std::string &opt)
346{
347 if (!object || !object->GetClass())
348 return false;
349
350 auto draw_func = [&subpad, &object, &opt](Draw7Func_t &func) -> bool {
351 return func(subpad, object, opt);
352 };
353
354 if (ScanProviderMap<Draw7Map_t,Draw7Func_t>(GetDraw7Map(), object->GetClass(), false, draw_func))
355 return true;
356
357 auto &entry = GetClassEntry(object->GetClass());
358 if (!entry.dummy() && !entry.draw7lib.empty())
359 gSystem->Load(entry.draw7lib.c_str());
360
361 return ScanProviderMap<Draw7Map_t,Draw7Func_t>(GetDraw7Map(), object->GetClass(), true, draw_func);
362}
363
364/////////////////////////////////////////////////////////////////////
365/// Return icon name for the given class - either class name or TClass *
366
367std::string RProvider::GetClassIcon(const ClassArg &arg, bool is_folder)
368{
369 auto &entry = GetClassEntry(arg);
370 if (!entry.iconname.empty())
371 return entry.iconname;
372
373 return is_folder ? "sap-icon://folder-blank"s : "sap-icon://electronic-medical-record"s;
374}
375
376/////////////////////////////////////////////////////////////////////
377/// Return configured draw option for the class
378
380{
381 return GetClassEntry(arg).drawopt;
382}
383
384/////////////////////////////////////////////////////////////////////
385/// Set draw option for the class
386/// Return true if entry for the class exists
387
388bool RProvider::SetClassDrawOption(const ClassArg &arg, const std::string &opt)
389{
390 auto &entry = GetClassEntry(arg);
391 if (entry.dummy())
392 return false;
393
394 entry.drawopt = opt;
395 return true;
396}
397
398/////////////////////////////////////////////////////////////////////
399/// Return true if provided class can have childs
400
402{
403 return GetClassEntry(arg).can_have_childs;
404}
405
406/////////////////////////////////////////////////////////////////////
407/// Check if showing of sub-elements was disabled
408
410{
411 auto &entry = GetClassEntry(arg);
412 return !entry.dummy() && !entry.can_have_childs;
413}
414
415/////////////////////////////////////////////////////////////////////
416/// Return true if provided class can be drawn on the TCanvas
417
419{
420 if (ScanProviderMap<Draw6Map_t,Draw6Func_t>(GetDraw6Map(), arg))
421 return true;
422
423 if (!GetClassEntry(arg).draw6lib.empty())
424 return true;
425
426 return false;
427}
428
429/////////////////////////////////////////////////////////////////////
430/// Return true if provided class can be drawn on the RCanvas
431
433{
434 if (ScanProviderMap<Draw7Map_t,Draw7Func_t>(GetDraw7Map(), arg))
435 return true;
436
437 if (!GetClassEntry(arg).draw7lib.empty())
438 return true;
439
440 return false;
441}
442
443/////////////////////////////////////////////////////////////////////
444/// Create progress handle
445
447{
448 fHandle = handle;
449 RProvider::GetProgressVect().emplace_back(StructProgress{handle, nullptr, func});
450}
451
452/////////////////////////////////////////////////////////////////////
453/// Destroy progress handle
454
456{
457 auto &vect = RProvider::GetProgressVect();
458 auto iter = vect.begin();
459 while (iter != vect.end()) {
460 if (iter->handle == fHandle) {
461 vect.erase(iter);
462 } else {
463 iter++;
464 }
465 }
466}
467
468/////////////////////////////////////////////////////////////////////
469/// Extend progress handle
470
472{
473 RProvider::ExtendProgressHandle(fHandle, handle2);
474}
475
476/////////////////////////////////////////////////////////////////////
477/// Extend progress handle - to be able react on sub item
478
479void RProvider::ExtendProgressHandle(void *handle, void *handle2)
480{
481 for (auto &elem : GetProgressVect())
482 if (elem.handle == handle)
483 elem.handle2 = handle2;
484}
485
486/////////////////////////////////////////////////////////////////////
487/// Report running progress
488/// Returns true if handling function was invoked
489/// Method can be used to detect if there any progress handler assigned
490
491
492bool RProvider::ReportProgress(void *handle, float progress)
493{
494 bool is_any = false;
495 for (auto &elem : GetProgressVect())
496 if ((elem.handle == handle) || (elem.handle2 == handle)) {
497 elem.func(progress, elem.handle);
498 is_any = true;
499 }
500
501 return is_any;
502}
503
504// ==============================================================================================
505
507
508public:
510 {
511 // TODO: let read from rootrc or any other files
512 RegisterClass("ROOT::Experimental::RH1D", "sap-icon://bar-chart", "", "", "libROOTHistDrawProvider");
513 RegisterClass("ROOT::Experimental::RH2D", "sap-icon://pixelate", "", "", "libROOTHistDrawProvider");
514 RegisterClass("ROOT::Experimental::RH3D", "sap-icon://product", "", "", "libROOTHistDrawProvider");
515 RegisterClass("ROOT::Experimental::RCanvas", "sap-icon://business-objects-experience", "", "", "libROOTHistDrawProvider");
516 RegisterClass("ROOT::Experimental::RNTuple", "sap-icon://table-chart", "libROOTNTupleBrowseProvider", "libROOTNTupleDraw6Provider", "libROOTNTupleDraw7Provider");
517 }
518
520
#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:233
R__EXTERN TSystem * gSystem
Definition TSystem.h:555
const char * extension
Definition civetweb.c:8026
const std::string & GetName() const
Definition RProvider.hxx:57
const TClass * GetClass() const
Definition RProvider.hxx:56
void Extend(void *handle2)
Extend progress handle.
ProgressHandle(const ProgressHandle &)=delete
~ProgressHandle()
Destroy progress handle.
Provider of different browsing methods for supported classes.
Definition RProvider.hxx:37
void RegisterDraw7(const TClass *cl, Draw7Func_t func)
static bool ReportProgress(void *handle, float progress)
Report running progress Returns true if handling function was invoked Method can be used to detect if...
static ProgressVect_t & GetProgressVect()
Definition RProvider.cxx:71
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="")
static bool CanDraw6(const ClassArg &)
Return true if provided class can be drawn on the TCanvas.
static ClassMap_t & GetClassMap()
Definition RProvider.cxx:62
static bool SetClassDrawOption(const ClassArg &, const std::string &)
Set draw option for the class Return true if entry for the class exists.
static FileMap_t & GetFileMap()
Definition RProvider.cxx:35
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...
std::multimap< const TClass *, StructDraw6 > Draw6Map_t
virtual ~RProvider()
Automatically unregister provider from all maps.
Definition RProvider.cxx:82
std::function< std::shared_ptr< RElement >(const std::string &)> FileFunc_t
Definition RProvider.hxx:95
static std::string GetClassIcon(const ClassArg &, bool=false)
Return icon name for the given class - either class name or TClass *.
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...
std::function< void(float progress, void *handle)> ProgressFunc_t
Definition RProvider.hxx:43
std::multimap< const TClass *, StructBrowse > BrowseMap_t
void RegisterFile(const std::string &extension, FileFunc_t func)
Definition RProvider.cxx:95
static bool IsFileFormatSupported(const std::string &extension)
static Draw7Map_t & GetDraw7Map()
Definition RProvider.cxx:53
std::function< bool(TVirtualPad *, std::unique_ptr< RHolder > &, const std::string &)> Draw6Func_t
Definition RProvider.hxx:98
void RegisterBrowse(const TClass *cl, BrowseFunc_t func)
std::function< std::shared_ptr< RElement >(std::unique_ptr< RHolder > &)> BrowseFunc_t
Definition RProvider.hxx:96
void RegisterNTupleFunc(BrowseNTupleFunc_t func)
static bool CanHaveChilds(const ClassArg &)
Return true if provided class can have childs.
static BrowseMap_t & GetBrowseMap()
Definition RProvider.cxx:26
static StructClass & GetClassEntry(const ClassArg &)
std::function< bool(std::shared_ptr< ROOT::Experimental::RPadBase > &, std::unique_ptr< RHolder > &, const std::string &)> Draw7Func_t
Definition RProvider.hxx:99
static std::shared_ptr< RElement > OpenFile(const std::string &extension, const std::string &fullname)
std::vector< StructProgress > ProgressVect_t
void CleanThis(Map_t &fmap)
std::multimap< std::string, StructFile > FileMap_t
static Draw6Map_t & GetDraw6Map()
Definition RProvider.cxx:44
std::function< std::shared_ptr< RElement >(const std::string &, const std::string &)> BrowseNTupleFunc_t
Definition RProvider.hxx:97
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< std::string, StructClass > ClassMap_t
static void ExtendProgressHandle(void *handle, void *handle2)
Extend progress handle - to be able react on sub item.
std::multimap< const TClass *, StructDraw7 > Draw7Map_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:1857
TVirtualPad is an abstract base class for the Pad and Canvas classes.
Definition TVirtualPad.h:51
ROOT::Experimental::RLogChannel & BrowsableLog()
Log channel for Browsable diagnostics.
Definition RElement.cxx:20