]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EVE/EveDet/AliEveListAnalyserEditor.cxx
- last version of the list analyser by Ben
[u/mrichter/AliRoot.git] / EVE / EveDet / AliEveListAnalyserEditor.cxx
1 // Author: Benjamin Hess   29/01/2010
2
3 /*************************************************************************
4  * Copyright (C) 2009-2010, Alexandru Bercuci, Benjamin Hess.            *
5  * All rights reserved.                                                  *
6  *************************************************************************/
7
8 //////////////////////////////////////////////////////////////////////////
9 //                                                                      //
10 // AliEveListAnalyserEditor                                             //
11 //                                                                      //
12 // The AliEveListAnalyserEditor provides the graphical func-            //
13 // tionality for the AliEveListAnalyser. It creates the tabs            //
14 // and canvases, when they are needed and, as well, frees allocated     //
15 // memory on destruction (or if new events are loaded and thus some     //
16 // tabs are closed).                                                    //
17 // The function DrawHistos() accesses the temporary file created by the //
18 // AliEveListAnalyser and draws the desired data (the file will         //
19 // be created within the call of ApplyMacros()). Have a look at this    //
20 // function to learn more about the structure of the file and how to    //
21 // access the data.                                                     //
22 // You can add objects to the list (of analysis objects) "by clicking"! //
23 // To do this, click the "start" button in the "list" tab. Pressing it, //
24 // connects the class to signals of objects in the viewer.              //
25 // You have to kinds of selection:                                      //
26 //                                                                      //
27 // Secondary selection:                                                 //
28 // You can hold "CTRL"+"ALT" (depending on your system, "ALT" alone can //
29 // also be fine) and click an single object (e.g. a single cluster of a //
30 // TEvePointSet) in the viewer to add it to the list. If the object is  //
31 // already in the list, it will be removed from it!                     //
32 //                                                                      //
33 // Primary selection:                                                   //
34 // Just click the object you want to add in the viewer (or as well in   //
35 // the browser (left panel)). If the object is already in the list, it  //
36 // will be removed from it!                                             //
37 //                                                                      //
38 // For both cases: Note:                                                //
39 // If you have added all the desired objects, please press the "stop"   //
40 // button in the "list" tab to disconnect the class from the signals.   //
41 // If you want to remove an object, you HAVE to use the same procedure  //
42 // that you have used for adding it. e.g. you cannot(!) remove an       //
43 // object added by the secondary selection method by using the primary  //
44 // selection method!                                                    //
45 //////////////////////////////////////////////////////////////////////////
46
47 #include <EveDet/AliEveListAnalyser.h>
48 #include "AliEveListAnalyserEditor.h"
49
50 #include <EveBase/AliEveEventManager.h>
51 #include <TCanvas.h>     
52 #include <TEveBrowser.h>
53 #include <TEveGedEditor.h> 
54 #include <TEveMacro.h>
55 #include <TEveManager.h>
56 #include <TFile.h>
57 #include <TG3DLine.h>
58 #include <TGButton.h>
59 #include <TGButtonGroup.h>
60 #include <TGComboBox.h>
61 #include <TGFileDialog.h>
62 #include <TGLabel.h>
63 #include <TGListBox.h>
64 #include <TGMsgBox.h>
65 #include <TGTab.h>
66 #include <TGTextEdit.h>
67 #include <TGTextEntry.h>
68 #include <TGTextView.h>
69 #include <TH1.h>
70 #include <TMap.h>
71 #include <TObjString.h>
72 #include <TROOT.h>
73 #include <TString.h>
74 #include <TSystem.h>
75 #include <TTreeStream.h>
76
77
78 ClassImp(AliEveListAnalyserEditor)
79
80 ///////////////////////////////////////////////////////////
81 /////////////   AliEveListAnalyserEditor //////////////////
82 ///////////////////////////////////////////////////////////
83 AliEveListAnalyserEditor::AliEveListAnalyserEditor(const TGWindow* p, Int_t width, Int_t height,
84                                                    UInt_t options, Pixel_t back) :
85   TGedFrame(p, width, height, options, back),
86   fM(0),
87   fHistoCanvas(0),
88   fHistoCanvasName(0),
89   fInheritedMacroList(0),
90   fInheritSettings(kFALSE),
91   fBrowseFrame(0),
92   fHistoFrame(0),
93   fHistoSubFrame(0),
94   fMainFrame(0),
95   fObjectFrame(0),  
96   //fbAddPrimObjects(0),
97   fbApplyMacros(0),
98   fbBrowse(0),
99   fbDrawHisto(0),
100   fbNew(0),
101   //fbRemovePrimObjects(0),
102   fbRemoveMacros(0),
103   fbReset(0),
104   fbStart(0),
105   fbStop(0),
106   fteField(0),
107   ftlMacroList(0),
108   ftlMacroSelList(0),
109   fFileInfo(0),
110   fFileTypes(0),
111   fLabel1(0), fLabel2(0), fLabel3(0), fLabel4(0),
112   fLine1(0), fLine2(0), fLine3(0), fLine4(0),
113   fCheckButtons(0)
114 {
115   // Creates the AliEveListAnalyserEditor.
116
117   // Functionality for adding objects
118   fObjectFrame = CreateEditorTabSubFrame("List");
119
120 /*
121   TGLabel* label = new TGLabel(fObjectFrame,"Add objects via primary selection:");
122   fObjectFrame->AddFrame(label);
123
124   fbAddPrimObjects = new TGTextButton(fObjectFrame, "Add selected object(s)");
125   fObjectFrame->AddFrame(fbAddPrimObjects, new TGLayoutHints(kLHintsLeft | kLHintsExpandX, 4, 1, 3, 1));
126   fbAddPrimObjects->SetToolTipText("TODO! - Use primary selection to add \"complete\" objects like tracks, tracklets etc.\nHold the CTRL-key for multiple selection.");
127   fbAddPrimObjects->Connect("Clicked()", "AliEveListAnalyserEditor", this, "DoAddPrimSelectedObjects()");
128
129   fbRemovePrimObjects = new TGTextButton(fObjectFrame, "Remove selected object(s)");
130   fObjectFrame->AddFrame(fbRemovePrimObjects, new TGLayoutHints(kLHintsLeft | kLHintsExpandX, 4, 1, 3, 1));
131   fbRemovePrimObjects->SetToolTipText("TODO! - Hold the CTRL-key for multiple selection");
132   fbRemovePrimObjects->Connect("Clicked()", "AliEveListAnalyserEditor", this, "DoRemovePrimSelectedObjects()");
133
134   TGHorizontal3DLine* line = new TGHorizontal3DLine(this, 194, 8);
135   fObjectFrame->AddFrame(line, new TGLayoutHints(kLHintsLeft  | kLHintsExpandX, 2, 2, 8, 8));
136 */
137
138   TGLabel* label = new TGLabel(fObjectFrame,"Add objects by clicking:");
139   fObjectFrame->AddFrame(label);
140
141   fbStart = new TGTextButton(fObjectFrame, "Start");
142   fObjectFrame->AddFrame(fbStart, new TGLayoutHints(kLHintsLeft | kLHintsExpandX, 4, 1, 3, 1));
143   fbStart->SetToolTipText("Start \"adding objects by clicking\":\n\nPrimary selection: Simply left-click an object in the viewer with your mouse to add it to the list analyser.\nIf you click an object that is already in the list, it will be removed from it.\n\nSecondary selection: Simply hold ALT+CTRL and left-click a single object of a TEvePointSet (e.g. single clusters or a single digit from TEveQuadSet)\nin the viewer with your mouse to add it to the list analyser.\nIf you click (in this way!) an object that is already in the list, it will be removed from it.\nNote: The key combination depends on your operating system and might be different!\n\nAlso note: Remove objects with the same type of selection you added them,\ne.g. you cannot(!) remove a single cluster added via secondary selection\nby using primary selection with this object!");
144   fbStart->Connect("Clicked()", "AliEveListAnalyserEditor", this, "DoStartAddingObjects()");
145
146   fbReset = new TGTextButton(fObjectFrame, "Reset");
147   fObjectFrame->AddFrame(fbReset, new TGLayoutHints(kLHintsLeft | kLHintsExpandX, 4, 1, 1, 1));
148   fbReset->SetToolTipText("Remove all(!) objects from the list");
149   fbReset->Connect("Clicked()", "AliEveListAnalyserEditor", this, "DoResetObjectList()");
150
151   fbStop = new TGTextButton(fObjectFrame, "Stop");
152   fObjectFrame->AddFrame(fbStop, new TGLayoutHints(kLHintsLeft | kLHintsExpandX, 4, 1, 1, 4));
153   fbStop->SetToolTipText("Stop \"adding objects by clicking\"");
154   fbStop->Connect("Clicked()", "AliEveListAnalyserEditor", this, "DoStopAddingObjects()");
155
156   // Functionality for adding macros  
157   fMainFrame = CreateEditorTabSubFrame("Process");
158    
159   fLabel1 = new TGLabel(fMainFrame,"Add plugin(s):");
160   fMainFrame->AddFrame(fLabel1);
161   fBrowseFrame = new TGHorizontalFrame(fMainFrame);
162
163   fteField = new TGTextEntry(fBrowseFrame);
164   fteField->SetToolTipText("Enter the pathname of the macro you want to add here and press \"Enter\"");
165   fteField->Connect("ReturnPressed()","AliEveListAnalyserEditor", this, "HandleMacroPathSet()"); 
166   fBrowseFrame->AddFrame(fteField);
167   
168   fbBrowse = new TGTextButton(fBrowseFrame, "Browse");
169   fbBrowse->SetToolTipText("Browse the macro you want to add");
170   fbBrowse->Connect("Clicked()", "AliEveListAnalyserEditor", this, "BrowseMacros()");
171   fBrowseFrame->AddFrame(fbBrowse);
172   
173   fbNew = new TGTextButton(fBrowseFrame, "New");
174   fbNew->SetToolTipText("Start macro creation wizard");
175   fbNew->Connect("Clicked()", "AliEveListAnalyserEditor", this, "NewMacros()");
176   fBrowseFrame->AddFrame(fbNew);
177   fMainFrame->AddFrame(fBrowseFrame);
178
179   fLine1 = new TGHorizontal3DLine(fMainFrame, 194, 8);
180   fMainFrame->AddFrame(fLine1, new TGLayoutHints(kLHintsLeft  | kLHintsTop, 2, 2, 8, 2));
181   fLabel2 = new TGLabel(fMainFrame,"Selection plugins:");
182   fMainFrame->AddFrame(fLabel2);
183
184   ftlMacroSelList = new TGListBox(fMainFrame);
185   ftlMacroSelList->Resize(194, 94);
186   ftlMacroSelList->SetMultipleSelections(kTRUE);
187   fMainFrame->AddFrame(ftlMacroSelList);
188
189   fLine2 = new TGHorizontal3DLine(fMainFrame, 194, 8);
190   fMainFrame->AddFrame(fLine2, new TGLayoutHints(kLHintsLeft  | kLHintsTop, 2, 2, 8, 2));
191   fLabel3 = new TGLabel(fMainFrame,"Process plugins:");
192   fMainFrame->AddFrame(fLabel3);
193
194   ftlMacroList = new TGListBox(fMainFrame);
195   ftlMacroList->Resize(194, 94);
196   ftlMacroList->SetMultipleSelections(kTRUE);
197   fMainFrame->AddFrame(ftlMacroList);
198
199   fLine3 = new TGHorizontal3DLine(fMainFrame, 194, 8);
200   fMainFrame->AddFrame(fLine3, new TGLayoutHints(kLHintsLeft  | kLHintsTop, 2, 2, 8, 2));  
201
202   fbApplyMacros = new TGTextButton(fMainFrame, "Apply plugin(s)");
203   fbApplyMacros->SetToolTipText("Apply all selected macros/class functins to the list of objects -> A data file will be generated");
204   fbApplyMacros->Connect("Clicked()", "AliEveListAnalyserEditor", this, "ApplyMacros()");
205   fbApplyMacros->SetRightMargin(12);
206   fMainFrame->AddFrame(fbApplyMacros);
207
208   fbRemoveMacros = new TGTextButton(fMainFrame, "Remove plugin(s)");
209   fbRemoveMacros->SetToolTipText("Remove the selected macros/class functions from the list(s)");
210   fbRemoveMacros->Connect("Clicked()", "AliEveListAnalyserEditor", this, "RemoveMacros()");
211   fMainFrame->AddFrame(fbRemoveMacros);
212
213   // Stuff for displaying histograms
214   fHistoFrame = CreateEditorTabSubFrame("Results");  
215   fHistoFrame->SetMapSubwindows(kTRUE);
216   fLabel4 = new TGLabel(fHistoFrame,"Data from plugins:");
217   fHistoFrame->AddFrame(fLabel4);
218
219   fHistoSubFrame = new TGVerticalFrame(fHistoFrame);
220   fHistoSubFrame->SetMapSubwindows(kTRUE);
221   fHistoSubFrame->Resize(194, 200);
222   fHistoFrame->AddFrame(fHistoSubFrame);
223
224   fLine4 = new TGHorizontal3DLine(fHistoFrame, 194, 8);
225   fHistoFrame->AddFrame(fLine4, new TGLayoutHints(kLHintsLeft  | kLHintsTop, 2, 2, 8, 2));  
226
227   fbDrawHisto = new TGTextButton(fHistoFrame, "Draw projections");
228   fbDrawHisto->SetToolTipText("Uses the data file created by the last \"Apply selected plugin(s)\".\nClick here to display the data histograms of the selected macros.\nSelect multiple macros to create multi-dimensional plots.\nHisto macros cannot be used for multi-dimensional plots!");
229   fbDrawHisto->Connect("Clicked()", "AliEveListAnalyserEditor", this, "DrawHistos()");
230   fHistoFrame->AddFrame(fbDrawHisto);
231
232   // Set up file dialog
233   fFileInfo = new TGFileInfo();
234   fFileInfo->SetMultipleSelection(kTRUE);
235
236   fFileTypes = new Char_t*[6];
237   fFileTypes[0] = (Char_t*)"All files"; fFileTypes[1] = (Char_t*)"*";
238   fFileTypes[2] = (Char_t*)"ROOT macros"; fFileTypes[3] = (Char_t*)"*.C";
239   fFileTypes[4] = 0; fFileTypes[5] = 0;
240   fFileInfo->fFileTypes = (const Char_t**)fFileTypes;
241   fFileInfo->fFileTypeIdx = 2;
242   fFileInfo->fMultipleSelection = kTRUE;
243
244   fHistoCanvasName = new TGString("");
245
246   // Handle the signal "Selected(Int_t ind)"
247   ftlMacroList->Connect("Selected(Int_t)", "AliEveListAnalyserEditor", this, "UpdateMacroListSelection(Int_t)");
248   ftlMacroSelList->Connect("Selected(Int_t)", "AliEveListAnalyserEditor", this, "UpdateMacroListSelection(Int_t)");
249
250   // Handle the signal "NewEventLoaded"
251   AliEveEventManager::GetMaster()->Connect("NewEventLoaded()", "AliEveListAnalyserEditor", this, "HandleNewEventLoaded()");
252
253   // Handle the signal "Selected" (another tab has been selected)
254   GetGedEditor()->GetTab()->Connect("Selected(Int_t)", "AliEveListAnalyserEditor", this, "HandleTabChangedToIndex(Int_t)");
255 }
256
257 //______________________________________________________
258 AliEveListAnalyserEditor::~AliEveListAnalyserEditor()
259 {
260   // Destructor: Closes all tabs created by this object and
261   // frees the corresponding memory.
262
263   if (fFileTypes != 0)
264   {
265     delete [] fFileTypes;
266     fFileTypes = 0;
267   }
268
269   if (fFileInfo != 0)
270   {
271     delete fFileInfo; 
272     fFileInfo = 0;
273   }
274   // Close and delete all tabs that have been created by this class
275   CloseTabs();
276
277   if (fHistoCanvasName != 0)
278   {
279     delete fHistoCanvasName;
280     fHistoCanvasName = 0;
281   }
282   
283   if (fInheritedMacroList != 0)
284   {
285     fInheritedMacroList->Delete();
286     delete fInheritedMacroList;
287     fInheritedMacroList = 0;
288   }
289 }
290
291 //______________________________________________________
292 void AliEveListAnalyserEditor::AddMacro(const Char_t* name, const Char_t* path)
293 {
294   // Adds the macro path/name to the macro list. A warning is provided, if there is
295   // something wrong, e.g. if the macro does not have the correct signature.
296   Int_t result = fM->AddMacro(path, name);
297
298   switch (result)
299   {
300   case SUCCESS:
301     UpdateMacroList();
302     break;
303   case WARNING:
304     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Warning", "Macro is already in list (won't be added again)!",
305                  kMBIconExclamation, kMBOk);
306     break;
307   case ERROR:
308     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", "Failed to load the macro (check messages in the terminal)!",
309                  kMBIconExclamation, kMBOk);
310     break;
311   case SIGNATURE_ERROR:
312     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
313                  "Macro has not the signature of...\n...a single object selection macro: Bool_t YourMacro(const YourObjectType*)\n...a correlated objects selection macro: Bool_t YourMacro(const YourObjectType*, const YourObjectType2*)\n...a single object analyse macro: void YourMacro(const YourObjectType*, Double_t*&, Int_t&)\n...a correlated objects analyse macro: void YourMacro(const YourObjectType*, const YourObjectType2*, Double_t*&, Int_t&)\n...a single object histo macro: TH1* YourMacro(const YourObjectType*)\n...a correlated objects histo macro: TH1* YourMacro(const YourObjectType*, const YourObjectType2*)", 
314                  kMBIconExclamation, kMBOk);
315     break;               
316   case NOT_EXIST_ERROR:
317     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
318                  "File does not exist or you do not have read permission!", kMBIconExclamation, kMBOk);
319     break;
320   case UNKNOWN_OBJECT_TYPE_ERROR:
321     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
322                  "Unknown object type of macro parameter!", kMBIconExclamation, kMBOk);
323     break;
324   default:
325     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
326                  Form("AliEveListAnalyser::AddMacro exited with unknown return value: %d", result),
327                  kMBIconExclamation, kMBOk);
328     break;
329   }
330 }
331
332 //______________________________________________________
333 void AliEveListAnalyserEditor::ApplyMacros()
334 {
335   // Applies the selected macros and updates the view.
336
337   Bool_t success = kFALSE;
338
339   // First apply the single object selection macros
340   TList* selIterator = new TList();
341   ftlMacroSelList->GetSelectedEntries(selIterator);
342   fM->ApplySOSelectionMacros(selIterator);
343   
344   // Update view
345   gEve->Redraw3D();
346
347   // Now apply the process macros
348   TList* procIterator = new TList();
349   ftlMacroList->GetSelectedEntries(procIterator);
350   success = fM->ApplyProcessMacros(selIterator, procIterator);
351
352   // Update histogram tab (data has to be reloaded)
353   SetModel(fM);
354   Update();
355
356   // AliEveListAnalyser::ApplyProcessMacros() automatically selects a macro -> Draw the histogram for it,
357   // if a process macro has been applied
358   if (success && procIterator->GetEntries() > 0) 
359   {
360     // Set focus on "Histograms" tab
361     GetGedEditor()->GetTab()->SetTab("Results");
362
363     DrawHistos();
364   }
365
366   if (selIterator != 0) delete selIterator;
367   selIterator = 0;  
368   if (procIterator != 0)  delete procIterator;  
369   procIterator = 0;  
370   
371   if (!success)
372   {
373     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
374                  "AliEveListAnalyser::ApplyProcessMacros experienced an error (cf. CINT-output)!", 
375                  kMBIconExclamation, kMBOk);  
376   }
377 }
378
379 //______________________________________________________
380 void AliEveListAnalyserEditor::BrowseMacros()
381 {
382   // Creates a file-dialog. The selected files will be added to the macro list
383   // via AddMacro(...).
384
385   new TGFileDialog(gClient->GetRoot(), GetMainFrame(), kFDOpen, fFileInfo);
386   
387   if (fFileInfo->fIniDir != 0 && fFileInfo->fFileNamesList != 0)
388   {       
389     // Extract filenames
390     TObject* iter = fFileInfo->fFileNamesList->First();
391  
392     Char_t* name = 0;
393
394     while (iter != 0)
395     {
396       // NOTE: fileInfo->fFileNamesList will be changed by that, too!
397       name = (Char_t*)strrchr(iter->GetName(), '/');
398       // Delete '"' at the end
399       name[strlen(name)] = '\0';
400               
401       AddMacro(name + 1, fFileInfo->fIniDir); 
402       iter = (TObjString*)fFileInfo->fFileNamesList->After(iter);
403     }
404   }
405 }
406
407 //______________________________________________________
408 void AliEveListAnalyserEditor::CloseTabs()
409 {
410   // Closes + deletes the tabs created by this object
411
412   if (fHistoCanvas != 0)
413   {
414     // Close the created tab, if it exists
415     if (fHistoCanvasName != 0)
416     {
417       if (gEve->GetBrowser()->GetTab(1)->SetTab(fHistoCanvasName->GetString()))
418       {
419         // Now the created tab is the current one and can be deleted
420         gEve->GetBrowser()->GetTab(1)->RemoveTab();
421       }
422     }
423     // With the tab removal, the canvas will be deleted automatically!
424     fHistoCanvas = 0;
425   }
426 }
427
428 /*
429 //______________________________________________________
430 void AliEveListAnalyserEditor::DoAddPrimSelectedObjects()
431 {
432   // Adds the selected object(s) to the list ("primary selection").
433
434   fM->AddPrimSelectedObjects();
435 }
436
437 //______________________________________________________
438 void AliEveListAnalyserEditor::DoRemovePrimSelectedObjects()
439 {
440   // Removes the selected object(s) from the list ("primary selection").
441
442   fM->RemovePrimSelectedObjects();
443 }
444 */
445
446 //______________________________________________________
447 void AliEveListAnalyserEditor::DoResetObjectList()
448 {
449   // Removes all objects from the list.
450
451   fM->ResetObjectList();
452   Update();
453 }
454
455 //______________________________________________________
456 void AliEveListAnalyserEditor::DoStartAddingObjects()
457 {
458   // Starts adding objects for the analysis.
459
460   if (fM->StartAddingObjects())
461   {
462     fbStart->SetState(kButtonDisabled);
463     fbStop->SetState(kButtonUp);
464   }
465   else
466   {
467     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", "Failed to connect socket!", kMBIconExclamation, kMBOk);
468
469     if (fM->GetConnected())
470     {
471       fbStop->SetState(kButtonDisabled);
472       fbStart->SetState(kButtonUp);
473     }
474   }
475 }
476
477 //______________________________________________________
478 void AliEveListAnalyserEditor::DoStopAddingObjects()
479 {
480   // Stops adding objects for the analysis.
481
482   if (fM->StopAddingObjects())
483   {
484     fbStop->SetState(kButtonDisabled);
485     fbStart->SetState(kButtonUp);
486   }
487   else
488   {
489     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", "Failed to disconnect socket!", kMBIconExclamation, kMBOk);
490     
491     if (fM->GetConnected())
492     {
493       fbStop->SetState(kButtonUp);
494       fbStart->SetState(kButtonDisabled);
495     }
496   }
497 }
498
499 //______________________________________________________
500 void AliEveListAnalyserEditor::DrawHistos()
501 {
502   // Accesses the temporary data file created by the last call of ApplyMacros() and draws
503   // histograms according to the selection in the "Histograms"-tab.
504  
505   Int_t nHistograms = GetNSelectedHistograms();
506   if (nHistograms <= 0)
507   {
508     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
509                  "No data selected. Please select the data you want to plot!", kMBIconExclamation, kMBOk);
510     return;
511   }
512   if (nHistograms > 3)
513   {
514     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), 
515                  "Error", "Only histograms with up to 3 dimensions supported. Please select 1,2 or 3 data macros!",
516                  kMBIconExclamation, kMBOk);
517     return;
518   }
519
520   // Check, if a histo macro shall be drawn
521   Int_t indexOfHistoMacro = -1;
522   Int_t selectedChecked = 0;
523   for (Int_t j = 0; j < fM->fDataFromMacroList->GetEntries(); j++)
524   {
525     if (fCheckButtons[j]->TGButton::GetState() == kButtonDown)
526     {
527       selectedChecked++;
528
529       // Histo macro? -> To check this, look for the substring "(histo macro)"
530       if (strstr(fM->fDataFromMacroList->At(j)->GetName(), "(histo macro)") != 0)
531       {
532         // Is also another macro selected?
533         if (nHistograms > 1)
534         {
535           // Histo macros cannot(!) be correlated!
536           new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
537                        "Histo macros (return value \"TH1*\") cannot be combined with other macros", 
538                        kMBIconExclamation, kMBOk);
539           return;        
540         }
541
542         // Mark this histo macro for drawing
543         indexOfHistoMacro = j;
544
545         // Have all selected macros been checked? -> If yes, we are done with this
546         if (selectedChecked == nHistograms)  break;
547       }
548     }
549   }
550
551   TFile* file = new TFile(Form("/tmp/ListAnalyserMacroData_%s.root", gSystem->Getenv("USER")), "READ");
552   if (!file)  
553   {
554     Error("Draw histograms", Form("Cannot open file \"/tmp/ListAnalyserMacroData_%s.root\"", 
555                                   gSystem->Getenv("USER")));
556     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
557                  Form("Cannot open file \"/tmp/ListAnalyserMacroData_%s.root\"", gSystem->Getenv("USER")),
558                  kMBIconExclamation, kMBOk);
559     return;
560   }
561   
562   TTree* t = 0;
563   TTree* tFriend1 = 0;
564   TTree* tFriend2 = 0;
565
566   Int_t indexOfMacro1 = 0;
567   Int_t indexOfMacro2 = 0;
568   Int_t indexOfMacro3 = 0;
569
570   // Variable for the loop below -> Will be set to aborting value, if a histo macro is drawn
571   Int_t i = 0;
572   
573   // Draw histo macro?
574   if (indexOfHistoMacro >= 0)
575   {
576     if ((t = (TTree*)file->Get(Form("ObjectData%d", indexOfHistoMacro))))
577     {
578       SetDrawingToHistoCanvasTab();
579  
580       TH1* myHist = 0;
581       t->SetBranchAddress(Form("Macro%d", indexOfHistoMacro), &myHist);
582       t->GetEntry(0);
583       if (myHist != 0)  myHist->Draw();
584       else
585       {
586         Error("Draw histograms", Form("No histogram for histo macro \"%s\" found!", 
587                                       fM->fDataFromMacroList->At(indexOfHistoMacro)->GetName()));
588         new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
589                      Form("No histogram for histo macro \"%s\" found!", 
590                           fM->fDataFromMacroList->At(indexOfHistoMacro)->GetName()), kMBIconExclamation, kMBOk);
591                
592       }
593
594       UpdateHistoCanvasTab();    
595     }
596     else
597     {
598       Error("Draw histograms", Form("No data for histo macro \"%s\" found!\nMaybe no objects have been selected.", 
599                                     fM->fDataFromMacroList->At(indexOfHistoMacro)->GetName()));
600       new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
601                    Form("No data for histo macro \"%s\" found!\nMaybe no objects have been selected.", 
602                         fM->fDataFromMacroList->At(indexOfHistoMacro)->GetName()), kMBIconExclamation, kMBOk);
603     }
604
605     // Skip the loop below
606     i = fM->fDataFromMacroList->GetEntries();
607   }
608
609   // Load the trees in succession and remember the entries -> Plot the analyse macros
610   for ( ; i < fM->fDataFromMacroList->GetEntries(); i++)
611   {
612     if (fCheckButtons[i]->TGButton::GetState() == kButtonDown)
613     {
614       if (t == 0)
615       {
616         indexOfMacro1 = i;
617         if (!(t = (TTree*)file->Get(Form("ObjectData%d", i))))
618         { 
619           Error("Draw histograms", Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
620                                         fM->fDataFromMacroList->At(i)->GetName()));
621           new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
622                        Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
623                             fM->fDataFromMacroList->At(i)->GetName()), kMBIconExclamation, kMBOk);
624           break;   
625         }
626
627         // 1d histogram
628         if (nHistograms == 1) 
629         {
630           SetDrawingToHistoCanvasTab();
631       
632           t->Draw(Form("Macro%d", indexOfMacro1), "1");
633           ((TH1*)gPad->GetPrimitive("htemp"))->SetTitle(Form("%s;%s",
634             fM->fDataFromMacroList->At(indexOfMacro1)->GetName(),
635             fM->fDataFromMacroList->At(indexOfMacro1)->GetName()));
636           UpdateHistoCanvasTab();        
637
638           break;     
639         }
640       }
641       else if (tFriend1 == 0)
642       {
643         indexOfMacro2 = i;
644         if (!(tFriend1 = (TTree*)file->Get(Form("ObjectData%d", i))))
645         { 
646           Error("Draw histograms", Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
647                                         fM->fDataFromMacroList->At(i)->GetName()));
648           new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
649                        Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
650                             fM->fDataFromMacroList->At(i)->GetName()),
651                             kMBIconExclamation, kMBOk);
652           break;   
653         }
654         
655         // 2d histogram
656         if (nHistograms == 2) 
657         {
658           SetDrawingToHistoCanvasTab();
659
660           t->AddFriend(tFriend1);
661           t->Draw(Form("Macro%d:Macro%d", indexOfMacro1, indexOfMacro2), "1");
662           ((TH1*)gPad->GetPrimitive("htemp"))->SetTitle(Form("%s - %s;%s;%s",
663             fM->fDataFromMacroList->At(indexOfMacro2)->GetName(),
664             fM->fDataFromMacroList->At(indexOfMacro1)->GetName(),
665             fM->fDataFromMacroList->At(indexOfMacro2)->GetName(),
666             fM->fDataFromMacroList->At(indexOfMacro1)->GetName()));
667
668           UpdateHistoCanvasTab();
669  
670           break;     
671         }
672       }    
673       // 3d histogram
674       else
675       {
676         indexOfMacro3 = i;
677         if (!(tFriend2 = (TTree*)file->Get(Form("ObjectData%d", i))))
678         { 
679           Error("Draw histograms", Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
680                                         fM->fDataFromMacroList->At(i)->GetName()));
681           new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
682                        Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
683                             fM->fDataFromMacroList->At(i)->GetName()), kMBIconExclamation, kMBOk);
684           break;   
685         }
686
687         SetDrawingToHistoCanvasTab();
688
689         t->AddFriend(tFriend1);
690         t->AddFriend(tFriend2);
691         t->Draw(Form("Macro%d:Macro%d:Macro%d", indexOfMacro1, indexOfMacro2, indexOfMacro3), "1");
692         ((TH1*)gPad->GetPrimitive("htemp"))->SetTitle(Form("%s - %s - %s;%s;%s;%s",
693             fM->fDataFromMacroList->At(indexOfMacro3)->GetName(),
694             fM->fDataFromMacroList->At(indexOfMacro2)->GetName(),
695             fM->fDataFromMacroList->At(indexOfMacro1)->GetName(),
696             fM->fDataFromMacroList->At(indexOfMacro3)->GetName(),
697             fM->fDataFromMacroList->At(indexOfMacro2)->GetName(),
698             fM->fDataFromMacroList->At(indexOfMacro1)->GetName()));
699         
700         UpdateHistoCanvasTab();
701  
702         break;     
703       }
704     }
705   }
706
707   if (t != 0) delete t;
708   t = 0;
709   if (tFriend1 != 0)  delete tFriend1;
710   tFriend1 = 0;
711   if (tFriend2 != 0)  delete tFriend2;
712   tFriend2 = 0;
713
714   file->Close("R");
715   delete file;
716   file = 0;
717 }
718
719 //______________________________________________________
720 Int_t AliEveListAnalyserEditor::GetNSelectedHistograms() const
721 {
722   // Returns the number of selected macros (or rather: of their selected data) in the "Histograms"-tab
723
724   Int_t count = 0;
725   
726   for (Int_t i = 0; i < fM->fDataFromMacroList->GetEntries(); i++)
727   {
728     if (fCheckButtons[i]->TGButton::GetState() == kButtonDown)  count++;
729   }
730
731   return count;
732 }
733
734 //______________________________________________________
735 void AliEveListAnalyserEditor::HandleMacroPathSet()
736 {
737   // Takes the input of the text field (adding a macro), checks if the macro can be
738   // accessed (and that it exists) and adds the macro to the macro list via AddMacro(...).
739   // You can use environment variables in the text field, e.g. "$ALICE_ROOT/Eve/alice-macro/myMacro.C".
740
741   if (strlen(fteField->GetText()) != 0)
742   {  
743     // Expand the pathname
744     Char_t* systemPath = gSystem->ExpandPathName(fteField->GetText());
745     fteField->SetText(systemPath);
746     delete systemPath;
747     systemPath = 0;
748                         
749     // Check if file exists
750     FILE* fp = NULL;
751
752     fp = fopen(fteField->GetText(), "rb");
753     if (fp != NULL)
754     {
755       fclose(fp);
756
757       // Extract filename
758       Char_t* name = (Char_t*)strrchr(fteField->GetText(), '/');
759
760       // Current path
761       if (name == NULL)
762       {
763         name = new Char_t[AliEveListAnalyser::fkMaxMacroNameLength];
764         memset(name, '\0', sizeof(Char_t) * AliEveListAnalyser::fkMaxMacroNameLength);
765         sprintf(name, "%s", fteField->GetText());
766
767         // Add path to textfield -> Path is "./" -> Use length for the name + 2
768         Char_t pathname[AliEveListAnalyser::fkMaxMacroNameLength + 2];
769         memset(pathname, '\0', sizeof(Char_t) * (AliEveListAnalyser::fkMaxMacroNameLength + 2));
770         sprintf(pathname, "./%s", fteField->GetText());
771         fteField->SetText(pathname);
772
773         AddMacro(name);  
774         if (name != 0)  delete name;
775         name = 0;
776       }
777       // Different path
778       else
779       {
780         // Extract path
781         Char_t* path = new Char_t[AliEveListAnalyser::fkMaxMacroPathLength];
782         memset(path, '\0', sizeof(Char_t) * AliEveListAnalyser::fkMaxMacroPathLength);
783         strncpy(path, fteField->GetText(), strlen(fteField->GetText()) - strlen(name));
784         
785         // Ignore the slash "/" in name
786         AddMacro(name + 1, path);  
787   
788         if (path != 0)  delete path;
789         path = 0;
790       }       
791     }
792     else
793     {
794       new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
795                    "File does not exist or you do not have read permission!", kMBIconExclamation, kMBOk);
796     }
797   }
798 }
799
800 //______________________________________________________
801 void AliEveListAnalyserEditor::HandleNewEventLoaded()
802 {
803   // Closes the tabs created by this object and sets a flag that will
804   // cause the function SetModel() to inherit the macro lists
805   // for the next AliEveListAnalyser from the current one.
806
807   // Inherit the macro list for the next analyse object list!
808   fInheritSettings = kTRUE;
809
810   // Close the tabs
811   CloseTabs();
812 }
813
814 //______________________________________________________
815 void AliEveListAnalyserEditor::HandleTabChangedToIndex(Int_t index)
816 {
817   // Saves the current tab in the current AliEveListAnalyser.
818
819   fM->SetSelectedTab(index);
820 }
821
822 //______________________________________________________
823 void AliEveListAnalyserEditor::InheritMacroList()
824 {
825   // The old macro list is possibly stored in the corresponding interior map. This function will 
826   // use this interior map to move the data from the interior map to the newly loaded AliEveListAnalyser. 
827   // Then the interior map will be cleaned up. With this, the settings will be inherited from the previously 
828   // loaded AliEveListAnalyser.
829
830   if (fInheritedMacroList == 0)  return;
831
832   // Clear list  
833   fM->fMacroList->Delete();
834
835   // Store data from interior list in the analyse object list's map
836   TMapIter* iter = (TMapIter*)fInheritedMacroList->MakeIterator();
837   
838   TObject* key = 0;
839   TGeneralMacroData* macro = 0;
840   
841   while ((key = iter->Next()) != 0)
842   {
843     macro = (TGeneralMacroData*)fInheritedMacroList->GetValue(key);
844     if (macro != 0)  fM->fMacroList->Add(new TObjString(key->GetName()), 
845                                          new TGeneralMacroData(macro->GetName(), macro->GetPath(), macro->GetType(), 
846                                                                macro->GetObjectType(), macro->GetObjectType2()));
847     else
848     {
849       Error("AliEveListAnalyserEditor::InheritMacroList", Form("Failed to inherit the macro \"%s\"!", key->GetName()));
850     }
851   }
852   
853   fInheritedMacroList->Delete();
854   delete fInheritedMacroList;
855   fInheritedMacroList = 0;
856 }
857
858 //______________________________________________________
859 void AliEveListAnalyserEditor::NewMacros()
860 {
861   // Start the macro creation wizard.
862   // thanks to Jacek Otwinowski<J.Otwinowski@GSI.DE> for this suggestion
863
864   AliEveGeneralMacroWizard *wizz = new AliEveGeneralMacroWizard();
865   wizz->Connect("Create(Char_t*)", "AliEveListAnalyserEditor", this, "AddMacro(Char_t*)");
866 }
867
868 //______________________________________________________
869 void AliEveListAnalyserEditor::RemoveMacros()
870 {
871   // Removes the selected macros from the corresponding list.
872
873   TList* iterator = new TList();
874   
875   ftlMacroList->GetSelectedEntries(iterator);
876   fM->RemoveSelectedMacros(iterator);
877
878   if (iterator != 0)  delete iterator;
879
880   iterator = new TList();
881   ftlMacroSelList->GetSelectedEntries(iterator);
882   fM->RemoveSelectedMacros(iterator);
883
884   // Selected macros are deleted from the list -> No selected entries left
885   fM->fMacroListSelected = 0;
886
887   UpdateMacroList();
888
889   if (iterator != 0)  delete iterator;
890   iterator = 0;
891 }
892
893 //______________________________________________________
894 void AliEveListAnalyserEditor::SaveMacroList(TMap* list)
895 {
896   // Saves the provided macro list in an interior list. This list will be used by
897   // InheritMacroList() to restore the data in "list". With this method one is able
898   // to inherit the macro list from analyse object list to analyse object list (i.e. from event to event).
899
900   if (fInheritedMacroList != 0)
901   {
902     fInheritedMacroList->Delete();
903     delete fInheritedMacroList;
904   }
905   fInheritedMacroList = new TMap();
906   fInheritedMacroList->SetOwnerKeyValue(kTRUE, kTRUE);
907
908   TMapIter* iter = (TMapIter*)list->MakeIterator();
909   TObject* key = 0;
910   TGeneralMacroData* macro = 0;
911   
912   while ((key = iter->Next()) != 0)
913   {
914     macro = (TGeneralMacroData*)fM->fMacroList->GetValue(key);
915     if (macro != 0) fInheritedMacroList->Add(new TObjString(key->GetName()), 
916                                              new TGeneralMacroData(macro->GetName(), macro->GetPath(), macro->GetType(), 
917                                                                    macro->GetObjectType(), macro->GetObjectType2()));
918     else
919     {
920       Error("AliEveListAnalyserEditor::SaveMacroList", Form("Failed to inherit the macro \"%s\"!", key->GetName()));
921     }
922   }
923 }
924
925 //______________________________________________________
926 void AliEveListAnalyserEditor::SetDrawingToHistoCanvasTab()
927 {
928   // Sets gPad to the tab with the name of the current AliEveListAnalyser. If this tab does
929   // not exist, it will be created. Otherwise, it is re-used.
930
931   // If the tab with the canvas has been closed, the canvas will be deleted.
932   // So, if there is no tab, set the canvas pointer to zero and recreate it in a new tab.
933   if (fHistoCanvas != 0) 
934   {
935     if (gEve->GetBrowser()->GetTab(1)->SetTab(fHistoCanvasName->GetString()) == 0)
936     {
937       fHistoCanvas = 0;
938     }
939   }
940
941   if (!fHistoCanvas)
942   {
943     fHistoCanvas = gEve->AddCanvasTab(fM->GetName());     
944   }
945                            
946   gPad = fHistoCanvas;
947 }
948
949 //______________________________________________________
950 void AliEveListAnalyserEditor::SetModel(TObject* obj)
951 {  
952   // Sets the model object, updates the related data in the GUI and
953   // inherits settings (cf. Inherit*(...)), if the flag fInheritSettings is set to kTRUE.
954
955   fM = dynamic_cast<AliEveListAnalyser*>(obj);
956
957   if (fM == 0) 
958   {
959     Error("SetModel", "Parameter is zero pointer");
960     return;
961   }
962
963   // Provide a pointer to this editor
964   fM->fEditor = this;
965
966   // If macro list + track style shall be inherited from previously loaded track list, do so
967   if (fInheritSettings)
968   {
969     InheritMacroList();
970
971     fInheritSettings = kFALSE;
972   }
973
974   UpdateMacroList();
975   UpdateHistoList(); 
976
977   // View correct tab
978   GetGedEditor()->GetTab()->SetTab(fM->GetSelectedTab()); 
979
980   // Set connection buttons correctly
981   if(fM->GetConnected())
982   {
983     fbStart->SetState(kButtonDisabled);
984     fbStop->SetState(kButtonUp);
985   }
986   else
987   {
988     fbStop->SetState(kButtonDisabled);
989     fbStart->SetState(kButtonEngaged);
990     fbStart->SetState(kButtonUp);
991   }
992 }
993
994 //______________________________________________________
995 void AliEveListAnalyserEditor::UpdateDataFromMacroListSelection()
996 {
997   // Saves the current selection in the "Histograms"-tab to the current
998   // AliEveListAnalyser. This means that the selection is updated and won't
999   // get lost, if another editor is loaded in Eve.
1000
1001   for (Int_t i = 0; i < fM->fDataFromMacroList->GetEntries(); i++)
1002   {
1003     fM->SetHistoDataSelection(i, fCheckButtons[i]->IsOn());
1004   }
1005 }
1006
1007 //______________________________________________________
1008 void AliEveListAnalyserEditor::UpdateHistoCanvasTab()
1009 {
1010   // Updates the histogram and the corresponding tab (including titles).
1011
1012   // Update name of the tab (tab has been set to current tab!)
1013   fHistoCanvasName->SetString(fM->GetName());  
1014
1015   // Use a copy of fHistoCanvasName!! -> If the user closes a tab manually, the TGString
1016   // will be deleted -> Error might occur, when accessing the pointer   
1017   gEve->GetBrowser()->GetTab(1)->GetCurrentTab()->SetText(new TGString(fHistoCanvasName));
1018
1019   // Switch tabs to force redrawing
1020   gEve->GetBrowser()->GetTab(1)->SetTab(0);
1021   gEve->GetBrowser()->GetTab(1)->SetTab(fHistoCanvasName->GetString());
1022   fHistoCanvas->Update();
1023 }
1024
1025 //______________________________________________________
1026 void AliEveListAnalyserEditor::UpdateHistoList()
1027 {
1028   // Reloads (updates) the buttons in the "Histograms"-tab via
1029   // the current AliEveListAnalyser (data).
1030
1031   fHistoSubFrame->TGCompositeFrame::Cleanup();
1032   
1033   // Set buttons for histograms
1034   if (fCheckButtons != 0) delete fCheckButtons;
1035   fCheckButtons = new TGCheckButton*[fM->fDataFromMacroList->GetEntries()];
1036   
1037   TObjString* iter = (TObjString*)fM->fDataFromMacroList->First();
1038   for (Int_t i = 0; i < fM->fDataFromMacroList->GetEntries() && iter != 0; i++)
1039   {
1040     fCheckButtons[i] = new TGCheckButton(fHistoSubFrame, iter->GetName());
1041     fHistoSubFrame->AddFrame(fCheckButtons[i]);
1042     
1043     fCheckButtons[i]->SetState(kButtonUp, kFALSE);
1044     fCheckButtons[i]->MapRaised();
1045     fCheckButtons[i]->SetOn(fM->HistoDataIsSelected(i));
1046     fCheckButtons[i]->Connect("Clicked()", "AliEveListAnalyserEditor", this, "UpdateDataFromMacroListSelection()");
1047             
1048     iter = (TObjString*)fM->fDataFromMacroList->After(iter);
1049   }  
1050 }
1051
1052 //______________________________________________________
1053 void AliEveListAnalyserEditor::UpdateMacroList()
1054 {
1055   // Reloads (updates) the macro list (selection AND process macros) via
1056   // the current AliEveListAnalyser (data).
1057
1058   ftlMacroList->RemoveAll();
1059   ftlMacroSelList->RemoveAll();
1060    
1061   TMapIter* iter = (TMapIter*)fM->fMacroList->MakeIterator();
1062   TObject* key = 0;
1063   TGeneralMacroData* macro = 0;
1064
1065   Int_t ind = 0;
1066   while ((key = iter->Next()) != 0)
1067   {
1068     macro = (TGeneralMacroData*)fM->fMacroList->GetValue(key);
1069     if (macro != 0)
1070     {
1071       if (macro->IsProcessMacro())
1072       {
1073         ftlMacroList->AddEntry(macro->GetName(), ind);
1074         // Select, what has been selected before
1075         ftlMacroList->Select(ind, fM->MacroListIsSelected(ind));
1076         ind++;
1077       }
1078       else if (macro->IsSelectionMacro())
1079       {
1080         ftlMacroSelList->AddEntry(macro->GetName(), ind);
1081         // Select, what has been selected before
1082         ftlMacroSelList->Select(ind, fM->MacroListIsSelected(ind));
1083         ind++;
1084       }
1085       else
1086       {
1087         Error("AliEveListAnalyserEditor::UpdateMacroList()", 
1088               Form("Macro \"%s/%s.C\" is neither a selection macro nor a process macro!",
1089                    macro->GetPath(), macro->GetName()));                                        
1090       }
1091     }
1092     else
1093     {
1094       Error("AliEveListAnalyserEditor::UpdateMacroList()", 
1095               Form("Macro list is corrupted: Macro \"%s\" not found!", key->GetName()));            
1096     }     
1097   }
1098
1099   ftlMacroList->SortByName(); 
1100   ftlMacroSelList->SortByName(); 
1101 }
1102
1103 //______________________________________________________
1104 void AliEveListAnalyserEditor::UpdateMacroListSelection(Int_t ind)
1105 {
1106   // Saves the current selection in the macro listS to the current
1107   // AliEveListAnalyser. This means that the selection is updated and won't
1108   // get lost, if another editor is loaded in Eve.
1109   // NOTE: The indices in BOTH lists will be unique!
1110
1111   // Toggle selected item
1112   fM->SetMacroListSelection(ind, !fM->MacroListIsSelected(ind));
1113 }
1114
1115
1116 //______________________________________________________
1117 //______________________________________________________
1118 //______________________________________________________
1119
1120
1121 /////////////////////////////////////////////////
1122 ClassImp(AliEveGeneralMacroWizard)
1123 /////////////////////////////////////////////////
1124
1125 //______________________________________________________
1126 AliEveGeneralMacroWizard::AliEveGeneralMacroWizard(const TGWindow* p)
1127   :TGMainFrame(p ? p : gClient->GetRoot(), 10, 10, kMainFrame | kVerticalFrame)
1128   ,fbCancel(0x0)
1129   ,fbCreate(0x0)
1130   ,fCombo(0x0)
1131   ,fTextEdit(0x0)
1132   ,fTextIncludes(0x0)
1133   ,fTextName(0x0)  
1134   ,fTextObjectType(0x0)
1135   ,fTextObjectType2(0x0)
1136 {
1137   // Creates the macro wizard.
1138
1139   const Int_t width = 300;
1140
1141   // horizontal frame
1142   TGHorizontalFrame *fFrameName = new TGHorizontalFrame(this, 10, 10, kHorizontalFrame);
1143   TGLabel *fLabel = new TGLabel(fFrameName, "Name*");
1144   fLabel->SetTextJustify(36);
1145   fLabel->SetMargins(0,0,0,0);
1146   fLabel->SetWrapLength(-1);
1147   fFrameName->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
1148
1149   fTextName = new TGTextEntry(fFrameName);
1150   fTextName->SetMaxLength(255);
1151   fTextName->SetAlignment(kTextLeft);
1152   fTextName->SetText("");
1153   fTextName->SetToolTipText("The name of your macro");
1154   fTextName->Resize(width, fTextName->GetDefaultHeight());
1155   fFrameName->AddFrame(fTextName, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2));
1156
1157   // horizontal frame
1158   TGHorizontalFrame *fFrameObjectType = new TGHorizontalFrame(this, 10, 10, kHorizontalFrame);
1159   fLabel = new TGLabel(fFrameObjectType, "1st object type of macro");
1160   fLabel->SetTextJustify(36);
1161   fLabel->SetMargins(0,0,0,0);
1162   fLabel->SetWrapLength(-1);
1163   fFrameObjectType->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
1164
1165   fTextObjectType = new TGTextEntry(fFrameObjectType);
1166   fTextObjectType->SetAlignment(kTextLeft);
1167   fTextObjectType->SetText("");
1168   // Limit max.length to 80 characters
1169   fTextObjectType->SetMaxLength(80);
1170   fTextObjectType->SetToolTipText("The type of objects, your macro will work with (type of the first pointer)");
1171   fTextObjectType->Resize(width, fTextObjectType->GetDefaultHeight());
1172   fFrameObjectType->AddFrame(fTextObjectType, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2));
1173
1174    // horizontal frame
1175   TGHorizontalFrame *fFrameObjectType2 = new TGHorizontalFrame(this, 10, 10, kHorizontalFrame);
1176   fLabel = new TGLabel(fFrameObjectType2, "2nd object type of macro (pair");
1177   fLabel->SetTextJustify(36);
1178   fLabel->SetMargins(0,0,0,0);
1179   fLabel->SetWrapLength(-1);
1180   fFrameObjectType2->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
1181
1182   fTextObjectType2 = new TGTextEntry(fFrameObjectType2);
1183   fTextObjectType2->SetAlignment(kTextLeft);
1184   fTextObjectType2->SetText("");
1185   // Limit max.length to 80 characters
1186   fTextObjectType2->SetMaxLength(80);
1187   fTextObjectType2->SetToolTipText("The type of objects, your macro will work with (type of the second pointer)\nOnly needed for macros dealing with object pairs");
1188   fTextObjectType2->Resize(width, fTextObjectType2->GetDefaultHeight());
1189   fFrameObjectType2->AddFrame(fTextObjectType2, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2));
1190   fTextObjectType2->SetEnabled(kFALSE);
1191
1192   // horizontal frame
1193   TGHorizontalFrame *fFrameIncludes = new TGHorizontalFrame(this,10,10,kHorizontalFrame);
1194   fLabel = new TGLabel(fFrameIncludes, "Include files");
1195   fLabel->SetTextJustify(36);
1196   fLabel->SetMargins(0,0,0,0);
1197   fLabel->SetWrapLength(-1);
1198   fFrameIncludes->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
1199
1200   fTextIncludes = new TGTextEntry(fFrameIncludes);
1201   fTextObjectType->SetAlignment(kTextLeft);
1202   fTextIncludes->SetText("<TRD/AliTRDgeometry.h>,<TRD/AliTRDcluster.h>,<TRD/AliTRDseedV1.h>,<TRD/AliTRDtrackV1.h>");
1203   fTextIncludes->SetCursorPosition(0);
1204   fTextIncludes->SetToolTipText("The include files for your macro - separated by commas! -\n e.g. \"<TRD/AliTRDcluster.h>,<TRD/AliTRDtrackV1.h>\".\nThe suggested/default files can be used for track analysis");
1205   fTextIncludes->Resize(width, fTextIncludes->GetDefaultHeight());
1206   fFrameIncludes->AddFrame(fTextIncludes, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2));
1207
1208   // horizontal frame
1209   TGHorizontalFrame *fFrameComment = new TGHorizontalFrame(this,10,10,kHorizontalFrame);
1210   fLabel = new TGLabel(fFrameComment, "Comment");
1211   fLabel->SetTextJustify(36);
1212   fLabel->SetMargins(0,0,0,0);
1213   fLabel->SetWrapLength(-1);
1214   fFrameComment->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
1215
1216   fTextEdit = new TGTextEdit(fFrameComment, width, 5*fTextName->GetDefaultHeight());
1217   fFrameComment->AddFrame(fTextEdit, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2));
1218
1219   // horizontal frame
1220   TGHorizontalFrame *fFrameType = new TGHorizontalFrame(this,10,10,kHorizontalFrame);
1221   fLabel = new TGLabel(fFrameType, "Type*");
1222   fLabel->SetTextJustify(36);
1223   fLabel->SetMargins(0,0,0,0);
1224   fLabel->SetWrapLength(-1);
1225   fFrameType->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
1226
1227   fCombo = new TGComboBox(fFrameType, -1, kHorizontalFrame | kSunkenFrame | kDoubleBorder | kOwnBackground);
1228   fCombo->AddEntry("Single Object Selection", AliEveListAnalyser::kSingleObjectSelect);
1229   fCombo->AddEntry("Pair Objects Selection", AliEveListAnalyser::kCorrelObjectSelect);
1230   fCombo->AddEntry("Single Object Analyse", AliEveListAnalyser::kSingleObjectAnalyse);
1231   fCombo->AddEntry("Single Object Histo", AliEveListAnalyser::kSingleObjectHisto);
1232   fCombo->AddEntry("Pair Objects Analyse", AliEveListAnalyser::kCorrelObjectAnalyse);
1233   fCombo->AddEntry("Pair Objects Histo", AliEveListAnalyser::kCorrelObjectHisto);
1234   fCombo->Select(-1);
1235   fCombo->Resize(width, fTextName->GetDefaultHeight());
1236   fFrameType->AddFrame(fCombo, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2));
1237
1238   // horizontal frame
1239   TGHorizontalFrame *fFrameAction = new TGHorizontalFrame(this,10,10,kHorizontalFrame);
1240   fbCancel = new TGTextButton(fFrameAction, "Cancel");
1241   fbCancel->SetToolTipText("Exit macro creation wizard");
1242   fFrameAction->AddFrame(fbCancel, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2)); 
1243   fbCreate = new TGTextButton(fFrameAction, "Done");
1244   fbCreate->SetToolTipText("Use settings to create the macro");
1245   fFrameAction->AddFrame(fbCreate, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2)); 
1246
1247   // horizontal frame
1248   TGHorizontalFrame *fFrameText = new TGHorizontalFrame(this,10,10,kHorizontalFrame);
1249   fLabel = new TGLabel(fFrameText, "(*) Mandatory fields");
1250   fLabel->SetTextJustify(36);
1251   fLabel->SetMargins(0,0,0,0);
1252   fLabel->SetWrapLength(-1);
1253   fFrameText->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
1254
1255   // put things together  
1256   AddFrame(fFrameName, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
1257   AddFrame(fFrameObjectType, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
1258   AddFrame(fFrameObjectType2, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
1259   AddFrame(fFrameIncludes, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
1260   AddFrame(fFrameComment, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
1261   AddFrame(fFrameType, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
1262   AddFrame(fFrameAction, new TGLayoutHints(kLHintsRight | kLHintsTop | kLHintsExpandX,2,2,2,2));
1263
1264   TGHorizontal3DLine *fLine = new TGHorizontal3DLine(this, 281, 2);
1265   AddFrame(fLine, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
1266   AddFrame(fFrameText, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
1267
1268
1269   SetWindowName("Macro Wizard");
1270   SetMWMHints(kMWMDecorAll,
1271               kMWMFuncAll,
1272               kMWMInputModeless);
1273   MapSubwindows();
1274
1275   Resize(GetDefaultSize());
1276   MapWindow();
1277
1278   // Do the linking
1279   fCombo->Connect("Selected(Int_t)", "AliEveGeneralMacroWizard", this, "HandleSelectionChanged(Int_t)");
1280   fbCreate->Connect("Clicked()", "AliEveGeneralMacroWizard", this, "HandleCreate()");
1281   fbCancel->Connect("Clicked()", "AliEveGeneralMacroWizard", this, "CloseWindow()");
1282
1283   // Standard choice
1284   fCombo->Select(1, kFALSE);
1285 }  
1286
1287 const Char_t *fGeneralIncludes = 
1288 "#if !defined(__CINT__) || defined(__MAKECINT__)\n"
1289 "#include <TROOT.h>\n"
1290 "#include <TH1.h>\n";
1291
1292 const Char_t *fGeneralMacroTemplate[7] = {
1293 ""
1294 ,"  if (!object) return kFALSE;\n"
1295
1296 ,"  n = 0;\n"
1297 "  r = 0x0;\n"
1298 "  if (!object) return;\n"
1299
1300 ,"  if (!object) return 0x0;\n"
1301 "  TH1* h = 0x0;\n\n"
1302 "// Set bins, xmin and xmax here\n"
1303 "  Int_t n = 1;\n"
1304 "  Double_t xmin = 0;\n"
1305 "  Double_t xmax = 100;\n\n" 
1306 "  if(!(h = (TH1*)gROOT->FindObject(\"h\"))){\n"
1307 "    h = new TH1(\"h\", \"Title\", n, xmin, xmax);\n"
1308 "    h->GetXaxis()->SetTitle("");\n"
1309 "    h->GetYaxis()->SetTitle("");\n"
1310 "  } else h->Reset();\n"
1311
1312 ,"  if (!object) return kFALSE;\n"
1313 "  if (!object2) return kFALSE;\n"
1314
1315 ,"  n = 0;\n"
1316 "  r = 0x0;\n"
1317 "  if (!object) return;\n"
1318 "  if (!object2) return;\n"
1319
1320 ,"  if (!object) return 0x0;\n"
1321 "  if (!object2) return 0x0;\n"
1322 "  TH1* h = 0x0;\n\n"
1323 "// Set bins, xmin and xmax here\n"
1324 "  Int_t n = 1;\n"
1325 "  Double_t xmin = 0;\n"
1326 "  Double_t xmax = 100;\n\n" 
1327 "  if(!(h = (TH1*)gROOT->FindObject(\"h\"))){\n"
1328 "    h = new TH1(\"h\", \"Title\", n, xmin, xmax);\n"
1329 "    h->GetXaxis()->SetTitle("");\n"
1330 "    h->GetYaxis()->SetTitle("");\n"
1331 "  } else h->Reset();\n"
1332 };
1333
1334 //______________________________________________________
1335 void AliEveGeneralMacroWizard::Create(Int_t type)
1336 {
1337   // Creates the macro with the selected type (combo box).
1338
1339   const Char_t* name = fTextName->GetText();
1340   if(strcmp(name,"") == 0)
1341   {
1342     Error("AliEveGeneralMacroWizard::Create", "Please specify a name for your macro.");
1343     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
1344                  "Please specify a name for your macro.", kMBIconExclamation, kMBOk);
1345     return;
1346   }
1347
1348   Bool_t useGivenType = kFALSE;
1349   Bool_t useGivenType2 = kFALSE;
1350
1351   // Remove white-spaces
1352   TString* typeStr = new TString();
1353
1354   typeStr->Append(fTextObjectType->GetText());
1355   typeStr->ReplaceAll(" ", "");
1356   fTextObjectType->SetText(typeStr->Data(), kFALSE);
1357
1358   TString* typeStr2 = new TString();
1359
1360   typeStr2->Append(fTextObjectType2->GetText());
1361   typeStr2->ReplaceAll(" ", "");
1362   fTextObjectType2->SetText(typeStr2->Data(), kFALSE);
1363
1364   // If an object type is provided by the user, use it!
1365   if (strlen(typeStr->Data()) > 0)
1366   {
1367     // Check, if the class really exists
1368     if (TClass::GetClass(typeStr->Data()) != 0x0)
1369     {
1370       useGivenType = kTRUE; 
1371     }
1372     else
1373     {
1374       Int_t buttonsPressed = 0;
1375       new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Unknown object type", 
1376         Form("The class of your 1st object, \"%s\" has not been found. Do you really want to create your macro with this object type?", 
1377              typeStr->Data()), kMBIconExclamation, kMBYes | kMBNo, &buttonsPressed);
1378
1379       if (buttonsPressed & kMBYes)  useGivenType = kTRUE;
1380       else useGivenType = kFALSE;
1381
1382       // Cancel creation
1383       if (!useGivenType)
1384       {
1385         if (typeStr != 0)
1386         {
1387           typeStr->Clear();
1388           delete typeStr;
1389         }
1390         typeStr = 0;
1391
1392         if (typeStr2 != 0)
1393         {
1394           typeStr2->Clear();
1395           delete typeStr2;
1396         }
1397         typeStr2 = 0;
1398
1399         return;
1400       }
1401     }
1402   }
1403
1404   // If an object type is provided by the user, use it!
1405   if (strlen(typeStr2->Data()) > 0)
1406   {
1407     // Check, if the class really exists
1408     if (TClass::GetClass(typeStr2->Data()) != 0x0)
1409     {
1410       useGivenType2 = kTRUE; 
1411     }
1412     else
1413     {
1414       Int_t buttonsPressed = 0;
1415       new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Unknown object type", 
1416         Form("The class of your 2nd object, \"%s\" has not been found. Do you really want to create your macro with this object type?", 
1417              typeStr2->Data()), kMBIconExclamation, kMBYes | kMBNo, &buttonsPressed);
1418
1419       if (buttonsPressed & kMBYes)  useGivenType2 = kTRUE;
1420       else useGivenType2 = kFALSE;
1421
1422       // Cancel creation
1423       if (!useGivenType2)
1424       {
1425         if (typeStr != 0)
1426         {
1427           typeStr->Clear();
1428           delete typeStr;
1429         }
1430         typeStr = 0;
1431
1432         if (typeStr2 != 0)
1433         {
1434           typeStr2->Clear();
1435           delete typeStr2;
1436         }
1437         typeStr2 = 0;
1438
1439         return;
1440       }
1441     }
1442   }
1443
1444   // Note: gSystem->AccessPathName(...) returns kTRUE, if the access FAILED!
1445   if(!gSystem->AccessPathName(Form("./%s.C", name)))
1446   {
1447     // If there is already a file with this name -> Error
1448     Error("AliEveGeneralMacroWizard::Create", Form("A macro \"%s.C\" already exists in the current directory!\nPlease choose another name!", name));
1449     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
1450                  Form("A macro \"%s.C\" already exists in the current directory!\nPlease choose another name!", name), kMBIconExclamation, kMBOk);
1451     return;
1452   }
1453
1454   FILE* fp = 0x0;
1455   if(!(fp = fopen(Form("%s.C", name), "wt"))){
1456     Error("AliEveGeneralMacroWizard::Create", "Couldn't create macro file.");
1457     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
1458                  "Couldn't create macro file.", kMBIconExclamation, kMBOk);
1459     return;
1460   }
1461
1462   TGText* comment = fTextEdit->GetText();
1463   Char_t* line = 0x0; Int_t iline = 0;
1464   while((line = comment->GetLine(TGLongPosition(0,iline++), 200))) fprintf(fp, "// %s\n", line);
1465
1466   TString* tempStr = new TString();
1467
1468   // Add include files:
1469   // Remove white-spaces and replace commas
1470   tempStr->Append(fTextIncludes->GetText());  
1471   tempStr->ReplaceAll(" ", "");
1472   tempStr->ReplaceAll(",","\n#include ");
1473   // If there are files, add the first "#include " in front
1474   if (tempStr->Length() > 3)  tempStr->Prepend("#include "); 
1475
1476   fprintf(fp, "\n%s%s\n#endif\n\n", fGeneralIncludes, tempStr->Data());
1477   
1478   tempStr->Clear();
1479
1480   // Use default type
1481   if (!useGivenType)
1482   {
1483     typeStr->Clear();
1484     typeStr->Append("TObject");
1485   }
1486   if (!useGivenType2)
1487   {
1488     typeStr2->Clear();
1489     typeStr2->Append("TObject");
1490   }
1491
1492   switch(type){
1493   case AliEveListAnalyser::kSingleObjectSelect:
1494     // Use "Bool_t 'NAME'(const 'OBJECTTYPE' *object)\n"
1495     tempStr->Append("Bool_t ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object)\n");
1496     fprintf(fp, tempStr->Data());
1497     break;
1498   case AliEveListAnalyser::kCorrelObjectSelect:
1499     // Use "Bool_t 'NAME'(const 'OBJECTTYPE' *object, const 'OBJECTTYPE2' *object2)\n"
1500     tempStr->Append("Bool_t ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object, const ").Append(typeStr2->Data()).Append(" *object2)\n");
1501     fprintf(fp, tempStr->Data());
1502     break;
1503   case AliEveListAnalyser::kSingleObjectAnalyse:    
1504     // Use "void 'NAME'(const 'OBJECTTYPE' *object, Double_t*& r, Int_t& n)\n"
1505     tempStr->Append("void ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object, Double_t*& r, Int_t& n)\n");
1506     fprintf(fp, tempStr->Data());
1507     break;
1508   case AliEveListAnalyser::kSingleObjectHisto:
1509     // Use "TH1* 'NAME'(const 'OBJECTTYPE' *object)\n"
1510     tempStr->Append("TH1* ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object)\n");
1511     fprintf(fp, tempStr->Data());
1512     break;
1513   case AliEveListAnalyser::kCorrelObjectAnalyse:
1514     // Use "void 'NAME'(const 'OBJECTTYPE' *object, const 'OBJECTTYPE2' *object2, Double_t*& r, Int_t& n)\n"
1515     tempStr->Append("void ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object, const ").Append(typeStr2->Data()).Append(" *object2, Double_t*& r, Int_t& n)\n");
1516     fprintf(fp, tempStr->Data());
1517     break;
1518   case AliEveListAnalyser::kCorrelObjectHisto:
1519     // Use "TH1* 'NAME'(const 'OBJECTTYPE' *object, const 'OBJECTTYPE2' *object2)\n"
1520     tempStr->Append("TH1* ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object, const ").Append(typeStr2->Data()).Append(" *object2)\n");
1521     fprintf(fp, tempStr->Data());
1522     break;
1523   default:
1524     Error("AliEveGeneralMacroWizard::Create", Form("Unknown type[%d]", type));
1525     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
1526                  Form("Unknown type[%d]", type), kMBIconExclamation, kMBOk);
1527     fclose(fp);
1528     gSystem->Exec(Form("rm -f %s.C", name));
1529
1530     tempStr->Clear();
1531     if (tempStr != 0) delete tempStr;
1532     tempStr = 0;
1533
1534     typeStr->Clear();
1535     if (typeStr != 0) delete typeStr;
1536     typeStr = 0;
1537
1538     return;
1539   }
1540
1541   tempStr->Clear();
1542   if (tempStr != 0) delete tempStr;
1543   tempStr = 0;
1544
1545   typeStr->Clear();
1546   if (typeStr != 0) delete typeStr;
1547   typeStr = 0;
1548
1549   typeStr2->Clear();
1550   if (typeStr2 != 0) delete typeStr2;
1551   typeStr2 = 0;
1552
1553   fprintf(fp, "{\n%s\n", fGeneralMacroTemplate[type]);
1554
1555   // Add some further information for analyse macros
1556   if (type == AliEveListAnalyser::kSingleObjectAnalyse || type == AliEveListAnalyser::kCorrelObjectAnalyse)
1557   {
1558     fprintf(fp, "// add your own code here\n// Please allocate memory for your results, e.g. by doing:\n// n = YourNumberOfResults;\n// r = new Double_t[YourNumberOfResults];\n\n}\n");
1559   }
1560   else
1561   {
1562     fprintf(fp, "// add your own code here\n\n\n}\n");
1563   }
1564   
1565   fclose(fp);
1566
1567   Emit("Create(Int_t)", type);
1568   Create((Char_t*)name);
1569   CloseWindow();
1570 }
1571
1572 //______________________________________________________
1573 void AliEveGeneralMacroWizard::Create(Char_t *name)
1574 {
1575   // Emits the creation signal.
1576
1577   Emit("Create(Char_t*)", Form("%s.C", name));
1578 }
1579
1580 //______________________________________________________
1581 void AliEveGeneralMacroWizard::HandleCreate()
1582 {
1583   // Handles the signal, when the creation button is pressed.
1584
1585   Create(fCombo->GetSelected());
1586 }
1587
1588 //______________________________________________________
1589 void AliEveGeneralMacroWizard::HandleSelectionChanged(Int_t sel)
1590 {
1591   // Handles the change of the selected macro type.
1592
1593   switch (sel)
1594   {
1595 case AliEveListAnalyser::kCorrelObjectSelect:
1596 case AliEveListAnalyser::kCorrelObjectAnalyse:
1597 case AliEveListAnalyser::kCorrelObjectHisto:
1598     // Enable 2nd object type
1599     fTextObjectType2->SetEnabled(kTRUE);
1600   break;
1601 default:
1602     // Disable 2nd object type
1603     fTextObjectType2->SetEnabled(kFALSE);
1604   break;
1605   }
1606 }