00001
00002
00003
00004
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
00056 }
00057
00058 class MemDebug : public TObject
00059 {
00060 public:
00061
00062 MemDebug()
00063 {
00064 printf("MemDebug %p created!\n", this);
00065 }
00066
00067 ~MemDebug()
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
00131 return NULL;
00132 }
00133
00134 TObject *obj = gObjectCache[src];
00135 if (obj)
00136 {
00137
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
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
00193 if (obj != xobj)
00194 {
00195
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)
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();
00248 MapWindow();
00249 fStatusBar->SetText("Welcome to Roody");
00250
00251 fZoneRows = 1;
00252 fZoneColumns = 1;
00253 fUpdateTimerSec = 0;
00254 fUpdatePause = false;
00255 fUpdateTimer = new TTimer(0,kTRUE);
00256
00257 TQObject::Connect( fUpdateTimer,"Timeout()","Roody",this,"RefreshAll()" );
00258 StartUpdateTimer();
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
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
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
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
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
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
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
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
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
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
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
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
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
00752
00753
00754
00755
00756 }
00757
00758 void Roody::LayoutGUI()
00759 {
00760 LayoutMenuBar();
00761
00762
00763
00764
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
00820
00821
00822 Associate(this);
00823 GetOptStat();
00824 SetOptStat();
00825 }
00826
00827 Bool_t ProcessMessage( Long_t msg, Long_t parm1, Long_t parm2 )
00828 {
00829
00830
00831 if (GET_MSG(msg) == kC_COMMAND && GET_SUBMSG(msg) == kCM_MENU)
00832 {
00833
00834
00835 if (IsEntryChecked(parm1))
00836 UnCheckEntry(parm1);
00837 else
00838 CheckEntry(parm1);
00839
00840
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);
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
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
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);
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
01049 h->GetXaxis()->SetRange(ufirst, ulast);
01050
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
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
01086 pad = canvas;
01087 }
01088
01089
01090
01091 TList* xcontents = pad->GetListOfPrimitives();
01092 int xcount = 0;
01093 if (xcontents)
01094 xcount = xcontents->GetSize();
01095
01096
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
01144
01145 padvec->push_back(PadObject(padNum, xobj, src, drawOpt));
01146 }
01147
01148 static void CopyAttrs(TObject* dest, TObject* src)
01149 {
01150
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
01213 if (gAllObjects->FindObject(oldobject))
01214 {
01215
01216 oldobject->GetName();
01217 }
01218 else
01219 {
01220
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
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
01297
01298 if (!gPad || !strcmp(gPad->GetCanvas()->GetName(),"Zoom Canvas"))
01299 return;
01300
01301
01302
01303
01304 PadObjectVec* contents = &gPadContents[gPad];
01305
01306
01307
01308
01309 TVirtualPad *padSave = gPad;
01310
01311 if (fZoomCanvas)
01312 delete fZoomCanvas;
01313 fZoomCanvas = new TCanvas("Zoom Canvas", "Zoom Canvas");
01314 fZoomCanvas->cd();
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
01369
01370
01371
01372
01373
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();
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
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
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)
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
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
01509
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);
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);
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();
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
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
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
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
01829
01830
01831
01832
01833
01834
01835
01836
01837 switch (GET_MSG(msg))
01838 {
01839 case kC_LISTTREE:
01840 {
01841 switch (GET_SUBMSG(msg))
01842 {
01843 default:
01844 break;
01845 case kCT_ITEMCLICK:
01846 {
01847 switch (parm1)
01848 {
01849 default:
01850 break;
01851
01852 case kButton1:
01853 break;
01854
01855 case kButton2:
01856 break;
01857
01858 case kButton3:
01859 {
01860
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
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:
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:
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
01953 }
01954 break;
01955 default:
01956 break;
01957 }
01958 break;
01959 }
01960 case kCM_MENUSELECT:
01961 {
01962 break;
01963 }
01964 case kCM_MENU:
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
02298
02299 for (TGListTreeItem *item = folder->GetFirstChild(); item != NULL; item = item->GetNextSibling())
02300 {
02301 if (gItemActions[item] == A_ITEM)
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
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
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
02607
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
02645
02646
02647 if( className.find("TH1") != className.npos )
02648 {
02649 #if 0
02650 if( title.find("Run#") == title.npos &&
02651 runNumber.find_first_not_of(" ") != runNumber.npos )
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
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 &&
02671 runNumber.find_first_not_of(" ") != runNumber.npos )
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 &&
02691 runNumber.find_first_not_of(" ") != runNumber.npos )
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
02850
02851 if (fUpdateTimerSec > 0 && !fUpdatePause)
02852 {
02853 fUpdateTimer->SetTime(fUpdateTimerSec*1000);
02854 fUpdateTimer->Start();
02855 }
02856 else
02857 {
02858 fUpdateTimer->Stop();
02859 }
02860 }
02861
02862 void Roody::RefreshAll()
02863 {
02864
02865
02866 fUpdateTimer->Stop();
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
02969
02970
02971
02972
02973
02974