// -*- C++ -*-
//
// Package:     Core
// Class  :     FWGUIManager
//
// Implementation:
//     <Notes on implementation>
//
// Original Author:  Chris Jones
//         Created:  Mon Feb 11 11:06:40 EST 2008
// system include files
#include <functional>
#include <stdexcept>
#include <iostream>
#include <cstdio>
#include <sstream>
#include <thread>
#include <future>

#include "TGButton.h"
#include "TGLabel.h"
#include "TSystem.h"
#include "TGLIncludes.h"
#include "TGLViewer.h"
#include "TEveBrowser.h"
#include "TEveManager.h"
#include "TGPack.h"
#include "TEveWindow.h"
#include "TEveViewer.h"
#include "TEveWindowManager.h"
#include "TEveSelection.h"
#include "TVirtualX.h"
#include "TFile.h"

// user include files
#include "Fireworks/Core/interface/FWGUIManager.h"
#include "Fireworks/Core/interface/Context.h"
#include "Fireworks/Core/interface/FWGUISubviewArea.h"
#include "Fireworks/Core/interface/FWTEveViewer.h"

#include "Fireworks/Core/interface/FWSelectionManager.h"
#include "Fireworks/Core/interface/FWEventItemsManager.h"
#include "Fireworks/Core/interface/FWSummaryManager.h"
#include "Fireworks/Core/interface/FWColorManager.h"
#include "Fireworks/Core/interface/FWDetailViewManager.h"
#include "Fireworks/Core/interface/FWViewBase.h"
#include "Fireworks/Core/interface/FWViewType.h"
#include "Fireworks/Core/interface/FWGeometryTableViewBase.h"
#include "Fireworks/Core/interface/FWJobMetadataManager.h"
#include "Fireworks/Core/interface/FWInvMassDialog.h"

#include "Fireworks/Core/interface/FWConfiguration.h"

#include "Fireworks/Core/interface/CmsShowMainFrame.h"
#include "Fireworks/Core/interface/FWNavigatorBase.h"

#include "Fireworks/Core/src/FWGUIEventDataAdder.h"
#include "Fireworks/Core/src/FWNumberEntry.h"

#include "Fireworks/Core/interface/CSGAction.h"

#include "Fireworks/Core/interface/ActionsList.h"

#include "Fireworks/Core/interface/CmsShowEDI.h"
#include "Fireworks/Core/interface/CmsShowCommon.h"
#include "Fireworks/Core/interface/CmsShowCommonPopup.h"
#include "Fireworks/Core/interface/CmsShowModelPopup.h"
#include "Fireworks/Core/interface/CmsShowViewPopup.h"

#include "Fireworks/Core/interface/CmsShowHelpPopup.h"

#include "Fireworks/Core/interface/CmsShowTaskExecutor.h"

#include "Fireworks/Core/interface/FWTypeToRepresentations.h"
#include "Fireworks/Core/interface/FWIntValueListener.h"
#include "Fireworks/Core/interface/FWCustomIconsButton.h"

#include "Fireworks/Core/src/FWModelContextMenuHandler.h"

#include "Fireworks/Core/interface/fwLog.h"

#include "Fireworks/Core/interface/FWEventItem.h"
#include "Fireworks/Core/interface/FW3DViewBase.h"
#include "Fireworks/Core/interface/FWExpressionException.h"

#include "FWCore/Common/interface/EventBase.h"

#include "CommonTools/Utils/interface/Grammar.h"
#include "CommonTools/Utils/interface/Exception.h"

// constants, enums and typedefs
//
//
// static data member definitions
//
FWGUIManager* FWGUIManager::m_guiManager = nullptr;

//
// constructors and destructor
//

