Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:27:12

0001 // -*- C++ -*-
0002 //
0003 // Package:     Core
0004 // Class  :     FWEveViewManager
0005 //
0006 // Implementation:
0007 //     [Notes on implementation]
0008 //
0009 // Original Author:  Chris Jones, Alja Mrak-Tadel
0010 //         Created:  Thu Mar 18 14:11:32 CET 2010
0011 //
0012 
0013 // system include files
0014 
0015 #include <functional>
0016 
0017 // user include files
0018 #include "TEveManager.h"
0019 #include "TEveSelection.h"
0020 #include "TEveScene.h"
0021 #include "TEveViewer.h"
0022 #include "TEveCalo.h"
0023 #include "TEveGedEditor.h"
0024 #include "TGListTree.h"
0025 #include "TGeoManager.h"
0026 #include "TExMap.h"
0027 #include "TEnv.h"
0028 
0029 #include "Fireworks/Core/interface/FWEveViewManager.h"
0030 #include "Fireworks/Core/interface/FWSelectionManager.h"
0031 #include "Fireworks/Core/interface/FWColorManager.h"
0032 #include "Fireworks/Core/interface/Context.h"
0033 #include "Fireworks/Core/interface/FWInteractionList.h"
0034 #include "Fireworks/Core/interface/CmsShowCommon.h"
0035 #include "Fireworks/Core/interface/fwLog.h"
0036 #include "Fireworks/Core/interface/FWViewEnergyScale.h"
0037 #include "Fireworks/Core/interface/FWSimpleRepresentationChecker.h"
0038 
0039 // PB
0040 #include "Fireworks/Core/interface/FWEDProductRepresentationChecker.h"
0041 #include "Fireworks/Core/interface/FWSimpleRepresentationChecker.h"
0042 #include "Fireworks/Core/interface/FWTypeToRepresentations.h"
0043 #include "Fireworks/Core/interface/FWEventItem.h"
0044 #include "Fireworks/Core/interface/FWProxyBuilderFactory.h"
0045 #include "Fireworks/Core/interface/FWProxyBuilderBase.h"
0046 
0047 // viewes
0048 #include "Fireworks/Core/interface/FWGUIManager.h"
0049 #include "Fireworks/Core/interface/FWISpyView.h"
0050 #include "Fireworks/Core/interface/FW3DView.h"
0051 #include "Fireworks/Core/interface/FWGlimpseView.h"
0052 #include "Fireworks/Core/interface/FWEveLegoView.h"
0053 #include "Fireworks/Core/interface/FWHFView.h"
0054 #include "Fireworks/Core/interface/FWRPZView.h"
0055 
0056 #include "Fireworks/Core/interface/FWTGLViewer.h"
0057 bool FWEveViewManager::s_syncAllViews = false;
0058 
0059 class FWViewContext;
0060 
0061 // sentry class block TEveSelection signals when call TEveSelection::Remove/AddElement and
0062 // when process its callbacks
0063 class EveSelectionSentry {
0064 public:
0065   EveSelectionSentry() { m_blocked = gEve->GetSelection()->BlockSignals(true); }
0066   ~EveSelectionSentry() { gEve->GetSelection()->BlockSignals(m_blocked); }
0067 
0068 private:
0069   bool m_blocked;
0070 };
0071 
0072 //
0073 //
0074 // constants, enums and typedefs
0075 //
0076 //
0077 // constructors and destructor
0078 //
0079 FWEveViewManager::FWEveViewManager(FWGUIManager* iGUIMgr) : FWViewManagerBase() {
0080   // builders
0081   std::set<std::string> builders;
0082 
0083   std::vector<edmplugin::PluginInfo> available = FWProxyBuilderFactory::get()->available();
0084   std::transform(available.begin(),
0085                  available.end(),
0086                  std::inserter(builders, builders.begin()),
0087                  std::bind(&edmplugin::PluginInfo::name_, std::placeholders::_1));
0088 
0089   if (edmplugin::PluginManager::get()->categoryToInfos().end() !=
0090       edmplugin::PluginManager::get()->categoryToInfos().find(FWProxyBuilderFactory::get()->category())) {
0091     available =
0092         edmplugin::PluginManager::get()->categoryToInfos().find(FWProxyBuilderFactory::get()->category())->second;
0093     std::transform(available.begin(),
0094                    available.end(),
0095                    std::inserter(builders, builders.begin()),
0096                    std::bind(&edmplugin::PluginInfo::name_, std::placeholders::_1));
0097   }
0098 
0099   for (std::set<std::string>::iterator it = builders.begin(), itEnd = builders.end(); it != itEnd; ++it) {
0100     std::string::size_type first = it->find_first_of('@') + 1;
0101     std::string purpose = it->substr(first, it->find_last_of('@') - first);
0102 
0103     first = it->find_last_of('@') + 1;
0104     std::string view_str = it->substr(first, it->find_last_of('#') - first);
0105     int viewTypes = atoi(view_str.c_str());
0106     std::string fullName = *it;
0107     m_typeToBuilder[purpose].push_back(BuilderInfo(*it, viewTypes));
0108   }
0109 
0110   m_views.resize(FWViewType::kTypeSize);
0111 
0112   // view construction called via GUI mng
0113   FWGUIManager::ViewBuildFunctor f =
0114       std::bind(&FWEveViewManager::buildView, this, std::placeholders::_1, std::placeholders::_2);
0115   for (int i = 0; i < FWViewType::kTypeSize; i++) {
0116     if (i == FWViewType::kTable || i == FWViewType::kTableHLT || i == FWViewType::kTableL1)
0117       continue;
0118     iGUIMgr->registerViewBuilder(FWViewType::idToName(i), f);
0119   }
0120 
0121   // signal
0122   gEve->GetHighlight()->SetPickToSelect(TEveSelection::kPS_Master);
0123   TEveSelection* eveSelection = gEve->GetSelection();
0124   eveSelection->SetPickToSelect(TEveSelection::kPS_Master);
0125   eveSelection->Connect("SelectionAdded(TEveElement*)", "FWEveViewManager", this, "selectionAdded(TEveElement*)");
0126   eveSelection->Connect("SelectionRepeated(TEveElement*)", "FWEveViewManager", this, "selectionAdded(TEveElement*)");
0127   eveSelection->Connect("SelectionRemoved(TEveElement*)", "FWEveViewManager", this, "selectionRemoved(TEveElement*)");
0128   eveSelection->Connect("SelectionCleared()", "FWEveViewManager", this, "selectionCleared()");
0129 
0130   gEve->GetHighlight()->Connect(
0131       "SelectionAdded(TEveElement*)", "FWEveViewManager", this, "highlightAdded(TEveElement*)");
0132   gEve->GetHighlight()->Connect(
0133       "SelectionRepeated(TEveElement*)", "FWEveViewManager", this, "highlightAdded(TEveElement*)");
0134 
0135   TGeoManager::SetVerboseLevel(0);
0136 }
0137 
0138 FWEveViewManager::~FWEveViewManager() {}
0139 
0140 //
0141 // member functions
0142 //
0143 
0144 //______________________________________________________________________________
0145 
0146 /**
0147    Helper function to add products from a given builder to a given view.
0148    FWRPZView is a base class for all projected views 
0149     (name derives from  FWViewType::RPhi and FWViewType::RhoZ projection).
0150   */
0151 void addElements(const FWEventItem* item, FWEveView* view, int viewType, TEveElementList* product) {
0152   if (FWViewType::isProjected(viewType)) {
0153     FWRPZView* rpzView = dynamic_cast<FWRPZView*>(view);
0154     assert(rpzView);
0155     rpzView->importElements(product, item->layer(), rpzView->eventScene());
0156   } else {
0157     view->eventScene()->AddElement(product);
0158   }
0159 }
0160 
0161 /** This  is  invoked  when  a  new  item  is  created
0162     by  the  FWEventItemsManager.  The  workflow  is  the  following
0163 
0164    1.  First  we  check  if  we  have  a  builder  info  for  the  given  purpose  of  the
0165        item.  We  return  simply  if  we  don't.
0166    2.  We  iterate  over  all  the  proxy  builder  registered  for  the  given
0167        purpose  and  create  a  new  one  for  this  given  item.
0168    3.  Interaction  lists  are  set  up  in  case  the  proxy  builder  does  not  handle
0169        interaction  by  itself.
0170    4.  We  then  iterate  on  the  various  supported  views  and  add  elements  to  them,
0171        making  sure  that  we  handle  the  case  in  which  those  elements  are  not
0172        unique  among  all  the  views.
0173   */
0174 
0175 void FWEveViewManager::newItem(const FWEventItem* iItem) {
0176   TypeToBuilder::iterator itFind = m_typeToBuilder.find(iItem->purpose());
0177 
0178   if (itFind == m_typeToBuilder.end())
0179     return;
0180 
0181   std::vector<BuilderInfo>& blist = itFind->second;
0182 
0183   std::string bType;
0184   bool bIsSimple;
0185   for (size_t bii = 0, bie = blist.size(); bii != bie; ++bii) {
0186     // 1.
0187     BuilderInfo& info = blist[bii];
0188     info.classType(bType, bIsSimple);
0189     if (bIsSimple) {
0190       unsigned int distance = 1;
0191       edm::TypeWithDict modelType(*(iItem->modelType()->GetTypeInfo()));
0192       if (!FWSimpleRepresentationChecker::inheritsFrom(modelType, bType, distance)) {
0193         // printf("PB does not matche itemType (%s) !!! EDproduct %s %s\n", info.m_name.c_str(), iItem->modelType()->GetTypeInfo()->name(), bType.c_str() );
0194         continue;
0195       }
0196     } else {
0197       std::string itype = iItem->type()->GetTypeInfo()->name();
0198       if (itype != bType) {
0199         // printf("PB does not match modeType (%s)!!! EDproduct %s %s\n", info.m_name.c_str(), itype.c_str(), bType.c_str() );
0200         continue;
0201       }
0202     }
0203 
0204     std::string builderName = info.m_name;
0205     int builderViewBit = info.m_viewBit;
0206 
0207     std::shared_ptr<FWProxyBuilderBase> builder;
0208     try {
0209       builder = std::shared_ptr<FWProxyBuilderBase>{FWProxyBuilderFactory::get()->create(builderName)};
0210 
0211     } catch (std::exception& exc) {
0212       fwLog(fwlog::kWarning)
0213           << "FWEveViewManager::newItem ignoring the following exception (probably edmplugincache mismatch):"
0214           << std::endl
0215           << exc.what();
0216     }
0217     if (!builder)
0218       continue;
0219 
0220     // 2.
0221     // printf("FWEveViewManager::makeProxyBuilderFor NEW builder %s \n", builderName.c_str());
0222 
0223     builder->setItem(iItem);
0224     iItem->changed_.connect(std::bind(&FWEveViewManager::modelChanges, this, std::placeholders::_1));
0225     iItem->goingToBeDestroyed_.connect(std::bind(&FWEveViewManager::removeItem, this, std::placeholders::_1));
0226     iItem->itemChanged_.connect(std::bind(&FWEveViewManager::itemChanged, this, std::placeholders::_1));
0227 
0228     // 3.
0229     // This calud be opaque to the user. I would pass a reference to the m_interactionLists to
0230     // FWProxyBuilderBase::setInteractionList and handle different case differently.
0231     if (builder->willHandleInteraction() == false) {
0232       typedef std::map<const FWEventItem*, FWInteractionList*>::iterator Iterator;
0233       std::pair<Iterator, bool> t = m_interactionLists.insert(std::make_pair(iItem, (FWInteractionList*)nullptr));
0234 
0235       if (t.second == true)
0236         t.first->second = new FWInteractionList(iItem);
0237       //  printf(">>> builder %s add list %p \n", iItem->name().c_str(), il); fflush(stdout);
0238       builder->setInteractionList(t.first->second, iItem->purpose());
0239     }
0240 
0241     builder->setHaveWindow(haveViewForBit(builderViewBit));
0242 
0243     // 4.
0244     for (size_t viewType = 0; viewType < FWViewType::kTypeSize; ++viewType) {
0245       if (((1 << viewType) & builderViewBit) == 0)
0246         continue;
0247 
0248       FWViewType::EType type = (FWViewType::EType)viewType;
0249 
0250       // printf("%s builder %s supportsd view %s \n",  iItem->name().c_str(), builderName.c_str(), FWViewType::idToName(viewType).c_str());
0251       if (builder->havePerViewProduct((FWViewType::EType)viewType)) {
0252         for (size_t i = 0, e = m_views[viewType].size(); i != e; ++i) {
0253           FWEveView* view = m_views[viewType][i].get();
0254           TEveElementList* product = builder->createProduct(type, view->viewContext());
0255           addElements(iItem, view, viewType, product);
0256         }
0257       } else {
0258         TEveElementList* product = builder->createProduct(type, nullptr);
0259 
0260         for (size_t i = 0, e = m_views[viewType].size(); i != e; ++i)
0261           addElements(iItem, m_views[viewType][i].get(), viewType, product);
0262       }
0263     }
0264 
0265     m_builders[builderViewBit].emplace_back(std::move(builder));
0266   }  // loop views
0267 }
0268 
0269 //______________________________________________________________________________
0270 FWViewBase* FWEveViewManager::buildView(TEveWindowSlot* iParent, const std::string& viewName) {
0271   FWViewType::EType type = FWViewType::kTypeSize;
0272   for (int i = 0; i < FWViewType::kTypeSize; ++i) {
0273     if (viewName == FWViewType::idToName(i)) {
0274       type = FWViewType::EType(i);
0275       break;
0276     }
0277   }
0278 
0279   std::shared_ptr<FWEveView> view;
0280   switch (type) {
0281     case FWViewType::k3D:
0282       view.reset(new FW3DView(iParent, type));
0283       break;
0284     case FWViewType::kISpy:
0285       view.reset(new FWISpyView(iParent, type));
0286       break;
0287     case FWViewType::kRhoPhi:
0288     case FWViewType::kRhoZ:
0289     case FWViewType::kRhoPhiPF:
0290       view.reset(new FWRPZView(iParent, type));
0291       break;
0292     case FWViewType::kLego:
0293     case FWViewType::kLegoPFECAL:
0294       view.reset(new FWEveLegoView(iParent, type));
0295       break;
0296     case FWViewType::kLegoHF:
0297       view.reset(new FWHFView(iParent, type));
0298       break;
0299     case FWViewType::kGlimpse:
0300       view.reset(new FWGlimpseView(iParent, type));
0301       break;
0302     default:
0303       break;
0304   }
0305 
0306   m_views[type].push_back(std::shared_ptr<FWEveView>(view));
0307   return finishViewCreate(m_views[type].back());
0308 }
0309 
0310 FWEveView* FWEveViewManager::finishViewCreate(std::shared_ptr<FWEveView> view) {
0311   // printf("new view %s added \n", view->typeName().c_str());
0312   gEve->DisableRedraw();
0313 
0314   // set geometry and calo data
0315   view->setContext(context());
0316 
0317   FWColorManager::setColorSetViewer(view->viewerGL(), context().colorManager()->background());
0318 
0319   // set proxies have a window falg
0320   int viewerBit = 1 << view->typeId();
0321   if (m_views[view->typeId()].size() == 1) {
0322     for (std::map<int, BuilderVec>::iterator i = m_builders.begin(); i != m_builders.end(); ++i) {
0323       int builderViewBit = i->first;
0324       BuilderVec& bv = i->second;
0325       if (viewerBit == (builderViewBit & viewerBit)) {
0326         for (BuilderVec_it bIt = bv.begin(); bIt != bv.end(); ++bIt) {
0327           (*bIt)->setHaveWindow(true);
0328         }
0329       }
0330     }
0331   }
0332 
0333   FWRPZView* rpzView = dynamic_cast<FWRPZView*>(view.get());
0334   for (std::map<int, BuilderVec>::iterator i = m_builders.begin(); i != m_builders.end(); ++i) {
0335     int builderViewBit = i->first;
0336     BuilderVec& bv = i->second;
0337     if (viewerBit == (builderViewBit & viewerBit)) {
0338       for (BuilderVec_it bIt = bv.begin(); bIt != bv.end(); ++bIt) {
0339         // it is ok to call create even for shared productsm since
0340         // builder map key garanties that
0341         TEveElementList* product = (*bIt)->createProduct(view->typeId(), view->viewContext());
0342 
0343         if ((*bIt)->havePerViewProduct((FWViewType::EType)view->typeId())) {
0344           // view owned
0345           (*bIt)->build();
0346           if (rpzView) {
0347             rpzView->importElements(product, (*bIt)->item()->layer(), rpzView->ownedProducts());
0348           } else {
0349             view->ownedProducts()->AddElement(product);
0350           }
0351         } else {
0352           // shared
0353           if (rpzView) {
0354             rpzView->importElements(product, (*bIt)->item()->layer(), rpzView->eventScene());
0355           } else {
0356             view->eventScene()->AddElement(product);
0357           }
0358         }
0359       }
0360     }
0361   }
0362 
0363   view->beingDestroyed_.connect(std::bind(&FWEveViewManager::beingDestroyed, this, std::placeholders::_1));
0364 
0365   view->setupEnergyScale();  // notify PB for energy scale
0366 
0367   gEve->EnableRedraw();
0368   view->viewerGL()->UpdateScene();
0369   gEve->Redraw3D();
0370 
0371   return view.get();
0372 }
0373 
0374 void FWEveViewManager::beingDestroyed(const FWViewBase* vb) {
0375   FWEveView* view = (FWEveView*)vb;
0376   int typeId = view->typeId();
0377 
0378   int viewerBit = 1 << typeId;
0379   int nviews = m_views[typeId].size();
0380   for (std::map<int, BuilderVec>::iterator i = m_builders.begin(); i != m_builders.end(); ++i) {
0381     int builderBit = i->first;
0382     if (viewerBit == (builderBit & viewerBit))  // check only in case if connected
0383     {
0384       BuilderVec& bv = i->second;
0385 
0386       // remove view-owned product
0387       if (viewerBit == (builderBit & viewerBit)) {
0388         for (BuilderVec_it bIt = bv.begin(); bIt != bv.end(); ++bIt)
0389           (*bIt)->removePerViewProduct(view->typeId(), view->viewContext());
0390       }
0391 
0392       // and setup proxy builders have-a-window flag
0393       if (nviews == 1) {
0394         if (!haveViewForBit(builderBit)) {
0395           if (viewerBit == (builderBit & viewerBit)) {
0396             for (BuilderVec_it bIt = bv.begin(); bIt != bv.end(); ++bIt)
0397               (*bIt)->setHaveWindow(false);
0398           }
0399         }
0400       }
0401     }
0402   }
0403 
0404   for (EveViewVec_it i = m_views[typeId].begin(); i != m_views[typeId].end(); ++i) {
0405     if (i->get() == vb) {
0406       m_views[typeId].erase(i);
0407       break;
0408     }
0409   }
0410 }
0411 
0412 //______________________________________________________________________________
0413 
0414 void FWEveViewManager::modelChangesComing() { gEve->DisableRedraw(); }
0415 
0416 void FWEveViewManager::modelChangesDone() { gEve->EnableRedraw(); }
0417 
0418 /** Callback of event item changed_ signal.*/
0419 void FWEveViewManager::modelChanges(const FWModelIds& iIds) {
0420   FWModelId id = *(iIds.begin());
0421   const FWEventItem* item = id.item();
0422 
0423   // in standard case new elements can be build in case of change of visibility
0424   // and in non-standard case (e.g. calo towers) PB's modelChages handles all changes
0425   bool itemHaveWindow = false;
0426   for (std::map<int, BuilderVec>::iterator i = m_builders.begin(); i != m_builders.end(); ++i) {
0427     for (size_t bi = 0, be = i->second.size(); bi != be; ++bi) {
0428       FWProxyBuilderBase* builder = i->second[bi].get();
0429       if (builder->getHaveWindow() && builder->item() == item) {
0430         builder->modelChanges(iIds);
0431         itemHaveWindow = true;
0432       }
0433     }
0434   }
0435 
0436   if (!itemHaveWindow)
0437     return;
0438 
0439   EveSelectionSentry();
0440 
0441   std::map<const FWEventItem*, FWInteractionList*>::iterator it = m_interactionLists.find(item);
0442   if (it != m_interactionLists.end()) {
0443     if (!it->second->empty())
0444       it->second->modelChanges(iIds);
0445   }
0446 }
0447 
0448 /** Callback of itemChanged_ signal.
0449     Iterate over all the builders for all the views and call itemChanged
0450     for any of the builders.
0451     If any of the builder also has at least one view, also update the interaction list.
0452 */
0453 void FWEveViewManager::itemChanged(const FWEventItem* item) {
0454   if (!item)
0455     return;
0456 
0457   bool itemHaveWindow = false;
0458 
0459   for (std::map<int, BuilderVec>::iterator i = m_builders.begin(); i != m_builders.end(); ++i) {
0460     for (size_t bi = 0, be = i->second.size(); bi != be; ++bi) {
0461       FWProxyBuilderBase* builder = i->second[bi].get();
0462 
0463       if (builder->item() != item)
0464         continue;
0465 
0466       builder->itemChanged(item);
0467       itemHaveWindow |= builder->getHaveWindow();
0468     }
0469   }
0470 
0471   if (!itemHaveWindow)
0472     return;
0473 
0474   std::map<const FWEventItem*, FWInteractionList*>::iterator it = m_interactionLists.find(item);
0475   if (it != m_interactionLists.end()) {
0476     if (!it->second->empty())
0477       it->second->itemChanged();
0478   }
0479 }
0480 
0481 /** Remove an item from the given view.
0482   */
0483 void FWEveViewManager::removeItem(const FWEventItem* item) {
0484   EveSelectionSentry();
0485 
0486   std::map<const FWEventItem*, FWInteractionList*>::iterator it = m_interactionLists.find(item);
0487   if (it != m_interactionLists.end()) {
0488     delete it->second;
0489     m_interactionLists.erase(it);
0490   }
0491 
0492   for (std::map<int, BuilderVec>::iterator i = m_builders.begin(); i != m_builders.end(); ++i) {
0493     BuilderVec_it bIt = i->second.begin();
0494     while (bIt != i->second.end()) {
0495       if ((*bIt)->item() == item) {
0496         // TODO caching of proxy builders
0497         (*bIt)->itemBeingDestroyed(item);
0498         bIt = i->second.erase(bIt);
0499       } else {
0500         ++bIt;
0501       }
0502     }
0503   }
0504 }
0505 
0506 void FWEveViewManager::setContext(const fireworks::Context* x) {
0507   FWViewManagerBase::setContext(x);
0508   x->commonPrefs()->getEnergyScale()->parameterChanged_.connect(
0509       std::bind(&FWEveViewManager::globalEnergyScaleChanged, this));
0510   x->commonPrefs()->eventCenterChanged_.connect(std::bind(&FWEveViewManager::eventCenterChanged, this));
0511 }
0512 
0513 void FWEveViewManager::globalEnergyScaleChanged() {
0514   for (int t = 0; t < FWViewType::kTypeSize; ++t) {
0515     for (EveViewVec_it i = m_views[t].begin(); i != m_views[t].end(); ++i) {
0516       if ((*i)->isEnergyScaleGlobal()) {
0517         (*i)->setupEnergyScale();
0518       }
0519     }
0520   }
0521 }
0522 
0523 void FWEveViewManager::eventCenterChanged() {
0524   for (int t = 0; t < FWViewType::kTypeSize; ++t) {
0525     for (EveViewVec_it i = m_views[t].begin(); i != m_views[t].end(); ++i) {
0526       (*i)->setupEventCenter();
0527     }
0528   }
0529 }
0530 
0531 void FWEveViewManager::colorsChanged() {
0532   for (int t = 0; t < FWViewType::kTypeSize; ++t) {
0533     for (EveViewVec_it i = m_views[t].begin(); i != m_views[t].end(); ++i)
0534       (*i)->setBackgroundColor(colorManager().background());
0535   }
0536 }
0537 
0538 //______________________________________________________________________________
0539 void FWEveViewManager::eventBegin() {
0540   // Prevent registration of redraw timer, full redraw is done in
0541   // FWEveViewManager::eventEnd().
0542   gEve->EnforceTimerActive(kTRUE);
0543   gEve->DisableRedraw();
0544 
0545   context().resetMaxEtAndEnergy();
0546 
0547   for (int t = 0; t < FWViewType::kTypeSize; ++t) {
0548     for (EveViewVec_it i = m_views[t].begin(); i != m_views[t].end(); ++i)
0549       (*i)->eventBegin();
0550   }
0551 }
0552 
0553 void FWEveViewManager::eventEnd() {
0554   for (int t = 0; t < FWViewType::kTypeSize; ++t) {
0555     for (EveViewVec_it i = m_views[t].begin(); i != m_views[t].end(); ++i)
0556       (*i)->eventEnd();
0557   }
0558 
0559   // What follows is a copy of TEveManager::DoRedraw3D() with the difference that
0560   // we have full control over execution of GL view rendering. In particular:
0561   // - optionally delay buffer swapping so they can all be swapped together;
0562   // - we could render into FBO once and then use this to be put on screen
0563   //   and saved into an image file.
0564 
0565   {
0566     TEveElement::List_t scenes;
0567     Long64_t key, value;
0568     TExMapIter stamped_elements(gEve->PtrToStampedElements());
0569     while (stamped_elements.Next(key, value)) {
0570       TEveElement* el = reinterpret_cast<TEveElement*>(key);
0571       if (el->GetChangeBits() & TEveElement::kCBVisibility) {
0572         el->CollectSceneParents(scenes);
0573       }
0574     }
0575     gEve->ScenesChanged(scenes);
0576   }
0577 
0578   // Process changes in scenes.
0579   gEve->GetScenes()->ProcessSceneChanges(kFALSE, gEve->PtrToStampedElements());
0580 
0581   // To synchronize buffer swapping set swap_on_render to false.
0582   // Note that this costs 25-40% extra time with 4 views, depending on V-sync settings.
0583   // Tested with NVIDIA 343.22.
0584   const bool swap_on_render = !s_syncAllViews;
0585 
0586   // Loop over viewers, swap buffers if swap_on_render is true.
0587   for (int t = 0; t < FWViewType::kTypeSize; ++t) {
0588     for (EveViewVec_it i = m_views[t].begin(); i != m_views[t].end(); ++i)
0589       (*i)->fwViewerGL()->DrawHiLod(swap_on_render);
0590   }
0591 
0592   // Swap buffers if they were not swapped before.
0593   if (!swap_on_render) {
0594     for (int t = 0; t < FWViewType::kTypeSize; ++t) {
0595       for (EveViewVec_it i = m_views[t].begin(); i != m_views[t].end(); ++i)
0596         (*i)->fwViewerGL()->JustSwap();
0597     }
0598   }
0599 
0600   gEve->GetViewers()->RepaintChangedViewers(kFALSE, kFALSE);
0601 
0602   {
0603     Long64_t key, value;
0604     TExMapIter stamped_elements(gEve->PtrToStampedElements());
0605     while (stamped_elements.Next(key, value)) {
0606       TEveElement* el = reinterpret_cast<TEveElement*>(key);
0607       if (gEve->GetEditor()->GetModel() == el->GetEditorObject("FWEveViewManager::eventEnd"))
0608         gEve->EditElement(el);
0609       TEveGedEditor::ElementChanged(el);
0610 
0611       el->ClearStamps();
0612     }
0613   }
0614   gEve->PtrToStampedElements()->Delete();
0615 
0616   gEve->GetListTree()->ClearViewPort();  // Fix this when several list-trees can be added.
0617 
0618   gEve->EnableRedraw();
0619   gEve->EnforceTimerActive(kFALSE);
0620 }
0621 
0622 //______________________________________________________________________________
0623 
0624 /** Helper function to extract the FWFromEveSelectorBase * from an TEveElement.
0625   */
0626 FWFromEveSelectorBase* getSelector(TEveElement* iElement) {
0627   if (!iElement)
0628     return nullptr;
0629 
0630   //std::cout <<"  non null"<<std::endl;
0631   void* userData = iElement->GetUserData();
0632   //std::cout <<"  user data "<<userData<<std::endl;
0633   if (!userData)
0634     return nullptr;
0635 
0636   //std::cout <<"    have userData"<<std::endl;
0637   //std::cout <<"      calo"<<std::endl;
0638   EveSelectionSentry();
0639   return reinterpret_cast<FWFromEveSelectorBase*>(userData);
0640 }
0641 
0642 void FWEveViewManager::selectionAdded(TEveElement* iElement) {
0643   FWFromEveSelectorBase* selector = getSelector(iElement);
0644   if (selector)
0645     selector->doSelect();
0646 }
0647 
0648 void FWEveViewManager::selectionRemoved(TEveElement* iElement) {
0649   FWFromEveSelectorBase* selector = getSelector(iElement);
0650   if (selector)
0651     selector->doUnselect();
0652 }
0653 
0654 void FWEveViewManager::selectionCleared() { context().selectionManager()->clearSelection(); }
0655 
0656 //
0657 // const member functions
0658 //
0659 
0660 FWTypeToRepresentations FWEveViewManager::supportedTypesAndRepresentations() const {
0661   // needed for add collection GUI
0662   FWTypeToRepresentations returnValue;
0663   const static std::string kFullFrameWorkPBExtension = "FullFramework";
0664   for (TypeToBuilder::const_iterator it = m_typeToBuilder.begin(), itEnd = m_typeToBuilder.end(); it != itEnd; ++it) {
0665     std::vector<BuilderInfo> blist = it->second;
0666     for (size_t bii = 0, bie = blist.size(); bii != bie; ++bii) {
0667       BuilderInfo& info = blist[bii];
0668 
0669       if (context().getHidePFBuilders()) {
0670         const static std::string pfExt = "PF ";
0671         if (std::string::npos != info.m_name.find(pfExt))
0672           continue;
0673       }
0674 
0675       unsigned int bitPackedViews = info.m_viewBit;
0676       bool representsSubPart = (info.m_name.substr(info.m_name.find_first_of('@') - 1, 1) == "!");
0677       size_t extp = info.m_name.rfind(kFullFrameWorkPBExtension);
0678       bool FFOnly = (extp != std::string::npos);
0679 
0680       std::string name;
0681       bool isSimple;
0682       info.classType(name, isSimple);
0683       if (isSimple) {
0684         returnValue.add(std::make_shared<FWSimpleRepresentationChecker>(
0685             name, it->first, bitPackedViews, representsSubPart, FFOnly));
0686       } else {
0687         returnValue.add(std::make_shared<FWEDProductRepresentationChecker>(
0688             name, it->first, bitPackedViews, representsSubPart, FFOnly));
0689       }
0690     }
0691   }
0692   return returnValue;
0693 }
0694 
0695 /** Checks whether any of the views */
0696 bool FWEveViewManager::haveViewForBit(int bit) const {
0697   for (int t = 0; t < FWViewType::kTypeSize; ++t) {
0698     if ((bit & (1 << t)) && !m_views[t].empty())
0699       return true;
0700   }
0701   // printf("have %d view for bit %d \n", haveView, bit);
0702   return false;
0703 }
0704 
0705 void FWEveViewManager::BuilderInfo::classType(std::string& typeName, bool& simple) const {
0706   const std::string kSimple("simple#");
0707   simple = (m_name.substr(0, kSimple.size()) == kSimple);
0708   if (simple) {
0709     typeName = m_name.substr(kSimple.size(), m_name.find_first_of('@') - kSimple.size() - 1);
0710   } else {
0711     typeName = m_name.substr(0, m_name.find_first_of('@') - 1);
0712   }
0713 }
0714 
0715 /*
0716 AMT: temporary workaround for using TEveCaloDataHist instead of
0717 TEveCaloDataVec. 
0718 
0719  */
0720 
0721 #include "TH2F.h"
0722 #include "TAxis.h"
0723 #include "TEveCaloData.h"
0724 
0725 void FWEveViewManager::highlightAdded(TEveElement* iElement) {
0726   bool blocked = gEve->GetHighlight()->BlockSignals(true);
0727 
0728   if (iElement == context().getCaloData()) {
0729     TEveCaloData::vCellId_t& hlist = context().getCaloData()->GetCellsHighlighted();
0730     std::set<TEveCaloData::CellId_t> hset;
0731 
0732     int etaBin, phiBin, w, newPhiBin, tower;
0733     TH2F* hist = context().getCaloData()->GetHist(0);
0734     TAxis* etaAxis = hist->GetXaxis();
0735     int nBinsX = etaAxis->GetNbins() + 2;
0736 
0737     for (TEveCaloData::vCellId_i i = hlist.begin(); i != hlist.end(); ++i) {
0738       hist->GetBinXYZ((*i).fTower, etaBin, phiBin, w);
0739       if (TMath::Abs(etaAxis->GetBinCenter(etaBin)) > 4.71475) {
0740         newPhiBin = ((phiBin + 1) / 4) * 4 - 1;
0741         if (newPhiBin <= 0)
0742           newPhiBin = 71;
0743 
0744         tower = etaBin + newPhiBin * nBinsX;
0745         hset.insert(TEveCaloData::CellId_t(tower, (*i).fSlice, (*i).fFraction));
0746         tower += nBinsX;
0747         hset.insert(TEveCaloData::CellId_t(tower, (*i).fSlice, (*i).fFraction));
0748         tower += nBinsX;
0749 
0750         if (newPhiBin == 71)
0751           tower = etaBin + 1 * nBinsX;
0752 
0753         hset.insert(TEveCaloData::CellId_t(tower, (*i).fSlice, (*i).fFraction));
0754         tower += nBinsX;
0755         hset.insert(TEveCaloData::CellId_t(tower, (*i).fSlice, (*i).fFraction));
0756       } else if (TMath::Abs(etaAxis->GetBinCenter(etaBin)) > 1.747650) {
0757         newPhiBin = ((phiBin + 1) / 2) * 2 - 1;
0758         tower = etaBin + newPhiBin * nBinsX;
0759         hset.insert(TEveCaloData::CellId_t(tower, (*i).fSlice, (*i).fFraction));
0760         tower += nBinsX;
0761         hset.insert(TEveCaloData::CellId_t(tower, (*i).fSlice, (*i).fFraction));
0762       } else {
0763         hset.insert(*i);
0764       }
0765     }
0766 
0767     // edit calo data list
0768     hlist.clear();
0769     for (std::set<TEveCaloData::CellId_t>::iterator it = hset.begin(); it != hset.end(); ++it) {
0770       hlist.push_back(*it);
0771     }
0772     context().getCaloData()->CellSelectionChanged();
0773   }
0774 
0775   gEve->GetHighlight()->BlockSignals(blocked);
0776 }