diff --git a/core/gui/inc/TToggle.h b/core/gui/inc/TToggle.h index 045fe1cedbfba..757d699ad5db7 100644 --- a/core/gui/inc/TToggle.h +++ b/core/gui/inc/TToggle.h @@ -44,32 +44,36 @@ class TMethod; #include "TMethod.h" #endif +class TDataMember; + class TToggle: public TNamed { private: - Bool_t fState; //Object's state - "a local copy" - Long_t fOnValue; //Value recognized as switched ON (Def=1) - Long_t fOffValue; //Value recognized as switched OFF(Def=0) - Longptr_t fValue; //Local copy of a value returned by called function + Bool_t fState = kFALSE; //Object's state - "a local copy" + Long_t fOnValue = 1; //Value recognized as switched ON (Def=1) + Long_t fOffValue = 0; //Value recognized as switched OFF(Def=0) + Longptr_t fValue = -1; //Local copy of a value returned by called function protected: - Bool_t fInitialized; //True if either SetToggledObject or SetToggledVariable called - enables Toggle() method. - TObject *fObject; //The object this Toggle belongs to - TMethodCall *fGetter; //Method to Get a value of fObject; - TMethodCall *fSetter; //Method to Set a value of fObject; + Int_t fInitialized = 0; //0 - off, 1 - only object and member is set, 2 - also getters and setters for the object is set + TObject *fObject = nullptr; //The object this Toggle belongs to + TDataMember *fMember = nullptr; //Data member which will be toggled + TMethodCall *fGetter = nullptr; //Method to Get a value of fObject; + TMethodCall *fSetter = nullptr; //Method to Set a value of fObject; - Int_t *fTglVariable; //Alternatively: pointer to an integer value to be Toggled instead of TObjectl + Int_t *fTglVariable = nullptr; //Alternatively: pointer to an integer value to be Toggled instead of TObjectl public: TToggle(); virtual void SetToggledObject(TObject *obj, TMethod *anymethod); + virtual void SetToggledObject(TObject *obj, TDataMember *member); // you just provide any method which has got an initialized pointer // to TDataMember... The rest is done automatically... virtual void SetToggledVariable(Int_t &var); - virtual Bool_t IsInitialized(){ return fInitialized; } + virtual Bool_t IsInitialized() { return fInitialized > 0; } virtual Bool_t GetState(); virtual void SetState(Bool_t state); @@ -83,8 +87,8 @@ class TToggle: public TNamed { virtual Int_t GetValue() { return fValue; } virtual void SetValue(Long_t val); - TMethodCall *GetGetter() const { return fGetter; } - TMethodCall *GetSetter() const { return fSetter; } + TMethodCall *GetGetter() const; + TMethodCall *GetSetter() const; ClassDefOverride(TToggle,0) //Facility for toggling datamembers on/off }; diff --git a/core/gui/src/TToggle.cxx b/core/gui/src/TToggle.cxx index 93be5fedfb8f7..14d6a6521168a 100644 --- a/core/gui/src/TToggle.cxx +++ b/core/gui/src/TToggle.cxx @@ -27,9 +27,10 @@ automaticaly find a matching "get-method" by lookin for a method with name GetXXX, IsXXX or HasXXX for given object. */ +#include "TToggle.h" + #include "TMethod.h" #include "TMethodCall.h" -#include "TToggle.h" #include "TDataMember.h" #include "snprintf.h" @@ -40,15 +41,6 @@ with name GetXXX, IsXXX or HasXXX for given object. TToggle::TToggle() { - fState = kFALSE; - fValue = -1; - fOnValue = 1; - fOffValue = 0; - fInitialized = 0; - fObject = nullptr; - fGetter = nullptr; - fSetter = nullptr; - fTglVariable = nullptr; } //////////////////////////////////////////////////////////////////////////////// @@ -57,8 +49,8 @@ TToggle::TToggle() void TToggle::SetToggledVariable(Int_t &var) { - fTglVariable=&var; - fValue=var; + fTglVariable = &var; + fValue = var; } //////////////////////////////////////////////////////////////////////////////// @@ -67,9 +59,11 @@ void TToggle::SetToggledVariable(Int_t &var) Bool_t TToggle::GetState() { - if (fInitialized) - if (fGetter) fGetter->Execute(fObject, fValue); - return (fState = (fValue == fOnValue)); + if (auto fget = GetGetter()) + fget->Execute(fObject, fValue); + + fState = (fValue == fOnValue); + return fState; } //////////////////////////////////////////////////////////////////////////////// @@ -78,16 +72,7 @@ Bool_t TToggle::GetState() void TToggle::SetState(Bool_t state) { - if (fInitialized) { - char stringon[20]; - char stringoff[20]; - snprintf(stringon,sizeof(stringon),"%li",fOnValue); - snprintf(stringoff,sizeof(stringoff),"%li",fOffValue); - - fSetter->Execute(fObject, state ? stringon:stringoff); - fState=state; - fValue= ( state ? fOnValue : fOffValue); - } + SetValue(state ? fOnValue : fOffValue); } //////////////////////////////////////////////////////////////////////////////// @@ -96,12 +81,10 @@ void TToggle::SetState(Bool_t state) void TToggle::SetValue(Long_t val) { - if (fInitialized) { - char stringval[20]; - snprintf(stringval,sizeof(stringval),"%li",val); - fSetter->Execute(fObject, stringval); - fState=(val==fOnValue); - fValue= val; + if (auto fset = GetSetter()) { + fset->Execute(fObject, TString::Format("%li", val).Data()); + fState = (val == fOnValue); + fValue = val; } } @@ -110,43 +93,81 @@ void TToggle::SetValue(Long_t val) void TToggle::Toggle() { - if (fInitialized){ + if (IsInitialized()) { if (fTglVariable){ *fTglVariable = !(*fTglVariable); - fValue=(*fTglVariable); - fState=*fTglVariable; + fValue = (*fTglVariable); + fState = *fTglVariable; } - if (fGetter && fSetter){ - fGetter->Execute(fObject,fValue); - fValue=( (fValue==fOnValue) ? fOffValue:fOnValue); - fState=(!(fValue!=fOnValue)); - char stringon[20]; - snprintf(stringon,sizeof(stringon),"%zi",(size_t)fValue); - fSetter->Execute(fObject, stringon); + auto fget = GetGetter(); + auto fset = GetSetter(); + if (fget && fset) { + fget->Execute(fObject, fValue); + fValue = (fValue == fOnValue) ? fOffValue : fOnValue; + fState = (fValue == fOnValue); + fset->Execute(fObject, TString::Format("%zi", (size_t)fValue).Data()); } } } //////////////////////////////////////////////////////////////////////////////// -/// Initializes it to toggle an object's datamember using this object's -/// method. +/// Initializes it to toggle an object's datamember using this object's method. void TToggle::SetToggledObject(TObject *obj, TMethod *anymethod) { - fObject = obj; - TDataMember *m = anymethod->FindDataMember(); - if (!m) { - // try to see if the TMethod has a getter associated via the *GETTER= - // comment string - if (anymethod->GetterMethod()) { - fGetter = anymethod->GetterMethod(); - fSetter = anymethod->SetterMethod(); - fInitialized = 1; - } else - Error("SetToggledObject", "cannot determine getter method for %s", anymethod->GetName()); - } else { - fGetter = m->GetterMethod(obj->IsA()); - fSetter = m->SetterMethod(obj->IsA()); - fInitialized = 1; + TDataMember *member = anymethod->FindDataMember(); + if (member) + TToggle::SetToggledObject(obj, member); + else if (!anymethod) + Error("SetToggledObject", "Method pointer not provided"); + else if (!anymethod->GetterMethod()) + Error("SetToggledObject", "cannot determine getter method for %s", anymethod->GetName()); + else { + // try to see if the TMethod has a getter associated via the *GETTER= comment string + fObject = obj; + // TMethodCall pointer can be stored - it is not recerated + fGetter = anymethod->GetterMethod(); + fSetter = anymethod->SetterMethod(); + fInitialized = 2; } } + +//////////////////////////////////////////////////////////////////////////////// +/// Initializes it to toggle an object's datamember + +void TToggle::SetToggledObject(TObject *obj, TDataMember *member) +{ + fObject = obj; + fMember = member; + fInitialized = 1; + + // one cannot remember TMethodCall pointers from TDataMember + // while they will be recreated any time they requested again + fGetter = nullptr; + fSetter = nullptr; +} + + +//////////////////////////////////////////////////////////////////////////////// +/// return getter method +/// request new for the TDataMember while it can be recreated at any time + +TMethodCall *TToggle::GetGetter() const +{ + if ((fInitialized == 1) && fMember && fObject) + return const_cast(fMember)->GetterMethod(fObject->IsA()); + + return fGetter; +} + +//////////////////////////////////////////////////////////////////////////////// +/// return setter method +/// request new for the TDataMember while it can be recreated at any time + +TMethodCall *TToggle::GetSetter() const +{ + if ((fInitialized == 1) && fMember && fObject) + return const_cast(fMember)->SetterMethod(fObject->IsA()); + + return fSetter; +} diff --git a/core/meta/src/TDataMember.cxx b/core/meta/src/TDataMember.cxx index b284df90d2c4b..6bc17e4362c8b 100644 --- a/core/meta/src/TDataMember.cxx +++ b/core/meta/src/TDataMember.cxx @@ -152,6 +152,7 @@ but also in Dump() and Inspect() methods and by the THtml class. #include "TList.h" #include "TListOfDataMembers.h" #include "TMethod.h" +#include "TMethodArg.h" #include "TMethodCall.h" #include "TRealData.h" #include "TROOT.h" @@ -728,9 +729,16 @@ void TDataMember::ExtractOptionsFromComment() Fatal("TDataMember","Internal error, found \"SetMethod\" but not \"\\\"\" in %s.",GetTitle()); return; } + // setter method may accept enum data type - therefore check if it exists at all if (GetClass()->GetMethod(ptr1,"1")) // FIXME: wrong in case called derives via multiple inheritance from this class - fValueSetter = new TMethodCall(GetClass(),ptr1,"1"); + fValueSetter = new TMethodCall(GetClass(), ptr1, "1"); + else if (auto method = IsEnum() ? GetClass()->GetMethodAny(ptr1) : nullptr) { + // if data member is enum, take setter and cast 1 to argument data type + auto arg = dynamic_cast(method->GetListOfMethodArgs()->First()); + auto sarg = TString::Format("(%s) 1", arg ? arg->GetFullTypeName() : "int"); + fValueSetter = new TMethodCall(GetClass(), ptr1, sarg.Data()); + } } } diff --git a/gui/gui/src/TRootContextMenu.cxx b/gui/gui/src/TRootContextMenu.cxx index 6d76afb4fadd5..51892b6611bd9 100644 --- a/gui/gui/src/TRootContextMenu.cxx +++ b/gui/gui/src/TRootContextMenu.cxx @@ -270,20 +270,18 @@ void TRootContextMenu::CreateMenu(TObject *object) TList *methodList = new TList; object->IsA()->GetMenuItems(methodList); - TMethod *method; - TClass *classPtr = 0; + TClass *classPtr = nullptr; TIter next(methodList); Bool_t needSep = kFALSE; - while ((method = (TMethod*) next())) { + while (auto method = (TMethod*) next()) { if (classPtr != method->GetClass()) { needSep = kTRUE; classPtr = method->GetClass(); } - TDataMember *m; EMenuItemKind menuKind = method->IsMenuItem(); - TGPopupMenu *currentMenu = 0; + TGPopupMenu *currentMenu = nullptr; TString last_component; switch (menuKind) { @@ -297,12 +295,12 @@ void TRootContextMenu::CreateMenu(TObject *object) AddEntrySorted(currentMenu,last_component.Length() ? last_component.Data() : method->GetName(), entry++, method,0,currentMenu != this); break; case kMenuSubMenu: - if ((m = method->FindDataMember())) { + if (auto member = method->FindDataMember()) { // search for arguments to the MENU statement currentMenu = FindHierarchy(method->GetCommentString(),last_component); - if (m->GetterMethod()) { + if (member->GetterMethod()) { TGPopupMenu *r = new TGPopupMenu(gClient->GetDefaultRoot()); if (needSep && currentMenu == this) { AddSeparator(); @@ -314,18 +312,14 @@ void TRootContextMenu::CreateMenu(TObject *object) currentMenu->AddPopup(method->GetName(), r); } fTrash->Add(r); - TIter nxt(m->GetOptions()); - TOptionListItem *it; - while ((it = (TOptionListItem*) nxt())) { - const char *name = it->fOptName; - Long_t val = it->fValue; - + TIter nxt(member->GetOptions()); + while (auto it = (TOptionListItem*) nxt()) { TToggle *t = new TToggle; - t->SetToggledObject(object, method); - t->SetOnValue(val); + t->SetToggledObject(object, member); + t->SetOnValue(it->fValue); fTrash->Add(t); - r->AddEntry(name, togglelist++, t); + r->AddEntry(it->fOptName, togglelist++, t); if (t->GetState()) r->CheckEntry(togglelist-1); }