source: trunk/MagicSoft/Mars/mbase/MStatusArray.cc@ 9026

Last change on this file since 9026 was 9026, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 11.4 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz 03/2004 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2004
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26//
27// MStatusArray
28//
29// Helper class for MStatusDisplay
30//
31// If you want to read a MStatusArray (normally with name MStatusDisplay)
32// it is recommended to do it like this:
33// TFile f("myfile.root", "read");
34// MStatusArray arr;
35// arr.Read();
36//
37// If you want to use TFile::Get or TFile::GetObject you should switch off
38// addding Histograms automatically to the current directory first:
39// TFile f("myfile.root", "read");
40// TH1::AddDirectory(kFALSE);
41// f.Get("MStatusDisplay");
42//
43//////////////////////////////////////////////////////////////////////////////
44#include "MStatusArray.h"
45
46#include <TH1.h> // TH1::AddDirectoryStatus();
47#include <TClass.h>
48#include <TCanvas.h>
49
50#include "MLog.h"
51#include "MLogManip.h"
52
53#include "MParContainer.h" // MParContainer::GetClass
54#include "MStatusDisplay.h"
55
56ClassImp(MStatusArray);
57
58using namespace std;
59
60// --------------------------------------------------------------------------
61//
62// Initialize the MStatusArray from an MStatusDisplay. Note, the contents
63// still owned by MStatusDisplay and will vanish if the display changes
64// or is deleted without further notice.
65//
66MStatusArray::MStatusArray(const MStatusDisplay &d) : TObjArray()
67{
68 d.FillArray(*this);
69}
70
71// --------------------------------------------------------------------------
72//
73// If o==NULL a new status display is created, otherwise the one with name o
74// is searched in gROOT->GetListOfSpecials().
75// In this display the contents of the MStatusArray is displayed.
76//
77TObject *MStatusArray::DisplayIn(Option_t *o) const
78{
79 MStatusDisplay *d = 0;
80 if (TString(o).IsNull())
81 d = new MStatusDisplay;
82
83 if (!d)
84 d = (MStatusDisplay*)gROOT->GetListOfSpecials()->FindObject(o);
85
86 if (!d)
87 return 0;
88
89 if (d->Display(*this))
90 return d;
91
92 delete d;
93 return 0;
94}
95
96// --------------------------------------------------------------------------
97//
98// Display the contents of the given tab in the display given as argument.
99//
100void MStatusArray::DisplayIn(MStatusDisplay &d, const char *tab) const
101{
102 d.Display(*this, tab);
103}
104
105TObject *MStatusArray::FindObjectInPad(TVirtualPad *pad, const char *object, TClass *cls) const
106{
107 TObject *o = NULL;//pad->FindObject(object);
108// if (o && o->InheritsFrom(cls))
109// return o;
110
111 TIter Next(pad->GetListOfPrimitives());
112 while ((o=Next()))
113 {
114 if (o->GetName()==(TString)object && o->InheritsFrom(cls))
115 return o;
116
117 if (o==pad || !o->InheritsFrom(TVirtualPad::Class()))
118 continue;
119
120 if ((o = FindObjectInPad((TVirtualPad*)o, object, cls)))
121 return o;
122// if (o->InheritsFrom(cls))
123// return o;
124 }
125 return 0;
126}
127
128TCanvas *MStatusArray::FindCanvas(const char *name) const
129{
130 TObject *o = TObjArray::FindObject(name);
131 if (!o)
132 return 0;
133
134 return o->InheritsFrom(TCanvas::Class()) ? (TCanvas*)o : 0;
135}
136
137
138TObject *MStatusArray::FindObjectInCanvas(const char *object, const char *base, const char *canvas) const
139{
140 gLog << err;
141 TClass *cls = MParContainer::GetClass(base, &gLog);
142 if (!cls)
143 return 0;
144
145 TCanvas *c = canvas ? FindCanvas(canvas) : 0;
146 if (canvas)
147 {
148 if (!c)
149 {
150 gLog << warn << "Canvas '" << canvas << "' not found..." << endl;
151 return 0;
152 }
153
154 TObject *o = FindObjectInPad(c, object, cls);
155 if (!o)
156 {
157 gLog << warn << "Object '" << object << "' [" << base << "] not found in canvas '" << canvas << "'..." << endl;
158 return 0;
159 }
160
161 return o; //o->InheritsFrom(cls) ? o : 0;
162 }
163
164 TObject *o=0;
165 TIter Next(this);
166 while ((o=Next()))
167 {
168 if (!o->InheritsFrom(TVirtualPad::Class()))
169 continue;
170
171 if ((o=FindObjectInPad((TVirtualPad*)c, object, cls)))
172 return o;
173 }
174
175 gLog << warn << "Object '" << object << "' [" << base << "] not found in canvas '" << canvas << "'..." << endl;
176 return NULL;
177}
178
179TObject *MStatusArray::FindObjectInCanvas(const char *object, const char *canvas) const
180{
181 return FindObjectInCanvas(object, object, canvas);
182}
183
184TObject *MStatusArray::FindObject(const char *object, const char *base) const
185{
186 return FindObjectInCanvas(object, base, 0);
187}
188
189TObject *MStatusArray::FindObject(const char *object) const
190{
191 return FindObjectInCanvas(object, object, 0);
192}
193
194// --------------------------------------------------------------------------
195//
196// Print recursively all objects in this and sub-pads
197//
198void MStatusArray::PrintObjectsInPad(const TCollection *list, const TString &name, Int_t lvl) const
199{
200 TIter Next(list);
201 TObject *o=0;
202 while ((o=Next()))
203 {
204 const Bool_t print = name.IsNull() || name==(TString)o->GetName();
205 if (print)
206 {
207 if (lvl>0)
208 gLog << setw(lvl) << ' ';
209 gLog << " " << o->ClassName() << ": " << o->GetName() << " <" << Next.GetOption() << "> (" << o << ") " << (int)o->TestBit(kCanDelete) << endl;
210 }
211
212 if (o->InheritsFrom(TVirtualPad::Class()))
213 PrintObjectsInPad(((TVirtualPad*)o)->GetListOfPrimitives(), print?TString():name, lvl+1);
214 }
215}
216
217// --------------------------------------------------------------------------
218//
219// Print recursively all objects in this and sub-pads. If !option.IsNull()
220// only objects in the corresponding pad are printed.
221//
222void MStatusArray::Print(Option_t *option) const
223{
224 gLog << all;
225
226 PrintObjectsInPad(this, TString(option));
227}
228
229/*
230// --------------------------------------------------------------------------
231//
232// Make sure that kCanDelete is properly set for all directly contained
233// objects. Some kCanDelete bits might not be properly set or get lost when
234// the MParContainer is stored.
235//
236void MStatusArray::SetCanDelete(const TCollection *list) const
237{
238 TIter Next(list);
239 TObject *o=0;
240 while ((o=Next()))
241 {
242 if (o->InheritsFrom(TVirtualPad::Class()))
243 SetCanDelete(((TVirtualPad*)o)->GetListOfPrimitives());
244 else
245 o->SetBit(kCanDelete|kMustCleanup);
246 }
247}
248*/
249
250// --------------------------------------------------------------------------
251//
252// Set kCanDelete for all objects for which kMyCanDelete is set. This
253// is a STUPID workaruond for an ANNOYING root bug which is that
254// the streamer function of TH1 resets the KCanDelete bit after reading.
255//
256void MStatusArray::SetCanDelete(const TCollection *list) const
257{
258 TIter Next(list);
259 TObject *o=0;
260 while ((o=Next()))
261 {
262 if (o->InheritsFrom(TVirtualPad::Class()))
263 SetCanDelete(((TVirtualPad*)o)->GetListOfPrimitives());
264 else
265 {
266 if (o->TestBit(kMyCanDelete) && o->InheritsFrom("TH1"))
267 {
268 o->SetBit(kCanDelete);
269 o->ResetBit(kMyCanDelete);
270 }
271 }
272 }
273}
274
275void MStatusArray::EnableTH1Workaround(const TCollection *list) const
276{
277 TIter Next(list?list:this);
278 TObject *o=0;
279 while ((o=Next()))
280 {
281 if (o->InheritsFrom(TVirtualPad::Class()))
282 EnableTH1Workaround(((TVirtualPad*)o)->GetListOfPrimitives());
283 else
284 if (o->InheritsFrom("TH1"))
285 o->SetBit(kCanDelete);
286 }
287}
288
289// --------------------------------------------------------------------------
290//
291// Set kMyCanDelete for all objects for which kCanDelete is set. This
292// is a STUPID workaruond for an ANNOYING root bug which is that
293// the streamer function of TH1 resets the KCanDelete bit after reading.
294//
295void MStatusArray::SetMyCanDelete(const TCollection *list) const
296{
297 TIter Next(list);
298 TObject *o=0;
299 while ((o=Next()))
300 {
301 if (o->InheritsFrom(TVirtualPad::Class()))
302 SetMyCanDelete(((TVirtualPad*)o)->GetListOfPrimitives());
303 else
304 {
305 if (o->TestBit(kMyCanDelete) && o->InheritsFrom("TH1"))
306 gLog << warn << "WARNING - MStatusArray::Write - " << o->GetName() << " [" << o->ClassName() << "] has BIT(30) already set!" << endl;
307
308 if (o->TestBit(kCanDelete) && o->InheritsFrom("TH1"))
309 o->SetBit(kMyCanDelete);
310 }
311 }
312}
313
314// --------------------------------------------------------------------------
315//
316// Reset kMyCanDelete for all objects for which kMyCanDelete is set. This
317// is a STUPID workaruond for an ANNOYING root bug which is that
318// the streamer function of TH1 resets the KCanDelete bit after reading.
319//
320void MStatusArray::ResetMyCanDelete(const TCollection *list) const
321{
322 TIter Next(list);
323 TObject *o=0;
324 while ((o=Next()))
325 {
326 if (o->InheritsFrom(TVirtualPad::Class()))
327 ResetMyCanDelete(((TVirtualPad*)o)->GetListOfPrimitives());
328 else
329 {
330 if (o->TestBit(kMyCanDelete) && o->InheritsFrom("TH1"))
331 o->ResetBit(kMyCanDelete);
332 }
333 }
334}
335
336// --------------------------------------------------------------------------
337//
338// Switch off adding histograms to current directory before reading.
339// Switch back
340//
341Int_t MStatusArray::Read(const char *name)
342{
343 // It seems that the contents are not properly deleted by TObjArray::Read
344 Delete();
345
346 // Make sure newly read histograms are not added to the current directory
347 const Bool_t store = TH1::AddDirectoryStatus();
348 TH1::AddDirectory(kFALSE);
349 const Int_t rc = TObjArray::Read(name?name:"MStatusDisplay");
350 TH1::AddDirectory(store);
351
352 // All objects in the list (TNamed, TCanvas, etc) do not have
353 // the kCanDelete bit set. Make sure that it is set to make
354 // them deleted by the destructor of this list
355 TIter Next(this);
356 TObject *o=0;
357 while ((o=Next()))
358 {
359 if (o->InheritsFrom(TVirtualPad::Class()))
360 {
361 TIter Next2(((TVirtualPad*)o)->GetListOfPrimitives());
362 TObject *o2=0;
363 while ((o2=Next2()))
364 if (o2->InheritsFrom("MParContainer"))
365 o2->SetBit(kCanDelete);
366 }
367 o->SetBit(kCanDelete);
368 }
369
370 // Make sure that all kCanDelete bits are properly set
371 SetCanDelete(this);
372 SetOwner();
373
374 return rc;
375}
376
377// --------------------------------------------------------------------------
378//
379// Switch off adding histograms to current directory before reading.
380// Switch back
381//
382Int_t MStatusArray::Write(const char *name, Int_t option, Int_t bufsize) const
383{
384 SetMyCanDelete(this);
385 const Int_t rc = TObjArray::Write(name, option, bufsize);
386 ResetMyCanDelete(this);
387
388 return rc;
389}
Note: See TracBrowser for help on using the repository browser.