Logo ROOT   6.16/01
Reference Guide
RPad.hxx
Go to the documentation of this file.
1/// \file ROOT/RPad.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_RPad
17#define ROOT7_RPad
18
19#include <memory>
20#include <vector>
21
22#include "ROOT/RDrawable.hxx"
23#include "ROOT/RDrawingAttr.hxx"
24#include "ROOT/RDrawingOptsBase.hxx"
25#include "ROOT/RFrame.hxx"
26#include "ROOT/RPadExtent.hxx"
27#include "ROOT/RPadPos.hxx"
28#include "ROOT/RPadUserAxis.hxx"
29#include "ROOT/TypeTraits.hxx"
30
31namespace ROOT {
32namespace Experimental {
33
34class RPad;
35class RCanvas;
36
37/** \class ROOT::Experimental::RPadBase
38 Base class for graphic containers for `RDrawable`-s.
39 */
40
41class RPadBase {
42public:
43 using Primitives_t = std::vector<std::shared_ptr<RDrawable>>;
44
45private:
46 /// Content of the pad.
48
49 /// RFrame with user coordinate system, if used by this pad.
50 std::unique_ptr<RFrame> fFrame;
51
52 /// Disable copy construction.
53 RPadBase(const RPadBase &) = delete;
54
55 /// Disable assignment.
56 RPadBase &operator=(const RPadBase &) = delete;
57
58 void AssignUniqueID(std::shared_ptr<RDrawable> &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
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
75protected:
76 /// Allow derived classes to default construct a RPadBase.
77 RPadBase() = default;
78
79public:
80 virtual ~RPadBase();
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<RPad *>> Divide(int nHoriz, int nVert, const RPadExtent &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(RDrawingOptsBase& opts) {
119 auto iter = std::find_if(fPrimitives.begin(), fPrimitives.end(),
120 [&opts](const std::shared_ptr<RDrawable>& 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<RDrawable> 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 RFrame *GetFrame() const { return fFrame.get(); }
139
140 RPadUserAxisBase* GetOrCreateAxis(size_t dimension);
141 RPadUserAxisBase* GetAxis(size_t dimension) const;
142
143 void SetAxisBounds(int dimension, double begin, double end);
144 void SetAxisBound(int dimension, RPadUserAxisBase::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);
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<RPadLength::Normal, 2> PixelsToNormal(const std::array<RPadLength::Pixel, 2> &pos) const = 0;
162
163 /// Access to the top-most canvas, if any (const version).
164 virtual const RCanvas *GetCanvas() const = 0;
165
166 /// Access to the top-most canvas, if any (non-const version).
167 virtual RCanvas *GetCanvas() = 0;
168
169 /// Convert user coordinates to normal coordinates.
170 std::array<RPadLength::Normal, 2> UserToNormal(const std::array<RPadLength::User, 2> &pos) const
171 {
172 return fFrame->UserToNormal(pos);
173 }
174};
175
176class RPadDrawable;
177
178/** \class ROOT::Experimental::RPad
179 Graphic container for `RDrawable`-s.
180 */
181
182class RPad: public RPadBase {
183private:
184 /// Pad containing this pad as a sub-pad.
185 RPadBase *fParent = nullptr; /// The parent pad, if this pad has one.
186
187 /// Size of the pad in the parent's (!) coordinate system.
188 RPadExtent fSize = {1._normal, 1._normal}; // {640_px, 400_px};
189
190public:
191 friend std::unique_ptr<RPadDrawable> GetDrawable(std::unique_ptr<RPad> &&pad);
192
193 /// Create a topmost, non-paintable pad.
194 RPad() = default;
195
196 /// Create a child pad.
197 RPad(RPadBase &parent, const RPadExtent &size): fParent(&parent), fSize(size) {}
198
199 /// Destructor to have a vtable.
200 virtual ~RPad();
201
202 /// Access to the parent pad (const version).
203 const RPadBase *GetParent() const { return fParent; }
204
205 /// Access to the parent pad (non-const version).
207
208 /// Access to the top-most canvas (const version).
209 const RCanvas *GetCanvas() const override { return fParent ? fParent->GetCanvas() : nullptr; }
210
211 /// Access to the top-most canvas (non-const version).
212 RCanvas *GetCanvas() override { return fParent ? fParent->GetCanvas() : nullptr; }
213
214 /// Get the size of the pad in parent (!) coordinates.
215 const RPadExtent &GetSize() const { return fSize; }
216
217 /// Convert a `Pixel` position to Canvas-normalized positions.
218 std::array<RPadLength::Normal, 2> PixelsToNormal(const std::array<RPadLength::Pixel, 2> &pos) const override
219 {
220 std::array<RPadLength::Normal, 2> posInParentNormal = fParent->PixelsToNormal(pos);
221 std::array<RPadLength::Normal, 2> myPixelInNormal =
223 std::array<RPadLength::Normal, 2> myUserInNormal =
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 RPadPos to [x, y] of normalized coordinates.
232 std::array<RPadLength::Normal, 2> ToNormal(const Internal::RPadHorizVert &pos) const
233 {
234 std::array<RPadLength::Normal, 2> pixelsInNormal = PixelsToNormal({{pos.fHoriz.fPixel, pos.fVert.fPixel}});
235 std::array<RPadLength::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 RPadDrawingOpts
242 Drawing options for a RPad
243 */
244
245class RPadDrawingOpts: public RDrawingOptsBase {
246 RDrawingAttr<RPadPos> fPos{*this, "PadOffset"}; ///< Offset with respect to parent RPad.
247
248public:
249 RPadDrawingOpts() = default;
250
251 /// Construct the drawing options.
252 RPadDrawingOpts(const RPadPos& 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 RDrawingAttr<RPadPos> &GetOffset() { return fPos; }
262 const RDrawingAttr<RPadPos> &GetOffset() const { return fPos; }
263};
264
265/** \class RPadDrawable
266 Draw a RPad, by drawing its contained graphical elements at the pad offset in the parent pad.'
267 */
268class RPadDrawable: public RDrawableBase<RPadDrawable> {
269private:
270 const std::shared_ptr<RPad> fPad; ///< The pad to be painted
271 RPadDrawingOpts fOpts; ///< The drawing options.
272
273public:
274 /// Move a sub-pad into this (i.e. parent's) list of drawables.
275 RPadDrawable(std::shared_ptr<RPad> pPad, const RPadDrawingOpts& opts = {});
276
277 /// Paint primitives from the pad.
278 void Paint(Internal::RPadPainter &) final;
279
280 RPad *Get() const { return fPad.get(); }
281
282 /// Drawing options.
284};
285
286template <class... ARGS>
287inline std::shared_ptr<RPadDrawable> GetDrawable(std::unique_ptr<RPad> &&pad, ARGS... args)
288{
289 return std::make_shared<RPadDrawable>(std::move(pad), RPadDrawingOpts(args...));
290}
291
292template <class... ARGS>
293inline std::shared_ptr<RPadDrawable> GetDrawable(const std::shared_ptr<RPad> &pad, ARGS... args)
294{
295 return std::make_shared<RPadDrawable>(pad, RPadDrawingOpts(args...));
296}
297
298} // namespace Experimental
299} // namespace ROOT
300
301#endif
int type
Definition: TGX11.cxx:120
Abstract interface for object painting on the pad/canvas.
Definition: RPadPainter.hxx:37
A window's topmost RPad.
Definition: RCanvas.hxx:33
Holds a user coordinate system with a palette.
Definition: RFrame.hxx:35
Base class for graphic containers for RDrawable-s.
Definition: RPad.hxx:41
RPadBase & operator=(const RPadBase &)=delete
Disable assignment.
RPadBase(const RPadBase &)=delete
Disable copy construction.
const RFrame * GetFrame() const
Definition: RPad.hxx:138
virtual std::array< RPadLength::Normal, 2 > PixelsToNormal(const std::array< RPadLength::Pixel, 2 > &pos) const =0
Convert a Pixel position to Canvas-normalized positions.
std::array< RPadLength::Normal, 2 > UserToNormal(const std::array< RPadLength::User, 2 > &pos) const
Convert user coordinates to normal coordinates.
Definition: RPad.hxx:170
Primitives_t fPrimitives
Content of the pad.
Definition: RPad.hxx:47
auto Draw(const T &what, ARGS... args)
Add a copy of something to be painted.
Definition: RPad.hxx:111
std::vector< std::shared_ptr< RDrawable > > Primitives_t
Definition: RPad.hxx:43
void SetAllAxisBound(const std::vector< BoundKindAndValue > &vecBoundAndKind)
Set the range of an axis as bound kind and bound (up or down).
Definition: RPad.cxx:182
void SetAxisBounds(int dimension, double begin, double end)
Set the range of an axis as begin, end.
Definition: RPad.cxx:138
virtual const RCanvas * GetCanvas() const =0
Access to the top-most canvas, if any (const version).
void SetAllAxisAutoBounds()
Set the range of an axis as bound kind and bound (up or down).
Definition: RPad.cxx:199
bool Remove(RDrawingOptsBase &opts)
Remove an object from the list of primitives.
Definition: RPad.hxx:118
void SetAxisBound(int dimension, RPadUserAxisBase::EAxisBoundsKind boundsKind, double bound)
Set the range of an axis as bound kind and bound (up or down).
Definition: RPad.cxx:147
std::unique_ptr< RFrame > fFrame
RFrame with user coordinate system, if used by this pad.
Definition: RPad.hxx:50
const Primitives_t & GetPrimitives() const
Get the elements contained in the canvas.
Definition: RPad.hxx:158
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: RPad.cxx:165
auto Draw(std::unique_ptr< T > &&what, ARGS... args)
Add something to be painted.
Definition: RPad.hxx:102
virtual RCanvas * GetCanvas()=0
Access to the top-most canvas, if any (non-const version).
RPadUserAxisBase * GetAxis(size_t dimension) const
Get a pad axis from the RFrame.
Definition: RPad.cxx:118
RPadUserAxisBase * GetOrCreateAxis(size_t dimension)
Get a pad axis from the RFrame.
Definition: RPad.cxx:129
RFrame * GetOrCreateFrame()
Definition: RPad.cxx:100
void AssignUniqueID(std::shared_ptr< RDrawable > &ptr)
Definition: RPad.cxx:30
auto Draw(const std::shared_ptr< T > &what, ARGS... args)
Add something to be painted.
Definition: RPad.hxx:93
void Wipe()
Wipe the pad by clearing the list of primitives.
Definition: RPad.hxx:130
void SetAxisAutoBounds(int dimension)
Set the range of an axis as bound kind and bound (up or down).
Definition: RPad.cxx:156
auto AddDrawable(std::shared_ptr< DRAWABLE > &&uPtr)
Adds a DRAWABLE to fPrimitives, returning a shared_ptr to DRAWABLE::GetOptions().
Definition: RPad.hxx:62
RPadBase()=default
Allow derived classes to default construct a RPadBase.
std::vector< std::vector< RPad * > > Divide(int nHoriz, int nVert, const RPadExtent &padding={})
Divide this pad into a grid of subpads with padding in between.
Definition: RPad.cxx:65
std::shared_ptr< RDrawable > FindDrawable(const std::string &id) const
Definition: RPad.cxx:44
Draw a RPad, by drawing its contained graphical elements at the pad offset in the parent pad.
Definition: RPad.hxx:268
void Paint(Internal::RPadPainter &) final
Paint primitives from the pad.
Definition: RPad.cxx:219
RPadDrawingOpts fOpts
The drawing options.
Definition: RPad.hxx:271
const std::shared_ptr< RPad > fPad
The pad to be painted.
Definition: RPad.hxx:270
RPadDrawingOpts & GetOptions()
Drawing options.
Definition: RPad.hxx:283
RPadDrawable(std::shared_ptr< RPad > pPad, const RPadDrawingOpts &opts={})
Move a sub-pad into this (i.e. parent's) list of drawables.
Definition: RPad.cxx:213
Drawing options for a RPad.
Definition: RPad.hxx:245
RPadDrawingOpts & At(const RPadPos &pos)
Set the position of this pad with respect to the parent pad.
Definition: RPad.hxx:255
const RDrawingAttr< RPadPos > & GetOffset() const
Definition: RPad.hxx:262
RDrawingAttr< RPadPos > & GetOffset()
Definition: RPad.hxx:261
RPadDrawingOpts(const RPadPos &pos)
Construct the drawing options.
Definition: RPad.hxx:252
RDrawingAttr< RPadPos > fPos
Offset with respect to parent RPad.
Definition: RPad.hxx:246
Pixel fPixel
The pixel coordinate summand.
Definition: RPadLength.hxx:101
User fUser
The user coordinate summand.
Definition: RPadLength.hxx:104
Normal fNormal
The normalized coordinate summand.
Definition: RPadLength.hxx:98
EAxisBoundsKind
Types of axis bounds to respect by the painter.
@ kAxisBoundsAuto
no defined axis range; the painter will decide
Graphic container for RDrawable-s.
Definition: RPad.hxx:182
const RPadExtent & GetSize() const
Get the size of the pad in parent (!) coordinates.
Definition: RPad.hxx:215
RPad(RPadBase &parent, const RPadExtent &size)
Create a child pad.
Definition: RPad.hxx:197
const RCanvas * GetCanvas() const override
Access to the top-most canvas (const version).
Definition: RPad.hxx:209
const RPadBase * GetParent() const
Access to the parent pad (const version).
Definition: RPad.hxx:203
RCanvas * GetCanvas() override
Access to the top-most canvas (non-const version).
Definition: RPad.hxx:212
friend std::unique_ptr< RPadDrawable > GetDrawable(std::unique_ptr< RPad > &&pad)
virtual ~RPad()
Destructor to have a vtable.
RPadBase * GetParent()
Access to the parent pad (non-const version).
Definition: RPad.hxx:206
std::array< RPadLength::Normal, 2 > PixelsToNormal(const std::array< RPadLength::Pixel, 2 > &pos) const override
Convert a Pixel position to Canvas-normalized positions.
Definition: RPad.hxx:218
RPadBase * fParent
Pad containing this pad as a sub-pad.
Definition: RPad.hxx:185
std::array< RPadLength::Normal, 2 > ToNormal(const Internal::RPadHorizVert &pos) const
Convert a RPadPos to [x, y] of normalized coordinates.
Definition: RPad.hxx:232
RPad()=default
Create a topmost, non-paintable pad.
RPadExtent fSize
The parent pad, if this pad has one.
Definition: RPad.hxx:188
std::shared_ptr< RPadDrawable > GetDrawable(std::unique_ptr< RPad > &&pad, ARGS... args)
Definition: RPad.hxx:287
double T(double x)
Definition: ChebyshevPol.h:34
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
A 2D (horizontal and vertical) combination of RPadLengths.
Definition: RPadExtent.hxx:32
RPadLength fHoriz
Horizontal position.
Definition: RPadExtent.hxx:33
RPadLength fVert
Vertical position.
Definition: RPadExtent.hxx:34
Simple struct representing an axis bound.
Definition: RPad.hxx:150
RPadUserAxisBase::EAxisBoundsKind fKind
Definition: RPad.hxx:151
An extent / size (horizontal and vertical) in a RPad.
Definition: RPadExtent.hxx:47
A position (horizontal and vertical) in a RPad.
Definition: RPadPos.hxx:27
#define ARGS(alist)
Definition: gifencode.c:10