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
86 static RCanvasCleanup *gInstance;
87
88 RCanvasCleanup() : TObject() { gInstance = this; }
89
90 virtual ~RCanvasCleanup()
91 {
92 gInstance = nullptr;
94 }
95};
96
97RCanvasCleanup *RCanvasCleanup::gInstance = nullptr;
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
112 if (!RCanvasCleanup::gInstance) {
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 if (fPainter) {
139 bool isany = (fPainter->NumDisplays() > 0);
140
141 if (!where.empty())
142 fPainter->NewDisplay(where);
143
144 if (isany) return;
145 }
146
147 if (!fModified)
148 fModified = 1; // 0 is special value, means no changes and no drawings
149
150 if (!fPainter)
152
153 if (fPainter) {
154 fPainter->NewDisplay(where);
155 fPainter->CanvasUpdated(fModified, true, nullptr); // trigger async display
156 }
157}
158
159//////////////////////////////////////////////////////////////////////////
160/// Returns window name for canvas
161
163{
164 if (fPainter)
165 return fPainter->GetWindowAddr();
166
167 return "";
168}
169
170
171//////////////////////////////////////////////////////////////////////////
172/// Hide all canvas displays
173
175{
176 if (fPainter)
177 delete fPainter.release();
178}
179
180//////////////////////////////////////////////////////////////////////////
181/// Create image file for the canvas
182/// Supported SVG (extension .svg), JPEG (extension .jpg or .jpeg) and PNG (extension .png)
183
184bool ROOT::Experimental::RCanvas::SaveAs(const std::string &filename)
185{
186 if (!fPainter)
188
189 if (!fPainter)
190 return false;
191
192 auto width = fSize[0].fVal;
193 auto height = fSize[1].fVal;
194
195 return fPainter->ProduceBatchOutput(filename, width > 1 ? (int) width : 800, height > 1 ? (int) height : 600);
196}
197
198//////////////////////////////////////////////////////////////////////////
199/// Remove canvas from global canvas lists, will be destroyed once last shared_ptr is disappear
200
202{
203 std::lock_guard<std::mutex> grd(GetHeldCanvasesMutex());
204 auto &held = GetHeldCanvases();
205 auto indx = held.size();
206 while (indx-- > 0) {
207 if (held[indx].get() == this)
208 held.erase(held.begin() + indx);
209 }
210}
211
212//////////////////////////////////////////////////////////////////////////
213/// Run canvas functionality for the given time (in seconds)
214/// Used to process canvas-related actions in the appropriate thread context.
215/// Must be regularly called when canvas created and used in extra thread.
216/// Time parameter specifies minimal execution time in seconds - if default value 0 is used,
217/// just all pending actions will be performed.
218/// When canvas is not yet displayed - just performs sleep for given time interval.
219///
220/// Example of usage:
221///
222/// ~~~ {.cpp}
223/// void draw_canvas(bool &run_loop, std::make_shared<RH1D> hist)
224/// {
225/// auto canvas = RCanvas::Create("Canvas title");
226/// canvas->Draw(hist)->SetLineColor(RColor::kBlue);
227/// canvas->Show();
228/// while (run_loop) {
229/// pHist->Fill(1);
230/// canvas->Modified();
231/// canvas->Update();
232/// canvas->Run(0.1); // process canvas events
233/// }
234///
235/// canvas->Remove();
236/// }
237///
238/// int main()
239/// {
240/// RAxisConfig xaxis(100, -10., 10.);
241/// auto pHist = std::make_shared<RH1D>(xaxis);
242/// bool run_loop = true;
243///
244/// std::thread thrd(draw_canvas, run_loop, pHist);
245/// std::this_thread::sleep_for(std::chrono::seconds(100));
246/// run_loop = false;
247/// thrd.join();
248/// return 0;
249/// }
250/// ~~~
251
253{
254 if (fPainter) {
255 fPainter->Run(tm);
256 } else if (tm>0) {
257 std::this_thread::sleep_for(std::chrono::milliseconds(int(tm*1000)));
258 }
259}
260
261//////////////////////////////////////////////////////////////////////////
262/// To resolve problem with storing of shared pointers
263/// Call this method when reading canvas from the file
264/// Can be called many times - after reinitialization of shared pointers no changes will be performed
265
267{
269
270 CollectShared(vect);
271
272 for (unsigned n = 0; n < vect.size(); ++n) {
273 if (vect[n]->HasShared() || !vect[n]->GetIOPtr()) continue;
274
275 auto shrd_ptr = vect[n]->MakeShared();
276
277 for (auto n2 = n+1; n2 < vect.size(); ++n2) {
278 if (vect[n2]->GetIOPtr() == vect[n]->GetIOPtr()) {
279 if (vect[n2]->HasShared())
280 R__LOG_ERROR(GPadLog()) << "FATAL Shared pointer for same IO ptr already exists";
281 else
282 vect[n2]->SetShared(shrd_ptr);
283 }
284 }
285
286 }
287}
288
289
290/////////////////////////////////////////////////////////////////////////////////////////////////
291/// Apply attributes changes to the drawable
292/// Return mask with actions which were really applied
293
294std::unique_ptr<ROOT::Experimental::RDrawableReply> ROOT::Experimental::RChangeAttrRequest::Process()
295{
296 // suppress all changes coming from non-main connection
297 if (!GetContext().IsMainConn())
298 return nullptr;
299
300 auto canv = const_cast<ROOT::Experimental::RCanvas *>(GetContext().GetCanvas());
301 if (!canv) return nullptr;
302
303 if ((ids.size() != names.size()) || (ids.size() != values.size())) {
304 R__LOG_ERROR(GPadLog()) << "Mismatch of arrays size in RChangeAttrRequest";
305 return nullptr;
306 }
307
308 Version_t vers = 0;
309
310 for(int indx = 0; indx < (int) ids.size(); indx++) {
311 if (ids[indx] == "canvas") {
312 if (canv->GetAttrMap().Change(names[indx], values[indx].get())) {
313 if (!vers) vers = canv->IncModified();
314 canv->SetDrawableVersion(vers);
315 }
316 } else {
317 auto drawable = canv->FindPrimitiveByDisplayId(ids[indx]);
318 if (drawable && drawable->GetAttrMap().Change(names[indx], values[indx].get())) {
319 if (!vers) vers = canv->IncModified();
320 drawable->SetDrawableVersion(vers);
321 }
322 }
323 }
324
325 fNeedUpdate = (vers > 0) && update;
326
327 return nullptr; // no need for any reply
328}
size_t fSize
#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:406
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:184
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:162
void Remove()
Remove canvas from global canvas lists, will be destroyed when shared_ptr will be removed.
Definition RCanvas.cxx:201
void ResolveSharedPtrs()
To resolve problem with storing of shared pointers Call this method when reading canvas from the file...
Definition RCanvas.cxx:266
void Run(double tm=0.)
Run canvas functionality for given time (in seconds)
Definition RCanvas.cxx:252
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:174
std::unique_ptr< RDrawableReply > Process() override
Apply attributes changes to the drawable Return mask with actions which were really applied.
Definition RCanvas.cxx:294
Describe directory structure in memory.
Definition TDirectory.h:45
virtual TList * GetList() const
Definition TDirectory.h:176
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
std::function< void(bool)> CanvasCallback_t
RLogChannel & GPadLog()
Log channel for GPad diagnostics.
Definition RAttrBase.cxx:19