diff --git a/core/qa/CMakeLists.txt b/core/qa/CMakeLists.txt index 1140f0e592341210ff1e5e5d4c45b0df1ced8b6e..5ba68ecd51ee047646163515abe1aef1c7772903 100644 --- a/core/qa/CMakeLists.txt +++ b/core/qa/CMakeLists.txt @@ -20,6 +20,7 @@ link_directories( ${LINK_DIRECTORIES}) set(SRCS CbmQaCanvas.cxx +CbmQaPie.cxx ) set(LINKDEF CbmQaBaseLinkDef.h) diff --git a/core/qa/CbmQaBaseLinkDef.h b/core/qa/CbmQaBaseLinkDef.h index 1709eae5e18db5a891cc4b2ca5d1f03f24b064b1..3241d06482adbce51cb0c6ff4b314ccefbc16cb8 100644 --- a/core/qa/CbmQaBaseLinkDef.h +++ b/core/qa/CbmQaBaseLinkDef.h @@ -5,4 +5,6 @@ #pragma link off all functions; #pragma link C++ class CbmQaCanvas - ; +#pragma link C++ class CbmQaPieSlice + ; +#pragma link C++ class CbmQaPie - ; #endif diff --git a/core/qa/CbmQaPie.cxx b/core/qa/CbmQaPie.cxx new file mode 100644 index 0000000000000000000000000000000000000000..0014f3bbf98ea38b458297455b61ed9d1211d45e --- /dev/null +++ b/core/qa/CbmQaPie.cxx @@ -0,0 +1,96 @@ +/// \file CbmQaPie.cxx +/// \brief Implementation of the CbmQaPie class +/// \author Sergey Gorbunov <se.gorbunov@gsi.de> +/// \date 07.11.2020 + +#include "CbmQaPie.h" +#include "TBrowser.h" +#include "TBuffer.h" +#include "TPad.h" + +ClassImp(CbmQaPieSlice); +ClassImp(CbmQaPie); + +CbmQaPie::CbmQaPie(const CbmQaPie& cpy) + : TPie(cpy.GetName(), cpy.GetTitle(), cpy.fNvals) { + /// Prevent original copy constructor from a crash + cpy.TAttText::Copy(*this); + fAngularOffset = cpy.fAngularOffset; + fX = cpy.fX; + fY = cpy.fY; + fRadius = cpy.fRadius; + for (Int_t i = 0; i < fNvals; ++i) { + *fPieSlices[i] = *cpy.fPieSlices[i]; + ((CbmQaPieSlice*) fPieSlices[i])->SetPie(this); + } +} + +void CbmQaPie::Browse(TBrowser* b) { + /// Draw CbmQaPie by a mouse click in the TBrowser + Draw(b ? b->GetDrawOption() : ""); + gPad->Update(); +} + +void CbmQaPie::Draw(Option_t* option) { + // Prevents original TPie::Draw() from crashing when there are no entries + double sum = 0.; + for (int i = 0; i < fNvals; i++) { + sum += fabs(GetEntryVal(i)); + } + if (sum < 1.e-20) { + for (int i = 0; i < fNvals; i++) { + SetEntryVal(i, 1.e-20); + } + } + TPie::Draw(option); + if (sum < 1.e-20) { + for (int i = 0; i < fNvals; i++) { + SetEntryVal(i, 0.); + } + } +} + +void CbmQaPie::Streamer(TBuffer& R__b) { + /// The Streamer is declared by ClassDef() macro + /// Stream an object of class CbmQaPie + /// + + if (R__b.IsReading()) { + + for (int i = 0; i < fNvals; i++) { + if (gPad && gPad->GetListOfPrimitives()) { + gPad->GetListOfPrimitives()->Remove(fPieSlices[i]); + } + delete fPieSlices[i]; + fPieSlices[i] = nullptr; + } + delete[] fPieSlices; + fPieSlices = nullptr; + fNvals = 0; + + R__b.ReadClassBuffer(CbmQaPie::Class(), this); + + fNvals = fSliceStore.size(); + fPieSlices = new TPieSlice*[fNvals]; + for (int i = 0; i < fNvals; i++) { + fSliceStore[i].SetPie(this); + fPieSlices[i] = new TPieSlice(fSliceStore[i]); + } + fSliceStore.clear(); + + } else { + + fSliceStore.resize(fNvals); + for (int i = 0; i < fNvals; i++) { + fSliceStore[i] = *fPieSlices[i]; + fSliceStore[i].SetPie(nullptr); + } + TPieSlice** tmp = fPieSlices; + fPieSlices = nullptr; + fNvals = 0; + R__b.WriteClassBuffer(CbmQaPie::Class(), this); + fPieSlices = tmp; + fNvals = fSliceStore.size(); + fSliceStore.clear(); + } +} diff --git a/core/qa/CbmQaPie.h b/core/qa/CbmQaPie.h new file mode 100644 index 0000000000000000000000000000000000000000..6643b6972c7823bfe2c975da66c059e13f6679f6 --- /dev/null +++ b/core/qa/CbmQaPie.h @@ -0,0 +1,62 @@ +/// \file CbmQaPie.h +/// \brief Definition of the CbmQaPie class +/// \author Sergey Gorbunov <se.gorbunov@gsi.de> +/// \date 07.11.2020 + +#ifndef CbmQaPie_H +#define CbmQaPie_H + +#include "TPie.h" +#include "TPieSlice.h" +#include <vector> + +class TBrowser; + +/// A helper class for accessing protected members of TPieSlice +/// +class CbmQaPieSlice : public TPieSlice { +public: + /// assignment operator + CbmQaPieSlice& operator=(const TPieSlice& inp) { + return (*this = (const CbmQaPieSlice&) (inp)); + } + /// set a TPie pointer + void SetPie(TPie* p) { fPie = p; } + + ClassDef(CbmQaPieSlice, 1); +}; + +/// A modification of TPie which fixes the following issues: +/// +/// 1. When a TPie is read from a file as a part of TCanvas, it crashes at the destructor. +/// 2. When a TPie is created via copy constructor it crashes at the destructor. +/// 3. An empty TPie crashes at Draw() +/// 4. When one clicks on a TPie in the TBrowser, the TBrowser crashes. +/// 5. TBrowser dosen't draw a TPie by a mouse click. +/// +class CbmQaPie : public TPie { +public: + /// Reimplementation of any existing TPie constructor + template<typename... Types> + CbmQaPie(Types... args) : TPie(args...) {} + + /// Prevent original copy constructor from a crash + CbmQaPie(const CbmQaPie& cpy); + + /// Destructor + ~CbmQaPie() {} + + /// Draw TPie by a mouse click in the TBrowser + void Browse(TBrowser* b); + + /// Prevents original TPie::Draw() from crashing when there are no entries + void Draw(Option_t* option = "l"); + +private: + /// a vector for slice streaming. It replaces the original array of pointers. + std::vector<CbmQaPieSlice> fSliceStore; + + ClassDef(CbmQaPie, 1); +}; + +#endif