Logo ROOT   6.12/07
Reference Guide
TDrawingAttrs.cxx
Go to the documentation of this file.
1 /// \file TDrawingOptsBase.cxx
2 /// \ingroup Gpad ROOT7
3 /// \author Axel Naumann <axel@cern.ch>
4 /// \date 2017-09-26
5 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6 /// is welcome!
7 
8 /*************************************************************************
9  * Copyright (C) 1995-2017, Rene Brun and Fons Rademakers. *
10  * All rights reserved. *
11  * *
12  * For the licensing terms see $ROOTSYS/LICENSE. *
13  * For the list of contributors see $ROOTSYS/README/CREDITS. *
14  *************************************************************************/
15 
16 #include "ROOT/TDrawingAttrs.hxx"
17 
18 #include "ROOT/TCanvas.hxx"
19 #include "ROOT/TColor.hxx"
20 #include "ROOT/TLogger.hxx"
21 
22 #include "TDrawingOptsReader.hxx" // in src/
23 
24 #include <algorithm>
25 #include <cassert>
26 #include <cstddef>
27 #include <unordered_map>
28 
29 using namespace ROOT::Experimental;
30 
31 namespace {
32 
33 /// The default attribute values for drawing options.
34 static Internal::TDrawingOptsReader::Attrs_t &GetDefaultAttrConfig()
35 {
37  return sDefaults;
38 }
39 
40 template <class PRIMITIVE>
41 using ParsedAttrs_t = std::unordered_map<std::string, TDrawingAttrRef<PRIMITIVE>>;
42 using AllParsedAttrs_t = std::tuple<ParsedAttrs_t<TColor>, ParsedAttrs_t<long long>, ParsedAttrs_t<double>>;
43 
44 static AllParsedAttrs_t &GetParsedDefaultAttrs()
45 {
46  static AllParsedAttrs_t sAllParsedAttrs;
47  return sAllParsedAttrs;
48 }
49 
50 static ParsedAttrs_t<TColor> &GetParsedDefaultAttrsOfAKind(TColor *)
51 {
52  return std::get<0>(GetParsedDefaultAttrs());
53 }
54 
55 static ParsedAttrs_t<long long> &GetParsedDefaultAttrsOfAKind(long long *)
56 {
57  return std::get<1>(GetParsedDefaultAttrs());
58 }
59 static ParsedAttrs_t<double> &GetParsedDefaultAttrsOfAKind(double *)
60 {
61  return std::get<2>(GetParsedDefaultAttrs());
62 }
63 
64 } // unnamed namespace
65 
66 template <class PRIMITIVE>
68  const PRIMITIVE &deflt, const std::vector<std::string_view> &optStrings)
69 {
70  std::string fullName = opts.GetName() + "." + attrName;
71  static constexpr PRIMITIVE *kNullPtr = (PRIMITIVE *)nullptr;
72  auto &parsedAttrs = GetParsedDefaultAttrsOfAKind(kNullPtr);
73  TCanvas &canv = opts.GetCanvas();
75  // We are a member of the default option object.
76  auto iIdx = parsedAttrs.find(fullName);
77  if (iIdx == parsedAttrs.end()) {
78  // We haven't read the default yet, do that now:
79  PRIMITIVE val = Internal::TDrawingOptsReader(GetDefaultAttrConfig()).Parse(fullName, deflt, optStrings);
80  fIdx = opts.Register(val);
81  parsedAttrs[fullName] = *this;
82  } else {
83  fIdx = opts.SameAs(iIdx->second);
84  }
85  } else {
86  auto &defCanv = static_cast<TCanvas &>(opts.GetDefaultCanvas(TStyle::GetCurrent()));
87  const auto &defaultTable = defCanv.GetAttrTable((PRIMITIVE *)nullptr);
88  PRIMITIVE val = defaultTable.Get(parsedAttrs[fullName]);
89  fIdx = opts.Register(val);
90  }
91 }
92 
93 namespace ROOT {
94 namespace Experimental {
95 template class TDrawingAttrRef<TColor>;
96 template class TDrawingAttrRef<long long>;
97 template class TDrawingAttrRef<double>;
98 } // namespace Experimental
99 } // namespace ROOT
100 
101 template <class PRIMITIVE>
103 {
104  if (fUseCount) {
105  R__ERROR_HERE("Gpad") << "Refusing to clear a referenced primitive (use count " << fUseCount << ")!";
106  return;
107  }
108  // destroy fVal:
109  fVal.~PRIMITIVE();
110 }
111 
112 template <class PRIMITIVE>
114 {
115  if (fUseCount) {
116  R__ERROR_HERE("Gpad") << "Refusing to create a primitive over an existing one (use count " << fUseCount << ")!";
117  return;
118  }
119  // copy-construct fVal:
120  new (&fVal) PRIMITIVE(val);
121  fUseCount = 1;
122 }
123 
124 template <class PRIMITIVE>
126 {
127  if (fUseCount == 0) {
128  R__ERROR_HERE("Gpad") << "Refusing to increase use count on a non-existing primitive!";
129  return;
130  }
131  ++fUseCount;
132 }
133 
134 template <class PRIMITIVE>
136 {
137  if (fUseCount == 0) {
138  R__ERROR_HERE("Gpad") << "Refusing to decrease use count on a non-existing primitive!";
139  return;
140  }
141  --fUseCount;
142  if (fUseCount == 0)
143  Clear();
144 }
145 
146 // Available specialization:
150 
151 template <class PRIMITIVE>
153 {
154  auto isFree = [](const value_type &el) -> bool { return el.IsFree(); };
155  auto iSlot = std::find_if(fTable.begin(), fTable.end(), isFree);
156  if (iSlot != fTable.end()) {
157  iSlot->Create(val);
158  std::ptrdiff_t offset = iSlot - fTable.begin();
159  assert(offset >= 0 && "This offset cannot possibly be negative!");
160  return TDrawingAttrRef<PRIMITIVE>{static_cast<size_t>(offset)};
161  }
162  fTable.emplace_back(val);
163  return TDrawingAttrRef<PRIMITIVE>{fTable.size() - 1};
164 }
165 
166 template <class PRIMITIVE>
168 {
169  if (&fTable.front().Get() > &val || &fTable.back().Get() < &val)
170  return TDrawingAttrRef<PRIMITIVE>{}; // not found.
171  std::ptrdiff_t offset = &val - &fTable.front().Get();
172  assert(offset >= 0 && "Logic error, how can offset be < 0?");
173  TDrawingAttrRef<PRIMITIVE> idx{static_cast<size_t>(offset)};
174  IncrUse(idx);
175  return TDrawingAttrRef<PRIMITIVE>{idx};
176 }
177 
178 // Provide specializations promised by the header:
182 
183 template <class PRIMITIVE>
186 {
187  fRefArray.push_back(canv.GetAttrTable((PRIMITIVE *)nullptr).Register(val));
188  return fRefArray.back();
189 }
190 
191 template <class PRIMITIVE>
194 {
195  canv.GetAttrTable((PRIMITIVE *)nullptr).IncrUse(idx);
196  return idx;
197 }
198 
199 template <class PRIMITIVE>
202 {
203  return canv.GetAttrTable((PRIMITIVE *)nullptr).SameAs(val);
204 }
205 
206 template <class PRIMITIVE>
208  const PRIMITIVE &val)
209 {
210  canv.GetAttrTable((PRIMITIVE *)nullptr).Update(idx, val);
211 }
212 
213 template <class PRIMITIVE>
215 {
216  for (auto idx: fRefArray)
217  canv.GetAttrTable((PRIMITIVE *)nullptr).DecrUse(idx);
218  fRefArray.clear();
219 }
220 
221 template <class PRIMITIVE>
223 {
224  for (auto idx: fRefArray)
225  canv.GetAttrTable((PRIMITIVE *)nullptr).IncrUse(idx);
226 }
227 
228 template <class PRIMITIVE>
230 {
231  return canv.GetAttrTable((PRIMITIVE *)nullptr).Get(idx);
232 }
233 
234 template <class PRIMITIVE>
236 {
237  return canv.GetAttrTable((PRIMITIVE *)nullptr).Get(idx);
238 }
239 
240 template <class PRIMITIVE>
242 {
243  if (!fRefArray.empty())
244  R__ERROR_HERE("Gpad") << "Drawing attributes table not empty - must call Release() before!";
245 }
246 
247 // Provide specializations promised by the header:
Internal::TDrawingAttrTable< TColor > & GetAttrTable(TColor *)
Attribute table (non-const access).
Definition: TCanvas.hxx:74
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
void IncrUse()
Increase the use count; use count must be >= 1 before (i.e. does not create or "resurrect" values)...
A window&#39;s topmost TPad.
Definition: TCanvas.hxx:39
void Create(const PRIMITIVE &val)
Create a value, initializing use count to 1.
TColor Parse(std::string_view attr, const TColor &deflt, std::vector< std::string_view >={})
Convenience overloads:
TDrawingAttrRef< PRIMITIVE > SameAs(TDrawingAttrRef< PRIMITIVE > idx)
static TStyle & GetCurrent()
Get the current TStyle.
Definition: TStyle.cxx:72
void RegisterCopy(TCanvas &canv)
Once copied, elements of a OptsAttrRefArr need to increase their use count.
std::unordered_map< std::string, std::string > Attrs_t
const PRIMITIVE & Get(TCanvas &canv, TDrawingAttrRef< PRIMITIVE > idx) const
Access to attribute (const version).
void Update(TCanvas &canv, TDrawingAttrRef< PRIMITIVE > idx, const PRIMITIVE &val)
Update the attribute at index idx to the value val.
TCanvas & GetCanvas()
The TCanvas holding the TDrawable (or its TPad) (non-const version).
static bool IsDefaultCanvas(const TPadBase &canv)
Whether the canvas is one of the canvases used to store attribute defaults.
void Release(TCanvas &canv)
Clear all attribute references, removing their uses in TCanvas.
void DecrUse()
Decrease the use count; use count must be >= 1 before the call. Calls Clear() if use count drops to 0...
const std::string & GetName() const
Get the (style config) name of this option set.
TDrawingAttrRef()=default
Construct an invalid reference.
void Clear()
Clear the value; use count must be 0.
TDrawingAttrRef< PRIMITIVE > Register(const PRIMITIVE &val)
Register an attribute with the table.
TDrawingAttrRef< PRIMITIVE > Register(const PRIMITIVE &val)
The TCanvas keep track of TColors, integer and floating point attributes used by the drawing options...
Definition: TCanvas.hxx:32
static TPadBase & GetDefaultCanvas(const TStyle &style)
Default attributes need to register their values in a pad - they will take this pad for default attri...
static Attrs_t ReadDefaults()
Reads the attribute config values from .rootstylerc.
TDrawingAttrRef< PRIMITIVE > Register(TCanvas &canv, const PRIMITIVE &val)
Register an attribute.
A color: Red|Green|Blue|Alpha, or a position in a TPalette.
Definition: TColor.hxx:27
TDrawingAttrRef< PRIMITIVE > SameAs(const PRIMITIVE &val)
Find the index belonging to the attribute at the given address and add a use.
TDrawingAttrRef< PRIMITIVE > SameAs(TCanvas &canv, TDrawingAttrRef< PRIMITIVE > idx)
Re-use an existing attribute.
#define R__ERROR_HERE(GROUP)
Definition: TLogger.hxx:126