FWGUIManager::FWGUIManager(fireworks::Context* ctx, const FWViewManagerManager* iVMMgr, FWNavigatorBase* navigator)
    : m_context(ctx),
      m_summaryManager(nullptr),
      m_detailViewManager(nullptr),
      m_viewManagerManager(iVMMgr),
      m_contextMenuHandler(nullptr),
      m_navigator(navigator),
      m_dataAdder(nullptr),
      m_ediFrame(nullptr),
      m_modelPopup(nullptr),
      m_viewPopup(nullptr),
      m_commonPopup(nullptr),
      m_invMassDialog(nullptr),
      m_helpPopup(nullptr),
      m_shortcutPopup(nullptr),
      m_helpGLPopup(nullptr),
      m_tasks(new CmsShowTaskExecutor),
      m_WMOffsetX(0),
      m_WMOffsetY(0),
      m_WMDecorH(0) {
  m_guiManager = this;

  measureWMOffsets();

  FWEventItemsManager* im = (FWEventItemsManager*)m_context->eventItemsManager();
  im->newItem_.connect(std::bind(&FWGUIManager::newItem, this, std::placeholders::_1));

  m_context->colorManager()->colorsHaveChangedFinished_.connect(std::bind(&FWGUIManager::finishUpColorChange, this));

  TEveCompositeFrame::IconBarCreator_foo foo = &FWGUIManager::makeGUIsubview;
  TEveCompositeFrame::SetupFrameMarkup(foo, 20, 4, false);

  {
    m_cmsShowMainFrame = new CmsShowMainFrame(gClient->GetRoot(), 950, 750, this);

    m_cmsShowMainFrame->SetCleanup(kDeepCleanup);

    /*
        int mlist[FWViewType::kTypeSize] = {FWViewType::kRhoPhi, FWViewType::kRhoZ, FWViewType::k3D, FWViewType::kISpy, FWViewType::kLego, FWViewType::kLegoHF, FWViewType::kGlimpse, 
        FWViewType::kTable, FWViewType::kTableL1, FWViewType::kTableHLT,
        FWViewType::kGeometryTable,
        FWViewType::kRhoPhiPF, FWViewType::kLegoPFECAL}; */

    for (int i = 0; i < FWViewType::kTypeSize; ++i) {
      if (m_context->getHidePFBuilders() && (i == FWViewType::kLegoPFECAL || i == FWViewType::kRhoPhiPF))
        continue;

      bool separator = (i == FWViewType::kGlimpse || i == FWViewType::kTableHLT || i == FWViewType::kLegoPFECAL);
      CSGAction* action = m_cmsShowMainFrame->createNewViewerAction(FWViewType::idToName(i), separator);
      action->activated.connect(std::bind(&FWGUIManager::newViewSlot, this, FWViewType::idToName(i)));
    }

    m_detailViewManager = new FWDetailViewManager(m_context);
    m_contextMenuHandler = new FWModelContextMenuHandler(
        m_context->selectionManager(), m_detailViewManager, m_context->colorManager(), this);

    getAction(cmsshow::sExportImage)->activated.connect(sigc::mem_fun(*this, &FWGUIManager::exportImageOfMainView));
    getAction(cmsshow::sExportAllImages)->activated.connect(sigc::mem_fun(*this, &FWGUIManager::exportImagesOfAllViews));
    getAction(cmsshow::sLoadConfig)
        ->activated.connect(sigc::mem_fun(*this, &FWGUIManager::promptForLoadConfigurationFile));
    getAction(cmsshow::sLoadPartialConfig)
        ->activated.connect(sigc::mem_fun(*this, &FWGUIManager::promptForPartialLoadConfigurationFile));
    getAction(cmsshow::sSaveConfig)->activated.connect(writeToPresentConfigurationFile_);

    getAction(cmsshow::sSavePartialConfig)
        ->activated.connect(sigc::mem_fun(*this, &FWGUIManager::savePartialToConfigurationFile));
    getAction(cmsshow::sSaveConfigAs)
        ->activated.connect(sigc::mem_fun(*this, &FWGUIManager::promptForSaveConfigurationFile));
    getAction(cmsshow::sSavePartialConfigAs)
        ->activated.connect(sigc::mem_fun(*this, &FWGUIManager::promptForPartialSaveConfigurationFile));
    getAction(cmsshow::sShowEventDisplayInsp)->activated.connect(std::bind(&FWGUIManager::showEDIFrame, this, -1));
    getAction(cmsshow::sShowMainViewCtl)->activated.connect(sigc::mem_fun(*m_guiManager, &FWGUIManager::showViewPopup));
    getAction(cmsshow::sShowObjInsp)->activated.connect(sigc::mem_fun(*m_guiManager, &FWGUIManager::showModelPopup));

    getAction(cmsshow::sBackgroundColor)
        ->activated.connect(sigc::mem_fun(*m_context->colorManager(), &FWColorManager::switchBackground));
    getAction(cmsshow::sShowCommonInsp)->activated.connect(sigc::mem_fun(*m_guiManager, &FWGUIManager::showCommonPopup));

    getAction(cmsshow::sShowInvMassDialog)
        ->activated.connect(sigc::mem_fun(*m_guiManager, &FWGUIManager::showInvMassDialog));

    getAction(cmsshow::sShowAddCollection)->activated.connect(sigc::mem_fun(*m_guiManager, &FWGUIManager::addData));
    assert(getAction(cmsshow::sHelp) != nullptr);
    getAction(cmsshow::sHelp)->activated.connect(sigc::mem_fun(*m_guiManager, &FWGUIManager::createHelpPopup));
    assert(getAction(cmsshow::sKeyboardShort) != nullptr);
    getAction(cmsshow::sKeyboardShort)
        ->activated.connect(sigc::mem_fun(*m_guiManager, &FWGUIManager::createShortcutPopup));
    getAction(cmsshow::sHelpGL)->activated.connect(sigc::mem_fun(*m_guiManager, &FWGUIManager::createHelpGLPopup));

    // toolbar special widget with non-void actions
    m_cmsShowMainFrame->m_delaySliderListener->valueChanged_.connect(
        std::bind(&FWGUIManager::delaySliderChanged, this, std::placeholders::_1));

    TQObject::Connect(m_cmsShowMainFrame->m_runEntry, "ReturnPressed()", "FWGUIManager", this, "runIdChanged()");
    TQObject::Connect(m_cmsShowMainFrame->m_lumiEntry, "ReturnPressed()", "FWGUIManager", this, "lumiIdChanged()");
    TQObject::Connect(m_cmsShowMainFrame->m_eventEntry, "ReturnPressed()", "FWGUIManager", this, "eventIdChanged()");

    TQObject::Connect(
        m_cmsShowMainFrame->m_filterShowGUIBtn, "Clicked()", "FWGUIManager", this, "showEventFilterGUI()");
    TQObject::Connect(
        m_cmsShowMainFrame->m_filterEnableBtn, "Clicked()", "FWGUIManager", this, "filterButtonClicked()");

    TQObject::Connect(gEve->GetWindowManager(),
                      "WindowSelected(TEveWindow*)",
                      "FWGUIManager",
                      this,
                      "checkSubviewAreaIconState(TEveWindow*)");
    TQObject::Connect(gEve->GetWindowManager(),
                      "WindowDocked(TEveWindow*)",
                      "FWGUIManager",
                      this,
                      "checkSubviewAreaIconState(TEveWindow*)");
    TQObject::Connect(gEve->GetWindowManager(),
                      "WindowUndocked(TEveWindow*)",
                      "FWGUIManager",
                      this,
                      "checkSubviewAreaIconState(TEveWindow*)");
  }
}

void FWGUIManager::connectSubviewAreaSignals(FWGUISubviewArea* a) {
  a->goingToBeDestroyed_.connect(std::bind(&FWGUIManager::subviewIsBeingDestroyed, this, std::placeholders::_1));
  a->selected_.connect(std::bind(&FWGUIManager::subviewInfoSelected, this, std::placeholders::_1));
  a->unselected_.connect(std::bind(&FWGUIManager::subviewInfoUnselected, this, std::placeholders::_1));
  a->swap_.connect(std::bind(&FWGUIManager::subviewSwapped, this, std::placeholders::_1));
}

//
// Destructor
//
FWGUIManager::~FWGUIManager() {
  delete m_invMassDialog;
  delete m_summaryManager;
  delete m_detailViewManager;
  delete m_cmsShowMainFrame;
  delete m_viewPopup;
  delete m_ediFrame;
  delete m_contextMenuHandler;
}

void FWGUIManager::evePreTerminate() {
  gEve->GetWindowManager()->Disconnect("WindowSelected(TEveWindow*)", this, "checkSubviewAreaIconState(TEveWindow*)");
  gEve->GetWindowManager()->Disconnect("WindowDocked(TEveWindow*)", this, "checkSubviewAreaIconState(TEveWindow*)");
  gEve->GetWindowManager()->Disconnect("WindowUndocked(TEveWindow*)", this, "checkSubviewAreaIconState(TEveWindow*)");

  // avoid emit signals at end
  gEve->GetSelection()->Disconnect();
  gEve->GetHighlight()->Disconnect();
  gEve->GetSelection()->RemoveElements();
  gEve->GetHighlight()->RemoveElements();

  m_cmsShowMainFrame->UnmapWindow();
  for (ViewMap_i wIt = m_viewMap.begin(); wIt != m_viewMap.end(); ++wIt) {
    TEveCompositeFrameInMainFrame* mainFrame =
        dynamic_cast<TEveCompositeFrameInMainFrame*>((*wIt).first->GetEveFrame());
    //  main frames not to watch dying
    if (mainFrame)
      mainFrame->UnmapWindow();
    // destroy
    (*wIt).second->destroy();
  }
}

//______________________________________________________________________________
// subviews construction
//

TGFrame* FWGUIManager::makeGUIsubview(TEveCompositeFrame* cp, TGCompositeFrame* parent, Int_t height) {
  TGFrame* frame = new FWGUISubviewArea(cp, parent, height);
  return frame;
}

void FWGUIManager::registerViewBuilder(const std::string& iName, ViewBuildFunctor& iBuilder) {
  m_nameToViewBuilder[iName] = iBuilder;
}

void FWGUIManager::newViewSlot(const std::string& iName) {
  // this function have to exist, becuse CSGAction binds to void functions
  createView(iName);
}

