]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONVPainter.cxx
Fixing (most of) compiler warnings
[u/mrichter/AliRoot.git] / MUON / AliMUONVPainter.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 "AliMUONVPainter.h"
19
20 #include "AliCodeTimer.h"
21 #include "AliLog.h"
22 #include "AliMUONObjectPair.h"
23 #include "AliMUONPainterContour.h"
24 #include "AliMUONPainterGroup.h"
25 #include "AliMUONPainterHelper.h"
26 #include "AliMUONTrackerDataHistogrammer.h"
27 #include "AliMUONVTrackerData.h"
28 #include <Riostream.h>
29 #include <TCanvas.h>
30 #include <TClass.h>
31 #include <TClassMenuItem.h>
32 #include <TH1.h>
33 #include <TList.h>
34 #include <TMap.h>
35 #include <TMath.h>
36 #include <TMethodCall.h>
37 #include <TObjArray.h>
38 #include <TObjString.h>
39 #include <TROOT.h>
40 #include <TVirtualPad.h>
41 #include <cassert>
42 #include <float.h>
43
44 /// \class AliMUONVPainter
45 ///
46 /// Base class for a graphical object representing some part of the
47 /// MUON tracking system.
48 /// 
49 /// A painter is a graphical representation of some part (e.g. detection element,
50 /// full chamber, one manu, etc...) of the MUON tracking system.
51 ///
52 /// A painter is a double fold hierarchical structure. 
53 ///
54 /// First, a painter is part of a tree (mother->childrens), that describe
55 /// the natural organization of the spectrometer. For instance, a chamber
56 /// painter has children that are the detection element, the detection elements
57 /// themselves contain manus, which in turn contain channels.
58 ///
59 /// Second, a painter contains a number of "painter groups" (see AliMUONPainterGroup). 
60 /// A group gather all the painters of the same type, 
61 /// where the type is a string identifying which part of system we're dealing
62 /// with (chamber, DE, manu, etc...)
63 ///
64 /// The groups are there to ease the manipulation of similar painters, e.g. if
65 /// we want to hide all detection elements, we hide the "detection element group"
66 /// Some special groups are the responder and the plotter groups. The responder
67 /// group is the group which is currently responding to mouse events. 
68 /// The plotter group is the group which is supposed to represent some data.
69 /// 
70 /// There are two ways to represent the painter on screen. In any case, we can
71 /// outline the painter (i.e. draw its borders) (see AliMUONVPainter::PaintOutline).
72 /// In the cases where the painter is attached to some data source (i.e. it is
73 /// used to represent some data about its type, e.g. the mean charge on some manu),
74 /// we can draw the full area of the contour, using some color (see
75 /// AliMUONVPainter::PaintArea).
76 ///
77 /// Note that you can outline several types of painters (aka groups) at the same
78 /// time, but you cannot plot several groups at the same time.
79 ///
80 /// Painters are TQObject so they can emit signals.
81 ///
82 /// Currently emitted signal are : 
83 ///
84 /// void Clicked(AliMUONVPainter* painter, Double_t*);
85 /// DoubleClicked(AliMUONVPainter* painter, Double_t*);
86 ///
87 /// to know which and where a painter was (double-) clicked.
88 ///
89 /// \author Laurent Aphecetche, Subatech
90
91 ///\cond CLASSIMP
92 ClassImp(AliMUONVPainter)
93 ///\endcond
94
95 //_____________________________________________________________________________
96 AliMUONVPainter::AliMUONVPainter(const char* type)
97 : TObject(), 
98   TQObject(),
99   fName(""),
100   fPathName(""),
101   fType(type),
102   fMother(0x0),
103   fGroup(0x0),
104   fContour(0x0),
105   fPainterGroups(0x0),
106   fChildren(0x0),
107   fResponderGroup(0x0),
108   fPlotterGroup(0x0),
109   fBorderFactor(1.1),
110   fPad(0x0),
111   fAttributes(),
112   fLineColor(1),
113   fLineWidth(1),
114   fIsValid(kTRUE),
115   fHistogram(0x0)
116 {
117     /// ctor
118     SetID(-1,-1);
119 }
120
121 //_____________________________________________________________________________
122 AliMUONVPainter::AliMUONVPainter(const AliMUONVPainter& rhs)
123 : TObject(rhs),
124 TQObject(),
125 fName(""),
126 fPathName(""),
127 fType(""),
128 fMother(0x0),
129 fGroup(0x0),
130 fContour(0x0),
131 fPainterGroups(0x0),
132 fChildren(0x0),
133 fResponderGroup(0x0),
134 fPlotterGroup(0x0),
135 fBorderFactor(1.0),
136 fPad(0x0),
137 fAttributes(),
138 fLineColor(-1),
139 fLineWidth(-1),
140 fIsValid(kTRUE),
141 fHistogram(0x0)
142 {
143   /// copy ctor
144   rhs.Copy(*this);
145 }
146
147 //_____________________________________________________________________________
148 AliMUONVPainter& 
149 AliMUONVPainter::operator=(const AliMUONVPainter& rhs)
150 {
151   /// assignment operator
152   if ( this != &rhs ) 
153   {
154     rhs.Copy(*this);
155   }
156   return *this;
157 }
158
159 //_____________________________________________________________________________
160 AliMUONVPainter::~AliMUONVPainter()
161 {
162   /// dtor
163   delete fChildren;
164   delete fHistogram;
165 }
166
167 //_____________________________________________________________________________
168 AliMpArea
169 AliMUONVPainter::Area() const
170 {
171   /// Return the area covered by this painter
172   if ( fContour ) 
173   {
174     return fContour->Area();
175   }
176   else
177   {
178     AliWarning("Returning an invalid area, as contour is not defined");
179     return AliMpArea();
180   }
181 }
182
183 //_____________________________________________________________________________
184 void
185 AliMUONVPainter::Add(AliMUONVPainter* painter)
186 {
187   /// Add a child painter
188   if (!fChildren) fChildren = new TObjArray;
189   assert(painter->Mother()==0x0);
190   fChildren->Add(painter);
191   painter->SetMother(this);
192 }
193
194 //_____________________________________________________________________________
195 TCollection*
196 AliMUONVPainter::Children() const
197 {
198   /// Return the list of childrens
199   return fChildren;
200 }
201
202 //_____________________________________________________________________________
203 void
204 AliMUONVPainter::Clicked(AliMUONVPainter* painter, Double_t* values)
205 {
206   /// Let our mother emit the signal as clients are probably connected to
207   /// our (grand)mother, not to us
208
209   if ( Mother() ) 
210   {
211     Mother()->Clicked(painter,values);
212   }
213   else
214   {
215     Long_t param[] = { (Long_t)painter,(Long_t)values };
216   
217     Emit("Clicked(AliMUONVPainter*,Double_t*)",param);
218   }
219 }
220
221 //_____________________________________________________________________________
222 void
223 AliMUONVPainter::ShiftClicked(AliMUONVPainter* painter, Double_t* values)
224 {
225   /// Let our mother emit the signal as clients are probably connected to
226   /// our (grand)mother, not to us
227   
228   if ( Mother() ) 
229   {
230     Mother()->ShiftClicked(painter,values);
231   }
232   else
233   {
234     Long_t param[] = { (Long_t)painter,(Long_t)values };
235     
236     Emit("ShiftClicked(AliMUONVPainter*,Double_t*)",param);
237   }
238 }
239
240 //_____________________________________________________________________________
241 void
242 AliMUONVPainter::ComputeDataRange(const AliMUONVTrackerData&, Int_t,
243                                   Double_t&, Double_t&) const
244 {
245   /// Should compute the min and max of a given data source
246   AliError("Not implemented. Please fixe me");
247 }
248
249 //_____________________________________________________________________________
250 TString
251 AliMUONVPainter::ContourName() const
252 {
253   /// Default implementation of the contour name.
254   
255   TString name(PathName());
256
257   name += "-";
258   name += fAttributes.Name();
259   
260   return name;
261 }
262
263 //_____________________________________________________________________________
264 void
265 AliMUONVPainter::Copy(TObject& object) const
266 {
267   /// Copy this to object.
268   
269   TObject::Copy(object);
270
271   AliMUONVPainter& painter = static_cast<AliMUONVPainter&>(object);
272
273   painter.fType = fType;
274   painter.fName = fName;
275   painter.fPathName = fPathName;
276   
277   painter.fMother = 0x0;
278   painter.fContour = fContour;
279   
280   painter.fGroup = 0x0;
281   painter.fResponderGroup = 0x0;
282   painter.fPlotterGroup = 0x0;
283   
284   painter.fBorderFactor = fBorderFactor;
285
286   painter.fAttributes = fAttributes;
287   
288   painter.fAttributes.SetCathodeAndPlaneDisabled(kFALSE);
289   
290   painter.fPad = fPad;
291   
292   painter.fLineColor = fLineColor;
293   painter.fLineWidth = fLineWidth;
294   
295   painter.fIsValid = fIsValid;
296   
297   delete painter.fChildren;
298   painter.fChildren = 0x0;
299   
300   painter.fID[0] = fID[0];
301   painter.fID[1] = fID[1];
302   
303   delete painter.fHistogram;
304   painter.fHistogram = 0x0;
305   
306   TIter next(fChildren);
307   AliMUONVPainter* p;
308   
309   while ( ( p = static_cast<AliMUONVPainter*>(next()) ) )
310   {
311     painter.Add(static_cast<AliMUONVPainter*>(p->Clone()));
312   }
313     
314   painter.UpdateGroupsFrom(*this);
315   
316   object.ResetBit(kCanDelete);
317 }
318
319 //_____________________________________________________________________________
320 AliMUONPainterGroup*
321 AliMUONVPainter::CreateGroup(const char* type, Int_t depth)
322 {
323   /// Create a painter group at a given depth
324   
325   if (!fPainterGroups) fPainterGroups = new TMap;
326   TObject* o = fPainterGroups->GetValue(type);
327   if (o)
328   {
329     AliError(Form("Group %s is already there ! Check this",type));
330     return 0x0;
331   }
332   AliMUONPainterGroup* group = new AliMUONPainterGroup(type,depth);
333   fPainterGroups->Add(new TObjString(type),group);
334   return group;
335 }
336
337 //_____________________________________________________________________________
338 void
339 AliMUONVPainter::CreateGroups()
340 {
341   /// Groups our children into groups
342   
343   if ( Mother() ) 
344   {
345     AliFatal("Not supposed to create groups for a children");
346   }
347   
348   TList list;
349   FlatList(list);
350   
351   TIter next(&list);
352   AliMUONVPainter* painter;
353   
354   while ( ( painter = static_cast<AliMUONVPainter*>(next()) ) )
355   {
356     AliMUONPainterGroup* group = Group(painter->Type());
357     if (!group) 
358     {
359       group = CreateGroup(painter->Type(),painter->Depth());
360     }
361     group->Add(painter);
362   }
363 }
364
365 //_____________________________________________________________________________
366 AliMUONVPainter*
367 AliMUONVPainter::Detach() const
368 {
369   /// Make this a new top painter (i.e. a master)
370   
371   AliDebug(1,Form("Detaching %s",GetName()));
372            
373   AliMUONVPainter* p = static_cast<AliMUONVPainter*>(Clone());
374   
375   AliMUONVPainter* master = Master();
376   
377   if ( master )
378   {
379     AliDebug(1,Form("UpdatingGroups of the detached painter %s from its master %s",
380                     p->GetName(),master->GetName()));
381     p->UpdateGroupsFrom(*master);
382   }
383   
384   return p;
385 }
386
387 //_____________________________________________________________________________
388 Int_t
389 AliMUONVPainter::Depth() const
390 {
391   /// Return our depth in the hierarchy
392   
393   if ( Mother() ) 
394   {
395     return Mother()->Depth() + 1;
396   }
397   else
398   {
399     return 0;
400   }
401 }
402
403 //_____________________________________________________________________________
404 Int_t   
405 AliMUONVPainter::DistancetoPrimitive(Int_t px, Int_t py)
406 {
407   /// See TObject::DistancetoPrimitive
408   
409   static const Int_t kBigValue = 999999;
410
411   if (!gPad) return kBigValue;
412   
413   Double_t x,y;
414   
415   AliMUONVPainter* painter = GetPainter(px,py,x,y);
416   
417   x=y=0.0; // to avoid compiler warning
418   
419   if ( painter == this) return 0;
420   
421   return kBigValue;
422 }
423
424 //_____________________________________________________________________________
425 void
426 AliMUONVPainter::DoubleClicked(AliMUONVPainter*, Double_t*)
427 {
428   /// Should emit the DoubleClicked signal (if I knew how to detect those events...)
429   
430   AliWarning("Please implement me !");
431
432   //  if ( fMother )
433 //  {
434 //    // let our top mother emit the signal as clients are probably connected to
435 //    // our mother, not to us
436 //    Top()->DoubleClicked(painter,values);
437 //  }
438 //  else
439 //  {
440 //    Long_t param[] = { (Long_t)painter,(Long_t)values };
441 //    
442 //    Emit("DoubleClicked(AliMUONVPainter*,Double_t*)",param);
443 //  }
444 }
445
446 //_____________________________________________________________________________
447 void
448 AliMUONVPainter::Draw(Option_t* opt)
449 {
450   /// Append ourselves to the current pad
451   
452   if (!gPad) 
453   {
454     gROOT->MakeDefCanvas();
455   }
456   
457   Bool_t kMustSetRange(kFALSE);
458  
459   TString sopt(opt);
460   sopt.ToUpper();
461  
462   if (sopt.Contains("R") ) kMustSetRange=kTRUE;
463   
464   if (kMustSetRange)
465   {
466     Double_t x1,y1,x2,y2;
467     GetBoundingBox(x1,y1,x2,y2);
468     if ( gPad) gPad->Range(x1,y1,x2,y2);
469   }
470  
471   if ( !fMother && !fPainterGroups ) 
472   {
473     CreateGroups();
474   }
475   
476   TIter next(fChildren);
477   AliMUONVPainter* painter;
478   while ( ( painter = static_cast<AliMUONVPainter*>(next()) ) )
479   {
480     painter->Draw();
481   }  
482   
483   AppendPad(opt);
484   
485   fPad = gPad;
486 }
487
488 //_____________________________________________________________________________
489 void 
490 AliMUONVPainter::ExecuteEvent(Int_t event, Int_t px, Int_t py)
491 {
492   /// Handle graphics events
493   
494   Double_t x,y;
495     
496   AliMUONVPainter* painter = GetPainter(px,py,x,y);
497
498   if ( painter == this ) 
499   {
500     Double_t values[] = { x,y };
501   
502     switch (event)
503     {
504       case kButton2Up:
505         ShiftClicked(this,values);
506         break;
507       case kButton1Up:
508         Clicked(this,values);      
509         break;
510       case kButton1Double:
511         //the following statement is required against other loop executions before returning (depending on the time between the clicks) 
512         gPad->GetCanvas()->HandleInput((EEventType)-1,0,0); 
513         DoubleClicked(this,values);
514         break;
515     }
516   }
517 }
518
519 //_____________________________________________________________________________
520 void
521 AliMUONVPainter::FlatList(TList& list)
522 {
523   /// Make a flat list of our children (and ourselves)
524   
525   TIter next(fChildren);
526   AliMUONVPainter* painter;
527   while ( ( painter = static_cast<AliMUONVPainter*>(next())))
528   {
529     painter->FlatList(list);
530   }
531   
532   list.Add(this);
533 }
534
535 //_____________________________________________________________________________
536 void 
537 AliMUONVPainter::GetBoundingBox(Double_t& x1, Double_t& y1, 
538                                 Double_t& x2, Double_t& y2) const
539 {
540   /// Get the bounding box = our area
541   AliMpArea area(Area().Position(),Area().Dimensions()*fBorderFactor);
542
543   x1 = area.LeftBorder();
544   y1 = area.DownBorder();
545   x2 = area.RightBorder();
546   y2 = area.UpBorder();
547 }
548
549 //_____________________________________________________________________________
550 char*   
551 AliMUONVPainter::GetObjectInfo(Int_t, Int_t) const
552 {
553   /// See TObject::GetObjectInfo
554   return const_cast<char*>(GetName());
555 }
556
557 //_____________________________________________________________________________
558 AliMUONVPainter* 
559 AliMUONVPainter::GetPainter(Int_t px, Int_t py, Double_t& x, Double_t& y) const
560 {
561   /// Get the responder painter at integer position (px,py), and get back its
562   /// absolute position (x,y)
563   
564   PixelToPad(px,py,x,y);
565   
566   if ( !IsInside(x,y) ) return 0x0;
567   
568   if ( fGroup->IsResponder() ) return const_cast<AliMUONVPainter*>(this);
569   
570   if (fChildren)
571   {
572     TIter next(fChildren);
573     AliMUONVPainter* painter;
574     
575     while ( ( painter = static_cast<AliMUONVPainter*>(next()) ) )
576     {
577       AliMUONVPainter* p = painter->GetPainter(px,py,x,y);
578       if (p) return p;
579     }
580   }  
581   
582   return 0x0;
583 }
584
585 //_____________________________________________________________________________
586 void
587 AliMUONVPainter::GetTypes(TObjArray& types) const
588 {
589   /// Get the list of types (as a TObjArray of TObjString) 
590   /// of our hierarchy, sorted alphabetically
591   
592   types.SetOwner(kTRUE);
593   types.Clear();
594
595   TObjArray tmp;
596   tmp.SetOwner(kFALSE);
597   
598   TIter next(fPainterGroups);
599   
600   TObjString* str;
601   while ( ( str = static_cast<TObjString*>(next()) ) )
602   {
603     AliMUONPainterGroup* group = Group(str->String().Data());
604     tmp.AddLast(group);
605   }
606   
607   tmp.Sort();
608   
609   Int_t n = tmp.GetLast()+1;
610   
611   Int_t* index = new Int_t[n];
612   
613   Int_t* a = new Int_t[n];
614   
615   for ( Int_t i = 0; i < n; ++i )
616   {
617     AliMUONPainterGroup* group = static_cast<AliMUONPainterGroup*>(tmp.At(i));
618     a[i] = group->Depth();
619   }
620   
621   TMath::Sort(n,a,index,kFALSE);
622   
623   for ( Int_t i = 0; i < n; ++i ) 
624   {
625     AliMUONPainterGroup* group = static_cast<AliMUONPainterGroup*>(tmp.At(index[i]));
626     types.AddLast(new TObjString(group->Type()));
627   }
628   
629   delete[] index;
630   delete[] a;
631 }
632
633 //_____________________________________________________________________________
634 AliMUONPainterGroup*
635 AliMUONVPainter::Group(const char* type) const
636 {
637   /// Returns a group of a given type
638   if (!fPainterGroups) return 0x0;
639   return static_cast<AliMUONPainterGroup*>(fPainterGroups->GetValue(type));
640 }
641
642 //_____________________________________________________________________________
643 AliMUONPainterGroup*
644 AliMUONVPainter::Group(Int_t depth) const
645 {
646   /// Returns a group of a given depth
647   if (!fPainterGroups) return 0x0;
648   TIter next(fPainterGroups);
649   TObjString* groupName;
650   while ( ( groupName = static_cast<TObjString*>(next()) ) )
651   {
652     AliMUONPainterGroup* group = static_cast<AliMUONPainterGroup*>
653     (fPainterGroups->GetValue(groupName->String().Data()));
654     if ( group->Depth() == depth ) 
655     {
656       return group;
657     }
658   }
659   return 0x0;
660 }
661
662 //_____________________________________________________________________________
663 Bool_t 
664 AliMUONVPainter::IsInside(Double_t x, Double_t y) const
665 {
666   /// Whether point (x,y) is inside our contour
667   if (!fContour) return kFALSE;
668   return fContour->IsInside(x,y);
669 }
670
671 //_____________________________________________________________________________
672 Bool_t 
673 AliMUONVPainter::IsResponder() const
674 {
675   /// Whether we're responding to mouse events
676   return MotherGroup()->IsResponder();
677 }
678
679 //_____________________________________________________________________________
680 AliMUONVPainter*
681 AliMUONVPainter::Master() const
682 {
683   /// Return the top of the hierarchy
684   
685   /// if we get no mother, we are the master
686   
687   if ( Mother() == 0x0 ) return const_cast<AliMUONVPainter*>(this);
688   
689   AliMUONVPainter* p = Mother();
690   
691   while ( p->Mother() )
692   {
693     p = p->Mother();
694   }
695   
696   return p;
697 }
698
699 //_____________________________________________________________________________
700 void
701 AliMUONVPainter::Paint(Option_t*)
702 {
703   /// Paint ourselves of screen
704   /// If we have some data (i.e. we're belonging to the plotter group)
705   /// we use PaintArea.
706   /// And if must be outlined, then we do that too.
707   
708   if ( !MotherGroup()->IsVisible() ) return;
709
710   if ( MotherGroup()->IsPlotter() ) 
711   {
712     PaintArea(*(MotherGroup()->Data()),
713               MotherGroup()->DataIndex(),
714               MotherGroup()->DataMin(),
715               MotherGroup()->DataMax());
716   }
717   
718   if ( MotherGroup()->IsOutlined() )
719   {
720     PaintOutline();
721   }
722 }
723
724 //_____________________________________________________________________________
725 TString
726 AliMUONVPainter::Describe(const AliMUONVTrackerData&, Int_t, Double_t, Double_t)
727 {
728   /// Default implementation (must be overriden)
729   AliError(Form("%s : implement me",GetName()));
730   return "";
731 }
732
733 //_____________________________________________________________________________
734 void
735 AliMUONVPainter::PaintArea(const AliMUONVTrackerData&, Int_t, Double_t, Double_t)
736 {
737   /// Default implementation (must be overriden)
738   AliError(Form("%s : implement me",GetName()));
739 }
740
741 //_____________________________________________________________________________
742 void
743 AliMUONVPainter::PaintOutline(Int_t color, Int_t width, Double_t /*x*/, Double_t /*y*/)
744 {
745   /// Default implementation is simply a drawing of the contour lines,
746   /// not using the optional (x,y)
747   Int_t c = color >= 0 ? color : GetLineColor();
748   Int_t w = width >= 0 ? width : GetLineWidth();
749   
750   fContour->PaintOutline(c,w);
751 }
752
753 //_____________________________________________________________________________
754 void 
755 AliMUONVPainter::PixelToPad(Int_t px, Int_t py, Double_t& x, Double_t& y)
756 {
757   /// convert (px,py) into pad position (x,y)
758   
759   x = gPad->PadtoX(gPad->AbsPixeltoX(px));
760   y = gPad->PadtoY(gPad->AbsPixeltoY(py));
761 }
762
763 //_____________________________________________________________________________
764 void
765 AliMUONVPainter::Print(Option_t* opt) const
766 {
767   /// Printout
768   for ( Int_t i = 0; i < Depth()*4; ++i ) 
769   {
770     cout << " ";
771   }
772   
773   if ( !IsValid() ) cout << "!!!INVALID!!!" << endl;
774   
775   cout << Form("%p Name %s Depth %d ContourName %s ID=(%d,%d)",
776                this,GetName(),Depth(),ContourName().Data(),ID0(),ID1());
777   
778   if ( fResponderGroup )
779   {
780     cout << Form(" Responder group %p %s",fResponderGroup,fResponderGroup->Type());
781   }
782   if ( fPlotterGroup )
783   {
784     cout << Form(" Plotter group %p %s",fPlotterGroup,fPlotterGroup->Type());
785   }
786   if ( Mother() )
787   {
788     cout << Form(" Mother %p %s",Mother(),Mother()->GetName());
789   }
790   if ( MotherGroup() )
791   {
792     cout << Form(" Group %p %s ",MotherGroup(),MotherGroup()->Type());
793   }
794   
795   if ( fChildren ) 
796   {
797     cout << Form(" %d children",fChildren->GetLast()+1);
798   }
799   
800   cout << endl;
801   
802   TString sopt(opt);
803   sopt.ToUpper();
804   
805   if ( fChildren && ( sopt == "FULL" || sopt == "CHILD" ) ) 
806   {
807     TIter next(fChildren);
808     AliMUONVPainter* painter;
809     while ( ( painter = static_cast<AliMUONVPainter*>(next()) ) )
810     {
811       painter->Print(opt);
812     }
813   }
814   
815   if ( fPainterGroups && ( sopt == "FULL" || sopt == "GROUP" ) )
816   {
817     TIter next(fPainterGroups);
818     TObjString* groupName;
819     while ( ( groupName = static_cast<TObjString*>(next()) ) )
820     {
821       AliMUONPainterGroup* group = Group(groupName->String().Data());
822       group->Print(opt);
823     }
824   }
825 }
826
827 //_____________________________________________________________________________
828 void 
829 AliMUONVPainter::SetAttributes(const AliMUONAttPainter& attributes)
830 {
831   /// Set our attributes  
832   fAttributes = attributes;
833 }
834
835 //_____________________________________________________________________________
836 void 
837 AliMUONVPainter::SetContour(AliMUONPainterContour* contour)
838 {
839   /// Set out contour
840   if (!contour)
841   {
842     AliError(Form("Setting a null contour for painter %s : bad idea !",PathName().Data()));
843   }
844   fContour = contour;
845 }
846
847 //_____________________________________________________________________________
848 void
849 AliMUONVPainter::SetData(const char* pattern, AliMUONVTrackerData* data,
850                          Int_t dataIndex)
851 {
852   /// Tell all painters which type matches pattern that they should
853   /// monitor a given data source
854   
855   if ( !fPainterGroups ) 
856   {
857     CreateGroups();
858   }
859   
860   TIter next(fPainterGroups);
861   TObjString* str;
862   
863   fPlotterGroup = 0x0;
864   
865   while ( ( str = static_cast<TObjString*>(next()) ) )
866   {
867     AliMUONPainterGroup* group = static_cast<AliMUONPainterGroup*>(fPainterGroups->GetValue(str));
868         
869     if ( group->Matches(pattern) )
870     {
871       group->SetData(data,dataIndex);
872       if ( data ) 
873       {        
874         fPlotterGroup = group;
875       }
876     }
877     else
878     {
879       group->SetData(0x0,-1);
880     }
881   }
882   
883   // Update context menus
884   TList list;
885   FlatList(list);
886   
887   TIter pnext(&list);
888   AliMUONVPainter* p;
889   
890   AliMUONPainterGroup* group = Master()->PlotterGroup();
891   
892   while ( ( p = static_cast<AliMUONVPainter*>(pnext()) ) )
893   {
894     TList* l = p->IsA()->GetMenuList();
895   
896     l->Clear();
897   
898     if ( group ) 
899     {
900       Int_t dim = group->Data()->InternalToExternal(group->DataIndex());
901       if ( dim < group->Data()->ExternalDimension() )
902       {      
903         if ( data && data->IsHistogrammed(dim) ) 
904         {
905           // Add histo drawing to the popup menu
906           TClassMenuItem* n = new TClassMenuItem(TClassMenuItem::kPopupUserFunction,p->IsA(),
907                                                  "Draw histogram","DrawHistogram",p,"",-1,kTRUE);
908           l->AddFirst(n);
909           
910           n = new TClassMenuItem(TClassMenuItem::kPopupUserFunction,p->IsA(),
911                                  "Draw histogram clone","DrawHistogramClone",p,"",-1,kTRUE);
912           l->AddFirst(n);
913           
914           
915         }
916       }
917     }
918   }
919 }
920
921 //_____________________________________________________________________________
922 void
923 AliMUONVPainter::DrawHistogram() const
924 {
925   /// Draw histogram (and delete the previous one)
926
927   delete fHistogram;
928   fHistogram = 0x0;
929   
930   DrawHistogramClone();
931 }
932
933 //_____________________________________________________________________________
934 void
935 AliMUONVPainter::DrawHistogramClone() const
936 {
937   /// Draw histogram 
938   
939   fHistogram = AliMUONTrackerDataHistogrammer::CreateHisto(*this);
940   
941   if (fHistogram) 
942   {
943     new TCanvas();
944     fHistogram->Draw();
945   }
946 }
947
948 //_____________________________________________________________________________
949 void
950 AliMUONVPainter::FillManuList(TObjArray& manuList) const
951 {
952   /// Append to manulist
953   /// This is the default implementation, which just calls the FillManuList
954   /// of all our children.
955   /// Some derived class might need to override this in order to exclude
956   /// some children from the fill.
957   
958   TIter next(Children());
959   
960   AliMUONVPainter* p;
961   
962   while ( ( p = static_cast<AliMUONVPainter*>(next()) ) )
963   {
964     p->FillManuList(manuList);
965   }
966 }
967
968 //_____________________________________________________________________________
969 void
970 AliMUONVPainter::SetLine(Int_t depth, Int_t lineColor, Int_t lineWidth)
971 {
972   /// Set the line attributes of painters at a given depth
973   AliMUONPainterGroup* group = Group(depth);
974   if ( group )
975   {
976     group->SetLine(lineColor,lineWidth);
977   }
978 }
979
980 //_____________________________________________________________________________
981 void
982 AliMUONVPainter::SetMother(AliMUONVPainter* painter)
983 {
984   /// Set our mother
985   fMother = painter;
986 }
987
988 //_____________________________________________________________________________
989 void
990 AliMUONVPainter::SetOutlined(const char* pattern, Bool_t flag)
991 {
992   /// Decide whether or not painters which type matches pattern 
993   /// should be outlined
994   
995   AliDebug(1,Form("pattern=%s flag=%d",pattern,flag));
996   
997   if (!fPainterGroups)
998   {
999     CreateGroups();
1000   }
1001   
1002   TIter next(fPainterGroups);
1003   TObjString* str;
1004   
1005   while ( ( str = static_cast<TObjString*>(next()) ) )
1006   {
1007     AliMUONPainterGroup* group = static_cast<AliMUONPainterGroup*>(fPainterGroups->GetValue(str));
1008     if ( group->Matches(pattern) )
1009     {
1010       group->SetOutlined(flag);
1011     }
1012   }
1013 }
1014
1015 //_____________________________________________________________________________
1016 void
1017 AliMUONVPainter::SetResponder(const char* pattern)
1018 {
1019   /// Set the painters matching pattern to be the responder
1020   
1021   AliDebug(1,Form("pattern=%s",pattern));
1022   
1023   if (!fPainterGroups)
1024   {
1025     CreateGroups();
1026   }
1027   
1028   TIter next(fPainterGroups);
1029   TObjString* str;
1030   
1031   fResponderGroup = 0x0;
1032   
1033   while ( ( str = static_cast<TObjString*>(next()) ) )
1034   {
1035     AliMUONPainterGroup* group = static_cast<AliMUONPainterGroup*>(fPainterGroups->GetValue(str));
1036     if ( group->Matches(pattern) )
1037     {
1038       AliDebug(1,Form("group %s is matching pattern %s : setting to responder",
1039                       group->Type(),pattern));
1040       group->SetResponder(kTRUE);
1041       fResponderGroup = group;
1042     }
1043     else
1044     {
1045       group->SetResponder(kFALSE);
1046     }
1047   }
1048 }
1049
1050 //_____________________________________________________________________________
1051 void
1052 AliMUONVPainter::SetResponder(Int_t depth)
1053 {
1054   /// Select as responder the *first* group that has a given depth
1055   
1056   AliDebug(1,Form("depth=%d",depth));
1057   
1058   if (!fPainterGroups)
1059   {
1060     CreateGroups();
1061   }
1062   
1063   TIter next(fPainterGroups);
1064   TObjString* str;
1065   
1066   fResponderGroup = 0x0;
1067   
1068   while ( ( str = static_cast<TObjString*>(next()) ) )
1069   {
1070     AliMUONPainterGroup* group = static_cast<AliMUONPainterGroup*>(fPainterGroups->GetValue(str));
1071     if ( group->Depth() == depth ) 
1072     {
1073       AliDebug(1,Form("group %s has correct depth = %d, using as responder",
1074                       group->Type(),depth));
1075       group->SetResponder(kTRUE);
1076       fResponderGroup = group;
1077       break;
1078     }
1079     else
1080     {
1081       group->SetResponder(kFALSE);
1082     }
1083   }
1084 }
1085
1086 //_____________________________________________________________________________
1087 void
1088 AliMUONVPainter::SetVisible(const char* pattern, Bool_t flag)
1089 {
1090   /// Decide whether the painters matching pattern should be visible or not
1091   AliDebug(1,Form("pattern=%s flag=%d",pattern,flag));
1092   
1093   if (!fPainterGroups)
1094   {
1095     CreateGroups();
1096   }
1097   
1098   TIter next(fPainterGroups);
1099   TObjString* str;
1100   
1101   while ( ( str = static_cast<TObjString*>(next()) ) )
1102   {
1103     AliMUONPainterGroup* group = static_cast<AliMUONPainterGroup*>(fPainterGroups->GetValue(str));
1104     if ( group->Matches(pattern) )
1105     {
1106       group->SetVisible(flag);
1107     }
1108   }
1109 }
1110
1111 //_____________________________________________________________________________
1112 void
1113 AliMUONVPainter::UpdateGroupsFrom(const AliMUONVPainter& painter)
1114 {
1115   /// (re)Create groups
1116   delete fPainterGroups;
1117   fPainterGroups = 0x0;
1118   
1119   CreateGroups();
1120   
1121   // and copy the status of responder, plotter and visible
1122   if ( painter.ResponderGroup() ) 
1123   {
1124     SetResponder(painter.ResponderGroup()->Type());
1125   }
1126   
1127   if ( painter.PlotterGroup() ) 
1128   {
1129     SetData(painter.PlotterGroup()->Type(),
1130             painter.PlotterGroup()->Data(),
1131             painter.PlotterGroup()->DataIndex());
1132     PlotterGroup()->SetDataRange(painter.PlotterGroup()->DataMin(),
1133                                  painter.PlotterGroup()->DataMax());
1134   }
1135   
1136   TObjArray types;
1137   painter.GetTypes(types);
1138   TIter next(&types);
1139   TObjString* groupName;
1140   
1141   while ( ( groupName = static_cast<TObjString*>(next()) ) )
1142   {
1143     AliMUONPainterGroup* group = painter.Group(groupName->String().Data());      
1144     if ( group->IsVisible() ) 
1145     {
1146       SetVisible(group->Type(),kTRUE);
1147     }
1148     else
1149     {
1150       SetVisible(group->Type(),kFALSE);
1151     }
1152
1153     if ( group->IsOutlined() ) 
1154     {
1155       SetOutlined(group->Type(),kTRUE);
1156     }
1157     else
1158     {
1159       SetOutlined(group->Type(),kFALSE);
1160     }
1161     
1162     SetLine(group->Depth(),group->GetLineColor(),group->GetLineWidth());
1163   }
1164 }
1165
1166 //_____________________________________________________________________________
1167 AliMUONVPainter* 
1168 AliMUONVPainter::CreatePainter(const char* className, 
1169                                const AliMUONAttPainter& att, 
1170                                Int_t id1, Int_t id2)
1171 {
1172   /// Create a painter (factory method)
1173   
1174   TClass* c = TClass::GetClass(className);
1175   
1176   if (!c)
1177   {
1178     AliErrorClass(Form("Cannot get class %s",className));
1179     return 0x0;
1180   }
1181   
1182   Int_t n(0);
1183   
1184   TMethodCall call;
1185   
1186   call.InitWithPrototype(c,className,"AliMUONAttPainter&,Int_t");
1187   
1188   if (call.IsValid()) n = 1;
1189   else
1190   {
1191     call.InitWithPrototype(c,className,"AliMUONAttPainter&,Int_t,Int_t");
1192     
1193     if ( call.IsValid() ) n = 2;
1194   }
1195   
1196   Long_t returnLong(0x0);
1197   
1198   if ( n ==1 ) 
1199   {
1200     Long_t params[] = { (Long_t)(&att), (Long_t)(id1) };
1201     call.SetParamPtrs((void*)(params));
1202     call.Execute((void*)(0x0),returnLong);
1203   }
1204   else if ( n == 2 ) 
1205   {
1206     Long_t params[] = { (Long_t)(&att), (Long_t)(id1), (Long_t)(id2) };
1207     call.SetParamPtrs((void*)(params));
1208     call.Execute((void*)(0x0),returnLong);
1209   }
1210   
1211   if (!returnLong)
1212   {
1213     AliErrorClass(Form("Cannot create a painter of class %s",className));
1214   }
1215   
1216   AliMUONVPainter* rv = reinterpret_cast<AliMUONVPainter*> (returnLong);
1217   
1218   if (!rv->IsValid()) 
1219   {
1220     AliErrorClass(Form("Painter of class %s is not valid",className));
1221     delete rv;
1222     rv = 0x0;
1223   }
1224   return rv;
1225 }
1226