Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RCanvas.cxx
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (C) 1995-2015, 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
9#include "ROOT/RCanvas.hxx"
10
11#include "ROOT/RLogger.hxx"
12
13#include <algorithm>
14#include <memory>
15#include <mutex>
16#include <thread>
17#include <chrono>
18#include <stdio.h>
19#include <string.h>
20
21#include "TList.h"
22#include "TROOT.h"
23
24namespace {
25
26static std::mutex &GetHeldCanvasesMutex()
27{
28 static std::mutex sMutex;
29 return sMutex;
30}
31
32static std::vector<std::shared_ptr<ROOT::Experimental::RCanvas>> &GetHeldCanvases()
33{
34 static std::vector<std::shared_ptr<ROOT::Experimental::RCanvas>> sCanvases;
35 return sCanvases;
36}
37
38
39} // namespace
40
41///////////////////////////////////////////////////////////////////////////////////////
42/// Returns list of created canvases
43
44const std::vector<std::shared_ptr<ROOT::Experimental::RCanvas>> ROOT::Experimental::RCanvas::GetCanvases()
45{
46 std::lock_guard<std::mutex> grd(GetHeldCanvasesMutex());
47
48 return GetHeldCanvases();
49}
50
51///////////////////////////////////////////////////////////////////////////////////////
52/// Release list of held canvases pointers
53/// If no other shared pointers exists on the canvas, object will be destroyed
54
56{
57 std::vector<std::shared_ptr<ROOT::Experimental::RCanvas>> vect;
58
59 {
60 std::lock_guard<std::mutex> grd(GetHeldCanvasesMutex());
61
62 std::swap(vect, GetHeldCanvases());
63 }
64}
65
66///////////////////////////////////////////////////////////////////////////////////////
67/// Returns true is canvas was modified since last painting
68
70{
71 return fPainter ? fPainter->IsCanvasModified(fModified) : fModified;
72}
73
74///////////////////////////////////////////////////////////////////////////////////////
75/// Update canvas
76
78{
79 if (fPainter)
80 fPainter->CanvasUpdated(fModified, async, callback);
81}
82
83class RCanvasCleanup : public TObject {
84public:
85
87
88 RCanvasCleanup() : TObject() { gInstance = this; }
89
91 {
92 gInstance = nullptr;
93 // ROOT::Experimental::RCanvas::ReleaseHeldCanvases();
94 }
95};
96
98
99
100///////////////////////////////////////////////////////////////////////////////////////
101/// Create new canvas instance
102
103std::shared_ptr<ROOT::Experimental::RCanvas> ROOT::Experimental::RCanvas::Create(const std::string &title)
104{
105 auto pCanvas = std::make_shared<RCanvas>();
106 pCanvas->SetTitle(title);
107 {
108 std::lock_guard<std::mutex> grd(GetHeldCanvasesMutex());
109 GetHeldCanvases().emplace_back(pCanvas);
110 }
111
113 auto cleanup = new RCanvasCleanup();
114 TDirectory::TContext ctxt(nullptr);
115 TDirectory *dummydir = new TDirectory("rcanvas_cleanup_dummydir","title");
116 dummydir->GetList()->Add(cleanup);
117 gROOT->GetListOfClosedObjects()->Add(dummydir);
118 }
119
120 return pCanvas;
121}
122
123//////////////////////////////////////////////////////////////////////////
124/// Create new display for the canvas
125/// The parameter `where` specifies which program could be used for display creation
126/// Possible values:
127///
128/// - `cef` Chromium Embeded Framework, local display, local communication
129/// - `qt5` Qt5 WebEngine (when running via rootqt5), local display, local communication
130/// - `browser` default system web-browser, communication via random http port from range 8800 - 9800
131/// - `<prog>` any program name which will be started instead of default browser, like firefox or /usr/bin/opera
132/// one could also specify $url in program name, which will be replaced with canvas URL
133/// - `native` either any available local display or default browser
134///
135/// Canvas can be displayed in several different places
136
137void ROOT::Experimental::RCanvas::Show(const std::string &where)
138{
139 fShown = true;
140
141 // workaround - in jupyter do not create any painters yet
142 if (gROOT->GetWebDisplay() == "jupyter") return;
143
144 if (fPainter) {
145 bool isany = (fPainter->NumDisplays() > 0);
146
147 if (!where.empty())
148 fPainter->NewDisplay(where);
149
150 if (isany) return;
151 }
152
153 if (!fModified)
154 fModified = 1; // 0 is special value, means no changes and no drawings
155
156 if (!fPainter)
158
159 if (fPainter) {
160 fPainter->NewDisplay(where);
161 fPainter->CanvasUpdated(fModified, true, nullptr); // trigger async display
162 }
163}
164
165//////////////////////////////////////////////////////////////////////////
166/// Returns window name for canvas
167
169{
170 if (fPainter)
171 return fPainter->GetWindowAddr();
172
173 return "";
174}
175
176
177//////////////////////////////////////////////////////////////////////////
178/// Hide all canvas displays
179
181{
182 if (fPainter)
183 delete fPainter.release();
184}
185
186//////////////////////////////////////////////////////////////////////////
187/// Create image file for the canvas
188/// Supported SVG (extension .svg), JPEG (extension .jpg or .jpeg), PNG (extension .png) or JSON (extension .json)
189
190bool ROOT::Experimental::RCanvas::SaveAs(const std::string &filename)
191{
192 if (!fPainter)
194
195 if (!fPainter)
196 return false;
197
198 int width = GetWidth();
199 int height = GetHeight();
200
201 return fPainter->ProduceBatchOutput(filename, width > 1 ? width : 800, height > 1 ? height : 600);
202}
203
204//////////////////////////////////////////////////////////////////////////
205/// Create JSON data for the canvas
206/// Can be used of offline display with JSROOT
207
209{
210 if (!fPainter)
212
213 if (!fPainter)
214 return "";
215
216 return fPainter->ProduceJSON();
217}
218
219//////////////////////////////////////////////////////////////////////////
220/// Remove canvas from global canvas lists, will be destroyed once last shared_ptr is disappear
221
223{
224 std::lock_guard<std::mutex> grd(GetHeldCanvasesMutex());
225 auto &held = GetHeldCanvases();
226 auto indx = held.size();
227 while (indx-- > 0) {
228 if (held[indx].get() == this)
229 held.erase(held.begin() + indx);
230 }
231}
232
233//////////////////////////////////////////////////////////////////////////
234/// Run canvas functionality for the given time (in seconds)
235/// Used to process canvas-related actions in the appropriate thread context.
236/// Must be regularly called when canvas created and used in extra thread.
237/// Time parameter specifies minimal execution time in seconds - if default value 0 is used,
238/// just all pending actions will be performed.
239/// When canvas is not yet displayed - just performs sleep for given time interval.
240///
241/// Example of usage:
242///
243/// ~~~ {.cpp}
244/// void draw_canvas(bool &run_loop, std::make_shared<RH1D> hist)
245/// {
246/// auto canvas = RCanvas::Create("Canvas title");
247/// canvas->Draw(hist)->SetLineColor(RColor::kBlue);
248/// canvas->Show();
249/// while (run_loop) {
250/// pHist->Fill(1);
251/// canvas->Modified();
252/// canvas->Update();
253/// canvas->Run(0.1); // process canvas events
254/// }
255///
256/// canvas->Remove();
257/// }
258///
259/// int main()
260/// {
261/// RAxisConfig xaxis(100, -10., 10.);
262/// auto pHist = std::make_shared<RH1D>(xaxis);
263/// bool run_loop = true;
264///
265/// std::thread thrd(draw_canvas, run_loop, pHist);
266/// std::this_thread::sleep_for(std::chrono::seconds(100));
267/// run_loop = false;
268/// thrd.join();
269/// return 0;
270/// }
271/// ~~~
272
274{
275 if (fPainter) {
276 fPainter->Run(tm);
277 } else if (tm>0) {
278 std::this_thread::sleep_for(std::chrono::milliseconds(int(tm*1000)));
279 }
280}
281
282//////////////////////////////////////////////////////////////////////////
283/// To resolve problem with storing of shared pointers
284/// Call this method when reading canvas from the file
285/// Can be called many times - after reinitialization of shared pointers no changes will be performed
286
288{
290
291 CollectShared(vect);
292
293 for (unsigned n = 0; n < vect.size(); ++n) {
294 if (vect[n]->HasShared() || !vect[n]->GetIOPtr()) continue;
295
296 auto shrd_ptr = vect[n]->MakeShared();
297
298 for (auto n2 = n+1; n2 < vect.size(); ++n2) {
299 if (vect[n2]->GetIOPtr() == vect[n]->GetIOPtr()) {
300 if (vect[n2]->HasShared())
301 R__LOG_ERROR(GPadLog()) << "FATAL Shared pointer for same IO ptr already exists";
302 else
303 vect[n2]->SetShared(shrd_ptr);
304 }
305 }
306
307 }
308}
309
310
311/////////////////////////////////////////////////////////////////////////////////////////////////
312/// Apply attributes changes to the drawable
313/// Return mask with actions which were really applied
314
315std::unique_ptr<ROOT::Experimental::RDrawableReply> ROOT::Experimental::RChangeAttrRequest::Process()
316{
317 // suppress all changes coming from non-main connection
318 if (!GetContext().IsMainConn())
319 return nullptr;
320
321 auto canv = const_cast<ROOT::Experimental::RCanvas *>(GetContext().GetCanvas());
322 if (!canv) return nullptr;
323
324 if ((ids.size() != names.size()) || (ids.size() != values.size())) {
325 R__LOG_ERROR(GPadLog()) << "Mismatch of arrays size in RChangeAttrRequest";
326 return nullptr;
327 }
328
329 Version_t vers = 0;
330
331 for(int indx = 0; indx < (int) ids.size(); indx++) {
332 if (ids[indx] == "canvas") {
333 if (canv->GetAttrMap().Change(names[indx], values[indx].get())) {
334 if (!vers) vers = canv->IncModified();
335 canv->SetDrawableVersion(vers);
336 }
337 } else {
338 auto drawable = canv->FindPrimitiveByDisplayId(ids[indx]);
339 if (drawable && drawable->GetAttrMap().Change(names[indx], values[indx].get())) {
340 if (!vers) vers = canv->IncModified();
341 drawable->SetDrawableVersion(vers);
342 }
343 }
344 }
345
346 fNeedUpdate = (vers > 0) && update;
347
348 return nullptr; // no need for any reply
349}
#define R__LOG_ERROR(...)
Definition RLogger.hxx:362
static void update(gsl_integration_workspace *workspace, double a1, double b1, double area1, double error1, double a2, double b2, double area2, double error2)
short Version_t
Definition RtypesCore.h:65
include TDocParser_001 C image html pict1_TDocParser_001 png width
#define gROOT
Definition TROOT.h:404
virtual ~RCanvasCleanup()
Definition RCanvas.cxx:90
static RCanvasCleanup * gInstance
Definition RCanvas.cxx:86
static std::unique_ptr< RVirtualCanvasPainter > Create(RCanvas &canv)
Loads the plugin that implements this class.
A window's topmost RPad.
Definition RCanvas.hxx:47
static const std::vector< std::shared_ptr< RCanvas > > GetCanvases()
Returns list of created canvases.
Definition RCanvas.cxx:44
static void ReleaseHeldCanvases()
Release list of held canvases pointers If no other shared pointers exists on the canvas,...
Definition RCanvas.cxx:55
bool SaveAs(const std::string &filename)
Save canvas in image file.
Definition RCanvas.cxx:190
bool IsModified() const
Returns true is canvas was modified since last painting.
Definition RCanvas.cxx:69
void Show(const std::string &where="")
Display the canvas.
Definition RCanvas.cxx:137
std::string GetWindowAddr() const
Returns window name used to display canvas.
Definition RCanvas.cxx:168
void Remove()
Remove canvas from global canvas lists, will be destroyed when shared_ptr will be removed.
Definition RCanvas.cxx:222
void ResolveSharedPtrs()
To resolve problem with storing of shared pointers Call this method when reading canvas from the file...
Definition RCanvas.cxx:287
void Run(double tm=0.)
Run canvas functionality for given time (in seconds)
Definition RCanvas.cxx:273
std::string CreateJSON()
Provide JSON which can be used for offline display.
Definition RCanvas.cxx:208
static std::shared_ptr< RCanvas > Create(const std::string &title)
Create new canvas instance.
Definition RCanvas.cxx:103
void Update(bool async=false, CanvasCallback_t callback=nullptr)
update drawing
Definition RCanvas.cxx:77
void Hide()
Hide all canvas displays.
Definition RCanvas.cxx:180
std::unique_ptr< RDrawableReply > Process() override
Apply attributes changes to the drawable Return mask with actions which were really applied.
Definition RCanvas.cxx:315
TDirectory::TContext keeps track and restore the current directory.
Definition TDirectory.h:89
Describe directory structure in memory.
Definition TDirectory.h:45
virtual TList * GetList() const
Definition TDirectory.h:222
virtual void Add(TObject *obj)
Definition TList.h:81
Mother of all ROOT objects.
Definition TObject.h:41
const Int_t n
Definition legend1.C:16
std::vector< RIOSharedBase * > RIOSharedVector_t
Definition RDrawable.hxx:52
std::function< void(bool)> CanvasCallback_t
RLogChannel & GPadLog()
Log channel for GPad diagnostics.
Definition RAttrBase.cxx:17