// @(#)root/eve:$Id: TEveUtil.cxx 21534 2007-12-20 12:17:22Z matevz $
// Authors: Matevz Tadel & Alja Mrak-Tadel: 2006, 2007

/*************************************************************************
 * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "TEveUtil.h"
#include "TEveElement.h"

#include "TError.h"
#include "TPad.h"
#include "TGeoManager.h"
#include "TClass.h"

#include "TStyle.h"
#include "TColor.h"

#include "TROOT.h"
#include "TInterpreter.h"
#include "TSystem.h"

#include "TGClient.h"
#include "TGMimeTypes.h"

#include <list>
#include <algorithm>
#include <iostream>

//______________________________________________________________________________
// TEveUtil
//
// Standard utility functions for Reve.

ClassImp(TEveUtil)

//______________________________________________________________________________
void TEveUtil::SetupEnvironment()
{
   // Setup Include and Macro paths.
   // Since inclusion into ROOT this does nothing but could
   // potentially be reactivated if some common macros are established
   // and shipped with binary ROOT (in macros/eve). For example, these
   // might be used to spawn specific GUI / GL configurations.

   static const TEveException eh("TEveUtil::SetupEnvironment");
   static Bool_t setupDone = kFALSE;

   if (setupDone) {
      Info(eh.Data(), "has already been run.");
      return;
   }

   // Old initialization for ALICE.
   // Left as an example.
   /*
   // Check if REVESYS exists, try fallback to $ALICE_ROOT/EVE.
   if(gSystem->Getenv("REVESYS") == 0) {
      if(gSystem->Getenv("ALICE_ROOT") != 0) {
         Info(eh.Data(), "setting REVESYS from ALICE_ROOT.");
         gSystem->Setenv("REVESYS", Form("%s/EVE", gSystem->Getenv("ALICE_ROOT")));
      } else {
         Error(eh.Data(), "REVESYS not defined, neither is ALICE_ROOT.");
         gSystem->Exit(1);
      }
   }
   if(gSystem->AccessPathName(gSystem->Getenv("REVESYS")) == kTRUE) {
      Error(eh.Data(), "REVESYS '%s' does not exist.", gSystem->Getenv("REVESYS"));
      gSystem->Exit(1);
   }

   TString macPath(gROOT->GetMacroPath());
   macPath += Form(":%s/macros", gSystem->Getenv("REVESYS"));
   gInterpreter->AddIncludePath(gSystem->Getenv("REVESYS"));
   if(gSystem->Getenv("ALICE_ROOT") != 0) {
      macPath += Form(":%s/alice-macros", gSystem->Getenv("REVESYS"));
      gInterpreter->AddIncludePath(Form("%s/include", gSystem->Getenv("ALICE_ROOT")));
      gInterpreter->AddIncludePath(gSystem->Getenv("ALICE_ROOT"));
   }
   gROOT->SetMacroPath(macPath);
   */
}

//______________________________________________________________________________
void TEveUtil::SetupGUI()
{
   // Setup icon pictures and mime-types.

   TString fld( Form("%s/icons/", gSystem->Getenv("ROOTSYS")) );

   TEveElement::fgRnrIcons[0] = gClient->GetPicture(fld + "eve_rnr00_t.xpm");
   TEveElement::fgRnrIcons[1] = gClient->GetPicture(fld + "eve_rnr01_t.xpm");
   TEveElement::fgRnrIcons[2] = gClient->GetPicture(fld + "eve_rnr10_t.xpm");
   TEveElement::fgRnrIcons[3] = gClient->GetPicture(fld + "eve_rnr11_t.xpm");

   TEveElement::fgListTreeIcons[0] = gClient->GetPicture("folder_t.xpm");
   TEveElement::fgListTreeIcons[1] = gClient->GetPicture(fld + "eve_viewer.xpm");
   TEveElement::fgListTreeIcons[2] = gClient->GetPicture(fld + "eve_scene.xpm");
   TEveElement::fgListTreeIcons[3] = gClient->GetPicture(fld + "eve_pointset.xpm");
   TEveElement::fgListTreeIcons[4] = gClient->GetPicture(fld + "eve_track.xpm");

   gClient->GetMimeTypeList()->AddType("root/tmacro", "TEveMacro",
                                       "tmacro_s.xpm", "tmacro_t.xpm", "");
}

/******************************************************************************/

namespace
{
//______________________________________________________________________________
void ChompTail(TString& s, char c='.')
{
   // Remove last part of string 's', starting from the last
   // occurrence of character 'c'.

   Ssiz_t p = s.Last(c);
   if(p != kNPOS)
      s.Remove(p);
}
}

