]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EVE/EveDet/AliEveListAnalyserEditor.cxx
Fix compilation warning.
[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   delete selIterator;
366   delete procIterator;  
367   
368   if (!success)
369   {
370     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
371                  "AliEveListAnalyser::ApplyProcessMacros experienced an error (cf. CINT-output)!", 
372                  kMBIconExclamation, kMBOk);  
373   }
374 }
375
376 //______________________________________________________
377 void AliEveListAnalyserEditor::BrowseMacros()
378 {
379   // Creates a file-dialog. The selected files will be added to the macro list
380   // via AddMacro(...).
381
382   new TGFileDialog(gClient->GetRoot(), GetMainFrame(), kFDOpen, fFileInfo);
383   
384   if (fFileInfo->fIniDir != 0 && fFileInfo->fFileNamesList != 0)
385   {       
386     // Extract filenames
387     TObject* iter = fFileInfo->fFileNamesList->First();
388  
389     Char_t* name = 0;
390
391     while (iter != 0)
392     {
393       // NOTE: fileInfo->fFileNamesList will be changed by that, too!
394       name = (Char_t*)strrchr(iter->GetName(), '/');
395       // Delete '"' at the end
396       name[strlen(name)] = '\0';
397               
398       AddMacro(name + 1, fFileInfo->fIniDir); 
399       iter = (TObjString*)fFileInfo->fFileNamesList->After(iter);
400     }
401   }
402 }
403
404 //______________________________________________________
405 void AliEveListAnalyserEditor::CloseTabs()
406 {
407   // Closes + deletes the tabs created by this object
408
409   if (fHistoCanvas != 0)
410   {
411     // Close the created tab, if it exists
412     if (fHistoCanvasName != 0)
413     {
414       if (gEve->GetBrowser()->GetTab(1)->SetTab(fHistoCanvasName->GetString()))
415       {
416         // Now the created tab is the current one and can be deleted
417         gEve->GetBrowser()->GetTab(1)->RemoveTab();
418       }
419     }
420     // With the tab removal, the canvas will be deleted automatically!
421     fHistoCanvas = 0;
422   }
423 }
424
425 /*
426 //______________________________________________________
427 void AliEveListAnalyserEditor::DoAddPrimSelectedObjects()
428 {
429   // Adds the selected object(s) to the list ("primary selection").
430
431   fM->AddPrimSelectedObjects();
432 }
433
434 //______________________________________________________
435 void AliEveListAnalyserEditor::DoRemovePrimSelectedObjects()
436 {
437   // Removes the selected object(s) from the list ("primary selection").
438
439   fM->RemovePrimSelectedObjects();
440 }
441 */
442
443 //______________________________________________________
444 void AliEveListAnalyserEditor::DoResetObjectList()
445 {
446   // Removes all objects from the list.
447
448   fM->ResetObjectList();
449   Update();
450 }
451
452 //______________________________________________________
453 void AliEveListAnalyserEditor::DoStartAddingObjects()
454 {
455   // Starts adding objects for the analysis.
456
457   if (fM->StartAddingObjects())
458   {
459     fbStart->SetState(kButtonDisabled);
460     fbStop->SetState(kButtonUp);
461   }
462   else
463   {
464     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", "Failed to connect socket!", kMBIconExclamation, kMBOk);
465
466     if (fM->GetConnected())
467     {
468       fbStop->SetState(kButtonDisabled);
469       fbStart->SetState(kButtonUp);
470     }
471   }
472 }
473
474 //______________________________________________________
475 void AliEveListAnalyserEditor::DoStopAddingObjects()
476 {
477   // Stops adding objects for the analysis.
478
479   if (fM->StopAddingObjects())
480   {
481     fbStop->SetState(kButtonDisabled);
482     fbStart->SetState(kButtonUp);
483   }
484   else
485   {
486     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", "Failed to disconnect socket!", kMBIconExclamation, kMBOk);
487     
488     if (fM->GetConnected())
489     {
490       fbStop->SetState(kButtonUp);
491       fbStart->SetState(kButtonDisabled);
492     }
493   }
494 }
495
496 //______________________________________________________
497 void AliEveListAnalyserEditor::DrawHistos()
498 {
499   // Accesses the temporary data file created by the last call of ApplyMacros() and draws
500   // histograms according to the selection in the "Histograms"-tab.
501  
502   Int_t nHistograms = GetNSelectedHistograms();
503   if (nHistograms <= 0)
504   {
505     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
506                  "No data selected. Please select the data you want to plot!", kMBIconExclamation, kMBOk);
507     return;
508   }
509   if (nHistograms > 3)
510   {
511     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), 
512                  "Error", "Only histograms with up to 3 dimensions supported. Please select 1,2 or 3 data macros!",
513                  kMBIconExclamation, kMBOk);
514     return;
515   }
516
517   // Check, if a histo macro shall be drawn
518   Int_t indexOfHistoMacro = -1;
519   Int_t selectedChecked = 0;
520   for (Int_t j = 0; j < fM->fDataFromMacroList->GetEntries(); j++)
521   {
522     if (fCheckButtons[j]->TGButton::GetState() == kButtonDown)
523     {
524       selectedChecked++;
525
526       // Histo macro? -> To check this, look for the substring "(histo macro)"
527       if (strstr(fM->fDataFromMacroList->At(j)->GetName(), "(histo macro)") != 0)
528       {
529         // Is also another macro selected?
530         if (nHistograms > 1)
531         {
532           // Histo macros cannot(!) be correlated!
533           new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
534                        "Histo macros (return value \"TH1*\") cannot be combined with other macros", 
535                        kMBIconExclamation, kMBOk);
536           return;        
537         }
538
539         // Mark this histo macro for drawing
540         indexOfHistoMacro = j;
541
542         // Have all selected macros been checked? -> If yes, we are done with this
543         if (selectedChecked == nHistograms)  break;
544       }
545     }
546   }
547
548   TFile* file = new TFile(Form("/tmp/ListAnalyserMacroData_%s.root", gSystem->Getenv("USER")), "READ");
549   if (!file)  
550   {
551     Error("Draw histograms", Form("Cannot open file \"/tmp/ListAnalyserMacroData_%s.root\"", 
552                                   gSystem->Getenv("USER")));
553     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
554                  Form("Cannot open file \"/tmp/ListAnalyserMacroData_%s.root\"", gSystem->Getenv("USER")),
555                  kMBIconExclamation, kMBOk);
556     return;
557   }
558   
559   TTree* t = 0;
560   TTree* tFriend1 = 0;
561   TTree* tFriend2 = 0;
562
563   Int_t indexOfMacro1 = 0;
564   Int_t indexOfMacro2 = 0;
565   Int_t indexOfMacro3 = 0;
566
567   // Variable for the loop below -> Will be set to aborting value, if a histo macro is drawn
568   Int_t i = 0;
569   
570   // Draw histo macro?
571   if (indexOfHistoMacro >= 0)
572   {
573     if ((t = (TTree*)file->Get(Form("ObjectData%d", indexOfHistoMacro))))
574     {
575       SetDrawingToHistoCanvasTab();
576  
577       TH1* myHist = 0;
578       t->SetBranchAddress(Form("Macro%d", indexOfHistoMacro), &myHist);
579       t->GetEntry(0);
580       if (myHist != 0)  myHist->Draw();
581       else
582       {
583         Error("Draw histograms", Form("No histogram for histo macro \"%s\" found!", 
584                                       fM->fDataFromMacroList->At(indexOfHistoMacro)->GetName()));
585         new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
586                      Form("No histogram for histo macro \"%s\" found!", 
587                           fM->fDataFromMacroList->At(indexOfHistoMacro)->GetName()), kMBIconExclamation, kMBOk);
588                
589       }
590
591       UpdateHistoCanvasTab();    
592     }
593     else
594     {
595       Error("Draw histograms", Form("No data for histo macro \"%s\" found!\nMaybe no objects have been selected.", 
596                                     fM->fDataFromMacroList->At(indexOfHistoMacro)->GetName()));
597       new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
598                    Form("No data for histo macro \"%s\" found!\nMaybe no objects have been selected.", 
599                         fM->fDataFromMacroList->At(indexOfHistoMacro)->GetName()), kMBIconExclamation, kMBOk);
600     }
601
602     // Skip the loop below
603     i = fM->fDataFromMacroList->GetEntries();
604   }
605
606   // Load the trees in succession and remember the entries -> Plot the analyse macros
607   for ( ; i < fM->fDataFromMacroList->GetEntries(); i++)
608   {
609     if (fCheckButtons[i]->TGButton::GetState() == kButtonDown)
610     {
611       if (t == 0)
612       {
613         indexOfMacro1 = i;
614         if (!(t = (TTree*)file->Get(Form("ObjectData%d", i))))
615         { 
616           Error("Draw histograms", Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
617                                         fM->fDataFromMacroList->At(i)->GetName()));
618           new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
619                        Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
620                             fM->fDataFromMacroList->At(i)->GetName()), kMBIconExclamation, kMBOk);
621           break;   
622         }
623
624         // 1d histogram
625         if (nHistograms == 1) 
626         {
627           SetDrawingToHistoCanvasTab();
628       
629           t->Draw(Form("Macro%d", indexOfMacro1), "1");
630           ((TH1*)gPad->GetPrimitive("htemp"))->SetTitle(Form("%s;%s",
631             fM->fDataFromMacroList->At(indexOfMacro1)->GetName(),
632             fM->fDataFromMacroList->At(indexOfMacro1)->GetName()));
633           UpdateHistoCanvasTab();        
634
635           break;     
636         }
637       }
638       else if (tFriend1 == 0)
639       {
640         indexOfMacro2 = i;
641         if (!(tFriend1 = (TTree*)file->Get(Form("ObjectData%d", i))))
642         { 
643           Error("Draw histograms", Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
644                                         fM->fDataFromMacroList->At(i)->GetName()));
645           new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
646                        Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
647                             fM->fDataFromMacroList->At(i)->GetName()),
648                             kMBIconExclamation, kMBOk);
649           break;   
650         }
651         
652         // 2d histogram
653         if (nHistograms == 2) 
654         {
655           SetDrawingToHistoCanvasTab();
656
657           t->AddFriend(tFriend1);
658           t->Draw(Form("Macro%d:Macro%d", indexOfMacro1, indexOfMacro2), "1");
659           ((TH1*)gPad->GetPrimitive("htemp"))->SetTitle(Form("%s - %s;%s;%s",
660             fM->fDataFromMacroList->At(indexOfMacro2)->GetName(),
661             fM->fDataFromMacroList->At(indexOfMacro1)->GetName(),
662             fM->fDataFromMacroList->At(indexOfMacro2)->GetName(),
663             fM->fDataFromMacroList->At(indexOfMacro1)->GetName()));
664
665           UpdateHistoCanvasTab();
666  
667           break;     
668         }
669       }    
670       // 3d histogram
671       else
672       {
673         indexOfMacro3 = i;
674         if (!(tFriend2 = (TTree*)file->Get(Form("ObjectData%d", i))))
675         { 
676           Error("Draw histograms", Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
677                                         fM->fDataFromMacroList->At(i)->GetName()));
678           new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error - Draw histograms", 
679                        Form("No data for macro \"%s\" found!\nMaybe no objects have been selected.", 
680                             fM->fDataFromMacroList->At(i)->GetName()), kMBIconExclamation, kMBOk);
681           break;   
682         }
683
684         SetDrawingToHistoCanvasTab();
685
686         t->AddFriend(tFriend1);
687         t->AddFriend(tFriend2);
688         t->Draw(Form("Macro%d:Macro%d:Macro%d", indexOfMacro1, indexOfMacro2, indexOfMacro3), "1");
689         ((TH1*)gPad->GetPrimitive("htemp"))->SetTitle(Form("%s - %s - %s;%s;%s;%s",
690             fM->fDataFromMacroList->At(indexOfMacro3)->GetName(),
691             fM->fDataFromMacroList->At(indexOfMacro2)->GetName(),
692             fM->fDataFromMacroList->At(indexOfMacro1)->GetName(),
693             fM->fDataFromMacroList->At(indexOfMacro3)->GetName(),
694             fM->fDataFromMacroList->At(indexOfMacro2)->GetName(),
695             fM->fDataFromMacroList->At(indexOfMacro1)->GetName()));
696         
697         UpdateHistoCanvasTab();
698  
699         break;     
700       }
701     }
702   }
703
704   if (t != 0) delete t;
705   t = 0;
706   if (tFriend1 != 0)  delete tFriend1;
707   tFriend1 = 0;
708   if (tFriend2 != 0)  delete tFriend2;
709   tFriend2 = 0;
710
711   file->Close("R");
712   delete file;
713   file = 0;
714 }
715
716 //______________________________________________________
717 Int_t AliEveListAnalyserEditor::GetNSelectedHistograms() const
718 {
719   // Returns the number of selected macros (or rather: of their selected data) in the "Histograms"-tab
720
721   Int_t count = 0;
722   
723   for (Int_t i = 0; i < fM->fDataFromMacroList->GetEntries(); i++)
724   {
725     if (fCheckButtons[i]->TGButton::GetState() == kButtonDown)  count++;
726   }
727
728   return count;
729 }
730
731 //______________________________________________________
732 void AliEveListAnalyserEditor::HandleMacroPathSet()
733 {
734   // Takes the input of the text field (adding a macro), checks if the macro can be
735   // accessed (and that it exists) and adds the macro to the macro list via AddMacro(...).
736   // You can use environment variables in the text field, e.g. "$ALICE_ROOT/Eve/alice-macro/myMacro.C".
737
738   if (strlen(fteField->GetText()) != 0)
739   {  
740     // Expand the pathname
741     Char_t* systemPath = gSystem->ExpandPathName(fteField->GetText());
742     fteField->SetText(systemPath);
743     delete systemPath;
744     systemPath = 0;
745                         
746     // Check if file exists
747     FILE* fp = NULL;
748
749     fp = fopen(fteField->GetText(), "rb");
750     if (fp != NULL)
751     {
752       fclose(fp);
753
754       // Extract filename
755       Char_t* name = (Char_t*)strrchr(fteField->GetText(), '/');
756
757       // Current path
758       if (name == NULL)
759       {
760         name = new Char_t[AliEveListAnalyser::fkMaxMacroNameLength];
761         memset(name, '\0', sizeof(Char_t) * AliEveListAnalyser::fkMaxMacroNameLength);
762         snprintf(name, AliEveListAnalyser::fkMaxMacroNameLength, "%s", fteField->GetText());
763
764         // Add path to textfield -> Path is "./" -> Use length for the name + 2
765         Char_t pathname[AliEveListAnalyser::fkMaxMacroNameLength + 2];
766         memset(pathname, '\0', sizeof(Char_t) * (AliEveListAnalyser::fkMaxMacroNameLength + 2));
767         snprintf(pathname, AliEveListAnalyser::fkMaxMacroNameLength + 2, "./%s", fteField->GetText());
768         fteField->SetText(pathname);
769
770         AddMacro(name);  
771         delete [] name;
772       }
773       // Different path
774       else
775       {
776         // Extract path
777         Char_t* path = new Char_t[AliEveListAnalyser::fkMaxMacroPathLength];
778         memset(path, '\0', sizeof(Char_t) * AliEveListAnalyser::fkMaxMacroPathLength);
779         strncpy(path, fteField->GetText(), strlen(fteField->GetText()) - strlen(name));
780         
781         // Ignore the slash "/" in name
782         AddMacro(name + 1, path);    
783         delete [] path;
784       }       
785     }
786     else
787     {
788       new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
789                    "File does not exist or you do not have read permission!", kMBIconExclamation, kMBOk);
790     }
791   }
792 }
793
794 //______________________________________________________
795 void AliEveListAnalyserEditor::HandleNewEventLoaded()
796 {
797   // Closes the tabs created by this object and sets a flag that will
798   // cause the function SetModel() to inherit the macro lists
799   // for the next AliEveListAnalyser from the current one.
800
801   // Inherit the macro list for the next analyse object list!
802   fInheritSettings = kTRUE;
803
804   // Close the tabs
805   CloseTabs();
806 }
807
808 //______________________________________________________
809 void AliEveListAnalyserEditor::HandleTabChangedToIndex(Int_t index)
810 {
811   // Saves the current tab in the current AliEveListAnalyser.
812
813   fM->SetSelectedTab(index);
814 }
815
816 //______________________________________________________
817 void AliEveListAnalyserEditor::InheritMacroList()
818 {
819   // The old macro list is possibly stored in the corresponding interior map. This function will 
820   // use this interior map to move the data from the interior map to the newly loaded AliEveListAnalyser. 
821   // Then the interior map will be cleaned up. With this, the settings will be inherited from the previously 
822   // loaded AliEveListAnalyser.
823
824   if (fInheritedMacroList == 0)  return;
825
826   // Clear list  
827   fM->fMacroList->Delete();
828
829   // Store data from interior list in the analyse object list's map
830   TMapIter* iter = (TMapIter*)fInheritedMacroList->MakeIterator();
831   
832   TObject* key = 0;
833   TGeneralMacroData* macro = 0;
834   
835   while ((key = iter->Next()) != 0)
836   {
837     macro = (TGeneralMacroData*)fInheritedMacroList->GetValue(key);
838     if (macro != 0)  fM->fMacroList->Add(new TObjString(key->GetName()), 
839                                          new TGeneralMacroData(macro->GetName(), macro->GetPath(), macro->GetType(), 
840                                                                macro->GetObjectType(), macro->GetObjectType2()));
841     else
842     {
843       Error("AliEveListAnalyserEditor::InheritMacroList", Form("Failed to inherit the macro \"%s\"!", key->GetName()));
844     }
845   }
846   
847   fInheritedMacroList->Delete();
848   delete fInheritedMacroList;
849   fInheritedMacroList = 0;
850 }
851
852 //______________________________________________________
853 void AliEveListAnalyserEditor::NewMacros()
854 {
855   // Start the macro creation wizard.
856   // thanks to Jacek Otwinowski<J.Otwinowski@GSI.DE> for this suggestion
857
858   AliEveGeneralMacroWizard *wizz = new AliEveGeneralMacroWizard();
859   wizz->Connect("Create(Char_t*)", "AliEveListAnalyserEditor", this, "AddMacro(Char_t*)");
860 }
861
862 //______________________________________________________
863 void AliEveListAnalyserEditor::RemoveMacros()
864 {
865   // Removes the selected macros from the corresponding list.
866
867   TList* iterator = new TList();
868   
869   ftlMacroList->GetSelectedEntries(iterator);
870   fM->RemoveSelectedMacros(iterator);
871
872   delete iterator;
873
874   iterator = new TList();
875   ftlMacroSelList->GetSelectedEntries(iterator);
876   fM->RemoveSelectedMacros(iterator);
877
878   // Selected macros are deleted from the list -> No selected entries left
879   fM->fMacroListSelected = 0;
880
881   UpdateMacroList();
882   delete iterator;
883 }
884
885 //______________________________________________________
886 void AliEveListAnalyserEditor::SaveMacroList(TMap* list)
887 {
888   // Saves the provided macro list in an interior list. This list will be used by
889   // InheritMacroList() to restore the data in "list". With this method one is able
890   // to inherit the macro list from analyse object list to analyse object list (i.e. from event to event).
891
892   if (fInheritedMacroList != 0)
893   {
894     fInheritedMacroList->Delete();
895     delete fInheritedMacroList;
896   }
897   fInheritedMacroList = new TMap();
898   fInheritedMacroList->SetOwnerKeyValue(kTRUE, kTRUE);
899
900   TMapIter* iter = (TMapIter*)list->MakeIterator();
901   TObject* key = 0;
902   TGeneralMacroData* macro = 0;
903   
904   while ((key = iter->Next()) != 0)
905   {
906     macro = (TGeneralMacroData*)fM->fMacroList->GetValue(key);
907     if (macro != 0) fInheritedMacroList->Add(new TObjString(key->GetName()), 
908                                              new TGeneralMacroData(macro->GetName(), macro->GetPath(), macro->GetType(), 
909                                                                    macro->GetObjectType(), macro->GetObjectType2()));
910     else
911     {
912       Error("AliEveListAnalyserEditor::SaveMacroList", Form("Failed to inherit the macro \"%s\"!", key->GetName()));
913     }
914   }
915 }
916
917 //______________________________________________________
918 void AliEveListAnalyserEditor::SetDrawingToHistoCanvasTab()
919 {
920   // Sets gPad to the tab with the name of the current AliEveListAnalyser. If this tab does
921   // not exist, it will be created. Otherwise, it is re-used.
922
923   // If the tab with the canvas has been closed, the canvas will be deleted.
924   // So, if there is no tab, set the canvas pointer to zero and recreate it in a new tab.
925   if (fHistoCanvas != 0) 
926   {
927     if (gEve->GetBrowser()->GetTab(1)->SetTab(fHistoCanvasName->GetString()) == 0)
928     {
929       fHistoCanvas = 0;
930     }
931   }
932
933   if (!fHistoCanvas)
934   {
935     fHistoCanvas = gEve->AddCanvasTab(fM->GetName());     
936   }
937                            
938   gPad = fHistoCanvas;
939 }
940
941 //______________________________________________________
942 void AliEveListAnalyserEditor::SetModel(TObject* obj)
943 {  
944   // Sets the model object, updates the related data in the GUI and
945   // inherits settings (cf. Inherit*(...)), if the flag fInheritSettings is set to kTRUE.
946
947   fM = dynamic_cast<AliEveListAnalyser*>(obj);
948
949   if (fM == 0) 
950   {
951     Error("SetModel", "Parameter is zero pointer");
952     return;
953   }
954
955   // Provide a pointer to this editor
956   fM->fEditor = this;
957
958   // If macro list + track style shall be inherited from previously loaded track list, do so
959   if (fInheritSettings)
960   {
961     InheritMacroList();
962
963     fInheritSettings = kFALSE;
964   }
965
966   UpdateMacroList();
967   UpdateHistoList(); 
968
969   // View correct tab
970   GetGedEditor()->GetTab()->SetTab(fM->GetSelectedTab()); 
971
972   // Set connection buttons correctly
973   if(fM->GetConnected())
974   {
975     fbStart->SetState(kButtonDisabled);
976     fbStop->SetState(kButtonUp);
977   }
978   else
979   {
980     fbStop->SetState(kButtonDisabled);
981     fbStart->SetState(kButtonEngaged);
982     fbStart->SetState(kButtonUp);
983   }
984 }
985
986 //______________________________________________________
987 void AliEveListAnalyserEditor::UpdateDataFromMacroListSelection()
988 {
989   // Saves the current selection in the "Histograms"-tab to the current
990   // AliEveListAnalyser. This means that the selection is updated and won't
991   // get lost, if another editor is loaded in Eve.
992
993   for (Int_t i = 0; i < fM->fDataFromMacroList->GetEntries(); i++)
994   {
995     fM->SetHistoDataSelection(i, fCheckButtons[i]->IsOn());
996   }
997 }
998
999 //______________________________________________________
1000 void AliEveListAnalyserEditor::UpdateHistoCanvasTab()
1001 {
1002   // Updates the histogram and the corresponding tab (including titles).
1003
1004   // Update name of the tab (tab has been set to current tab!)
1005   fHistoCanvasName->SetString(fM->GetName());  
1006
1007   // Use a copy of fHistoCanvasName!! -> If the user closes a tab manually, the TGString
1008   // will be deleted -> Error might occur, when accessing the pointer   
1009   gEve->GetBrowser()->GetTab(1)->GetCurrentTab()->SetText(new TGString(fHistoCanvasName));
1010
1011   // Switch tabs to force redrawing
1012   gEve->GetBrowser()->GetTab(1)->SetTab(0);
1013   gEve->GetBrowser()->GetTab(1)->SetTab(fHistoCanvasName->GetString());
1014   fHistoCanvas->Update();
1015 }
1016
1017 //______________________________________________________
1018 void AliEveListAnalyserEditor::UpdateHistoList()
1019 {
1020   // Reloads (updates) the buttons in the "Histograms"-tab via
1021   // the current AliEveListAnalyser (data).
1022
1023   fHistoSubFrame->TGCompositeFrame::Cleanup();
1024   
1025   // Set buttons for histograms
1026   if (fCheckButtons != 0) delete fCheckButtons;
1027   fCheckButtons = new TGCheckButton*[fM->fDataFromMacroList->GetEntries()];
1028   
1029   TObjString* iter = (TObjString*)fM->fDataFromMacroList->First();
1030   for (Int_t i = 0; i < fM->fDataFromMacroList->GetEntries() && iter != 0; i++)
1031   {
1032     fCheckButtons[i] = new TGCheckButton(fHistoSubFrame, iter->GetName());
1033     fHistoSubFrame->AddFrame(fCheckButtons[i]);
1034     
1035     fCheckButtons[i]->SetState(kButtonUp, kFALSE);
1036     fCheckButtons[i]->MapRaised();
1037     fCheckButtons[i]->SetOn(fM->HistoDataIsSelected(i));
1038     fCheckButtons[i]->Connect("Clicked()", "AliEveListAnalyserEditor", this, "UpdateDataFromMacroListSelection()");
1039             
1040     iter = (TObjString*)fM->fDataFromMacroList->After(iter);
1041   }  
1042 }
1043
1044 //______________________________________________________
1045 void AliEveListAnalyserEditor::UpdateMacroList()
1046 {
1047   // Reloads (updates) the macro list (selection AND process macros) via
1048   // the current AliEveListAnalyser (data).
1049
1050   ftlMacroList->RemoveAll();
1051   ftlMacroSelList->RemoveAll();
1052    
1053   TMapIter* iter = (TMapIter*)fM->fMacroList->MakeIterator();
1054   TObject* key = 0;
1055   TGeneralMacroData* macro = 0;
1056
1057   Int_t ind = 0;
1058   while ((key = iter->Next()) != 0)
1059   {
1060     macro = (TGeneralMacroData*)fM->fMacroList->GetValue(key);
1061     if (macro != 0)
1062     {
1063       if (macro->IsProcessMacro())
1064       {
1065         ftlMacroList->AddEntry(macro->GetName(), ind);
1066         // Select, what has been selected before
1067         ftlMacroList->Select(ind, fM->MacroListIsSelected(ind));
1068         ind++;
1069       }
1070       else if (macro->IsSelectionMacro())
1071       {
1072         ftlMacroSelList->AddEntry(macro->GetName(), ind);
1073         // Select, what has been selected before
1074         ftlMacroSelList->Select(ind, fM->MacroListIsSelected(ind));
1075         ind++;
1076       }
1077       else
1078       {
1079         Error("AliEveListAnalyserEditor::UpdateMacroList()", 
1080               Form("Macro \"%s/%s.C\" is neither a selection macro nor a process macro!",
1081                    macro->GetPath(), macro->GetName()));                                        
1082       }
1083     }
1084     else
1085     {
1086       Error("AliEveListAnalyserEditor::UpdateMacroList()", 
1087               Form("Macro list is corrupted: Macro \"%s\" not found!", key->GetName()));            
1088     }     
1089   }
1090
1091   ftlMacroList->SortByName(); 
1092   ftlMacroSelList->SortByName(); 
1093 }
1094
1095 //______________________________________________________
1096 void AliEveListAnalyserEditor::UpdateMacroListSelection(Int_t ind)
1097 {
1098   // Saves the current selection in the macro listS to the current
1099   // AliEveListAnalyser. This means that the selection is updated and won't
1100   // get lost, if another editor is loaded in Eve.
1101   // NOTE: The indices in BOTH lists will be unique!
1102
1103   // Toggle selected item
1104   fM->SetMacroListSelection(ind, !fM->MacroListIsSelected(ind));
1105 }
1106
1107
1108 //______________________________________________________
1109 //______________________________________________________
1110 //______________________________________________________
1111
1112
1113 /////////////////////////////////////////////////
1114 ClassImp(AliEveGeneralMacroWizard)
1115 /////////////////////////////////////////////////
1116
1117 //______________________________________________________
1118 AliEveGeneralMacroWizard::AliEveGeneralMacroWizard(const TGWindow* p)
1119   :TGMainFrame(p ? p : gClient->GetRoot(), 10, 10, kMainFrame | kVerticalFrame)
1120   ,fbCancel(0x0)
1121   ,fbCreate(0x0)
1122   ,fCombo(0x0)
1123   ,fTextEdit(0x0)
1124   ,fTextIncludes(0x0)
1125   ,fTextName(0x0)  
1126   ,fTextObjectType(0x0)
1127   ,fTextObjectType2(0x0)
1128 {
1129   // Creates the macro wizard.
1130
1131   const Int_t width = 300;
1132
1133   // horizontal frame
1134   TGHorizontalFrame *fFrameName = new TGHorizontalFrame(this, 10, 10, kHorizontalFrame);
1135   TGLabel *fLabel = new TGLabel(fFrameName, "Name*");
1136   fLabel->SetTextJustify(36);
1137   fLabel->SetMargins(0,0,0,0);
1138   fLabel->SetWrapLength(-1);
1139   fFrameName->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
1140
1141   fTextName = new TGTextEntry(fFrameName);
1142   fTextName->SetMaxLength(255);
1143   fTextName->SetAlignment(kTextLeft);
1144   fTextName->SetText("");
1145   fTextName->SetToolTipText("The name of your macro");
1146   fTextName->Resize(width, fTextName->GetDefaultHeight());
1147   fFrameName->AddFrame(fTextName, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2));
1148
1149   // horizontal frame
1150   TGHorizontalFrame *fFrameObjectType = new TGHorizontalFrame(this, 10, 10, kHorizontalFrame);
1151   fLabel = new TGLabel(fFrameObjectType, "1st object type of macro");
1152   fLabel->SetTextJustify(36);
1153   fLabel->SetMargins(0,0,0,0);
1154   fLabel->SetWrapLength(-1);
1155   fFrameObjectType->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
1156
1157   fTextObjectType = new TGTextEntry(fFrameObjectType);
1158   fTextObjectType->SetAlignment(kTextLeft);
1159   fTextObjectType->SetText("");
1160   // Limit max.length to 80 characters
1161   fTextObjectType->SetMaxLength(80);
1162   fTextObjectType->SetToolTipText("The type of objects, your macro will work with (type of the first pointer)");
1163   fTextObjectType->Resize(width, fTextObjectType->GetDefaultHeight());
1164   fFrameObjectType->AddFrame(fTextObjectType, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2));
1165
1166    // horizontal frame
1167   TGHorizontalFrame *fFrameObjectType2 = new TGHorizontalFrame(this, 10, 10, kHorizontalFrame);
1168   fLabel = new TGLabel(fFrameObjectType2, "2nd object type of macro (pair");
1169   fLabel->SetTextJustify(36);
1170   fLabel->SetMargins(0,0,0,0);
1171   fLabel->SetWrapLength(-1);
1172   fFrameObjectType2->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
1173
1174   fTextObjectType2 = new TGTextEntry(fFrameObjectType2);
1175   fTextObjectType2->SetAlignment(kTextLeft);
1176   fTextObjectType2->SetText("");
1177   // Limit max.length to 80 characters
1178   fTextObjectType2->SetMaxLength(80);
1179   fTextObjectType2->SetToolTipText("The type of objects, your macro will work with (type of the second pointer)\nOnly needed for macros dealing with object pairs");
1180   fTextObjectType2->Resize(width, fTextObjectType2->GetDefaultHeight());
1181   fFrameObjectType2->AddFrame(fTextObjectType2, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2));
1182   fTextObjectType2->SetEnabled(kFALSE);
1183
1184   // horizontal frame
1185   TGHorizontalFrame *fFrameIncludes = new TGHorizontalFrame(this,10,10,kHorizontalFrame);
1186   fLabel = new TGLabel(fFrameIncludes, "Include files");
1187   fLabel->SetTextJustify(36);
1188   fLabel->SetMargins(0,0,0,0);
1189   fLabel->SetWrapLength(-1);
1190   fFrameIncludes->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
1191
1192   fTextIncludes = new TGTextEntry(fFrameIncludes);
1193   fTextObjectType->SetAlignment(kTextLeft);
1194   fTextIncludes->SetText("<TRD/AliTRDgeometry.h>,<TRD/AliTRDcluster.h>,<TRD/AliTRDseedV1.h>,<TRD/AliTRDtrackV1.h>");
1195   fTextIncludes->SetCursorPosition(0);
1196   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");
1197   fTextIncludes->Resize(width, fTextIncludes->GetDefaultHeight());
1198   fFrameIncludes->AddFrame(fTextIncludes, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2));
1199
1200   // horizontal frame
1201   TGHorizontalFrame *fFrameComment = new TGHorizontalFrame(this,10,10,kHorizontalFrame);
1202   fLabel = new TGLabel(fFrameComment, "Comment");
1203   fLabel->SetTextJustify(36);
1204   fLabel->SetMargins(0,0,0,0);
1205   fLabel->SetWrapLength(-1);
1206   fFrameComment->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
1207
1208   fTextEdit = new TGTextEdit(fFrameComment, width, 5*fTextName->GetDefaultHeight());
1209   fFrameComment->AddFrame(fTextEdit, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2));
1210
1211   // horizontal frame
1212   TGHorizontalFrame *fFrameType = new TGHorizontalFrame(this,10,10,kHorizontalFrame);
1213   fLabel = new TGLabel(fFrameType, "Type*");
1214   fLabel->SetTextJustify(36);
1215   fLabel->SetMargins(0,0,0,0);
1216   fLabel->SetWrapLength(-1);
1217   fFrameType->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
1218
1219   fCombo = new TGComboBox(fFrameType, -1, kHorizontalFrame | kSunkenFrame | kDoubleBorder | kOwnBackground);
1220   fCombo->AddEntry("Single Object Selection", AliEveListAnalyser::kSingleObjectSelect);
1221   fCombo->AddEntry("Pair Objects Selection", AliEveListAnalyser::kCorrelObjectSelect);
1222   fCombo->AddEntry("Single Object Analyse", AliEveListAnalyser::kSingleObjectAnalyse);
1223   fCombo->AddEntry("Single Object Histo", AliEveListAnalyser::kSingleObjectHisto);
1224   fCombo->AddEntry("Pair Objects Analyse", AliEveListAnalyser::kCorrelObjectAnalyse);
1225   fCombo->AddEntry("Pair Objects Histo", AliEveListAnalyser::kCorrelObjectHisto);
1226   fCombo->Select(-1);
1227   fCombo->Resize(width, fTextName->GetDefaultHeight());
1228   fFrameType->AddFrame(fCombo, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2));
1229
1230   // horizontal frame
1231   TGHorizontalFrame *fFrameAction = new TGHorizontalFrame(this,10,10,kHorizontalFrame);
1232   fbCancel = new TGTextButton(fFrameAction, "Cancel");
1233   fbCancel->SetToolTipText("Exit macro creation wizard");
1234   fFrameAction->AddFrame(fbCancel, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2)); 
1235   fbCreate = new TGTextButton(fFrameAction, "Done");
1236   fbCreate->SetToolTipText("Use settings to create the macro");
1237   fFrameAction->AddFrame(fbCreate, new TGLayoutHints(kLHintsRight | kLHintsTop,2,2,2,2)); 
1238
1239   // horizontal frame
1240   TGHorizontalFrame *fFrameText = new TGHorizontalFrame(this,10,10,kHorizontalFrame);
1241   fLabel = new TGLabel(fFrameText, "(*) Mandatory fields");
1242   fLabel->SetTextJustify(36);
1243   fLabel->SetMargins(0,0,0,0);
1244   fLabel->SetWrapLength(-1);
1245   fFrameText->AddFrame(fLabel, new TGLayoutHints(kLHintsLeft | kLHintsTop,2,2,2,2));
1246
1247   // put things together  
1248   AddFrame(fFrameName, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
1249   AddFrame(fFrameObjectType, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
1250   AddFrame(fFrameObjectType2, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
1251   AddFrame(fFrameIncludes, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
1252   AddFrame(fFrameComment, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
1253   AddFrame(fFrameType, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
1254   AddFrame(fFrameAction, new TGLayoutHints(kLHintsRight | kLHintsTop | kLHintsExpandX,2,2,2,2));
1255
1256   TGHorizontal3DLine *fLine = new TGHorizontal3DLine(this, 281, 2);
1257   AddFrame(fLine, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
1258   AddFrame(fFrameText, new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX,2,2,2,2));
1259
1260
1261   SetWindowName("Macro Wizard");
1262   SetMWMHints(kMWMDecorAll,
1263               kMWMFuncAll,
1264               kMWMInputModeless);
1265   MapSubwindows();
1266
1267   Resize(GetDefaultSize());
1268   MapWindow();
1269
1270   // Do the linking
1271   fCombo->Connect("Selected(Int_t)", "AliEveGeneralMacroWizard", this, "HandleSelectionChanged(Int_t)");
1272   fbCreate->Connect("Clicked()", "AliEveGeneralMacroWizard", this, "HandleCreate()");
1273   fbCancel->Connect("Clicked()", "AliEveGeneralMacroWizard", this, "CloseWindow()");
1274
1275   // Standard choice
1276   fCombo->Select(1, kFALSE);
1277 }  
1278
1279 const Char_t *fGeneralIncludes = 
1280 "#if !defined(__CINT__) || defined(__MAKECINT__)\n"
1281 "#include <TROOT.h>\n"
1282 "#include <TH1.h>\n";
1283
1284 const Char_t *fGeneralMacroTemplate[7] = {
1285 ""
1286 ,"  if (!object) return kFALSE;\n"
1287
1288 ,"  n = 0;\n"
1289 "  r = 0x0;\n"
1290 "  if (!object) return;\n"
1291
1292 ,"  if (!object) return 0x0;\n\n"
1293 "// Set bins, xmin and xmax here - you can also use a different histogram type (but must inherit from TH1)\n"
1294 "  Int_t n = 1;\n"
1295 "  Double_t xmin = 0;\n"
1296 "  Double_t xmax = 100;\n\n" 
1297 "  TH1S* h = new TH1S(\"h\", \"Your title\", n, xmin, xmax);\n"
1298 "  h->GetXaxis()->SetTitle("");\n"
1299 "  h->GetYaxis()->SetTitle("");\n"
1300
1301 ,"  if (!object) return kFALSE;\n"
1302 "  if (!object2) return kFALSE;\n"
1303
1304 ,"  n = 0;\n"
1305 "  r = 0x0;\n"
1306 "  if (!object) return;\n"
1307 "  if (!object2) return;\n"
1308
1309 ,"  if (!object) return 0x0;\n"
1310 "  if (!object2) return 0x0;\n\n"
1311 "// Set bins, xmin and xmax here - you can also use a different histogram type (but must inherit from TH1)\n"
1312 "  Int_t n = 1;\n"
1313 "  Double_t xmin = 0;\n"
1314 "  Double_t xmax = 100;\n\n"
1315 "  TH1S* h = new TH1S(\"h\", \"Your title\", n, xmin, xmax);\n"
1316 "  h->GetXaxis()->SetTitle("");\n"
1317 "  h->GetYaxis()->SetTitle("");\n"
1318 };
1319
1320 //______________________________________________________
1321 void AliEveGeneralMacroWizard::Create(Int_t type)
1322 {
1323   // Creates the macro with the selected type (combo box).
1324
1325   const Char_t* name = fTextName->GetText();
1326   if(strcmp(name,"") == 0)
1327   {
1328     Error("AliEveGeneralMacroWizard::Create", "Please specify a name for your macro.");
1329     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
1330                  "Please specify a name for your macro.", kMBIconExclamation, kMBOk);
1331     return;
1332   }
1333
1334   Bool_t useGivenType = kFALSE;
1335   Bool_t useGivenType2 = kFALSE;
1336
1337   // Remove white-spaces
1338   TString* typeStr = new TString(fTextObjectType->GetText());
1339   typeStr->ReplaceAll(" ", "");
1340   fTextObjectType->SetText(typeStr->Data(), kFALSE);
1341
1342   TString* typeStr2 = new TString(fTextObjectType2->GetText());
1343   typeStr2->ReplaceAll(" ", "");
1344   fTextObjectType2->SetText(typeStr2->Data(), kFALSE);
1345
1346   // If an object type is provided by the user, use it!
1347   if (strlen(typeStr->Data()) > 0)
1348   {
1349     // Check, if the class really exists
1350     if (TClass::GetClass(typeStr->Data()) != 0x0)
1351     {
1352       useGivenType = kTRUE; 
1353     }
1354     else
1355     {
1356       Int_t buttonsPressed = 0;
1357       new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Unknown object type", 
1358         Form("The class of your 1st object, \"%s\" has not been found. Do you really want to create your macro with this object type?", 
1359              typeStr->Data()), kMBIconExclamation, kMBYes | kMBNo, &buttonsPressed);
1360
1361       if (buttonsPressed & kMBYes)  useGivenType = kTRUE;
1362       else useGivenType = kFALSE;
1363
1364       // Cancel creation
1365       if (!useGivenType)
1366       {
1367         typeStr->Clear();
1368         delete typeStr;
1369         typeStr = 0;
1370
1371         typeStr2->Clear();
1372         delete typeStr2;
1373         typeStr2 = 0;
1374
1375         return;
1376       }
1377     }
1378   }
1379
1380   // If an object type is provided by the user, use it!
1381   if (strlen(typeStr2->Data()) > 0)
1382   {
1383     // Check, if the class really exists
1384     if (TClass::GetClass(typeStr2->Data()) != 0x0)
1385     {
1386       useGivenType2 = kTRUE; 
1387     }
1388     else
1389     {
1390       Int_t buttonsPressed = 0;
1391       new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Unknown object type", 
1392         Form("The class of your 2nd object, \"%s\" has not been found. Do you really want to create your macro with this object type?", 
1393              typeStr2->Data()), kMBIconExclamation, kMBYes | kMBNo, &buttonsPressed);
1394
1395       if (buttonsPressed & kMBYes)  useGivenType2 = kTRUE;
1396       else useGivenType2 = kFALSE;
1397
1398       // Cancel creation
1399       if (!useGivenType2)
1400       {
1401         typeStr->Clear();
1402         delete typeStr;
1403         typeStr = 0;
1404
1405         typeStr2->Clear();
1406         delete typeStr2;
1407         typeStr2 = 0;
1408
1409         return;
1410       }
1411     }
1412   }
1413
1414   // Note: gSystem->AccessPathName(...) returns kTRUE, if the access FAILED!
1415   if(!gSystem->AccessPathName(Form("./%s.C", name)))
1416   {
1417     // If there is already a file with this name -> Error
1418     Error("AliEveGeneralMacroWizard::Create", Form("A macro \"%s.C\" already exists in the current directory!\nPlease choose another name!", name));
1419     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
1420                  Form("A macro \"%s.C\" already exists in the current directory!\nPlease choose another name!", name), kMBIconExclamation, kMBOk);
1421     return;
1422   }
1423
1424   FILE* fp = 0x0;
1425   if(!(fp = fopen(Form("%s.C", name), "wt"))){
1426     Error("AliEveGeneralMacroWizard::Create", "Couldn't create macro file.");
1427     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
1428                  "Couldn't create macro file.", kMBIconExclamation, kMBOk);
1429     return;
1430   }
1431
1432   TGText* comment = fTextEdit->GetText();
1433   Char_t* line = 0x0; Int_t iline = 0;
1434   while((line = comment->GetLine(TGLongPosition(0,iline++), 200))) fprintf(fp, "// %s\n", line);
1435
1436   TString* tempStr = new TString(fTextIncludes->GetText());
1437
1438   // Add include files:
1439   // Remove white-spaces and replace commas
1440   tempStr->ReplaceAll(" ", "");
1441   tempStr->ReplaceAll(",","\n#include ");
1442   // If there are files, add the first "#include " in front
1443   if (tempStr->Length() > 3)  tempStr->Prepend("#include "); 
1444
1445   fprintf(fp, "\n%s%s\n#endif\n\n", fGeneralIncludes, tempStr->Data());
1446   
1447   tempStr->Clear();
1448
1449   // Use default type
1450   if (!useGivenType)
1451   {
1452     typeStr->Clear();
1453     (*typeStr)="TObject";
1454   }
1455   if (!useGivenType2)
1456   {
1457     typeStr2->Clear();
1458     (*typeStr2)="TObject";
1459   }
1460
1461   switch(type){
1462   case AliEveListAnalyser::kSingleObjectSelect:
1463     // Use "Bool_t 'NAME'(const 'OBJECTTYPE' *object)\n"
1464     tempStr->Append("Bool_t ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object)\n");
1465     fprintf(fp, tempStr->Data());
1466     break;
1467   case AliEveListAnalyser::kCorrelObjectSelect:
1468     // Use "Bool_t 'NAME'(const 'OBJECTTYPE' *object, const 'OBJECTTYPE2' *object2)\n"
1469     tempStr->Append("Bool_t ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object, const ").Append(typeStr2->Data()).Append(" *object2)\n");
1470     fprintf(fp, tempStr->Data());
1471     break;
1472   case AliEveListAnalyser::kSingleObjectAnalyse:    
1473     // Use "void 'NAME'(const 'OBJECTTYPE' *object, Double_t*& r, Int_t& n)\n"
1474     tempStr->Append("void ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object, Double_t*& r, Int_t& n)\n");
1475     fprintf(fp, tempStr->Data());
1476     break;
1477   case AliEveListAnalyser::kSingleObjectHisto:
1478     // Use "TH1* 'NAME'(const 'OBJECTTYPE' *object)\n"
1479     tempStr->Append("TH1* ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object)\n");
1480     fprintf(fp, tempStr->Data());
1481     break;
1482   case AliEveListAnalyser::kCorrelObjectAnalyse:
1483     // Use "void 'NAME'(const 'OBJECTTYPE' *object, const 'OBJECTTYPE2' *object2, Double_t*& r, Int_t& n)\n"
1484     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");
1485     fprintf(fp, tempStr->Data());
1486     break;
1487   case AliEveListAnalyser::kCorrelObjectHisto:
1488     // Use "TH1* 'NAME'(const 'OBJECTTYPE' *object, const 'OBJECTTYPE2' *object2)\n"
1489     tempStr->Append("TH1* ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object, const ").Append(typeStr2->Data()).Append(" *object2)\n");
1490     fprintf(fp, tempStr->Data());
1491     break;
1492   default:
1493     Error("AliEveGeneralMacroWizard::Create", Form("Unknown type[%d]", type));
1494     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
1495                  Form("Unknown type[%d]", type), kMBIconExclamation, kMBOk);
1496     fclose(fp);
1497     gSystem->Exec(Form("rm -f %s.C", name));
1498
1499     tempStr->Clear();
1500     delete tempStr;
1501     tempStr = 0;
1502
1503     typeStr->Clear();
1504     delete typeStr;
1505     typeStr = 0;
1506
1507     return;
1508   }
1509
1510   tempStr->Clear();
1511   delete tempStr;
1512   tempStr = 0;
1513
1514   typeStr->Clear();
1515   delete typeStr;
1516   typeStr = 0;
1517
1518   typeStr2->Clear();
1519   delete typeStr2;
1520   typeStr2 = 0;
1521
1522   fprintf(fp, "{\n%s\n", fGeneralMacroTemplate[type]);
1523
1524   // Add some further information for analyse macros
1525   if (type == AliEveListAnalyser::kSingleObjectAnalyse || type == AliEveListAnalyser::kCorrelObjectAnalyse)
1526   {
1527     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");
1528   }
1529   else
1530   {
1531     fprintf(fp, "// add your own code here\n\n\n}\n");
1532   }
1533   
1534   fclose(fp);
1535
1536   Emit("Create(Int_t)", type);
1537   Create((Char_t*)name);
1538   CloseWindow();
1539 }
1540
1541 //______________________________________________________
1542 void AliEveGeneralMacroWizard::Create(Char_t *name)
1543 {
1544   // Emits the creation signal.
1545
1546   Emit("Create(Char_t*)", Form("%s.C", name));
1547 }
1548
1549 //______________________________________________________
1550 void AliEveGeneralMacroWizard::HandleCreate()
1551 {
1552   // Handles the signal, when the creation button is pressed.
1553
1554   Create(fCombo->GetSelected());
1555 }
1556
1557 //______________________________________________________
1558 void AliEveGeneralMacroWizard::HandleSelectionChanged(Int_t sel)
1559 {
1560   // Handles the change of the selected macro type.
1561
1562   switch (sel)
1563   {
1564 case AliEveListAnalyser::kCorrelObjectSelect:
1565 case AliEveListAnalyser::kCorrelObjectAnalyse:
1566 case AliEveListAnalyser::kCorrelObjectHisto:
1567     // Enable 2nd object type
1568     fTextObjectType2->SetEnabled(kTRUE);
1569   break;
1570 default:
1571     // Disable 2nd object type
1572     fTextObjectType2->SetEnabled(kFALSE);
1573   break;
1574   }
1575 }