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