diff --git a/graf2d/gpad/inc/LinkDef.h b/graf2d/gpad/inc/LinkDef.h index f71a8b529b1af3b164a6b0a72c517f381188bea5..fb58879c7f89ceb2e895dc25f51729df367571c1 100644 --- a/graf2d/gpad/inc/LinkDef.h +++ b/graf2d/gpad/inc/LinkDef.h @@ -40,8 +40,11 @@ #pragma link C++ class ROOT::Experimental::TUniqueDisplayItem<TPad>+; #pragma link C++ class ROOT::Experimental::TOrdinaryDisplayItem<TH1>+; #pragma link C++ class ROOT::Experimental::Detail::TMenuItem+; -#pragma link C++ class ROOT::Experimental::Detail::TCheckedMenuItem+; #pragma link C++ class std::vector<ROOT::Experimental::Detail::TMenuItem*>+; +#pragma link C++ class ROOT::Experimental::Detail::TCheckedMenuItem+; +#pragma link C++ class ROOT::Experimental::Detail::TMenuArgument+; +#pragma link C++ class std::vector<ROOT::Experimental::Detail::TMenuArgument>+; +#pragma link C++ class ROOT::Experimental::Detail::TArgsMenuItem+; #pragma link C++ class ROOT::Experimental::TMenuItems+; #endif diff --git a/graf2d/gpad/v7/inc/ROOT/TMenuItem.hxx b/graf2d/gpad/v7/inc/ROOT/TMenuItem.hxx index bd195266bb4e4139789c663e26d53956d86da36f..c3d7944f1c75db6dd39e259683915bbb2954ecdf 100644 --- a/graf2d/gpad/v7/inc/ROOT/TMenuItem.hxx +++ b/graf2d/gpad/v7/inc/ROOT/TMenuItem.hxx @@ -19,6 +19,8 @@ #include <string> #include <vector> +class TClass; + namespace ROOT { namespace Experimental { namespace Detail { @@ -59,9 +61,7 @@ public: /** Default constructor */ TCheckedMenuItem() = default; - /** Create menu item with the name and title - * name used to display item in the object context menu, - * title shown as hint info for that item */ + /** Create checked menu item */ TCheckedMenuItem(const std::string &name, const std::string &title, bool checked = false) : TMenuItem(name, title), fChecked(checked) { @@ -73,6 +73,34 @@ public: bool IsChecked() const { return fChecked; } }; +class TMenuArgument { +protected: + std::string fName; ///< name of call argument + std::string fTitle; ///< title of call argument + std::string fTypeName; ///< typename + std::string fDefault; ///< default value +public: + /** Default constructor */ + TMenuArgument() = default; + + TMenuArgument(const std::string &name, const std::string &title, const std::string &typname, const std::string &dflt) + : fName(name), fTitle(title), fTypeName(typname), fDefault(dflt) + { + } +}; + +class TArgsMenuItem : public TMenuItem { +protected: + std::vector<TMenuArgument> fArgs; + +public: + TArgsMenuItem() = default; + + TArgsMenuItem(const std::string &name, const std::string &title) : TMenuItem(name, title) {} + + void AddArg(const TMenuArgument &arg) { fArgs.push_back(arg); } +}; + } // namespace Detail /////////////////////////////////////////////////////////////////////// @@ -95,6 +123,14 @@ public: Add(item); } + Detail::TArgsMenuItem *AddArgsMenuItem(const std::string &name, const std::string &title, const std::string &exec) + { + Detail::TArgsMenuItem *item = new Detail::TArgsMenuItem(name, title); + item->SetExec(exec); + Add(item); + return item; + } + void AddChkMenuItem(const std::string &name, const std::string &title, bool checked, const std::string &toggle) { Detail::TCheckedMenuItem *item = new Detail::TCheckedMenuItem(name, title, checked); @@ -104,6 +140,8 @@ public: void Cleanup(); + void PopulateObjectMenu(void *obj, TClass *cl); + std::string ProduceJSON(); }; diff --git a/graf2d/gpad/v7/src/TMenuItem.cxx b/graf2d/gpad/v7/src/TMenuItem.cxx index aa491c8295b4c52766d0fdbbfd7b1cdf13b1c6b4..9f47c1eb00953cb74cdd9d2f4018840b6416508e 100644 --- a/graf2d/gpad/v7/src/TMenuItem.cxx +++ b/graf2d/gpad/v7/src/TMenuItem.cxx @@ -17,6 +17,9 @@ #include "TROOT.h" #include "TClass.h" +#include "TList.h" +#include "TMethod.h" +#include "TMethodCall.h" #include "TBufferJSON.h" void ROOT::Experimental::TMenuItems::Cleanup() @@ -26,6 +29,61 @@ void ROOT::Experimental::TMenuItems::Cleanup() fItems.clear(); } +void ROOT::Experimental::TMenuItems::PopulateObjectMenu(void *obj, TClass *cl) +{ + Cleanup(); + + TList *lst = new TList; + cl->GetMenuItems(lst); + + TIter iter(lst); + TMethod *m = 0; + + while ((m = (TMethod *)iter()) != 0) { + + if (m->IsMenuItem() == kMenuToggle) { + TString getter; + if (m->Getter() && strlen(m->Getter()) > 0) { + getter = m->Getter(); + } else if (strncmp(m->GetName(), "Set", 3) == 0) { + getter = TString(m->GetName())(3, strlen(m->GetName()) - 3); + if (cl->GetMethodAllAny(TString("Has") + getter)) + getter = TString("Has") + getter; + else if (cl->GetMethodAllAny(TString("Get") + getter)) + getter = TString("Get") + getter; + else if (cl->GetMethodAllAny(TString("Is") + getter)) + getter = TString("Is") + getter; + else + getter = ""; + } + + if ((getter.Length() > 0) && cl->GetMethodAllAny(getter)) { + // execute getter method to get current state of toggle item + + TMethodCall *call = new TMethodCall(cl, getter, ""); + + if (call->ReturnType() == TMethodCall::kLong) { + Long_t l(0); + call->Execute(obj, l); + + AddChkMenuItem(m->GetName(), m->GetTitle(), l != 0, + Form("%s(%s)", m->GetName(), (l != 0) ? "0" : "1")); + + } else { + // Error("CheckModifiedFlag", "Cannot get toggle value with getter %s", getter.Data()); + } + + delete call; + } + } else { + AddMenuItem(m->GetName(), m->GetTitle(), Form("%s()", m->GetName())); + } + } + + delete lst; +} + + std::string ROOT::Experimental::TMenuItems::ProduceJSON() { TClass *cl = gROOT->GetClass("std::vector<ROOT::Experimental::Detail::TMenuItem*>"); diff --git a/graf2d/gpad/v7/src/TObjectDrawable.cxx b/graf2d/gpad/v7/src/TObjectDrawable.cxx index eae95100be4242ea9496324176505f0bd0f1e5d1..f49546f07a63d46aba15ccec5fb9bf0ee305537b 100644 --- a/graf2d/gpad/v7/src/TObjectDrawable.cxx +++ b/graf2d/gpad/v7/src/TObjectDrawable.cxx @@ -21,9 +21,6 @@ #include <ROOT/TVirtualCanvasPainter.hxx> #include "TClass.h" -#include "TList.h" -#include "TMethod.h" -#include "TMethodCall.h" #include "TROOT.h" #include <exception> @@ -41,55 +38,7 @@ void ROOT::Experimental::Internal::TObjectDrawable::PopulateMenu(TMenuItems &ite TObject *obj = fObj.get(); // fill context menu items for the ROOT class - - TClass *cl = obj->IsA(); - - TList *lst = new TList; - cl->GetMenuItems(lst); - - TIter iter(lst); - TMethod *m = 0; - - while ((m = (TMethod *)iter()) != 0) { - - if (m->IsMenuItem() == kMenuToggle) { - TString getter; - if (m->Getter() && strlen(m->Getter()) > 0) { - getter = m->Getter(); - } else if (strncmp(m->GetName(), "Set", 3) == 0) { - getter = TString(m->GetName())(3, strlen(m->GetName()) - 3); - if (cl->GetMethodAllAny(TString("Has") + getter)) - getter = TString("Has") + getter; - else if (cl->GetMethodAllAny(TString("Get") + getter)) - getter = TString("Get") + getter; - else if (cl->GetMethodAllAny(TString("Is") + getter)) - getter = TString("Is") + getter; - else - getter = ""; - } - - if ((getter.Length() > 0) && cl->GetMethodAllAny(getter)) { - // execute getter method to get current state of toggle item - - TMethodCall *call = new TMethodCall(cl, getter, ""); - - if (call->ReturnType() == TMethodCall::kLong) { - Long_t l(0); - call->Execute(obj, l); - - items.AddChkMenuItem(m->GetName(), m->GetTitle(), l != 0, - Form("%s(%s)", m->GetName(), (l != 0) ? "0" : "1")); - - } else { - // Error("CheckModifiedFlag", "Cannot get toggle value with getter %s", getter.Data()); - } - - delete call; - } - } else { - items.AddMenuItem(m->GetName(), m->GetTitle(), Form("%s()", m->GetName())); - } - } + items.PopulateObjectMenu(obj, obj->IsA()); } void ROOT::Experimental::Internal::TObjectDrawable::Execute(const std::string &exec) diff --git a/hist/hist/v7/inc/ROOT/THistDrawable.hxx b/hist/hist/v7/inc/ROOT/THistDrawable.hxx index 1ee130e2dfadeda0b885f598d0977d3242a460d9..bc127b55cc820a3b6346bb61825eeb6b61dd2749 100644 --- a/hist/hist/v7/inc/ROOT/THistDrawable.hxx +++ b/hist/hist/v7/inc/ROOT/THistDrawable.hxx @@ -20,6 +20,9 @@ #include "ROOT/THistDrawOptions.hxx" #include "ROOT/TLogger.hxx" +// TODO: from Sergey Linev: should libHist depend from libGpad? +//#include "ROOT/TMenuItem.hxx" + #include <memory> class TH1; @@ -76,10 +79,7 @@ public: THistDrawableBase &operator=(THistDrawableBase &&); - void PopulateMenu(TMenuItems &) final - { - // here should be filling of context menu for the given object - } + void PopulateMenu(TMenuItems &) final; void Execute(const std::string &) final { diff --git a/hist/hist/v7/src/THistDrawable.cxx b/hist/hist/v7/src/THistDrawable.cxx index 6e86c350f3535081eb0baeb691bcc29c62443ffb..f079fcbe78ecd305302e758c9a66a65fefa9bacb 100644 --- a/hist/hist/v7/src/THistDrawable.cxx +++ b/hist/hist/v7/src/THistDrawable.cxx @@ -2,7 +2,8 @@ /// \ingroup Hist ROOT7 /// \author Axel Naumann <axel@cern.ch> /// \date 2015-09-11 -/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome! +/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback +/// is welcome! /************************************************************************* * Copyright (C) 1995-2015, Rene Brun and Fons Rademakers. * @@ -26,107 +27,102 @@ using namespace ROOT::Experimental; using namespace ROOT::Experimental::Internal; -void ROOT::Experimental::Internal::LoadHistPainterLibrary() { - gSystem->Load("libHistPainter"); +void ROOT::Experimental::Internal::LoadHistPainterLibrary() +{ + gSystem->Load("libHistPainter"); } - template <int DIMENSION> -THistPainterBase<DIMENSION>::~THistPainterBase() { fgPainter = nullptr; } +THistPainterBase<DIMENSION>::~THistPainterBase() +{ + fgPainter = nullptr; +} template <int DIMENSION> -THistPainterBase<DIMENSION>* THistPainterBase<DIMENSION>::fgPainter = nullptr; - +THistPainterBase<DIMENSION> *THistPainterBase<DIMENSION>::fgPainter = nullptr; Internal::THistDrawableBase::THistDrawableBase() = default; -Internal::THistDrawableBase::THistDrawableBase(THistDrawableBase&&) = default; +Internal::THistDrawableBase::THistDrawableBase(THistDrawableBase &&) = default; Internal::THistDrawableBase::~THistDrawableBase() = default; -Internal::THistDrawableBase& -Internal::THistDrawableBase::operator=(THistDrawableBase&&) = default; +Internal::THistDrawableBase &Internal::THistDrawableBase::operator=(THistDrawableBase &&) = default; +void Internal::THistDrawableBase::PopulateMenu(TMenuItems &) +{ + // here should be filling of context menu for the given object + // for the moment commented out, while TMenuItems is not available in libHist + + // items.PopulateObjectMenu(GetOldHist(), GetOldHist()->IsA()); +} template <int DIMENSIONS> -bool -THistDrawable<DIMENSIONS>::UpdateOldHist() { - auto implBase = fHistImpl.Get(); - if (!implBase) { - fOldHist.reset(); - return false; - } - - std::array<TAxisView, DIMENSIONS> axes; - for (int i = 0; i < DIMENSIONS; ++i) - axes[i] = implBase->GetAxis(i); - - TH1 *old = nullptr; - - // Create a unique name, for what it's worth. - std::string histName; - { - std::stringstream strm; - strm << "drawAdaptor" << this; - } - - // Create old histogram; set nbins because TH1::fNcells is not accessible. - switch (DIMENSIONS) { - case 1: - old = new TH1D(histName.c_str(), - implBase->GetTitle().c_str(), - axes[0].GetNBins() - 2, 0., 1.); - break; - case 2: - old = new TH2D(histName.c_str(), - implBase->GetTitle().c_str(), - axes[0].GetNBins() - 2, 0., 1., +bool THistDrawable<DIMENSIONS>::UpdateOldHist() +{ + auto implBase = fHistImpl.Get(); + if (!implBase) { + fOldHist.reset(); + return false; + } + + std::array<TAxisView, DIMENSIONS> axes; + for (int i = 0; i < DIMENSIONS; ++i) axes[i] = implBase->GetAxis(i); + + TH1 *old = nullptr; + + // Create a unique name, for what it's worth. + std::string histName; + { + std::stringstream strm; + strm << "drawAdaptor" << this; + } + + // Create old histogram; set nbins because TH1::fNcells is not accessible. + switch (DIMENSIONS) { + case 1: old = new TH1D(histName.c_str(), implBase->GetTitle().c_str(), axes[0].GetNBins() - 2, 0., 1.); break; + case 2: + old = new TH2D(histName.c_str(), implBase->GetTitle().c_str(), axes[0].GetNBins() - 2, 0., 1., axes[1].GetNBins() - 2, 0., 1.); break; - case 3: - old = new TH3D(histName.c_str(), - implBase->GetTitle().c_str(), - axes[0].GetNBins() - 2, 0., 1., - axes[1].GetNBins() - 2, 0., 1., - axes[2].GetNBins() - 2, 0., 1.); + case 3: + old = new TH3D(histName.c_str(), implBase->GetTitle().c_str(), axes[0].GetNBins() - 2, 0., 1., + axes[1].GetNBins() - 2, 0., 1., axes[2].GetNBins() - 2, 0., 1.); break; - default: + default: // And anyway, this should really give a missing symbol due to the export // template. - R__ERROR_HERE("Hist") << "Drawing of " << DIMENSIONS - << " dimensional histograms not supported."; + R__ERROR_HERE("Hist") << "Drawing of " << DIMENSIONS << " dimensional histograms not supported."; return false; - } - - old->SetDirectory(nullptr); - - // See TH1::SetBins(). - std::array<TAxis*, 3> oldAxes{{old->GetXaxis(), old->GetYaxis(), old->GetZaxis()}}; - for (int i = 0; i < DIMENSIONS; ++i) { - oldAxes[i]->SetRange(0, 0); - oldAxes[i]->SetTitle(axes[i].GetTitle().c_str()); - if (axes[i].GetAsEquidistant()) { - oldAxes[i]->Set(axes[i].GetNBins() - 2, axes[i].GetFrom(), axes[i].GetTo()); - } else if (const TAxisIrregular* irr = axes[i].GetAsIrregular()) { - oldAxes[i]->Set(axes[i].GetNBins() - 2, &irr->GetBinBorders()[0]); - } else { - assert(0 && "Logic error; the axis is neither equidistant nor irregular."); - } - } - - int nBins = implBase->GetNBins(); - old->SetBinsLength(nBins); - if (implBase->HasBinUncertainty()) - old->Sumw2(); - - // Set the bin content + uncertainty. - for (int binidx = 0; binidx < nBins; ++binidx) { - old->SetBinContent(binidx, implBase->GetBinContentAsDouble(binidx)); - old->SetBinError(binidx, implBase->GetBinUncertainty(binidx)); - } - fOldHist.reset(old); - return true; + } + + old->SetDirectory(nullptr); + + // See TH1::SetBins(). + std::array<TAxis *, 3> oldAxes{{old->GetXaxis(), old->GetYaxis(), old->GetZaxis()}}; + for (int i = 0; i < DIMENSIONS; ++i) { + oldAxes[i]->SetRange(0, 0); + oldAxes[i]->SetTitle(axes[i].GetTitle().c_str()); + if (axes[i].GetAsEquidistant()) { + oldAxes[i]->Set(axes[i].GetNBins() - 2, axes[i].GetFrom(), axes[i].GetTo()); + } else if (const TAxisIrregular *irr = axes[i].GetAsIrregular()) { + oldAxes[i]->Set(axes[i].GetNBins() - 2, &irr->GetBinBorders()[0]); + } else { + assert(0 && "Logic error; the axis is neither equidistant nor irregular."); + } + } + + int nBins = implBase->GetNBins(); + old->SetBinsLength(nBins); + if (implBase->HasBinUncertainty()) old->Sumw2(); + + // Set the bin content + uncertainty. + for (int binidx = 0; binidx < nBins; ++binidx) { + old->SetBinContent(binidx, implBase->GetBinContentAsDouble(binidx)); + old->SetBinError(binidx, implBase->GetBinUncertainty(binidx)); + } + fOldHist.reset(old); + return true; } - namespace ROOT { namespace Experimental { namespace Internal {