First big commit of the mchview program and its accompanying library,
[u/mrichter/AliRoot.git] / MUON / AliMUONPainterPlotSelector.cxx
1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 *                                                                        *
4 * Author: The ALICE Off-line Project.                                    *
5 * Contributors are mentioned in the code where appropriate.              *
6 *                                                                        *
7 * Permission to use, copy, modify and distribute this software and its   *
8 * documentation strictly for non-commercial purposes is hereby granted   *
9 * without fee, provided that the above copyright notice appears in all   *
10 * copies and that both the copyright notice and this permission notice   *
11 * appear in the supporting documentation. The authors make no claims     *
12 * about the suitability of this software for any purpose. It is          *
13 * provided "as is" without express or implied warranty.                  *
14 **************************************************************************/
15
16 // $Id$
17
18 /// \class AliMUONPainterPlotSelector
19 /// 
20 /// Widget to select which data to plot for painters
21 /// 
22 /// \author Laurent Aphecetche
23 ///
24 /// See AliMUONPainterInterfaceHelper for an important implementation note
25 /// about our use of TGButtonGroup
26 ///
27
28 #include "AliMUONPainterPlotSelector.h"
29
30 #include "AliMUONPainterGroup.h"
31 #include "AliMUONPainterInterfaceHelper.h"
32 #include "AliMUONPainterMatrix.h"
33 #include "AliMUONPainterRegistry.h"
34 #include "AliMUONVPainter.h"
35 #include "AliMUONVTrackerData.h"
36 #include "AliLog.h"
37 #include <Riostream.h>
38 #include <TGButton.h>
39 #include <TGButtonGroup.h>
40 #include <TObjArray.h>
41 #include <TObjString.h>
42
43 ///\cond CLASSIMP
44 ClassImp(AliMUONPainterPlotSelector)
45 ///\endcond
46
47 const char* AliMUONPainterPlotSelector::fgkDefaultSourceName = "none";  
48
49 //_____________________________________________________________________________
50 AliMUONPainterPlotSelector::AliMUONPainterPlotSelector(const TGWindow* window, UInt_t w, UInt_t h)
51 : TGCompositeFrame(window,w,h,kHorizontalFrame),
52 fTypes(0x0),
53 fDataSourceNames(0x0),
54 fDataSourceDimensions(0x0),
55 fDimensionButtonMap(new TMap),
56 fCurrentType(""),
57 fCurrentData(0x0),
58 fCurrentDimension(-1)
59 {
60   /// ctor
61   fTypes = new TGButtonGroup(this,"Plot");
62
63   fDataSourceNames = new TGButtonGroup(this,"Sources");
64       
65   AliMUONPainterRegistry* reg = AliMUONPainterRegistry::Instance();
66   
67   reg->Connect("DataSourceWasRegistered(AliMUONVTrackerData*)",
68                "AliMUONPainterPlotSelector",
69                this,
70                "DataSourceWasRegistered(AliMUONVTrackerData*)");
71   
72   reg->Connect("DataSourceWasUnregistered(AliMUONVTrackerData*)",
73                "AliMUONPainterPlotSelector",
74                this,
75                "DataSourceWasUnregistered(AliMUONVTrackerData*)");
76     
77   AliMUONPainterInterfaceHelper::AddRadioButton(*fDataSourceNames,
78                                                 fgkDefaultSourceName,
79                                                 0x0,
80                                                 kTRUE);
81   
82   CreateDimensionButtons(fgkDefaultSourceName);
83   
84   fDataSourceDimensions = new TGButtonGroup(this,0,3,5,0,"Dimensions");
85   
86   for ( Int_t i = 0; i < reg->NumberOfDataSources(); ++i )
87   {
88     AliMUONVTrackerData* data = reg->DataSource(i);
89     DataSourceWasRegistered(data);
90   }
91   
92   fDataSourceNames->Connect("Clicked(Int_t)","AliMUONPainterPlotSelector",
93                             this,
94                             "SourceButtonWasClicked(Int_t)");
95
96   AddFrame(fTypes);
97   AddFrame(fDataSourceNames);
98   AddFrame(fDataSourceDimensions);
99 }
100
101 //_____________________________________________________________________________
102 AliMUONPainterPlotSelector::~AliMUONPainterPlotSelector()
103 {
104   /// dtor
105 }
106
107 //_____________________________________________________________________________
108 void
109 AliMUONPainterPlotSelector::BackupDimensionButtons()
110 {
111   /// Backup the dimension button group
112   
113   TString name = fDataSourceDimensions->GetTitle();
114
115   AliDebug(1,Form("name %s",name.Data()));
116
117   if ( name !=  fgkDefaultSourceName )
118   {
119     TGButtonGroup* group = static_cast<TGButtonGroup*>(fDimensionButtonMap->GetValue(name));
120     if (!group) 
121     {
122       AliError(Form("Did not find group %s",name.Data()));
123     }
124     else
125     {
126       AliMUONPainterInterfaceHelper::Copy(*fDataSourceDimensions,*group);
127     }
128   
129   }
130   
131   fDataSourceDimensions->Disconnect("Clicked(Int_t)",
132                                     this,
133                                     "DimensionButtonWasClicked(Int_t)");  
134 }
135
136
137 //_____________________________________________________________________________
138 void
139 AliMUONPainterPlotSelector::CreateDimensionButtons(const char* dataSourceName)
140 {
141   /// Create the dimension button group for a given data source
142   
143   AliDebug(1,Form("Creating dimension buttons for dataSource %s",dataSourceName));
144   
145   AliMUONVTrackerData* data = AliMUONPainterRegistry::Instance()->FindDataSource(dataSourceName);
146
147   TGButtonGroup* bg = new TGButtonGroup(this,0,3,5,0,dataSourceName);
148   
149   if ( data ) 
150   {
151     for ( Int_t i = 0; i < data->NumberOfDimensions(); ++i ) 
152     {
153       AliMUONPainterInterfaceHelper::AddRadioButton(*bg,
154                                                     data->DimensionName(i),
155                                                     reinterpret_cast<void*>(i));
156     }
157   }
158   
159   fDimensionButtonMap->Add(new TObjString(dataSourceName),bg);
160   
161   AliDebug(1,Form("bg is %p Count=%d",bg,bg->GetCount()));
162   StdoutToAliDebug(1,AliMUONPainterInterfaceHelper::Dump(*bg));
163   
164   bg->Connect("Clicked(Int_t)","AliMUONPainterPlotSelector",this,
165                                 "DimensionButtonWasClicked(Int_t)");
166 }
167
168 //_____________________________________________________________________________
169 void
170 AliMUONPainterPlotSelector::CreateTypeButtons(const TObjArray& types)
171 {
172   /// Create the type button group
173   
174   AliMUONPainterInterfaceHelper::ClearButtons(*fTypes);
175
176   TIter nextType(&types);
177   TObjString* str;
178
179   while ( ( str = static_cast<TObjString*>(nextType()) ) )
180   {
181     AliMUONPainterInterfaceHelper::AddRadioButton(*fTypes,str->String());
182   }
183
184   fTypes->Connect("Clicked(Int_t)","AliMUONPainterPlotSelector",this,
185                   "TypeButtonWasClicked(Int_t)");
186   
187   fTypes->Show();
188 }
189
190 //_____________________________________________________________________________
191 void
192 AliMUONPainterPlotSelector::DataSourceWasChanged()
193 {
194   /// Data source was changed
195   DataSourceWasChanged(fCurrentType.Data(),fCurrentData,fCurrentDimension);
196 }
197
198 //_____________________________________________________________________________
199 void 
200 AliMUONPainterPlotSelector::DataSourceWasChanged(const char* type, 
201                                                  AliMUONVTrackerData* data,
202                                                  Int_t dataIndex)
203 {
204   /// Emit a signal to tell data source was changed
205   AliDebug(1,Form("type=%s data=%s (%s)",
206                   type,
207                   ( data ? data->GetName() : "" ),
208                   ( ( data && dataIndex >= 0 ) ? data->DimensionName(dataIndex).Data() :
209                     "")));
210   
211   Long_t param[] = { (Long_t)type, (Long_t)data,
212     (Long_t)dataIndex };
213   
214   Emit("DataSourceWasChanged(const char*,AliMUONVTrackerData*,Int_t)",param);
215 }
216
217 //_____________________________________________________________________________
218 void
219 AliMUONPainterPlotSelector::DataSourceWasRegistered(AliMUONVTrackerData* data)
220 {
221   /// A new data source has been registered : add it to the interface
222   
223   AliDebug(1,Form("Registering %s",data->GetName()));
224   
225   AliMUONPainterInterfaceHelper::AddRadioButton(*fDataSourceNames,
226                                                 data->GetName(),
227                                                 data);
228   
229   data->Connect("NumberOfEventsChanged()",
230                 "AliMUONPainterPlotSelector",
231                 this,
232                 "NumberOfEventsChanged()");
233   
234   CreateDimensionButtons(data->GetName());
235   
236   fDataSourceNames->Show();
237   
238   Layout();
239 }
240
241 //_____________________________________________________________________________
242 void
243 AliMUONPainterPlotSelector::NumberOfEventsChanged()
244 {
245   /// Change the tool tip of the corresponding data source button
246
247   // find first the sender of the signal
248   
249   AliMUONVTrackerData* data = reinterpret_cast<AliMUONVTrackerData*>(gTQSender);
250   
251   TGButton* button = AliMUONPainterInterfaceHelper::FindButtonByUserData(*fDataSourceNames,data);
252   
253   if (button)
254   {
255     button->SetToolTipText(Form("%d events",data->NumberOfEvents()),250);
256   }
257 }
258
259 //_____________________________________________________________________________
260 void
261 AliMUONPainterPlotSelector::DataSourceWasUnregistered(AliMUONVTrackerData* data)
262 {
263   /// A data source has been unregistered : remove it from the interface
264   
265   AliDebug(1,Form("Unregistering %s",data->GetName()));
266
267   TGButton* button = AliMUONPainterInterfaceHelper::FindButtonByName(*fDataSourceNames,
268                                                                      data->GetName());
269   AliMUONVTrackerData* check = reinterpret_cast<AliMUONVTrackerData*>(button->GetUserData());
270   if ( !button || check != data )
271   {
272     AliError("Something is seriously wrong. Please check");
273     return;
274   }
275   
276   fDataSourceNames->Remove(button);
277   delete button;
278   button->DestroyWindow();
279   
280   fDataSourceNames->Show();
281   
282   TObject* o = fDimensionButtonMap->Remove(new TObjString(data->GetName()));
283   
284   if (!o)
285   {
286     AliError("Remove failed. Please check");    
287   }
288   
289   Layout();
290 }
291
292 //_____________________________________________________________________________
293 void 
294 AliMUONPainterPlotSelector::DimensionButtonWasClicked(Int_t id)
295 {
296   /// One dim button was clicked
297   
298   AliDebug(1,Form("id=%d",id));
299   
300   TGTextButton* button = (TGTextButton*)fDataSourceDimensions->GetButton(id);
301   
302   SetCurrentDimension(reinterpret_cast<Int_t>(button->GetUserData()));
303   
304   if ( fCurrentDimension >= 0 )
305   {
306     AliMUONPainterInterfaceHelper::SetState(*fTypes,kTRUE);
307     AliMUONPainterInterfaceHelper::Select(*fTypes,fCurrentType.Data(),kFALSE);
308     fTypes->Show();
309   }
310   
311   AliDebug(1,Form("fCurrentDimension=%d fCurrentData=%p fCurrentType=%s",
312                   fCurrentDimension,fCurrentData,fCurrentType.Data()));
313   
314   DataSourceWasChanged();
315 }
316
317 //_____________________________________________________________________________
318 void
319 AliMUONPainterPlotSelector::ResetDimensionButtonMap()
320 {
321   /// Reset the button group map
322   
323   TIter next(fDimensionButtonMap);
324   TObjString* str;
325   
326   while ( ( str = static_cast<TObjString*>(next()) ) )
327   {
328     TGButtonGroup* bg = static_cast<TGButtonGroup*>(fDimensionButtonMap->GetValue(str->String()));
329     AliMUONPainterInterfaceHelper::Unselect(*bg,"*");
330   }
331 }
332
333 //_____________________________________________________________________________
334 void
335 AliMUONPainterPlotSelector::RestoreDimensionButtons(const char* dataSourceName,
336                                                     Bool_t updateCurrentDimension)
337 {
338   /// Restore (i.e. contrary of Backup) a given dimension button group
339   
340   AliDebug(1,Form("name %s",dataSourceName));
341   TGButtonGroup* group = static_cast<TGButtonGroup*>(fDimensionButtonMap->GetValue(dataSourceName));
342   
343   AliMUONPainterInterfaceHelper::Copy(*group,*fDataSourceDimensions);
344   
345   fDataSourceDimensions->Connect("Clicked(Int_t)",
346                                  "AliMUONPainterPlotSelector",this,
347                                  "DimensionButtonWasClicked(Int_t)");    
348   
349   if ( updateCurrentDimension ) 
350   {
351     TGButton* button = AliMUONPainterInterfaceHelper::FindDownButton(*fDataSourceDimensions);
352     if ( button ) 
353     {
354       SetCurrentDimension(reinterpret_cast<Int_t>(button->GetUserData()));
355     }
356     else 
357     {
358       SetCurrentDimension(-1);
359     }
360   }
361   
362   fDataSourceDimensions->Show();
363 }
364
365 //_____________________________________________________________________________
366 void 
367 AliMUONPainterPlotSelector::SetCurrentData(AliMUONVTrackerData* data)
368 {
369   /// Set the current data pointer
370   AliDebug(1,Form("fCurrentData %p -> %p",fCurrentData,data));
371   fCurrentData = data;
372 }
373
374 //_____________________________________________________________________________
375 void 
376 AliMUONPainterPlotSelector::SetCurrentDimension(Int_t i)
377 {
378   /// Set the current dimension
379   AliDebug(1,Form("fCurrentDimension %d -> %d",fCurrentDimension,i));
380   fCurrentDimension = i;
381 }
382
383 //_____________________________________________________________________________
384 void 
385 AliMUONPainterPlotSelector::SetCurrentType(const char* type)
386 {
387   /// Set the current type
388   AliDebug(1,Form("fCurrentType %s -> %s",fCurrentType.Data(),type));
389   fCurrentType = type;
390 }
391
392 //_____________________________________________________________________________
393 void
394 AliMUONPainterPlotSelector::SourceButtonWasClicked(Int_t id)
395 {
396   /// A source button was clicked
397   AliDebug(1,Form("BEGIN id %d fCurrentDimension=%d fCurrentData=%p fCurrentType=%s",
398                   id,
399                   fCurrentDimension,fCurrentData,fCurrentType.Data()));
400
401   BackupDimensionButtons();
402   
403   TGButton* button = fDataSourceNames->GetButton(id);
404   if ( !button ) 
405   {
406     AliError(Form("Could not get DataSource button id=%d",id));
407     StdoutToAliDebug(1,AliMUONPainterInterfaceHelper::Dump(*fDataSourceNames));
408     button->GetUserData(); // to trigger a crash so gdb is possible ;-)
409   }
410   
411   AliMUONVTrackerData* data = reinterpret_cast<AliMUONVTrackerData*>(button->GetUserData());
412
413   TString name =  data ? data->GetName() : fgkDefaultSourceName;
414
415   RestoreDimensionButtons(name,kTRUE);
416   
417   if ( data != 0 && 
418        fCurrentDimension >= 0 && 
419        fCurrentDimension < data->NumberOfDimensions() )
420   {
421     AliMUONPainterInterfaceHelper::SetState(*fTypes,kTRUE);
422   }
423   else
424   {
425     AliMUONPainterInterfaceHelper::SetState(*fTypes,kFALSE);
426   }
427   
428   SetCurrentData(data);
429   
430   UpdateTypeButton();
431   
432   fDataSourceNames->Show();
433   fDataSourceDimensions->Show();
434   fTypes->Show();
435   
436   Resize();
437   Layout();
438   
439   AliDebug(1,Form("END fCurrentDimension=%d fCurrentData=%p fCurrentType=%s",
440                   fCurrentDimension,fCurrentData,fCurrentType.Data()));
441
442   DataSourceWasChanged();
443 }
444
445 //_____________________________________________________________________________
446 void
447 AliMUONPainterPlotSelector::TypeButtonWasClicked(Int_t id)
448 {
449   /// A type button was clicked
450   AliDebug(1,Form("fCurrentDimension=%d fCurrentData=%p",
451                   fCurrentDimension,fCurrentData));
452
453   TGTextButton* button = (TGTextButton*)fTypes->GetButton(id);
454   SetCurrentType(button->GetTitle());
455   
456   AliDebug(1,Form("fCurrentType=%s",fCurrentType.Data()));
457   
458   DataSourceWasChanged();
459 }
460
461 //_____________________________________________________________________________
462 void AliMUONPainterPlotSelector::Update(const AliMUONPainterMatrix& painterMatrix)
463 {
464   /// Update ourselves from a new painter matrix
465   
466   AliDebug(1,"BEGIN");
467
468   SetCurrentType("");
469   SetCurrentData(0x0);
470   SetCurrentDimension(-1);
471   
472   AliMUONPainterInterfaceHelper::Unselect(*fDataSourceNames,"*");
473   AliMUONPainterInterfaceHelper::Unselect(*fDataSourceDimensions,"*");
474   
475   ResetDimensionButtonMap();
476   
477   TObjArray types;
478   types.SetOwner(kTRUE);  
479   painterMatrix.GetTypes(types);  
480   CreateTypeButtons(types);
481   
482   if ( painterMatrix.Size() > 0 ) 
483   {
484     AliMUONVPainter* painter = painterMatrix.Painter(painterMatrix.Size()-1);
485     
486     AliMUONPainterGroup* plotterGroup = painter->PlotterGroup();
487     
488     if ( plotterGroup )
489     {
490       // the group have some data to plot, so update our internal pointers
491       // to reflect that
492       SetCurrentData(plotterGroup->Data());
493       SetCurrentDimension(plotterGroup->DataIndex());
494       SetCurrentType(plotterGroup->Type());
495     }
496   }
497   
498   AliDebug(1,Form("After update type=%s data=%p dim=%d",
499                   fCurrentType.Data(),fCurrentData,fCurrentDimension));
500
501   // the *order* of the 3 following lines is *very* important
502
503   AliDebug(1,"Will update source buttons");
504   UpdateSourceButton();
505   AliDebug(1,"Will update dimension buttons");
506   UpdateDimensionButton();
507   AliDebug(1,"Will update type buttons");
508   UpdateTypeButton();
509   
510   Resize();
511   Layout();
512   
513   AliDebug(1,Form("END fCurrentType=%s fCurrentData=%p fCurrentDimension=%d",
514                   fCurrentType.Data(),fCurrentData,
515                   fCurrentDimension));
516 }
517
518 //_____________________________________________________________________________
519 void 
520 AliMUONPainterPlotSelector::UpdateDimensionButton()
521 {
522   /// Update the dim buttons
523   
524   TGTextButton* button = static_cast<TGTextButton*>
525   (AliMUONPainterInterfaceHelper::FindButtonByUserData(*fDataSourceDimensions,
526                                                        reinterpret_cast<void*>(fCurrentDimension)));
527   
528   if ( button ) 
529   {
530     // set this button as "ON"
531     AliMUONPainterInterfaceHelper::Select(*fDataSourceDimensions,button->GetTitle());
532   }
533   else
534   {
535     AliMUONPainterInterfaceHelper::Unselect(*fDataSourceDimensions,"*");
536   }
537   
538   fDataSourceDimensions->Show();
539 }
540
541 //_____________________________________________________________________________
542 void
543 AliMUONPainterPlotSelector::UpdateSourceButton()
544 {
545   /// Update the source buttons
546   
547   TGTextButton* button = static_cast<TGTextButton*>
548   (AliMUONPainterInterfaceHelper::FindButtonByUserData(*fDataSourceNames,
549                                                        fCurrentData));
550   
551   AliMUONPainterInterfaceHelper::Select(*fDataSourceNames,button->GetTitle());
552   
553   RestoreDimensionButtons(button->GetTitle(),kFALSE);
554   
555   fDataSourceNames->Show();
556 }
557
558 //_____________________________________________________________________________
559 void
560 AliMUONPainterPlotSelector::UpdateTypeButton()
561 {
562   /// Update the type buttons
563   
564   AliDebug(1,Form("fCurrentType=%s",fCurrentType.Data()));
565   
566   TGTextButton* button = static_cast<TGTextButton*>
567   (AliMUONPainterInterfaceHelper::FindButtonByName(*fTypes,fCurrentType));
568
569   if ( button ) 
570   {
571     AliMUONPainterInterfaceHelper::Select(*fTypes,button->GetTitle());
572   }
573   else
574   {
575     AliMUONPainterInterfaceHelper::Unselect(*fTypes,"*");
576   }
577
578   if (!fCurrentData)
579   {
580     AliMUONPainterInterfaceHelper::SetState(*fTypes,kFALSE);
581   }
582   
583   fTypes->Show();
584 }
585