source: trunk/Mars/mbase/MEnv.cc@ 18525

Last change on this file since 18525 was 18018, checked in by dneise, 10 years ago
ticket:#11 MEnv, will now check if the last line ends with a \n ,and if not, it will throw an exception, print an explanation and stop fatally. This will hopefully make the user to add an empty line to the file and be happy.
File size: 34.1 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 2/2005 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2009
21!
22!
23\* ======================================================================== */
24
25//////////////////////////////////////////////////////////////////////////////
26//
27// MEnv
28//
29// It is a slightly changed version of TEnv. It logs all resources which are
30// touched, so that you can print all untouched resources by
31// PrintUntouched()
32//
33// A new special resource is available. With the resource "Include"
34// you can include resources from other files, for example
35//
36// Include: file1.rc file2.rc
37//
38// Including can be done recursively. Resources from the included files
39// have lower priority. This allows to write a resource file with your
40// default resources which then can be included in other files overwriting
41// some of the resources.
42//
43// If given paths are not absolute there base is always th elocation of
44// the including file.
45//
46// Class Version 1:
47// ----------------
48// + TString fName
49//
50//////////////////////////////////////////////////////////////////////////////
51#include "MEnv.h"
52
53#include <fstream>
54#include <exception>
55
56#include <Gtypes.h>
57#include <TObjString.h>
58#include <TObjArray.h>
59
60#include <TPave.h>
61#include <TAttText.h>
62#include <TAttMarker.h>
63#include <THashList.h> // needed since root v5.10/00 (TEnv::GetTable)
64
65#include "MLog.h"
66#include "MLogManip.h"
67
68#include "MArgs.h"
69#include "MString.h"
70
71ClassImp(MEnv);
72
73using namespace std;
74
75//---------------------------------------------------------------------------
76//
77// (Default) constructor. If the given file cannot be accessed SetRcName("")
78// is called which can then be checked by IsValid()
79//
80// The second argument is the default name. Usually as name of the MEnv
81// the base name of the file is returned. By giving a default name
82// you can overwrite this behavious. This is useful for I/O
83// because it allows to use Read and Write without argument.
84//
85MEnv::MEnv(const char *name, const char *defname) : TEnv(name), fName(defname)
86{
87 fChecked.SetOwner();
88
89 // If TEnv::TEnv has not set fRcName
90 if (!IsValid())
91 return;
92
93 // ExpandPathName (not done by TEnv::TEnv) and read again
94 TString fname(name);
95 gSystem->ExpandPathName(fname);
96
97 // Is file accessible
98 if (gSystem->AccessPathName(fname, kFileExists))
99 fname = "";
100
101 SetRcName(fname);
102
103 if (!IsTEnvCompliant(name)){
104 throw "This file can't be correctly parsed by TEnv";
105 return;
106 }
107
108 // No file found
109 if (fname.IsNull())
110 return;
111
112 // File has been already processed, but ReadInclude is part of a
113 // derived function, i.e. not yet executed.
114 if (GetEntries()>0 || fname==name)
115 {
116 if (ReadInclude()<0)
117 SetRcName("");
118 return;
119 }
120
121 // File not yet processed. Reread file.
122 if (ReadFile(fname, kEnvLocal)<0)
123 SetRcName("");
124}
125
126//---------------------------------------------------------------------------
127//
128// Process an Include directive and read the corresponding contents
129//
130Int_t MEnv::ReadInclude()
131{
132 // Check for "Include" resource
133 const TString incl = GetValue("Include", "");
134 if (incl.IsNull())
135 return 0;
136
137 const char *dir = gSystem->DirName(GetRcName());
138
139 // Tokenize the array into single files divided by a whitespace
140 TObjArray *arr = incl.Tokenize(" ");
141
142 // We have to rebuild the Include array from scratch to get the
143 // correct sorting for a possible rereading.
144 SetValue("Include", "");
145
146 // FIXME: Make sure that recursions don't crash the system!
147
148 for (int i=0; i<arr->GetEntries(); i++)
149 {
150 // Get file name to include
151 TString fenv = (*arr)[i]->GetName();
152
153 // If the is not anabsolute path we prepend the dir-name
154 // of the including file. This allows that includes
155 // do not necessarily need absolute paths and paths are always
156 // relative to the location of th eincluding file.
157 if (!gSystem->IsAbsoluteFileName(fenv))
158 {
159 fenv.Prepend("/");
160 fenv.Prepend(dir);
161 }
162
163 // Read included file and check if its valid
164 const MEnv env(fenv);
165 if (!env.IsValid())
166 {
167 delete arr;
168 return -1;
169 }
170
171 // Add file name before its childs
172 SetValue("+Include", fenv);
173
174 // If it is valid add entries from include without overwriting,
175 // i.e. the included resources have lower priority
176 AddEnv(env, kFALSE);
177
178 // Get a possible child include from env
179 const TString incl2 = const_cast<MEnv&>(env).GetValue("Include", "");
180 if (!incl2.IsNull())
181 SetValue("+Include", incl2);
182 }
183
184 delete arr;
185
186 // Get final compiled resource
187 TString inc = GetValue("Include", "");
188
189 // Remove obsolete whitespaces for convinience
190 inc.ReplaceAll(" ", " ");
191 inc = inc.Strip(TString::kBoth);
192
193 // Set final resource, now as kEnvLocal (previously set as kEnvChanged)
194 SetValue("Include", inc, kEnvLocal);
195
196 // FIXME: Remove douplets in the correct order
197
198 return 0;
199}
200
201//---------------------------------------------------------------------------
202//
203// Check if the input file is compatible to the way TEnv parses a resource file.
204//
205// Returns true in case everything is file and
206// false in case there is a problem with the file.
207//
208// Background:
209// This check has been introduced as a workaround for a ROOT feature.
210// TEnv will not see the last line in a text file, when this last line
211// does not end with a \n.
212//
213// In addition we check for the occurence of \r, since some editors would
214// place \r instead of \n (unlike windows that uses \n\r), which would
215// also result in problems.
216// FIXME: So currently we also complain about "\n\r" and "\r\n" as well as
217// "\r \t \n" or "\n \t\t\t\r", which would in fact not be a problem at
218// all.
219Bool_t MEnv::IsTEnvCompliant(const char *fname)
220{
221 ifstream ifs(fname);
222 bool printable_char_since_last_lf = false;
223 char c;
224 while (ifs.good()){
225 ifs.get(c);
226
227 if (c==13){
228 gLog << err << "Menv::IsTEnvCompliant - file:" << fname
229 << " contains \\r this might lead to parsing errors. "
230 <<"Please exchange \\r by \\n everywhere in that file."
231 << endl;
232 return false;
233 }
234 if (c=='\n'){
235 printable_char_since_last_lf = false;
236 }
237 if (isgraph(c)){
238 printable_char_since_last_lf = true;
239 }
240 }
241 if (printable_char_since_last_lf){
242 gLog << err << "Menv::IsTEnvCompliant - file:" << fname
243 << " must have \\n at the end of the file. "
244 <<"Please make sure this is the case."
245 << endl;
246 return false;
247 }
248 return true;
249}
250
251//---------------------------------------------------------------------------
252//
253// Read and parse the resource file for a certain level.
254// Returns -1 on case of error, 0 in case of success.
255//
256// Check for an include directive
257//
258Int_t MEnv::ReadFile(const char *fname, EEnvLevel level)
259{
260 // First read the file via TEnv
261 if (TEnv::ReadFile(fname, level)<0)
262 return -1;
263
264 return ReadInclude();
265}
266
267// --------------------------------------------------------------------------
268//
269// Read an object from the current directory. If no name is given
270// the name of this object is used.
271//
272Int_t MEnv::Read(const char *name)
273{
274 const Int_t rc = TEnv::Read(name?name:(const char*)fName);
275 //if (name)
276 // SetName(name);
277 return rc;
278}
279
280//---------------------------------------------------------------------------
281//
282// Make sure that the name used for writing doesn't contain a full path
283//
284const char *MEnv::GetName() const
285{
286 if (!fName.IsNull())
287 return fName;
288
289 const char *pos = strrchr(GetRcName(), '/');
290 return pos>0 ? pos+1 : GetRcName();
291}
292
293//---------------------------------------------------------------------------
294//
295// Return the total number of entries in the table
296//
297Int_t MEnv::GetEntries() const
298{
299 if (!GetTable())
300 return -1;
301
302 return GetTable()->GetEntries();
303}
304
305//---------------------------------------------------------------------------
306//
307// Compile str+post and make sure that in between there is a unique dot.
308//
309TString MEnv::Compile(TString str, const char *post) const
310{
311 if (!str.IsNull() && !str.EndsWith("."))
312 str += ".";
313
314 str += post;
315
316 return str;
317}
318
319//---------------------------------------------------------------------------
320//
321// Get the value from the table and remember the value as checked
322//
323Int_t MEnv::GetValue(const char *name, Int_t dflt)
324{
325 if (!fChecked.FindObject(name))
326 fChecked.Add(new TObjString(name));
327 return TEnv::GetValue(name, dflt);
328}
329
330//---------------------------------------------------------------------------
331//
332// Get the value from the table and remember the value as checked
333//
334Double_t MEnv::GetValue(const char *name, Double_t dflt)
335{
336 if (!fChecked.FindObject(name))
337 fChecked.Add(new TObjString(name));
338 return TEnv::GetValue(name, dflt);
339}
340
341//---------------------------------------------------------------------------
342//
343// Get the value from the table and remember the value as checked
344//
345const char *MEnv::GetValue(const char *name, const char *dflt)
346{
347 if (!fChecked.FindObject(name))
348 fChecked.Add(new TObjString(name));
349 return TEnv::GetValue(name, dflt);
350}
351
352//---------------------------------------------------------------------------
353//
354// TEnv doen't have a streamer --> cannot be cloned
355// --> we have to clone it ourself
356//
357TObject *MEnv::Clone(const char *) const
358{
359 MEnv *env = new MEnv("/dev/null");
360 env->SetRcName(GetRcName());
361 env->AddEnv(*this);
362 return env;
363}
364
365//---------------------------------------------------------------------------
366//
367// Interprete fill style: Hollow, Solid, Hatch, 0%-100%
368// If no text style is detected the value is converted to an integer.
369//
370Int_t MEnv::GetFillStyle(const char *name, Int_t dftl)
371{
372 TString str = GetValue(name, "");
373 str = str.Strip(TString::kBoth);
374 if (str.IsNull())
375 return dftl;
376
377 str.ToLower();
378
379 switch (str.Hash())
380 {
381 case 2374867578U: return 0; // hollow
382 case 764279305U: return 1001; // solid
383 case 1854683492U: return 2001; // hatch
384 }
385
386 return str.EndsWith("%") ? 4000+str.Atoi() : str.Atoi();
387}
388
389//---------------------------------------------------------------------------
390//
391// Interprete line style: Solid, Dashed, Dotted, DashDotted
392// If no line style is detected the value is converted to an integer.
393//
394Int_t MEnv::GetLineStyle(const char *name, Int_t dftl)
395{
396 TString str = GetValue(name, "");
397 str = str.Strip(TString::kBoth);
398 if (str.IsNull())
399 return dftl;
400
401 str.ToLower();
402
403 switch (str.Hash())
404 {
405 case 764279305U: return kSolid;
406 case 241979881U: return kDashed;
407 case 2391642602U: return kDotted;
408 case 1124931659U: return kDashDotted;
409 }
410
411 return str.Atoi();
412}
413
414//---------------------------------------------------------------------------
415//
416// Interprete alignment: Top, Right, Left, Bottom, Center, tr, cc, bl, ...
417// If no text align is detected the value is converted to an integer.
418//
419// eg.
420// Top Right
421// Bottom Center
422// Center
423// tr
424// br
425// cr
426//
427Int_t MEnv::GetAlign(const char *name, Int_t dftl)
428{
429 TString str = GetValue(name, "");
430 str = str.Strip(TString::kBoth);
431 if (str.IsNull())
432 return dftl;
433
434 str.ToLower();
435
436 switch (str.Hash())
437 {
438 case 29746: return 33; // tr
439 case 25379: return 22; // cc
440 case 25132: return 11; // bl
441
442 case 25388: return 12; // cl
443 case 25394: return 32; // cr
444
445 case 29731: return 23; // tc
446 case 25123: return 32; // bc
447
448 case 29740: return 13; // tl
449 case 25138: return 13; // br
450 }
451
452 Int_t align = 0;
453 if (str.Contains("right", TString::kIgnoreCase))
454 align += 3;
455 if (str.Contains("left", TString::kIgnoreCase))
456 align += 1;
457 if (str.Contains("bottom", TString::kIgnoreCase))
458 align += 10;
459 if (str.Contains("top", TString::kIgnoreCase))
460 align += 30;
461
462 if (str.Contains("center", TString::kIgnoreCase))
463 {
464 if (align==0)
465 return 22;
466 if (align/10==0)
467 return align+20;
468 if (align%10==0)
469 return align+2;
470 }
471
472 return align>0 ? align : str.Atoi();
473}
474
475//---------------------------------------------------------------------------
476//
477// Interprete color: Black, White, Red, Green, Blue, Yellow, Magenta,
478// Cyan, Gray1-5, Grey1-5.
479// If no text color is detected the value is converted to an integer.
480//
481// eg.
482// Red
483// Light Red
484// Dark Red
485//
486Int_t MEnv::GetColor(const char *name, Int_t dftl)
487{
488 TString str = GetValue(name, "");
489
490 str = str.Strip(TString::kBoth);
491 if (str.IsNull())
492 return dftl;
493
494 str.ToLower();
495
496 Int_t offset=0;
497 if (str.Contains("dark"))
498 {
499 str.ReplaceAll("dark", "");
500 str = str.Strip(TString::kBoth);
501 offset = 100;
502 }
503 if (str.Contains("light"))
504 {
505 str.ReplaceAll("light", "");
506 str = str.Strip(TString::kBoth);
507 offset = 150;
508 }
509
510 switch (str.Hash())
511 {
512 case 2368543371U: return kWhite+offset;
513 case 1814927399U: return kBlack+offset;
514 case 7496964U: return kRed+offset;
515 case 2897107074U: return kGreen+offset;
516 case 1702194402U: return kBlue+offset;
517 case 2374817882U: return kYellow+offset;
518 case 2894218701U: return kMagenta+offset;
519 case 1851881955U: return kCyan+offset;
520 case 749623518U: return 19; // grey1
521 case 749623517U: return 18; // grey2
522 case 749623516U: return 17; // grey3
523 case 749623515U: return 16; // grey4
524 case 749623514U: return 15; // grey5
525 case 749623513U: return 14; // grey6
526 case 749623512U: return 13; // grey7
527 case 749623511U: return 12; // grey8
528 case 741234910U: return 19; // gray1
529 case 741234909U: return 18; // gray2
530 case 741234908U: return 17; // gray3
531 case 741234907U: return 16; // gray4
532 case 741234906U: return 15; // gray5
533 case 741234905U: return 14; // gray6
534 case 741234904U: return 13; // gray7
535 case 741234903U: return 12; // gray8
536 }
537 return str.Atoi();
538}
539
540//---------------------------------------------------------------------------
541//
542// As possible convert the color col into a text string which can be
543// interpreted by GetColor before setting the resource value
544//
545void MEnv::SetColor(const char *name, Int_t col)
546{
547 TString val;
548
549 if (col>99 && col<101+kCyan)
550 {
551 val = "Dark ";
552 col -= 100;
553 }
554 if (col>150 && col<151+kCyan)
555 {
556 val = "Light ";
557 col -= 150;
558 }
559
560 switch (col)
561 {
562 case kWhite: val += "White"; break;
563 case kBlack: val += "Black"; break;
564 case kRed: val += "Red"; break;
565 case kGreen: val += "Green"; break;
566 case kBlue: val += "Blue"; break;
567 case kYellow: val += "Yellow"; break;
568 case kMagenta: val += "Magenta"; break;
569 case kCyan: val += "Cyan"; break;
570 case 19: val += "Grey1"; break;
571 case 18: val += "Grey2"; break;
572 case 17: val += "Grey3"; break;
573 case 16: val += "Grey4"; break;
574 case 15: val += "Grey5"; break;
575 case 14: val += "Grey6"; break;
576 case 13: val += "Grey7"; break;
577 case 12: val += "Grey8"; break;
578 }
579
580 if (val.IsNull())
581 val += col;
582
583 SetValue(name, val);
584}
585
586//---------------------------------------------------------------------------
587//
588// As possible convert the alignment align into a text string which can be
589// interpreted by GetAlign before setting the resource value
590//
591void MEnv::SetAlign(const char *name, Int_t align)
592{
593 TString val;
594 if (align==22)
595 {
596 SetValue(name, "Center");
597 return;
598 }
599
600 switch (align%10)
601 {
602 case 1: val += "Left"; break;
603 case 2: val += "Center"; break;
604 case 3: val += "Right"; break;
605 }
606
607 switch (align/10)
608 {
609 case 1: val += "Bottom"; break;
610 case 2: val += "Center"; break;
611 case 3: val += "Top"; break;
612 }
613
614 SetValue(name, val);
615}
616
617//---------------------------------------------------------------------------
618//
619// As possible convert the fill style style into a text string which can be
620// interpreted by GetFillStyle before setting the resource value
621//
622void MEnv::SetFillStyle(const char *name, Int_t style)
623{
624 TString val;
625
626 if (style>3999 && style<4101)
627 val = MString::Format("%d%%", style-4000);
628
629 switch (style)
630 {
631 case 0: val = "Hollow"; break;
632 case 1001: val = "Solid"; break;
633 case 2001: val = "Hatch"; break;
634 }
635
636 if (val.IsNull())
637 val += style;
638
639 SetValue(name, val);
640}
641
642//---------------------------------------------------------------------------
643//
644// As possible convert the line style style into a text string which can be
645// interpreted by GetLineStyle before setting the resource value
646//
647void MEnv::SetLineStyle(const char *name, Int_t style)
648{
649 TString val;
650 switch (style)
651 {
652 case kSolid: val = "Solid"; break;
653 case kDashed: val = "Dashed"; break;
654 case kDotted: val = "Dotted"; break;
655 case kDashDotted: val = "DashDotted"; break;
656 }
657
658 if (val.IsNull())
659 val += style;
660
661 SetValue(name, val);
662}
663
664//---------------------------------------------------------------------------
665//
666// As possible convert the marker style style into a text string which can be
667// interpreted by GetLineStyle before setting the resource value
668//
669void MEnv::SetMarkerStyle(const char *name, Int_t style)
670{
671 TString val;
672 switch (style)
673 {
674 case kDot: val = "dot";
675 case kPlus: val = "plus";
676 case kCircle: val = "circle";
677 case kMultiply: val = "multiply";
678 case kFullDotSmall: val = "fulldotsmall";
679 case kFullDotMedium: val = "fulldotmedium";
680 case kFullDotLarge: val = "fulldotlarge";
681// case kOpenTriangleDown: val = "opentriangledown";
682// case kFullCross: val = "fullcross";
683 case kFullCircle: val = "fullcircle";
684 case kFullSquare: val = "fullsquare";
685 case kFullTriangleDown: val = "fulltriangledown";
686 case kOpenCircle: val = "opencircle";
687 case kOpenSquare: val = "opensquare";
688 case kOpenTriangleUp: val = "opentriangleup";
689 case kOpenDiamond: val = "opendiamond";
690 case kOpenCross: val = "opencross";
691 case kFullStar: val = "fullstar";
692 case kOpenStar: val = "openstar";
693 }
694
695 if (val.IsNull())
696 val += style;
697
698 SetValue(name, val);
699}
700
701//---------------------------------------------------------------------------
702//
703// Get the attributed from a TAttLine (if dftl is given use it as default)
704// name.LineColor <see also GetColor>
705// name.LineStyle
706// name.LineWidth
707// For more details on the meaning see TAttLine
708//
709void MEnv::GetAttLine(const char *name, TAttLine &line, TAttLine *dftl)
710{
711 const TString color = Compile(name, "LineColor");
712 const TString style = Compile(name, "LineStyle");
713 const TString width = Compile(name, "LineWidth");
714
715 if (!dftl)
716 dftl = &line;
717
718 const Color_t col = GetColor(color, dftl->GetLineColor());
719 const Style_t sty = GetLineStyle(style, dftl->GetLineStyle());
720 const Style_t wid = GetValue(width, dftl->GetLineWidth());
721
722 line.SetLineColor(col);
723 line.SetLineStyle(sty);
724 line.SetLineWidth(wid);
725}
726
727//---------------------------------------------------------------------------
728//
729// Get the attributed from a TAttText (if dftl is given use it as default)
730// name.TextColor <see also GetColor>
731// name.TextAlign <see also GetAlign>
732// name.TextAngle
733// name.TextFont
734// name.TextSize
735// For more details on the meaning see TAttText
736//
737void MEnv::GetAttText(const char *name, TAttText &text, TAttText *dftl)
738{
739 const TString color = Compile(name, "TextColor");
740 const TString align = Compile(name, "TextAlign");
741 const TString angle = Compile(name, "TextAngle");
742 const TString font = Compile(name, "TextFont");
743 const TString size = Compile(name, "TextSize");
744
745 if (!dftl)
746 dftl = &text;
747
748 const Color_t col = GetColor(color, dftl->GetTextColor());
749 const Short_t ali = GetAlign(align, dftl->GetTextAlign());
750 const Float_t ang = GetValue(angle, dftl->GetTextAngle());
751 const Font_t fon = GetValue(font, dftl->GetTextFont());
752 const Float_t siz = GetValue(size, dftl->GetTextSize());
753
754 text.SetTextColor(col);
755 text.SetTextAlign(ali);
756 text.SetTextAngle(ang);
757 text.SetTextFont(fon);
758 text.SetTextSize(siz);
759}
760
761//---------------------------------------------------------------------------
762//
763// Get the attributed from a TAttFill (if dftl is given use it as default)
764// name.FillColor <see also GetColor>
765// name.FillStyle <see also GetFillStyle>
766// For more details on the meaning see TAttFill
767//
768void MEnv::GetAttFill(const char *name, TAttFill &fill, TAttFill *dftl)
769{
770 const TString color = Compile(name, "FillColor");
771 const TString style = Compile(name, "FillStyle");
772
773 if (!dftl)
774 dftl = &fill;
775
776 const Color_t col = GetColor(color, dftl->GetFillColor());
777 const Style_t sty = GetFillStyle(style, dftl->GetFillStyle());
778
779 fill.SetFillColor(col);
780 fill.SetFillStyle(sty);
781}
782
783//---------------------------------------------------------------------------
784//
785// Get the attributed from a TAttMarker (if dftl is given use it as default)
786// name.MarkerColor <see also GetColor>
787// name.MarkerStyle
788// name.MarkerSize
789// For more details on the meaning see TAttMarker
790//
791void MEnv::GetAttMarker(const char *name, TAttMarker &marker, TAttMarker *dftl)
792{
793 const TString color = Compile(name, "MarkerColor");
794 const TString style = Compile(name, "MarkerStyle");
795 const TString size = Compile(name, "MarkerSize");
796
797 if (!dftl)
798 dftl = &marker;
799
800 const Color_t col = GetColor(color, dftl->GetMarkerColor());
801 const Style_t sty = GetValue(style, dftl->GetMarkerStyle());
802 const Size_t siz = GetValue(size, dftl->GetMarkerSize());
803
804 marker.SetMarkerColor(col);
805 marker.SetMarkerStyle(sty);
806 marker.SetMarkerSize(siz);
807}
808
809//---------------------------------------------------------------------------
810//
811// Get the attributed from a TPave (if dftl is given use it as default)
812// name.CornerRadius
813// name.BorderSize
814// name.Option
815// Also all resources from TAttLine and TAttFill are supported.
816//
817// For your conveinience: If the CornerRadius is greater than 0 "arc" is
818// added to the options. If it is equal or less than 0 "arc" is removed
819// from the options.
820//
821// For more details on the meaning see TPave
822//
823void MEnv::GetAttPave(const char *str, TPave &pave, TPave *dftl)
824{
825 const TString post(str);
826
827 TString name(pave.GetName());
828 if (!name.IsNull() && name!=pave.ClassName())
829 name = Compile(name, post);
830
831 GetAttLine(name, pave, dftl);
832 GetAttFill(name, pave, dftl);
833
834 const TString corner = Compile(name, "CornerRadius");
835 const TString border = Compile(name, "BorderSize");
836 const TString option = Compile(name, "Option");
837
838 if (!dftl)
839 dftl = &pave;
840
841 const Double_t cor = GetValue(corner, dftl->GetCornerRadius());
842 const Int_t bor = GetValue(border, dftl->GetBorderSize());
843
844 pave.SetCornerRadius(cor);
845 pave.SetBorderSize(bor);
846
847 TString opt = GetValue(option, dftl->GetOption());
848 opt.ToLower();
849
850 const Bool_t has = pave.GetCornerRadius()>0;
851
852 if (has && !opt.Contains("arc"))
853 opt += "arc";
854
855 if (!has && opt.Contains("arc"))
856 opt.ReplaceAll("arc", "");
857
858 pave.SetOption(opt);
859
860}
861
862//---------------------------------------------------------------------------
863//
864// Get the attributed for the TObject obj. Use dftl for default attributes
865// if given.
866//
867// There is support for:
868// TPave <see GetAttPave>
869// TAttLine <see GetAttLine>
870// TAttText <see GetAttText>
871// TAttFill <see GetAttFill>
872// TAttMarker <see GetAttMarker>
873//
874void MEnv::GetAttributes(const char *name, TObject *obj, TObject *dftl)
875{
876 //TAttAxis *line = dynamic_cast<TAttAxis*>(obj);
877 //TAtt3D *line = dynamic_cast<TAtt3D*>(obj);
878 //TAttCanvas *line = dynamic_cast<TAttCanvas*>(obj);
879 //TAttFillCanvas *line = dynamic_cast<TAttFillEitor*>(obj);
880 //TAttLineCanvas *line = dynamic_cast<TAttLineCanvas*>(obj);
881 //TAttLineEditor *line = dynamic_cast<TAttLineEditor*>(obj);
882 //TAttMarkerCanvas *line = dynamic_cast<TAttMarkerCanvas*>(obj);
883 //TAttMarkerEditor *line = dynamic_cast<TAttMarkerEditor*>(obj);
884 //TAttPad *line = dynamic_cast<TAttPad*>(obj);
885 //TAttParticle *line = dynamic_cast<TAttParticle*>(obj);
886 //TAttTextCanvas *line = dynamic_cast<TAttTextCanvas*>(obj);
887 //TAttTextEditor *line = dynamic_cast<TAttTextEditor*>(obj);
888
889 TPave *pave = dynamic_cast<TPave*>(obj);
890 TAttLine *line = dynamic_cast<TAttLine*>(obj);
891 TAttText *text = dynamic_cast<TAttText*>(obj);
892 TAttFill *fill = dynamic_cast<TAttFill*>(obj);
893 TAttMarker *mark = dynamic_cast<TAttMarker*>(obj);
894
895 if (pave)
896 {
897 GetAttPave(name, *pave, dynamic_cast<TPave*>(dftl));
898 return;
899 }
900
901 if (line)
902 GetAttLine(name, *line, dynamic_cast<TAttLine*>(dftl));
903 if (text)
904 GetAttText(name, *text, dynamic_cast<TAttText*>(dftl));
905 if (fill)
906 GetAttFill(name, *fill, dynamic_cast<TAttFill*>(dftl));
907 if (mark)
908 GetAttMarker(name, *mark, dynamic_cast<TAttMarker*>(dftl));
909}
910
911//---------------------------------------------------------------------------
912//
913// Set the resources from a TAttLine:
914// name.LineColor <see also SetColor>
915// name.LineStyle
916// name.LineWidth
917//
918void MEnv::SetAttLine(const char *name, const TAttLine &line)
919{
920 const TString color = Compile(name, "LineColor");
921 const TString style = Compile(name, "LineStyle");
922 const TString width = Compile(name, "LineWidth");
923
924 SetColor(color, line.GetLineColor());
925 SetLineStyle(style, line.GetLineStyle());
926 SetValue(width, line.GetLineWidth());
927}
928
929//---------------------------------------------------------------------------
930//
931// Set the resources from a TAttText:
932// name.TextColor <see also SetColor>
933// name.TextAlign <see also SetAlign>
934// name.TextAngle
935// name.TextFont
936// name.TextSize
937//
938void MEnv::SetAttText(const char *name, const TAttText &text)
939{
940 const TString color = Compile(name, "TextColor");
941 const TString align = Compile(name, "TextAlign");
942 const TString angle = Compile(name, "TextAngle");
943 const TString font = Compile(name, "TextFont");
944 const TString size = Compile(name, "TextSize");
945
946 SetColor(color, text.GetTextColor());
947 SetAlign(align, text.GetTextAlign());
948 SetValue(angle, text.GetTextAngle());
949 SetValue(font, text.GetTextFont());
950 SetValue(size, text.GetTextSize());
951}
952
953//---------------------------------------------------------------------------
954//
955// Set the resources from a TAttFill:
956// name.FillColor <see also SetColor>
957// name.FillStyle <see also SetFillStyle>
958//
959void MEnv::SetAttFill(const char *name, const TAttFill &fill)
960{
961 const TString color = Compile(name, "FillColor");
962 const TString style = Compile(name, "FillStyle");
963
964 SetColor(color, fill.GetFillColor());
965 SetFillStyle(style, fill.GetFillStyle());
966}
967
968//---------------------------------------------------------------------------
969//
970// Set the resources from a TAttMarker:
971// name.MarkerColor <see also SetColor>
972// name.MarkerStyle
973// name.MarkerSize
974//
975void MEnv::SetAttMarker(const char *name, const TAttMarker &marker)
976{
977 const TString color = Compile(name, "MarkerColor");
978 const TString style = Compile(name, "MarkerStyle");
979 const TString size = Compile(name, "MarkerSize");
980
981 SetColor(color, marker.GetMarkerColor());
982 SetMarkerStyle(style, marker.GetMarkerStyle());
983 SetValue(size, marker.GetMarkerSize());
984}
985
986//---------------------------------------------------------------------------
987//
988// Set the resources from a TPave:
989// name.CornerRadius
990// name.BorderSize
991// name.Option
992// Also all resources from TAttLine and TAttFill are supported.
993//
994void MEnv::SetAttPave(const char *str, const TPave &pave)
995{
996 const TString name(str);
997
998 SetAttLine(name, pave);
999 SetAttFill(name, pave);
1000
1001 const TString corner = Compile(name, "CornerRadius");
1002 const TString border = Compile(name, "BorderSize");
1003 const TString option = Compile(name, "Option");
1004
1005 SetValue(corner, const_cast<TPave&>(pave).GetCornerRadius());
1006 SetValue(border, const_cast<TPave&>(pave).GetBorderSize());
1007 SetValue(option, pave.GetOption());
1008}
1009
1010//---------------------------------------------------------------------------
1011//
1012// Set the attributed for the TObject obj.
1013//
1014// There is support for:
1015// TPave <see SetAttPave>
1016// TAttLine <see SetAttLine>
1017// TAttText <see SetAttText>
1018// TAttFill <see SetAttFill>
1019// TAttMarker <see SetAttMarker>
1020//
1021void MEnv::SetAttributes(const char *name, const TObject *obj)
1022{
1023 const TPave *pave = dynamic_cast<const TPave*>(obj);
1024 const TAttLine *line = dynamic_cast<const TAttLine*>(obj);
1025 const TAttText *text = dynamic_cast<const TAttText*>(obj);
1026 const TAttFill *fill = dynamic_cast<const TAttFill*>(obj);
1027 const TAttMarker *mark = dynamic_cast<const TAttMarker*>(obj);
1028
1029 if (pave)
1030 {
1031 SetAttPave(name, *pave);
1032 return;
1033 }
1034
1035 if (line)
1036 SetAttLine(name, *line);
1037 if (text)
1038 SetAttText(name, *text);
1039 if (fill)
1040 SetAttFill(name, *fill);
1041 if (mark)
1042 SetAttMarker(name, *mark);
1043}
1044
1045//---------------------------------------------------------------------------
1046//
1047// Add all values from TEnv env the this MEnv. To not overwrite existing
1048// values set overwrite to kFALSE
1049//
1050void MEnv::AddEnv(const TEnv &env, Bool_t overwrite)
1051{
1052 if (!GetTable() || !env.GetTable())
1053 return;
1054
1055 TIter Next(env.GetTable());
1056
1057 TEnvRec *er;
1058 while ((er = (TEnvRec*)Next()))
1059 {
1060 if (overwrite || !Defined(er->GetName()))
1061 SetValue(er->GetName(), er->GetValue(), er->GetLevel(), er->GetType());
1062 }
1063}
1064
1065//---------------------------------------------------------------------------
1066//
1067// Check MArgs for all options "--rc=" and remove them. Options should be
1068// given like
1069//
1070// program --rc=Option1:Test1 --rc=Option2.SubOption:Test2
1071//
1072// If all resources could be interpeted corrctly kTRUE is returned. If
1073// there were problems kFALSE is returned.
1074//
1075Bool_t MEnv::TakeEnv(MArgs &arg, Bool_t print, Bool_t overwrite)
1076{
1077 if (!GetTable())
1078 {
1079 gLog << err << "ERROR - MEnv not yet initialized." << endl;
1080 return kFALSE;
1081 }
1082
1083 Bool_t ret = kTRUE;
1084 while (1)
1085 {
1086 const TString rc = arg.GetStringAndRemove("--rc=");
1087 if (rc.IsNull())
1088 break;
1089
1090 const Ssiz_t pos = rc.First(':');
1091 if (pos<0)
1092 {
1093 gLog << warn << "WARNING - Resource '" << rc << "' doesn't contain a colon... ignored." << endl;
1094 ret=kFALSE;
1095 continue;
1096 }
1097 if (pos==0)
1098 {
1099 gLog << warn << "WARNING - Resource '" << rc << "' doesn't contain a name... ignored." << endl;
1100 ret=kFALSE;
1101 continue;
1102 }
1103 if (pos==rc.Length()-1)
1104 {
1105 gLog << warn << "WARNING - Resource '" << rc << "' empty... ignored." << endl;
1106 ret=kFALSE;
1107 continue;
1108 }
1109
1110 const TString name = rc(0, pos);
1111 const TString val = rc(pos+1, rc.Length());
1112
1113 if (print)
1114 gLog << all << "Command line resource '" << name << "' with value '" << val << "'...";
1115
1116 const Bool_t exists = Defined(name);
1117 if (!exists)
1118 {
1119 SetValue(name, val, kEnvLocal);
1120 if (print)
1121 gLog << "set." << endl;
1122 continue;
1123 }
1124
1125 if (overwrite)
1126 {
1127 SetValue(name, "");
1128 SetValue(name, val, kEnvLocal);
1129 if (print)
1130 gLog << "changed." << endl;
1131 continue;
1132 }
1133
1134 if (print)
1135 gLog << "skipped/existing." << endl;
1136 }
1137 return ret;
1138}
1139
1140//---------------------------------------------------------------------------
1141//
1142// Add name and full path to output
1143//
1144void MEnv::PrintEnv(EEnvLevel level) const
1145{
1146 if (!TString(GetRcName()).IsNull())
1147 {
1148 cout << "# Path: " << GetRcName() << endl;
1149 cout << "# File: " << gSystem->BaseName(GetRcName()) << endl;
1150 }
1151 if (!fName.IsNull())
1152 cout << "# Name: " << fName << endl;
1153
1154 TEnv::PrintEnv(level);
1155}
1156
1157//---------------------------------------------------------------------------
1158//
1159// Print resources which have never been touched (for debugging)
1160//
1161void MEnv::PrintUntouched() const
1162{
1163 int i=0;
1164 gLog << inf << flush;
1165
1166 TString sep = "Untouched Resources in ";
1167 sep += GetRcName();
1168 gLog.Separator(sep);
1169 TIter Next(GetTable());
1170 TObject *o=0;
1171
1172 while ((o=Next()))
1173 if (!fChecked.FindObject(o->GetName()))
1174 {
1175 gLog << warn << " - Resource " << o->GetName() << " untouched" << endl;
1176 i++;
1177 }
1178 if (i==0)
1179 gLog << inf << "None." << endl;
1180 else
1181 gLog << inf << i << " resources have not been touched." << endl;
1182}
1183
1184//---------------------------------------------------------------------------
1185//
1186// Return number of resources which have not been touched.
1187//
1188Int_t MEnv::GetNumUntouched() const
1189{
1190 int i=0;
1191 TIter Next(GetTable());
1192 TObject *o=0;
1193 while ((o=Next()))
1194 if (!fChecked.FindObject(o->GetName()))
1195 i++;
1196 return i;
1197}
Note: See TracBrowser for help on using the repository browser.