FWGUIManager::ViewMap_i FWGUIManager::createView(const std::string& iName, TEveWindowSlot* slot) {
  NameToViewBuilder::iterator itFind = m_nameToViewBuilder.find(iName);
  assert(itFind != m_nameToViewBuilder.end());
  if (itFind == m_nameToViewBuilder.end()) {
    throw std::runtime_error(std::string("Unable to create view named ") + iName + " because it is unknown");
  }

  if (!slot) {
    if (m_viewSecPack) {
      slot = m_viewSecPack->NewSlot();
    } else {
      slot = m_viewPrimPack->NewSlot();
      m_viewSecPack = m_viewPrimPack->NewSlot()->MakePack();
      m_viewSecPack->SetShowTitleBar(kFALSE);
    }
  }
  TEveCompositeFrame* ef = slot->GetEveFrame();
  FWViewBase* viewBase = itFind->second(slot, iName);
  //in future, get context from 'view'
  FWViewContextMenuHandlerBase* base = viewBase->contextMenuHandler();
  viewBase->openSelectedModelContextMenu_.connect(std::bind(
      &FWGUIManager::showSelectedModelContextMenu, m_guiManager, std::placeholders::_1, std::placeholders::_2, base));

  TEveWindow* eveWindow = ef->GetEveWindow();
  eveWindow->SetElementName(iName.c_str());

  std::pair<ViewMap_i, bool> insertPair = m_viewMap.insert(std::make_pair(eveWindow, viewBase));
  return insertPair.first;
}

//
// actions
//

void FWGUIManager::enableActions(bool enable) { m_cmsShowMainFrame->enableActions(enable); }

void FWGUIManager::titleChanged(const char* subtitle) {
  char title[128];
  snprintf(title, 127, "cmsShow: %s", subtitle);
  m_cmsShowMainFrame->SetWindowName(title);
}

void FWGUIManager::eventChangedCallback() {
  // To be replaced when we can get index from fwlite::Event

  TEveViewerList* viewers = gEve->GetViewers();
  for (TEveElement::List_i i = viewers->BeginChildren(); i != viewers->EndChildren(); ++i) {
    TEveViewer* ev = dynamic_cast<TEveViewer*>(*i);
    if (ev)
      ev->GetGLViewer()->DeleteOverlayAnnotations();
  }

  for (auto reg : m_regionViews) {
    for (ViewMap_i it = m_viewMap.begin(); it != m_viewMap.end(); ++it) {
      if (it->second == reg) {
        m_viewMap.erase(it);
        reg->destroy();
        break;
      }
    }
  }

  m_cmsShowMainFrame->loadEvent(*getCurrentEvent());
  m_detailViewManager->newEventCallback();
}

CSGAction* FWGUIManager::getAction(const std::string name) { return m_cmsShowMainFrame->getAction(name); }

CSGContinuousAction* FWGUIManager::playEventsAction() { return m_cmsShowMainFrame->playEventsAction(); }

CSGContinuousAction* FWGUIManager::playEventsBackwardsAction() {
  return m_cmsShowMainFrame->playEventsBackwardsAction();
}

CSGContinuousAction* FWGUIManager::loopAction() { return m_cmsShowMainFrame->loopAction(); }

void FWGUIManager::disablePrevious() { m_cmsShowMainFrame->enablePrevious(false); }

void FWGUIManager::disableNext() { m_cmsShowMainFrame->enableNext(false); }

void FWGUIManager::setPlayMode(bool play) {
  m_cmsShowMainFrame->m_runEntry->SetEnabled(!play);
  m_cmsShowMainFrame->m_eventEntry->SetEnabled(!play);
}

void FWGUIManager::updateStatus(const char* status) { m_cmsShowMainFrame->updateStatusBar(status); }

void FWGUIManager::clearStatus() { m_cmsShowMainFrame->clearStatusBar(); }

void FWGUIManager::newItem(const FWEventItem* iItem) {
#if defined(THIS_WILL_NEVER_BE_DEFINED)
  m_selectionItemsComboBox->AddEntry(iItem->name().c_str(), iItem->id());
  if (iItem->id() == 0) {
    m_selectionItemsComboBox->Select(0);
  }
#endif
}

void FWGUIManager::addData() {
  if (nullptr == m_dataAdder) {
    m_dataAdder = new FWGUIEventDataAdder(100,
                                          100,
                                          (FWEventItemsManager*)m_context->eventItemsManager(),
                                          m_cmsShowMainFrame,
                                          m_context->metadataManager());
  }
  m_dataAdder->show();
}

//  subview actions
//

TEveWindow* FWGUIManager::getSwapCandidate() {
  TEveWindow* swapCandidate = nullptr;

  if (gEve->GetWindowManager()->GetCurrentWindow()) {
    swapCandidate = gEve->GetWindowManager()->GetCurrentWindow();
  } else {
    // swap with first docked view
    TEveCompositeFrame* pef;
    TGFrameElementPack* pel;

    // check if there is view in prim pack
    TGPack* pp = m_viewPrimPack->GetPack();
    if (pp->GetList()->GetSize() > 2) {
      pel = (TGFrameElementPack*)pp->GetList()->At(1);
      if (pel->fState)  // is first undocked
      {
        pef = dynamic_cast<TEveCompositeFrame*>(pel->fFrame);
        if (pef && pef->GetEveWindow())
          swapCandidate = pef->GetEveWindow();
      }
    }
    if (swapCandidate == nullptr) {
      // no eve window found in primary, check secondary
      TGPack* sp = m_viewSecPack->GetPack();
      TIter frame_iterator(sp->GetList());
      while ((pel = (TGFrameElementPack*)frame_iterator())) {
        pef = dynamic_cast<TEveCompositeFrame*>(pel->fFrame);
        if (pef && pef->GetEveWindow() && pel->fState) {
          swapCandidate = pef->GetEveWindow();
          break;
        }
      }
    }
  }
  return swapCandidate;
}

void FWGUIManager::checkSubviewAreaIconState(TEveWindow* /*ew*/) {
  // First argumet is needed for signals/slot symetry

  // disable swap on the first left TEveCompositeFrame
  // check info button
  TEveWindow* current = getSwapCandidate();
  bool checkInfoBtn = m_viewPopup ? m_viewPopup->mapped() : false;
  TEveWindow* selected = m_viewPopup ? m_viewPopup->getEveWindow() : nullptr;

  for (ViewMap_i it = m_viewMap.begin(); it != m_viewMap.end(); it++) {
    FWGUISubviewArea* ar = FWGUISubviewArea::getToolBarFromWindow(it->first);
    ar->setSwapIcon(current != it->first);
    if (checkInfoBtn && selected)
      ar->setInfoButton(selected == it->first);
  }
}

void FWGUIManager::subviewIsBeingDestroyed(FWGUISubviewArea* sva) {
  if (sva->isSelected())
    setViewPopup(nullptr);

  CmsShowTaskExecutor::TaskFunctor f;
  f = std::bind(&FWGUIManager::subviewDestroy, this, sva);
  m_tasks->addTask(f);
  m_tasks->startDoingTasks();
}

void FWGUIManager::subviewDestroy(FWGUISubviewArea* sva) {
  TEveWindow* ew = sva->getEveWindow();
  FWViewBase* viewBase = m_viewMap[ew];
  m_viewMap.erase(ew);
  viewBase->destroy();
}

