new functionality and new class added
[u/mrichter/AliRoot.git] / MUON / AliMUONPainterMasterFrame.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 #include "AliMUONPainterMasterFrame.h"
19
20 #include "AliMUONChamberPainter.h"
21 #include "AliMUONPainterGroup.h"
22 #include "AliMUONPainterMatrix.h"
23 #include "AliMUONPainterMatrixFrame.h"
24 #include "AliMUONPainterInterfaceHelper.h"
25 #include "AliMUONPainterRegistry.h"
26 #include "AliMUONAttPainterSelectorFrame.h"
27 #include "AliMUONVPainter.h"
28 #include "AliCodeTimer.h"
29 #include "AliLog.h"
30 #include <Riostream.h>
31 #include <TApplication.h>
32 #include <TCanvas.h>
33 #include <TEnv.h>
34 #include <TGComboBox.h>
35 #include <TGFileDialog.h>
36 #include <TGLabel.h>
37 #include <TObjArray.h>
38 #include <TObjString.h>
39 #include <TGButtonGroup.h>
40 #include <TGMsgBox.h>
41 #include <TSystem.h>
42
43 /// \class AliMUONPainterMasterFrame
44 ///
45 /// Main window of the 2D display
46 ///
47 /// \author Laurent Aphecetche, Subatech
48
49 ///\cond CLASSIMP
50 ClassImp(AliMUONPainterMasterFrame)
51 ///\endcond
52
53 namespace
54 {
55   UInt_t UniqueID(Int_t nx, Int_t ny)
56   {
57     return ny | (nx << 8);
58   }
59   
60   Int_t Nx(UInt_t uniqueID)
61   {
62     return ( uniqueID & 0xFF00 ) >> 8;
63   }
64
65   Int_t Ny(UInt_t uniqueID)
66   {
67     return uniqueID & 0xFF;
68   }
69
70 }
71
72 const Int_t AliMUONPainterMasterFrame::fgkBorderSize = 10;
73
74 //_____________________________________________________________________________
75 AliMUONPainterMasterFrame::AliMUONPainterMasterFrame(const TGWindow* p, 
76                                                      UInt_t w, UInt_t h, AliMUONPainterMatrix* matrix)
77 : TGCompositeFrame(p,w,h,kVerticalFrame),
78 fNavigationFrame(0x0),
79 fPainterMatrixFrame(0x0),
80 fBackButton(0x0),
81 fForwardButton(0x0),
82 fGroupTitle(0x0),
83 fPrintMeButton(0x0),
84 fPrintAsButton(0x0),
85 fNavigation(),
86 fCurrentNavigationPosition(-1),
87 fAttPainterSelectorFrame(0x0)
88 {  
89   /// ctor
90     
91   UInt_t wi = w - fgkBorderSize*2;
92   UInt_t hi = h - fgkBorderSize*3;
93   
94   fNavigationFrame = new TGHorizontalFrame(this,wi);
95   
96   AddFrame(fNavigationFrame,new TGLayoutHints(kLHintsExpandX|kLHintsTop,
97                                               fgkBorderSize,fgkBorderSize,
98                                               fgkBorderSize,fgkBorderSize));
99   
100   fBackButton = new TGPictureButton(fNavigationFrame,
101                                     gClient->GetPicture("tb_back.xpm"));
102   
103   fForwardButton = new TGPictureButton(fNavigationFrame,
104                                        gClient->GetPicture("tb_forw.xpm"));    
105
106   fPrintMeButton = new TGTextButton(fNavigationFrame,"Print");
107   fPrintAsButton = new TGTextButton(fNavigationFrame,"Print As...");
108
109   fAttPainterSelectorFrame = new AliMUONAttPainterSelectorFrame(fNavigationFrame,w/2,20);
110   
111   fGroupTitle = new TGLabel(fNavigationFrame,"");
112   
113   fNavigationFrame->AddFrame(fBackButton,new TGLayoutHints(kLHintsCenterY));
114   fNavigationFrame->AddFrame(fForwardButton,new TGLayoutHints(kLHintsCenterY));
115   
116   fNavigationFrame->AddFrame(fAttPainterSelectorFrame,new TGLayoutHints(kLHintsCenterY,10));
117
118   fNavigationFrame->AddFrame(fPrintMeButton,new TGLayoutHints(kLHintsCenterY,10));
119   fNavigationFrame->AddFrame(fPrintAsButton,new TGLayoutHints(kLHintsCenterY,10));
120
121   fAttPainterSelectorFrame->Connect("Clicked(AliMUONAttPainter*)",
122                                     "AliMUONPainterMasterFrame",
123                                     this,
124                                     "AttributesChanged(AliMUONAttPainter*)");
125   
126   fNavigationFrame->AddFrame(fGroupTitle,new TGLayoutHints(kLHintsExpandX|kLHintsCenterX|kLHintsCenterY,10));
127   
128   fForwardButton->Connect("Clicked()","AliMUONPainterMasterFrame",
129                           this,
130                           "Forward()");
131
132   fBackButton->Connect("Clicked()","AliMUONPainterMasterFrame",
133                           this,
134                           "Backward()");
135     
136   fPrintMeButton->Connect("Clicked()","AliMUONPainterMasterFrame",
137                         this,
138                         "PrintMe()");
139
140   fPrintAsButton->Connect("Clicked()","AliMUONPainterMasterFrame",
141                         this,
142                         "PrintAs()");
143   
144   UInt_t w1 = wi;
145   //  UInt_t h1 = hi - fNavigationFrame->GetHeight() - 3*fgkBorderSize;
146   UInt_t h1 = hi - 7*12;
147   
148   MakeTopPainterMatrix(w1,h1,matrix);
149
150   AddFrame(fPainterMatrixFrame,new TGLayoutHints(kLHintsExpandX,
151                                                 fgkBorderSize,fgkBorderSize,
152                                                 0,fgkBorderSize));
153   
154   AliMUONPainterInterfaceHelper::SetBackgroundColor("MasterFrame.Navigation",*fNavigationFrame);
155   AliMUONPainterInterfaceHelper::SetBackgroundColor("MasterFrame.Main",*this);
156   
157   AliDebug(1,Form("fNavigation=%p",&fNavigation));
158   
159   AliMUONPainterRegistry::Instance()->Connect("PainterMatrixWantToShow(AliMUONPainterMatrix*)",
160                                               "AliMUONPainterMasterFrame",
161                                               this,
162                                               "PainterMatrixWantToShow(AliMUONPainterMatrix*)");
163   
164   fPainterMatrixFrame->DataSourceWasChanged(matrix->DataPattern().Data(),matrix->Data(),matrix->DataIndex());
165 }
166
167 //_____________________________________________________________________________
168 AliMUONPainterMasterFrame::~AliMUONPainterMasterFrame()
169 {
170   /// dtor
171   Cleanup();
172 }
173
174 //_____________________________________________________________________________
175 void
176 AliMUONPainterMasterFrame::AddPainterMatrix(AliMUONPainterMatrix* painterMatrix)
177 {
178   /// array is adopted (by the registry)
179
180   AliDebug(1,Form("matrix=%x %s",painterMatrix,painterMatrix->GetName()));
181   
182   Int_t i = AliMUONPainterRegistry::Instance()->Register(painterMatrix);
183
184   SetNavigation(i);
185 }
186
187 //_____________________________________________________________________________
188 void
189 AliMUONPainterMasterFrame::PainterMatrixWantToShow(AliMUONPainterMatrix* group)
190 {
191   /// FIXME: should check whether we are the active window before
192   /// responding to this message ?
193
194   AliDebug(1,Form("group=%x %s",group,group->GetName()));
195   
196   Int_t i = AliMUONPainterRegistry::Instance()->FindIndexOf(group);
197
198   Int_t alreadyThere(-1);
199   
200   for ( Int_t j = 0; j < fNavigation.GetSize(); ++j )
201   {
202     if ( fNavigation[j] == i ) alreadyThere = j;
203   }
204   
205   if (alreadyThere<0) 
206   {
207     SetNavigation(i);
208   }
209   else
210   {
211     fCurrentNavigationPosition = alreadyThere;
212   }
213   
214   ShowPainterMatrix(group);  
215 }
216      
217 //_____________________________________________________________________________
218 void
219 AliMUONPainterMasterFrame::PrintAs() const
220 {
221   /// Handle the PrintAs button
222   
223   TGFileInfo fileInfo;
224   
225   new TGFileDialog(gClient->GetRoot(),gClient->GetRoot(),
226                    kFDSave,&fileInfo);
227   
228   if ( fileInfo.fFilename ) 
229   {
230     SaveAs(gSystem->ExpandPathName(Form("%s",fileInfo.fFilename)),"RECREATE");
231   }
232 }
233
234 //_____________________________________________________________________________
235 void
236 AliMUONPainterMasterFrame::PrintMe() const
237 {
238   /// Handle the PrintMe button
239   
240   SaveAs(gSystem->ExpandPathName(Form("%s.png",fPainterMatrixFrame->Matrix()->GetName())),"RECREATE");
241 }
242
243 //_____________________________________________________________________________
244 void
245 AliMUONPainterMasterFrame::SetNavigation(Int_t i)
246 {
247   /// Change navigation position
248   
249   ++fCurrentNavigationPosition;
250   fNavigation.Set(fCurrentNavigationPosition+1);
251   fNavigation[fCurrentNavigationPosition] = i;
252 }
253
254 //_____________________________________________________________________________
255 void
256 AliMUONPainterMasterFrame::ShowPainterMatrix(AliMUONPainterMatrix* painterMatrix)
257 {
258   /// Change the painter matrix we show
259   
260   fPainterMatrixFrame->Use(painterMatrix);
261   
262   painterMatrix->Connect("Clicked(AliMUONVPainter*,Double_t*)",
263                          "AliMUONPainterMasterFrame",this,
264                          "Clicked(AliMUONVPainter*,Double_t*)");
265
266   painterMatrix->Connect("ShiftClicked(AliMUONVPainter*,Double_t*)",
267                          "AliMUONPainterMasterFrame",this,
268                          "ShiftClicked(AliMUONVPainter*,Double_t*)");
269   
270   fPainterMatrixFrame->Connect("TitleHasChanged(const char*)",
271                               "AliMUONPainterMasterFrame",this,
272                               "ChangeTitle(const char*)");
273   UpdateNavigation();
274   
275   UpdateAttributes(*(fPainterMatrixFrame->Matrix()));
276   
277   AliMUONPainterRegistry::Instance()->AddToHistory(painterMatrix);
278   
279   Layout();
280 }
281
282 //_____________________________________________________________________________
283 void
284 AliMUONPainterMasterFrame::ChangeTitle(const char* newTitle)
285 {
286   /// Change the top title
287   
288   fGroupTitle->SetText(newTitle);
289   fGroupTitle->Resize();
290   Layout();
291 }
292
293 //_____________________________________________________________________________
294 void
295 AliMUONPainterMasterFrame::Backward()
296 {
297   /// Move back one step in the history
298   --fCurrentNavigationPosition;
299   
300   AliMUONPainterMatrix* group = 
301     AliMUONPainterRegistry::Instance()->PainterMatrix(fNavigation[fCurrentNavigationPosition]);
302   
303   ShowPainterMatrix(group);
304   
305   UpdateNavigation();
306 }
307
308 //_____________________________________________________________________________
309 void
310 AliMUONPainterMasterFrame::Forward()
311 {
312   /// Move forward one step in history
313   
314   ++fCurrentNavigationPosition;
315   
316   AliMUONPainterMatrix* group = 
317     AliMUONPainterRegistry::Instance()->PainterMatrix(fNavigation[fCurrentNavigationPosition]);
318   
319   ShowPainterMatrix(group);
320   
321   UpdateNavigation();
322 }
323
324 //_____________________________________________________________________________
325 void 
326 AliMUONPainterMasterFrame::Clicked(AliMUONVPainter* painter, Double_t* values)
327 {
328   /// A given painter was (singly) clicked
329
330   if ( painter->CanBeDetached() )
331   {
332     fPainterMatrixFrame->MouseLeave(painter);
333   
334     AliMUONPainterMatrix* matrix = new AliMUONPainterMatrix(painter->Name().Data());
335
336     AliMUONVPainter* p = painter->Detach();
337
338     p->SetResponder(1);
339
340     matrix->Adopt(p);
341   
342     AddPainterMatrix(matrix);
343     ShowPainterMatrix(matrix);
344   }
345   else
346   {
347     painter->DrawHistogram(values);
348   }
349 }
350
351 //_____________________________________________________________________________
352 void 
353 AliMUONPainterMasterFrame::ShiftClicked(AliMUONVPainter* painter, Double_t*)
354 {
355   /// A given painter was shift-clicked
356   
357   if ( !painter->CanBeDetached() ) return;
358   
359   AliMUONPainterMatrix* currentMatrix = fPainterMatrixFrame->Matrix();
360   
361   AliMUONAttPainter a = painter->Attributes();
362   
363   TString basename(Form("%s-DUAL",painter->GetName()));
364   
365   TString newName = AliMUONPainterMatrix::NameIt(currentMatrix->Whatname(),basename.Data(),a);
366   
367   AliMUONPainterMatrix* matrix = AliMUONPainterRegistry::Instance()->PainterMatrix(newName.Data());
368   
369   if (!matrix)
370   {
371     // No. So we must make a new matrix painter from the existing one,
372     // and add to this new matrix the painters of the other one, but
373     // using the new attributes...
374     
375     // create "opposite" attributes
376     AliMUONAttPainter a1(a);
377     AliMUONAttPainter a2(a);
378   
379     a2.Invert();
380     
381     a1.SetCathodeAndPlaneDisabled(kTRUE);
382     a2.SetCathodeAndPlaneDisabled(kTRUE);
383     
384     AliMUONVPainter* p1 = AliMUONVPainter::CreatePainter(painter->ClassName(),
385                                                          a1,
386                                                          painter->ID0(),
387                                                          painter->ID1());
388     
389     AliMUONVPainter* p2 = AliMUONVPainter::CreatePainter(painter->ClassName(),
390                                                          a2,
391                                                          painter->ID0(),
392                                                          painter->ID1());
393     
394     if (!p1 || !p2)
395     {
396       Int_t ret;
397       new TGMsgBox(gClient->GetRoot(), this,
398                    "Invalid combination", "Cannot create 2 views from this painter",
399                    kMBIconExclamation, kMBOk, &ret);
400       PainterMatrixWantToShow(currentMatrix);
401       delete p1;
402       delete p2;
403       return;
404     }
405     
406     p1->UpdateGroupsFrom(*(painter->Master()));
407     p2->UpdateGroupsFrom(*(painter->Master()));
408     
409     p1->SetResponder(1);
410     p2->SetResponder(1);
411     
412     Int_t nx(2);
413     Int_t ny(1);
414     
415     AliMpArea area(painter->Area());
416     
417     if ( area.GetDimensionX() > 1.2*area.GetDimensionY() ) 
418     {
419       nx = 1;
420       ny = 2;
421     }
422     
423     matrix = new AliMUONPainterMatrix(basename.Data(),nx,ny);
424     
425     matrix->Adopt(p1);
426     matrix->Adopt(p2);
427     
428     AddPainterMatrix(matrix);
429   }
430   
431   matrix->SetData(currentMatrix->DataPattern(),
432                   currentMatrix->Data(),
433                   currentMatrix->DataIndex());
434   
435   fPainterMatrixFrame->MouseLeave(painter);
436   
437   PainterMatrixWantToShow(matrix);
438 }
439
440 //_____________________________________________________________________________
441 void 
442 AliMUONPainterMasterFrame::SaveAs(const char* filename, Option_t* option) const
443 {
444   /// Save painter matrix (in the sense of "print") in filename
445   fPainterMatrixFrame->SaveAs(filename,option);
446 }
447
448 //_____________________________________________________________________________
449 void
450 AliMUONPainterMasterFrame::Update()
451 {
452   /// Update ourselves
453   
454   fPainterMatrixFrame->Update();
455   fPainterMatrixFrame->UpdateInterface(kFALSE);
456 }
457
458 //_____________________________________________________________________________
459 void
460 AliMUONPainterMasterFrame::UpdateAttributes(const AliMUONPainterMatrix& painterMatrix)
461 {
462   /// Update the view buttons from the matrix we actually plot
463   
464   fAttPainterSelectorFrame->Update(painterMatrix.Attributes());
465 }
466
467 //_____________________________________________________________________________
468 void
469 AliMUONPainterMasterFrame::MakeTopPainterMatrix(UInt_t w, UInt_t h, AliMUONPainterMatrix* matrix)
470 {
471   /// Create the first painter matrix that appears when we are create
472   /// FIXME: how to make this more flexible ?
473   
474   fPainterMatrixFrame = new AliMUONPainterMatrixFrame(this,w,h);
475
476   if (matrix)
477   {
478     PainterMatrixWantToShow(matrix);
479   }
480   else
481   {
482     AliError("Cannot work without a painterMatrix");
483   }
484 }
485
486 //_____________________________________________________________________________
487 void
488 AliMUONPainterMasterFrame::UpdateNavigation()
489 {
490   /// Update navigation frame
491
492   fBackButton->SetEnabled(kTRUE);
493   fForwardButton->SetEnabled(kTRUE);
494
495   if ( fCurrentNavigationPosition == 0 ) 
496   {
497     fBackButton->SetEnabled(kFALSE);
498   }
499   if ( fCurrentNavigationPosition == fNavigation.GetSize()-1 ) 
500   {
501     fForwardButton->SetEnabled(kFALSE);
502   }
503 }
504
505 //_____________________________________________________________________________
506 void
507 AliMUONPainterMasterFrame::AttributesChanged(AliMUONAttPainter* newValues)
508 {
509   /// Attributes changed (e.g. from cath0 to cath1 or bending to nonbending, etc...)
510   
511   AliMUONPainterMatrix* currentMatrix = fPainterMatrixFrame->Matrix();
512   
513   AliMUONAttPainter a = currentMatrix->Validate(*newValues);
514   
515   if (!a.IsValid())
516   {
517     Int_t ret;
518     new TGMsgBox(gClient->GetRoot(), this,
519                  "Invalid combination", "Change of attributes not possible for this object",
520                  kMBIconExclamation, kMBOk, &ret);
521     PainterMatrixWantToShow(currentMatrix);
522     return;
523   }
524   
525   // First check if we already have this matrix available
526   
527   TString newName = AliMUONPainterMatrix::NameIt(currentMatrix->Whatname(),currentMatrix->Basename(),a);
528   
529   AliMUONPainterMatrix* matrix = AliMUONPainterRegistry::Instance()->PainterMatrix(newName.Data());
530
531   if (!matrix)
532   {
533     // No. So we must make a new matrix painter from the existing one,
534     // and add to this new matrix the painters of the other one, but
535     // using the new attributes...
536     
537     matrix = currentMatrix->Clone(a);
538   
539     AddPainterMatrix(matrix);
540   }
541   
542   matrix->SetData(currentMatrix->DataPattern(),
543                   currentMatrix->Data(),
544                   currentMatrix->DataIndex());
545   
546   PainterMatrixWantToShow(matrix);
547 }