Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RAttrBase.hxx
Go to the documentation of this file.
1 /*************************************************************************
2  * Copyright (C) 1995-2019, 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 #ifndef ROOT7_RAttrBase
10 #define ROOT7_RAttrBase
11 
12 #include <ROOT/RAttrMap.hxx>
13 #include <ROOT/RStyle.hxx>
14 #include <ROOT/RDrawable.hxx>
15 
16 namespace ROOT {
17 namespace Experimental {
18 
19 /** \class RAttrBase
20 \ingroup GpadROOT7
21 \author Sergey Linev <s.linev@gsi.de>
22 \date 2019-09-17
23 \brief Base class for all attributes, used with RDrawable
24 \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
25 */
26 
27 class RAttrBase {
28 
29  friend class RAttrMap;
30 
31  RDrawable *fDrawable{nullptr}; ///<! drawable used to store attributes
32  std::unique_ptr<RAttrMap> fOwnAttr; ///<! own instance when deep copy is created
33  std::string fPrefix; ///<! name prefix for all attributes values
34  RAttrBase *fParent{nullptr}; ///<! parent attributes, prefix applied to it
35 
36 protected:
37 
38  virtual const RAttrMap &GetDefaults() const;
39 
40  bool CopyValue(const std::string &name, const RAttrMap::Value_t &value, bool check_type = true);
41 
42  bool IsValueEqual(const std::string &name, const RAttrMap::Value_t &value, bool use_style = false) const;
43 
44  ///////////////////////////////////////////////////////////////////////////////
45 
46  void AssignDrawable(RDrawable *drawable, const std::string &prefix);
47 
48  void AssignParent(RAttrBase *parent, const std::string &prefix);
49 
50  struct Rec_t {
51  RAttrMap *attr{nullptr};
52  std::string fullname;
53  RDrawable *drawable{nullptr};
54  operator bool() const { return !!attr; }
55  };
56 
57  /// Find attributes container and full-qualified name for value
58  const Rec_t AccessAttr(const std::string &name) const
59  {
60  const RAttrBase *prnt = this;
61  std::string fullname = name;
62  while (prnt) {
63  fullname.insert(0, prnt->fPrefix); // fullname = prnt->fPrefix + fullname
64  if (prnt->fDrawable)
65  return {&(prnt->fDrawable->fAttr), fullname, prnt->fDrawable};
66  if (prnt->fOwnAttr)
67  return {prnt->fOwnAttr.get(), fullname, nullptr};
68  prnt = prnt->fParent;
69  }
70  return {nullptr, fullname, nullptr};
71  }
72 
73  struct Val_t {
74  const RAttrMap::Value_t *value{nullptr};
75  std::shared_ptr<RStyle> style;
76  operator bool() const { return !!value; }
77  };
78 
79  const Val_t AccessValue(const std::string &name, bool use_style = true) const
80  {
81  if (auto access = AccessAttr(name)) {
82  if (auto rec = access.attr->Find(access.fullname))
83  return {rec, nullptr};
84  if (access.drawable && use_style)
85  if (auto observe = access.drawable->fStyle.lock()) {
86  if (auto rec = observe->Eval(access.fullname, *access.drawable))
87  return {rec, observe};
88  }
89  }
90 
91  return {nullptr, nullptr};
92  }
93 
94  /// Ensure attribute with give name exists - creates container for attributes if required
95 
96  Rec_t EnsureAttr(const std::string &name)
97  {
98  auto prnt = this;
99  std::string fullname = name;
100  while (prnt) {
101  fullname.insert(0, prnt->fPrefix); // fullname = prnt->fPrefix + fullname
102  if (prnt->fDrawable)
103  return {&(prnt->fDrawable->fAttr), fullname, prnt->fDrawable};
104  if (!prnt->fParent && !prnt->fOwnAttr)
105  prnt->fOwnAttr = std::make_unique<RAttrMap>();
106  if (prnt->fOwnAttr)
107  return {prnt->fOwnAttr.get(), fullname, nullptr};
108  prnt = prnt->fParent;
109  }
110  return {nullptr, fullname, nullptr};
111  }
112 
113  /// Evaluate attribute value
114 
115  template <typename RET_TYPE,typename MATCH_TYPE = void>
116  auto Eval(const std::string &name, bool use_dflts = true) const
117  {
118  if (auto v = AccessValue(name, true))
119  return RAttrMap::Value_t::GetValue<RET_TYPE,MATCH_TYPE>(v.value);
120 
121  const RAttrMap::Value_t *rec = nullptr;
122 
123  if (use_dflts)
124  rec = GetDefaults().Find(name);
125 
126  return RAttrMap::Value_t::GetValue<RET_TYPE,MATCH_TYPE>(rec);
127  }
128 
129  void CopyTo(RAttrBase &tgt, bool use_style = true) const;
130 
131  bool IsSame(const RAttrBase &src, bool use_style = true) const;
132 
133  RAttrBase(RDrawable *drawable, const std::string &prefix) { AssignDrawable(drawable, prefix); }
134 
135  RAttrBase(RAttrBase *parent, const std::string &prefix) { AssignParent(parent, prefix); }
136 
137  RAttrBase(const RAttrBase &src) { src.CopyTo(*this); }
138 
139  RAttrBase &operator=(const RAttrBase &src)
140  {
141  Clear();
142  src.CopyTo(*this);
143  return *this;
144  }
145 
146  void SetValue(const std::string &name, bool value);
147  void SetValue(const std::string &name, double value);
148  void SetValue(const std::string &name, int value);
149  void SetValue(const std::string &name, const std::string &value);
150 
151  const std::string &GetPrefix() const { return fPrefix; }
152 
153  void ClearValue(const std::string &name);
154 
155  void Clear();
156 
157  template <typename T = void>
158  bool HasValue(const std::string &name, bool check_defaults = false) const
159  {
160  return Eval<const RAttrMap::Value_t *, T>(name, check_defaults) != nullptr;
161  }
162 
163  template <typename T>
164  T GetValue(const std::string &name) const
165  {
166  return Eval<T>(name);
167  }
168 
169 public:
170  RAttrBase() = default;
171 
172  virtual ~RAttrBase() = default;
173 
174  friend bool operator==(const RAttrBase& lhs, const RAttrBase& rhs){ return lhs.IsSame(rhs) && rhs.IsSame(lhs); }
175  friend bool operator!=(const RAttrBase& lhs, const RAttrBase& rhs){ return !lhs.IsSame(rhs) || !rhs.IsSame(lhs); }
176 };
177 
178 
179 } // namespace Experimental
180 } // namespace ROOT
181 
182 #define R__ATTR_CLASS(ClassName,dflt_prefix,dflt_values) \
183 protected: \
184 const RAttrMap &GetDefaults() const override \
185 { \
186  static auto dflts = RAttrMap().dflt_values; \
187  return dflts; \
188 } \
189 public: \
190  ClassName() = default; \
191  ClassName(RDrawable *drawable, const std::string &prefix = dflt_prefix) { AssignDrawable(drawable, prefix); } \
192  ClassName(RAttrBase *parent, const std::string &prefix = dflt_prefix) { AssignParent(parent, prefix); } \
193  ClassName(const ClassName &src) : ClassName() { src.CopyTo(*this); } \
194  ClassName(ClassName &&src) = default; \
195  ClassName &operator=(ClassName &&src) = default; \
196  ClassName &operator=(const ClassName &src) \
197  { \
198  Clear(); \
199  src.CopyTo(*this); \
200  return *this; \
201  }
202 
203 #endif