void FWGUIManager::subviewDestroyAll() {
  std::vector<FWGUISubviewArea*> sd;
  for (ViewMap_i wIt = m_viewMap.begin(); wIt != m_viewMap.end(); ++wIt) {
    FWGUISubviewArea* ar = FWGUISubviewArea::getToolBarFromWindow(wIt->first);
    sd.push_back(ar);
  }

  for (std::vector<FWGUISubviewArea*>::iterator i = sd.begin(); i != sd.end(); ++i) {
    if ((*i)->isSelected())
      setViewPopup(nullptr);
    subviewDestroy(*i);
  }

  gSystem->ProcessEvents();
  gSystem->Sleep(200);

  while (m_viewPrimPack->HasChildren()) {
    TEveWindow* w = dynamic_cast<TEveWindow*>(m_viewPrimPack->FirstChild());
    if (w)
      w->DestroyWindowAndSlot();
  }

  gSystem->Sleep(200);
  m_viewSecPack = nullptr;
  gSystem->ProcessEvents();
}

void FWGUIManager::subviewInfoSelected(FWGUISubviewArea* sva) {
  // release button on previously selected
  TEveWindow* ew = sva->getEveWindow();
  for (ViewMap_i wIt = m_viewMap.begin(); wIt != m_viewMap.end(); ++wIt) {
    if (wIt->first != ew)
      FWGUISubviewArea::getToolBarFromWindow(wIt->first)->setInfoButton(kFALSE);
  }
  setViewPopup(sva->getEveWindow());
}

void FWGUIManager::subviewInfoUnselected(FWGUISubviewArea* sva) { m_viewPopup->UnmapWindow(); }

void FWGUIManager::subviewSwapped(FWGUISubviewArea* sva) {
  TEveWindow* curr = getSwapCandidate();
  TEveWindow* swap = sva->getEveWindow();
  if (curr)
    swap->SwapWindow(curr);

  checkSubviewAreaIconState(nullptr);
}

TGVerticalFrame* FWGUIManager::createList(TGCompositeFrame* p) {
  TGVerticalFrame* listFrame = new TGVerticalFrame(p, p->GetWidth(), p->GetHeight());

  TGHorizontalFrame* addFrame = new TGHorizontalFrame(listFrame, p->GetWidth(), 10, kRaisedFrame);
  TGLabel* addLabel = new TGLabel(addFrame, "Summary View");
  addFrame->AddFrame(addLabel, new TGLayoutHints(kLHintsCenterX, 0, 0, 2, 2));
  listFrame->AddFrame(addFrame, new TGLayoutHints(kLHintsExpandX | kLHintsTop));

  m_summaryManager = new FWSummaryManager(listFrame,
                                          m_context->selectionManager(),
                                          (FWEventItemsManager*)m_context->eventItemsManager(),
                                          this,
                                          m_context->modelChangeManager(),
                                          m_context->colorManager());

  const unsigned int backgroundColor = 0x2f2f2f;
  TGTextButton* addDataButton = new TGTextButton(m_summaryManager->widget(), "Add Collection");
  addDataButton->ChangeOptions(kRaisedFrame);
  addDataButton->SetBackgroundColor(backgroundColor);
  addDataButton->SetTextColor(0xFFFFFF);
  addDataButton->SetToolTipText("Show additional collections");
  addDataButton->Connect("Clicked()", "FWGUIManager", this, "addData()");
  m_summaryManager->widget()->AddFrame(addDataButton, new TGLayoutHints(kLHintsExpandX | kLHintsLeft | kLHintsTop));
  listFrame->AddFrame(m_summaryManager->widget(), new TGLayoutHints(kLHintsExpandX | kLHintsExpandY));

  return listFrame;
}

void FWGUIManager::createViews(TEveWindowSlot* slot) {
  m_viewPrimPack = slot->MakePack();
  m_viewPrimPack->SetHorizontal();
  m_viewPrimPack->SetElementName("Views");
  m_viewPrimPack->SetShowTitleBar(kFALSE);
  m_viewSecPack = nullptr;
}

void FWGUIManager::createEDIFrame() {
  if (m_ediFrame == nullptr) {
    m_ediFrame = new CmsShowEDI(m_cmsShowMainFrame, 200, 200, m_context->selectionManager(), m_context->colorManager());
    m_ediFrame->CenterOnParent(kTRUE, TGTransientFrame::kTopRight);
    m_cmsShowMainFrame->bindCSGActionKeys(m_ediFrame);
  }
}

void FWGUIManager::showEDIFrame(int iToShow) {
  createEDIFrame();
  if (-1 != iToShow) {
    m_ediFrame->show(static_cast<FWDataCategories>(iToShow));
  }
  m_ediFrame->MapRaised();
}

void FWGUIManager::open3DRegion() {
  try {
    FWModelId id = *(m_context->selectionManager()->selected().begin());
    float theta = 0, phi = 0;
    edm::TypeWithDict type = edm::TypeWithDict((TClass*)id.item()->modelType());
    using namespace boost::spirit::classic;
    reco::parser::ExpressionPtr tmpPtr;
    reco::parser::Grammar grammar(tmpPtr, type);
    edm::ObjectWithDict o(type, (void*)id.item()->modelData(id.index()));
    if (parse("theta()", grammar.use_parser<1>() >> end_p, space_p).full)
      theta = tmpPtr->value(o);
    else
      throw FWExpressionException("syntax error", -1);
    if (parse("phi()", grammar.use_parser<1>() >> end_p, space_p).full)
      phi = tmpPtr->value(o);
    else
      throw FWExpressionException("syntax error", -1);
    ViewMap_i it = createView("3D Tower", m_viewSecPack->NewSlot());
    FW3DViewBase* v = static_cast<FW3DViewBase*>(it->second);
    v->setClip(theta, phi);
    it->first->UndockWindow();
  } catch (const reco::parser::BaseException& e) {
    std::cout << " FWModelFilter failed to base " << e.what() << std::endl;
  }
}

void FWGUIManager::showCommonPopup() {
  if (!m_commonPopup) {
    m_commonPopup = new CmsShowCommonPopup(m_context->commonPrefs(), m_cmsShowMainFrame, 200, 200);
    m_context->commonPrefs()->setView(m_commonPopup);
    m_cmsShowMainFrame->bindCSGActionKeys(m_commonPopup);
  }
  m_commonPopup->MapRaised();
}

void FWGUIManager::createModelPopup() {
  m_modelPopup = new CmsShowModelPopup(
      m_detailViewManager, m_context->selectionManager(), m_context->colorManager(), m_cmsShowMainFrame, 200, 200);
  m_modelPopup->CenterOnParent(kTRUE, TGTransientFrame::kRight);
  m_cmsShowMainFrame->bindCSGActionKeys(m_modelPopup);
}

void FWGUIManager::showModelPopup() {
  if (!m_modelPopup)
    createModelPopup();
  m_modelPopup->MapRaised();
}

void FWGUIManager::popupViewClosed() {
  if (m_viewPopup->getEveWindow()) {
    FWGUISubviewArea* sa = FWGUISubviewArea::getToolBarFromWindow(m_viewPopup->getEveWindow());
    sa->setInfoButton(kFALSE);
  }
}

void FWGUIManager::showViewPopup() {
  // CSG action.
  setViewPopup(nullptr);
}

