Previous commit had the bad side-effect of changing the behaviour of Raw QA to comput...
[u/mrichter/AliRoot.git] / MUON / AliMUONPainterMatrixFrame.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 "AliMUONPainterMatrixFrame.h"
19
20 #include "AliMUONPainterColorSlider.h"
21 #include "AliMUONPainterMatrix.h"
22 #include "AliMUONPainterGroup.h"
23 #include "AliMUONPainterHighlighter.h"
24 #include "AliMUONPainterInterfaceHelper.h"
25 #include "AliMUONPainterPlotSelector.h"
26 #include "AliMUONPainterRegistry.h"
27 #include "AliMUONVTrackerData.h"
28 #include "AliMUONVPainter.h"
29 #include "AliLog.h"
30 #include <Riostream.h>
31 #include <TCanvas.h>
32 #include <TEnv.h>
33 #include <TGButton.h>
34 #include <TGButtonGroup.h>
35 #include <TGFrame.h>
36 #include <TGListBox.h>
37 #include <TObjArray.h>
38 #include <TObjString.h>
39 #include <TRootEmbeddedCanvas.h>
40 #include <TString.h>
41 #include <cassert>
42 #include <float.h>
43
44 /// \class AliMUONPainterMatrixFrame
45 ///
46 /// A widget to draw a painter matrix, and the corresponding interface
47 /// to select what to outline or paint, and which part of the painter
48 /// is responding to mouse events
49 ///
50 /// \author Laurent Aphecetche, Subatech
51
52 ///\cond CLASSIMP
53 ClassImp(AliMUONPainterMatrixFrame)
54 ///\endcond
55
56 //_____________________________________________________________________________
57 AliMUONPainterMatrixFrame::AliMUONPainterMatrixFrame(const TGWindow* window, 
58                                                    UInt_t w, UInt_t h)
59 : TGCompositeFrame(window,w,h,kVerticalFrame|kDoubleBorder),
60   fPainterMatrix(0x0),
61   fView(0x0),
62   fInterface(0x0),
63   fResponderButtons(0x0),
64   fOutlineButtons(0x0),
65   fPlotSelector(0x0),
66   fPainterHighlighter(new AliMUONPainterHighlighter),
67   fCanvasWidth(0),
68   fCanvasHeight(0),
69   fMainFrame(0x0),
70   fColorSlider(0x0)
71 {
72     /// ctor
73     const Int_t kBorderSize = 10;
74
75     UInt_t wi = w - kBorderSize*0;
76     UInt_t hi = h - kBorderSize*1;
77     
78     fCanvasWidth = wi;
79     fCanvasHeight = (UInt_t)(hi*0.75);
80     
81     fMainFrame = new TGHorizontalFrame(this,fCanvasWidth,hi);
82     
83     const Int_t kColorWidth = 100;
84     
85     fColorSlider = new AliMUONPainterColorSlider(fMainFrame,kColorWidth,fCanvasHeight);
86     
87     fView = new TRootEmbeddedCanvas("ec",fMainFrame,fCanvasWidth-kColorWidth,fCanvasHeight,kChildFrame);
88     
89     fInterface = new TGHorizontalFrame(this,fCanvasWidth);
90     
91     fMainFrame->AddFrame(fView, new TGLayoutHints(kLHintsLeft));
92     fMainFrame->AddFrame(fColorSlider,new TGLayoutHints(kLHintsTop|kLHintsRight|kLHintsExpandX|kLHintsCenterY,kBorderSize/2));
93
94     AliMUONPainterInterfaceHelper::SetBackgroundColor("MatrixFrame.ColorSlider",*fColorSlider);
95     
96     fResponderButtons = new TGButtonGroup(fInterface,"Responder");
97     
98     fOutlineButtons = new TGButtonGroup(fInterface,"Outline");
99     
100     fInterface->AddFrame(fResponderButtons);
101     fInterface->AddFrame(fOutlineButtons);
102
103     fPlotSelector = 
104       new AliMUONPainterPlotSelector(fInterface);//,wi,interfaceHeight);
105     
106     fInterface->AddFrame(fPlotSelector);//,new TGLayoutHints(kLHintsRight|kLHintsExpandX));
107
108     fOutlineButtons->Show();
109     fResponderButtons->Show();
110         
111     AddFrame(fMainFrame,new TGLayoutHints(kLHintsExpandX|kLHintsTop,
112                                          0,0,0,0));
113
114     AddFrame(fInterface,new TGLayoutHints(kLHintsExpandX|kLHintsBottom,
115              0,0,kBorderSize,0));
116
117
118     // Set the connections
119     
120     fPlotSelector->Connect("DataSourceWasChanged(const char*,AliMUONVTrackerData*,Int_t)",                                
121                                  "AliMUONPainterMatrixFrame",
122                                  this,
123                                  "DataSourceWasChanged(const char*,AliMUONVTrackerData*,Int_t)");
124     
125     fColorSlider->Connect("DataRangeWasChanged(Double_t*)",
126                           "AliMUONPainterMatrixFrame",
127                          this,
128                          "DataRangeWasChanged(Double_t*)");
129
130     fColorSlider->Connect("DataRangeAutoRequested()",
131                           "AliMUONPainterMatrixFrame",
132                          this,
133                          "DataRangeAutoRequested()");
134     
135     // Set the colors (mainly for debugging frame layout)
136
137     AliMUONPainterInterfaceHelper::SetBackgroundColor("MatrixFrame.Main",*this);
138     
139     fMainFrame->HideFrame(fColorSlider);
140     
141     fMainFrame->Resize();
142 }
143
144 //_____________________________________________________________________________
145 AliMUONPainterMatrixFrame::~AliMUONPainterMatrixFrame()
146 {
147   /// dtor
148   delete fPainterHighlighter;
149   AliError("Please write a decent dtor for this class !");
150 }
151
152 //_____________________________________________________________________________
153 void
154 AliMUONPainterMatrixFrame::ChangeTitle(const TString& title)
155 {
156   /// Change title
157   
158   TitleHasChanged(title.Data());
159 }
160
161 //_____________________________________________________________________________
162 void
163 AliMUONPainterMatrixFrame::ChangeTitle(AliMUONVPainter* painter, 
164                                        const char* basename,
165                                        Double_t x, Double_t y)
166 {
167   /// Change the title according to painter
168   
169   TString name;
170   
171   if (painter) 
172   {
173
174     if ( basename ) name = basename;
175     else name = painter->PathName();
176     
177     AliMUONVPainter* master = painter->Master();
178     
179     AliMUONPainterGroup* group = master->PlotterGroup();
180
181     AliDebug(1,Form("Painter is %s plotterGroup is %x %s",
182                     painter->PathName().Data(),
183                     group,
184                     ( group ? group->Type() : "")));
185     
186     
187     if ( group && group->Data() ) 
188     {
189       name += "\n";
190       name += painter->Describe(*(group->Data()),group->DataIndex(),x,y);
191     }
192   }
193   else
194   {
195     name = fPainterMatrix->Name();
196   }
197   
198   TitleHasChanged(name.Data());
199 }
200
201 //_____________________________________________________________________________
202 void
203 AliMUONPainterMatrixFrame::Clear(Option_t*)
204 {
205   /// Clear the view(s)
206   
207   fPainterMatrix = 0x0;
208
209   AliMUONPainterInterfaceHelper::ClearButtons(*fOutlineButtons);
210   AliMUONPainterInterfaceHelper::ClearButtons(*fResponderButtons);
211   
212   fView->GetCanvas()->SetEditable(kTRUE);
213   fView->GetCanvas()->Clear();
214   fView->GetCanvas()->Modified();
215   fView->GetCanvas()->Update();
216   fView->GetCanvas()->SetEditable(kFALSE);
217
218   Layout();  
219 }
220
221 //_____________________________________________________________________________
222 void 
223 AliMUONPainterMatrixFrame::CreateButtons()
224 {
225   /// Create the interface buttons
226   
227   AliDebug(1,"");
228   
229 //  AliMUONVPainter* painter = fPainterMatrix->Painter(0);
230   
231   /// create buttons    
232   TObjArray types;
233   
234   fPainterMatrix->GetTypes(types);
235   
236   TIter nextType(&types);
237   TObjString* str;
238   
239   while ( ( str = static_cast<TObjString*>(nextType()) ) )
240   {
241     AliMUONPainterInterfaceHelper::AddRadioButton(*fResponderButtons,str->String());
242     AliMUONPainterInterfaceHelper::AddCheckButton(*fOutlineButtons,str->String());
243   }
244   
245   fOutlineButtons->Connect("Clicked(Int_t)","AliMUONPainterMatrixFrame",
246                         this,"OutlineButtonWasClicked(Int_t)");
247   
248   fResponderButtons->Connect("Clicked(Int_t)","AliMUONPainterMatrixFrame",
249                              this,"ResponderButtonWasClicked(Int_t)");        
250 }
251
252 //_____________________________________________________________________________
253 void 
254 AliMUONPainterMatrixFrame::DataRangeAutoRequested()
255 {
256   /// Get there when the "Auto" button below the color slider is clicked,
257   /// to compute the data range actually painted.
258   
259   Double_t dataMin, dataMax;
260
261   AliDebug(1,"");
262   
263   fPainterMatrix->ComputeDataRange();
264
265   fPainterMatrix->GetDataRange(dataMin,dataMax);
266   
267   AliDebug(1,Form("dataMin,Max for SetRange=%e,%e",dataMin,dataMax));
268   
269   Bool_t emit(kTRUE);
270   
271   fColorSlider->SetRange(dataMin,dataMax,emit);
272   
273   Update();
274 }
275
276 //_____________________________________________________________________________
277 void 
278 AliMUONPainterMatrixFrame::DataRangeWasChanged(Double_t* range)
279 {
280   /// Get there when the data range is changed
281   
282   AliDebug(1,Form("range=%e,%e",range[0],range[1]));
283
284   fPainterMatrix->SetDataRange(range[0],range[1]);
285   
286   if ( !fColorSlider->IsLocked() )
287   {
288     Update();
289   }
290 }
291
292 //_____________________________________________________________________________
293 void
294 AliMUONPainterMatrixFrame::DataSourceWasChanged(const char* type,
295                                                AliMUONVTrackerData* data,
296                                                Int_t indexInData)
297 {
298   /// Update what to plot
299  
300   TString pattern(type);
301
302   AliDebug(1,Form("type=%s data=%s index=%d",type,
303                   (data ? data->GetName() : "null"),indexInData));
304     
305   AliMUONVTrackerData* d = data;
306   
307   if ( !d || !data || indexInData < 0 || pattern == "" )
308   {
309     pattern = "*";
310     d = 0;
311     indexInData = -1;
312   }
313   
314   fPainterMatrix->SetData(pattern,d,indexInData);
315     
316   Update();
317   
318   ChangeTitle(fPainterMatrix->Painter(0));
319 }
320
321 //_____________________________________________________________________________
322 void
323 AliMUONPainterMatrixFrame::EventInfo(Int_t event, Int_t px ,Int_t py, TObject* object)
324 {
325   /// Used to detect entering/leaving a given painter 
326   
327   if (!gPad || !object) return;
328   
329 //  cout << "EventInfo : event " << event << " px " << px << " py " << py
330 //    << " object " << object << " " << object->GetName() << endl;
331 // 
332   if ( event == 7 ) 
333   {
334     if ( object->InheritsFrom("AliMUONVPainter") )
335     {
336       AliMUONVPainter* p = static_cast<AliMUONVPainter*>(object);
337       p->ExecuteEvent(7,px,py);
338       return;
339     }      
340   }
341   
342   if ( event == kMouseLeave )
343   {
344     if ( object->InheritsFrom("AliMUONVPainter") )
345     {
346       AliMUONVPainter* p = static_cast<AliMUONVPainter*>(object);
347       MouseLeave(p);
348       fPainterHighlighter->SetPainter(0x0);
349       gPad->Modified();
350       gPad->Update();
351     }
352   }
353
354   if ( event == kMouseEnter )
355   {
356     if ( object->InheritsFrom("AliMUONVPainter") )
357     {
358       AliMUONVPainter* painter = static_cast<AliMUONVPainter*>(object);
359       if ( painter->IsResponder() && !painter->HandleMouseMotion() )
360       {
361         MouseEnter(static_cast<AliMUONVPainter*>(object));
362         fPainterHighlighter->SetPainter(painter);
363         gPad->Modified();
364         gPad->Update();
365       }
366       else if ( !painter->HandleMouseMotion() )
367       {
368         MouseEnter(static_cast<AliMUONVPainter*>(object)); 
369       }
370     }
371   }
372   
373    if ( event == kMouseMotion ) 
374   {
375     if ( object->InheritsFrom("AliMUONVPainter") )
376     {
377       AliMUONVPainter* painter = static_cast<AliMUONVPainter*>(object);
378
379       if ( painter->HandleMouseMotion() && painter->IsResponder() )
380       {
381         Double_t pos[2];
382         TVirtualPad* padsave = gPad;
383         painter->Pad()->cd();
384         painter->PixelToPad(px,py,pos[0],pos[1]);
385         MouseMotion(static_cast<AliMUONVPainter*>(object),pos);
386         fPainterHighlighter->SetPainter(painter,pos[0],pos[1]);
387         gPad->Modified();
388         gPad->Update();
389         gPad = padsave;
390       }
391     }    
392   }
393 }
394
395 //_____________________________________________________________________________
396 void
397 AliMUONPainterMatrixFrame::MouseEnter(AliMUONVPainter* painter)
398 {
399   /// Emit a signal to notify that mouse pointer is entering a given painter
400
401   AliDebug(1,Form("painter=%x %s",painter,painter->PathName().Data()));
402   
403   ChangeTitle(painter);
404
405   Long_t params[] = { (Long_t)painter };
406   
407   Emit("MouseEnter(AliMUONVPainter*)",params);  
408 }
409
410
411 //_____________________________________________________________________________
412 void
413 AliMUONPainterMatrixFrame::MouseLeave(AliMUONVPainter* painter)
414 {
415   /// Emit a signal to notify that mouse pointer is leaving a given painter
416   
417   ChangeTitle(fPainterMatrix->Name());
418
419   Long_t params[] = { (Long_t)painter };
420   
421   Emit("MouseLeave(AliMUONVPainter*)",params);
422 }
423
424 //_____________________________________________________________________________
425 void
426 AliMUONPainterMatrixFrame::MouseMotion(AliMUONVPainter* painter, Double_t* position)
427 {
428   /// Emit a signal to notify that mouse pointer is moving within a given painter
429   
430   ChangeTitle(painter,painter->NameAtPosition(position[0],position[1]),
431               position[0],position[1]);
432   
433   Long_t params[] = { (Long_t)painter, (Long_t)position };
434   
435   Emit("MouseMotion(AliMUONVPainter*,Double_t*)",params);
436 }
437
438
439 //_____________________________________________________________________________
440 void
441 AliMUONPainterMatrixFrame::ResponderButtonWasClicked(Int_t id)
442 {
443   /// One responder button was clicked
444   
445   TGTextButton* button = static_cast<TGTextButton*>(fResponderButtons->GetButton(id));
446   TString pattern = button->GetString();
447   
448 //  AliInfo(Form("id=%d button=%d %s",id,button->IsOn(),pattern.Data()));
449
450   assert(button->IsOn()==1);
451   
452   fPainterMatrix->SetResponder(pattern.Data());
453 }
454
455 //_____________________________________________________________________________
456 void
457 AliMUONPainterMatrixFrame::OutlineButtonWasClicked(Int_t id)
458 {
459   /// One outline button was clicked
460   
461   TGTextButton* button = static_cast<TGTextButton*>(fOutlineButtons->GetButton(id));
462   TString pattern = button->GetString();
463   
464   fPainterMatrix->SetOutlined(pattern.Data(),button->IsOn());
465   
466   ViewModified();
467   fView->GetCanvas()->Update();
468     
469   // Update the interface (e.g. list of possible responders can have 
470   // changed due to visibility change)
471   UpdateInterface(kFALSE);
472 }
473
474 //_____________________________________________________________________________
475 void 
476 AliMUONPainterMatrixFrame::SaveAs(const char* filename, Option_t* option) const
477 {
478   /// Save painter matrix (in the sense of "print") in filename
479   fView->GetCanvas()->SaveAs(filename,option);
480 }
481
482 //_____________________________________________________________________________
483 void
484 AliMUONPainterMatrixFrame::TitleHasChanged(const char* title)
485 {
486   /// Emit the TitleHasChanged signal
487   
488   Long_t params[] = { (Long_t)title };
489   Emit("TitleHasChanged(const char*)",params);
490 }
491
492
493 //_____________________________________________________________________________
494 void
495 AliMUONPainterMatrixFrame::Update()
496 {
497   /// Force update of all canvases
498
499   UpdateDataRange();
500   
501   fView->GetCanvas()->SetEditable(kTRUE);
502   
503   Bool_t colorSlider = ( fPainterMatrix->Data() != 0x0 );
504   
505   ViewModified();
506
507   fView->GetCanvas()->SetEditable(kFALSE);
508   
509   AliDebug(1,Form("colorSlider=%d",colorSlider));
510   
511   if ( colorSlider )
512   {
513     fMainFrame->ShowFrame(fColorSlider);
514   }
515   else
516   {
517     fMainFrame->HideFrame(fColorSlider);
518   }
519   
520   fMainFrame->Layout();
521   Layout();
522 }
523
524 //_____________________________________________________________________________
525 void
526 AliMUONPainterMatrixFrame::UpdateDataRange()
527 {
528   /// Update the data range
529
530   if ( fColorSlider->IsLocked() ) 
531   {
532     fColorSlider->SetRange(0,0,kTRUE);
533     return;
534   }
535   
536   Double_t min, max;
537
538   fPainterMatrix->GetDataRange(min,max);
539
540   AliDebug(1,Form("min %e max %e",min,max));
541
542   if ( min > max ) 
543   {
544     fPainterMatrix->ComputeDataRange();
545     fPainterMatrix->GetDataRange(min,max);
546   }
547
548   fColorSlider->SetRange(min,max,kFALSE);
549 }
550
551 //_____________________________________________________________________________
552 void 
553 AliMUONPainterMatrixFrame::UpdateInterface(Bool_t fromScratch)
554 {
555   /// Update the full interface
556   
557   if ( fromScratch || fOutlineButtons->GetCount() == 0 ) 
558   {
559     CreateButtons();
560   }
561   
562   AliMUONPainterInterfaceHelper::Unselect(*fResponderButtons,"*");
563   AliMUONPainterInterfaceHelper::Unselect(*fOutlineButtons,"*");
564   
565   AliMUONVPainter* painter = fPainterMatrix->Painter(0);
566   
567   TObjArray types;
568   types.SetOwner(kTRUE);
569   
570   fPainterMatrix->GetTypes(types);
571   
572   // update button states
573   TIter next(&types);
574   TObjString* otype;
575   
576   TString theResponder;
577   
578   while ( ( otype = static_cast<TObjString*>(next()) ) )
579   {    
580     AliMUONPainterGroup* group = painter->Group(otype->String());
581     
582     if ( group && group->IsOutlined() ) 
583     {
584       AliMUONPainterInterfaceHelper::Select(*fOutlineButtons,otype->String().Data());
585     }    
586   }
587   
588   if ( painter ) 
589   {
590     AliMUONPainterGroup* responderGroup = painter->ResponderGroup();
591   
592     if (responderGroup)
593     {
594       AliMUONPainterInterfaceHelper::Select(*fResponderButtons,responderGroup->Type());
595     }
596   }
597   
598   // update data source view
599   
600   fPlotSelector->Update(*fPainterMatrix);
601     
602   fResponderButtons->Show();
603   fOutlineButtons->Show();
604
605   Layout();
606 }
607
608 //_____________________________________________________________________________
609 void 
610 AliMUONPainterMatrixFrame::Use(AliMUONPainterMatrix* group)
611 {
612   /// Change the matrix used
613   
614   Clear();
615   
616   fPainterMatrix = group;
617   
618   fView->GetCanvas()->SetEditable(kTRUE);
619   
620   fView->GetCanvas()->Divide(fPainterMatrix->Nx(),fPainterMatrix->Ny());
621   
622   for ( Int_t i = 0; i < fPainterMatrix->Size(); ++i ) 
623   {
624     AliMUONVPainter* painter = fPainterMatrix->Painter(i);
625     fView->GetCanvas()->cd(i+1);
626     painter->Draw("R");
627     fPainterHighlighter->SetPainter(0x0);
628     fPainterHighlighter->Draw();
629   }  
630
631   Update();
632   
633   UpdateInterface(kTRUE);
634   
635   ChangeTitle(fPainterMatrix->Name());
636   
637   fView->GetCanvas()->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
638                               "AliMUONPainterMatrixFrame",this, 
639                               "EventInfo(Int_t,Int_t,Int_t,TObject*)"); 
640   
641 }
642
643 //_____________________________________________________________________________
644 void 
645 AliMUONPainterMatrixFrame::ViewModified()
646 {
647   /// Update our canvas
648   
649   for ( Int_t i = 0; i < fPainterMatrix->Size(); ++i ) 
650   {
651     fView->GetCanvas()->GetPad(i+1)->Modified();
652   }
653   fView->GetCanvas()->Modified();
654   fView->GetCanvas()->Update();
655 }
656
657