//______________________________________________________________________________
Bool_t TEveUtil::CheckMacro(const Text_t* mac)
{
   // Checks if macro 'mac' is loaded.

   // Axel's advice; now sth seems slow, using old method below for test.
   // return gROOT->GetInterpreter()->IsLoaded(mac);

   // Previous version expected function with same name and used ROOT's
   // list of global functions.

   TString foo(mac); ChompTail(foo);
   /*
     if(recreate) {
     TCollection* logf = gROOT->GetListOfGlobalFunctions(kFALSE);
     logf->SetOwner();
     logf->Clear();
     }
   */
   if (gROOT->GetGlobalFunction(foo.Data(), 0, kFALSE) != 0)
      return kTRUE;
   else
      return (gROOT->GetGlobalFunction(foo.Data(), 0, kTRUE) != 0);
}

//______________________________________________________________________________
void TEveUtil::AssertMacro(const Text_t* mac)
{
   // Load and execute macro 'mac' if it has not been loaded yet.

   if(CheckMacro(mac) == kFALSE) {
      gROOT->Macro(mac);
   }
}

//______________________________________________________________________________
void TEveUtil::Macro(const Text_t* mac)
{
   // Execute macro 'mac'. Do not reload the macro.

   if(CheckMacro(mac) == kFALSE) {
      gROOT->LoadMacro(mac);
   }
   TString foo(mac); ChompTail(foo); foo += "()";
   gROOT->ProcessLine(foo.Data());
}

//______________________________________________________________________________
void TEveUtil::LoadMacro(const Text_t* mac)
{
   // Makes sure that macro 'mac' is loaded, but do not reload it.

   if(CheckMacro(mac) == kFALSE) {
      gROOT->LoadMacro(mac);
   }
}

/******************************************************************************/
// Color management
/******************************************************************************/

//______________________________________________________________________________
void TEveUtil::ColorFromIdx(Color_t ci, UChar_t col[4], Bool_t alpha)
{
   // Fill col with RGBA values corresponding to index ci. If alpha
   // is true, set alpha component of col to 255.
   // ROOT's indexed color palette does not support transparency.

   if (ci < 0) {
      col[0] = col[1] = col[2] = col[3] = 0;
      return;
   }
   TColor* c = gROOT->GetColor(ci);
   if (c) {
      col[0] = (UChar_t)(255*c->GetRed());
      col[1] = (UChar_t)(255*c->GetGreen());
      col[2] = (UChar_t)(255*c->GetBlue());
      if (alpha) col[3] = 255;
   }
}

//______________________________________________________________________________
void TEveUtil::ColorFromIdx(Float_t f1, Color_t c1, Float_t f2, Color_t c2,
			    UChar_t col[4], Bool_t alpha)
{
   // Fill col with weighted RGBA values corresponding to
   // color-indices c1 and c2. If alpha is true, set alpha component
   // of col to 255.

   TColor* t1 = gROOT->GetColor(c1);
   TColor* t2 = gROOT->GetColor(c2);
   if(t1 && t2) {
      col[0] = (UChar_t)(255*(f1*t1->GetRed()   + f2*t2->GetRed()));
      col[1] = (UChar_t)(255*(f1*t1->GetGreen() + f2*t2->GetGreen()));
      col[2] = (UChar_t)(255*(f1*t1->GetBlue()  + f2*t2->GetBlue()));
      if (alpha) col[3] = 255;
   }
}

//______________________________________________________________________________
Color_t* TEveUtil::FindColorVar(TObject* obj, const Text_t* varname)
{
   // Find address of Color_t data-member with name varname in object
   // obj.
   //
   // This is used to access color information for TGListTreeItem
   // coloration from visualization macros that wrap TObjects into
   // TEveElementObjectPtr instances.

   static const TEveException eh("TEveUtil::FindColorVar");

   Int_t off = obj->IsA()->GetDataMemberOffset(varname);
   if(off == 0)
      throw(eh + "could not find member '" + varname + "' in class " + obj->IsA()->GetName() + ".");
   return (Color_t*) (((char*)obj) + off);
}


/******************************************************************************/
// TEveException
/******************************************************************************/

//______________________________________________________________________________
// 
// Exception class thrown by TEve classes and macros.

ClassImp(TEveException)

//______________________________________________________________________________
bool operator==(const TString& t, const std::string& s)
{ return (s == t.Data()); }

bool operator==(const std::string&  s, const TString& t)
{ return (s == t.Data()); }

// Exc

TEveException::TEveException(const std::string& s) : TString(s.c_str())
{
   // Constructor.
}

// Exc + ops