void FWGUIManager::setViewPopup(TEveWindow* ew) {
  FWViewBase* vb = ew ? m_viewMap[ew] : nullptr;
  if (m_viewPopup == nullptr) {
    m_viewPopup = new CmsShowViewPopup(nullptr, 200, 200, m_context->colorManager(), vb, ew);
    m_viewPopup->closed_.connect(sigc::mem_fun(*m_guiManager, &FWGUIManager::popupViewClosed));
  } else {
    m_viewPopup->UnmapWindow();
  }
  m_viewPopup->reset(vb, ew);
  m_viewPopup->MapRaised();
}

void FWGUIManager::showInvMassDialog() {
  if (!m_invMassDialog) {
    m_invMassDialog = new FWInvMassDialog(m_context->selectionManager());
    m_cmsShowMainFrame->bindCSGActionKeys(m_invMassDialog);
  }
  m_invMassDialog->MapRaised();
}

void FWGUIManager::createHelpPopup() {
  if (m_helpPopup == nullptr) {
    m_helpPopup = new CmsShowHelpPopup("help.html", "CmsShow Help", m_cmsShowMainFrame, 800, 600);
    m_helpPopup->CenterOnParent(kTRUE, TGTransientFrame::kBottomRight);
  }
  m_helpPopup->MapWindow();
}

void FWGUIManager::createShortcutPopup() {
  if (m_shortcutPopup == nullptr) {
    m_shortcutPopup = new CmsShowHelpPopup(
        "shortcuts.html", getAction(cmsshow::sKeyboardShort)->getName(), m_cmsShowMainFrame, 800, 600);

    m_shortcutPopup->CenterOnParent(kTRUE, TGTransientFrame::kBottomRight);
  }
  m_shortcutPopup->MapWindow();
}

void FWGUIManager::createHelpGLPopup() {
  if (m_helpGLPopup == nullptr) {
    m_helpGLPopup =
        new CmsShowHelpPopup("helpGL.html", getAction(cmsshow::sHelpGL)->getName(), m_cmsShowMainFrame, 800, 600);

    m_helpGLPopup->CenterOnParent(kTRUE, TGTransientFrame::kBottomRight);
  }
  m_helpGLPopup->MapWindow();
}

void FWGUIManager::showSelectedModelContextMenu(Int_t iGlobalX,
                                                Int_t iGlobalY,
                                                FWViewContextMenuHandlerBase* iHandler) {
  if (!m_context->selectionManager()->selected().empty()) {
    m_contextMenuHandler->showSelectedModelContext(iGlobalX, iGlobalY, iHandler);
  }
}

//
// const member functions
//

FWGUIManager* FWGUIManager::getGUIManager() { return m_guiManager; }

const edm::EventBase* FWGUIManager::getCurrentEvent() const { return m_navigator->getCurrentEvent(); }

/** Helper method for a load / save configuration dialog.

    @a result where the picked file is stored.
    
    @a mode the mode for the dialog (i.e. Load / Save).
    
    @return true if a file was successfully picked, false otherwise.
  */
bool FWGUIManager::promptForConfigurationFile(std::string& result, enum EFileDialogMode mode) {
  const static char* kFileTypes[] = {"Fireworks Configuration files", "*.fwc", "All Files", "*", nullptr, nullptr};

  static TString dir(".");

  TGFileInfo fi;
  fi.fFileTypes = kFileTypes;
  fi.fIniDir = StrDup(dir);
  new TGFileDialog(gClient->GetDefaultRoot(), m_cmsShowMainFrame, mode, &fi);
  dir = fi.fIniDir;
  if (fi.fFilename == nullptr)  // to handle "cancel" button properly
    return false;
  std::string name = fi.fFilename;
  // if the extension isn't already specified by hand, specify it now
  std::string ext = kFileTypes[fi.fFileTypeIdx + 1] + 1;
  if (!ext.empty() && name.find(ext) == name.npos)
    name += ext;
  result = name;
  return true;
}

/** Emits the signal which request to load the configuration file picked up 
    in a dialog.
  */
void FWGUIManager::promptForLoadConfigurationFile() {
  std::string name;
  if (!promptForConfigurationFile(name, kFDOpen))
    return;

  loadFromConfigurationFile_(name);
}

void FWGUIManager::promptForPartialLoadConfigurationFile() {
  std::string name;
  if (!promptForConfigurationFile(name, kFDOpen))
    return;

  loadPartialFromConfigurationFile_(name);
  //
}

/** Emits the signal which requests to save the current configuration in the 
    file picked up in the dialog.
  */
void FWGUIManager::promptForSaveConfigurationFile() {
  std::string name;
  if (!promptForConfigurationFile(name, kFDSave))
    return;

  writeToConfigurationFile_(name);
}

void FWGUIManager::promptForPartialSaveConfigurationFile() {
  std::string name;
  if (!promptForConfigurationFile(name, kFDSave))
    return;

  writePartialToConfigurationFile_(name);
}

void FWGUIManager::savePartialToConfigurationFile() { writePartialToConfigurationFile_("current"); }

void FWGUIManager::exportImageOfMainView() {
  if (m_viewPrimPack->GetPack()->GetList()->GetSize() > 2) {
    TGFrameElementPack* frameEL = (TGFrameElementPack*)m_viewPrimPack->GetPack()->GetList()->At(1);
    TEveCompositeFrame* ef = dynamic_cast<TEveCompositeFrame*>(frameEL->fFrame);
    m_viewMap[ef->GetEveWindow()]->promptForSaveImageTo(m_cmsShowMainFrame);
  } else {
    fwLog(fwlog::kError) << "Main view has been destroyed." << std::endl;
  }
}

void FWGUIManager::exportImagesOfAllViews() {
  try {
    static TString dir(".");
    const char* kImageExportTypes[] = {"PNG",
                                       "*.png",
                                       "GIF",
                                       "*.gif",
                                       "JPEG",
                                       "*.jpg",
                                       "PDF",
                                       "*.pdf",
                                       "Encapsulated PostScript",
                                       "*.eps",
                                       nullptr,
                                       nullptr};

    TGFileInfo fi;
    fi.fFileTypes = kImageExportTypes;
    fi.fIniDir = StrDup(dir);
    new TGFileDialog(gClient->GetDefaultRoot(), m_cmsShowMainFrame, kFDSave, &fi);
    dir = fi.fIniDir;
    if (fi.fFilename != nullptr) {
      std::string name = fi.fFilename;
      // fi.fFileTypeIdx points to the name of the file type
      // selected in the drop-down menu, so fi.fFileTypeIdx gives us
      // the extension
      std::string ext = kImageExportTypes[fi.fFileTypeIdx + 1] + 1;
      if (name.find(ext) == name.npos)
        name += ext;
      // now add format trailing before the extension
      name.insert(name.rfind('.'), "-%u_%u_%u_%s");
      exportAllViews(name, -1);
    }
  } catch (std::runtime_error& e) {
    std::cout << e.what() << std::endl;
  }
}

