Logo ROOT  
Reference Guide
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;
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 *dummydir = new TDirectory("rcanvas_cleanup_dummydir","title");
115 dummydir->GetList()->Add(cleanup);
116 gROOT->GetListOfClosedObjects()->Add(dummydir);
117 }
118
119 return pCanvas;
120}
121
122//////////////////////////////////////////////////////////////////////////
123/// Create new display for the canvas
124/// The parameter `where` specifies which program could be used for display creation
125/// Possible values:
126///
127/// - `cef` Chromium Embeded Framework, local display, local communication
128/// - `qt5` Qt5 WebEngine (when running via rootqt5), local display, local communication
129/// - `browser` default system web-browser, communication via random http port from range 8800 - 9800
130/// - `<prog>` any program name which will be started instead of default browser, like firefox or /usr/bin/opera
131/// one could also specify $url in program name, which will be replaced with canvas URL
132/// - `native` either any available local display or default browser
133///
134/// Canvas can be displayed in several different places
135
136void ROOT::Experimental::RCanvas::Show(const std::string &where)
137{
138 fShown = true;
139
140 // workaround - in jupyter do not create any painters yet
141 if (gROOT->GetWebDisplay() == "jupyter") return;
142
143 if (fPainter) {
144 bool isany = (fPainter->NumDisplays() > 0);
145
146 if (!where.empty())
147 fPainter->NewDisplay(where);
148
149 if (isany) return;
150 }
151
152 if (!fModified)
153 fModified = 1; // 0 is special value, means no changes and no drawings
154
155 if (!fPainter)
157
158 if (fPainter) {
159 fPainter->NewDisplay(where);
160 fPainter->CanvasUpdated(fModified, true, nullptr); // trigger async display
161 }
162}
163
164//////////////////////////////////////////////////////////////////////////
165/// Returns window name for canvas
166
168{
169 if (fPainter)
170 return fPainter->GetWindowAddr();
171
172 return "";
173}
174
175
176//////////////////////////////////////////////////////////////////////////
177/// Hide all canvas displays
178
180{
181 if (fPainter)
182 delete fPainter.release();
183}
184
185//////////////////////////////////////////////////////////////////////////
186/// Create image file for the canvas
187/// Supported SVG (extension .svg), JPEG (extension .jpg or .jpeg), PNG (extension .png) or JSON (extension .json)
188
189bool ROOT::Experimental::RCanvas::SaveAs(const std::string &filename)
190{
191 if (!fPainter)
193
194 if (!fPainter)
195 return false;
196
197 int width = GetWidth();
198 int height = GetHeight();
199
200 return fPainter->ProduceBatchOutput(filename, width > 1 ? width : 800, height > 1 ? height : 600);
201}
202
203//////////////////////////////////////////////////////////////////////////
204/// Create JSON data for the canvas
205/// Can be used of offline display with JSROOT
206
208{
209 if (!fPainter)
211
212 if (!fPainter)
213 return "";
214
215 return fPainter->ProduceJSON();
216}
217
218//////////////////////////////////////////////////////////////////////////
219/// Remove canvas from global canvas lists, will be destroyed once last shared_ptr is disappear
220
222{
223 std::lock_guard<std::mutex> grd(GetHeldCanvasesMutex());
224 auto &held = GetHeldCanvases();
225 auto indx = held.size();
226 while (indx-- > 0) {
227 if (held[indx].get() == this)
228 held.erase(held.begin() + indx);
229 }
230}
231
232//////////////////////////////////////////////////////////////////////////
233/// Run canvas functionality for the given time (in seconds)
234/// Used to process canvas-related actions in the appropriate thread context.
235/// Must be regularly called when canvas created and used in extra thread.
236/// Time parameter specifies minimal execution time in seconds - if default value 0 is used,
237/// just all pending actions will be performed.
238/// When canvas is not yet displayed - just performs sleep for given time interval.
239///
240/// Example of usage:
241///
242/// ~~~ {.cpp}
243/// void draw_canvas(bool &run_loop, std::make_shared<RH1D> hist)
244/// {
245/// auto canvas = RCanvas::Create("Canvas title");
246/// canvas->Draw(hist)->SetLineColor(RColor::kBlue);
247/// canvas->Show();
248/// while (run_loop) {
249/// pHist->Fill(1);
250/// canvas->Modified();
251/// canvas->Update();
252/// canvas->Run(0.1); // process canvas events
253/// }
254///
255/// canvas->Remove();
256/// }
257///
258/// int main()
259/// {
260/// RAxisConfig xaxis(100, -10., 10.);
261/// auto pHist = std::make_shared<RH1D>(xaxis);
262/// bool run_loop = true;
263///
264/// std::thread thrd(draw_canvas, run_loop, pHist);
265/// std::this_thread::sleep_for(std::chrono::seconds(100));
266/// run_loop = false;
267/// thrd.join();
268/// return 0;
269/// }
270/// ~~~
271
273{
274 if (fPainter) {
275 fPainter->Run(tm);
276 } else if (tm>0) {
277 std::this_thread::sleep_for(std::chrono::milliseconds(int(tm*1000)));
278 }
279}
280
281//////////////////////////////////////////////////////////////////////////
282/// To resolve problem with storing of shared pointers
283/// Call this method when reading canvas from the file
284/// Can be called many times - after reinitialization of shared pointers no changes will be performed
285
287{
289
290 CollectShared(vect);
291
292 for (unsigned n = 0; n < vect.size(); ++n) {
293 if (vect[n]->HasShared() || !vect[n]->GetIOPtr()) continue;
294
295 auto shrd_ptr = vect[n]->MakeShared();
296
297 for (auto n2 = n+1; n2 < vect.size(); ++n2) {
298 if (vect[n2]->GetIOPtr() == vect[n]->GetIOPtr()) {
299 if (vect[n2]->HasShared())
300 R__LOG_ERROR(GPadLog()) << "FATAL Shared pointer for same IO ptr already exists";
301 else
302 vect[n2]->SetShared(shrd_ptr);
303 }
304 }
305
306 }
307}
308
309
310/////////////////////////////////////////////////////////////////////////////////////////////////
311/// Apply attributes changes to the drawable
312/// Return mask with actions which were really applied
313
314std::unique_ptr<ROOT::Experimental::RDrawableReply> ROOT::Experimental::RChangeAttrRequest::Process()
315{
316 // suppress all changes coming from non-main connection
317 if (!GetContext().IsMainConn())
318 return nullptr;
319
320 auto canv = const_cast<ROOT::Experimental::RCanvas *>(GetContext().GetCanvas());
321 if (!canv) return nullptr;
322
323 if ((ids.size() != names.size()) || (ids.size() != values.size())) {
324 R__LOG_ERROR(GPadLog()) << "Mismatch of arrays size in RChangeAttrRequest";
325 return nullptr;
326 }
327
328 Version_t vers = 0;
329
330 for(int indx = 0; indx < (int) ids.size(); indx++) {
331 if (ids[indx] == "canvas") {
332 if (canv->GetAttrMap().Change(names[indx], values[indx].get())) {
333 if (!vers) vers = canv->IncModified();
334 canv->SetDrawableVersion(vers);
335 }
336 } else {
337 auto drawable = canv->FindPrimitiveByDisplayId(ids[indx]);
338 if (drawable && drawable->GetAttrMap().Change(names[indx], values[indx].get())) {
339 if (!vers) vers = canv->IncModified();
340 drawable->SetDrawableVersion(vers);
341 }
342 }
343 }
344
345 fNeedUpdate = (vers > 0) && update;
346
347 return nullptr; // no need for any reply
348}
#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
Definition: TDocParser.cxx:121
#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:189
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:136
std::string GetWindowAddr() const
Returns window name used to display canvas.
Definition: RCanvas.cxx:167
void Remove()
Remove canvas from global canvas lists, will be destroyed when shared_ptr will be removed.
Definition: RCanvas.cxx:221
void ResolveSharedPtrs()
To resolve problem with storing of shared pointers Call this method when reading canvas from the file...
Definition: RCanvas.cxx:286
void Run(double tm=0.)
Run canvas functionality for given time (in seconds)
Definition: RCanvas.cxx:272
std::string CreateJSON()
Provide JSON which can be used for offline display.
Definition: RCanvas.cxx:207
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:179
std::unique_ptr< RDrawableReply > Process() override
Apply attributes changes to the drawable Return mask with actions which were really applied.
Definition: RCanvas.cxx:314
Describe directory structure in memory.
Definition: TDirectory.h:45
virtual TList * GetList() const
Definition: TDirectory.h:213
virtual void Add(TObject *obj)
Definition: TList.h:87
Mother of all ROOT objects.
Definition: TObject.h:37
const Int_t n
Definition: legend1.C:16
std::vector< RIOSharedBase * > RIOSharedVector_t
Definition: RDrawable.hxx:52
void swap(RDirectoryEntry &e1, RDirectoryEntry &e2) noexcept
std::function< void(bool)> CanvasCallback_t
RLogChannel & GPadLog()
Log channel for GPad diagnostics.
Definition: RAttrBase.cxx:17