Logo ROOT  
Reference Guide
RPadBase.cxx
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (C) 1995-2017, 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/RPadBase.hxx"
10
11#include "ROOT/RLogger.hxx"
12#include "ROOT/RPadExtent.hxx"
13#include "ROOT/RPadPos.hxx"
14#include <ROOT/RPad.hxx>
15#include <ROOT/RCanvas.hxx>
17
18#include <cassert>
19#include <limits>
20
21using namespace std::string_literals;
22
24
25///////////////////////////////////////////////////////////////////////////
26/// Use provided style for pad and all primitives inside
27
28void ROOT::Experimental::RPadBase::UseStyle(const std::shared_ptr<RStyle> &style)
29{
31 for (auto &drawable : fPrimitives)
32 drawable->UseStyle(style);
33}
34
35///////////////////////////////////////////////////////////////////////////
36/// Find primitive with specified id
37
38std::shared_ptr<ROOT::Experimental::RDrawable> ROOT::Experimental::RPadBase::FindPrimitive(const std::string &id) const
39{
40 for (auto &drawable : fPrimitives) {
41
42 if (drawable->GetId() == id)
43 return drawable.get_shared();
44
45 const RPadBase *pad_draw = dynamic_cast<const RPadBase *> (drawable.get());
46
47 if (pad_draw) {
48 auto subelem = pad_draw->FindPrimitive(id);
49
50 if (subelem)
51 return subelem;
52 }
53 }
54
55 return nullptr;
56}
57
58///////////////////////////////////////////////////////////////////////////
59/// Find primitive with unique id, produce for RDisplayItem
60/// Such id used for client-server identification of objects
61
62std::shared_ptr<ROOT::Experimental::RDrawable> ROOT::Experimental::RPadBase::FindPrimitiveByDisplayId(const std::string &id) const
63{
64 auto p = id.find("_");
65 if (p == std::string::npos)
66 return nullptr;
67
68 auto prim = GetPrimitive(std::stoul(id.substr(0,p)));
69 if (!prim)
70 return nullptr;
71
72 auto subid = id.substr(p+1);
73
74 if (RDisplayItem::ObjectIDFromPtr(prim.get()) == subid)
75 return prim;
76
77 auto subpad = std::dynamic_pointer_cast<RPadBase>(prim);
78
79 return subpad ? subpad->FindPrimitiveByDisplayId(subid) : nullptr;
80}
81
82///////////////////////////////////////////////////////////////////////////
83/// Find subpad which contains primitive with given display id
84
86{
87 auto p = id.find("_");
88 if (p == std::string::npos)
89 return nullptr;
90
91 auto prim = GetPrimitive(std::stoul(id.substr(0,p)));
92 if (!prim)
93 return nullptr;
94
95 auto subid = id.substr(p+1);
96
97 if (RDisplayItem::ObjectIDFromPtr(prim.get()) == subid)
98 return this;
99
100 auto subpad = std::dynamic_pointer_cast<RPadBase>(prim);
101
102 return subpad ? subpad->FindPadForPrimitiveWithDisplayId(subid) : nullptr;
103}
104
105///////////////////////////////////////////////////////////////////////////
106/// Method collect existing colors and assign new values if required
107
109{
110 int cnt = 0;
111 RColor col;
112
113 for (auto &drawable : fPrimitives) {
114 for (auto &attr: drawable->fAttr) {
115 // only boolean attribute can return true
116 if (!attr.second->GetBool()) continue;
117 auto pos = attr.first.rfind("_color_auto");
118 if ((pos > 0) && (pos == attr.first.length() - 11)) {
119 // FIXME: dummy code to assign autocolors, later should use RPalette
120 switch (cnt++ % 3) {
121 case 0: col = RColor::kRed; break;
122 case 1: col = RColor::kGreen; break;
123 case 2: col = RColor::kBlue; break;
124 }
125 drawable->fAttr.AddString(attr.first.substr(0,pos) + "_color_rgb", col.AsHex());
126 }
127 }
128 }
129}
130
131///////////////////////////////////////////////////////////////////////////
132/// Create display items for all primitives in the pad
133/// Each display item gets its special id, which used later for client-server communication
134/// Second parameter is version id which already delivered to the client
135
137{
138 paditem.SetAttributes(&GetAttrMap());
139 paditem.SetPadStyle(fStyle.lock());
140
141 unsigned indx = 0;
142
143 for (auto &drawable : fPrimitives) {
144
145 ctxt.SetDrawable(drawable.get(), indx++);
146
147 auto item = drawable->Display(ctxt);
148
149 if (!item)
150 item = std::make_unique<RDisplayItem>(true);
151
152 item->SetObjectIDAsPtr(drawable.get());
153 item->SetIndex(ctxt.GetIndex());
154 // add object with the style
155 paditem.Add(std::move(item), drawable->fStyle.lock());
156 }
157}
158
159///////////////////////////////////////////////////////////////////////////
160/// Divide pad on nHoriz X nVert subpads
161/// Return array of array of pads
162
163std::vector<std::vector<std::shared_ptr<ROOT::Experimental::RPad>>>
164ROOT::Experimental::RPadBase::Divide(int nHoriz, int nVert, const RPadExtent &padding)
165{
166 std::vector<std::vector<std::shared_ptr<RPad>>> ret;
167 if (!nHoriz)
168 R__ERROR_HERE("Gpad") << "Cannot divide into 0 horizontal sub-pads!";
169 if (!nVert)
170 R__ERROR_HERE("Gpad") << "Cannot divide into 0 vertical sub-pads!";
171 if (!nHoriz || !nVert)
172 return ret;
173
174 // Start with the whole (sub-)pad:
175 RPadExtent offset{1._normal, 1._normal};
176 /// We need n Pads plus n-1 padding. Thus each `(subPadSize + padding)` is `(parentPadSize + padding) / n`.
177 offset = (offset + padding);
178 offset *= {1. / nHoriz, 1. / nVert};
179 const RPadExtent size = offset - padding;
180
181 for (int iHoriz = 0; iHoriz < nHoriz; ++iHoriz) {
182 ret.emplace_back();
183 for (int iVert = 0; iVert < nVert; ++iVert) {
184 RPadPos subPos = offset;
185 subPos *= {1. * iHoriz, 1. * iVert};
186
187 auto subpad = Draw<RPad>(this, subPos, size);
188
189 ret.back().emplace_back(subpad);
190 // printf("Create subpad pos %5.2f %5.2f\n", subPos.fHoriz.fNormal.fVal, subPos.fVert.fNormal.fVal);
191 }
192 }
193 return ret;
194}
195
196/////////////////////////////////////////////////////////////////////////////////////////////////
197/// Get a frame object for the pad.
198/// If frame not exists - creates and add to the end of primitives list
199
200
201std::shared_ptr<ROOT::Experimental::RFrame> ROOT::Experimental::RPadBase::GetOrCreateFrame()
202{
203 auto frame = GetFrame();
204 if (!frame) {
205 frame.reset(new RFrame());
206 fPrimitives.emplace_back(frame);
207 }
208
209 return frame;
210}
211
212/////////////////////////////////////////////////////////////////////////////////////////////////
213/// Get a frame object if exists
214
215const std::shared_ptr<ROOT::Experimental::RFrame> ROOT::Experimental::RPadBase::GetFrame() const
216{
217 for (auto &drawable : fPrimitives) {
218 if (drawable->GetCssType() == "frame") {
219 const std::shared_ptr<RFrame> frame = std::dynamic_pointer_cast<RFrame>(drawable.get_shared());
220 if (frame) return frame;
221 }
222 }
223 return nullptr;
224}
225
226/////////////////////////////////////////////////////////////////////////////////////////////////
227/// Get a frame object if exists
228
229std::shared_ptr<ROOT::Experimental::RFrame> ROOT::Experimental::RPadBase::GetFrame()
230{
231 for (auto &drawable : fPrimitives) {
232 if (drawable->GetCssType() == "frame") {
233 std::shared_ptr<RFrame> frame = std::dynamic_pointer_cast<RFrame>(drawable.get_shared());
234 if (frame) return frame;
235 }
236 }
237 return nullptr;
238}
239
240/////////////////////////////////////////////////////////////////////////////////////////////////
241/// Get a pad axis from the RFrame.
242/// \param dimension - Index of the dimension of the RFrame user coordinate system.
243
245{
246 auto frame = GetFrame();
247
248 if (frame && dimension < frame->GetNDimensions())
249 return &frame->GetUserAxis(dimension);
250 return nullptr;
251}
252
253/////////////////////////////////////////////////////////////////////////////////////////////////
254/// Get a pad axis from the RFrame.
255/// \param dimension - Index of the dimension of the RFrame user coordinate system.
256
258{
259 auto frame = GetOrCreateFrame();
260 frame->GrowToDimensions(dimension);
261 return &frame->GetUserAxis(dimension);
262}
263
264/////////////////////////////////////////////////////////////////////////////////////////////////
265/// Set the range of an axis as begin, end.
266
267void ROOT::Experimental::RPadBase::SetAxisBounds(int dimension, double begin, double end)
268{
269 GetOrCreateFrame()->GrowToDimensions(dimension);
270 GetAxis(dimension)->SetBounds(begin, end);
271}
272
273/////////////////////////////////////////////////////////////////////////////////////////////////
274/// Set the range of an axis as bound kind and bound (up or down).
275
277{
278 GetOrCreateFrame()->GrowToDimensions(dimension);
279 GetAxis(dimension)->SetBound(boundsKind, bound);
280}
281
282/////////////////////////////////////////////////////////////////////////////////////////////////
283/// Set the range of an axis as bound kind and bound (up or down).
284
286{
287 GetOrCreateFrame()->GrowToDimensions(dimension);
288 GetAxis(dimension)->SetAutoBounds();
289}
290
291/////////////////////////////////////////////////////////////////////////////////////////////////
292/// Set the range of an axis as bound kind and bound (up or down).
293
294void ROOT::Experimental::RPadBase::SetAllAxisBounds(const std::vector<std::array<double, 2>> &vecBeginAndEnd)
295{
296 auto frame = GetOrCreateFrame();
297
298 frame->GrowToDimensions(vecBeginAndEnd.size());
299 if (vecBeginAndEnd.size() != frame->GetNDimensions()) {
300 R__ERROR_HERE("Gpadv7")
301 << "Array of axis bound has wrong size " << vecBeginAndEnd.size()
302 << " versus numer of axes in frame " << frame->GetNDimensions();
303 return;
304 }
305
306 for (size_t i = 0, n = frame->GetNDimensions(); i < n; ++i)
307 frame->GetUserAxis(i).SetBounds(vecBeginAndEnd[i][0], vecBeginAndEnd[i][1]);
308}
309
310/////////////////////////////////////////////////////////////////////////////////////////////////
311/// Set the range of an axis as bound kind and bound (up or down).
312
313void ROOT::Experimental::RPadBase::SetAllAxisBound(const std::vector<BoundKindAndValue> &vecBoundAndKind)
314{
315 auto frame = GetOrCreateFrame();
316
317 frame->GrowToDimensions(vecBoundAndKind.size());
318 if (vecBoundAndKind.size() != frame->GetNDimensions()) {
319 R__ERROR_HERE("Gpadv7")
320 << "Array of axis bound has wrong size " << vecBoundAndKind.size()
321 << " versus numer of axes in frame " << frame->GetNDimensions();
322 return;
323 }
324
325 for (size_t i = 0, n = frame->GetNDimensions(); i < n; ++i)
326 frame->GetUserAxis(i).SetBound(vecBoundAndKind[i].fKind, vecBoundAndKind[i].fBound);
327}
328
329/////////////////////////////////////////////////////////////////////////////////////////////////
330/// Collect all shared items to resolve shared_ptr after IO
331
333{
334 for (auto &handle : fPrimitives) {
335 vect.emplace_back(&handle);
336 auto drawable = handle.get();
337 if (drawable) drawable->CollectShared(vect);
338 }
339}
340
341/////////////////////////////////////////////////////////////////////////////////////////////////
342/// Set the range of an axis as bound kind and bound (up or down).
343
345{
346 auto frame = GetOrCreateFrame();
347
348 for (size_t i = 0, n = frame->GetNDimensions(); i < n; ++i)
349 frame->GetUserAxis(i).SetAutoBounds();
350}
351
352/////////////////////////////////////////////////////////////////////////////////////////////////
353/// Convert user coordinates to normal coordinates.
354
355std::array<ROOT::Experimental::RPadLength::Normal, 2> ROOT::Experimental::RPadBase::UserToNormal(const std::array<RPadLength::User, 2> &pos) const
356{
357 auto frame = GetFrame();
358 if (!frame) return {};
359
360 return frame->UserToNormal(pos);
361}
362
363/////////////////////////////////////////////////////////////////////////////////////////////////
364/// Assign drawable version - for pad itself and all primitives
365
367{
369
370 for (auto &drawable : fPrimitives)
371 drawable->SetDrawableVersion(vers);
372}
#define R__ERROR_HERE(GROUP)
Definition: RLogger.hxx:183
The color class.
Definition: RColor.hxx:34
static constexpr RGB_t kRed
Definition: RColor.hxx:219
static constexpr RGB_t kGreen
Definition: RColor.hxx:207
static constexpr RGB_t kBlue
Definition: RColor.hxx:214
std::string AsHex(bool with_alpha=false) const
Returns color value in hex format like "66FF66" - without any prefix Alpha parameter can be optionall...
Definition: RColor.cxx:162
static std::string ObjectIDFromPtr(const void *ptr)
Construct fillid using pointer value.
void SetDrawable(RDrawable *dr, unsigned indx)
Set drawable and its index in list of primitives.
Definition: RDrawable.hxx:140
virtual void SetDrawableVersion(Version_t vers)
Definition: RDrawable.hxx:184
virtual void UseStyle(const std::shared_ptr< RStyle > &style)
Definition: RDrawable.hxx:200
Holds an area where drawing on user coordinate-system can be performed.
Definition: RFrame.hxx:40
void SetPadStyle(std::shared_ptr< RStyle > &&style)
Assign style for the pad.
void Add(std::unique_ptr< RDisplayItem > &&item, std::shared_ptr< RStyle > &&style)
Add display item and style which should be used for it.
Base class for graphic containers for RDrawable-s.
Definition: RPadBase.hxx:37
std::shared_ptr< RFrame > GetFrame()
Get a frame object if exists.
Definition: RPadBase.cxx:229
std::array< RPadLength::Normal, 2 > UserToNormal(const std::array< RPadLength::User, 2 > &pos) const
Convert user coordinates to normal coordinates.
Definition: RPadBase.cxx:355
std::shared_ptr< RFrame > GetOrCreateFrame()
Get a frame object for the pad.
Definition: RPadBase.cxx:201
void DisplayPrimitives(RPadBaseDisplayItem &paditem, RDisplayContext &ctxt)
Create display items for all primitives in the pad Each display item gets its special id,...
Definition: RPadBase.cxx:136
void UseStyle(const std::shared_ptr< RStyle > &style) override
Use provided style for pad and all primitives inside.
Definition: RPadBase.cxx:28
void CollectShared(Internal::RIOSharedVector_t &) override
Collect all shared items to resolve shared_ptr after IO.
Definition: RPadBase.cxx:332
std::vector< std::vector< std::shared_ptr< RPad > > > Divide(int nHoriz, int nVert, const RPadExtent &padding={})
Divide this pad into a grid of subpads with padding in between.
Definition: RPadBase.cxx:164
void SetAllAxisBound(const std::vector< BoundKindAndValue > &vecBoundAndKind)
Set the range of an axis as bound kind and bound (up or down).
Definition: RPadBase.cxx:313
void SetAxisBounds(int dimension, double begin, double end)
Set the range of an axis as begin, end.
Definition: RPadBase.cxx:267
void SetAllAxisAutoBounds()
Set the range of an axis as bound kind and bound (up or down).
Definition: RPadBase.cxx:344
void SetDrawableVersion(Version_t vers) override
Assign drawable version - for pad itself and all primitives.
Definition: RPadBase.cxx:366
void SetAxisBound(int dimension, RPadUserAxisBase::EAxisBoundsKind boundsKind, double bound)
Set the range of an axis as bound kind and bound (up or down).
Definition: RPadBase.cxx:276
std::vector< Primitive_t > fPrimitives
Content of the pad.
Definition: RPadBase.hxx:45
void SetAllAxisBounds(const std::vector< std::array< double, 2 > > &vecBeginAndEnd)
Set the range of an axis as bound kind and bound (up or down).
Definition: RPadBase.cxx:294
RPadUserAxisBase * GetAxis(size_t dimension) const
Get a pad axis from the RFrame.
Definition: RPadBase.cxx:244
void AssignAutoColors()
Method collect existing colors and assign new values if required.
Definition: RPadBase.cxx:108
RPadUserAxisBase * GetOrCreateAxis(size_t dimension)
Get a pad axis from the RFrame.
Definition: RPadBase.cxx:257
std::shared_ptr< RDrawable > FindPrimitiveByDisplayId(const std::string &display_id) const
Find primitive with unique id, produce for RDisplayItem Such id used for client-server identification...
Definition: RPadBase.cxx:62
void SetAxisAutoBounds(int dimension)
Set the range of an axis as bound kind and bound (up or down).
Definition: RPadBase.cxx:285
std::shared_ptr< RDrawable > FindPrimitive(const std::string &id) const
Find primitive with specified id.
Definition: RPadBase.cxx:38
const RPadBase * FindPadForPrimitiveWithDisplayId(const std::string &display_id) const
Find subpad which contains primitive with given display id.
Definition: RPadBase.cxx:85
An extent / size (horizontal and vertical) in a RPad.
Definition: RPadExtent.hxx:27
A position (horizontal and vertical) in a RPad.
Definition: RPadPos.hxx:28
Base class for user coordinates (e.g.
EAxisBoundsKind
Types of axis bounds to respect by the painter.
const Int_t n
Definition: legend1.C:16
std::vector< RIOSharedBase * > RIOSharedVector_t
Definition: RDrawable.hxx:51
const char * cnt
Definition: TXMLSetup.cxx:74
TCanvas * style()
Definition: style.C:1