void FWGUIManager::exportAllViews(const std::string& format, int height) {
  // Save all GL views.
  // Expects format to have "%u %u %llu %s" which are replaced with
  //   run-number, event number, lumi block and view-name.
  // Blanks in view-name are removed.
  // If several views shave the same name, they are post-fixed
  // with "_%d". They are sorted by view diagonal.

  typedef std::list<FWTEveViewer*> viewer_list_t;
  typedef viewer_list_t::iterator viewer_list_i;

  typedef std::map<TString, viewer_list_t> name_map_t;
  typedef name_map_t::iterator name_map_i;

  name_map_t vls;

  for (ViewMap_i i = m_viewMap.begin(); i != m_viewMap.end(); ++i) {
    FWTEveViewer* ev = dynamic_cast<FWTEveViewer*>(i->first);
    if (ev) {
      TString name(ev->GetElementName());
      name.ReplaceAll(" ", "");
      viewer_list_t& l = vls[name];
      viewer_list_i li = l.begin();
      while (li != l.end() && (*li)->GetGLViewer()->ViewportDiagonal() < ev->GetGLViewer()->ViewportDiagonal())
        ++li;
      l.insert(li, ev);
    }
  }

  std::vector<std::future<int>> futures;

  const edm::EventBase* event = getCurrentEvent();
  for (name_map_i i = vls.begin(); i != vls.end(); ++i) {
    bool multi_p = (i->second.size() > 1);
    int view_count = 1;
    for (viewer_list_i j = i->second.begin(); j != i->second.end(); ++j, ++view_count) {
      TString view_name(i->first);
      if (multi_p) {
        view_name += "_";
        view_name += view_count;
      }
      TString file;
      file.Form(format.c_str(), event->id().run(), event->id().event(), event->luminosityBlock(), view_name.Data());

      if (GLEW_EXT_framebuffer_object) {
        // Multi-threaded save
        futures.push_back((*j)->CaptureAndSaveImage(file, height));
      } else {
        // Single-threaded save
        if (height == -1)
          (*j)->GetGLViewer()->SavePicture(file);
        else
          (*j)->GetGLViewer()->SavePictureHeight(file, height);
      }
    }
  }

  for (auto& f : futures) {
    f.get();
  }
}

static const std::string kMainWindow("main window");
static const std::string kViews("views");
static const std::string kViewArea("view area");
static const std::string kUndocked("undocked views");
static const std::string kControllers("controllers");
static const std::string kCollectionController("collection");
static const std::string kViewController("view");
static const std::string kObjectController("object");
static const std::string kCommonController("common");

static void addWindowInfoTo(const TGFrame* iMain, FWConfiguration& oTo) {
  Window_t wdummy;
  Int_t ax, ay;
  gVirtualX->TranslateCoordinates(iMain->GetId(),
                                  gClient->GetDefaultRoot()->GetId(),
                                  0,
                                  0,  //0,0 in local coordinates
                                  ax,
                                  ay,  //coordinates of screen
                                  wdummy);
  {
    std::stringstream s;
    s << ax;
    oTo.addKeyValue("x", FWConfiguration(s.str()));
  }
  {
    std::stringstream s;
    s << ay;
    oTo.addKeyValue("y", FWConfiguration(s.str()));
  }
  {
    std::stringstream s;
    s << iMain->GetWidth();
    oTo.addKeyValue("width", FWConfiguration(s.str()));
  }
  {
    std::stringstream s;
    s << iMain->GetHeight();
    oTo.addKeyValue("height", FWConfiguration(s.str()));
  }
}

class areaInfo {
  // helper class to save and restore view area
public:
  areaInfo(TGFrameElementPack* frameElement) {
    eveWindow = nullptr;
    originalSlot = nullptr;
    undockedMainFrame = nullptr;
    weight = frameElement->fWeight;
    undocked = !frameElement->fState;

    TEveCompositeFrame* eveFrame = dynamic_cast<TEveCompositeFrame*>(frameElement->fFrame);
    assert(eveFrame);

    if (frameElement->fState)
      eveWindow = eveFrame->GetEveWindow();
    else
      originalSlot = eveFrame->GetEveWindow();
  }

  areaInfo() : weight(0), undocked(false) {}

  Float_t weight;
  Bool_t undocked;
  TEveWindow* eveWindow;
  TGMainFrame* undockedMainFrame;  // cached to help find original slot for undocked windows
  TEveWindow* originalSlot;
};

static void addAreaInfoTo(areaInfo& pInfo, FWConfiguration& oTo) {
  {
    std::stringstream s;
    s << pInfo.weight;
    oTo.addKeyValue("weight", FWConfiguration(s.str()));
  }
  {
    std::stringstream s;
    s << pInfo.undocked;
    oTo.addKeyValue("undocked", FWConfiguration(s.str()));
  }

  if (pInfo.undockedMainFrame) {
    FWConfiguration temp(oTo);
    addWindowInfoTo(pInfo.undockedMainFrame, temp);
    oTo.addKeyValue("UndockedWindowPos", temp);
  }
}

