Logo ROOT   master
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>
16 #include <ROOT/RPadDisplayItem.hxx>
17 
18 #include <cassert>
19 #include <limits>
20 
21 using namespace std::string_literals;
22 
24 
25 ///////////////////////////////////////////////////////////////////////////
26 /// Use provided style for pad and all primitives inside
27 
28 void ROOT::Experimental::RPadBase::UseStyle(const std::shared_ptr<RStyle> &style)
29 {
30  RDrawable::UseStyle(style);
31  for (auto &drawable : fPrimitives)
32  drawable->UseStyle(style);
33 }
34 
35 ///////////////////////////////////////////////////////////////////////////
36 /// Find primitive with specified id
37 
38 std::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 
62 std::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 
163 std::vector<std::vector<std::shared_ptr<ROOT::Experimental::RPad>>>
164 ROOT::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 
201 std::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 
215 const 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 
229 std::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 
267 void 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 
294 void 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 
313 void 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 
355 std::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 {
368  RDrawable::SetDrawableVersion(vers);
369 
370  for (auto &drawable : fPrimitives)
371  drawable->SetDrawableVersion(vers);
372 }
std::shared_ptr< RDrawable > FindPrimitive(const std::string &id) const
Find primitive with specified id.
Definition: RPadBase.cxx:38
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
Definition: Rtypes.h:64
Base class for user coordinates (e.g.
std::shared_ptr< RFrame > GetOrCreateFrame()
Get a frame object for the pad.
Definition: RPadBase.cxx:201
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
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
Definition: Rtypes.h:64
void SetDrawableVersion(Version_t vers) override
Assign drawable version - for pad itself and all primitives.
Definition: RPadBase.cxx:366
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
void CollectShared(Internal::RIOSharedVector_t &) override
Collect all shared items to resolve shared_ptr after IO.
Definition: RPadBase.cxx:332
void SetPadStyle(std::shared_ptr< RStyle > &&style)
Assign style for the pad.
Holds an area where drawing on user coordinate-system can be performed.
Definition: RFrame.hxx:40
void SetDrawable(RDrawable *dr, unsigned indx)
Set drawable and its index in list of primitives.
Definition: RDrawable.hxx:140
EAxisBoundsKind
Types of axis bounds to respect by the painter.
XFontStruct * id
Definition: TGX11.cxx:108
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
std::vector< RIOSharedBase * > RIOSharedVector_t
Definition: RDrawable.hxx:51
void AssignAutoColors()
Method collect existing colors and assign new values if required.
Definition: RPadBase.cxx:108
The color class.
Definition: RColor.hxx:34
std::shared_ptr< RFrame > GetFrame()
Get a frame object if exists.
Definition: RPadBase.cxx:229
RPadUserAxisBase * GetAxis(size_t dimension) const
Get a pad axis from the RFrame.
Definition: RPadBase.cxx:244
void SetAxisAutoBounds(int dimension)
Set the range of an axis as bound kind and bound (up or down).
Definition: RPadBase.cxx:285
void SetAxisBounds(int dimension, double begin, double end)
Set the range of an axis as begin, end.
Definition: RPadBase.cxx:267
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
TCanvas * style()
Definition: style.C:1
std::array< RPadLength::Normal, 2 > UserToNormal(const std::array< RPadLength::User, 2 > &pos) const
Convert user coordinates to normal coordinates.
Definition: RPadBase.cxx:355
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
A position (horizontal and vertical) in a RPad.
Definition: RPadPos.hxx:28
void UseStyle(const std::shared_ptr< RStyle > &style) override
Use provided style for pad and all primitives inside.
Definition: RPadBase.cxx:28
void SetAllAxisAutoBounds()
Set the range of an axis as bound kind and bound (up or down).
Definition: RPadBase.cxx:344
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
Definition: Rtypes.h:64
#define R__ERROR_HERE(GROUP)
Definition: RLogger.hxx:183
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
const Int_t n
Definition: legend1.C:16
const char * cnt
Definition: TXMLSetup.cxx:75