Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
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 
23 ROOT::Experimental::RPadBase::~RPadBase() = default;
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 /// Method collect existing colors and assign new values if required
84 
85 void ROOT::Experimental::RPadBase::AssignAutoColors()
86 {
87  int cnt = 0;
88  RColor col;
89 
90  for (auto &drawable : fPrimitives) {
91  for (auto &attr: drawable->fAttr) {
92  // only boolean attribute can return true
93  if (!attr.second->GetBool()) continue;
94  auto pos = attr.first.rfind("_color_auto");
95  if ((pos > 0) && (pos == attr.first.length() - 11)) {
96  // FIXME: dummy code to assign autocolors, later should use RPalette
97  switch (cnt++ % 3) {
98  case 0: col = RColor::kRed; break;
99  case 1: col = RColor::kGreen; break;
100  case 2: col = RColor::kBlue; break;
101  }
102  drawable->fAttr.AddString(attr.first.substr(0,pos) + "_color_rgb", col.GetHex());
103  }
104  }
105  }
106 }
107 
108 ///////////////////////////////////////////////////////////////////////////
109 /// Create display items for all primitives in the pad
110 /// Each display item gets its special id, which used later for client-server communication
111 
112 void ROOT::Experimental::RPadBase::DisplayPrimitives(RPadBaseDisplayItem &paditem) const
113 {
114  paditem.SetAttributes(&GetAttrMap());
115  paditem.SetFrame(GetFrame());
116 
117  paditem.SetPadStyle(fStyle.lock());
118 
119  unsigned indx = 0;
120 
121  for (auto &drawable : fPrimitives) {
122  auto item = drawable->Display();
123  if (item) {
124  item->SetObjectIDAsPtr(drawable.get());
125  item->SetIndex(indx);
126  // add object with the style
127  paditem.Add(std::move(item), drawable->fStyle.lock());
128  }
129  ++indx;
130  }
131 }
132 
133 ///////////////////////////////////////////////////////////////////////////
134 /// Divide pad on nHoriz X nVert subpads
135 /// Return array of array of pads
136 
137 std::vector<std::vector<std::shared_ptr<ROOT::Experimental::RPad>>>
138 ROOT::Experimental::RPadBase::Divide(int nHoriz, int nVert, const RPadExtent &padding)
139 {
140  std::vector<std::vector<std::shared_ptr<RPad>>> ret;
141  if (!nHoriz)
142  R__ERROR_HERE("Gpad") << "Cannot divide into 0 horizontal sub-pads!";
143  if (!nVert)
144  R__ERROR_HERE("Gpad") << "Cannot divide into 0 vertical sub-pads!";
145  if (!nHoriz || !nVert)
146  return ret;
147 
148  // Start with the whole (sub-)pad:
149  RPadExtent offset{1._normal, 1._normal};
150  /// We need n Pads plus n-1 padding. Thus each `(subPadSize + padding)` is `(parentPadSize + padding) / n`.
151  offset = (offset + padding);
152  offset *= {1. / nHoriz, 1. / nVert};
153  const RPadExtent size = offset - padding;
154 
155  for (int iHoriz = 0; iHoriz < nHoriz; ++iHoriz) {
156  ret.emplace_back();
157  for (int iVert = 0; iVert < nVert; ++iVert) {
158  RPadPos subPos = offset;
159  subPos *= {1. * iHoriz, 1. * iVert};
160 
161  auto subpad = Draw<RPad>(this, subPos, size);
162 
163  ret.back().emplace_back(subpad);
164  // printf("Create subpad pos %5.2f %5.2f\n", subPos.fHoriz.fNormal.fVal, subPos.fVert.fNormal.fVal);
165  }
166  }
167  return ret;
168 }
169 
170 ROOT::Experimental::RFrame *ROOT::Experimental::RPadBase::GetOrCreateFrame()
171 {
172  CreateFrameIfNeeded();
173  return fFrame.get();
174 }
175 
176 void ROOT::Experimental::RPadBase::CreateFrameIfNeeded()
177 {
178  if (!fFrame)
179  fFrame = std::make_unique<ROOT::Experimental::RFrame>();
180 }
181 
182 
183 /////////////////////////////////////////////////////////////////////////////////////////////////
184 /// Get a pad axis from the RFrame.
185 /// \param dimension - Index of the dimension of the RFrame user coordinate system.
186 
187 ROOT::Experimental::RPadUserAxisBase* ROOT::Experimental::RPadBase::GetAxis(size_t dimension) const
188 {
189  if (fFrame && dimension < fFrame->GetNDimensions())
190  return &fFrame->GetUserAxis(dimension);
191  return nullptr;
192 }
193 
194 /////////////////////////////////////////////////////////////////////////////////////////////////
195 /// Get a pad axis from the RFrame.
196 /// \param dimension - Index of the dimension of the RFrame user coordinate system.
197 
198 ROOT::Experimental::RPadUserAxisBase* ROOT::Experimental::RPadBase::GetOrCreateAxis(size_t dimension)
199 {
200  GetOrCreateFrame()->GrowToDimensions(dimension);
201  return &fFrame->GetUserAxis(dimension);
202 }
203 
204 /////////////////////////////////////////////////////////////////////////////////////////////////
205 /// Set the range of an axis as begin, end.
206 
207 void ROOT::Experimental::RPadBase::SetAxisBounds(int dimension, double begin, double end)
208 {
209  GetOrCreateFrame()->GrowToDimensions(dimension);
210  GetAxis(dimension)->SetBounds(begin, end);
211 }
212 
213 /////////////////////////////////////////////////////////////////////////////////////////////////
214 /// Set the range of an axis as bound kind and bound (up or down).
215 
216 void ROOT::Experimental::RPadBase::SetAxisBound(int dimension, RPadUserAxisBase::EAxisBoundsKind boundsKind, double bound)
217 {
218  GetOrCreateFrame()->GrowToDimensions(dimension);
219  GetAxis(dimension)->SetBound(boundsKind, bound);
220 }
221 
222 /////////////////////////////////////////////////////////////////////////////////////////////////
223 /// Set the range of an axis as bound kind and bound (up or down).
224 
225 void ROOT::Experimental::RPadBase::SetAxisAutoBounds(int dimension)
226 {
227  GetOrCreateFrame()->GrowToDimensions(dimension);
228  GetAxis(dimension)->SetAutoBounds();
229 }
230 
231 /////////////////////////////////////////////////////////////////////////////////////////////////
232 /// Set the range of an axis as bound kind and bound (up or down).
233 
234 void ROOT::Experimental::RPadBase::SetAllAxisBounds(const std::vector<std::array<double, 2>> &vecBeginAndEnd)
235 {
236  GetOrCreateFrame()->GrowToDimensions(vecBeginAndEnd.size());
237  if (vecBeginAndEnd.size() != fFrame->GetNDimensions()) {
238  R__ERROR_HERE("Gpadv7")
239  << "Array of axis bound has wrong size " << vecBeginAndEnd.size()
240  << " versus numer of axes in frame " << fFrame->GetNDimensions();
241  return;
242  }
243 
244  for (size_t i = 0, n = fFrame->GetNDimensions(); i < n; ++i)
245  fFrame->GetUserAxis(i).SetBounds(vecBeginAndEnd[i][0], vecBeginAndEnd[i][1]);
246 }
247 
248 /////////////////////////////////////////////////////////////////////////////////////////////////
249 /// Set the range of an axis as bound kind and bound (up or down).
250 
251 void ROOT::Experimental::RPadBase::SetAllAxisBound(const std::vector<BoundKindAndValue> &vecBoundAndKind)
252 {
253  GetOrCreateFrame()->GrowToDimensions(vecBoundAndKind.size());
254  if (vecBoundAndKind.size() != fFrame->GetNDimensions()) {
255  R__ERROR_HERE("Gpadv7")
256  << "Array of axis bound has wrong size " << vecBoundAndKind.size()
257  << " versus numer of axes in frame " << fFrame->GetNDimensions();
258  return;
259  }
260 
261  for (size_t i = 0, n = fFrame->GetNDimensions(); i < n; ++i)
262  fFrame->GetUserAxis(i).SetBound(vecBoundAndKind[i].fKind, vecBoundAndKind[i].fBound);
263 }
264 
265 /////////////////////////////////////////////////////////////////////////////////////////////////
266 /// Collect all shared items to resolve shared_ptr after IO
267 
268 void ROOT::Experimental::RPadBase::CollectShared(Internal::RIOSharedVector_t &vect)
269 {
270  for (auto &handle : fPrimitives) {
271  vect.emplace_back(&handle);
272  auto drawable = handle.get();
273  if (drawable) drawable->CollectShared(vect);
274  }
275 }
276 
277 /////////////////////////////////////////////////////////////////////////////////////////////////
278 /// Set the range of an axis as bound kind and bound (up or down).
279 
280 void ROOT::Experimental::RPadBase::SetAllAxisAutoBounds()
281 {
282  for (size_t i = 0, n = GetOrCreateFrame()->GetNDimensions(); i < n; ++i)
283  fFrame->GetUserAxis(i).SetAutoBounds();
284 }