-
Sergey Linev authored
Some RDrawable may require RFrame, therefore when such drawable add to the pad, automatically RFrame will be created
Sergey Linev authoredSome RDrawable may require RFrame, therefore when such drawable add to the pad, automatically RFrame will be created
RPadBase.hxx 6.77 KiB
/*************************************************************************
* Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
#ifndef ROOT7_RPadBase
#define ROOT7_RPadBase
#include "ROOT/RDrawable.hxx"
#include "ROOT/RFrame.hxx"
#include "ROOT/RPadExtent.hxx"
#include "ROOT/RPadPos.hxx"
#include "ROOT/RPadUserAxis.hxx"
#include "ROOT/TypeTraits.hxx"
#include <memory>
#include <vector>
namespace ROOT {
namespace Experimental {
class RPad;
class RCanvas;
class RPadBaseDisplayItem;
/** \class ROOT::Experimental::RPadBase
\ingroup GpadROOT7
\brief Base class for graphic containers for `RDrawable`-s.
\authors Axel Naumann <axel@cern.ch> Sergey Linev <s.linev@gsi.de>
\date 2019-10-02
\warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
*/
class RPadBase : public RDrawable {
private:
using Primitive_t = Internal::RIOShared<RDrawable>;
/// Content of the pad.
std::vector<Primitive_t> fPrimitives;
/// Disable copy construction.
RPadBase(const RPadBase &) = delete;
/// Disable assignment.
RPadBase &operator=(const RPadBase &) = delete;
void TestIfFrameRequired(const RDrawable *drawable)
{
if (drawable->IsFrameRequired())
GetOrCreateFrame();
}
protected:
/// Allow derived classes to default construct a RPadBase.
RPadBase() : RDrawable("pad") {}
void CollectShared(Internal::RIOSharedVector_t &) override;
void DisplayPrimitives(RPadBaseDisplayItem &paditem) const;
public:
using Primitives_t = std::vector<std::shared_ptr<RDrawable>>;
virtual ~RPadBase();
void UseStyle(const std::shared_ptr<RStyle> &style) override;
/// Divide this pad into a grid of subpads with padding in between.
/// \param nHoriz Number of horizontal pads.
/// \param nVert Number of vertical pads.
/// \param padding Padding between pads.
/// \returns vector of vector (ret[x][y]) of created pads.
std::vector<std::vector<std::shared_ptr<RPad>>> Divide(int nHoriz, int nVert, const RPadExtent &padding = {});
/// Create drawable of specified class T
template<class T, class... ARGS>
auto Draw(ARGS... args)
{
auto drawable = std::make_shared<T>(args...);
TestIfFrameRequired(drawable.get());
fPrimitives.emplace_back(drawable);
return drawable;
}
/// Add existing drawable instance to canvas
auto Draw(std::shared_ptr<RDrawable> &&drawable)
{
TestIfFrameRequired(drawable.get());
fPrimitives.emplace_back(std::move(drawable));
return fPrimitives.back().get_shared();
}
/// Add object to be painted.
/// Correspondent drawable will be created via GetDrawable() function which should be defined and be accessed at calling time.
/// If required, extra arguments for GetDrawable() function can be provided.
template <class T, class... ARGS>
auto Draw(const std::shared_ptr<T> &what, ARGS... args)
{
// Requires GetDrawable(what) to be known!
auto drawable = GetDrawable(what, args...);
TestIfFrameRequired(drawable.get());
fPrimitives.emplace_back(drawable);
return drawable;
}
/// returns number of primitives in the pad
unsigned NumPrimitives() const { return fPrimitives.size(); }
/// returns primitive of given number
std::shared_ptr<RDrawable> GetPrimitive(unsigned num) const
{
if (num >= fPrimitives.size()) return nullptr;
return fPrimitives[num].get_shared();
}
std::shared_ptr<RDrawable> FindPrimitive(const std::string &id) const;
std::shared_ptr<RDrawable> FindPrimitiveByDisplayId(const std::string &display_id) const;
/// Get all primitives contained in the pad.
auto GetPrimitives() const
{
Primitives_t res;
for (auto &entry : fPrimitives)
res.emplace_back(entry.get_shared());
return res;
}
/// Remove an object from the list of primitives.
bool Remove(const std::string &id)
{
auto iter = std::find_if(fPrimitives.begin(), fPrimitives.end(),
[&id](const Internal::RIOShared<RDrawable>& dr) { return dr->GetId() == id; });
if (iter == fPrimitives.end())
return false;
iter->reset();
fPrimitives.erase(iter);
return true;
}
/// Remove drawable from list of primitives
bool Remove(const std::shared_ptr<RDrawable> &drawable)
{
auto iter = std::find_if(fPrimitives.begin(), fPrimitives.end(),
[&drawable](const Internal::RIOShared<RDrawable>& dr) { return drawable.get() == dr.get(); });
if (iter == fPrimitives.end())
return false;
iter->reset();
fPrimitives.erase(iter);
return true;
}
/// Remove drawable at specified position
bool RemoveAt(unsigned indx)
{
if (indx >= fPrimitives.size()) return false;
fPrimitives[indx].reset();
fPrimitives.erase(fPrimitives.begin() + indx);
return true;
}
/// Wipe the pad by clearing the list of primitives.
void Wipe() { fPrimitives.clear(); }
std::shared_ptr<RFrame> GetOrCreateFrame();
std::shared_ptr<RFrame> GetFrame();
const std::shared_ptr<RFrame> GetFrame() const;
RPadUserAxisBase* GetOrCreateAxis(size_t dimension);
RPadUserAxisBase* GetAxis(size_t dimension) const;
void SetAxisBounds(int dimension, double begin, double end);
void SetAxisBound(int dimension, RPadUserAxisBase::EAxisBoundsKind boundsKind, double bound);
void SetAxisAutoBounds(int dimension);
void SetAllAxisBounds(const std::vector<std::array<double, 2>> &vecBeginAndEnd);
/// Simple struct representing an axis bound.
struct BoundKindAndValue {
RPadUserAxisBase::EAxisBoundsKind fKind = RPadUserAxisBase::kAxisBoundsAuto;
double fBound = 0.;
};
void SetAllAxisBound(const std::vector<BoundKindAndValue> &vecBoundAndKind);
void SetAllAxisAutoBounds();
/// Convert a `Pixel` position to Canvas-normalized positions.
virtual std::array<RPadLength::Normal, 2> PixelsToNormal(const std::array<RPadLength::Pixel, 2> &pos) const = 0;
/// Access to the top-most canvas, if any (const version).
virtual const RCanvas *GetCanvas() const = 0;
/// Access to the top-most canvas, if any (non-const version).
virtual RCanvas *GetCanvas() = 0;
/// Convert user coordinates to normal coordinates.
std::array<RPadLength::Normal, 2> UserToNormal(const std::array<RPadLength::User, 2> &pos) const;
void AssignAutoColors();
};
} // namespace Experimental
} // namespace ROOT
#endif