]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MONITOR/AliMonitorClient.cxx
- Adapted comments for Doxygen
[u/mrichter/AliRoot.git] / MONITOR / AliMonitorClient.cxx
1 /**************************************************************************
2  * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3  *                                                                        *
4  * Author: The ALICE Off-line Project.                                    *
5  * Contributors are mentioned in the code where appropriate.              *
6  *                                                                        *
7  * Permission to use, copy, modify and distribute this software and its   *
8  * documentation strictly for non-commercial purposes is hereby granted   *
9  * without fee, provided that the above copyright notice appears in all   *
10  * copies and that both the copyright notice and this permission notice   *
11  * appear in the supporting documentation. The authors make no claims     *
12  * about the suitability of this software for any purpose. It is          *
13  * provided "as is" without express or implied warranty.                  *
14  **************************************************************************/
15
16 /* $Id$ */
17
18 ///////////////////////////////////////////////////////////////////////////////
19 //                                                                           //
20 //  This class receives monitor histograms from a monitor process and        //
21 //  provides a graphical user interface for browsing and analysing the       //
22 //  monitor histograms.                                                      //
23 //                                                                           //
24 ///////////////////////////////////////////////////////////////////////////////
25
26
27 #include "AliMonitorClient.h"
28 #include "AliMonitorProcess.h"
29 #include "AliLog.h"
30 #include <TGMsgBox.h>
31 #include <TGFileDialog.h>
32 #include <TMessage.h>
33 #include <TCanvas.h>
34 #include <TApplication.h>
35 #include <TStyle.h>
36 #include <TGMenu.h>
37 #include <TGButton.h>
38 #include <TGLabel.h>
39 #include <TGTextEntry.h>
40 #include <TGToolBar.h>
41 #include <TG3DLine.h>
42 #include <TGNumberEntry.h>
43 #include <TGCanvas.h>
44 #include <TGSplitter.h>
45 #include <TGListTree.h>
46 #include <TRootEmbeddedCanvas.h>
47 #include <TGTextView.h>
48 #include <TFolder.h>
49 #include <TSocket.h>
50 #include <TTimer.h>
51 #include <TFile.h>
52 #include "AliMonitorHisto.h"
53
54
55 ClassImp(AliMonitorClient) 
56
57
58 const char* AliMonitorClient::fgSettingsFileName = ".AliMonitorClient";
59
60
61 //_____________________________________________________________________________
62 AliMonitorClient::AliMonitorStringDlg::AliMonitorStringDlg(TString& string, 
63                                                            TGFrame* main, 
64                                                            const char* title, 
65                                                            const char* label) :
66   AliMonitorDialog(main, 300, 80), fString(string)
67 {
68 // create a dialog for connecting to a monitor process
69
70   fStringLayout = new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 5, 2, 2);
71   fStringLabel = new TGLabel(fFrame, label);
72   fFrame->AddFrame(fStringLabel, fStringLayout);
73   fStringEntry = new TGTextEntry(fFrame, string.Data());
74   fStringEntry->Resize(100, fStringEntry->GetDefaultHeight());
75   fFrame->AddFrame(fStringEntry, fStringLayout);
76
77   fString = "";
78
79   fMain->SetWindowName(title);
80   fMain->MapSubwindows();
81   fMain->Layout();
82   gClient->WaitFor(fMain);
83 }
84
85 //_____________________________________________________________________________
86 AliMonitorClient::AliMonitorStringDlg::~AliMonitorStringDlg()
87 {
88 // clean up
89
90   delete fStringLabel;
91   delete fStringLayout;
92   delete fStringEntry;
93 }
94
95 //_____________________________________________________________________________
96 void AliMonitorClient::AliMonitorStringDlg::OnOkClicked()
97 {
98   fString = fStringEntry->GetText();
99 }
100
101
102 //_____________________________________________________________________________
103 AliMonitorClient::AliMonitorNumberDlg::AliMonitorNumberDlg(Float_t& value, 
104                                                            TGFrame* main, 
105                                                            const char* title, 
106                                                            const char* label, 
107                                                            Float_t min) :
108   AliMonitorDialog(main, 250, 80), fNumber(value)
109 {
110 // create a dialog for getting a number
111
112   fNumberLayout = new TGLayoutHints(kLHintsLeft | kLHintsCenterY, 2, 5, 2, 2);
113   fNumberLabel = new TGLabel(fFrame, label);
114   fFrame->AddFrame(fNumberLabel, fNumberLayout);
115   fNumberEntry = new TGNumberEntry(fFrame, value, 4, -1,
116                                    TGNumberFormat::kNESRealOne);
117   fNumberEntry->SetLimits(TGNumberFormat::kNELLimitMin, min, 0);
118   fFrame->AddFrame(fNumberEntry, fNumberLayout);
119
120   fNumber = -1;
121
122   fMain->SetWindowName(title);
123   fMain->MapSubwindows();
124   fMain->Layout();
125   gClient->WaitFor(fMain);
126 }
127
128 //_____________________________________________________________________________
129 AliMonitorClient::AliMonitorNumberDlg::~AliMonitorNumberDlg()
130 {
131 // clean up
132
133   delete fNumberLabel;
134   delete fNumberLayout;
135   delete fNumberEntry;
136 }
137
138 //_____________________________________________________________________________
139 void AliMonitorClient::AliMonitorNumberDlg::OnOkClicked()
140 {
141   fNumber = fNumberEntry->GetNumber();
142 }
143
144
145
146 // constants for menu entries
147 enum {kMenuFileConnect, kMenuFileDisconnect, kMenuFileOpen, kMenuFileExit,
148       kMenuViewToolBar, kMenuViewTree, kMenuViewDescription, 
149       kMenuViewReference, kMenuViewStatistics,
150       kMenuFavAdd, kMenuFavDelete, 
151       kMenuFavLoad, kMenuFavSave,  kMenuFavSaveAs, kMenuFavSaveOnExit,
152       kMenuRefLoad, kMenuRefThreshold, 
153       kMenuRefTakeCurrent, kMenuRefSave, kMenuRefSaveAs,
154       kMenuOptLoop, kMenuOptPrint, 
155       kMenuOptSave, kMenuOptSaveOnExit,
156       kMenuHelpDoc, kMenuHelpAbout
157 };
158
159 //_____________________________________________________________________________
160 AliMonitorClient::AliMonitorClient():
161   TGMainFrame(gClient->GetRoot(), 500, 300)
162 {
163 // initialize the monitoring client window
164
165   // *** menu bar ***
166   fMenuBarLayout = new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX,
167                                       0, 0, 1, 1);
168   fMenuBarItemLayout = new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0);
169   fMenuBarHelpLayout = new TGLayoutHints(kLHintsTop | kLHintsRight);
170
171   // File menu
172   fMenuFile = new TGPopupMenu(gClient->GetRoot());
173   fMenuFile->AddEntry("&Connect...", kMenuFileConnect);
174   fMenuFile->AddEntry("&Disconnect...", kMenuFileDisconnect);
175   fMenuFile->HideEntry(kMenuFileDisconnect);
176   fMenuFile->AddEntry("&Open...", kMenuFileOpen);
177   fMenuFile->AddSeparator();
178   fMenuFile->AddEntry("E&xit", kMenuFileExit);
179   fMenuFile->Connect("Activated(Int_t)", "AliMonitorClient", this,
180                      "OnMenuActivated(Int_t)");
181
182   // View menu
183   fMenuView = new TGPopupMenu(gClient->GetRoot());
184   fMenuView->AddEntry("Tool&bar", kMenuViewToolBar);
185   fMenuView->CheckEntry(kMenuViewToolBar);
186   fMenuView->AddEntry("&Tree", kMenuViewTree);
187   fMenuView->CheckEntry(kMenuViewTree);
188   fMenuView->AddEntry("&Description", kMenuViewDescription);
189   fMenuView->CheckEntry(kMenuViewDescription);
190   fMenuView->AddSeparator();
191   fMenuView->AddEntry("&Reference", kMenuViewReference);
192   fMenuView->CheckEntry(kMenuViewReference);
193   AliMonitorHisto::SetDrawRef(kTRUE);
194   fMenuView->AddEntry("&Statistics", kMenuViewStatistics);
195   fMenuView->CheckEntry(kMenuViewStatistics);
196   gStyle->SetOptStat(1110);
197   fMenuView->Connect("Activated(Int_t)", "AliMonitorClient", this,
198                      "OnMenuActivated(Int_t)");
199
200   // Favorites menu
201   fMenuFavorites = new TGPopupMenu(gClient->GetRoot());
202   fMenuFavorites->AddEntry("&Add", kMenuFavAdd);
203   fMenuFavorites->DisableEntry(kMenuFavAdd);
204   fMenuFavorites->AddEntry("&Delete", kMenuFavDelete);
205   fMenuFavorites->DisableEntry(kMenuFavDelete);
206   fMenuFavorites->AddSeparator();
207   fMenuFavorites->AddEntry("&Load...", kMenuFavLoad);
208   fMenuFavorites->AddEntry("&Save", kMenuFavSave);
209   fMenuFavorites->DisableEntry(kMenuFavSave);
210   fMenuFavorites->AddEntry("&Save As...", kMenuFavSaveAs);
211   fMenuFavorites->DisableEntry(kMenuFavSaveAs);
212   fMenuFavorites->AddEntry("Save On &Exit", kMenuFavSaveOnExit);
213   fMenuFavorites->CheckEntry(kMenuFavSaveOnExit);
214   fMenuFavorites->Connect("Activated(Int_t)", "AliMonitorClient", this,
215                           "OnMenuActivated(Int_t)");
216
217   // Reference menu
218   fMenuReference = new TGPopupMenu(gClient->GetRoot());
219   fMenuReference->AddEntry("&Load...", kMenuRefLoad);
220   fMenuReference->AddEntry("&Threshold...", kMenuRefThreshold);
221   fMenuReference->AddSeparator();
222   fMenuReference->AddEntry("Take &Current", kMenuRefTakeCurrent);
223   fMenuReference->DisableEntry(kMenuRefTakeCurrent);
224   fMenuReference->AddEntry("&Save", kMenuRefSave);
225   fMenuReference->DisableEntry(kMenuRefSave);
226   fMenuReference->AddEntry("Save &As...", kMenuRefSaveAs);
227   fMenuReference->DisableEntry(kMenuRefSaveAs);
228   fMenuReference->Connect("Activated(Int_t)", "AliMonitorClient", this,
229                           "OnMenuActivated(Int_t)");
230
231   // Options menu
232   fMenuOptions = new TGPopupMenu(gClient->GetRoot());
233   fMenuOptions->AddEntry("&Loop Interval...", kMenuOptLoop);
234   fMenuOptions->AddEntry("&Print Command...", kMenuOptPrint);
235   fMenuOptions->AddSeparator();
236   fMenuOptions->AddEntry("&Save Settings", kMenuOptSave);
237   fMenuOptions->AddEntry("Save Settings on &Exit", kMenuOptSaveOnExit);
238   fMenuOptions->CheckEntry(kMenuOptSaveOnExit);
239   fMenuOptions->Connect("Activated(Int_t)", "AliMonitorClient", this,
240                         "OnMenuActivated(Int_t)");
241
242   // Help menu
243   fMenuHelp = new TGPopupMenu(gClient->GetRoot());
244   fMenuHelp->AddEntry("&Documentation...", kMenuHelpDoc);
245   fMenuHelp->AddEntry("A&bout...", kMenuHelpAbout);
246   fMenuHelp->Connect("Activated(Int_t)", "AliMonitorClient", this,
247                      "OnMenuActivated(Int_t)");
248
249   // menu bar
250   fMenuBar = new TGMenuBar(this, 1, 1, kHorizontalFrame);
251   fMenuBar->AddPopup("&File", fMenuFile, fMenuBarItemLayout);
252   fMenuBar->AddPopup("&View", fMenuView, fMenuBarItemLayout);
253   fMenuBar->AddPopup("F&avorites", fMenuFavorites, fMenuBarItemLayout);
254   fMenuBar->AddPopup("&Reference", fMenuReference, fMenuBarItemLayout);
255   fMenuBar->AddPopup("&Options", fMenuOptions, fMenuBarItemLayout);
256   fMenuBar->AddPopup("&Help", fMenuHelp, fMenuBarHelpLayout);
257
258   AddFrame(fMenuBar, fMenuBarLayout);
259
260
261   // *** tool bar ***
262   fToolBarLayout = new TGLayoutHints(kLHintsTop | kLHintsExpandX, 0, 0, 2, 2);
263   fToolBarSep = new TGHorizontal3DLine(this);
264   AddFrame(fToolBarSep, fToolBarLayout);
265   fToolBar = new TGToolBar(this, 60, 20, kHorizontalFrame);
266   AddFrame(fToolBar, fToolBarLayout);
267
268   // event number field
269   fEventNumberLayout = new TGLayoutHints(kLHintsCenterY | kLHintsLeft, 
270                                          10, 2, 10, 5);
271   fEventNumber = new TGNumberEntry(fToolBar, 1, 4, 10, 
272                                    TGNumberFormat::kNESInteger);
273   fEventNumber->SetLimits(TGNumberFormat::kNELLimitMin, 1, 0);
274   fToolBar->AddFrame(fEventNumber, fEventNumberLayout);
275   fEventNumber->GetNumberEntry()->Connect("ReturnPressed()", 
276                                           "AliMonitorClient", this,
277                                           "OnEventNumberChanged()");
278   fEventNumber->GetButtonUp()->Connect("Clicked()", 
279                                        "AliMonitorClient", this,
280                                        "OnEventNumberChanged()");
281   fEventNumber->GetButtonDown()->Connect("Clicked()", 
282                                          "AliMonitorClient", this,
283                                          "OnEventNumberChanged()");
284
285   // draw event button
286   ToolBarData_t eventButton = {"h1_s.xpm", "draw event histogram", 
287                                kTRUE, 11, NULL};
288   fToolBar->AddButton(this, &eventButton, 5);
289   fEventButton = eventButton.fButton;
290   fEventButton->Connect("Pressed()", "AliMonitorClient", this,
291                         "OnEventButtonPressed()");
292
293   // draw sum button
294   ToolBarData_t sumButton = {"h2_s.xpm", "draw sum histogram", 
295                              kTRUE, 12, NULL};
296   fToolBar->AddButton(this, &sumButton, 5);
297   fSumButton = sumButton.fButton;
298   fSumButton->Connect("Pressed()", "AliMonitorClient", this,
299                       "OnSumButtonPressed()");
300
301   // draw run button
302   ToolBarData_t runButton = {"h3_s.xpm", "draw run histogram", 
303                              kTRUE, 13, NULL};
304   fToolBar->AddButton(this, &runButton, 5);
305   fRunButton = runButton.fButton;
306   fRunButton->SetDown(kTRUE);
307   fRunButton->Connect("Pressed()", "AliMonitorClient", this,
308                       "OnRunButtonPressed()");
309
310   // loop button
311   char fileName[256];
312   sprintf(fileName, "%s/MONITOR/loop_on.xpm", gSystem->Getenv("ALICE_ROOT"));
313   ToolBarData_t loopButton = {fileName, "loop over histograms", 
314                               kFALSE, 21, NULL};
315   fToolBar->AddButton(this, &loopButton, 25);
316   fLoopButton = loopButton.fButton;
317   fLoopButton->Connect("Clicked()", "AliMonitorClient", this,
318                        "OnLoopButtonClicked()");
319   fLoopOnPicture = gClient->GetPicture(fileName);
320   sprintf(fileName, "%s/MONITOR/loop_off2.xpm", gSystem->Getenv("ALICE_ROOT"));
321   fLoopOffPicture = gClient->GetPicture(fileName);
322
323   // previous button
324   sprintf(fileName, "%s/MONITOR/previous_s.xpm", 
325           gSystem->Getenv("ALICE_ROOT"));
326   ToolBarData_t previousButton = {fileName, "go to previous histogram", 
327                                   kFALSE, 22, NULL};
328   fToolBar->AddButton(this, &previousButton, 5);
329   fPreviousButton = previousButton.fButton;
330   fPreviousButton->Connect("Clicked()", "AliMonitorClient", this,
331                            "OnPreviousButtonClicked()");
332
333   // next button
334   sprintf(fileName, "%s/MONITOR/next_s.xpm", gSystem->Getenv("ALICE_ROOT"));
335   ToolBarData_t nextButton = {fileName, "go to next histogram", 
336                               kFALSE, 23, NULL};
337   fToolBar->AddButton(this, &nextButton, 5);
338   fNextButton = nextButton.fButton;
339   fNextButton->Connect("Clicked()", "AliMonitorClient", this,
340                        "OnNextButtonClicked()");
341
342   // copy button
343   sprintf(fileName, "%s/MONITOR/copy_s.xpm", gSystem->Getenv("ALICE_ROOT"));
344   ToolBarData_t copyButton = {fileName, 
345                               "copy the current histogram to a new canvas", 
346                               kFALSE, 31, NULL};
347   fToolBar->AddButton(this, &copyButton, 25);
348   fCopyButton = copyButton.fButton;
349   fCopyButton->Connect("Clicked()", "AliMonitorClient", this,
350                        "OnCopyButtonClicked()");
351
352   // save button
353   sprintf(fileName, "%s/MONITOR/save_s.xpm", gSystem->Getenv("ALICE_ROOT"));
354   ToolBarData_t saveButton = {fileName, "save the current histogram", 
355                               kFALSE, 32, NULL};
356   fToolBar->AddButton(this, &saveButton, 5);
357   fSaveButton = saveButton.fButton;
358   fSaveButton->Connect("Clicked()", "AliMonitorClient", this,
359                        "OnSaveButtonClicked()");
360
361   // print button
362   ToolBarData_t printButton = {"printer_s.xpm", "print the current histogram", 
363                              kFALSE, 33, NULL};
364   fToolBar->AddButton(this, &printButton, 5);
365   fPrintButton = printButton.fButton;
366   fPrintButton->Connect("Clicked()", "AliMonitorClient", this,
367                         "OnPrintButtonClicked()");
368
369   // *** frames ***
370   fBottomLayout = new TGLayoutHints(kLHintsExpandX | kLHintsBottom);
371   fLeftLayout = new TGLayoutHints(kLHintsLeft | kLHintsExpandY);
372   fExpandLayout = new TGLayoutHints(kLHintsExpandX | kLHintsExpandY);
373
374   fVerticalFrame = new TGVerticalFrame(this, 10, 10);
375   AddFrame(fVerticalFrame, fExpandLayout);
376
377   fHorizontalFrame = new TGHorizontalFrame(fVerticalFrame, 10, 10);
378   fVerticalFrame->AddFrame(fHorizontalFrame, fExpandLayout);
379
380   // tree frame
381   fTreeFrame = new TGCompositeFrame(fHorizontalFrame, 10, 10, 
382                                     kSunkenFrame | kFixedWidth);
383   fHorizontalFrame->AddFrame(fTreeFrame, fLeftLayout);
384   fTreeCanvas = new TGCanvas(fTreeFrame, 10, 10);
385   fTreeFrame->AddFrame(fTreeCanvas, fExpandLayout);
386   fTree = new TGListTree(fTreeCanvas, kHorizontalFrame);
387   fTreeCanvas->AddFrame(fTree, fExpandLayout);
388   fTree->Connect("Clicked(TGListTreeItem*,Int_t)", "AliMonitorClient",
389                  this, "OnTreeClicked(TGListTreeItem*,Int_t)");
390   fTree->Connect("ReturnPressed(TGListTreeItem*)", "AliMonitorClient",
391                  this, "OnTreeReturnPressed(TGListTreeItem*)");
392
393   // tree items
394   fAllItem = fTree->AddItem(NULL, "All");
395   fFavoritesItem = fTree->AddItem(NULL, "Favorites");
396   fComparisonItem = fTree->AddItem(NULL, "Comparison");
397   fHistoPicture = fClient->GetPicture("h1_t.xpm"); 
398   fTreeFrame->Resize(100, fTreeFrame->GetDefaultHeight());
399
400   // tree / histogram splitter
401   fTreeSplitter = new TGVSplitter(fHorizontalFrame, 4);
402   fTreeSplitter->SetFrame(fTreeFrame, kTRUE);
403   fHorizontalFrame->AddFrame(fTreeSplitter, fLeftLayout);
404
405   // histogram frame
406   fDrawFrame = new TGCompositeFrame(fHorizontalFrame, 10, 10, kSunkenFrame);
407   fHorizontalFrame->AddFrame(fDrawFrame, fExpandLayout);
408   fDrawCanvas = new TRootEmbeddedCanvas("current monitor histogram", 
409                                         fDrawFrame, 10, 10);
410   fDrawFrame->AddFrame(fDrawCanvas, fExpandLayout);
411
412   // description frame
413   fDescriptionFrame = new TGCompositeFrame(fVerticalFrame, 10, 60, 
414                                            kSunkenFrame | kFixedHeight);
415   fVerticalFrame->AddFrame(fDescriptionFrame, fBottomLayout);
416   fDescription = new TGTextView(fDescriptionFrame, 10, 60, "");
417   fDescriptionFrame->AddFrame(fDescription, fExpandLayout);
418
419   // histogram / description splitter
420   fDescriptionSplitter = new TGHSplitter(fVerticalFrame, 4, 4);
421   fVerticalFrame->AddFrame(fDescriptionSplitter, fBottomLayout);
422   fDescriptionSplitter->SetFrame(fDescriptionFrame, kFALSE);
423
424   // main window
425   Connect("CloseWindow()", "AliMonitorClient", this, "CloseWindow()");
426   SetWindowName("Monitor Client");
427   SetWMSize(GetWidth(), GetHeight());
428   Move(100, 100);
429   SetWMPosition(100, 100);
430   MapSubwindows();
431   Layout();
432   MapWindow();
433
434
435   // default data members
436   fServerName = "localhost";
437   fSocket = NULL;
438   fSocketHandler = NULL;
439
440   fFolder = CreateTopFolder();
441
442   fCurrentItem = NULL;
443   fBaseItem = NULL;
444   fLoopTimer = NULL;
445   fLoopInterval = 1000;
446
447   fFavoritesFileName = "";
448
449   fReferenceFileName = "";
450   fReference = CreateTopFolder();
451   AliMonitorHisto::SetThreshold(5.0);
452
453   fPrintCommand = "gv";
454
455   // load saved settings
456   LoadSettings();
457 }
458
459 //_____________________________________________________________________________
460 AliMonitorClient::AliMonitorClient(const AliMonitorClient& client) :
461   TGMainFrame(client)
462 {
463   AliFatal("copy constructor not implemented");
464 }
465
466 //_____________________________________________________________________________
467 AliMonitorClient& AliMonitorClient::operator = (const AliMonitorClient& 
468                                                 /*client*/)
469 {
470   AliFatal("assignment operator not implemented");
471   return *this;
472 }
473
474 //_____________________________________________________________________________
475 AliMonitorClient::~AliMonitorClient()
476 {
477 // clean up
478
479   delete fMenuBarLayout;
480   delete fMenuBarItemLayout;
481   delete fMenuBarHelpLayout;
482   delete fMenuFile;
483   delete fMenuView;
484   delete fMenuFavorites;
485   delete fMenuReference;
486   delete fMenuOptions;
487   delete fMenuHelp;
488   delete fMenuBar;
489
490   delete fEventNumberLayout;
491   delete fEventNumber;
492   delete fToolBarLayout;
493   delete fToolBarSep;
494   delete fToolBar;
495
496   delete fBottomLayout;
497   delete fLeftLayout;
498   delete fExpandLayout;
499
500   delete fTree;
501   delete fTreeCanvas;
502   delete fTreeFrame;
503   delete fTreeSplitter;
504
505   delete fDrawCanvas;
506   delete fDrawFrame;
507
508   delete fDescriptionSplitter;
509   delete fDescription;
510   delete fDescriptionFrame;
511
512   delete fVerticalFrame;
513   delete fHorizontalFrame;
514
515   if (fSocket) {
516     fSocketHandler->Remove();
517     fSocket->Send("disconnect");
518     fSocket->Close();
519     delete fSocket;
520     delete fSocketHandler;
521   }
522
523   if (fFolder) delete fFolder;
524
525   if (fLoopTimer) {
526     fLoopTimer->TurnOff();
527     delete fLoopTimer;
528   }
529
530   if (fReference) delete fReference;
531 }
532
533
534 //_____________________________________________________________________________
535 void AliMonitorClient::CloseWindow()
536 {
537 // terminate the application when the window is closed
538
539   if (fMenuFavorites->IsEntryChecked(kMenuFavSaveOnExit)) {
540     SaveFavorites();
541   }
542   if (fMenuOptions->IsEntryChecked(kMenuOptSaveOnExit)) {
543     SaveSettings();
544   }
545   if (fSocket) {
546     fSocketHandler->Remove();
547     fSocket->Send("disconnect");
548     fSocket->Close();
549     delete fSocket;
550     fSocket = NULL;
551     delete fSocketHandler;
552     fSocketHandler = NULL;
553   }
554
555   gApplication->Terminate(0);
556 }
557
558
559 //_____________________________________________________________________________
560 void AliMonitorClient::OnNewData()
561 {
562 // called when data has arrived from the monitor server
563
564   if (CheckForNewData()) UpdateAll();
565 }
566
567
568 //_____________________________________________________________________________
569 void AliMonitorClient::OnMenuActivated(Int_t id)
570 {
571 // called when a menu item was selected
572
573   switch (id) {
574
575   case kMenuFileConnect: {
576     if (ConnectToServer()) UpdateAll();
577     break;
578   }
579
580   case kMenuFileDisconnect: {
581     DisconnectFromServer();
582     break;
583   }
584
585   case kMenuFileOpen: {
586     if (OpenFile()) UpdateAll();
587     break;
588   }
589
590   case kMenuFileExit: {
591     CloseWindow();
592     break;
593   }
594
595   case kMenuViewToolBar: {
596     ViewToolBar(!fMenuView->IsEntryChecked(kMenuViewToolBar));
597     break;
598   }
599
600   case kMenuViewTree: {
601     ViewTree(!fMenuView->IsEntryChecked(kMenuViewTree));
602     break;
603   }
604
605   case kMenuViewDescription: {
606     ViewDescription(!fMenuView->IsEntryChecked(kMenuViewDescription));
607     break;
608   }
609
610   case kMenuViewReference: {
611     ViewReference(!fMenuView->IsEntryChecked(kMenuViewReference));
612     UpdateHisto();
613     break;
614   }
615
616   case kMenuViewStatistics: {
617     ViewStatistics(!fMenuView->IsEntryChecked(kMenuViewStatistics));
618     UpdateHisto();
619     break;
620   }
621
622   case kMenuFavAdd: {
623     if (AddFavorite()) {
624       fMenuFavorites->EnableEntry(kMenuFavSave);
625       fMenuFavorites->EnableEntry(kMenuFavSaveAs);
626     }
627     break;
628   }
629
630   case kMenuFavDelete: {
631     if (DeleteFavorite()) {
632       UpdateHisto();
633       UpdateDescription();
634       fMenuFavorites->DisableEntry(kMenuFavDelete);
635       fMenuFavorites->EnableEntry(kMenuFavSave);
636       fMenuFavorites->EnableEntry(kMenuFavSaveAs);
637     }
638     break;
639   }
640
641   case kMenuFavLoad: {
642     if (LoadFavorites()) {
643       UpdateHisto();
644       UpdateDescription();
645       fMenuFavorites->DisableEntry(kMenuFavSave);
646       fMenuFavorites->EnableEntry(kMenuFavSaveAs);
647     }
648     break;
649   }
650
651   case kMenuFavSave: {
652     if (SaveFavorites()) {
653       fMenuFavorites->DisableEntry(kMenuFavSave);
654     }
655     break;
656   }
657
658   case kMenuFavSaveAs: {
659     if (SaveFavoritesAs()) {
660       fMenuFavorites->DisableEntry(kMenuFavSave);
661     }
662     break;
663   }
664
665   case kMenuFavSaveOnExit: {
666     if (fMenuFavorites->IsEntryChecked(kMenuFavSaveOnExit)) {
667       fMenuFavorites->UnCheckEntry(kMenuFavSaveOnExit);
668     } else {
669       fMenuFavorites->CheckEntry(kMenuFavSaveOnExit);
670     }
671     break;
672   }
673
674   case kMenuRefLoad: {
675     if (LoadReference()) {
676       SetReference();
677       UpdateHisto();
678       UpdateComparisonTree();
679       fMenuReference->EnableEntry(kMenuRefSaveAs);
680     }
681     break;
682   }
683
684   case kMenuRefThreshold: {
685     Float_t threshold = AliMonitorHisto::GetThreshold();
686     new AliMonitorNumberDlg(threshold, this, 
687                             "Comparison with Reference Histograms",
688                             "threshold for comparison:", 0.);
689     if (threshold < 0) break;
690
691     AliMonitorHisto::SetThreshold(threshold);
692     UpdateHisto();
693     UpdateComparisonTree();
694     break;
695   }
696
697   case kMenuRefTakeCurrent: {
698     if (TakeCurrentReference()) {
699       UpdateHisto();
700       UpdateComparisonTree();
701       fMenuReference->EnableEntry(kMenuRefSave);
702       fMenuReference->EnableEntry(kMenuRefSaveAs);
703     }
704     break;
705   }
706
707   case kMenuRefSave: {
708     if (SaveReference()) {
709       fMenuReference->DisableEntry(kMenuRefSave);
710     }
711     break;
712   }
713
714   case kMenuRefSaveAs: {
715     if (SaveReferenceAs()) {
716       fMenuReference->DisableEntry(kMenuRefSave);
717     }
718     break;
719   }
720
721   case kMenuOptLoop: {
722     Float_t interval = fLoopInterval * 0.001;
723     new AliMonitorNumberDlg(interval, this, "Loop Interval",
724                             "loop time in seconds:", 0.1);
725     if (interval < 0) break;
726
727     fLoopInterval = Int_t(1000 * interval);
728     if (fLoopTimer) {
729       fLoopTimer->Stop();
730       fLoopTimer->Start(fLoopInterval);
731     }
732     break;
733   }
734
735   case kMenuOptPrint: {
736     TString printCommand(fPrintCommand);
737     new AliMonitorStringDlg(printCommand, this, "Print Command",
738                             "shell command for printing:");
739     if (printCommand.IsNull()) break;
740
741     fPrintCommand = printCommand;
742     break;
743   }
744
745   case kMenuOptSaveOnExit: {
746     if (fMenuOptions->IsEntryChecked(kMenuOptSaveOnExit)) {
747       fMenuOptions->UnCheckEntry(kMenuOptSaveOnExit);
748     } else {
749       fMenuOptions->CheckEntry(kMenuOptSaveOnExit);
750     }
751     break;
752   }
753
754   case kMenuOptSave: {
755     SaveSettings();
756     break;
757   }
758
759   case kMenuHelpAbout: {
760     Int_t result;
761     new TGMsgBox(gClient->GetRoot(), this, 
762                  "About", "AliMonitorClient $Revision$", 
763                  kMBIconAsterisk, kMBOk, &result);
764     break;
765   }
766
767   default: {
768     Int_t result;
769     new TGMsgBox(gClient->GetRoot(), this, 
770                  "AliMonitorClient", "not yet implemented", 
771                  kMBIconExclamation, kMBOk, &result);
772   }
773   }
774 }
775
776
777 //_____________________________________________________________________________
778 void AliMonitorClient::OnEventNumberChanged()
779 {
780 // called when the event number in the tool button was changed
781
782   if (!fRunButton->IsDown()) {
783     UpdateHisto();
784     UpdateComparisonTree();
785   }
786 }
787
788 //_____________________________________________________________________________
789 void AliMonitorClient::OnEventButtonPressed()
790 {
791 // called when the event tool button was clicked
792
793   fSumButton->SetDown(kFALSE);
794   fRunButton->SetDown(kFALSE);
795   UpdateHisto();
796   UpdateComparisonTree();
797 }
798
799 //_____________________________________________________________________________
800 void AliMonitorClient::OnSumButtonPressed()
801 {
802 // called when the sum tool button was clicked
803
804   fEventButton->SetDown(kFALSE);
805   fRunButton->SetDown(kFALSE);
806   UpdateHisto();
807   UpdateComparisonTree();
808 }
809
810 //_____________________________________________________________________________
811 void AliMonitorClient::OnRunButtonPressed()
812 {
813 // called when the run tool button was clicked
814
815   fEventButton->SetDown(kFALSE);
816   fSumButton->SetDown(kFALSE);
817   UpdateHisto();
818   UpdateComparisonTree();
819 }
820
821 //_____________________________________________________________________________
822 void AliMonitorClient::OnLoopButtonClicked()
823 {
824 // called when the loop tool button was clicked
825
826   // if loop is not running, start the loop timer and 
827   // set the stop loop button picture
828   if (!fLoopTimer) {  
829     if (!fBaseItem) {
830       if (!GetBaseItem()) return;
831     }
832     fLoopTimer = new TTimer(fLoopInterval);
833     fLoopTimer->Connect("Timeout()", "AliMonitorClient", this, 
834                         "OnLoopTimer()");
835     ((TGPictureButton*) fLoopButton)->SetPicture(fLoopOffPicture);
836     fLoopTimer->TurnOn();
837
838   // if the loop is running, stop it
839   } else {
840     StopLoop();
841   }
842 }
843
844 //_____________________________________________________________________________
845 void AliMonitorClient::OnPreviousButtonClicked()
846 {
847 // called when the previous tool button was clicked
848
849   if (!fBaseItem) {
850     if (!GetBaseItem()) return;
851   }
852   StopLoop();
853   GoToPreviousItem();
854 }
855
856 //_____________________________________________________________________________
857 void AliMonitorClient::OnNextButtonClicked()
858 {
859 // called when the next tool button was clicked
860
861   if (!fBaseItem) {
862     if (!GetBaseItem()) return;
863   }
864   StopLoop();
865   GoToNextItem();
866 }
867
868 //_____________________________________________________________________________
869 void AliMonitorClient::OnCopyButtonClicked()
870 {
871 // called when the copy tool button was clicked
872
873   fDrawCanvas->GetCanvas()->DrawClone();
874 }
875
876 //_____________________________________________________________________________
877 void AliMonitorClient::OnSaveButtonClicked()
878 {
879 // called when the save tool button was clicked
880
881   // display a file save dialog
882   static TGFileInfo fileInfo;
883   static const char* fileTypes[] = {"PostScript",   "*.ps",
884                                     "Encapsulated PostScript", "*.eps",
885                                     "SVG",          "*.svg",
886                                     "Gif files",    "*.gif",
887                                     "Macro files",  "*.C",
888                                     "ROOT files", "*.root", 
889                                     "All files",  "*", 
890                                     NULL,         NULL};
891   fileInfo.fFileTypes = fileTypes;
892   new TGFileDialog(gClient->GetRoot(), this, kFDSave, &fileInfo);
893   if (!fileInfo.fFilename) return;
894
895   fDrawCanvas->GetCanvas()->SaveAs(fileInfo.fFilename);
896 }
897
898 //_____________________________________________________________________________
899 void AliMonitorClient::OnPrintButtonClicked()
900 {
901 // called when the print tool button was clicked
902
903   // save the canvas to a temporary postscript file
904   char fileName[L_tmpnam+4];
905   sprintf(fileName, "%s.ps", tmpnam(NULL));
906   fDrawCanvas->GetCanvas()->SaveAs(fileName);
907
908   // call the print command and delete the temporary file
909   char command[256];
910   sprintf(command, "%s %s", fPrintCommand.Data(), fileName);
911   gSystem->Exec(command);
912   gSystem->Unlink(fileName);
913 }
914
915
916 //_____________________________________________________________________________
917 void AliMonitorClient::OnTreeClicked(TGListTreeItem* item, Int_t)
918 {
919 // called when an item in the histogram tree is clicked
920
921   OnTreeReturnPressed(item);
922 }
923
924 //_____________________________________________________________________________
925 void AliMonitorClient::OnTreeReturnPressed(TGListTreeItem* item)
926 {
927 // called when return is pressed at an item in the histogram tree
928
929   fCurrentItem = item;
930   fBaseItem = NULL;
931   StopLoop();
932   UpdateItem(kFALSE);
933 }
934
935
936 //_____________________________________________________________________________
937 void AliMonitorClient::OnLoopTimer()
938 {
939 // called by the loop timer when a new histogram should be displayed
940
941   if (!fBaseItem) {
942     if (!GetBaseItem()) return;
943   }
944   GoToNextItem();
945 }
946
947
948 //_____________________________________________________________________________
949 TFolder* AliMonitorClient::CreateTopFolder() const
950 {
951 // create a top folder for monitor histograms
952
953   return (new TFolder("Monitor", "monitor histograms"));
954 }
955
956 //_____________________________________________________________________________
957 AliMonitorHisto* AliMonitorClient::GetHisto(const char* folderName, 
958                                             const char* histoName)
959 {
960 // find the monitor histogram with the given name in the given folder
961
962   TGListTreeItem* folderItem = fTree->FindChildByName(fAllItem, folderName);
963   if (folderItem) {
964     TGListTreeItem* histoItem = fTree->FindChildByName(folderItem, histoName);
965     if (histoItem) return (AliMonitorHisto*) histoItem->GetUserData();
966   }
967   return NULL;
968 }
969
970 //_____________________________________________________________________________
971 TGListTreeItem* AliMonitorClient::GetItem(TGListTreeItem* base, 
972                                           const char* folderName, 
973                                           const char* histoName, 
974                                           Bool_t create)
975 {
976 // find the tree item with given name in the given folder
977 // if create is kTRUE it is created if it is not there
978
979   // get or create the folder
980   TGListTreeItem* folderItem = fTree->FindChildByName(base, folderName);
981   if (!folderItem) {
982     if (!create) return NULL;
983     folderItem = fTree->AddItem(base, folderName);
984   }
985
986   // get or create the histo
987   TGListTreeItem* histoItem = fTree->FindChildByName(folderItem, histoName);
988   if (!histoItem) {
989     if (!create) return NULL;
990     histoItem = fTree->AddItem(folderItem, histoName,
991                                fClient->GetPicture("h1_t.xpm"),
992                                fClient->GetPicture("h1_t.xpm"));
993   }
994   return histoItem;
995 }
996
997
998 //_____________________________________________________________________________
999 Bool_t AliMonitorClient::ConnectToServer()
1000 {
1001 // display the dialog for the server name or ip and try to connect to it
1002
1003   TString serverName(fServerName);
1004
1005   do {
1006     // ask for the server name or ip
1007     new AliMonitorStringDlg(serverName, this, "Connection to monitor process",
1008                             "monitor server name or ip:");
1009     if (serverName.IsNull()) return kFALSE;
1010
1011     // connect to the server
1012     fSocket = new TSocket(serverName, AliMonitorProcess::GetPort());
1013     if (!fSocket || !fSocket->IsValid() || (fSocket->Send("client") <= 0)) {
1014       if (fSocket) delete fSocket;
1015       fSocket = NULL;
1016       Int_t result;
1017       new TGMsgBox(gClient->GetRoot(), this, "Connect",
1018                    "connection to monitor server failed", 
1019                    kMBIconExclamation, kMBOk, &result);
1020
1021     } else {  // set up a handler for notifying when new data is there
1022       fServerName = serverName;
1023       fSocketHandler = new TFileHandler(fSocket->GetDescriptor(), 
1024                                         TFileHandler::kRead);
1025       fSocketHandler->Connect("Notified()", "AliMonitorClient", this,
1026                               "OnNewData()");
1027       fSocketHandler->Add();
1028       TInetAddress adr = fSocket->GetInetAddress();
1029       AliInfo(Form("connected to server: %s (%s), port %d",
1030                    adr.GetHostName(), adr.GetHostAddress(), adr.GetPort()));
1031       fMenuFile->HideEntry(kMenuFileConnect);
1032       fMenuFile->HideEntry(kMenuFileOpen);
1033       fMenuFile->EnableEntry(kMenuFileDisconnect);
1034     };
1035
1036   } while (!fSocket);
1037
1038   // delete the old monitor histos
1039   if (fFolder) delete fFolder;
1040   fFolder = CreateTopFolder();
1041   return kTRUE;
1042 }
1043
1044 //_____________________________________________________________________________
1045 void AliMonitorClient::DisconnectFromServer()
1046 {
1047 // disconnect from the monitor server
1048
1049   // are-you-really-sure-dialog
1050   Int_t result;
1051   new TGMsgBox(gClient->GetRoot(), this, "Disconnect",
1052                "Do you really want to disconnect from the monitor server?", 
1053                kMBIconQuestion, kMBYes | kMBNo, &result);
1054   if (result == kMBNo) return;
1055
1056   // disconnect from the server
1057   fSocketHandler->Remove();
1058   fSocket->Send("disconnect");
1059   fSocket->Close();
1060   delete fSocket;
1061   fSocket = NULL;
1062   fMenuFile->HideEntry(kMenuFileDisconnect);
1063   fMenuFile->EnableEntry(kMenuFileConnect);
1064   fMenuFile->EnableEntry(kMenuFileOpen);
1065 }
1066
1067 //_____________________________________________________________________________
1068 Bool_t AliMonitorClient::OpenFile()
1069 {
1070 // open a file with monitor histograms
1071
1072   // display a file open dialog
1073   static TGFileInfo fileInfo;
1074   static const char* fileTypes[] = {"ROOT files", "*.root", 
1075                                     "All files",  "*", 
1076                                     NULL,         NULL};
1077   fileInfo.fFileTypes = fileTypes;
1078   new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fileInfo);
1079   if (!fileInfo.fFilename) return kFALSE;
1080
1081   // open the root file
1082   TFile* file = TFile::Open(fileInfo.fFilename);
1083   if (!file || !file->IsOpen()) {
1084     Int_t result;
1085     new TGMsgBox(gClient->GetRoot(), this, "Open",
1086                  "The file could not be opened.", 
1087                  kMBIconExclamation, kMBOk, &result);
1088     return kFALSE;
1089   }
1090
1091   // get the folder with the monitor histograms
1092   TFolder* folder = (TFolder*) file->Get("Monitor");
1093   if (!folder || !folder->InheritsFrom(TFolder::Class())) {
1094     Int_t result;
1095     new TGMsgBox(gClient->GetRoot(), this, "Open",
1096                  "The file does not contain monitor histograms.", 
1097                  kMBIconExclamation, kMBOk, &result);
1098     file->Close();
1099     delete file;
1100     return kFALSE;
1101   }
1102
1103   // replace the old folder with the new one
1104   file->Clear();
1105   file->Close();
1106   delete file;
1107   if (fFolder) delete fFolder;
1108   fFolder = folder;
1109   return kTRUE;
1110 }
1111
1112
1113 //_____________________________________________________________________________
1114 void AliMonitorClient::ViewToolBar(Bool_t visible)
1115 {
1116 // en- or disable the view of the tool bar
1117
1118   if (visible) {
1119     ShowFrame(fToolBarSep);
1120     ShowFrame(fToolBar);
1121     fMenuView->CheckEntry(kMenuViewToolBar);
1122   } else {
1123     HideFrame(fToolBarSep);
1124     HideFrame(fToolBar);
1125     fMenuView->UnCheckEntry(kMenuViewToolBar);
1126   }
1127 }
1128
1129 //_____________________________________________________________________________
1130 void AliMonitorClient::ViewTree(Bool_t visible)
1131 {
1132 // en- or disable the view of the tree
1133
1134   if (visible) {
1135     fHorizontalFrame->ShowFrame(fTreeFrame);
1136     fHorizontalFrame->ShowFrame(fTreeSplitter);
1137     fMenuView->CheckEntry(kMenuViewTree);
1138   } else {
1139     fHorizontalFrame->HideFrame(fTreeFrame);
1140     fHorizontalFrame->HideFrame(fTreeSplitter);
1141     fMenuView->UnCheckEntry(kMenuViewTree);
1142   }
1143 }
1144
1145 //_____________________________________________________________________________
1146 void AliMonitorClient::ViewDescription(Bool_t visible)
1147 {
1148 // en- or disable the view of the histogram description
1149
1150   if (visible) {
1151     fVerticalFrame->ShowFrame(fDescriptionFrame);
1152     fVerticalFrame->ShowFrame(fDescriptionSplitter);
1153     fMenuView->CheckEntry(kMenuViewDescription);
1154   } else {
1155     fVerticalFrame->HideFrame(fDescriptionFrame);
1156     fVerticalFrame->HideFrame(fDescriptionSplitter);
1157     fMenuView->UnCheckEntry(kMenuViewDescription);
1158   }
1159 }
1160
1161 //_____________________________________________________________________________
1162 void AliMonitorClient::ViewReference(Bool_t visible)
1163 {
1164 // en- or disable the view of the reference histos
1165
1166   if (visible) {
1167     AliMonitorHisto::SetDrawRef(kTRUE);
1168     fMenuView->CheckEntry(kMenuViewReference);
1169   } else {
1170     AliMonitorHisto::SetDrawRef(kFALSE);
1171     fMenuView->UnCheckEntry(kMenuViewReference);
1172   }
1173 }
1174
1175 //_____________________________________________________________________________
1176 void AliMonitorClient::ViewStatistics(Bool_t visible)
1177 {
1178 // en- or disable the view of the statistics box
1179
1180   if (visible) {
1181     gStyle->SetOptStat(1110);
1182     fMenuView->CheckEntry(kMenuViewStatistics);
1183   } else {
1184     gStyle->SetOptStat(0);
1185     fMenuView->UnCheckEntry(kMenuViewStatistics);
1186   }
1187 }
1188
1189
1190 //_____________________________________________________________________________
1191 Bool_t AliMonitorClient::AddFavorite()
1192 {
1193 // add the current histogram or folder to the list of favorites
1194
1195   if (!fCurrentItem || !fCurrentItem->GetParent()) return kFALSE;
1196
1197   // get the folder item
1198   TGListTreeItem* folderItem = fCurrentItem->GetParent();
1199   if (fCurrentItem->GetFirstChild()) folderItem = fCurrentItem;
1200
1201   Bool_t result = kFALSE;
1202
1203   // add a folder
1204   if (fCurrentItem->GetFirstChild()) {
1205     TGListTreeItem* histoItem = fCurrentItem->GetFirstChild();
1206     while (histoItem) {
1207       if (!GetItem(fFavoritesItem, folderItem->GetText(), 
1208                    histoItem->GetText(), kFALSE)) result = kTRUE;
1209       TGListTreeItem* item = GetItem(fFavoritesItem, folderItem->GetText(), 
1210                                      histoItem->GetText(), kTRUE);
1211       item->SetUserData(histoItem->GetUserData());
1212       histoItem = histoItem->GetNextSibling();
1213     }
1214
1215   // add a histo
1216   } else {
1217     if (!GetItem(fFavoritesItem, folderItem->GetText(), 
1218                  fCurrentItem->GetText(), kFALSE)) result = kTRUE;
1219     TGListTreeItem* item = GetItem(fFavoritesItem, folderItem->GetText(), 
1220                                    fCurrentItem->GetText(), kTRUE);
1221     item->SetUserData(fCurrentItem->GetUserData());
1222   }
1223
1224   if (result) gClient->NeedRedraw(fTree);
1225   return result;
1226 }
1227
1228 //_____________________________________________________________________________
1229 Bool_t AliMonitorClient::DeleteFavorite()
1230 {
1231 // delete the current histogram or folder from the list of favorites
1232
1233   // check that the current item is a favorites histo or folder
1234   if (!fCurrentItem || !fCurrentItem->GetParent()) return kFALSE;
1235   TGListTreeItem* base = fCurrentItem;
1236   while (base->GetParent()) base = base->GetParent();
1237   if (base != fFavoritesItem) return kFALSE;
1238
1239   // delete it
1240   TGListTreeItem* parent = fCurrentItem->GetParent();
1241   fTree->DeleteItem(fCurrentItem);
1242   fCurrentItem = NULL;
1243
1244   // delete the parent folder if it is empty now
1245   if (parent->GetParent() != NULL) {
1246     if (!parent->GetFirstChild()) fTree->DeleteItem(parent);
1247   }
1248
1249   gClient->NeedRedraw(fTree);
1250   return kTRUE;
1251 }
1252
1253 //_____________________________________________________________________________
1254 Bool_t AliMonitorClient::LoadFavorites(Bool_t dialog)
1255 {
1256 // load the list of favorites from a file
1257
1258   // display a file open dialog
1259   TGFileInfo fileInfo;
1260   static const char* fileTypes[] = {"Favorites files", "*.fav", 
1261                                     "All files",  "*", 
1262                                     NULL,         NULL};
1263   fileInfo.fFileTypes = fileTypes;
1264   fileInfo.fIniDir = StrDup(".");
1265   fileInfo.fFilename = StrDup(fFavoritesFileName.Data());
1266   if (dialog) {
1267     new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fileInfo);
1268     if (!fileInfo.fFilename) return kFALSE;
1269   }
1270
1271   // open the text file
1272   FILE* file = fopen(fileInfo.fFilename, "rt");
1273   if (!file) {
1274     Int_t result;
1275     new TGMsgBox(gClient->GetRoot(), this, "Load Favorites",
1276                  "The file could not be opened.", 
1277                  kMBIconExclamation, kMBOk, &result);
1278     return kFALSE;
1279   }
1280
1281   // delete the old favorites
1282   TGListTreeItem* favFolderItem = fFavoritesItem->GetFirstChild();
1283   while (favFolderItem) {
1284     TGListTreeItem* deleteItem = favFolderItem;
1285     favFolderItem = favFolderItem->GetNextSibling();
1286     fTree->DeleteItem(deleteItem);
1287   }
1288
1289   // scan the text file and add the favorites histos
1290   char buffer[256];
1291   while (!feof(file)) {
1292     if (fgets(buffer, 255, file) == NULL) break;
1293     char* folder = strtok(buffer, "/");
1294     char* item = strtok(NULL, "\n");
1295     if (item[strlen(item)-1] == '\n') item[strlen(item)-1] = 0;
1296     if (!folder || !item) continue;
1297
1298     AliMonitorHisto* histo = GetHisto(folder, item);
1299     TGListTreeItem* histoItem = GetItem(fFavoritesItem, folder, item, kTRUE);
1300     histoItem->SetUserData(histo);
1301   }
1302   fclose(file);
1303
1304   return kTRUE;
1305 }
1306
1307 //_____________________________________________________________________________
1308 Bool_t AliMonitorClient::SaveFavorites()
1309 {
1310 // save the list of favorites in a file with the name fFavoritesFileName
1311
1312   // if no file name is given use a default one
1313   if (fFavoritesFileName.IsNull()) {
1314     char* fileName = gSystem->ConcatFileName(gSystem->HomeDirectory(), 
1315                                              "AliMonitorClient.fav");
1316     fFavoritesFileName = fileName;
1317     free(fileName);
1318   }
1319
1320   // open the text file
1321   FILE* file = fopen(fFavoritesFileName.Data(), "wt");
1322   if (!file) {
1323     Int_t result;
1324     new TGMsgBox(gClient->GetRoot(), this, "Save Favorites",
1325                  "The file could not be opened.", 
1326                  kMBIconExclamation, kMBOk, &result);
1327     return kFALSE;
1328   }
1329
1330   // loop over folders
1331   TGListTreeItem* folderItem = fFavoritesItem->GetFirstChild();
1332   while (folderItem) {
1333
1334     // loop over histos
1335     TGListTreeItem* histoItem = folderItem->GetFirstChild();
1336     while (histoItem) {
1337
1338       // write the favorites
1339       if (fprintf(file, "%s/%s\n", folderItem->GetText(), 
1340                   histoItem->GetText()) <= 0) {
1341         Int_t result;
1342         new TGMsgBox(gClient->GetRoot(), this, "Save Favorites",
1343                      "An error occured while sving the favorites.", 
1344                      kMBIconExclamation, kMBOk, &result);
1345         fclose(file);
1346         return kFALSE;
1347       }
1348       histoItem = histoItem->GetNextSibling();
1349     }
1350
1351     folderItem = folderItem->GetNextSibling();
1352   }
1353
1354   fclose(file);
1355   AliInfo(Form("favorites saved to file %s", fFavoritesFileName.Data()));
1356   return kTRUE;
1357 }
1358
1359 //_____________________________________________________________________________
1360 Bool_t AliMonitorClient::SaveFavoritesAs()
1361 {
1362 // ask for a file name and save the favorites to this file
1363
1364   // display a save file dialog
1365   TGFileInfo fileInfo;
1366   static const char* fileTypes[] = {"Favorites files", "*.fav", 
1367                                     "All files",  "*", 
1368                                     NULL,         NULL};
1369   fileInfo.fFileTypes = fileTypes;
1370   fileInfo.fIniDir = StrDup(".");
1371   fileInfo.fFilename = StrDup(fFavoritesFileName.Data());
1372   new TGFileDialog(gClient->GetRoot(), this, kFDSave, &fileInfo);
1373   if (!fileInfo.fFilename) return kFALSE;
1374
1375   // save the favorites
1376   fFavoritesFileName = fileInfo.fFilename;
1377   return SaveFavorites();
1378 }
1379
1380
1381 //_____________________________________________________________________________
1382 Bool_t AliMonitorClient::LoadReference(Bool_t dialog)
1383 {
1384 // load reference histograms from a file
1385
1386   // display a file open dialog
1387   TGFileInfo fileInfo;
1388   static const char* fileTypes[] = {"ROOT files", "*.root", 
1389                                     "All files",  "*", 
1390                                     NULL,         NULL};
1391   fileInfo.fFileTypes = fileTypes;
1392   fileInfo.fIniDir = StrDup(".");
1393   fileInfo.fFilename = StrDup(fReferenceFileName.Data());
1394   if (dialog) {
1395     new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fileInfo);
1396     if (!fileInfo.fFilename) return kFALSE;
1397   }
1398
1399   // open the root file
1400   TFile* file = TFile::Open(fileInfo.fFilename);
1401   if (!file || !file->IsOpen()) {
1402     Int_t result;
1403     new TGMsgBox(gClient->GetRoot(), this, "Load Reference",
1404                  "The file could not be opened.", 
1405                  kMBIconExclamation, kMBOk, &result);
1406     return kFALSE;
1407   }
1408
1409   // get the folder with the monitor histograms
1410   TFolder* folder = (TFolder*) file->Get("Monitor");
1411   if (!folder || !folder->InheritsFrom(TFolder::Class())) {
1412     Int_t result;
1413     new TGMsgBox(gClient->GetRoot(), this, "Load Reference",
1414                  "The file does not contain monitor histograms.", 
1415                  kMBIconExclamation, kMBOk, &result);
1416     file->Close();
1417     delete file;
1418     return kFALSE;
1419   }
1420
1421   // replace the old reference folder with the new one
1422   fReferenceFileName = fileInfo.fFilename;
1423   file->Clear();
1424   file->Close();
1425   delete file;
1426   if (fReference) delete fReference;
1427   fReference = folder;
1428   return kTRUE;
1429 }
1430
1431 //_____________________________________________________________________________
1432 void AliMonitorClient::SetReference()
1433 {
1434 // set the reference histograms for all monitor histograms
1435
1436   // loop over folder
1437   TIterator* iFolder = fFolder->GetListOfFolders()->MakeIterator();
1438   while (TFolder* folder = (TFolder*) iFolder->Next()) {
1439     TFolder* refFolder = (TFolder*) fReference->FindObject(folder->GetName());
1440     if (!refFolder) continue;
1441
1442     // loop over histos
1443     TIterator* iHisto = folder->GetListOfFolders()->MakeIterator();
1444     while (AliMonitorHisto* histo = (AliMonitorHisto*) iHisto->Next()) {
1445       AliMonitorHisto* refHisto = 
1446         (AliMonitorHisto*) refFolder->FindObject(histo->GetName());
1447       if (!refHisto) continue;
1448       histo->SetReference(refHisto);
1449     }
1450     delete iHisto;
1451
1452   }
1453   delete iFolder;
1454 }
1455
1456 //_____________________________________________________________________________
1457 Bool_t AliMonitorClient::TakeCurrentReference()
1458 {
1459 // take the current monitor histogram or folder as reference
1460
1461   // check that a histo or folder is selected
1462   if (!fCurrentItem) return kFALSE;
1463   AliMonitorHisto* histo = (AliMonitorHisto*) fCurrentItem->GetUserData();
1464   if (!histo && !fCurrentItem->GetFirstChild()) return kFALSE;
1465
1466   // confirm-dialog
1467   char message[256];
1468   if (histo) {
1469     sprintf(message, "Do you want to take the current histogram %s/%s "
1470             "as reference histogram?", fCurrentItem->GetParent()->GetText(),
1471             histo->GetName());
1472   } else {
1473     sprintf(message, "Do you want to take all current histogram of the "
1474             "folder %s as reference histogram?", fCurrentItem->GetText());
1475   }
1476   Int_t result;
1477   new TGMsgBox(gClient->GetRoot(), this, "Take Current as Reference",
1478                message, kMBIconQuestion, kMBYes | kMBNo, &result);
1479   if (result != kMBYes) return kFALSE;
1480
1481   // take ...
1482   if (histo) {   // ... a histo
1483     TakeReferenceHisto(fCurrentItem->GetParent()->GetText(), histo);
1484   } else if (fCurrentItem->GetParent()) {  // ... a folder
1485     TakeReferenceFolder(fCurrentItem);
1486   } else {  // ... a top folder
1487     TGListTreeItem* folderItem = fCurrentItem->GetFirstChild();
1488     while (folderItem) {
1489       TakeReferenceFolder(folderItem);
1490       folderItem = folderItem->GetNextSibling();
1491     }
1492   }
1493   return kTRUE;
1494 }
1495
1496 //_____________________________________________________________________________
1497 void AliMonitorClient::TakeReferenceHisto(const char* folderName,
1498                                           AliMonitorHisto* histo)
1499 {
1500 // take the given monitor histogram as reference histogram
1501
1502   // get or create the reference folder
1503   TFolder* refFolder = (TFolder*) fReference->FindObject(folderName);
1504   if (!refFolder) refFolder = fReference->AddFolder(folderName, folderName);
1505
1506   // delete the old reference histo
1507   AliMonitorHisto* refHisto = 
1508     (AliMonitorHisto*) refFolder->FindObject(histo->GetName());
1509   if (refHisto) {
1510     refFolder->Remove(refHisto);
1511     delete refHisto;
1512   }
1513
1514   // add the new one and use it as reference
1515   refFolder->Add(new AliMonitorHisto(*histo));
1516   histo->SetReference(histo);
1517 }
1518
1519 //_____________________________________________________________________________
1520 void AliMonitorClient::TakeReferenceFolder(TGListTreeItem* item)
1521 {
1522 // take all monitor histogram in the given folder as reference histograms
1523
1524   // loop over histos
1525   TGListTreeItem* histoItem = item->GetFirstChild();
1526   while (histoItem) {
1527     AliMonitorHisto* histo = (AliMonitorHisto*) histoItem->GetUserData();
1528     if (histo) TakeReferenceHisto(item->GetText(), histo);
1529     histoItem = histoItem->GetNextSibling();
1530   }
1531 }
1532
1533 //_____________________________________________________________________________
1534 Bool_t AliMonitorClient::SaveReference()
1535 {
1536 // save the reference histograms to the file with name fReferenceFileName
1537
1538   // if no file name is given use a default one
1539   if (fFavoritesFileName.IsNull()) {
1540     char* fileName = gSystem->ConcatFileName(gSystem->HomeDirectory(), 
1541                                              "AliMonitorClientRef.root");
1542     fFavoritesFileName = fileName;
1543     free(fileName);
1544   }
1545
1546   // open the root file
1547   TFile* file = TFile::Open(fReferenceFileName, "RECREATE");
1548   if (!file || !file->IsOpen()) {
1549     Int_t result;
1550     new TGMsgBox(gClient->GetRoot(), this, "Save Reference",
1551                  "The file could not be opened.", 
1552                  kMBIconExclamation, kMBOk, &result);
1553     if (file) delete file;
1554     return kFALSE;
1555   }
1556
1557   // write the reference folder
1558   fReference->Write();
1559   file->Close();
1560   delete file;
1561   AliInfo(Form("reference histograms saved to file %s", 
1562                fReferenceFileName.Data()));
1563   return kTRUE;
1564 }
1565
1566 //_____________________________________________________________________________
1567 Bool_t AliMonitorClient::SaveReferenceAs()
1568 {
1569 // ask for a file name and save the reference histograms to this file
1570
1571   // display a save file dialog
1572   TGFileInfo fileInfo;
1573   static const char* fileTypes[] = {"ROOT files", "*.root", 
1574                                     "All files",  "*", 
1575                                     NULL,         NULL};
1576   fileInfo.fFileTypes = fileTypes;
1577   fileInfo.fIniDir = StrDup(".");
1578   fileInfo.fFilename = StrDup(fReferenceFileName.Data());
1579   new TGFileDialog(gClient->GetRoot(), this, kFDSave, &fileInfo);
1580   if (!fileInfo.fFilename) return kFALSE;
1581
1582   // save the references
1583   fReferenceFileName = fileInfo.fFilename;
1584   return SaveReference();
1585 }
1586
1587
1588 //_____________________________________________________________________________
1589 void AliMonitorClient::StopLoop()
1590 {
1591 // stop looping over histograms
1592
1593   // stop the timer and reset the loop button picture
1594   if (fLoopTimer) {
1595     fLoopTimer->TurnOff();
1596     delete fLoopTimer;
1597     fLoopTimer = NULL;
1598     ((TGPictureButton*) fLoopButton)->SetPicture(fLoopOnPicture);
1599   }
1600 }
1601
1602 //_____________________________________________________________________________
1603 void AliMonitorClient::LoadSettings()
1604 {
1605 // load setting from the file with the name fgSettingFileName and apply them
1606
1607   // open the text file
1608   char* fileName = gSystem->ConcatFileName(gSystem->HomeDirectory(), 
1609                                            fgSettingsFileName);
1610   FILE* file = fopen(fileName, "rt");
1611   if (!file) {
1612     free(fileName);
1613     return;
1614   }
1615
1616   // scan the text file and apply the settings
1617   char buffer[256];
1618   while (!feof(file)) {
1619     if (fgets(buffer, 255, file) == NULL) break;
1620     char* token = strtok(buffer, "=");
1621     char* value = strtok(NULL, "\n");
1622     if (!token || !value) continue;
1623     if (value[strlen(value)-1] == '\n') value[strlen(value)-1] = 0;
1624
1625     if (strcmp(token, "ServerName") == 0) {
1626       fServerName = value;
1627
1628     } else if (strcmp(token, "ViewToolBar") == 0) {
1629       ViewToolBar(strcmp(value, "0") != 0);
1630     } else if (strcmp(token, "ViewTree") == 0) {
1631       ViewTree(strcmp(value, "0") != 0);
1632     } else if (strcmp(token, "ViewDescription") == 0) {
1633       ViewDescription(strcmp(value, "0") != 0);
1634     } else if (strcmp(token, "ViewReference") == 0) {
1635       ViewReference(strcmp(value, "0") != 0);
1636     } else if (strcmp(token, "ViewStatistics") == 0) {
1637       ViewStatistics(strcmp(value, "0") != 0);
1638
1639     } else if (strcmp(token, "FavoritesFileName") == 0) {
1640       fFavoritesFileName = value;
1641       LoadFavorites(kFALSE);
1642     } else if (strcmp(token, "FavoritesSaveOnExit") == 0) {
1643       if (strcmp(value, "0") != 0) {
1644         fMenuFavorites->CheckEntry(kMenuFavSaveOnExit);
1645       } else {
1646         fMenuFavorites->UnCheckEntry(kMenuFavSaveOnExit);
1647       }
1648
1649     } else if (strcmp(token, "ReferenceFileName") == 0) {
1650       fReferenceFileName = value;
1651       LoadReference(kFALSE);
1652     } else if (strcmp(token, "ReferenceThreshold") == 0) {
1653       AliMonitorHisto::SetThreshold(atof(value));
1654
1655     } else if (strcmp(token, "LoopInterval") == 0) {
1656       fLoopInterval = atoi(value);
1657     } else if (strcmp(token, "PrintCommand") == 0) {
1658       fPrintCommand = value;
1659     } else if (strcmp(token, "SettingsSaveOnExit") == 0) {
1660       if (strcmp(value, "0") != 0) {
1661         fMenuOptions->CheckEntry(kMenuOptSaveOnExit);
1662       } else {
1663         fMenuOptions->UnCheckEntry(kMenuOptSaveOnExit);
1664       }
1665     }
1666   }
1667
1668   fclose(file);
1669   AliDebug(1, Form("settings from file %s applied", fileName));
1670   free(fileName);
1671 }
1672
1673 //_____________________________________________________________________________
1674 void AliMonitorClient::SaveSettings()
1675 {
1676 // save setting to the file with the name fgSettingFileName
1677
1678   // open the text file
1679   char* fileName = gSystem->ConcatFileName(gSystem->HomeDirectory(), 
1680                                            fgSettingsFileName);
1681   FILE* file = fopen(fileName, "wt");
1682   if (!file) {
1683     Int_t result;
1684     new TGMsgBox(gClient->GetRoot(), this, "Save Settings",
1685                  "The file could not be opened.", 
1686                  kMBIconExclamation, kMBOk, &result);
1687     free(fileName);
1688     return;
1689   }
1690
1691   // write the settings
1692   fprintf(file, "ServerName=%s\n", fServerName.Data());
1693
1694   fprintf(file, "ViewToolBar=%d\n", 
1695           fMenuView->IsEntryChecked(kMenuViewToolBar));
1696   fprintf(file, "ViewTree=%d\n", 
1697           fMenuView->IsEntryChecked(kMenuViewTree));
1698   fprintf(file, "ViewDescription=%d\n", 
1699           fMenuView->IsEntryChecked(kMenuViewDescription));
1700   fprintf(file, "ViewReference=%d\n", 
1701           fMenuView->IsEntryChecked(kMenuViewReference));
1702   fprintf(file, "ViewStatistics=%d\n", 
1703           fMenuView->IsEntryChecked(kMenuViewStatistics));
1704
1705   if (!fFavoritesFileName.IsNull()) {
1706     fprintf(file, "FavoritesFileName=%s\n", fFavoritesFileName.Data());
1707   }
1708   fprintf(file, "FavoritesSaveOnExit=%d\n", 
1709           fMenuFavorites->IsEntryChecked(kMenuFavSaveOnExit));
1710
1711   if (!fReferenceFileName.IsNull()) {
1712     fprintf(file, "ReferenceFileName=%s\n", fReferenceFileName.Data());
1713   }
1714   fprintf(file, "ReferenceThreshold=%.1f\n", AliMonitorHisto::GetThreshold());
1715
1716   fprintf(file, "LoopInterval=%d\n", fLoopInterval);
1717   fprintf(file, "PrintCommand=%s\n", fPrintCommand.Data());
1718   fprintf(file, "SettingsSaveOnExit=%d\n", 
1719           fMenuOptions->IsEntryChecked(kMenuOptSaveOnExit));
1720
1721   fclose(file);
1722   AliInfo(Form("settings saved to file %s", fileName));
1723   free(fileName);
1724 }
1725
1726
1727 //_____________________________________________________________________________
1728 Bool_t AliMonitorClient::GetBaseItem()
1729 {
1730 // get the base item for looping over histograms
1731
1732   if (fCurrentItem) {
1733     // the base item is a folder
1734     fBaseItem = fCurrentItem;
1735     // if the current item is a histo, its parent is the base folder
1736     if (fBaseItem->GetParent() && fBaseItem->GetParent()->GetParent()) {
1737       fBaseItem = fBaseItem->GetParent();
1738     }
1739
1740   } else {  // if no item is selected the All item is the base item
1741     fBaseItem = fAllItem;
1742     fCurrentItem = fBaseItem->GetFirstChild();
1743     if (!fCurrentItem) return kFALSE;
1744   }
1745
1746   return kTRUE;
1747 }
1748
1749 //_____________________________________________________________________________
1750 Bool_t AliMonitorClient::GoToNextItem()
1751 {
1752 // go to the next histogram in the loop
1753
1754   if (!fCurrentItem) return kFALSE;
1755   if (!fBaseItem || !fBaseItem->GetFirstChild()) return kFALSE;
1756
1757   // remember the start item to avoid an endless loop
1758   TGListTreeItem* startItem = fCurrentItem;
1759
1760   do {
1761     // folder -> first child
1762     if (fCurrentItem->GetFirstChild()) {
1763       fCurrentItem = fCurrentItem->GetFirstChild();
1764
1765     // histo -> next histo
1766     } else if ((fCurrentItem != fBaseItem) &&
1767                (fCurrentItem->GetNextSibling())) {
1768       fCurrentItem = fCurrentItem->GetNextSibling();
1769
1770     // last histo in folder -> next folder
1771     } else if ((fCurrentItem != fBaseItem) &&
1772                (fCurrentItem->GetParent() != fBaseItem) &&
1773                fCurrentItem->GetParent()->GetNextSibling()) {
1774       fCurrentItem = fCurrentItem->GetParent()->GetNextSibling();
1775
1776     // last histo in last folder -> first folder
1777     } else {
1778       fCurrentItem = fBaseItem->GetFirstChild();
1779     }
1780
1781     // abort if no next item found
1782     if (fCurrentItem == startItem) return kFALSE;
1783
1784   // end loop if an item with a monitor histo was found
1785   } while (!fCurrentItem->GetUserData());
1786
1787   UpdateItem(kTRUE);
1788   return kTRUE;
1789 }
1790
1791 //_____________________________________________________________________________
1792 Bool_t AliMonitorClient::GoToPreviousItem()
1793 {
1794 // go to the previous histogram in the loop
1795
1796   if (!fCurrentItem) return kFALSE;
1797   if (!fBaseItem || !fBaseItem->GetFirstChild()) return kFALSE;
1798
1799   // remember the start item to avoid an endless loop
1800   TGListTreeItem* startItem = fCurrentItem;
1801
1802   do {
1803     // folder -> last child
1804     if (fCurrentItem->GetFirstChild()) {
1805       fCurrentItem = fCurrentItem->GetFirstChild();
1806       while (fCurrentItem->GetNextSibling()) {
1807         fCurrentItem = fCurrentItem->GetNextSibling();
1808       }
1809
1810     // histo -> previous histo
1811     } else if ((fCurrentItem != fBaseItem) && 
1812                (fCurrentItem->GetPrevSibling())) {
1813       fCurrentItem = fCurrentItem->GetPrevSibling();
1814
1815     // first histo in folder -> previous folder
1816     } else if ((fCurrentItem != fBaseItem) && 
1817                (fCurrentItem->GetParent() != fBaseItem) &&
1818                fCurrentItem->GetParent()->GetPrevSibling()) {
1819       fCurrentItem = fCurrentItem->GetParent()->GetPrevSibling();
1820
1821     // first histo in first folder -> last folder
1822     } else {
1823       fCurrentItem = fBaseItem->GetFirstChild();
1824       while (fCurrentItem->GetNextSibling()) {
1825         fCurrentItem = fCurrentItem->GetNextSibling();
1826       }
1827     }
1828
1829     // abort if no next item found
1830     if (fCurrentItem == startItem) return kFALSE;
1831
1832   // end loop if an item with a monitor histo was found
1833   } while (!fCurrentItem->GetUserData());
1834
1835   UpdateItem(kTRUE);
1836   return kTRUE;
1837 }
1838
1839 //_____________________________________________________________________________
1840 void AliMonitorClient::UpdateItem(Bool_t highlight)
1841 {
1842 // update the displayed tree for currently selected item
1843
1844   if (highlight) {  // highlight the selected item and open its parent folders
1845     TGListTreeItem* parent = fCurrentItem->GetParent();
1846     while (parent) {
1847       if (!parent->IsOpen()) fTree->OpenItem(parent);
1848       parent = parent->GetParent();
1849     }
1850     fTree->HighlightItem(fCurrentItem);
1851     gClient->NeedRedraw(fTree);
1852   }
1853
1854   // update displayed histo
1855   UpdateDescription();
1856   UpdateHisto();
1857
1858   // en- or disable the "Reference/Take Current" menu item
1859   TGListTreeItem* base = fCurrentItem;
1860   while (base->GetParent()) base = base->GetParent();
1861   if (base != fComparisonItem) {
1862     fMenuReference->EnableEntry(kMenuRefTakeCurrent);
1863   } else {
1864     fMenuReference->DisableEntry(kMenuRefTakeCurrent);
1865   }
1866
1867   // en- or disable the "Favorites/Add" and "Favorites/Delete" menu items
1868   if (fCurrentItem->GetParent()) {
1869     if (base == fFavoritesItem) {
1870       fMenuFavorites->DisableEntry(kMenuFavAdd);
1871       fMenuFavorites->EnableEntry(kMenuFavDelete);
1872     } else {
1873       fMenuFavorites->EnableEntry(kMenuFavAdd);
1874       fMenuFavorites->DisableEntry(kMenuFavDelete);
1875     }
1876   } else {
1877     fMenuFavorites->DisableEntry(kMenuFavAdd);
1878     fMenuFavorites->DisableEntry(kMenuFavDelete);
1879   }
1880 }
1881
1882
1883 //_____________________________________________________________________________
1884 Bool_t AliMonitorClient::CheckForNewData()
1885 {
1886 // check whether the monitor process server sent new data
1887
1888   // disable the socket handler in this method
1889   if (!fSocket || !fSocket->IsValid()) return kFALSE;
1890   fSocketHandler->Remove();
1891
1892   // receive a control message from the server
1893   char controlMessage[256];
1894   if (fSocket->Recv(controlMessage, 255) <= 0) {
1895     fSocketHandler->Add();
1896     return kFALSE;
1897   }
1898
1899   // if it is new histogram data, send ok
1900   if ((strcmp(controlMessage, "histograms") != 0) ||
1901       (fSocket->Send("ok") <= 0)) {
1902     fSocketHandler->Add();
1903     return kFALSE;
1904   }
1905
1906   // get the histogram data
1907   TMessage* message = NULL;
1908   if (fSocket->Recv(message) <= 0) {
1909     fSocketHandler->Add();
1910     return kFALSE;
1911   }
1912
1913   // replace the old folder of monitor histos with the new one
1914   if (message->GetClass()->InheritsFrom(TFolder::Class())) {
1915     if (fFolder) delete fFolder;
1916     fFolder = (TFolder*) message->ReadObject(message->GetClass());
1917     delete message;
1918     fSocketHandler->Add();
1919     return kTRUE;
1920   }
1921
1922   delete message;
1923   fSocketHandler->Add();
1924   return kFALSE;
1925 }
1926
1927 //_____________________________________________________________________________
1928 void AliMonitorClient::ClearItems(TGListTreeItem* base) const
1929 {
1930 // remove the references to the histograms from all subitems of the 
1931 // given tree item
1932
1933   // loop over folders
1934   TGListTreeItem* folderItem = base->GetFirstChild();
1935   while (folderItem) {
1936
1937     // loop over histos
1938     TGListTreeItem* histoItem = folderItem->GetFirstChild();
1939     while (histoItem) {
1940       histoItem->SetUserData(NULL);
1941       histoItem = histoItem->GetNextSibling();
1942     }
1943
1944     folderItem = folderItem->GetNextSibling();
1945   }
1946 }
1947
1948 //_____________________________________________________________________________
1949 void AliMonitorClient::CleanUpTree(TGListTreeItem* base)
1950 {
1951 // remove items without monitor histograms and 
1952 // folders without monitor histograms
1953
1954   // loop over folders
1955   TGListTreeItem* folderItem = base->GetFirstChild();
1956   while (folderItem) {
1957
1958     // loop over histos
1959     TGListTreeItem* histoItem = folderItem->GetFirstChild();
1960     while (histoItem) {
1961       TGListTreeItem* deleteItem = NULL;
1962       if (!histoItem->GetUserData()) deleteItem = histoItem;
1963       histoItem = histoItem->GetNextSibling();
1964       if (fCurrentItem == deleteItem) fCurrentItem = NULL;
1965       if (deleteItem) fTree->DeleteItem(deleteItem);
1966     }
1967
1968     folderItem = folderItem->GetNextSibling();
1969   }
1970
1971   // loop over folders and remove empty folders
1972   folderItem = base->GetFirstChild();
1973   while (folderItem) {
1974     TGListTreeItem* deleteItem = NULL;
1975     if (!folderItem->GetFirstChild()) deleteItem = folderItem;
1976     folderItem = folderItem->GetNextSibling();
1977     if (fCurrentItem == deleteItem) fCurrentItem = NULL;
1978     if (deleteItem) fTree->DeleteItem(deleteItem);
1979   }
1980 }
1981
1982 //_____________________________________________________________________________
1983 void AliMonitorClient::UpdateTree()
1984 {
1985 // update the tree of monitor histograms
1986
1987   // delete references to old monitor histograms
1988   ClearItems(fAllItem);
1989
1990   // loop over folder
1991   TIterator* iFolder = fFolder->GetListOfFolders()->MakeIterator();
1992   while (TFolder* folder = (TFolder*) iFolder->Next()) {
1993
1994     // loop over histos
1995     TIterator* iHisto = folder->GetListOfFolders()->MakeIterator();
1996     while (AliMonitorHisto* histo = (AliMonitorHisto*) iHisto->Next()) {
1997
1998       // add new monitor histograms
1999       TGListTreeItem* histoItem = GetItem(fAllItem, folder->GetName(),
2000                                           histo->GetName(), kTRUE);
2001       histoItem->SetUserData(histo);
2002     }
2003     delete iHisto;
2004
2005   }
2006   delete iFolder;
2007
2008   // remove items and folders without monitor histograms
2009   CleanUpTree(fAllItem);
2010
2011   gClient->NeedRedraw(fTree);
2012 }
2013
2014 //_____________________________________________________________________________
2015 void AliMonitorClient::UpdateFavoritesTree()
2016 {
2017 // update the tree of favorite monitor histograms
2018
2019   // loop over folders
2020   TGListTreeItem* folderItem = fFavoritesItem->GetFirstChild();
2021   while (folderItem) {
2022
2023     // loop over histos
2024     TGListTreeItem* histoItem = folderItem->GetFirstChild();
2025     while (histoItem) {
2026
2027       // set monitor histo
2028       histoItem->SetUserData(GetHisto(folderItem->GetText(), 
2029                                       histoItem->GetText()));
2030       histoItem = histoItem->GetNextSibling();
2031     }
2032
2033     folderItem = folderItem->GetNextSibling();
2034   }
2035 }
2036
2037 //_____________________________________________________________________________
2038 void AliMonitorClient::UpdateComparisonTree()
2039 {
2040 // update the tree of monitor histograms with significant deviation
2041 // from the reference histograms
2042
2043   if (!fFolder) return;
2044
2045   // delete references to old monitor histograms
2046   ClearItems(fComparisonItem);
2047
2048   // add monitor histograms where the comparison returns a deviation
2049   // loop over folders
2050   TIterator* iFolder = fFolder->GetListOfFolders()->MakeIterator();
2051   while (TFolder* folder = (TFolder*) iFolder->Next()) {
2052
2053     // loop over histos
2054     TIterator* iHisto = folder->GetListOfFolders()->MakeIterator();
2055     while (AliMonitorHisto* histo = (AliMonitorHisto*) iHisto->Next()) {
2056
2057       // compare the histo to its reference
2058       Bool_t comparison = kTRUE;
2059       if (fEventButton->IsDown()) {
2060         comparison = histo->CompareEvent(fEventNumber->GetIntNumber());
2061       } else if (fSumButton->IsDown()) {
2062         comparison = histo->CompareSum(fEventNumber->GetIntNumber());
2063       } else {
2064         comparison = histo->CompareRun();
2065       }
2066
2067       // add it to the comparison tree in case of a bad comparison result
2068       if (!comparison) {
2069         TGListTreeItem* histoItem = GetItem(fComparisonItem, folder->GetName(),
2070                                             histo->GetName(), kTRUE);
2071         histoItem->SetUserData(histo);
2072       }
2073     }
2074     delete iHisto;
2075
2076   }
2077   delete iFolder;
2078
2079   // remove items and folders without monitor histograms
2080   CleanUpTree(fComparisonItem);
2081
2082   gClient->NeedRedraw(fTree);
2083 }
2084
2085 //_____________________________________________________________________________
2086 void AliMonitorClient::UpdateDescription()
2087 {
2088 // update the description of the current monitor histogram
2089
2090   fDescription->Clear();
2091   AliMonitorHisto* histo = NULL;
2092   if (fCurrentItem) histo = (AliMonitorHisto*) fCurrentItem->GetUserData();
2093   if (histo) fDescription->LoadBuffer(histo->GetDescription().Data());
2094
2095   gClient->NeedRedraw(fDescription);
2096 }
2097
2098 //_____________________________________________________________________________
2099 void AliMonitorClient::UpdateHisto()
2100 {
2101 // update the current monitor histogram
2102
2103   // clear the canvas if no histo is selected
2104   AliMonitorHisto* histo = NULL;
2105   if (fCurrentItem) histo = (AliMonitorHisto*) fCurrentItem->GetUserData();
2106   if (!histo) {
2107     fDrawCanvas->GetCanvas()->Clear();
2108     fDrawCanvas->GetCanvas()->Update();
2109     return;
2110   }
2111
2112   // draw the histo for a single event or summed over several events or a run
2113   fDrawCanvas->GetCanvas()->cd();
2114   if (fEventButton->IsDown()) {
2115     histo->DrawEvent(fEventNumber->GetIntNumber());
2116   } else if (fSumButton->IsDown()) {
2117     histo->DrawSum(fEventNumber->GetIntNumber());
2118   } else {
2119     histo->DrawRun();
2120   }
2121 }
2122
2123 //_____________________________________________________________________________
2124 void AliMonitorClient::UpdateAll()
2125 {
2126 // update the trees, the histogram and the description
2127
2128   UpdateTree();
2129   UpdateFavoritesTree();
2130   UpdateComparisonTree();
2131   UpdateDescription();
2132   UpdateHisto();
2133 }
2134