Logo ROOT   6.14/05
Reference Guide
TPad.hxx
Go to the documentation of this file.
1 /// \file ROOT/TPad.hxx
2 /// \ingroup Gpad ROOT7
3 /// \author Axel Naumann <axel@cern.ch>
4 /// \date 2017-07-06
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 #ifndef ROOT7_TPad
17 #define ROOT7_TPad
18 
19 #include <memory>
20 #include <vector>
21 
22 #include "ROOT/TDrawable.hxx"
23 #include "ROOT/TDrawingAttr.hxx"
24 #include "ROOT/TDrawingOptsBase.hxx"
25 #include "ROOT/TFrame.hxx"
26 #include "ROOT/TPadExtent.hxx"
27 #include "ROOT/TPadPos.hxx"
28 #include "ROOT/TPadUserAxis.hxx"
29 #include "ROOT/TypeTraits.hxx"
30 
31 namespace ROOT {
32 namespace Experimental {
33 
34 class TPad;
35 class TCanvas;
36 
37 /** \class ROOT::Experimental::TPadBase
38  Base class for graphic containers for `TDrawable`-s.
39  */
40 
41 class TPadBase {
42 public:
43  using Primitives_t = std::vector<std::shared_ptr<TDrawable>>;
44 
45 private:
46  /// Content of the pad.
48 
49  /// TFrame with user coordinate system, if used by this pad.
50  std::unique_ptr<TFrame> fFrame;
51 
52  /// Disable copy construction.
53  TPadBase(const TPadBase &) = delete;
54 
55  /// Disable assignment.
56  TPadBase &operator=(const TPadBase &) = delete;
57 
58  void AssignUniqueID(std::shared_ptr<TDrawable> &ptr);
59 
60  /// Adds a `DRAWABLE` to `fPrimitives`, returning a `shared_ptr` to `DRAWABLE::GetOptions()`.
61  template <class DRAWABLE>
62  auto AddDrawable(std::shared_ptr<DRAWABLE> &&uPtr)
63  {
64  fPrimitives.emplace_back(std::move(uPtr));
65 
66  AssignUniqueID(fPrimitives.back());
67 
68  using Options_t = typename std::remove_reference<decltype(uPtr->GetOptions())>::type;
69  auto spDrawable = std::static_pointer_cast<DRAWABLE>(fPrimitives.back());
70  // Return a shared_ptr to the GetOptions() sub-object of the drawable inserted into fPrimitives,
71  // where the entry in fPrimitives defines the lifetime.
72  return std::shared_ptr<Options_t>(spDrawable, &spDrawable->GetOptions());
73  }
74 
75 protected:
76  /// Allow derived classes to default construct a TPadBase.
77  TPadBase() = default;
78 
79 public:
80  virtual ~TPadBase();
81 
82  /// Divide this pad into a grid of subpads with padding in between.
83  /// \param nHoriz Number of horizontal pads.
84  /// \param nVert Number of vertical pads.
85  /// \param padding Padding between pads.
86  /// \returns vector of vector (ret[x][y]) of created pads.
87  std::vector<std::vector<TPad *>> Divide(int nHoriz, int nVert, const TPadExtent &padding = {});
88 
89  /// Add something to be painted.
90  /// The pad observes what's lifetime through a weak pointer.
91  /// Drawing options will be constructed through `args`, which can be empty for default-constructed options.
92  template <class T, class... ARGS>
93  auto Draw(const std::shared_ptr<T> &what, ARGS... args)
94  {
95  // Requires GetDrawable(what) to be known!
96  return AddDrawable(GetDrawable(what, args...));
97  }
98 
99  /// Add something to be painted. The pad claims ownership.
100  /// Drawing options will be constructed through `args`, which can be empty for default-constructed options.
101  template <class T, class... ARGS>
102  auto Draw(std::unique_ptr<T> &&what, ARGS... args)
103  {
104  // Requires GetDrawable(what) to be known!
105  return AddDrawable(GetDrawable(std::move(what), args...));
106  }
107 
108  /// Add a copy of something to be painted.
109  /// Drawing options will be constructed through `args`, which can be empty for default-constructed options.
110  template <class T, class... ARGS, class = typename std::enable_if<!ROOT::TypeTraits::IsSmartOrDumbPtr<T>::value>::type>
111  auto Draw(const T &what, ARGS... args)
112  {
113  // Requires GetDrawable(what) to be known!
114  return Draw(std::make_unique<T>(what), args...);
115  }
116 
117  /// Remove an object from the list of primitives.
118  bool Remove(TDrawingOptsBase& opts) {
119  auto iter = std::find_if(fPrimitives.begin(), fPrimitives.end(),
120  [&opts](const std::shared_ptr<TDrawable>& drawable) { return &drawable->GetOptionsBase() == &opts; });
121  if (iter == fPrimitives.end())
122  return false;
123  iter->reset();
124  return true;
125  }
126 
127  std::shared_ptr<TDrawable> FindDrawable(const std::string &id) const;
128 
129  /// Wipe the pad by clearing the list of primitives.
130  void Wipe()
131  {
132  fPrimitives.clear();
133  }
134 
135  void CreateFrameIfNeeded();
136 
138  const TFrame *GetFrame() const { return fFrame.get(); }
139 
140  TPadUserAxisBase* GetOrCreateAxis(size_t dimension);
141  TPadUserAxisBase* GetAxis(size_t dimension) const;
142 
143  void SetAxisBounds(int dimension, double begin, double end);
144  void SetAxisBound(int dimension, TPadUserAxisBase::EAxisBoundsKind boundsKind, double bound);
145  void SetAxisAutoBounds(int dimension);
146 
147  void SetAllAxisBounds(const std::vector<std::array<double, 2>> &vecBeginAndEnd);
148 
149  /// Simple struct representing an axis bound.
152  double fBound = 0.;
153  };
154  void SetAllAxisBound(const std::vector<BoundKindAndValue> &vecBoundAndKind);
155  void SetAllAxisAutoBounds();
156 
157  /// Get the elements contained in the canvas.
158  const Primitives_t &GetPrimitives() const { return fPrimitives; }
159 
160  /// Convert a `Pixel` position to Canvas-normalized positions.
161  virtual std::array<TPadLength::Normal, 2> PixelsToNormal(const std::array<TPadLength::Pixel, 2> &pos) const = 0;
162 
163  /// Access to the top-most canvas, if any (const version).
164  virtual const TCanvas *GetCanvas() const = 0;
165 
166  /// Access to the top-most canvas, if any (non-const version).
167  virtual TCanvas *GetCanvas() = 0;
168 
169  /// Convert user coordinates to normal coordinates.
170  std::array<TPadLength::Normal, 2> UserToNormal(const std::array<TPadLength::User, 2> &pos) const
171  {
172  return fFrame->UserToNormal(pos);
173  }
174 };
175 
176 class TPadDrawable;
177 
178 /** \class ROOT::Experimental::TPad
179  Graphic container for `TDrawable`-s.
180  */
181 
182 class TPad: public TPadBase {
183 private:
184  /// Pad containing this pad as a sub-pad.
185  TPadBase *fParent = nullptr; /// The parent pad, if this pad has one.
186 
187  /// Size of the pad in the parent's (!) coordinate system.
188  TPadExtent fSize = {1._normal, 1._normal}; // {640_px, 400_px};
189 
190 public:
191  friend std::unique_ptr<TPadDrawable> GetDrawable(std::unique_ptr<TPad> &&pad);
192 
193  /// Create a topmost, non-paintable pad.
194  TPad() = default;
195 
196  /// Create a child pad.
197  TPad(TPadBase &parent, const TPadExtent &size): fParent(&parent), fSize(size) {}
198 
199  /// Destructor to have a vtable.
200  virtual ~TPad();
201 
202  /// Access to the parent pad (const version).
203  const TPadBase *GetParent() const { return fParent; }
204 
205  /// Access to the parent pad (non-const version).
206  TPadBase *GetParent() { return fParent; }
207 
208  /// Access to the top-most canvas (const version).
209  const TCanvas *GetCanvas() const override { return fParent ? fParent->GetCanvas() : nullptr; }
210 
211  /// Access to the top-most canvas (non-const version).
212  TCanvas *GetCanvas() override { return fParent ? fParent->GetCanvas() : nullptr; }
213 
214  /// Get the size of the pad in parent (!) coordinates.
215  const TPadExtent &GetSize() const { return fSize; }
216 
217  /// Convert a `Pixel` position to Canvas-normalized positions.
218  std::array<TPadLength::Normal, 2> PixelsToNormal(const std::array<TPadLength::Pixel, 2> &pos) const override
219  {
220  std::array<TPadLength::Normal, 2> posInParentNormal = fParent->PixelsToNormal(pos);
221  std::array<TPadLength::Normal, 2> myPixelInNormal =
222  fParent->PixelsToNormal({{fSize.fHoriz.fPixel, fSize.fVert.fPixel}});
223  std::array<TPadLength::Normal, 2> myUserInNormal =
224  fParent->UserToNormal({{fSize.fHoriz.fUser, fSize.fVert.fUser}});
225  // If the parent says pos is at 0.6 in normal coords, and our size converted to normal is 0.2, then pos in our
226  // coord system is 3.0!
227  return {{posInParentNormal[0] / (fSize.fHoriz.fNormal + myPixelInNormal[0] + myUserInNormal[0]),
228  posInParentNormal[1] / (fSize.fVert.fNormal + myPixelInNormal[1] + myUserInNormal[1])}};
229  }
230 
231  /// Convert a TPadPos to [x, y] of normalized coordinates.
232  std::array<TPadLength::Normal, 2> ToNormal(const Internal::TPadHorizVert &pos) const
233  {
234  std::array<TPadLength::Normal, 2> pixelsInNormal = PixelsToNormal({{pos.fHoriz.fPixel, pos.fVert.fPixel}});
235  std::array<TPadLength::Normal, 2> userInNormal = UserToNormal({{pos.fHoriz.fUser, pos.fVert.fUser}});
236  return {{pos.fHoriz.fNormal + pixelsInNormal[0] + userInNormal[0],
237  pos.fVert.fNormal + pixelsInNormal[1] + userInNormal[1]}};
238  }
239 };
240 
241 /** \class TPadDrawingOpts
242  Drawing options for a TPad
243  */
244 
245 class TPadDrawingOpts: public TDrawingOptsBase {
246  TDrawingAttr<TPadPos> fPos{*this, "PadOffset"}; ///< Offset with respect to parent TPad.
247 
248 public:
249  TPadDrawingOpts() = default;
250 
251  /// Construct the drawing options.
252  TPadDrawingOpts(const TPadPos& pos): fPos(*this, "PadOffset", pos) {}
253 
254  /// Set the position of this pad with respect to the parent pad.
256  {
257  fPos = pos;
258  return *this;
259  }
260 
261  TDrawingAttr<TPadPos> &GetOffset() { return fPos; }
262  const TDrawingAttr<TPadPos> &GetOffset() const { return fPos; }
263 };
264 
265 /** \class TPadDrawable
266  Draw a TPad, by drawing its contained graphical elements at the pad offset in the parent pad.'
267  */
268 class TPadDrawable: public TDrawableBase<TPadDrawable> {
269 private:
270  const std::shared_ptr<TPad> fPad; ///< The pad to be painted
271  TPadDrawingOpts fOpts; ///< The drawing options.
272 
273 public:
274  /// Move a sub-pad into this (i.e. parent's) list of drawables.
275  TPadDrawable(std::shared_ptr<TPad> pPad, const TPadDrawingOpts& opts = {});
276 
277  /// Paint primitives from the pad.
278  void Paint(Internal::TPadPainter &) final;
279 
280  TPad *Get() const { return fPad.get(); }
281 
282  /// Drawing options.
283  TPadDrawingOpts &GetOptions() { return fOpts; }
284 };
285 
286 template <class... ARGS>
287 inline std::shared_ptr<TPadDrawable> GetDrawable(std::unique_ptr<TPad> &&pad, ARGS... args)
288 {
289  return std::make_shared<TPadDrawable>(std::move(pad), TPadDrawingOpts(args...));
290 }
291 
292 template <class... ARGS>
293 inline std::shared_ptr<TPadDrawable> GetDrawable(const std::shared_ptr<TPad> &pad, ARGS... args)
294 {
295  return std::make_shared<TPadDrawable>(pad, TPadDrawingOpts(args...));
296 }
297 
298 } // namespace Experimental
299 } // namespace ROOT
300 
301 #endif
Draw a TPad, by drawing its contained graphical elements at the pad offset in the parent pad...
Definition: TPad.hxx:268
#define ARGS(alist)
Definition: gifencode.c:10
TPadUserAxisBase * GetOrCreateAxis(size_t dimension)
Get a pad axis from the TFrame.
Definition: TPad.cxx:129
std::vector< std::vector< TPad * > > Divide(int nHoriz, int nVert, const TPadExtent &padding={})
Divide this pad into a grid of subpads with padding in between.
Definition: TPad.cxx:65
TPadLength fVert
Vertical position.
Definition: TPadExtent.hxx:33
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
TPadUserAxisBase * GetAxis(size_t dimension) const
Get a pad axis from the TFrame.
Definition: TPad.cxx:118
double T(double x)
Definition: ChebyshevPol.h:34
A window&#39;s topmost TPad.
Definition: TCanvas.hxx:33
virtual const TCanvas * GetCanvas() const =0
Access to the top-most canvas, if any (const version).
Drawing options for a TPad.
Definition: TPad.hxx:245
TPad(TPadBase &parent, const TPadExtent &size)
Create a child pad.
Definition: TPad.hxx:197
no defined axis range; the painter will decide
std::shared_ptr< TDrawable > FindDrawable(const std::string &id) const
Definition: TPad.cxx:44
TPadBase & operator=(const TPadBase &)=delete
Disable assignment.
TPadDrawingOpts & At(const TPadPos &pos)
Set the position of this pad with respect to the parent pad.
Definition: TPad.hxx:255
auto Draw(std::unique_ptr< T > &&what, ARGS... args)
Add something to be painted.
Definition: TPad.hxx:102
TCanvas * GetCanvas() override
Access to the top-most canvas (non-const version).
Definition: TPad.hxx:212
void SetAllAxisBound(const std::vector< BoundKindAndValue > &vecBoundAndKind)
Set the range of an axis as bound kind and bound (up or down).
Definition: TPad.cxx:182
TPadLength fHoriz
Horizontal position.
Definition: TPadExtent.hxx:32
std::unique_ptr< TFrame > fFrame
TFrame with user coordinate system, if used by this pad.
Definition: TPad.hxx:50
TPadBase * GetParent()
Access to the parent pad (non-const version).
Definition: TPad.hxx:206
Pixel fPixel
The pixel coordinate summand.
Definition: TPadLength.hxx:99
const TDrawingAttr< TPadPos > & GetOffset() const
Definition: TPad.hxx:262
void Wipe()
Wipe the pad by clearing the list of primitives.
Definition: TPad.hxx:130
const TPadExtent & GetSize() const
Get the size of the pad in parent (!) coordinates.
Definition: TPad.hxx:215
auto Draw(const T &what, ARGS... args)
Add a copy of something to be painted.
Definition: TPad.hxx:111
Primitives_t fPrimitives
Content of the pad.
Definition: TPad.hxx:47
A position (horizontal and vertical) in a TPad.
Definition: TPadPos.hxx:27
Base class for graphic containers for TDrawable-s.
Definition: TPad.hxx:41
void AssignUniqueID(std::shared_ptr< TDrawable > &ptr)
Definition: TPad.cxx:30
Simple struct representing an axis bound.
Definition: TPad.hxx:150
const TPadBase * GetParent() const
Access to the parent pad (const version).
Definition: TPad.hxx:203
const Primitives_t & GetPrimitives() const
Get the elements contained in the canvas.
Definition: TPad.hxx:158
Normal fNormal
The normalized coordinate summand.
Definition: TPadLength.hxx:96
const std::shared_ptr< TPad > fPad
The pad to be painted.
Definition: TPad.hxx:270
TPadUserAxisBase::EAxisBoundsKind fKind
Definition: TPad.hxx:151
const TCanvas * GetCanvas() const override
Access to the top-most canvas (const version).
Definition: TPad.hxx:209
The most important graphics class in the ROOT system.
Definition: TPad.h:29
TPadDrawingOpts(const TPadPos &pos)
Construct the drawing options.
Definition: TPad.hxx:252
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: TPad.cxx:165
TFrame * GetOrCreateFrame()
Definition: TPad.cxx:100
EAxisBoundsKind
Types of axis bounds to respect by the painter.
void SetAxisAutoBounds(int dimension)
Set the range of an axis as bound kind and bound (up or down).
Definition: TPad.cxx:156
std::array< TPadLength::Normal, 2 > ToNormal(const Internal::TPadHorizVert &pos) const
Convert a TPadPos to [x, y] of normalized coordinates.
Definition: TPad.hxx:232
void SetAxisBound(int dimension, TPadUserAxisBase::EAxisBoundsKind boundsKind, double bound)
Set the range of an axis as bound kind and bound (up or down).
Definition: TPad.cxx:147
TPadDrawingOpts & GetOptions()
Drawing options.
Definition: TPad.hxx:283
Abstract interface for object painting on the pad/canvas.
Definition: TPadPainter.hxx:37
std::vector< std::shared_ptr< TDrawable > > Primitives_t
Definition: TPad.hxx:43
Holds a user coordinate system with a palette.
Definition: TFrame.hxx:35
The Canvas class.
Definition: TCanvas.h:31
std::shared_ptr< TPadDrawable > GetDrawable(std::unique_ptr< TPad > &&pad, ARGS... args)
Definition: TPad.hxx:287
int type
Definition: TGX11.cxx:120
TDrawingAttr< TPadPos > & GetOffset()
Definition: TPad.hxx:261
void SetAllAxisAutoBounds()
Set the range of an axis as bound kind and bound (up or down).
Definition: TPad.cxx:199
An extent / size (horizontal and vertical) in a TPad.
Definition: TPadExtent.hxx:44
std::array< TPadLength::Normal, 2 > PixelsToNormal(const std::array< TPadLength::Pixel, 2 > &pos) const override
Convert a Pixel position to Canvas-normalized positions.
Definition: TPad.hxx:218
TPadBase()=default
Allow derived classes to default construct a TPadBase.
auto AddDrawable(std::shared_ptr< DRAWABLE > &&uPtr)
Adds a DRAWABLE to fPrimitives, returning a shared_ptr to DRAWABLE::GetOptions(). ...
Definition: TPad.hxx:62
User fUser
The user coordinate summand.
Definition: TPadLength.hxx:102
const TFrame * GetFrame() const
Definition: TPad.hxx:138
std::array< TPadLength::Normal, 2 > UserToNormal(const std::array< TPadLength::User, 2 > &pos) const
Convert user coordinates to normal coordinates.
Definition: TPad.hxx:170
void SetAxisBounds(int dimension, double begin, double end)
Set the range of an axis as begin, end.
Definition: TPad.cxx:138
Graphic container for TDrawable-s.
Definition: TPad.hxx:182
TPadDrawingOpts fOpts
The drawing options.
Definition: TPad.hxx:271
virtual std::array< TPadLength::Normal, 2 > PixelsToNormal(const std::array< TPadLength::Pixel, 2 > &pos) const =0
Convert a Pixel position to Canvas-normalized positions.
A 2D (horizontal and vertical) combination of TPadLengths.
Definition: TPadExtent.hxx:31
auto Draw(const std::shared_ptr< T > &what, ARGS... args)
Add something to be painted.
Definition: TPad.hxx:93
bool Remove(TDrawingOptsBase &opts)
Remove an object from the list of primitives.
Definition: TPad.hxx:118