//______________________________________________________________________________
void FWGUIManager::addTo(FWConfiguration& oTo) const {
  Int_t cfgVersion = 3;

  FWConfiguration mainWindow(cfgVersion);
  float leftWeight, rightWeight;
  addWindowInfoTo(m_cmsShowMainFrame, mainWindow);
  {
    // write summary view weight
    {
      std::stringstream ss;
      ss << m_cmsShowMainFrame->getSummaryViewWeight();
      mainWindow.addKeyValue("summaryWeight", FWConfiguration(ss.str()));
    }

    // write proportions of horizontal pack (can be standalone item outside main frame)
    if (m_viewPrimPack->GetPack()->GetList()->GetSize() > 2) {
      TGFrameElementPack* frameEL;
      frameEL = (TGFrameElementPack*)m_viewPrimPack->GetPack()->GetList()->At(
          1);  // read every second  element, first on is splitter
      leftWeight = frameEL->fWeight;
      frameEL = (TGFrameElementPack*)m_viewPrimPack->GetPack()->GetList()->At(3);
      rightWeight = frameEL->fWeight;
    } else {
      leftWeight = 0;
      rightWeight = 1;
    }
    std::stringstream sL;
    sL << leftWeight;
    mainWindow.addKeyValue("leftWeight", FWConfiguration(sL.str()));
    std::stringstream sR;
    sR << rightWeight;
    mainWindow.addKeyValue("rightWeight", FWConfiguration(sR.str()));
  }
  oTo.addKeyValue(kMainWindow, mainWindow, true);

  //------------------------------------------------------------
  // organize info about all docked frames includding hidden, which point to undocked
  std::vector<areaInfo> wpacked;
  if (leftWeight > 0) {
    TGPack* pp = m_viewPrimPack->GetPack();
    TGFrameElementPack* frameEL = (TGFrameElementPack*)pp->GetList()->At(1);
    if (frameEL->fWeight > 0)
      wpacked.push_back(areaInfo(frameEL));
  }
  TGPack* sp = m_viewSecPack->GetPack();
  TGFrameElementPack* seFE;
  TIter frame_iterator(sp->GetList());
  while ((seFE = (TGFrameElementPack*)frame_iterator())) {
    if (seFE->fWeight)
      wpacked.push_back(areaInfo(seFE));
  }

  //  undocked info

  for (ViewMap_i wIt = m_viewMap.begin(); wIt != m_viewMap.end(); ++wIt) {
    TEveWindow* ew = wIt->first;
    TEveCompositeFrameInMainFrame* mainFrame = dynamic_cast<TEveCompositeFrameInMainFrame*>(ew->GetEveFrame());
    if (mainFrame) {
      for (std::vector<areaInfo>::iterator pIt = wpacked.begin(); pIt != wpacked.end(); ++pIt) {
        if ((*pIt).originalSlot && mainFrame->GetOriginalSlot() == (*pIt).originalSlot) {
          (*pIt).eveWindow = wIt->first;
          (*pIt).undockedMainFrame = (TGMainFrame*)mainFrame;
          // printf("found original slot for docked view %s\n", pInfo->viewBase->typeName().c_str());
          break;
        }  // found match
      }
    }  // end main frames
  }

  //------------------------------------------------------------
  // add sorted list in view area and FW-views configuration
  FWConfiguration views(1);
  FWConfiguration viewArea(cfgVersion);
  for (std::vector<areaInfo>::iterator it = wpacked.begin(); it != wpacked.end(); ++it) {
    TEveWindow* ew = (*it).eveWindow;
    if (ew) {
      FWViewBase* wb = m_viewMap[ew];
      FWConfiguration tempWiew(wb->version());
      wb->addTo(tempWiew);
      views.addKeyValue(wb->typeName(), tempWiew, true);
      FWConfiguration tempArea(cfgVersion);
      addAreaInfoTo((*it), tempArea);
      viewArea.addKeyValue(wb->typeName(), tempArea, true);
    }
  }
  oTo.addKeyValue(kViews, views, true);
  oTo.addKeyValue(kViewArea, viewArea, true);

  //------------------------------------------------------------
  //Remember where controllers were placed if they are open
  FWConfiguration controllers(1);
  {
    if (nullptr != m_ediFrame && m_ediFrame->IsMapped()) {
      FWConfiguration temp(1);
      addWindowInfoTo(m_ediFrame, temp);
      controllers.addKeyValue(kCollectionController, temp, true);
    }
    if (nullptr != m_viewPopup && m_viewPopup->IsMapped()) {
      FWConfiguration temp(1);
      addWindowInfoTo(m_viewPopup, temp);
      controllers.addKeyValue(kViewController, temp, true);
    }
    if (nullptr != m_modelPopup && m_modelPopup->IsMapped()) {
      FWConfiguration temp(1);
      addWindowInfoTo(m_modelPopup, temp);
      controllers.addKeyValue(kObjectController, temp, true);
    }
    if (nullptr != m_commonPopup && m_commonPopup->IsMapped()) {
      FWConfiguration temp(1);
      addWindowInfoTo(m_commonPopup, temp);
      controllers.addKeyValue(kCommonController, temp, true);
    }
  }
  oTo.addKeyValue(kControllers, controllers, true);
}

//----------------------------------------------------------------
void FWGUIManager::setWindowInfoFrom(const FWConfiguration& iFrom, TGMainFrame* iFrame) {
  int x = atoi(iFrom.valueForKey("x")->value().c_str()) + m_WMOffsetX;
  int y = atoi(iFrom.valueForKey("y")->value().c_str()) + m_WMOffsetY;
  if (y < m_WMDecorH)
    y = m_WMDecorH;
  int width = atoi(iFrom.valueForKey("width")->value().c_str());
  int height = atoi(iFrom.valueForKey("height")->value().c_str());
  iFrame->MoveResize(x, y, width, height);
  iFrame->SetWMPosition(x, y);
}

void FWGUIManager::setFrom(const FWConfiguration& iFrom) {
  gEve->DisableRedraw();
  // main window
  if (m_viewSecPack)
    subviewDestroyAll();

  const FWConfiguration* mw = iFrom.valueForKey(kMainWindow);
  assert(mw != nullptr);
  // Window needs to mapped before moving, otherwise move can lead
  // to wrong results on some window managers.

  // set from view reading area info nd view info
  float_t leftWeight = 1;
  float_t rightWeight = 1;
  if (mw->version() >= 2) {
    leftWeight = atof(mw->valueForKey("leftWeight")->value().c_str());
    rightWeight = atof(mw->valueForKey("rightWeight")->value().c_str());
  }

  if (mw->version() >= 3) {
    float summaryWeight = atof(mw->valueForKey("summaryWeight")->value().c_str());
    m_cmsShowMainFrame->setSummaryViewWeight(summaryWeight);
  }

  TEveWindowSlot* primSlot = (leftWeight > 0) ? m_viewPrimPack->NewSlotWithWeight(leftWeight) : nullptr;
  m_viewSecPack = m_viewPrimPack->NewSlotWithWeight(rightWeight)->MakePack();
  m_viewSecPack->SetVertical();
  m_viewSecPack->SetShowTitleBar(kFALSE);

  // views list
  const FWConfiguration* views = iFrom.valueForKey(kViews);
  assert(nullptr != views);
  const FWConfiguration::KeyValues* keyVals = views->keyValues();
  const FWConfiguration* viewArea = iFrom.valueForKey(kViewArea);

  // area list (ignored in older version)
  if (viewArea->version() > 1) {
    const FWConfiguration::KeyValues* akv = viewArea->keyValues();
    FWConfiguration::KeyValuesIt areaIt = akv->begin();

    for (FWConfiguration::KeyValuesIt it = keyVals->begin(); it != keyVals->end(); ++it) {
      float weight = atof((areaIt->second).valueForKey("weight")->value().c_str());
      TEveWindowSlot* slot =
          (!m_viewMap.empty() || (primSlot == nullptr)) ? m_viewSecPack->NewSlotWithWeight(weight) : primSlot;
      std::string name = FWViewType::checkNameWithViewVersion(it->first, it->second.version());
      ViewMap_i lastViewIt = createView(name, slot);
      lastViewIt->second->setFrom(it->second);

      bool undocked = atof((areaIt->second).valueForKey("undocked")->value().c_str());
      if (undocked) {
        TEveWindow* lastWindow = lastViewIt->first;
        lastWindow->UndockWindow();
        TEveCompositeFrameInMainFrame* emf = dynamic_cast<TEveCompositeFrameInMainFrame*>(lastWindow->GetEveFrame());
        if (emf) {
          const TGMainFrame* mf = dynamic_cast<const TGMainFrame*>(emf->GetParent());
          if (mf) {
            m_cmsShowMainFrame->bindCSGActionKeys(mf);
            TGMainFrame* mfp = (TGMainFrame*)mf;  // have to cast in non-const
            const FWConfiguration* mwc = (areaIt->second).valueForKey("UndockedWindowPos");
            setWindowInfoFrom(*mwc, mfp);
          }
        }
      }
      areaIt++;
    }
  } else {  // create views with same weight in old version
    for (FWConfiguration::KeyValuesIt it = keyVals->begin(); it != keyVals->end(); ++it) {
      std::string name = FWViewType::checkNameWithViewVersion(it->first, it->second.version());
      createView(name, !m_viewMap.empty() ? m_viewSecPack->NewSlot() : primSlot);

      ViewMap_i lastViewIt = m_viewMap.end();
      lastViewIt--;
      lastViewIt->second->setFrom(it->second);
    }
    // handle undocked windows in old version
    const FWConfiguration* undocked = iFrom.valueForKey(kUndocked);
    if (nullptr != undocked) {
      fwLog(fwlog::kWarning) << "Restrore of undocked windows with old window management not supported." << std::endl;
    }
  }

  //handle controllers
  const FWConfiguration* controllers = iFrom.valueForKey(kControllers);
  if (nullptr != controllers) {
    const FWConfiguration::KeyValues* keyVals = controllers->keyValues();
    if (nullptr != keyVals) {
      //we have open controllers
      for (FWConfiguration::KeyValuesIt it = keyVals->begin(); it != keyVals->end(); ++it) {
        const std::string& controllerName = it->first;
        // std::cout <<"found controller "<<controllerName<<std::endl;
        if (controllerName == kCollectionController) {
          showEDIFrame();
          setWindowInfoFrom(it->second, m_ediFrame);
        } else if (controllerName == kViewController) {
          setViewPopup(nullptr);
          setWindowInfoFrom(it->second, m_viewPopup);
        } else if (controllerName == kObjectController) {
          showModelPopup();
          setWindowInfoFrom(it->second, m_modelPopup);
        } else if (controllerName == kCommonController) {
          showCommonPopup();
          setWindowInfoFrom(it->second, m_commonPopup);
        }
      }
    }
  }

  for (ViewMap_i it = m_viewMap.begin(); it != m_viewMap.end(); ++it) {
    if (it->second->typeId() >= FWViewType::kGeometryTable) {
      FWGeometryTableViewBase* gv = (FWGeometryTableViewBase*)it->second;
      gv->populate3DViewsFromConfig();
    }
  }

  gEve->EnableRedraw();
  // disable first docked view
  checkSubviewAreaIconState(nullptr);

  m_cmsShowMainFrame->MapWindow();
  setWindowInfoFrom(*mw, m_cmsShowMainFrame);
  m_cmsShowMainFrame->MapSubwindows();
  m_cmsShowMainFrame->Layout();
  m_cmsShowMainFrame->MapRaised();
}

