Logo ROOT   6.18/05
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"
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.
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 {
183public:
184 /** \class DrawingOpts
185 Drawing options for a RPad
186 */
187
189 public:
190 DrawingOpts() = default;
191
192 DrawingOpts(const RPadPos &pos, const RPadExtent &size):
194 {
195 SetPos(pos);
196 SetSize(size);
197 }
198
199 RAttrBox Border() { return {FromOption, "border", *this}; }
200
201 /// The position (offset) of the pad.
202 DrawingOpts &SetPos(const RPadPos &pos) { Set("pos", pos); return *this; }
203 RPadPos GetPos() const { return Get<RPadPos>("pos"); }
204
205 /// The size of the pad.
206 DrawingOpts &SetSize(const RPadExtent &size) { Set("size", size); return *this; }
207 RPadExtent GetSize() const { return Get<RPadExtent>("size"); }
208 };
209
210private:
211 /// Pad containing this pad as a sub-pad.
212 RPadBase *fParent = nullptr; /// The parent pad, if this pad has one.
213
214 /// Drawing options, containing the size (in parent coordinates!)
216
217 /// Position of the pad in the parent's (!) coordinate system.
219
220 /// Size of the pad in the parent's (!) coordinate system.
221 RPadExtent fSize = fOpts.GetSize(); // {640_px, 400_px};
222
223public:
224 friend std::unique_ptr<RPadDrawable> GetDrawable(std::unique_ptr<RPad> &&pad);
225
226 /// Create a topmost, non-paintable pad.
227 RPad() = default;
228
229 /// Create a child pad.
230 RPad(RPadBase &parent, const RPadPos &pos, const RPadExtent &size): fParent(&parent), fPos(pos), fSize(size) {}
231
232 /// Destructor to have a vtable.
233 virtual ~RPad();
234
235 /// Access to the parent pad (const version).
236 const RPadBase *GetParent() const { return fParent; }
237
238 /// Access to the parent pad (non-const version).
240
241 /// Access to the top-most canvas (const version).
242 const RCanvas *GetCanvas() const override { return fParent ? fParent->GetCanvas() : nullptr; }
243
244 /// Access to the top-most canvas (non-const version).
245 RCanvas *GetCanvas() override { return fParent ? fParent->GetCanvas() : nullptr; }
246
247 /// Get the position of the pad in parent (!) coordinates.
248 const RPadPos &GetPos() const { return fPos; }
249
250 /// Get the size of the pad in parent (!) coordinates.
251 const RPadExtent &GetSize() const { return fSize; }
252
253 /// Drawing options.
255
256 /// Convert a `Pixel` position to Canvas-normalized positions.
257 std::array<RPadLength::Normal, 2> PixelsToNormal(const std::array<RPadLength::Pixel, 2> &pos) const override
258 {
259 std::array<RPadLength::Normal, 2> posInParentNormal = fParent->PixelsToNormal(pos);
260 std::array<RPadLength::Normal, 2> myPixelInNormal =
262 std::array<RPadLength::Normal, 2> myUserInNormal =
264 // 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
265 // coord system is 3.0!
266 return {{posInParentNormal[0] / (fSize.fHoriz.fNormal + myPixelInNormal[0] + myUserInNormal[0]),
267 posInParentNormal[1] / (fSize.fVert.fNormal + myPixelInNormal[1] + myUserInNormal[1])}};
268 }
269
270 /// Convert a RPadPos to [x, y] of normalized coordinates.
271 std::array<RPadLength::Normal, 2> ToNormal(const Internal::RPadHorizVert &pos) const
272 {
273 std::array<RPadLength::Normal, 2> pixelsInNormal = PixelsToNormal({{pos.fHoriz.fPixel, pos.fVert.fPixel}});
274 std::array<RPadLength::Normal, 2> userInNormal = UserToNormal({{pos.fHoriz.fUser, pos.fVert.fUser}});
275 return {{pos.fHoriz.fNormal + pixelsInNormal[0] + userInNormal[0],
276 pos.fVert.fNormal + pixelsInNormal[1] + userInNormal[1]}};
277 }
278};
279
280/** \class RPadDrawable
281 Draw a RPad, by drawing its contained graphical elements at the pad offset in the parent pad.'
282 */
283class RPadDrawable: public RDrawableBase<RPadDrawable> {
284private:
285 const std::shared_ptr<RPad> fPad; ///< The pad to be painted
286
287public:
288 /// Move a sub-pad into this (i.e. parent's) list of drawables.
289 RPadDrawable(const std::shared_ptr<RPad> &pPad, const RPad::DrawingOpts& opts = {});
290
291 /// Paint primitives from the pad.
292 void Paint(Internal::RPadPainter &) final;
293
294 RPad *Get() const { return fPad.get(); }
295
296 /// Drawing options.
297 RPad::DrawingOpts &GetOptions() { return fPad->GetDrawingOpts(); }
298};
299
300template <class... ARGS>
301inline std::shared_ptr<RPadDrawable> GetDrawable(std::unique_ptr<RPad> &&pad, ARGS... args)
302{
303 return std::make_shared<RPadDrawable>(std::move(pad), RPad::DrawingOpts(args...));
304}
305
306template <class... ARGS>
307inline std::shared_ptr<RPadDrawable> GetDrawable(const std::shared_ptr<RPad> &pad, ARGS... args)
308{
309 return std::make_shared<RPadDrawable>(pad, RPad::DrawingOpts(args...));
310}
311
312} // namespace Experimental
313} // namespace ROOT
314
315#endif
int type
Definition: TGX11.cxx:120
Abstract interface for object painting on the pad/canvas.
Definition: RPadPainter.hxx:37
class ROOT::Experimental::RAttrBox Drawing attributes for a box: rectangular lines with size and posi...
Definition: RAttrBox.hxx:31
A window's topmost RPad.
Definition: RCanvas.hxx:33
A collection of graphics attributes, for instance everything describing a line: color,...
void Set(const Name &name, const T &val)
Insert or update the attribute value identified by name to the given value.
static constexpr const FromOption_t FromOption
Holds a user coordinate system with a palette.
Definition: RFrame.hxx:33
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:179
void SetAxisBounds(int dimension, double begin, double end)
Set the range of an axis as begin, end.
Definition: RPad.cxx:135
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:196
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:144
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:162
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:115
RPadUserAxisBase * GetOrCreateAxis(size_t dimension)
Get a pad axis from the RFrame.
Definition: RPad.cxx:126
RFrame * GetOrCreateFrame()
Definition: RPad.cxx:97
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:153
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:283
void Paint(Internal::RPadPainter &) final
Paint primitives from the pad.
Definition: RPad.cxx:218
RPadDrawable(const std::shared_ptr< RPad > &pPad, const RPad::DrawingOpts &opts={})
Move a sub-pad into this (i.e. parent's) list of drawables.
Definition: RPad.cxx:210
const std::shared_ptr< RPad > fPad
The pad to be painted.
Definition: RPad.hxx:285
RPad::DrawingOpts & GetOptions()
Drawing options.
Definition: RPad.hxx:297
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
Drawing options for a RPad.
Definition: RPad.hxx:188
DrawingOpts(const RPadPos &pos, const RPadExtent &size)
Definition: RPad.hxx:192
DrawingOpts & SetPos(const RPadPos &pos)
The position (offset) of the pad.
Definition: RPad.hxx:202
DrawingOpts & SetSize(const RPadExtent &size)
The size of the pad.
Definition: RPad.hxx:206
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:251
const RCanvas * GetCanvas() const override
Access to the top-most canvas (const version).
Definition: RPad.hxx:242
const RPadBase * GetParent() const
Access to the parent pad (const version).
Definition: RPad.hxx:236
RCanvas * GetCanvas() override
Access to the top-most canvas (non-const version).
Definition: RPad.hxx:245
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:239
DrawingOpts & GetDrawingOpts()
Drawing options.
Definition: RPad.hxx:254
RPadPos fPos
Position of the pad in the parent's (!) coordinate system.
Definition: RPad.hxx:218
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:257
RPad(RPadBase &parent, const RPadPos &pos, const RPadExtent &size)
Create a child pad.
Definition: RPad.hxx:230
DrawingOpts fOpts
The parent pad, if this pad has one.
Definition: RPad.hxx:215
RPadBase * fParent
Pad containing this pad as a sub-pad.
Definition: RPad.hxx:212
std::array< RPadLength::Normal, 2 > ToNormal(const Internal::RPadHorizVert &pos) const
Convert a RPadPos to [x, y] of normalized coordinates.
Definition: RPad.hxx:271
RPad()=default
Create a topmost, non-paintable pad.
const RPadPos & GetPos() const
Get the position of the pad in parent (!) coordinates.
Definition: RPad.hxx:248
RPadExtent fSize
Size of the pad in the parent's (!) coordinate system.
Definition: RPad.hxx:221
std::shared_ptr< RPadDrawable > GetDrawable(std::unique_ptr< RPad > &&pad, ARGS... args)
Definition: RPad.hxx:301
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