TEveException operator+(const TEveException &s1, const std::string &s2)
{ TEveException r(s1); r += s2; return r; }

TEveException operator+(const TEveException &s1, const TString &s2)
{ TEveException r(s1); r += s2; return r; }

TEveException operator+(const TEveException &s1,  const char *s2)
{ TEveException r(s1); r += s2; return r; }


/******************************************************************************/
// TEvePadHolder
/******************************************************************************/

//______________________________________________________________________________
//
// Exception safe wrapper for setting gPad.
// Optionally calls gPad->Modified()/Update() in destructor.

ClassImp(TEvePadHolder)

//______________________________________________________________________________
TEvePadHolder::TEvePadHolder(Bool_t modify_update_p, TVirtualPad* new_pad, Int_t subpad) :
   fOldPad        (gPad),
   fModifyUpdateP (modify_update_p)
{
   // Constructor.

   if (new_pad != 0)
      new_pad->cd(subpad);
   else
      gPad = 0;
}

//______________________________________________________________________________
TEvePadHolder::~TEvePadHolder()
{
   // Destructor.

   if(fModifyUpdateP && gPad != 0) {
      gPad->Modified();
      gPad->Update();
   }
   gPad = fOldPad;
}


/******************************************************************************/
// TEveGeoManagerHolder
/******************************************************************************/

//______________________________________________________________________________
//
// Exception safe wrapper for setting gGeoManager.
// Functionality to lock-unlock via setting of a static lock in
// TGeoManager should be added (new feature of TGeoManager).

ClassImp(TEveGeoManagerHolder)

//______________________________________________________________________________
TEveGeoManagerHolder::TEveGeoManagerHolder(TGeoManager* new_gmgr) :
   fManager(gGeoManager)
{
   // Constructor.

   gGeoManager = new_gmgr;
}

//______________________________________________________________________________
TEveGeoManagerHolder::~TEveGeoManagerHolder()
{
   // Destructor.

   gGeoManager = fManager;
}


/******************************************************************************/
// TEveRefCnt
/******************************************************************************/

//______________________________________________________________________________
//
// Base-class for reference-counted objects.
// By default the object is destroyed when zero referece-count is reached.

ClassImp(TEveRefCnt)


/******************************************************************************/
// TEveRefBackPtr
/******************************************************************************/

//______________________________________________________________________________
//
// Base-class for reference-counted objects with reverse references to
// TEveElement objects.

ClassImp(TEveRefBackPtr)

//______________________________________________________________________________
TEveRefBackPtr::TEveRefBackPtr() :
   TEveRefCnt(),
   fBackRefs()
{
   // Default constructor.
}

//______________________________________________________________________________
TEveRefBackPtr::~TEveRefBackPtr()
{
   // Destructor. Noop, should complain if back-ref list is not empty.

   // !!! Complain if list not empty.
}

//______________________________________________________________________________
TEveRefBackPtr::TEveRefBackPtr(const TEveRefBackPtr&) :
   TEveRefCnt(),
   fBackRefs()
{
   // Copy constructor. New copy starts with zero reference count and
   // empty back-reference list.
}

//______________________________________________________________________________
TEveRefBackPtr& TEveRefBackPtr::operator=(const TEveRefBackPtr&)
{
   // Assignment operator. Reference count and back-reference
   // information is not assigned as these object hold pointers to a
   // specific object.

   return *this;
}

/******************************************************************************/

//______________________________________________________________________________
void TEveRefBackPtr::IncRefCount(TEveElement* re)
{
   // Increase reference cound and add re to the list of back-references.

   TEveRefCnt::IncRefCount();
   fBackRefs.push_back(re);
}

//______________________________________________________________________________
void TEveRefBackPtr::DecRefCount(TEveElement* re)
{
   // Decrease reference cound and remove re from the list of back-references.

   static const TEveException eh("TEveRefBackPtr::DecRefCount ");

   std::list<TEveElement*>::iterator i =
      std::find(fBackRefs.begin(), fBackRefs.end(), re);
   if (i != fBackRefs.end()) {
      fBackRefs.erase(i);
      TEveRefCnt::DecRefCount();
   } else {
      Warning(eh, Form("render element '%s' not found in back-refs.",
                       re->GetObject(eh)->GetName()));
   }
}

/******************************************************************************/

//______________________________________________________________________________
void TEveRefBackPtr::UpdateBackPtrItems()
{
   // Call UpdateItems() on list of reverse references.

   std::list<TEveElement*>::iterator i = fBackRefs.begin();
   while (i != fBackRefs.end())
   {
      (*i)->UpdateItems();
      ++i;
   }
}

Last update: Thu Jan 17 08:48:34 2008

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.