]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EVE/EveDet/AliEveListAnalyserEditor.cxx
fix user histogram management and style (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\n"
1301 "// Set bins, xmin and xmax here - you can also use a different histogram type (but must inherit from TH1)\n"
1302 "  Int_t n = 1;\n"
1303 "  Double_t xmin = 0;\n"
1304 "  Double_t xmax = 100;\n\n" 
1305 "  TH1S* h = new TH1S(\"h\", \"Your title\", n, xmin, xmax);\n"
1306 "  h->GetXaxis()->SetTitle("");\n"
1307 "  h->GetYaxis()->SetTitle("");\n"
1308
1309 ,"  if (!object) return kFALSE;\n"
1310 "  if (!object2) return kFALSE;\n"
1311
1312 ,"  n = 0;\n"
1313 "  r = 0x0;\n"
1314 "  if (!object) return;\n"
1315 "  if (!object2) return;\n"
1316
1317 ,"  if (!object) return 0x0;\n"
1318 "  if (!object2) return 0x0;\n\n"
1319 "// Set bins, xmin and xmax here - you can also use a different histogram type (but must inherit from TH1)\n"
1320 "  Int_t n = 1;\n"
1321 "  Double_t xmin = 0;\n"
1322 "  Double_t xmax = 100;\n\n"
1323 "  TH1S* h = new TH1S(\"h\", \"Your title\", n, xmin, xmax);\n"
1324 "  h->GetXaxis()->SetTitle("");\n"
1325 "  h->GetYaxis()->SetTitle("");\n"
1326 };
1327
1328 //______________________________________________________
1329 void AliEveGeneralMacroWizard::Create(Int_t type)
1330 {
1331   // Creates the macro with the selected type (combo box).
1332
1333   const Char_t* name = fTextName->GetText();
1334   if(strcmp(name,"") == 0)
1335   {
1336     Error("AliEveGeneralMacroWizard::Create", "Please specify a name for your macro.");
1337     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
1338                  "Please specify a name for your macro.", kMBIconExclamation, kMBOk);
1339     return;
1340   }
1341
1342   Bool_t useGivenType = kFALSE;
1343   Bool_t useGivenType2 = kFALSE;
1344
1345   // Remove white-spaces
1346   TString* typeStr = new TString();
1347
1348   typeStr->Append(fTextObjectType->GetText());
1349   typeStr->ReplaceAll(" ", "");
1350   fTextObjectType->SetText(typeStr->Data(), kFALSE);
1351
1352   TString* typeStr2 = new TString();
1353
1354   typeStr2->Append(fTextObjectType2->GetText());
1355   typeStr2->ReplaceAll(" ", "");
1356   fTextObjectType2->SetText(typeStr2->Data(), kFALSE);
1357
1358   // If an object type is provided by the user, use it!
1359   if (strlen(typeStr->Data()) > 0)
1360   {
1361     // Check, if the class really exists
1362     if (TClass::GetClass(typeStr->Data()) != 0x0)
1363     {
1364       useGivenType = kTRUE; 
1365     }
1366     else
1367     {
1368       Int_t buttonsPressed = 0;
1369       new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Unknown object type", 
1370         Form("The class of your 1st object, \"%s\" has not been found. Do you really want to create your macro with this object type?", 
1371              typeStr->Data()), kMBIconExclamation, kMBYes | kMBNo, &buttonsPressed);
1372
1373       if (buttonsPressed & kMBYes)  useGivenType = kTRUE;
1374       else useGivenType = kFALSE;
1375
1376       // Cancel creation
1377       if (!useGivenType)
1378       {
1379         if (typeStr != 0)
1380         {
1381           typeStr->Clear();
1382           delete typeStr;
1383         }
1384         typeStr = 0;
1385
1386         if (typeStr2 != 0)
1387         {
1388           typeStr2->Clear();
1389           delete typeStr2;
1390         }
1391         typeStr2 = 0;
1392
1393         return;
1394       }
1395     }
1396   }
1397
1398   // If an object type is provided by the user, use it!
1399   if (strlen(typeStr2->Data()) > 0)
1400   {
1401     // Check, if the class really exists
1402     if (TClass::GetClass(typeStr2->Data()) != 0x0)
1403     {
1404       useGivenType2 = kTRUE; 
1405     }
1406     else
1407     {
1408       Int_t buttonsPressed = 0;
1409       new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Unknown object type", 
1410         Form("The class of your 2nd object, \"%s\" has not been found. Do you really want to create your macro with this object type?", 
1411              typeStr2->Data()), kMBIconExclamation, kMBYes | kMBNo, &buttonsPressed);
1412
1413       if (buttonsPressed & kMBYes)  useGivenType2 = kTRUE;
1414       else useGivenType2 = kFALSE;
1415
1416       // Cancel creation
1417       if (!useGivenType2)
1418       {
1419         if (typeStr != 0)
1420         {
1421           typeStr->Clear();
1422           delete typeStr;
1423         }
1424         typeStr = 0;
1425
1426         if (typeStr2 != 0)
1427         {
1428           typeStr2->Clear();
1429           delete typeStr2;
1430         }
1431         typeStr2 = 0;
1432
1433         return;
1434       }
1435     }
1436   }
1437
1438   // Note: gSystem->AccessPathName(...) returns kTRUE, if the access FAILED!
1439   if(!gSystem->AccessPathName(Form("./%s.C", name)))
1440   {
1441     // If there is already a file with this name -> Error
1442     Error("AliEveGeneralMacroWizard::Create", Form("A macro \"%s.C\" already exists in the current directory!\nPlease choose another name!", name));
1443     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
1444                  Form("A macro \"%s.C\" already exists in the current directory!\nPlease choose another name!", name), kMBIconExclamation, kMBOk);
1445     return;
1446   }
1447
1448   FILE* fp = 0x0;
1449   if(!(fp = fopen(Form("%s.C", name), "wt"))){
1450     Error("AliEveGeneralMacroWizard::Create", "Couldn't create macro file.");
1451     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
1452                  "Couldn't create macro file.", kMBIconExclamation, kMBOk);
1453     return;
1454   }
1455
1456   TGText* comment = fTextEdit->GetText();
1457   Char_t* line = 0x0; Int_t iline = 0;
1458   while((line = comment->GetLine(TGLongPosition(0,iline++), 200))) fprintf(fp, "// %s\n", line);
1459
1460   TString* tempStr = new TString();
1461
1462   // Add include files:
1463   // Remove white-spaces and replace commas
1464   tempStr->Append(fTextIncludes->GetText());  
1465   tempStr->ReplaceAll(" ", "");
1466   tempStr->ReplaceAll(",","\n#include ");
1467   // If there are files, add the first "#include " in front
1468   if (tempStr->Length() > 3)  tempStr->Prepend("#include "); 
1469
1470   fprintf(fp, "\n%s%s\n#endif\n\n", fGeneralIncludes, tempStr->Data());
1471   
1472   tempStr->Clear();
1473
1474   // Use default type
1475   if (!useGivenType)
1476   {
1477     typeStr->Clear();
1478     typeStr->Append("TObject");
1479   }
1480   if (!useGivenType2)
1481   {
1482     typeStr2->Clear();
1483     typeStr2->Append("TObject");
1484   }
1485
1486   switch(type){
1487   case AliEveListAnalyser::kSingleObjectSelect:
1488     // Use "Bool_t 'NAME'(const 'OBJECTTYPE' *object)\n"
1489     tempStr->Append("Bool_t ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object)\n");
1490     fprintf(fp, tempStr->Data());
1491     break;
1492   case AliEveListAnalyser::kCorrelObjectSelect:
1493     // Use "Bool_t 'NAME'(const 'OBJECTTYPE' *object, const 'OBJECTTYPE2' *object2)\n"
1494     tempStr->Append("Bool_t ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object, const ").Append(typeStr2->Data()).Append(" *object2)\n");
1495     fprintf(fp, tempStr->Data());
1496     break;
1497   case AliEveListAnalyser::kSingleObjectAnalyse:    
1498     // Use "void 'NAME'(const 'OBJECTTYPE' *object, Double_t*& r, Int_t& n)\n"
1499     tempStr->Append("void ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object, Double_t*& r, Int_t& n)\n");
1500     fprintf(fp, tempStr->Data());
1501     break;
1502   case AliEveListAnalyser::kSingleObjectHisto:
1503     // Use "TH1* 'NAME'(const 'OBJECTTYPE' *object)\n"
1504     tempStr->Append("TH1* ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object)\n");
1505     fprintf(fp, tempStr->Data());
1506     break;
1507   case AliEveListAnalyser::kCorrelObjectAnalyse:
1508     // Use "void 'NAME'(const 'OBJECTTYPE' *object, const 'OBJECTTYPE2' *object2, Double_t*& r, Int_t& n)\n"
1509     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");
1510     fprintf(fp, tempStr->Data());
1511     break;
1512   case AliEveListAnalyser::kCorrelObjectHisto:
1513     // Use "TH1* 'NAME'(const 'OBJECTTYPE' *object, const 'OBJECTTYPE2' *object2)\n"
1514     tempStr->Append("TH1* ").Append(name).Append("(const ").Append(typeStr->Data()).Append(" *object, const ").Append(typeStr2->Data()).Append(" *object2)\n");
1515     fprintf(fp, tempStr->Data());
1516     break;
1517   default:
1518     Error("AliEveGeneralMacroWizard::Create", Form("Unknown type[%d]", type));
1519     new TGMsgBox(gClient->GetRoot(), GetMainFrame(), "Error", 
1520                  Form("Unknown type[%d]", type), kMBIconExclamation, kMBOk);
1521     fclose(fp);
1522     gSystem->Exec(Form("rm -f %s.C", name));
1523
1524     tempStr->Clear();
1525     if (tempStr != 0) delete tempStr;
1526     tempStr = 0;
1527
1528     typeStr->Clear();
1529     if (typeStr != 0) delete typeStr;
1530     typeStr = 0;
1531
1532     return;
1533   }
1534
1535   tempStr->Clear();
1536   if (tempStr != 0) delete tempStr;
1537   tempStr = 0;
1538
1539   typeStr->Clear();
1540   if (typeStr != 0) delete typeStr;
1541   typeStr = 0;
1542
1543   typeStr2->Clear();
1544   if (typeStr2 != 0) delete typeStr2;
1545   typeStr2 = 0;
1546
1547   fprintf(fp, "{\n%s\n", fGeneralMacroTemplate[type]);
1548
1549   // Add some further information for analyse macros
1550   if (type == AliEveListAnalyser::kSingleObjectAnalyse || type == AliEveListAnalyser::kCorrelObjectAnalyse)
1551   {
1552     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");
1553   }
1554   else
1555   {
1556     fprintf(fp, "// add your own code here\n\n\n}\n");
1557   }
1558   
1559   fclose(fp);
1560
1561   Emit("Create(Int_t)", type);
1562   Create((Char_t*)name);
1563   CloseWindow();
1564 }
1565
1566 //______________________________________________________
1567 void AliEveGeneralMacroWizard::Create(Char_t *name)
1568 {
1569   // Emits the creation signal.
1570
1571   Emit("Create(Char_t*)", Form("%s.C", name));
1572 }
1573
1574 //______________________________________________________
1575 void AliEveGeneralMacroWizard::HandleCreate()
1576 {
1577   // Handles the signal, when the creation button is pressed.
1578
1579   Create(fCombo->GetSelected());
1580 }
1581
1582 //______________________________________________________
1583 void AliEveGeneralMacroWizard::HandleSelectionChanged(Int_t sel)
1584 {
1585   // Handles the change of the selected macro type.
1586
1587   switch (sel)
1588   {
1589 case AliEveListAnalyser::kCorrelObjectSelect:
1590 case AliEveListAnalyser::kCorrelObjectAnalyse:
1591 case AliEveListAnalyser::kCorrelObjectHisto:
1592     // Enable 2nd object type
1593     fTextObjectType2->SetEnabled(kTRUE);
1594   break;
1595 default:
1596     // Disable 2nd object type
1597     fTextObjectType2->SetEnabled(kFALSE);
1598   break;
1599   }
1600 }