Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:10:45

0001 /*************************************************************************
0002  * Copyright (C) 1995-2021, Rene Brun and Fons Rademakers.               *
0003  * All rights reserved.                                                  *
0004  *                                                                       *
0005  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0006  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0007  *************************************************************************/
0008 
0009 #ifndef ROOT7_RLegend
0010 #define ROOT7_RLegend
0011 
0012 #include <ROOT/RPave.hxx>
0013 #include <ROOT/RAttrLine.hxx>
0014 #include <ROOT/RAttrFill.hxx>
0015 #include <ROOT/RAttrMarker.hxx>
0016 #include <ROOT/RDisplayItem.hxx>
0017 
0018 #include <initializer_list>
0019 #include <memory>
0020 #include <vector>
0021 
0022 namespace ROOT {
0023 namespace Experimental {
0024 
0025 /** \class RLegend
0026 \ingroup GrafROOT7
0027 \brief A legend for several drawables
0028 \author Sergey Linev <S.Linev@gsi.de>
0029 \date 2019-10-09
0030 \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
0031 */
0032 
0033 class RLegend : public RPave {
0034 
0035 public:
0036 
0037    /** \class RCustomDrawable
0038    \ingroup GrafROOT7
0039    \brief Special drawable to let provide line, fill or marker attributes for legend
0040    \author Sergey Linev <S.Linev@gsi.de>
0041    \date 2021-07-06
0042    \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
0043    is welcome!
0044    */
0045 
0046    class RCustomDrawable final : public RDrawable {
0047    public:
0048       RCustomDrawable() : RDrawable("lentry") {}
0049 
0050       RAttrLine line{this, "line"};          ///<! line attributes
0051       RAttrFill fill{this, "fill"};          ///<! fill attributes
0052       RAttrMarker marker{this, "marker"};    ///<! marker attributes
0053    };
0054 
0055    /** \class REntry
0056    \ingroup GrafROOT7
0057    \brief An entry in RLegend, references RDrawable and its attributes
0058    \author Sergey Linev <S.Linev@gsi.de>
0059    \date 2019-10-09
0060    \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
0061    is welcome!
0062    */
0063 
0064    class REntry {
0065 
0066       friend class RLegend;
0067 
0068       std::string fLabel; ///< label shown for the entry
0069 
0070       bool fLine{true}, fFill{false}, fMarker{false}, fError{false}; ///< enable line, fill, marker, error showing
0071 
0072       Internal::RIOShared<RDrawable> fDrawable; ///< reference to RDrawable
0073 
0074       std::string fDrawableId; ///< drawable id, used only when display item
0075 
0076       bool IsCustomDrawable() const { return dynamic_cast<const RCustomDrawable *>(fDrawable.get()) != nullptr; }
0077 
0078       void DecodeOptions(const std::string &opt)
0079       {
0080          if (opt.find('l') != std::string::npos) SetLine(true);
0081          if (opt.find('f') != std::string::npos) SetFill(true);
0082          if (opt.find('m') != std::string::npos) SetMarker(true);
0083          if (opt.find('e') != std::string::npos) SetError(true);
0084       }
0085 
0086    public:
0087       REntry() = default;
0088 
0089       /** Create entry without reference to existing drawable object, can assign attributes */
0090       REntry(const std::string &lbl, const std::string &opt)
0091       {
0092          fDrawableId = "custom";
0093          fLabel = lbl;
0094          DecodeOptions(opt);
0095       }
0096 
0097       /** Create entry with reference to existing drawable object */
0098       REntry(std::shared_ptr<RDrawable> drawable, const std::string &lbl, const std::string &opt)
0099       {
0100          fDrawable = drawable;
0101          fLabel = lbl;
0102          DecodeOptions(opt);
0103       }
0104 
0105       REntry &SetLabel(const std::string &lbl) { fLabel = lbl; return *this; }
0106       const std::string &GetLabel() const { return fLabel; }
0107 
0108       REntry &SetLine(bool on = true) { fLine = on; return *this; }
0109       bool GetLine() const { return fLine; }
0110 
0111       REntry &SetFill(bool on = true) { fFill = on; return *this; }
0112       bool GetFill() const { return fFill; }
0113 
0114       REntry &SetMarker(bool on = true) { fMarker = on; return *this; }
0115       bool GetMarker() const { return fMarker; }
0116 
0117       REntry &SetError(bool on = true) { fError = on; return *this; }
0118       bool GetError() const { return fError; }
0119 
0120       std::shared_ptr<RDrawable> GetDrawable() const { return fDrawable.get_shared(); }
0121    };
0122 
0123 private:
0124    std::string fTitle; ///< legend title
0125 
0126    std::vector<REntry> fEntries; ///< list of entries which should be displayed
0127 
0128 protected:
0129    void CollectShared(Internal::RIOSharedVector_t &vect) override
0130    {
0131       for (auto &entry : fEntries) {
0132          vect.emplace_back(&entry.fDrawable);
0133          if (entry.fDrawable)
0134             entry.fDrawable->CollectShared(vect);
0135       }
0136    }
0137 
0138    /** hide I/O pointers when creating display item */
0139    std::unique_ptr<RDisplayItem> Display(const RDisplayContext &) override
0140    {
0141       for (auto &entry : fEntries) {
0142          if (!entry.IsCustomDrawable()) {
0143             entry.fDrawableId = RDisplayItem::ObjectIDFromPtr(entry.fDrawable.get());
0144             entry.fDrawable.reset_io();
0145          }
0146       }
0147 
0148       return std::make_unique<RDrawableDisplayItem>(*this);
0149    }
0150 
0151    /** when display item destroyed - restore I/O pointers */
0152    void OnDisplayItemDestroyed(RDisplayItem *) const override
0153    {
0154       for (auto &centry : fEntries) {
0155          if (!centry.IsCustomDrawable()) {
0156             auto entry = const_cast<REntry *>(&centry);
0157             entry->fDrawable.restore_io();
0158             entry->fDrawableId.clear();
0159          }
0160       }
0161    }
0162 
0163 public:
0164    RLegend() : RPave("legend") {}
0165 
0166    RLegend(const std::string &title) : RLegend() { SetTitle(title); }
0167 
0168    RLegend(const RPadPos &offset, const RPadExtent &size) : RLegend()
0169    {
0170       offsetX = offset.Horiz();
0171       offsetY = offset.Vert();
0172       width = size.Horiz();
0173       height = size.Vert();
0174    }
0175 
0176    RLegend &SetTitle(const std::string &title) { fTitle = title; return *this; }
0177    const std::string &GetTitle() const { return fTitle; }
0178 
0179    std::shared_ptr<RCustomDrawable> AddEntry(const std::string &lbl, const std::string &opt = "")
0180    {
0181       fEntries.emplace_back(lbl, opt);
0182       auto drawable = std::make_shared<RCustomDrawable>();
0183       fEntries.back().fDrawable = drawable;
0184       return drawable;
0185    }
0186 
0187    void AddEntry(const std::shared_ptr<RDrawable> &drawable, const std::string &lbl, const std::string &opt = "")
0188    {
0189       fEntries.emplace_back(drawable, lbl, opt);
0190    }
0191 
0192    auto NumEntries() const { return fEntries.size(); }
0193 
0194    auto &GetEntry(int n) { return fEntries[n]; }
0195 };
0196 
0197 } // namespace Experimental
0198 } // namespace ROOT
0199 
0200 #endif