void FWGUIManager::openEveBrowserForDebugging() const { gEve->GetBrowser()->MapWindow(); }

//
// toolbar widgets callbacks
//
void FWGUIManager::delaySliderChanged(Int_t val) {
  Float_t sec = val * 0.001;
  m_cmsShowMainFrame->setPlayDelayGUI(sec, kFALSE);
  changedDelayBetweenEvents_.emit(sec);
}

void FWGUIManager::setDelayBetweenEvents(Float_t val) { m_cmsShowMainFrame->setPlayDelayGUI(val, kTRUE); }

void FWGUIManager::runIdChanged() {
  if (m_cmsShowMainFrame->m_runEntry->GetUIntNumber() == edm::invalidRunNumber) {
    m_cmsShowMainFrame->m_runEntry->SetUIntNumber(1);
  }

  m_cmsShowMainFrame->m_lumiEntry->SetText("", kFALSE);
  m_cmsShowMainFrame->m_lumiEntry->SetFocus();
}

void FWGUIManager::lumiIdChanged() {
  if (m_cmsShowMainFrame->m_lumiEntry->GetUIntNumber() == edm::invalidLuminosityBlockNumber) {
    m_cmsShowMainFrame->m_lumiEntry->SetUIntNumber(1);
  }

  m_cmsShowMainFrame->m_eventEntry->SetText("", kFALSE);
  m_cmsShowMainFrame->m_eventEntry->SetFocus();
}

void FWGUIManager::eventIdChanged() {
  if (m_cmsShowMainFrame->m_eventEntry->GetUIntNumber() == edm::invalidEventNumber) {
    m_cmsShowMainFrame->m_eventEntry->SetULong64Number(1);
  }

  changedEventId_.emit(m_cmsShowMainFrame->m_runEntry->GetUIntNumber(),
                       m_cmsShowMainFrame->m_lumiEntry->GetUIntNumber(),
                       m_cmsShowMainFrame->m_eventEntry->GetULong64Number());
}

void FWGUIManager::finishUpColorChange() {
  if (m_commonPopup)
    m_commonPopup->colorSetChanged();
  if (m_modelPopup)
    m_modelPopup->colorSetChanged();
  if (m_ediFrame)
    m_ediFrame->colorSetChanged();

  gEve->FullRedraw3D();
}
//______________________________________________________________________________

void FWGUIManager::showEventFilterGUI() { showEventFilterGUI_.emit(m_cmsShowMainFrame); }

void FWGUIManager::filterButtonClicked() { filterButtonClicked_.emit(); }

void FWGUIManager::setFilterButtonText(const char* txt) { m_cmsShowMainFrame->m_filterShowGUIBtn->SetText(txt); }

void FWGUIManager::setFilterButtonIcon(int state) {
  int i = state * 3;
  m_cmsShowMainFrame->m_filterEnableBtn->setIcons(m_cmsShowMainFrame->m_filterIcons[i],
                                                  m_cmsShowMainFrame->m_filterIcons[i + 1],
                                                  m_cmsShowMainFrame->m_filterIcons[i + 2]);
}

void FWGUIManager::updateEventFilterEnable(bool btnEnabled) {
  m_cmsShowMainFrame->m_filterEnableBtn->SetEnabled(btnEnabled);
}

void FWGUIManager::measureWMOffsets() {
  const Int_t x = 100, y = 100;

  TGMainFrame* mf1 = new TGMainFrame(nullptr, 0, 0);
  mf1->MapWindow();
  mf1->Move(x, y);

  // This seems to be the only reliable way to make sure Move() has been processed.
  {
    TGMainFrame* mf2 = new TGMainFrame(nullptr, 0, 0);
    mf2->MapWindow();
    while (!mf2->IsMapped())
      gClient->HandleInput();
    delete mf2;
  }
  {
    Int_t xm, ym;
    Window_t childdum;
    WindowAttributes_t attr;
    gVirtualX->TranslateCoordinates(mf1->GetId(), gClient->GetDefaultRoot()->GetId(), 0, 0, xm, ym, childdum);
    gVirtualX->GetWindowAttributes(mf1->GetId(), attr);
    m_WMOffsetX = x - xm;
    m_WMOffsetY = y - ym;
    m_WMDecorH = attr.fY;
    fwLog(fwlog::kDebug) << Form(
        "FWGUIManager::measureWMOffsets: required (%d,%d), measured(%d, %d) => dx=%d, dy=%d; decor_h=%d.\n",
        x,
        y,
        xm,
        ym,
        m_WMOffsetX,
        m_WMOffsetY,
        m_WMDecorH);
  }
  delete mf1;
}

void FWGUIManager::resetWMOffsets() { m_WMOffsetX = m_WMOffsetY = m_WMDecorH = 0; }

void FWGUIManager::initEmpty() {
  int x = 150 + m_WMOffsetX;
  int y = 50 + m_WMOffsetY;
  m_cmsShowMainFrame->Move(x, y);
  m_cmsShowMainFrame->SetWMPosition(x, y < m_WMDecorH ? m_WMDecorH : y);

  createView("Rho Phi");
  createView("Rho Z");

  m_cmsShowMainFrame->MapSubwindows();
  m_cmsShowMainFrame->Layout();
  m_cmsShowMainFrame->MapRaised();
}
