Roody.cxx

Go to the documentation of this file.
00001 //
00002 // Roody.cxx
00003 //
00004 // $Id$
00005 //
00006 
00007 #include <stdio.h>
00008 #include <math.h>
00009 
00010 #include "RoodyXML.h"
00011 #include "Roody.h"
00012 
00013 #include "TAxisLimitsDialog.h"
00014 
00015 #include "TROOT.h"
00016 #include "TCutG.h"
00017 #include "TNtuple.h"
00018 #include "TGraph.h"
00019 #include "TVirtualX.h"
00020 #include "TGListTree.h"
00021 #include "TGClient.h"
00022 #include "TGLabel.h"
00023 #include "TGButton.h"
00024 #include "TGMsgBox.h"
00025 #include "TGMenu.h"
00026 #include "TGCanvas.h"
00027 #include "TGTextDialog.h"
00028 #include "TCanvas.h"
00029 #include "TFrame.h"
00030 #include "TH1.h"
00031 #include "TSystem.h"
00032 #include "TFile.h"
00033 #include "TKey.h"
00034 #include "TGStatusBar.h"
00035 #include "TExec.h"
00036 #include "TStyle.h"
00037 #include "TTimer.h"
00038 #include "TContextMenu.h"
00039 #include "TClassMenuItem.h"
00040 #include "TSocket.h"
00041 #include "MTGListTree.h"
00042 #include "TPeakFindPanel.h"
00043 #include "TGFileDialog.h"
00044 #include "TPaveLabel.h"
00045 
00046 #ifdef HAVE_HBOOK
00047 #include "THbookKey.h"
00048 #include "THbookFile.h"
00049 #include "THbookTree.h"
00050 #include "THbookBranch.h"
00051 #endif
00052 
00053 void breakhere(void)
00054 {
00055   // nothing
00056 }
00057 
00058 class MemDebug : public TObject
00059 {
00060 public:
00061 
00062   MemDebug() // ctor
00063   {
00064     printf("MemDebug %p created!\n", this);
00065   }
00066 
00067   ~MemDebug() // dtor
00068   {
00069     printf("MemDebug %p destroyed!\n", this);
00070     breakhere();
00071   }
00072 
00073   TObject* Clone()
00074   {
00075     TObject* obj = new MemDebug();
00076     printf("MemDebug %p cloned into %p!\n", this, obj);
00077     return obj;
00078   }
00079 };
00080 
00081 #include "DataSourceBase.h"
00082 #include "DataSourceTDirectory.h"
00083 #include "DataSourceTNetFolder.h"
00084 #include "DataSourceTFile.h"
00085 #include "DataSourceXmlServer.h"
00086 #ifdef HAVE_NETDIRECTORY
00087 #include "DataSourceNetDirectory.h"
00088 #endif
00089 
00090 enum Action
00091   {
00092     A_ITEM   = 1,
00093     A_FOLDER = 2,
00094     A_SOURCE = 3,
00095     A_GROUP  = 4,
00096   };
00097 
00098 TList* gAllObjects = NULL;
00099 
00100 std::map<TGListTreeItem*, Action> gItemActions;
00101 
00102 std::map<ObjectPath,TObject*> gObjectCache;
00103 
00104 typedef std::map<std::string,DataSourceBase*> DataSourcesMap;
00105 DataSourcesMap gDataSources;
00106 
00107 std::map<TGListTreeItem*,ObjectPath>   gItemSources;
00108 std::map<ObjectPath,std::string>       gObjectClasses;
00109 
00110 std::map<std::string,std::vector<TGListTreeItem*> > gGroupContents;
00111 
00112 static TGListTreeItem* FindItem(ObjectPath src)
00113 {
00114   std::map<TGListTreeItem*,ObjectPath>::iterator curr = gItemSources.begin();
00115   std::map<TGListTreeItem*,ObjectPath>::iterator end  = gItemSources.end();
00116   for (; curr != end; curr++)
00117     {
00118       TGListTreeItem* p = (*curr).first;
00119       ObjectPath s = (*curr).second;
00120       if (s == src)
00121         return p;
00122     }
00123   return NULL;
00124 }
00125 
00126 TObject* Roody::GetObject(const ObjectPath& src)
00127 {
00128   if (src.size() < 1)
00129     {
00130       //printf("GetObject %s return NULL\n", src.toString().c_str());
00131       return NULL;
00132     }
00133 
00134   TObject *obj = gObjectCache[src];
00135   if (obj)
00136     {
00137       //printf("GetObject %s return %p (cached)\n", src.toString().c_str(), obj);
00138       return obj;
00139     }
00140 
00141   DataSourceBase* d = gDataSources[src.front()];
00142   if (d)
00143     {
00144       obj = d->GetObject(src);
00145 
00146       if (obj == NULL)
00147         {
00148           std::string s;
00149           s += "Cannot access ";
00150           s += src.toString();
00151           fStatusBar->SetText(s.c_str());
00152 #if 0
00153           obj = new TPaveLabel(0.1,0.1,0.9,0.9,s.c_str());
00154 #endif
00155         }
00156     }
00157   else
00158     {
00159       std::string s;
00160       s += "No source for ";
00161       s += src.toString();
00162       fStatusBar->SetText(s.c_str());
00163 #if 0
00164       obj = new TPaveLabel(0.1,0.1,0.9,0.9,s.c_str());
00165 #endif
00166     }
00167 
00168 
00169   gObjectCache[src] = obj;
00170   
00171   //printf("GetObject %s return %p\n", src.toString().c_str(), obj);
00172 
00173   return obj;
00174 }
00175 
00176 TObject* Roody::RereadObject(const ObjectPath& src)
00177 {
00178   TObject *obj = gObjectCache[src];
00179   if (obj)
00180     {
00181       gObjectCache.erase(src);
00182     }
00183 
00184   TObject *xobj = GetObject(src);
00185 
00186   if (xobj == NULL)
00187     {
00188       xobj = obj;
00189       gObjectCache[src] = obj;
00190     }
00191 
00192   // if new object is same as the old one, do not delete it!
00193   if (obj != xobj)
00194     {
00195       //printf("delete %p\n", obj);
00196       delete obj;
00197     }
00198 
00199   return xobj;
00200 }
00201 
00202 std::map<TVirtualPad*,PadObjectVec> gPadContents;
00203 
00204 ClassImp(Roody);
00205 
00206 TPeakFindPanel *Roody::fgPeakFindPanel = 0;
00207 
00208 Roody::Roody(const TGWindow *p, UInt_t w, UInt_t h) // ctor
00209   : TGMainFrame(p?p:gClient->GetRoot(), w, h)
00210 {
00211   if (gAllObjects == NULL)
00212     {
00213       gAllObjects = new TList();
00214       gROOT->GetListOfCleanups()->Add(gAllObjects);
00215     }
00216 
00217   //
00218   fPopupMenu = 0;
00219   fAddToGroupPopup = 0;
00220   //
00221   fCanvasCount = 0;
00222   fZoomCanvas = 0;
00223   //
00224   SetWindowName("Roody");
00225   //
00226 #if 0
00227   gStyle->SetPalette( 1 );
00228   //
00229   gStyle->SetTitleTextColor( kBlue );
00230   gStyle->SetStatTextColor( kBlue );
00231   gStyle->SetTitleBorderSize( 0 );
00232   gStyle->SetStatBorderSize( 0 );
00233   //
00234   gStyle->SetFuncColor( kBlue );
00235   gStyle->SetOptFit( 1111 );
00236 #endif
00237   gStyle->SetOptStat( 1001111 );
00238   //
00239   LayoutGUI();
00240   AddPeakFind();
00241   AddAxisLimits();
00242   AddSetCut();
00243   AddZoomOption();
00244   //
00245   Resize( GetDefaultSize() );
00246   MapSubwindows();
00247   Layout(); // member function of TGCompositeFrame
00248   MapWindow();
00249   fStatusBar->SetText("Welcome to Roody");
00250   //
00251   fZoneRows = 1;  // default zone row setting
00252   fZoneColumns = 1;  // default zone column setting
00253   fUpdateTimerSec = 0;  //default refresh time
00254   fUpdatePause = false;
00255   fUpdateTimer = new TTimer(0,kTRUE);
00256   //
00257   TQObject::Connect( fUpdateTimer,"Timeout()","Roody",this,"RefreshAll()" );
00258   StartUpdateTimer(); // Refresh off by default
00259   //
00260 }
00261 
00262 static std::string PathToString(const ObjectPath& src)
00263 {
00264   std::string s = src.front();
00265   for (unsigned int j=1; j<src.size(); j++)
00266     {
00267       s += "|";
00268       s += src[j];
00269     }
00270   return s;
00271 }
00272 
00273 static std::vector<std::string> split(char sep, const std::string& str)
00274 {
00275   std::vector<std::string> vec;
00276   
00277   char buf[1024];
00278   strncpy(buf, str.c_str(), sizeof(buf));
00279   buf[sizeof(buf)-1] = 0;
00280   
00281   char* s = buf;
00282   char* p = buf;
00283   
00284   while (s[0] != 0)
00285     {
00286       while (*p != 0)
00287         {
00288           if (*p == sep)
00289             {
00290               *p = 0;
00291               p++;
00292               break;
00293             }
00294           p++;
00295         }
00296       
00297       vec.push_back(s);
00298       s = p;
00299     }
00300 
00301   return vec;
00302 }
00303 
00304 static std::vector<int> toInt(const std::vector<std::string>& vec)
00305 {
00306   std::vector<int> ivec;
00307   for (unsigned int i=0; i<vec.size(); i++)
00308     ivec.push_back(atoi(vec[i].c_str()));
00309   return ivec;
00310 }
00311 
00312 static ObjectPath StringToPath(const std::string& source)
00313 {
00314   ObjectPath path;
00315   std::vector<std::string> s = split('|', source);
00316   for (unsigned int i=0; i<s.size(); i++)
00317     path.push_back(s[i]);
00318   return path;
00319 }
00320 
00321 #if 0
00322 static ObjectPath StringToPath(const std::string& source)
00323 {
00324   ObjectPath path;
00325   
00326   char buf[1024];
00327   strncpy(buf, source.c_str(), sizeof(buf));
00328   buf[sizeof(buf)-1] = 0;
00329   
00330   char* s = buf;
00331   char* p = buf;
00332   
00333   while (s[0] != 0)
00334     {
00335       while (*p != 0)
00336         {
00337           if (*p == '|')
00338             {
00339               *p = 0;
00340               p++;
00341               break;
00342             }
00343           p++;
00344         }
00345       
00346       path.push_back(s);
00347       s = p;
00348     }
00349 
00350   return path;
00351 }
00352 #endif
00353 
00354 void Roody::RestoreObjects(RoodyXML*xml, TVirtualPad *pad, PMXML_NODE parent)
00355 {
00356   for (int j=0; ; j++)
00357     {
00358       j = xml->FindNode(parent, j, "object");
00359       if (j<0)
00360         break;
00361 
00362       PMXML_NODE xobject = xml->GetNode(parent, j);
00363       
00364       std::string xclass     = xml->GetNodeString(xobject, xml->FindNode(xobject, 0, "class"));
00365       std::string name       = xml->GetNodeString(xobject, xml->FindNode(xobject, 0, "name"));
00366       std::string source     = xml->GetNodeString(xobject, xml->FindNode(xobject, 0, "source"));
00367       std::string drawOption = xml->GetNodeString(xobject, xml->FindNode(xobject, 0, "drawOption"));
00368       
00369       if (source.length() < 1)
00370         continue;
00371       
00372       ObjectPath path = StringToPath(source);
00373       TGListTreeItem* item = FindItem(path);
00374       
00375       if (!item)
00376         {
00377           std::string s;
00378           s += "Cannot find object \"";
00379           s += name;
00380           s += "\"";
00381           new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
00382           continue;
00383         }
00384       
00385       DrawItemOnPad(item, pad, true);
00386     }
00387 }
00388 
00389 void Roody::RestoreFile(const char* xmlFilename)
00390 {
00391   int inode;
00392   RoodyXML xml;
00393 
00394   if (!xmlFilename)
00395     {
00396       xmlFilename = "default.xml";
00397       // check that the default xml save file exists.
00398       FILE *fp = fopen(xmlFilename, "r");
00399       if (!fp)
00400          return;
00401       fclose(fp);
00402       if (!xml.OpenFileForRead(xmlFilename))
00403         return;
00404     }
00405   else
00406     {
00407       if (!xml.OpenFileForRead(xmlFilename))
00408         {
00409           std::string s = "Failed to open XML file: ";
00410           s += xmlFilename;
00411           fStatusBar->SetText(s.c_str());
00412           new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
00413           return;
00414         }
00415     }
00416 
00417   //xml.PrintTree( 0 );
00418 
00419   for (inode = 0; ; inode++)
00420     {
00421       inode = xml.FindNode(xml.roodyNode_, inode, "online");
00422       if (inode < 0)
00423         break;
00424   
00425       std::string serverName = xml.GetNodeString(xml.roodyNode_, inode);
00426 
00427       ConnectServer(serverName.c_str());
00428     }
00429   
00430   for (inode = 0; ; inode++)
00431     {
00432       inode = xml.FindNode(xml.roodyNode_, inode, "file");
00433       if (inode < 0)
00434         break;
00435   
00436       std::string fileName = xml.GetNodeString(xml.roodyNode_, inode);
00437 
00438       TGListTreeItem *fileItem = fContents->FindChildByName(fTreeItemFiles,fileName.c_str()); 
00439       if (!fileItem)
00440         {
00441           if (OpenFile(fileName.c_str()))
00442             { 
00443               std::string s("Could not open data file \"");
00444               s += fileName + "\"\nerror occurred while parsing xml file \"" + xmlFilename; 
00445               new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
00446               //return;
00447             }
00448         }
00449     }
00450   
00451   inode = xml.FindNode(xml.roodyNode_, 0, "graphics");
00452   
00453   if (inode >= 0)
00454     {
00455       PMXML_NODE xgraphics = xml.GetNode(xml.roodyNode_, inode);
00456       
00457       std::string zones = xml.GetNodeString(xgraphics, xml.FindNode(xgraphics, 0, "zones"));
00458       int refresh = atoi(xml.GetNodeString(xgraphics, xml.FindNode(xgraphics, 0, "refresh")).c_str());
00459 
00460       std::vector<int> izones = toInt(split('x', zones));
00461       
00462       fZoneColumns = izones[0];
00463       fZoneRows    = izones[1];
00464       SetupZonesMenu();
00465 
00466       SetRefreshRate(refresh);
00467     }
00468 
00469   for (int i=0; ; i++)
00470     {
00471       i = xml.FindNode(xml.roodyNode_, i, "canvas");
00472       if (i<0)
00473         break;
00474 
00475       PMXML_NODE xcanvas = xml.GetNode(xml.roodyNode_, i);
00476 
00477       std::string name  = xml.GetNodeString(xcanvas, xml.FindNode(xcanvas, 0, "name"));
00478       std::string size  = xml.GetNodeString(xcanvas, xml.FindNode(xcanvas, 0, "size"));
00479       std::string zones = xml.GetNodeString(xcanvas, xml.FindNode(xcanvas, 0, "zones"));
00480       //printf("canvas name: %s\n", name.c_str());
00481 
00482       std::vector<int> izones = toInt(split('x', zones));
00483       std::vector<int> isize  = toInt(split(' ', size));
00484 
00485       TCanvas* c = MakeNewCanvas(NULL, izones[0], izones[1], isize[0], isize[1], isize[2], isize[3]);
00486 
00487       RestoreObjects(&xml, c, xcanvas);
00488 
00489       for (int j=0; ; j++)
00490         {
00491           j = xml.FindNode(xcanvas, j, "pad");
00492           if (j<0)
00493             break;
00494 
00495           PMXML_NODE xpad = xml.GetNode(xcanvas, j);
00496 
00497           int number = atoi(xml.GetNodeString(xpad, xml.FindNode(xpad, 0, "number")).c_str());
00498           RestoreObjects(&xml, c->cd(number), xpad);
00499         }
00500     }
00501 
00502   for (int i=0; ; i++)
00503     {
00504       i = xml.FindNode(xml.roodyNode_, i, "group");
00505       if (i<0)
00506         break;
00507 
00508       PMXML_NODE xgroup = xml.GetNode(xml.roodyNode_, i);
00509 
00510       std::string groupname  = xml.GetNodeString(xgroup, xml.FindNode(xgroup, 0, "name"));
00511       //printf("group name: %s\n", groupname.c_str());
00512 
00513       fContents->OpenItem(fTreeItemGroups);
00514 
00515       TGListTreeItem *groupItem = MakeNewGroup(groupname.c_str());
00516       assert(groupItem);
00517 
00518       for (int j=0; ; j++)
00519         {
00520           j = xml.FindNode(xgroup, j, "histogram");
00521           if (j<0)
00522             break;
00523 
00524           PMXML_NODE xobject = xml.GetNode(xgroup, j);
00525 
00526           std::string name   = xml.GetNodeString(xobject, xml.FindNode(xobject, 0, "name"));
00527           std::string source = xml.GetNodeString(xobject, xml.FindNode(xobject, 0, "source"));
00528 
00529           ObjectPath path = StringToPath(source);
00530           TGListTreeItem* item = FindItem(path);
00531 
00532           AddHistogramToGroup(groupItem, name.c_str(), item);
00533         }
00534     }
00535 }
00536 
00537 void Roody::SetupZonesMenu()
00538 {
00539   UncheckAllZones();
00540   switch( fZoneColumns )
00541   {
00542     case 1:
00543     {
00544       switch( fZoneRows )
00545       {
00546         case 1:
00547           fMenuZones->CheckEntry( M_ZONES_11 );
00548           break;
00549         case 2:
00550           fMenuZones->CheckEntry( M_ZONES_12 );
00551           break;
00552         case 3:
00553           fMenuZones->CheckEntry( M_ZONES_13 );
00554           break;
00555         default:
00556           SetZonesUser();
00557       }
00558       break;
00559     }
00560     case 2:
00561     {
00562       switch( fZoneRows )
00563       {
00564         case 1:
00565           fMenuZones->CheckEntry( M_ZONES_21 );
00566           break;
00567         case 2:
00568           fMenuZones->CheckEntry( M_ZONES_22 );
00569           break;
00570         default:
00571           SetZonesUser();
00572       }
00573       break;
00574     }
00575     case 3:
00576     {
00577       switch( fZoneRows )
00578       {
00579         case 3:
00580           fMenuZones->CheckEntry( M_ZONES_33 );
00581           break;
00582         default:
00583           SetZonesUser();
00584       }
00585       break;
00586     }
00587     case 4:
00588     {
00589       switch( fZoneRows )
00590       {
00591         case 3:
00592           fMenuZones->CheckEntry( M_ZONES_44 );
00593           break;
00594         default:
00595           SetZonesUser();
00596       }
00597       break;
00598     }
00599     default:
00600       SetZonesUser();
00601   }
00602 }
00603 
00604 void Roody::SetZonesUser()
00605 {
00606   fMenuZones->DeleteEntry( M_ZONES_USER );
00607   std::stringstream ss;
00608   ss << fZoneColumns << "x" << fZoneRows;
00609   fMenuZones->AddEntry( ss.str().c_str(), M_ZONES_USER,
00610                         0, 0, fMenuZones->GetEntry(M_ZONES_DIALOG) );
00611   fMenuZones->CheckEntry( M_ZONES_USER );
00612 }
00613 
00614 void Roody::SaveFilePadContents(RoodyXML& xml, std::ofstream& output, std::string space, const PadObjectVec& contents)
00615 {
00616   for (unsigned int i=0; i<contents.size(); i++)
00617     {
00618       output << space << "<object>\n";
00619       ObjectPath src = contents[i].fSource;
00620       TObject *obj = GetObject(src);
00621       //printf("lookup object %p\n", obj);
00622       assert(obj);
00623       output << space << "  <class>" << obj->ClassName() << "</class>\n";
00624       output << space << "  <name>"  << xml.Encode(obj->GetName()) << "</name>\n";
00625       if (src.front() != "")
00626         {
00627           output << space << "  <source>";
00628           output << xml.Encode(PathToString(src));
00629           output << "</source>\n"; 
00630           output << space << "  <drawOption>";
00631           output << xml.Encode(contents[i].fDrawOption);
00632           output << "</drawOption>\n"; 
00633         }
00634       output << space << "</object>\n";
00635     }
00636 }
00637 
00638 void Roody::SaveFile(const char* xmlFilename)
00639 {
00640   fStatusBar->SetText((std::string("Saving session into: ") + xmlFilename).c_str());
00641 
00642   RoodyXML xml;
00643   std::ofstream &output( xml.OpenFileForWrite(xmlFilename) );
00644   if( output.rdstate() != std::ios::goodbit  )
00645   {
00646     std::string s("Failed to open XML file \"");
00647     s += xmlFilename;
00648     new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
00649     return;
00650   }
00651   output << "<roody>\n";
00652   //
00653   // write online section
00654   //
00655   for (unsigned int i=0; i<fOnlineFiles.size(); i++)
00656     {
00657       output << "  <online>";
00658       output << xml.Encode(fOnlineFiles[i].c_str());
00659       output << "</online>\n";
00660     }
00661   // 
00662   // write file section
00663   // 
00664   TGListTreeItem *temp = fTreeItemFiles->GetFirstChild();
00665   if( temp ) 
00666   { 
00667     output << "  <file>" << xml.Encode(temp->GetText()) << "</file>\n";
00668     TGListTreeItem *temp2;
00669     while( (temp2=temp->GetNextSibling()) )
00670     { 
00671       output << "  <file>" << xml.Encode(temp2->GetText()) << "</file>\n";
00672       temp = temp2;
00673     } 
00674   } 
00675   //
00676   // write graphics section
00677   //
00678   output << "  <graphics>\n";
00679   std::string zones = GetZoneSetting(fZoneColumns, fZoneRows);
00680   output << "    <zones>" << xml.Encode(zones) << "</zones>\n";
00681   output << "    <refresh>" << fUpdateTimerSec << "</refresh>\n";
00682   output << "  </graphics>\n";
00683   //
00684   // write canvas section
00685   //
00686   TIter next = gROOT->GetListOfCanvases();
00687   while (1)
00688   {
00689     TCanvas *canvas = (TCanvas*)next();
00690     if (!canvas)
00691       break;
00692 
00693     output << "  <canvas>\n";
00694     output << "    <name>" << canvas->GetName() << "</name>\n";
00695     output << "    <size>" << canvas->GetWindowTopX() << " " << canvas->GetWindowTopY() << " " << canvas->GetWindowWidth() << " " << canvas->GetWindowHeight() << "</size>\n";
00696     output << "    <zones>" << fCanvasColumns[canvas] << "x" << fCanvasRows[canvas] << "</zones>\n";
00697 
00698     if (gPadContents[canvas].size() > 0)
00699       {
00700         SaveFilePadContents(xml, output, "    ", gPadContents[canvas]);
00701       }
00702     else
00703       {
00704         for (int i=1; i<1000; i++)
00705           {
00706             TVirtualPad *pad = canvas->cd(i);
00707             //printf("canvas %p subpad %d is %p\n", canvas, i, pad);
00708             if (!pad || pad->GetNumber()!=i)
00709               break;
00710             
00711             output << "    <pad>\n";
00712             output << "      <number>" << pad->GetNumber() << "</number>\n";
00713             SaveFilePadContents(xml, output, "      ", gPadContents[pad]);
00714             output << "    </pad>\n";
00715           }
00716       }
00717 
00718     output << "  </canvas>\n";
00719   }
00720   //
00721   // write group section
00722   //
00723   std::size_t nGroups = fGroupFolders.size();
00724   for( std::size_t i=0; i<nGroups; ++i )
00725   {
00726     output << "  <group>\n";
00727     TGListTreeItem *groupFolder = fGroupFolders[i];
00728     output << "    <name>" << xml.Encode(groupFolder->GetText()) << "</name>\n";
00729 
00730     ItemVec items;
00731     GetFolderItems(&items, groupFolder);
00732 
00733     for (unsigned int j=0; j<items.size(); j++)
00734       {
00735         TGListTreeItem* item = items[j];
00736         output << "    <histogram>\n";
00737         output << "      <name>" << xml.Encode(item->GetText()) << "</name>\n";
00738         output << "      <source>" << xml.Encode(PathToString(gItemSources[item])) << "</source>\n";
00739         output << "    </histogram>\n";
00740       }
00741     output << "  </group>\n";
00742   }
00743   output << "</roody>\n";
00744 }
00745 
00746 Roody::~Roody()
00747 {
00748   fUpdateTimer->Stop();
00749   TQObject::Disconnect(fUpdateTimer);
00750   TQObject::Disconnect(this);
00751   //Timers
00752   //delete fUpdateTimer;
00753   //
00754   //Cleanup();
00755   //
00756 }
00757 
00758 void Roody::LayoutGUI()
00759 {
00760   LayoutMenuBar(); // Lay out the MenuBar
00761   //
00762   // Lay out the rest of the GUI
00763   //
00764   //TGLayoutHints* frameLayout1 = new TGLayoutHints( kLHintsTop|kLHintsLeft, 5, 5, 5, 5 );
00765   TGLayoutHints* frameLayout2 = new TGLayoutHints( kLHintsTop|kLHintsExpandX|kLHintsExpandY, 5, 5, 5, 5 );
00766   TGLayoutHints* frameLayout3 = new TGLayoutHints( kLHintsTop|kLHintsExpandX, 0, 0, 0, 0 );
00767   //
00768   TGVerticalFrame* verticalFrame = new TGVerticalFrame( this, 10, 10 );
00769   //
00770   TGHorizontalFrame* horizontalFrame = new TGHorizontalFrame( verticalFrame, 10, 10 );
00771   //
00772   fReopenButton = new TGTextButton( horizontalFrame, "Reopen", M_REOPEN_BUTTON );
00773   fReopenButton->Associate( this );
00774   fReopenButton->SetToolTipText( "click to reopen data sources", 250 );
00775   horizontalFrame->AddFrame( fReopenButton, new TGLayoutHints(kLHintsCenterX,2,2,2,2) );
00776   fRefreshButton = new TGTextButton( horizontalFrame, "Refresh NOW", M_REFRESH_BUTTON );
00777   fRefreshButton->Associate( this );
00778   fRefreshButton->SetToolTipText( "click to refresh online histograms once right now", 250 );
00779   horizontalFrame->AddFrame( fRefreshButton, new TGLayoutHints(kLHintsCenterX,2,2,2,2) );
00780   verticalFrame->AddFrame( horizontalFrame, frameLayout3 );
00781   //
00782   TGCanvas *canvas = new TGCanvas( verticalFrame, 340, 300 );
00783   fContents = new MTGListTree(canvas, kHorizontalFrame );
00784   fContents->AddItem( 0, "/" );
00785   TGListTreeItem* top = fContents->GetFirstItem();
00786   fTreeItemGroups = fContents->AddItem(top, "Groups" );
00787   fTreeItemFiles  = fContents->AddItem(top, "Offline" );
00788   fTreeItemOnline = fContents->AddItem(top, "Online" );
00789   fContents->OpenItem(top);
00790   fContents->Associate( this );
00791   verticalFrame->AddFrame(canvas, frameLayout2 );
00792   //
00793   AddFrame( verticalFrame, frameLayout2 );
00794   //
00795   TGLayoutHints* statusBarLayout = new TGLayoutHints( kLHintsBottom|kLHintsLeft|kLHintsExpandX,0, 0, 2, 0 );
00796   fStatusBar = new TGStatusBar( this, 50, 10, kHorizontalFrame );
00797   AddFrame( fStatusBar, statusBarLayout );
00798 }
00799 
00800 class OptStatMenu: public TGPopupMenu
00801 {
00802 public:
00803   OptStatMenu(const TGWindow* w)
00804     : TGPopupMenu(w)
00805   {
00806     AddEntry("Name",       'n');
00807     AddEntry("Entries",    'e');
00808     AddEntry("Mean", 'm');
00809     AddEntry("Mean with error", 'M');
00810     AddEntry("RMS",  'r');
00811     AddEntry("RMS with error",  'R');
00812     AddEntry("Underflows", 'u');
00813     AddEntry("Overflows",  'o');
00814     AddEntry("Integral",   'i');
00815     AddEntry("Skew",       's');
00816     AddEntry("Skew with error", 'S');
00817     AddEntry("Kurtosis",   'k');
00818     AddEntry("Kurtosis with error", 'K');
00819     //AddEntry( "user", M_ZONES_USER );
00820     //AddEntry( "&Set zones...", M_ZONES_DIALOG );
00821     //CheckEntry(M_ZONES_11); // place check mark on the default
00822     Associate(this);
00823     GetOptStat();
00824     SetOptStat();
00825   }
00826 
00827   Bool_t ProcessMessage( Long_t msg, Long_t parm1, Long_t parm2 )
00828   {
00829     //printf("OptStatMenu::ProcessMessage %d (%d, %d), parm1: %d, parm2: %d\n", msg, GET_MSG(msg), GET_SUBMSG(msg), parm1, parm2);
00830 
00831     if (GET_MSG(msg) == kC_COMMAND && GET_SUBMSG(msg) == kCM_MENU)
00832       {
00833         //printf("OptStatMenu::ProcessMessage menu message %d (%d, %d), parm1: %d \'%c\', parm2: %d\n", msg, GET_MSG(msg), GET_SUBMSG(msg), parm1, parm1, parm2);
00834 
00835         if (IsEntryChecked(parm1))
00836           UnCheckEntry(parm1);
00837         else
00838           CheckEntry(parm1);
00839 
00840         //Modified();
00841 
00842         SetOptStat();
00843       }
00844     return true;
00845   }
00846 
00847   void GetOptStat()
00848   {
00849     Int_t s = gStyle->GetOptStat();
00850     int ss;
00851 
00852     ss = s%10; s/=10; if (ss) CheckEntry('n');
00853     ss = s%10; s/=10; if (ss) CheckEntry('e');
00854     ss = s%10; s/=10; if (ss) CheckEntry('m'); if (ss>1) CheckEntry('M');
00855     ss = s%10; s/=10; if (ss) CheckEntry('r'); if (ss>1) CheckEntry('R');
00856     ss = s%10; s/=10; if (ss) CheckEntry('u');
00857     ss = s%10; s/=10; if (ss) CheckEntry('o');
00858     ss = s%10; s/=10; if (ss) CheckEntry('i');
00859     ss = s%10; s/=10; if (ss) CheckEntry('s'); if (ss>1) CheckEntry('S');
00860     ss = s%10; s/=10; if (ss) CheckEntry('k'); if (ss>1) CheckEntry('K');
00861   }
00862 
00863   void SetOptStat()
00864   {
00865     const TList* list = GetListOfEntries();
00866     TIter next(list);
00867     std::string s = "";
00868     while (TGMenuEntry *entry = (TGMenuEntry*)next())                                
00869       if (IsEntryChecked(entry->GetEntryId()))
00870         s += (char)entry->GetEntryId();
00871     gStyle->SetOptStat(s.c_str());
00872     printf("SetOptStat(\"%s\") got %d\n", s.c_str(), gStyle->GetOptStat());
00873   }
00874 };
00875 
00876 void Roody::LayoutMenuBar()
00877 {
00878   TGPopupMenu* menuFile = new TGPopupMenu( fClient->GetRoot() );
00879   //
00880   menuFile->AddEntry( "&New canvas", M_NEW_CANVAS);
00881   menuFile->AddEntry( "Redraw current canvas", M_REDRAW_CANVAS);
00882   menuFile->AddSeparator();
00883   menuFile->AddEntry( "Open data file...", M_FILE_OPEN );
00884   menuFile->AddEntry( "Open MIDAS connection...", M_FILE_ONLINE );
00885   menuFile->AddEntry( "Open ROOT connection...", M_FILE_NetDirectory );
00886   menuFile->AddSeparator();
00887   menuFile->AddEntry( "Save session",    M_FILE_SAVE_DEFAULT );
00888   menuFile->AddEntry( "Save session as...",    M_FILE_SAVE );
00889   menuFile->AddEntry( "Restore session...", M_FILE_RESTORE );
00890   menuFile->AddSeparator();
00891   menuFile->AddEntry( "&Exit", M_FILE_EXIT );
00892   //
00893   fMenuRefresh = new TGPopupMenu( fClient->GetRoot() );
00894   fMenuRefresh->AddEntry( "&Off", M_REFRESH_OFF );
00895   fMenuRefresh->AddEntry( "&Refresh now", M_REFRESH_NOW );
00896   fMenuRefresh->AddEntry( "&1 second", M_REFRESH_1SEC );
00897   fMenuRefresh->AddEntry( "&3 seconds", M_REFRESH_3SEC );
00898   fMenuRefresh->AddEntry( "&5 seconds", M_REFRESH_5SEC );
00899   fMenuRefresh->AddEntry( "10 seconds", M_REFRESH_10SEC );
00900   fMenuRefresh->AddEntry( "&Set refresh period...", M_REFRESH_DIALOG );
00901   //
00902   fMenuZones = new TGPopupMenu( fClient->GetRoot() );
00903   fMenuZones->AddEntry( "1x1", M_ZONES_11 );  
00904   fMenuZones->AddEntry( "1x2", M_ZONES_12 );  
00905   fMenuZones->AddEntry( "1x3", M_ZONES_13 );  
00906   fMenuZones->AddEntry( "2x1", M_ZONES_21 );  
00907   fMenuZones->AddEntry( "2x2", M_ZONES_22 ); 
00908   fMenuZones->AddEntry( "3x3", M_ZONES_33 );
00909   fMenuZones->AddEntry( "4x4", M_ZONES_44 );
00910   fMenuZones->AddEntry( "user", M_ZONES_USER );
00911   fMenuZones->AddEntry( "&Set zones...", M_ZONES_DIALOG );
00912   fMenuZones->CheckEntry(M_ZONES_11); // place check mark on the default
00913   //
00914   OptStatMenu* optStatMenu = new OptStatMenu(fClient->GetRoot());
00915   //
00916   fMenuPlot = new TGPopupMenu( fClient->GetRoot() );
00917   fMenuPlot->AddEntry( "New canvas", M_PLOT_NEW );
00918   fMenuPlot->AddEntry( "Current pad", M_PLOT_REPLACE );
00919   fMenuPlot->AddEntry( "Overlay on Current pad", M_PLOT_SAME );
00920   fMenuPlot->AddEntry( "Next pad", M_PLOT_NEXT );
00921   SetDestination( D_PLOT_NEW );
00922   //
00923   TGPopupMenu* menuClear = new TGPopupMenu( fClient->GetRoot() );
00924   menuClear->AddEntry( "&Reset all", M_RESET_ALL );
00925   //
00926   TGPopupMenu* menuHelp = new TGPopupMenu( fClient->GetRoot() );
00927   //menuHelp->AddEntry( "Contents", M_HELP_CONTENTS );
00928   menuHelp->AddEntry( "&About", M_HELP_ABOUT );
00929   //
00930   menuFile->Associate( this );
00931   fMenuRefresh->Associate( this );
00932   fMenuZones->Associate( this );
00933   fMenuPlot->Associate( this );
00934   menuClear->Associate( this );
00935   menuHelp->Associate( this );
00936   //
00937   TGLayoutHints* menuBarLayout1 = new TGLayoutHints( kLHintsNormal|kLHintsExpandX, 0, 0, 0, 10 );
00938   TGLayoutHints* menuBarLayout2 = new TGLayoutHints( kLHintsTop|kLHintsLeft , 5, 0, 0, 0 );
00939   TGLayoutHints* menuBarLayout3 = new TGLayoutHints( kLHintsTop|kLHintsRight, 0, 5, 0, 0 );
00940 
00941   TGMenuBar *menuBar = new TGMenuBar( this, 1, 1, kRaisedFrame );
00942   menuBar->AddPopup( "&File", menuFile, menuBarLayout2 );
00943   menuBar->AddPopup( "&Refresh", fMenuRefresh, menuBarLayout2 );
00944   menuBar->AddPopup( "&Zones", fMenuZones, menuBarLayout2 );
00945   menuBar->AddPopup( "OptStat",  optStatMenu, menuBarLayout2 );
00946   menuBar->AddPopup( "&Plot in", fMenuPlot, menuBarLayout2 );
00947   menuBar->AddPopup( "&Reset", menuClear, menuBarLayout2 );
00948   menuBar->AddPopup( "&Help", menuHelp, menuBarLayout3 );
00949   //
00950   AddFrame( menuBar, menuBarLayout1 );
00951 }
00952 
00953 void Roody::AddSetCut()
00954 {
00955   TClassMenuItem *menuItem = new TClassMenuItem( TClassMenuItem::kPopupUserFunction,
00956                                                  Roody::Class(),
00957                                                  "Send to Analyzer", "SetCut", this,
00958                                                  "TObject*", 0);
00959   TCutG::Class()->GetMenuList()->AddFirst(menuItem);
00960 }
00961 
00962 void Roody::SetCut( TObject *o )
00963 {
00964   TCutG *cut = static_cast<TCutG*>(o);
00965 
00966   new TGMsgBox( gClient->GetRoot(), this, "Error", "Roody::SetCut() is not implemented, sorry.", kMBIconExclamation, 0, NULL );
00967 
00968 #if 0  
00969   fSock->Send("SetCut");
00970   fSock->Send(cut->GetName());
00971   TMessage m (kMESS_OBJECT);
00972   m<<cut;
00973   fSock->Send(m);
00974 #endif
00975 }
00976 
00977 void Roody::AddAxisLimits()
00978 {
00979   TClassMenuItem *menuItem = new TClassMenuItem( TClassMenuItem::kPopupUserFunction,
00980                                                  Roody::Class(),
00981                                                  "AxisLimits", "AxisLimits", this, "" );
00982   TH1C::Class()->GetMenuList()->AddFirst(menuItem);
00983   TH1S::Class()->GetMenuList()->AddFirst(menuItem);
00984   TH1I::Class()->GetMenuList()->AddFirst(menuItem);
00985   TH1F::Class()->GetMenuList()->AddFirst(menuItem);
00986   TH1D::Class()->GetMenuList()->AddFirst(menuItem);
00987   TFrame::Class()->GetMenuList()->AddFirst(menuItem);
00988 }
00989 
00990 void Roody::AxisLimits()
00991 {
00992   CanvasLimits *limits = fCanvasLimits[gPad->GetCanvas()->GetCanvasID()];
00993   if (!limits)
00994     {
00995       limits = new CanvasLimits();
00996       fCanvasLimits[gPad->GetCanvas()->GetCanvasID()] = limits;
00997     }
00998   new TAxisLimitsDialog( gClient->GetRoot(), NULL, 250, 100, limits, this);
00999 }
01000 
01001 TObject* Roody::ApplyCanvasLimits(const CanvasLimits* limits, const ObjectPath* src, TObject *obj)
01002 {
01003   if (!limits)
01004     return obj;
01005 
01006   if (obj->InheritsFrom(TH1::Class()))
01007     {
01008       TH1* h = (TH1*)obj;
01009 
01010       const char* name = h->GetName();
01011       
01012       if (limits->fRebin > 1)
01013         {
01014           char rebinx[256];
01015           sprintf(rebinx,"_rebin%d_",limits->fRebin);
01016           
01017           if (strstr(name,rebinx)!=NULL)
01018             {
01019               //printf("histogram %s is already rebinned %s (%d)\n",name,rebinx,fRebin);
01020             }
01021           else
01022             {
01023               TH1* hh = (TH1*)GetObject(*src);
01024               assert(hh!=NULL);
01025               
01026               name = hh->GetName();
01027               char buf[256];
01028               sprintf(buf, "%s%s", name, rebinx);
01029               h = hh->Rebin(limits->fRebin, buf); // object "hh" is cloned into "h"
01030 
01031               delete obj;
01032             }
01033         }
01034       else
01035         {
01036           if (strstr(name,"_rebin")!=NULL)
01037             {
01038               h = (TH1*)GetObject(*src);
01039               assert(h != NULL);
01040             }
01041         }
01042       
01043       if (limits->fDoZoomXaxis)
01044         {
01045           int ufirst = h->GetXaxis()->FindBin(limits->fXmin);
01046           int ulast  = h->GetXaxis()->FindBin(limits->fXmax);
01047           bool rescaleY = (ufirst != h->GetXaxis()->GetFirst()) || (ulast != h->GetXaxis()->GetLast());
01048           //printf("set bins %d %d, rescaleY %d\n", ufirst, ulast, rescaleY);
01049           h->GetXaxis()->SetRange(ufirst, ulast);
01050           //h->GetXaxis()->SetRangeUser(limits->fXmin, limits->fXmax);
01051           if (!limits->fDoZoomYaxis)
01052             h->GetYaxis()->UnZoom();
01053         }
01054       
01055       if (limits->fDoZoomYaxis)
01056         {
01057           h->SetMinimum(limits->fYmin);
01058           h->SetMaximum(limits->fYmax);
01059         }
01060       
01061       if (limits->fForceUnzoomX)
01062         h->GetXaxis()->UnZoom();
01063       
01064       if (limits->fForceUnzoomY)
01065         h->GetYaxis()->UnZoom();
01066 
01067       return h;
01068     }
01069   else
01070     {
01071       return obj;
01072     }
01073 }
01074 
01075 static void DrawVec(TVirtualPad *canvas, const PadObjectVec* padvec)
01076 {
01077   //printf("DrawVec canvas %p, columns %d, rows %d\n", canvas, fCanvasColumns[canvas], fCanvasRows[canvas]);
01078 
01079   for (unsigned int i=0; i<padvec->size(); i++)
01080     {
01081       TVirtualPad* pad = canvas->cd((*padvec)[i].fPadNumber);
01082 
01083       if (!pad)
01084         {
01085           //printf("canvas %p has no pad %d\n", canvas, (*padvec)[i].fPadNumber);
01086           pad = canvas;
01087         }
01088 
01089       //printf("pad %p index %d\n", pad, (*padvec)[i].fPadNumber);
01090 
01091       TList* xcontents = pad->GetListOfPrimitives();
01092       int xcount = 0;
01093       if (xcontents)
01094         xcount = xcontents->GetSize();
01095 
01096       //printf("Draw %p into canvas %p pad %d %p[%d-%d], opt \'%s\'\n", (*padvec)[i].fObject, canvas, (*padvec)[i].fPadNumber, pad, xcount, gPadContents[pad].size(), (*padvec)[i].fDrawOption.c_str());
01097 
01098       if (xcount == 0)
01099         gPadContents.erase(pad);
01100 
01101       (*padvec)[i].fObject->Draw((*padvec)[i].fDrawOption.c_str());
01102 
01103       gPadContents[pad].push_back((*padvec)[i]);
01104 
01105       pad->Modified();
01106     }
01107 
01108   canvas->Modified();
01109   canvas->Update();
01110 }
01111 
01112 void Roody::AddObjectToVec(PadObjectVec* padvec, TVirtualPad* pad, const ObjectPath* src, TObject* obj, const char* drawOpt)
01113 {
01114   if (!obj)
01115     {
01116       fprintf(stderr,"Roody::AddObjectToVec: ERROR: attempt to draw a NULL object for %s!\n", src->toString().c_str());
01117       return;
01118     }
01119 
01120   pad->cd();
01121 
01122   TObject* xobj = ApplyCanvasLimits(fCanvasLimits[pad->GetCanvas()->GetCanvasID()], src, obj);
01123 
01124   if (xobj->InheritsFrom(TH1::Class()))
01125     {
01126       ((TH1*)xobj)->SetDirectory(0);
01127     }
01128 
01129   if (!gAllObjects->FindObject(xobj))
01130     gAllObjects->Add(xobj);
01131 
01132   xobj->SetBit(kCanDelete);
01133   xobj->SetBit(kMustCleanup);
01134 
01135   if (!drawOpt)
01136     drawOpt = "";
01137 
01138   int padNum = pad->GetNumber();
01139 
01140   if (padNum == 0)
01141      padNum = 1;
01142 
01143   //printf("add object %p to pad %p number %d, draw opt \'%s\'\n", obj, pad, padNum, drawOpt);
01144 
01145   padvec->push_back(PadObject(padNum, xobj, src, drawOpt));
01146 }
01147 
01148 static void CopyAttrs(TObject* dest, TObject* src)
01149 {
01150   //printf("copy attributes from %p to %p\n", src, dest);
01151   
01152   if (src->InheritsFrom(TAttLine::Class()) && dest->InheritsFrom(TAttLine::Class()))
01153     {
01154       TAttLine* hold = dynamic_cast<TAttLine*>(src);
01155       TAttLine* hnew = dynamic_cast<TAttLine*>(dest);
01156       hnew->SetLineColor(hold->GetLineColor());
01157       hnew->SetLineStyle(hold->GetLineStyle());
01158       hnew->SetLineWidth(hold->GetLineWidth());
01159     }
01160   
01161   if (src->InheritsFrom(TAttMarker::Class()) && dest->InheritsFrom(TAttMarker::Class()))
01162     {
01163       TAttMarker* hold = dynamic_cast<TAttMarker*>(src);
01164       TAttMarker* hnew = dynamic_cast<TAttMarker*>(dest);
01165       hnew->SetMarkerColor(hold->GetMarkerColor());
01166       hnew->SetMarkerSize(hold->GetMarkerSize());
01167       hnew->SetMarkerStyle(hold->GetMarkerStyle());
01168     }
01169   
01170   if (src->InheritsFrom(TAttFill::Class()) && dest->InheritsFrom(TAttFill::Class()))
01171     {
01172       TAttFill* hold = dynamic_cast<TAttFill*>(src);
01173       TAttFill* hnew = dynamic_cast<TAttFill*>(dest);
01174       hnew->SetFillColor(hold->GetFillColor());
01175       hnew->SetFillStyle(hold->GetFillStyle());
01176     }
01177 
01178   if (src->InheritsFrom(TH1::Class()) && dest->InheritsFrom(TH1::Class()))
01179     {
01180       TH1* hold = (TH1*)src;
01181       TH1* hnew = (TH1*)dest;
01182       hnew->GetXaxis()->SetRange(hold->GetXaxis()->GetFirst(),hold->GetXaxis()->GetLast());
01183     }
01184 }
01185 
01186 void Roody::AddPadToVec(PadObjectVec* padvec, TVirtualPad *pad, bool reread)
01187 {
01188   PadObjectVec* contents = &gPadContents[pad];
01189 
01190   if (!contents || contents->size() <= 0)
01191     return;
01192 
01193   for (unsigned int i=0; i<contents->size(); i++)
01194     {
01195       const PadObject *po = &(*contents)[i];
01196 
01197       TObject* newobject = NULL;
01198 
01199       if (reread)
01200         newobject = RereadObject(po->fSource);
01201       else
01202         newobject = GetObject(po->fSource);
01203 
01204       if (!newobject)
01205         continue;
01206 
01207       TObject* plotobject = newobject->Clone();
01208 
01209       TObject *oldobject  = po->fObject;
01210       if (oldobject)
01211         {
01212           // force a crash if oldobject has somehow been deleted
01213           if (gAllObjects->FindObject(oldobject))
01214             {
01215               //printf("maybe crash on destroyed %p\n", oldobject);
01216               oldobject->GetName();
01217             }
01218           else
01219             {
01220               //printf("maybe crash on destroyed %p ---> nope we know it is destroyed!\n", oldobject);
01221               oldobject = NULL;
01222             }
01223         }
01224 
01225       if (oldobject)
01226         CopyAttrs(plotobject, oldobject);
01227 
01228       AddObjectToVec(padvec, pad, &po->fSource, plotobject, po->fDrawOption.c_str());
01229     }
01230 
01231   pad->Modified();
01232 }
01233 
01234 void Roody::RedrawCanvas(TVirtualPad *canvas, bool reread)
01235 {
01236   if (!canvas && gPad)
01237     canvas = gPad->GetCanvas();
01238 
01239   if (!canvas)
01240     return;
01241 
01242   int savedPad = gPad->GetNumber();
01243 
01244   PadObjectVec padvec;
01245 
01246   if (gPadContents[canvas].size() > 0)
01247     {
01248       AddPadToVec(&padvec, canvas, reread);
01249     }
01250   else
01251     {
01252       for (int i=1; i<1000; i++)
01253         {
01254           TVirtualPad *pad = canvas->cd(i);
01255           //printf("canvas %p subpad %d is %p\n", canvas, i, pad);
01256           if (!pad || pad->GetNumber()!=i)
01257             break;
01258 
01259           AddPadToVec(&padvec, pad, reread);
01260         }
01261     }
01262 
01263   canvas->Clear();
01264 
01265   gPadContents.erase(canvas);
01266   for (int i=1; i<=fCanvasColumns[canvas]*fCanvasRows[canvas]; i++)
01267     gPadContents.erase(canvas->cd(i));
01268 
01269   canvas->Divide(fCanvasColumns[canvas], fCanvasRows[canvas]);
01270 
01271   gPadContents.erase(canvas);
01272   for (int i=1; i<=fCanvasColumns[canvas]*fCanvasRows[canvas]; i++)
01273     gPadContents.erase(canvas->cd(i));
01274 
01275   DrawVec(canvas, &padvec);
01276 
01277   canvas->cd(savedPad);
01278   canvas->Update();
01279 }
01280 
01281 void Roody::AddZoomOption()
01282 {
01283   TClassMenuItem *menuItem = new TClassMenuItem( TClassMenuItem::kPopupUserFunction,
01284                                                  Roody::Class(),
01285                                                  "ZoomOption", "ZoomOption", this, "" );
01286   TH1C::Class()->GetMenuList()->AddFirst(menuItem);
01287   TH1S::Class()->GetMenuList()->AddFirst(menuItem);
01288   TH1I::Class()->GetMenuList()->AddFirst(menuItem);
01289   TH1F::Class()->GetMenuList()->AddFirst(menuItem);
01290   TH1D::Class()->GetMenuList()->AddFirst(menuItem);
01291   TFrame::Class()->GetMenuList()->AddFirst(menuItem);
01292 }
01293 
01294 void Roody::ZoomOption()
01295 {
01296   // do not allow zoom on the zoom canvas
01297   //
01298   if (!gPad || !strcmp(gPad->GetCanvas()->GetName(),"Zoom Canvas"))
01299     return;
01300   //
01301   // find all histograms on the current pad, and store them in a vector
01302   //
01303 
01304   PadObjectVec* contents = &gPadContents[gPad];
01305 
01306   // make the zoom canvas (which is always 1x1),
01307   // and then draw the stored histograms on the zoom canvas
01308 
01309   TVirtualPad *padSave = gPad;
01310 
01311   if (fZoomCanvas)
01312     delete fZoomCanvas;
01313   fZoomCanvas = new TCanvas("Zoom Canvas", "Zoom Canvas");
01314   fZoomCanvas->cd();  // gPad should now be set to fZoomCanvas
01315 
01316   fZoomCanvas->Connect( "ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", "Roody",
01317                         this, "SelectPad(Int_t,Int_t,Int_t,TObject*)" );
01318 
01319   PadObjectVec padvec;
01320 
01321   for (unsigned int i=0; i<contents->size(); i++)
01322     {
01323       ObjectPath *src = &(*contents)[i].fSource;
01324       TObject* obj = GetObject(*src);
01325       if (!obj)
01326         continue;
01327       TObject *clone = obj->Clone();
01328       AddObjectToVec(&padvec, fZoomCanvas, src, clone, (*contents)[i].fDrawOption.c_str());
01329     }
01330 
01331   DrawVec(fZoomCanvas, &padvec);
01332 
01333   if (padSave)
01334     padSave->cd();
01335 }
01336 
01337 void Roody::AddPeakFind()
01338 {
01339   TClassMenuItem *menuItem = new TClassMenuItem( TClassMenuItem::kPopupUserFunction,
01340                                                  Roody::Class(),
01341                                                  "PeakFind", "PeakFind", this, "" );
01342   TH1C::Class()->GetMenuList()->AddFirst(menuItem);
01343   TH1S::Class()->GetMenuList()->AddFirst(menuItem);
01344   TH1I::Class()->GetMenuList()->AddFirst(menuItem);
01345   TH1F::Class()->GetMenuList()->AddFirst(menuItem);
01346   TH1D::Class()->GetMenuList()->AddFirst(menuItem);
01347   TFrame::Class()->GetMenuList()->AddFirst(menuItem);
01348 }
01349 
01350 void Roody::SetDestination(EDrawDestination dest)
01351 {
01352   if (fDefaultDrawDestination)
01353     fMenuPlot->UnCheckEntry(fDefaultDrawDestination);
01354   
01355   fDefaultDrawDestination = dest;
01356   fMenuPlot->CheckEntry(fDefaultDrawDestination);
01357 }
01358 
01359 std::string Roody::GetZoneSetting(int columns,int rows)
01360 {
01361   std::stringstream str;
01362   str << columns << "x" << rows;
01363   return str.str();
01364 }
01365 
01366 void Roody::SetupZones(int columns,int rows)
01367 {
01368   // set up the pads on the canvas
01369   // if the canvas already has things drawn on it,
01370   // redraw them in the new pads
01371   //
01372 
01373   //printf("SetupZones %d %d\n", columns, rows);
01374 
01375   fZoneColumns = columns;
01376   fZoneRows = rows;
01377 
01378   if (!gPad)
01379   {
01380     MakeNewCanvas(NULL, columns, rows);
01381     return;
01382   }
01383 
01384   TVirtualPad *canvas = gPad->GetCanvas()->cd(); // gPad should now be the parent canvas
01385 
01386 #if 0
01387  FIXME: why are we resetting the user choice?!?
01388   if (fZoneColumns*fZoneRows==1)
01389     SetDestination(D_PLOT_REPLACE);
01390   else
01391     SetDestination(D_PLOT_NEXT);
01392 #endif
01393 
01394   PadObjectVec padvec;
01395 
01396   if (gPadContents[canvas].size() > 0)
01397     {
01398       AddPadToVec(&padvec, canvas);
01399     }
01400   else
01401     {
01402       for (int i=1; i<1000; i++)
01403         {
01404           TVirtualPad *pad = canvas->cd(i);
01405           //printf("canvas %p subpad %d is %p\n", canvas, i, pad);
01406           if (!pad || pad->GetNumber()!=i)
01407             break;
01408 
01409           if (i > columns*rows)
01410             break;
01411 
01412           AddPadToVec(&padvec, pad);
01413         }
01414     }
01415 
01416   gPadContents.erase(canvas);
01417   for (int i=1; i<=fCanvasColumns[canvas]*fCanvasRows[canvas]; i++)
01418     gPadContents.erase(canvas->cd(i));
01419 
01420   canvas->Clear();
01421   canvas->Divide(columns, rows);
01422 
01423   fCanvasColumns[canvas] = columns;
01424   fCanvasRows[canvas] = rows;
01425 
01426   gPadContents.erase(canvas);
01427   for (int i=1; i<=fCanvasColumns[canvas]*fCanvasRows[canvas]; i++)
01428     gPadContents.erase(canvas->cd(i));
01429 
01430   DrawVec(canvas, &padvec);
01431 }
01432 
01433 void Roody::SelectPad( Int_t ev, Int_t x, Int_t y, TObject* obj )
01434 {
01435   // Makes the pad active for all mousebutton clicks
01436   if( ev==kButton1Down || ev==kButton3Down )
01437     gPad->GetCanvas()->HandleInput( kButton2Down, x, y );
01438 }
01439 
01440 void Roody::DrawItem(TGListTreeItem *item, EDrawDestination dest)
01441 {
01442   if (dest == D_PLOT_DEFAULT)
01443     dest = fDefaultDrawDestination;
01444 
01445   if( !gPad || dest==D_PLOT_NEW)
01446     MakeNewCanvas(NULL, fZoneColumns, fZoneRows);
01447 
01448   if (dest == D_PLOT_NEXT )
01449     {
01450       int currentNumber = gPad->GetNumber();
01451       if (currentNumber > 0) // select next pad
01452         {
01453           gPad->GetCanvas()->cd(currentNumber+1);
01454           if (gPad->GetNumber() == currentNumber)
01455             gPad->GetCanvas()->cd(1);
01456         }
01457     }
01458 
01459   DrawItemOnPad(item, gPad, dest != D_PLOT_SAME);
01460 }
01461 
01462 void Roody::DrawItemOnPad(TGListTreeItem *item, TVirtualPad *dest, bool replace)
01463 {
01464   if (replace)
01465     dest->Clear();
01466 
01467   ObjectPath src = gItemSources[item];
01468   TObject* obj = GetObject(src);
01469   if (!obj)
01470     return;
01471 
01472   if (strcmp(gObjectClasses[src].c_str(), obj->ClassName()) != 0)
01473     {
01474       //printf("update object class for %s: %s->%s!\n", obj->GetName(), gObjectClasses[src].c_str(), obj->ClassName());
01475       gObjectClasses[src] = obj->ClassName();
01476       UpdateObjectClass(item, obj);
01477     }
01478 
01479   PadObjectVec padvec;
01480 
01481   if (0)
01482   {
01483   }
01484   else if( obj->InheritsFrom(TTree::Class()) )
01485   {
01486     static_cast<TTree*>(obj)->StartViewer();
01487   }
01488   else if( obj->InheritsFrom(TNtuple::Class()) )
01489   {
01490     static_cast<TNtuple*>(obj)->StartViewer();
01491   }
01492   else if( obj->InheritsFrom(TPad::Class()) )
01493   {
01494     static_cast<TPad*>(obj)->Draw();
01495   }
01496   else if( obj->InheritsFrom(TH1::Class()) )
01497   {
01498     TH1 *clone = (TH1*)obj->Clone();
01499 
01500     if (replace)
01501       {
01502         AddObjectToVec(&padvec, dest, &src, clone, NULL);
01503       }
01504     else
01505       {
01506         int color = 1 + gPadContents[dest].size();
01507         clone->SetLineColor(color);
01508         //MemDebug *d = new MemDebug();
01509         //AddObjectToPad(dest, &src, d, "SAME");
01510         AddObjectToVec(&padvec, dest, &src, clone, "SAME");
01511       }
01512   }
01513   else if( obj->InheritsFrom(TCutG::Class()) )
01514   {
01515     TCutG *c = static_cast<TCutG*>(obj);
01516     c->Draw();
01517   }
01518   else if( obj->InheritsFrom(TGraph::Class()) )
01519   {
01520     TGraph *clone = (TGraph*)obj->Clone();
01521 
01522     if (replace)
01523       AddObjectToVec(&padvec, dest, &src, clone, "AC*");
01524     else
01525       AddObjectToVec(&padvec, dest, &src, clone, "C*");
01526   }
01527   else
01528   {
01529     TObject *clone = obj->Clone();
01530 
01531     if (replace)
01532       AddObjectToVec(&padvec, dest, &src, clone, NULL);
01533     else
01534       AddObjectToVec(&padvec, dest, &src, clone, NULL); // do not know how to overplot unknown objects
01535   }
01536 
01537   DrawVec(dest->GetCanvas(), &padvec);
01538 }
01539 
01540 void Roody::PeakFind()
01541 {
01542   if( fgPeakFindPanel )
01543     fgPeakFindPanel->MapRaised();
01544   else
01545     fgPeakFindPanel = new TPeakFindPanel(gClient->GetRoot(),0,250,220);
01546 }
01547 
01548 void Roody::PopupPlot(int x, int y)
01549 {
01550   if( fPopupMenu )delete fPopupMenu;
01551   //
01552   fPopupMenu = new TGPopupMenu( gClient->GetRoot() );
01553   fPopupMenu->AddEntry( "Plot on new canvas",     C_PLOT_NEW );
01554   fPopupMenu->AddEntry( "Plot on current pad",    C_PLOT_REPLACE );
01555   fPopupMenu->AddEntry( "Overlay on Current pad", C_PLOT_SAME );
01556   fPopupMenu->AddEntry( "Plot on next pad",       C_PLOT_NEXT );
01557   fPopupMenu->AddSeparator();
01558   fPopupMenu->AddEntry( "Add to new group...", C_ADD_TO_GROUP );
01559   for (unsigned int i=0; i<fGroupFolders.size(); i++)
01560     {
01561       std::string s;
01562       s += "Add to group ";
01563       s += fGroupFolders[i]->GetText();
01564       fPopupMenu->AddEntry( s.c_str(), C_ADD_TO_GROUP + 1000 * (i+1));
01565     }
01566   fPopupMenu->AddSeparator();
01567   fPopupMenu->AddEntry( "Reset", C_RESET_OBJECT );
01568   fPopupMenu->PlaceMenu( x, y, false, true );
01569   fXSave = x;
01570   fYSave = y;
01571   fPopupMenu->Associate( this );
01572 }
01573 
01574 void Roody::PopupPlotFolder(int x, int y)
01575 {
01576   if( fPopupMenu )delete fPopupMenu;
01577   //
01578   fPopupMenu = new TGPopupMenu( gClient->GetRoot() );
01579   fPopupMenu->AddEntry("Plot on new canvas", C_PLOT_FOLDER);
01580   fPopupMenu->AddSeparator();
01581   fPopupMenu->AddEntry("Reset", C_RESET_FOLDER);
01582   fPopupMenu->PlaceMenu( x, y, false, true );
01583   fXSave = x;
01584   fYSave = y;
01585   fPopupMenu->Associate( this );
01586 }
01587 
01588 void Roody::PopupPlotSource(int x, int y)
01589 {
01590   if( fPopupMenu )delete fPopupMenu;
01591   //
01592   fPopupMenu = new TGPopupMenu( gClient->GetRoot() );
01593   fPopupMenu->AddEntry("Plot all on new canvas", C_PLOT_FOLDER);
01594   fPopupMenu->AddSeparator();
01595   fPopupMenu->AddEntry("Reset all", C_RESET_FOLDER);
01596   fPopupMenu->AddSeparator();
01597   fPopupMenu->AddEntry("Reopen",    C_REOPEN_SOURCE);
01598   fPopupMenu->AddEntry("Close",     C_CLOSE_SOURCE);
01599   fPopupMenu->PlaceMenu( x, y, false, true);
01600   fXSave = x;
01601   fYSave = y;
01602   fPopupMenu->Associate(this);
01603 }
01604 
01605 void Roody::PopupTopGroup( int x, int y )
01606 {
01607   if( fPopupMenu )delete fPopupMenu;
01608   fPopupMenu = new TGPopupMenu( gClient->GetRoot() );
01609   fPopupMenu->AddEntry( "Make new group", C_NEW_GROUP );
01610   fPopupMenu->PlaceMenu( x, y, false, true );
01611   fPopupMenu->Associate( this );
01612 }
01613 
01614 void Roody::PopupGroup( int x, int y )
01615 {
01616   if( fPopupMenu )delete fPopupMenu;
01617   fPopupMenu = new TGPopupMenu( gClient->GetRoot() );
01618   fPopupMenu->AddEntry( "Draw group on new canvas", C_DRAW_GROUP );
01619   fPopupMenu->AddEntry( "Reset group", C_RESET_GROUP );
01620   fPopupMenu->AddEntry( "Delete group", C_DELETE_GROUP );
01621   fPopupMenu->PlaceMenu( x, y, false, true );
01622   fPopupMenu->Associate( this );
01623 }
01624 
01625 TGListTreeItem* Roody::PopupNewGroup(int x, int y)
01626 {
01627   TGListTreeItem* newgroup = NULL;
01628   TObjString objString;
01629   new TGTextDialog(gClient->GetRoot(), this, x, y, "Create new group: ", "", &objString);
01630 
01631   const char* name = objString.GetString();
01632 
01633   if (name && strlen(name) > 0 && strcmp(name,"-1") != 0)
01634     newgroup = MakeNewGroup(name);
01635 
01636   return newgroup;
01637 }
01638 
01639 TGListTreeItem* Roody::MakeNewGroup(const char *name)
01640 {
01641   TGListTreeItem* item = fContents->FindChildByName(fTreeItemGroups, name);
01642   if (!item)
01643     {
01644       item = fContents->AddItem(fTreeItemGroups, name);
01645       gItemActions[item] = A_GROUP;
01646       fGroupFolders.push_back(item); // fGroupFolders is a vector of TGListTreeItem*
01647       fContents->OpenItem(fTreeItemGroups);
01648       fContents->Resize();
01649       Layout();
01650     }
01651   return item;
01652 }
01653 
01654 void Roody::AddToGroup(TGListTreeItem* group, ItemVec* items)
01655 {
01656   if (group == NULL)
01657     group = PopupNewGroup(100, 100);
01658 
01659   if (group)
01660     for (unsigned int i=0; i<items->size(); i++)
01661       AddHistogramToGroup(group, (*items)[i]->GetText(), (*items)[i]);
01662 }
01663 
01664 void Roody::DeleteGroup(TGListTreeItem* groupItem)
01665 {
01666   ItemVec old = fGroupFolders;
01667   fGroupFolders.clear(); // std::vector does not have an "erase" method
01668   for (unsigned int i=0; i<old.size(); i++)
01669     {
01670       if (old[i] != groupItem)
01671         fGroupFolders.push_back(old[i]);
01672     }
01673       
01674   fContents->MDeleteItem(groupItem);
01675   fContents->Resize();
01676 }
01677 
01678 TCanvas* Roody::MakeNewCanvas(const char* title, int columns, int rows, int topx, int topy, int width, int height)
01679 {
01680   std::string name;
01681 
01682   //printf("MakeNewCanvas divide %d %d\n", columns, rows);
01683 
01684   if (title == NULL)
01685     {
01686       std::stringstream ss;
01687       ss << "canvas" << fCanvasCount++;
01688       name = ss.str();
01689     }
01690   else
01691     {
01692       name = title;
01693     }
01694 
01695   TCanvas* canvas;
01696   if (width*height==0)
01697     canvas = new TCanvas(name.c_str(), name.c_str());
01698   else
01699     canvas = new TCanvas(name.c_str(), name.c_str(), topx, topy, width, height);
01700 
01701   canvas->cd();
01702 
01703   if (columns*rows==1)
01704     {
01705       SetDestination(D_PLOT_REPLACE);
01706     }
01707   else
01708     {
01709       SetDestination(D_PLOT_NEXT);
01710       canvas->Divide(columns, rows );
01711       canvas->cd(columns*rows);
01712     }
01713 
01714   fCanvasColumns[canvas] = columns;
01715   fCanvasRows[canvas] = rows;
01716 
01717   canvas->Modified();
01718   canvas->Update();
01719 
01720   canvas->Connect( "ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", "Roody",
01721                            this, "SelectPad(Int_t,Int_t,Int_t,TObject*)" );
01722   return canvas;
01723 }
01724 
01725 void Roody::DrawItemsOnNewCanvas(const char* title, const ItemVec* items)
01726 {
01727   int nItems = items->size();
01728   assert(nItems > 0);
01729 
01730   int columns = (int)sqrt(nItems);
01731   int rows = nItems/columns;
01732 
01733   while (rows*columns < nItems)
01734     rows++;
01735 
01736   TCanvas *c = MakeNewCanvas(title, columns, rows);
01737 
01738   for (int i=0; i<nItems; i++)
01739     DrawItemOnPad((*items)[i], c->cd(i+1), true);
01740 
01741   c->Modified();
01742   c->Update();
01743 }
01744 
01745 void Roody::DrawGroup(TGListTreeItem* groupItem)
01746 {
01747   ItemVec items;
01748 
01749   GetFolderItems(&items, groupItem);
01750 
01751   if (items.size() < 1)
01752     {
01753       new TGMsgBox( gClient->GetRoot(), this, "Error", "group is empty",
01754                     kMBIconExclamation, 0, NULL );
01755       return;
01756     }
01757 
01758   std::string title( "Group canvas: " );
01759   title += groupItem->GetText();
01760 
01761   DrawItemsOnNewCanvas(title.c_str(), &items);
01762 }
01763 
01764 void Roody::SetRefreshRate(int newrefresh)
01765 {
01766   //printf("SetRefreshRate %d %d\n", newrefresh, fUpdatePause);
01767 
01768   fMenuRefresh->UnCheckEntry(M_REFRESH_OFF);
01769   fMenuRefresh->UnCheckEntry(M_REFRESH_NOW);
01770   fMenuRefresh->UnCheckEntry(M_REFRESH_1SEC);
01771   fMenuRefresh->UnCheckEntry(M_REFRESH_3SEC);
01772   fMenuRefresh->UnCheckEntry(M_REFRESH_5SEC);
01773   fMenuRefresh->UnCheckEntry(M_REFRESH_10SEC);
01774 
01775   fUpdateTimerSec = newrefresh;
01776 
01777   switch( fUpdateTimerSec )
01778     {
01779     case 0:  fMenuRefresh->CheckEntry( M_REFRESH_OFF );  break;
01780     case 1:  fMenuRefresh->CheckEntry( M_REFRESH_1SEC ); break;
01781     case 3:  fMenuRefresh->CheckEntry( M_REFRESH_3SEC ); break;
01782     case 5:  fMenuRefresh->CheckEntry( M_REFRESH_5SEC ); break;
01783     case 10: fMenuRefresh->CheckEntry( M_REFRESH_10SEC ); break;
01784     }
01785 
01786   //fRefreshButton->SetEnabled(kTRUE);
01787 
01788   if( fUpdateTimerSec > 0 )
01789     {
01790       if (fUpdatePause)
01791         {
01792           std::stringstream str;
01793           str << "  Resume Refresh (" << fUpdateTimerSec << ")  ";
01794           fRefreshButton->SetText( str.str().c_str() );
01795           fRefreshButton->SetToolTipText( "click to resume refresh of online histograms", 250 );
01796         }
01797       else
01798         {
01799           std::stringstream str;
01800           str << "  Pause Refresh (" << fUpdateTimerSec << ")  ";
01801           fRefreshButton->SetText( str.str().c_str() );
01802           fRefreshButton->SetToolTipText( "click to pause refresh of online histograms", 250 );
01803         }
01804     }
01805   else
01806     {
01807       fRefreshButton->SetText( "     Refresh NOW      " );
01808       fRefreshButton->SetToolTipText( "click to refresh online histograms once right now", 250 );
01809     }
01810 
01811   StartUpdateTimer();
01812 }
01813 
01814 void Roody::UncheckAllZones()
01815 {
01816   fMenuZones->UnCheckEntry(M_ZONES_11);
01817   fMenuZones->UnCheckEntry(M_ZONES_12);
01818   fMenuZones->UnCheckEntry(M_ZONES_13);
01819   fMenuZones->UnCheckEntry(M_ZONES_21);
01820   fMenuZones->UnCheckEntry(M_ZONES_22);
01821   fMenuZones->UnCheckEntry(M_ZONES_33);
01822   fMenuZones->UnCheckEntry(M_ZONES_44);
01823   fMenuZones->UnCheckEntry(M_ZONES_USER);
01824 }
01825 
01826 Bool_t Roody::ProcessMessage( Long_t msg, Long_t parm1, Long_t parm2 )
01827 {
01828   // ProcessMessage overrides the virtual function in TGCompositeFrame
01829   // (which is the base class for TGMainFrame)
01830   //
01831   // to see the predefined message types look at 
01832   // $ROOTSYS/include/WidgetMessageTypes.h
01833   //
01834 
01835   //printf("ProcessMessage %d (%d, %d), parm1: %d, parm2: %d\n", msg, GET_MSG(msg), GET_SUBMSG(msg), parm1, parm2);
01836 
01837   switch (GET_MSG(msg))
01838   {
01839     case kC_LISTTREE: // an event in TreeView
01840     {
01841       switch (GET_SUBMSG(msg))
01842       {
01843         default:
01844           break;
01845         case kCT_ITEMCLICK:  // single mouse click
01846         {
01847           switch (parm1)
01848           {
01849             default:
01850               break;
01851 
01852             case kButton1: // left mouse button click
01853               break;
01854 
01855             case kButton2:
01856               break;
01857 
01858             case kButton3: // right mouse button click
01859             {
01860               // see http://root.cern.ch/root/htmldoc/TGListTree.html#TGListTree:description
01861               int x = parm2&0xFFFF;
01862               int y = (parm2&0xFFFF0000)>>16;
01863               //
01864 
01865               ItemVec items;
01866               fContents->GetSelectedItems(items);
01867 
01868               for (unsigned int i=0; i<items.size(); i++)
01869                 {
01870                   if (items[i] == fTreeItemGroups)
01871                     {
01872                       PopupTopGroup( x, y );
01873                       return true;
01874                     }
01875 
01876                   Action act = gItemActions[items[i]];
01877                   //printf("Clicked on selected %s, action %d, parm1: %d\n", items[i]->GetText(), act, parm1);
01878 
01879                   switch (act)
01880                     {
01881                     default:
01882                       break;
01883 
01884                     case A_ITEM:
01885                       PopupPlot(x, y);
01886                       return true;
01887 
01888                     case A_FOLDER:
01889                       PopupPlotFolder(x, y);
01890                       return true;
01891 
01892                     case A_SOURCE:
01893                       PopupPlotSource(x, y);
01894                       return true;
01895 
01896                     case A_GROUP:
01897                       PopupGroup(x, y);
01898                       return true;
01899                     }
01900                 }
01901               break;
01902             }
01903           }
01904           break;
01905         }
01906         case kCT_ITEMDBLCLICK:  // double mouse click
01907         {
01908           TGListTreeItem* selected = fContents->GetSelected();
01909           if (gItemActions[selected] == A_ITEM)
01910             {
01911               ItemVec items;
01912               items.push_back(selected);
01913               PlotItems(&items, D_PLOT_DEFAULT);
01914               return true;
01915             }
01916           break;
01917         }
01918       }
01919       break;
01920     }
01921     case kC_COMMAND:  // 
01922     {
01923       switch (GET_SUBMSG(msg))
01924       {
01925         case kCM_BUTTON:  // a button was pressed
01926         {
01927           switch (parm1)
01928           {
01929           case M_REOPEN_BUTTON:
01930             printf("Reopen all data sources!\n");
01931             gObjectCache.clear();
01932             for (DataSourcesMap::iterator it=gDataSources.begin(); it!=gDataSources.end(); it++) {
01933               it->second->Reopen();
01934             }
01935             break;
01936           case M_REFRESH_BUTTON:
01937             if (fUpdateTimerSec == 0)
01938               {
01939                 fUpdatePause = false;
01940                 RefreshAll();
01941               }
01942             else if (fUpdatePause)
01943               {
01944                 fUpdatePause = false;
01945                 RefreshAll();
01946                 SetRefreshRate(fUpdateTimerSec);
01947               }
01948             else
01949               {
01950                 fUpdatePause = true;
01951                 SetRefreshRate(fUpdateTimerSec);
01952                 //StartUpdateTimer();
01953               }
01954             break;
01955           default:
01956             break;
01957           }
01958           break;
01959         }
01960         case kCM_MENUSELECT:
01961         {
01962           break;
01963         }
01964         case kCM_MENU: // menu item event
01965         {
01966           switch (parm1)
01967           {
01968             case M_NEW_CANVAS:
01969               MakeNewCanvas(NULL, fZoneColumns, fZoneRows);
01970               break;
01971 
01972             case M_REDRAW_CANVAS:
01973               RedrawCanvas();
01974               break;
01975 
01976             case M_FILE_OPEN:
01977               fStatusBar->SetText("Opening ...");
01978               OpenFileDialog();
01979               fStatusBar->SetText(" ");
01980               break;
01981 
01982             case M_FILE_ONLINE:
01983               ConnectServer(NULL);
01984               break;
01985 
01986             case M_FILE_NetDirectory:
01987               ConnectNetDirectory(NULL);
01988               break;
01989 
01990             case M_FILE_SAVE_DEFAULT:
01991               SaveFile("default.xml");
01992               break;
01993 
01994             case M_FILE_SAVE:
01995               OpenSaveDialog();
01996               break;
01997 
01998             case M_FILE_RESTORE:
01999               OpenRestoreDialog();
02000               break;
02001 
02002             case M_FILE_EXIT:
02003               CloseWindow();
02004               break;
02005 
02006             case M_HELP_ABOUT:
02007               new TGMsgBox( gClient->GetRoot(), this, "About Roody",
02008               "Roody is an application based solely on CERN-ROOT for histogram display.\nIt is meant for display of .root files and .hbook files.\nRunning this application in conjunction with either the Midas or ROME analyzer\nwill allow you to visualize online data retrieved through a socket port.\n\nThis is Roody svn revision $Id$", kMBIconQuestion, kMBOk, NULL );
02009               break;
02010 
02011             case M_HELP_CONTENTS:
02012             {
02013               fStatusBar->SetText("HELP CONTENTS -- Not yet available");
02014               std::cout << "HELP CONTENTS -- Not yet available" << std::endl;
02015               break;
02016             }
02017             case M_REFRESH_OFF:
02018             {
02019               SetRefreshRate(0); 
02020               break;
02021             }
02022             case M_REFRESH_NOW:
02023             {
02024               RefreshAll();
02025               break;
02026             }
02027             case M_REFRESH_1SEC:
02028             {
02029               SetRefreshRate(1); 
02030               break;
02031             }
02032             case M_REFRESH_3SEC:
02033             {
02034               SetRefreshRate(3); 
02035               break;
02036             }
02037             case M_REFRESH_5SEC:
02038             {
02039               SetRefreshRate(5); 
02040               break;
02041             }
02042             case M_REFRESH_10SEC:
02043             {
02044               SetRefreshRate(10); 
02045               break;
02046             }
02047             case M_REFRESH_DIALOG:
02048             {
02049               OpenRefreshDialog();
02050               break;
02051             }
02052             case M_ZONES_11:
02053             {
02054               UncheckAllZones();
02055               fMenuZones->CheckEntry(M_ZONES_11);
02056               SetupZones( 1, 1 );
02057               break;
02058             }
02059             case M_ZONES_12:
02060             {
02061               UncheckAllZones();
02062               fMenuZones->CheckEntry(M_ZONES_12);
02063               SetupZones( 1, 2 );
02064               break;
02065             }
02066             case M_ZONES_13:
02067             {
02068               UncheckAllZones();
02069               fMenuZones->CheckEntry(M_ZONES_13);
02070               SetupZones( 1, 3 );
02071               break;
02072             }
02073             case M_ZONES_21:
02074             {
02075               UncheckAllZones();
02076               fMenuZones->CheckEntry(M_ZONES_21);
02077               SetupZones( 2, 1 );
02078               break;
02079             }
02080             case M_ZONES_22:
02081             {
02082               UncheckAllZones();
02083               fMenuZones->CheckEntry(M_ZONES_22);
02084               SetupZones( 2, 2 );
02085               break;
02086             }
02087             case M_ZONES_33:
02088             {
02089               UncheckAllZones();
02090               fMenuZones->CheckEntry(M_ZONES_33);
02091               SetupZones( 3, 3 );
02092               break;
02093             }
02094             case M_ZONES_44:
02095             {
02096               UncheckAllZones();
02097               fMenuZones->CheckEntry(M_ZONES_44);
02098               SetupZones( 4, 4 );
02099               break;
02100             }
02101             case M_ZONES_USER:
02102             {
02103               std::string name = fMenuZones->GetEntry(M_ZONES_USER)->GetName();
02104               if (name.find("user") == 0)
02105                 OpenZoneDialog();
02106               else
02107                 {
02108                   std::size_t x = name.find("x");
02109                   int cols = atoi(name.substr(0,x).c_str());
02110                   int rows = atoi(name.substr(x+1,name.size()-x-1).c_str());
02111                   SetupZones( cols, rows );
02112                 }
02113               SetupZonesMenu();
02114               break;
02115             }
02116             case M_ZONES_DIALOG:
02117             {
02118               OpenZoneDialog();
02119               SetupZonesMenu();
02120               break;
02121             }
02122             case M_PLOT_NEW:
02123               SetDestination(D_PLOT_NEW);
02124               break;
02125             case M_PLOT_SAME:
02126               SetDestination(D_PLOT_SAME);
02127               break;
02128             case M_PLOT_REPLACE:
02129               SetDestination(D_PLOT_REPLACE);
02130               break;
02131             case M_PLOT_NEXT:
02132               SetDestination(D_PLOT_NEXT);
02133               break;
02134 
02135             case C_PLOT_FOLDER:
02136               {
02137                 ItemVec items;
02138                 GetFolderItems(&items, fContents->GetSelected());
02139                 DrawItemsOnNewCanvas(NULL, &items);
02140                 break;
02141               }
02142             case C_PLOT_NEW:
02143               {
02144                 ItemVec items;
02145                 fContents->GetSelectedItems(items);
02146                 DrawItemsOnNewCanvas(NULL, &items);
02147                 break;
02148               }
02149             case C_PLOT_REPLACE:
02150               {
02151                 ItemVec items;
02152                 fContents->GetSelectedItems(items);
02153                 PlotItems(&items, D_PLOT_REPLACE);
02154                 break;
02155               }
02156             case C_PLOT_SAME:
02157               {
02158                 ItemVec items;
02159                 fContents->GetSelectedItems(items);
02160                 PlotItems(&items, D_PLOT_SAME);
02161                 break;
02162               }
02163             case C_PLOT_NEXT:
02164               {
02165                 ItemVec items;
02166                 fContents->GetSelectedItems(items);
02167                 PlotItems(&items, D_PLOT_NEXT);
02168                 break;
02169               }
02170             case C_CLOSE_SOURCE:
02171               CloseSource(fContents->GetSelected());
02172               break;
02173             case C_REOPEN_SOURCE:
02174               ReopenSource(fContents->GetSelected());
02175               break;
02176 
02177             case C_NEW_GROUP:
02178               PopupNewGroup(100, 100);
02179               break;
02180             case C_DRAW_GROUP:
02181               DrawGroup(fContents->GetSelected());
02182               break;
02183             case C_DELETE_GROUP:
02184               DeleteGroup(fContents->GetSelected());
02185               break;
02186             case C_ADD_TO_GROUP:
02187               {
02188                 ItemVec items;
02189                 fContents->GetSelectedItems(items);
02190                 AddToGroup(NULL, &items);
02191                 break;
02192               }
02193             case C_RESET_GROUP:
02194               {
02195                 ItemVec items;
02196                 GetFolderItems(&items, fContents->GetSelected());
02197                 ResetMultiple(&items);
02198                 break;
02199               }
02200             case C_RESET_OBJECT:
02201               {
02202                 ItemVec items;
02203                 fContents->GetSelectedItems(items);
02204                 ResetMultiple(&items);
02205                 break;
02206               }
02207             case C_RESET_FOLDER:
02208               {
02209                 ItemVec items;
02210                 GetFolderItems(&items, fContents->GetSelected());
02211                 ResetMultiple(&items);
02212                 break;
02213               }
02214             case M_RESET_ALL:
02215               ResetAll();
02216               break;
02217 
02218             default:
02219               if (parm1%1000 == C_ADD_TO_GROUP)
02220                 {
02221                   unsigned int igroup = (parm1-C_ADD_TO_GROUP)/1000 - 1;
02222 
02223                   if (igroup>=0 && igroup<fGroupFolders.size())
02224                     {
02225                       ItemVec items;
02226                       fContents->GetSelectedItems(items);
02227                       AddToGroup(fGroupFolders[igroup], &items);
02228                       return true;
02229                     }
02230                 }
02231 
02232               new TGMsgBox( gClient->GetRoot(), this, "Error", "Unimplemented menu command", kMBIconExclamation, 0, NULL );
02233               break;
02234           }
02235           break;
02236         }
02237         default:
02238           break;
02239       }
02240       break;
02241     }
02242   }
02243   return kTRUE;
02244 }
02245 
02246 void Roody::AddHistogramToGroup(TGListTreeItem *groupItem, const char* name, TGListTreeItem *origItem )
02247 {
02248   TGListTreeItem *newitem = fContents->AddItem(groupItem, name);
02249   gItemActions[newitem] = A_ITEM;
02250   fContents->OpenItem(groupItem);
02251   fContents->Resize();
02252   Layout();
02253   gItemSources[newitem] = gItemSources[origItem];
02254 }
02255 
02256 void Roody::ReopenSource(TGListTreeItem* item)
02257 {
02258   const char* name = item->GetText();
02259   DataSourceBase *d = gDataSources[name];
02260   if (d)
02261     {
02262       std::string str;
02263       str += "Reopening ";
02264       str += name;
02265       fStatusBar->SetText(str.c_str());
02266       gObjectCache.clear();
02267       d->Reopen();
02268       AddDataSource(d, fContents, item->GetParent(), true);
02269       str  = "Connected to ";
02270       str += name;
02271       fStatusBar->SetText(str.c_str());
02272     }
02273 }
02274 
02275 void Roody::CloseSource(TGListTreeItem* item)
02276 {
02277   const char* name = item->GetText();
02278   DataSourceBase *d = gDataSources[name];
02279   if (d)
02280     {
02281       std::string str;
02282       str += "Closing ";
02283       str += name;
02284       fStatusBar->SetText(str.c_str());
02285       d->Close();
02286       delete d;
02287       gDataSources[name] = NULL;
02288     }
02289 
02290   fContents->MDeleteItem(item);
02291   fContents->Resize();
02292   Layout();
02293 }
02294 
02295 void Roody::GetFolderItems(ItemVec* items, TGListTreeItem *folder)
02296 {
02297   // fill "items" with all items in folder "folder", including subfolders
02298 
02299   for (TGListTreeItem *item = folder->GetFirstChild(); item != NULL; item = item->GetNextSibling())
02300     {
02301       if (gItemActions[item] == A_ITEM) // is it a sub-folder?
02302         items->push_back(item);
02303       else
02304         GetFolderItems(items, item);
02305     }
02306 }
02307 
02308 void Roody::ResetAll()
02309 {
02310   for (unsigned int i=0; i<fOnlineFiles.size(); i++)
02311     {
02312       DataSourceBase* d = gDataSources[fOnlineFiles[i]];
02313       if (d)
02314         d->ResetAll();
02315     }
02316 
02317   for (unsigned int i=0; i<fRootFiles.size(); i++)
02318     {
02319       DataSourceBase* d = gDataSources[fRootFiles[i]];
02320       if (d)
02321         d->ResetAll();
02322     }
02323 
02324   RefreshAll();
02325 }
02326 
02327 void Roody::ResetMultiple(const ItemVec* items)
02328 {
02329   for (unsigned int i=0; i<items->size(); i++)
02330     ResetItem((*items)[i]);
02331 }
02332 
02333 void Roody::ResetItem(TGListTreeItem* item)
02334 {
02335   ObjectPath src = gItemSources[item];
02336   if (src.size() < 1)
02337     return;
02338 
02339   DataSourceBase* d = gDataSources[src.front()];
02340   if (d)
02341     d->ResetObject(src);
02342 }
02343 
02344 void Roody::PlotItems(const ItemVec* items, EDrawDestination dest)
02345 {
02346   for (unsigned int i=0; i<items->size(); i++)
02347     DrawItem((*items)[i], dest);
02348   Layout();
02349 }
02350 
02351 void Roody::CloseWindow()
02352 {
02353   fUpdateTimer->Stop();
02354   TQObject::Disconnect(fUpdateTimer);
02355   TQObject::Disconnect(this);
02356   gApplication->Terminate(0);
02357 }
02358 
02359 bool Roody::OpenFile(const char* filename)
02360 {
02361   if (strstr(filename,".root"))
02362     return OpenRootFile(filename);
02363 #ifdef HAVE_HBOOK
02364   else
02365     return OpenHbookFile(filename);
02366 #endif
02367   return false;
02368 }
02369 
02370 
02371 void Roody::OpenFileDialog()
02372 {
02373   TGFileInfo fileinfo;
02374   fileinfo.fFilename = 0;
02375 #ifdef HAVE_HBOOK
02376   char const *fileTypes[] = {"Root files","*.root","Hbook files","*.hbook","Any","*",0,0};
02377 #else
02378   char const *fileTypes[] = {"Root files","*.root","Any","*",0,0};
02379 #endif
02380   fileinfo.fFileTypes = fileTypes;
02381 
02382   new TGFileDialog( fClient->GetRoot(), this, kFDOpen, &fileinfo );
02383 
02384   if (fileinfo.fFilename)
02385     OpenFile(fileinfo.fFilename);
02386   else
02387     fStatusBar->SetText("NO FILE SELECTED");
02388 }
02389 
02390 void Roody::AddDataSource(DataSourceBase* d, MTGListTree* tree, TGListTreeItem* branch, bool reopen)
02391 {
02392   gDataSources[d->GetName()] = d;
02393   std::string s = d->toString();
02394   //printf("Data source: [%s]\n", s.c_str());
02395 
02396   ObjectList list = d->GetList();
02397 
02398   bool first = true;
02399   int n = list.size();
02400   for (int i=0; i<n; i++)
02401     {
02402       ObjectPath p = list[i];
02403       int np = p.size();
02404       TGListTreeItem *xitem = branch;
02405       for (int j=0; j<np-1; j++)
02406         {
02407           TGListTreeItem *item = tree->FindChildByName(xitem, p[j].c_str());
02408 
02409           if (!item)
02410             {
02411               item = tree->AddItem(xitem,p[j].c_str());
02412               if (j==0)
02413                 gItemActions[item] = A_SOURCE;
02414               else
02415                 gItemActions[item] = A_FOLDER;
02416             }
02417 
02418           if (first && !reopen)
02419             tree->OpenItem(xitem);
02420 
02421           xitem = item;
02422         }
02423 
02424       if (first && !reopen)
02425         tree->OpenItem(xitem);
02426 
02427       first = false;
02428 
02429       std::string name = p.back();
02430       TGListTreeItem* iii = tree->FindChildByName(xitem, name.c_str());
02431       //printf("Looking for %s, %p\n", name.c_str(), iii);
02432       if (!iii)
02433         iii = tree->AddItem(xitem, name.c_str(), gClient->GetPicture("diamond.xpm"), gClient->GetPicture("diamond.xpm"));
02434 
02435       gItemActions[iii]   = A_ITEM;
02436       gItemSources[iii]   = p;
02437     }
02438 
02439   tree->Resize();
02440   Layout();
02441 }
02442 
02443 bool Roody::OpenRootFile( char const *filename )
02444 {
02445   if( fContents->FindChildByName(fTreeItemFiles,filename) )
02446   {
02447 #if 0
02448     std::string s("Error in loading file: \"");
02449     s += std::string(filename) + "\" is already loaded";
02450     new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
02451 #endif
02452     return true;
02453   }
02454 
02455 #if 0
02456   TFile *f = new TFile( filename, "READ" );
02457   if( !f )
02458   {
02459     new TGMsgBox( gClient->GetRoot(), this, "Error", "Error in loading file: could not allocate TFile object",
02460                   kMBIconExclamation, 0, NULL );
02461     return true;
02462   }
02463   if( f->IsZombie() )
02464   {
02465     std::string s("Error in loading file: \"");
02466     s += std::string(filename) + "\" is not a root file or the file doesn't exist";
02467     new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
02468     f->Close();
02469     delete f;
02470     return true;
02471   }
02472 
02473   DataSourceTDirectory* d = new DataSourceTDirectory(f);
02474 #endif
02475   DataSourceTFile* d = new DataSourceTFile(filename);
02476 
02477   AddDataSource(d, fContents, fTreeItemFiles);
02478 
02479   return false;
02480 }
02481 
02482 bool Roody::OpenXmlServer(char const *dest)
02483 {
02484   if( fContents->FindChildByName(fTreeItemOnline, dest))
02485     {
02486 #if 0
02487       std::string s("Error in loading file: \"");
02488       s += std::string(dest) + "\" is already loaded";
02489       new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
02490 #endif
02491       return true;
02492     }
02493 
02494   fOnlineFiles.push_back(dest);
02495 
02496   DataSourceXmlServer* d = new DataSourceXmlServer(dest);
02497 
02498   AddDataSource(d, fContents, fTreeItemOnline);
02499 
02500   return false;
02501 }
02502 
02503 bool Roody::OpenNetDirectory(char const *dest)
02504 {
02505 #ifdef HAVE_NETDIRECTORY
02506   if( fContents->FindChildByName(fTreeItemOnline, dest))
02507     {
02508 #if 0
02509       std::string s("Error in loading file: \"");
02510       s += std::string(dest) + "\" is already loaded";
02511       new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
02512 #endif
02513       return true;
02514     }
02515 
02516   TNetDirectory *f = new TNetDirectory(dest);
02517 
02518   if( f->IsZombie() )
02519     {
02520       std::string s("Error in loading file: \"");
02521       s += std::string(dest) + "\" is not a root file or the file doesn't exist";
02522       new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
02523       f->Close();
02524       delete f;
02525       return true;
02526     }
02527 
02528   fRootFiles.push_back(dest);
02529 
02530   DataSourceTDirectory* d = new DataSourceNetDirectory(f);
02531 
02532   AddDataSource(d, fContents, fTreeItemOnline);
02533 
02534   return false;
02535 #else
02536   std::string s("No support for TNetDirectory!");
02537   new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
02538   return true;
02539 #endif
02540 }
02541 
02542 #ifdef HAVE_HBOOK
02543 bool Roody::OpenHbookFile( char const *filename )
02544 {
02545   THbookFile *f = new THbookFile( filename );
02546   if( !f )
02547   {
02548     std::string s("Error in loading file: \"");
02549     s += std::string(filename) + "\" could not create THbookFile object";
02550     new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
02551     return true;
02552   }
02553   if( !f->IsOpen() )
02554   {
02555     std::string s("Error in loading file: \"");
02556     s += std::string(filename) + "\" is not an hbook file or the file doesn't exist";
02557     new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
02558     delete f;
02559     return true;
02560   }
02561   if( fContents->FindChildByName(fTreeItemFiles,filename) )
02562   {
02563     std::string s("Error in loading file: \"");
02564     s += std::string(filename) + "\" is already loaded";
02565     new TGMsgBox( gClient->GetRoot(), this, "Error", s.c_str(), kMBIconExclamation, 0, NULL );
02566     delete f;
02567     return true;
02568   }
02569 
02570 #if 0
02571   fContents->AddItem( fTreeItemFiles,
02572                                 filename,(void*)f,
02573                                 gClient->GetPicture("rootdb_t.xpm"),
02574                                 gClient->GetPicture("rootdb_t.xpm") );
02575   fTreeItemCurrent = fContents->FindChildByName( fTreeItemFiles, filename );
02576   fContents->OpenItem( fTreeItemFiles );
02577   DisplayHBook(f, fTreeItemCurrent );
02578   fContents->OpenItem( fTreeItemCurrent );
02579   fContents->Resize();
02580   Layout();
02581 #endif
02582 
02583 #if 0
02584   DataSourceTDirectory* d = new DataSourceTHbookFile(f);
02585 
02586   AddDataSource(d, fContents, fTreeItemFiles);
02587 #endif
02588 
02589   return false;
02590 }
02591 
02592 #if 0
02593 class MyTHbookKey: public THbookKey
02594 {
02595 public:
02596   int GetID() const { return fID; };
02597 };
02598 
02599 void Roody::DisplayHBook( THbookFile *file, TGListTreeItem *item )
02600 {
02601   TIter next( file->GetListOfKeys() );
02602   MyTHbookKey *key;
02603   while( (key=static_cast<MyTHbookKey*>(next())) )
02604   {
02605     TObject *obj = file->Get(key->GetID());
02606     //if (obj)
02607     //  DisplayObject( obj, item, "" );
02608     Layout();
02609   }
02610   fFileOnlineCanvas->Layout();
02611 }
02612 #endif
02613 #endif
02614 
02615 std::string Roody::GetRunNumber( char const *filename )
02616 {
02617   int end = strlen( filename );
02618   while( --end >= 0 )
02619   {
02620     if( filename[end] <= '9' && filename[end] >= '0' )break;
02621   }
02622   int begin = end;
02623   while( --begin >= 0 )
02624   {
02625     if( filename[begin] < '0' || filename[begin] > '9' )break;
02626   }
02627   ++begin;
02628   int len = end-begin+1;
02629   return std::string(TString( filename+begin,len).Data());
02630 }
02631 
02632 void Roody::UpdateObjectClass(TGListTreeItem *item, TObject* obj)
02633 {
02634   if (!item)
02635     return;
02636 
02637   if (!obj)
02638     return;
02639 
02640   std::string className = obj->ClassName();
02641   std::string name      = obj->GetName();
02642   std::string title     = obj->GetTitle();
02643   std::string itemDescription = name;
02644   //std::string runNumber = rn;
02645   //std::string file = fCurrentFile->GetName();
02646 
02647   if( className.find("TH1") != className.npos )
02648   {
02649 #if 0
02650     if( title.find("Run#") == title.npos &&                   // Run# not in title and
02651         runNumber.find_first_not_of(" ") != runNumber.npos )  // runNumber not blank
02652     {
02653       std::string s( title );
02654       s += "    Run# ";
02655       s += runNumber;
02656       static_cast<TH1*>(obj)->SetTitle( s.c_str() );
02657     }
02658 #endif
02659     if( name != title )
02660     {
02661       itemDescription += " ";
02662       itemDescription += title;
02663     }
02664     //item->Rename(itemDescription.c_str());
02665     item->SetPictures(gClient->GetPicture("h1_t.xpm"), gClient->GetPicture("h1_t.xpm"));
02666   }
02667 #if 0
02668   else if( className.find("TH2") != className.npos )
02669   {
02670     if( title.find("Run#") == title.npos &&                   // Run# not in title and
02671         runNumber.find_first_not_of(" ") != runNumber.npos )  // runNumber not blank
02672     {
02673       std::string s( title );
02674       s += "    Run# ";
02675       s += runNumber;
02676       static_cast<TH2*>(obj)->SetTitle( s.c_str() );
02677     }
02678     if( name != title )
02679     {
02680       itemDescription += " ";
02681       itemDescription += title;
02682     }
02683     fContents->AddItem( item, itemDescription.c_str(),
02684                                   (void*)obj,
02685                                   gClient->GetPicture("h2_t.xpm"),
02686                                   gClient->GetPicture("h2_t.xpm") );
02687   }
02688   else if( className.find("TH3") != className.npos )
02689   {
02690     if( title.find("Run#") == title.npos &&                   // Run# not in title and
02691         runNumber.find_first_not_of(" ") != runNumber.npos )  // runNumber not blank
02692     {
02693       std::string s( title );
02694       s += "    Run# ";
02695       s += runNumber;
02696       static_cast<TH3*>(obj)->SetTitle( s.c_str() );
02697     }
02698     if( name != title )
02699     {
02700       itemDescription += " ";
02701       itemDescription += title;
02702     }
02703     fContents->AddItem( item, itemDescription.c_str(),
02704                                   (void*)obj,
02705                                   gClient->GetPicture("h3_t.xpm"),
02706                                   gClient->GetPicture("h3_t.xpm") );
02707   }
02708   else if( className.find("Tree") != className.npos )
02709     fContents->AddItem( item, name.c_str(),
02710                                   (void*)obj,
02711                                   gClient->GetPicture("tree_t.xpm"),
02712                                   gClient->GetPicture("tree_t.xpm") );
02713   else if( className.find("Ntuple") != className.npos )
02714     fContents->AddItem( item, name.c_str(),
02715                                   (void*)obj,
02716                                   gClient->GetPicture("ntuple_t.xpm"),
02717                                   gClient->GetPicture("ntuple_t.xpm") );
02718   else if( className.find("Profile") != className.npos )
02719   {
02720      if( className.find("2D") != className.npos )
02721        fContents->AddItem( item, name.c_str(),
02722                                      (void*)obj,
02723                                      gClient->GetPicture("h2_t.xpm"),
02724                                      gClient->GetPicture("h2_t.xpm") );
02725      else
02726        fContents->AddItem( item, name.c_str(),
02727                                      (void*)obj,
02728                                      gClient->GetPicture("profile_t.xpm"),
02729                                      gClient->GetPicture("profile_t.xpm") );
02730   }
02731   else if( className.find("TCanvas") != className.npos )
02732   {
02733     fContents->AddItem( item, name.c_str(),
02734                                   (void*)obj,
02735                                   gClient->GetPicture("h1_t.xpm"),
02736                                   gClient->GetPicture("h1_t.xpm") );
02737   }
02738   else if( className.find("TCutG") != className.npos )
02739   {
02740     fContents->AddItem( item, name.c_str(),
02741                                   (void*)obj,
02742                                   gClient->GetPicture("cut_t.xpm"),
02743                                   gClient->GetPicture("cut_t.xpm") );
02744   }
02745 #endif
02746   else if (obj->InheritsFrom(TGraph::Class()))
02747   {
02748     item->SetPictures(gClient->GetPicture("h2_t.xpm"), gClient->GetPicture("h2_t.xpm"));
02749   }
02750   fContents->Resize();
02751 }
02752 
02753 void Roody::ConnectNetDirectory(const char*ss, bool displayMsgBox)
02754 {
02755   if (ss == NULL)
02756     {
02757       static TObjString ostr;
02758       static std::string istr = "";
02759       new TGTextDialog( gClient->GetRoot(), this, 100, 100, "&Host name:", istr.c_str(), &ostr);
02760       ss = ostr.GetString();
02761       if (strcmp(ss,"-1") == 0)
02762         return;
02763       istr = ss;
02764     }
02765 
02766   std::string server = ss;
02767   if (strstr(ss, ":") == NULL)
02768     server += ":9091";
02769 
02770   OpenNetDirectory(server.c_str());
02771 }
02772 
02773 void Roody::ConnectServer(const char*ss, bool displayMsgBox)
02774 {
02775   if (ss == NULL)
02776     {
02777       static TObjString ostr;
02778       static std::string istr = "";
02779       new TGTextDialog( gClient->GetRoot(), this, 100, 100, "&Host name:", istr.c_str(), &ostr);
02780       ss = ostr.GetString();
02781       if (strcmp(ss,"-1") == 0)
02782         return;
02783       istr = ss;
02784     }
02785 
02786   if (strncasecmp(ss, "http", 4) == 0) {
02787      OpenXmlServer(ss);
02788      return;
02789   }
02790 
02791   std::string server = ss;
02792   if (strstr(ss, ":") == NULL)
02793     server += ":9090";
02794 
02795   std::vector<std::string> s = split(':', server);
02796 
02797   std::string hostname = s[0];
02798   int port = atoi(s[1].c_str());
02799   if (port == 0)
02800     {
02801       std::string error;
02802       error += "Invalid port number in \'";
02803       error += server;
02804       error += "\'";
02805       new TGMsgBox(gClient->GetRoot(), this, "Error", error.c_str(), kMBIconExclamation, 0, NULL );
02806       return;
02807     }
02808 
02809   if (fContents->FindChildByName(fTreeItemOnline,server.c_str()))
02810     {
02811       std::string error;
02812       error += "Already connected to ";
02813       error += server;
02814       fStatusBar->SetText(error.c_str());
02815       return;
02816     }
02817 
02818   TSocket *sock = new TSocket(hostname.c_str(), port);
02819   if (!sock || !sock->IsValid())
02820     {
02821       if (sock)
02822         delete sock;
02823       sock = 0;
02824 
02825       if( displayMsgBox )
02826         {
02827           std::string error;
02828           error += "Cannot connect to Midas server \'";
02829           error += server;
02830           error += "\'";
02831           fStatusBar->SetText(error.c_str());
02832           new TGMsgBox( gClient->GetRoot(), this, "Error", error.c_str(), kMBIconExclamation, 0, NULL );
02833         }
02834       
02835       return;
02836     }
02837 
02838   DataSourceBase* d = new DataSourceTNetFolder(sock);
02839   fOnlineFiles.push_back(d->GetName());
02840 
02841   std::string msg = "Connected to ";
02842   msg += server;
02843   fStatusBar->SetText(msg.c_str());
02844   AddDataSource(d, fContents, fTreeItemOnline);
02845 }
02846 
02847 void Roody::StartUpdateTimer()
02848 {
02849   //printf("StartUpdateTimer %d %d\n", fUpdateTimerSec, fUpdatePause);
02850 
02851   if (fUpdateTimerSec > 0 && !fUpdatePause)
02852   {
02853     fUpdateTimer->SetTime(fUpdateTimerSec*1000); // changes timer length and restarts it
02854     fUpdateTimer->Start();
02855   }
02856   else
02857   {
02858     fUpdateTimer->Stop();
02859   }
02860 }
02861 
02862 void Roody::RefreshAll()
02863 {
02864   //printf("RefreshAll!\n");
02865 
02866   fUpdateTimer->Stop(); // so multiple updates do not occur at once
02867 
02868   TIter next = gROOT->GetListOfCanvases();
02869   while(1)
02870     {
02871       TCanvas *canvas = (TCanvas*)next();
02872       if (!canvas)
02873         break;
02874 
02875       RedrawCanvas(canvas, true);
02876     }
02877 
02878   StartUpdateTimer();
02879 }
02880 
02881 void Roody::OpenRefreshDialog()
02882 {
02883   TObjString ostr;
02884   new TGTextDialog( gClient->GetRoot(), this, 100, 100, "Refresh time in seconds: ", "", &ostr);
02885   const char* str = ostr.GetString();
02886   if (strcmp(str,"-1")==0)
02887     fStatusBar->SetText("Refresh not changed");
02888   else
02889     SetRefreshRate(atoi(str));
02890 }
02891 
02892 void Roody::OpenZoneDialog()
02893 {
02894   TObjString ostr;
02895   new TGTextDialog( gClient->GetRoot(), this, 100, 100,
02896                     "Zone Setting: (columns x rows, e.g. 2x2): ", "", &ostr);
02897   const char* str = ostr.GetString();
02898   if (strcmp(str,"-1")==0)
02899     {
02900       fStatusBar->SetText( "Zone settings not changed");
02901       return;
02902     }
02903   std::vector<std::string> sss = split('x', str);
02904   std::vector<int> iii = toInt(sss);
02905 
02906   int columns = iii[0];
02907   int rows    = iii[1];
02908 
02909   if (columns == 0)
02910     {
02911       columns = 1;
02912       std::string err;
02913       err += "Invalid number of columns in ";
02914       err += str;
02915       new TGMsgBox( gClient->GetRoot(), this, "Error", err.c_str(), kMBIconExclamation, 0, NULL );
02916     }
02917 
02918   if (rows == 0)
02919     {
02920       rows = 1;
02921       std::string err;
02922       err += "Invalid number of rows in ";
02923       err += str;
02924       new TGMsgBox( gClient->GetRoot(), this, "Error", err.c_str(), kMBIconExclamation, 0, NULL );
02925     }
02926 
02927   SetupZones( columns, rows );
02928   SetupZonesMenu();
02929 }
02930 
02931 void Roody::OpenSaveDialog()
02932 {
02933   TGFileInfo fileinfo;
02934   fileinfo.fFilename = 0;
02935   char const *fileTypes[] = {"Save file","*.xml","Any file","*",0,0};
02936   fileinfo.fFileTypes = fileTypes;
02937   new TGFileDialog( fClient->GetRoot(), this, kFDOpen, &fileinfo);
02938   TString savefileName = fileinfo.fFilename;
02939   if( savefileName.Contains("-1") )
02940   {
02941     fStatusBar->SetText( "NO FILE SELECTED" );
02942   }
02943   else
02944   {
02945     if (!savefileName.Contains(".xml"))
02946       savefileName += ".xml";
02947     SaveFile(savefileName.Data());
02948   }
02949 }
02950 
02951 void Roody::OpenRestoreDialog()
02952 {
02953   TGFileInfo fileinfo;
02954   fileinfo.fFilename = 0;
02955   char const *fileTypes[] = {"Save file","*.xml","Any file","*",0,0};
02956   fileinfo.fFileTypes = fileTypes;
02957   new TGFileDialog( fClient->GetRoot(), this, kFDOpen, &fileinfo );
02958   if( fileinfo.fFilename )
02959   {
02960     RestoreFile( fileinfo.fFilename );
02961   }
02962   else
02963   {
02964     fStatusBar->SetText( "NO FILE SELECTED" );
02965   }
02966 }
02967 
02968 /* emacs
02969  * Local Variables:
02970  * tab-width: 8
02971  * c-basic-offset: 3
02972  * indent-tabs-mode: nil
02973  * End:
02974  */
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends

Generated on 15 Nov 2016 for Roody by  doxygen 1.6.1