source: trunk/Mars/mtools/MCalendar.cc@ 10398

Last change on this file since 10398 was 8996, checked in by tbretz, 16 years ago
*** empty log message ***
File size: 48.5 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 12/2005 <mailto:tbretz@astro.uni-wuerzburg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2005
21!
22!
23\* ======================================================================== */
24
25/////////////////////////////////////////////////////////////////////////////
26//
27// MCalendar
28//
29//
30// Resource files
31// --------------
32//
33// A calendar sheet is bets setup via a resource file with the
34// following contants:
35//
36// The day shown in the first column. (Sun=0, Mon=1, ...)
37// FirstDay: 0
38//
39// The Number of blocks the calendar sheet is made of:
40// NumBlocks: 2
41//
42// Set the position a graphic of the moon. The alignment is
43// coded as described in TAttText (0=off):
44// Moon.Graf.Align: 11
45//
46// Set the position a text describing the moon phase. The alignment is
47// coded as described in TAttText (0=off):
48// Moon.Text.Align: 11
49//
50// Set the text type: 0=MoonPhase, 1=MoonPeriod, 2=MagicPeriod
51// Moon.Text.Type: 0
52//
53// Determin whether the text should be continous or only at
54// new moon (only valid if both alignments identical)
55// Moon.Text.Continous: Yes
56//
57// Radius of the moon graphics in units of the pave height:
58// Moon.Graf.Radius: 0.08
59//
60// Horizontal and vertical margin in units of the pave height
61// between the pave border and the text:
62// MarginX: 0.05
63//
64// Space between the cells in units of the cell height:
65// CellSpace: 0.01
66//
67// Space between the blocks in units of the cell height:
68// BlockSpace: 0.1
69//
70// Local to determin the language to be used. For more details see
71// for example MTime::GetStringFmt or strftime (eg. de_DE, es_ES, it_IT)
72// The empty default is the system default (eg as if you call "date")
73// Language:
74//
75// The file name of a file containing the setup for holidays and birthdays:
76// HolidayFile:
77//
78// The setup of the pave in your calendar is done by the style defined
79// by a pave. For more details see TPave or MEnv::GetEnvPave:
80// Date.{PaveStyle}
81//
82// The contents of each pave in your calendar.
83// Contents: Date Day Week Holiday Birthday
84//
85// There are NO predefined content-strings. All the names given here
86// are completely artificial. You could also call them just A and B.
87// If you setup them correctly they might still behave like Date and Day.
88// This also means that you can define as many of them as you want.
89//
90// You can setup the contents by their names individually (eg. Holiday).
91// The possible Style is defined by a TLatex object. For more details
92// see TLatex or MEnv::GetAttText.
93//
94// To setup the position in the pave use:
95// Holiday.TextAlign: center
96// Holiday.TextAlign: center top
97// Holiday.TextAlign: right center
98// Holiday.TextAlign: right top
99//
100// The text style can be setup by:
101// Holiday.TextSize: 0.13
102// Holiday.TextColor: Blue
103//
104// To setup a day-dependant string, in addition to the three resources
105// above, a format string as defined in MTime::GetStringFmt or strftime.
106// Holiday.Format: %a
107//
108// Contents for which a format was setup are compiled by using
109// MTime::GetStringFmt.
110// Contents without a format set (by eg. Holiday.Format) are searched in
111// the holiday resource file:
112//
113// For the 1.1. and 25.12. the setup could be:
114// Holiday.01/01: New year
115// Holiday.12/25: Christmas
116//
117// Holidays with respect to Easter are given as
118// Holiday.-1: Easter Saturday
119// Holiday.0: Easter
120// Holiday.1: Easter Monday
121//
122// In addition to this you can overwrite the default for the active
123// and/or inactivedays by:
124// Date.Active.{PaveStyle}
125// Holiday.Active.TextColor: Blue
126// Holiday.Inactive.TextColor: Gray1
127//
128// To define a special setup for only one day (Sun=0, Mon=1, ...) use:
129// Date.Active.0.{PaveStyle}
130// Holiday.Active.0.TextColor: Red
131// Holiday.Inactive.0.TextColor: White
132//
133// To get a resource file describing the default layout draw a calendar
134// sheet and choose "SaveResourceFile" from the context menu. By using
135// the context menu you can change the layout and also save it to a
136// resource file. Read such a resource file using ReadResourceFile.
137//
138//
139// Context Menu
140// ------------
141//
142// void SetDate(UInt_t Month, Int_t Year=-1)
143// Used to set new year and month. Use Year=-1 to keep the year
144//
145// void SetLocal(const char *Locale="")
146// Set new Localization. For more details see MTime::GetStringFmt or
147// strftime
148//
149// void SetFirstDay(Int_t FirstDay)
150// Define the WeekDay in the first column (Son=0, Mon=1, ...)
151//
152// void SetLayout(Byte_t NumberOfBlocks, Double_t MarginX, Double_t MarginY, Double_t CellSpace, Double_t BlockSpace)
153// change the Layout. For more details see section "Resource Files"
154//
155// void ResetLayout(num)
156// Remove everything from the layout. num is the number of default blocks
157// (corresponding to NumBlocks). A value smaller or equal 0 will leave
158// the number of block unchanged (which is the default from the
159// context menu)
160//
161// void ResetHolidays()
162// remove all holidays.
163//
164// void SetDefaultLayout(num)
165// set the layout to the default layout. num is the number of displayed
166// blocks (corresponding to NumBlocks). A value smaller or equal 0 will
167// leave the number of block unchanged (which is the default from the
168// context menu)
169//
170// void SetDefaultHolidays()
171// set the default holidays
172//
173// void ReadResourceFile(const char *FileName=0)
174// read layout from a resource file. (also the holidays are reread)
175//
176// void ReadHolidayFile(const char *FileName=0)
177// read holidays from a file
178//
179// void SaveResourceFile(const char *FileName=0)
180// save current layout to a file
181//
182// void SaveHolidayFile(const char *FileName=0)
183// save current holidays to a file
184//
185// void Add(const char *Name, Int_t Align, const char *Format, Float_t FontSize=0.3, Int_t FontColor=1); //*MENU
186// add contents to the pave (for more details see section
187// "resource files")
188//
189// void SetDay(const char *Format="%a", Float_t FontSize=0.3, Int_t Color=kBlack)
190// void SetDate(const char *Format="%e", Float_t FontSize=0.3, Int_t Color=kBlack) { Remove(GetAlign()); Add("Date", GetAlign(), Format, FontSize, Color); } //*MENU*
191// set the current position in the pave to a format defined by Format.
192// with FontSize and FontColor. For more details see MTime::GetStringFmt
193// or the man-page of strftime. The name of the corrsponding resources
194// is set to "Day" or "Date".
195//
196// void SetHoliday(Float_t FontSize=0.13, Int_t Color=kBlue)
197// void SetBirthday(Float_t FontSize=0.13, Int_t Color=kBlue)
198// void SetEaster(Float_t FontSize=0.13, Int_t Color=kBlue)
199// set the current position in the pave to a holiday with name
200// "Holiday", "Birthday". The holidays are read from the
201// holiday resource file. For more details see section "Resource files"
202//
203// void AddHoliday(const char *text)
204// void AddBirthday(const char *text)
205// void AddEaster(const char *text)
206// Add a holiday ("Holiday.mm/dd", "Birthday.mm/dd" or "Holiday.%d")
207// for the current date (for easter the offset to easter is used instead)
208// to the holiday resources.
209//
210// void Remove()
211// Remove the contents from the edge you are pointing to.
212//
213// void PrintEnv()
214// Print the current resources.
215//
216// void SetEnv(const char *VariableName, const char *Value)
217// Set a new resource.
218//
219// void RemoveEnv(const char *VariableName)
220// Remove a resource and all subsequent resources
221//
222// void SetMoonGraf(Int_t Align, Float_t Radius)
223// void SetMoonText(Int_t Align, Int_t Type, Int_t Continous)
224// change the setup of the moon. For more details see the
225// section "Resource Files"
226//
227//
228// Format
229// ------
230//
231// For convinience here is a copy from MTime of the most important
232// format string to be used in the "Format" resource, GetStringFmt
233// or DrawDate:
234//
235// %a The abbreviated weekday name according to the current locale.
236// %A The full weekday name according to the current locale.
237// %b The abbreviated month name according to the current locale.
238// %B The full month name according to the current locale.
239// %d The day of the month as a decimal number (range 01 to 31).
240// %e Like %d, the day of the month as a decimal number,
241// but a leading zero is replaced by a space.
242// %H The hour as a decimal number using a 24-hour clock (range 00 to 23)
243// %k The hour (24-hour clock) as a decimal number (range 0 to 23);
244// single digits are preceded by a blank.
245// %m The month as a decimal number (range 01 to 12).
246// %x The preferred date representation for the current locale w/o time.
247// %y The year as a decimal number without a century (range 00 to 99).
248// %Y The year as a decimal number including the century.
249
250/////////////////////////////////////////////////////////////////////////////
251#include "MCalendar.h"
252
253#include <TStyle.h>
254#include <TArrow.h>
255#include <TLatex.h>
256#include <TMarker.h>
257#include <TArrayD.h>
258#include <TCanvas.h>
259#include <TSystem.h>
260#include <TEllipse.h>
261#include <TASImage.h>
262#include <TPaveText.h>
263#include <THashList.h>
264#include <TObjArray.h>
265
266#include "MEnv.h"
267#include "MTime.h"
268
269ClassImp(MCalendar);
270
271// ****************+ ROOT Bugs *****************
272// fCornerRadius not handled in TPave::Copy
273// TEllipse::Paint(values) doesn't work at all
274// TEnv::SetValue crashes if created with default constructor
275// TEnv::Save doesn't take filename as an argument
276// TEnv::fRcName no Getter
277// DrawClone doesn't work for a canvas/pad containing a TASImage
278// TPave::GetCornerRadius not const
279// TPabe::GetBorderRadius not const
280// TEllipse is transparent if FillColor=kWhite
281// TLatex::PaintLatex also sets data members to arguments in
282// contradiction to all other graf-classes.
283// TEnv cannot be streamed from/to a file (means: cannot be cloned!)
284// Double_t TEnv::GetValue Typo: dobule
285// Support for TTF fonts in font directory in TText?
286// TASImage::DrawText doesn't search TTFonts in root ttfont-path
287// TTF::SetTextFont ttffont not deleted (see gSystem->Which)
288// TASImage doesn't support transparency?
289
290using namespace std;
291
292//---------------------------------------------------------------------------
293//
294// Convert Umlauts and other exotic characters to TLatex readable characters
295//
296void MCalendar::Convert2Latex(TString &str)
297{
298 str.ReplaceAll("\xe4", "\\ddot{a}");
299 str.ReplaceAll("\xf6", "\\ddot{o}");
300 str.ReplaceAll("\xfc", "\\ddot{u}");
301 str.ReplaceAll("\xc4", "\\ddot{A}");
302 str.ReplaceAll("\xd6", "\\ddot{O}");
303 str.ReplaceAll("\xdc", "\\ddot{U}");
304 str.ReplaceAll("\xdf", "\\beta");
305 str.ReplaceAll("\xe1", "\\acute{a}");
306 str.ReplaceAll("\xe9", "\\acute{e}");
307 str.ReplaceAll("\xec", "\\grave{i}");
308
309 str.ReplaceAll("\xc3\xa4", "\\ddot{a}");
310 str.ReplaceAll("\xc3\xb6", "\\ddot{o}");
311 str.ReplaceAll("\xc3\xbc", "\\ddot{u}");
312 str.ReplaceAll("\xc3\x84", "\\ddot{A}");
313 str.ReplaceAll("\xc3\x96", "\\ddot{O}");
314 str.ReplaceAll("\xc3\x9c", "\\ddot{U}");
315 str.ReplaceAll("\xc3\x9f", "\\beta");
316 str.ReplaceAll("\xc3\xa1", "\\acute{a}");
317 str.ReplaceAll("\xc3\xa9", "\\acute{e}");
318 str.ReplaceAll("\xc3\xac", "\\grave{i}");
319}
320
321void MCalendar::ConvertUTF8(TString &str, Bool_t fwd)
322{
323 if (fwd)
324 {
325 str.ReplaceAll("\xe4", "\xc3\xa4");
326 str.ReplaceAll("\xf6", "\xc3\xb6");
327 str.ReplaceAll("\xfc", "\xc3\xbc");
328 str.ReplaceAll("\xc4", "\xc3\x84");
329 str.ReplaceAll("\xd6", "\xc3\x96");
330 str.ReplaceAll("\xdc", "\xc3\x9c");
331 str.ReplaceAll("\xdf", "\xc3\x9f");
332 str.ReplaceAll("\xe1", "\xc3\xa1");
333 str.ReplaceAll("\xe9", "\xc3\xa9");
334 str.ReplaceAll("\xec", "\xc3\xac");
335 }
336 else
337 {
338 str.ReplaceAll("\xc3\xa4", "\xe4");
339 str.ReplaceAll("\xc3\xb6", "\xf6");
340 str.ReplaceAll("\xc3\xbc", "\xfc");
341 str.ReplaceAll("\xc3\x84", "\xc4");
342 str.ReplaceAll("\xc3\x96", "\xd6");
343 str.ReplaceAll("\xc3\x9c", "\xdc");
344 str.ReplaceAll("\xc3\x9f", "\xdf");
345 str.ReplaceAll("\xc3\xa1", "\xe1");
346 str.ReplaceAll("\xc3\xa9", "\xe9");
347 str.ReplaceAll("\xc3\xac", "\xec");
348 }
349}
350
351
352//---------------------------------------------------------------------------
353//
354// TEnv doesn't have a streamer so we have to make sure that the
355// resources get corretly cloned.
356//
357TObject *MCalendar::Clone(const char *newname) const
358{
359 MCalendar *cal = (MCalendar*)TObject::Clone(newname);
360
361 if (cal->fEnv)
362 delete cal->fEnv;
363 if (cal->fEnvHolidays)
364 delete cal->fEnvHolidays;
365
366 cal->fEnv = (MEnv*)fEnv->Clone();
367 cal->fEnvHolidays = (MEnv*)fEnvHolidays->Clone();
368
369 return cal;
370}
371
372//---------------------------------------------------------------------------
373//
374// return the StringFmt (see MTime::GetStringFmt or strftime)
375// corresponding to the Format fmt (Default="%B", LongMonthName).
376// For more complicated formatings day, hour, minutes and sec can
377// be given.
378//
379TString MCalendar::GetStringFmt(const char *fmt, Int_t day, Int_t h, Int_t m, Int_t s) const
380{
381 MTime t;
382 t.Set(fYear, fMonth, day, h, m, s);
383 return t.GetStringFmt(fmt, GetLanguage());
384}
385
386//---------------------------------------------------------------------------
387//
388// Get the Pave setup for the given condition from the resources
389//
390void MCalendar::GetPave(TPave &pave, Bool_t active, Int_t n)
391{
392 // ----- Default ----
393 TPave def;
394 def.SetName(pave.GetName());
395 def.SetLineStyle(kSolid);
396 def.SetLineColor(kBlack);
397 def.SetLineWidth(0);
398 def.SetFillColor(18);
399 def.SetFillStyle(1001);
400 def.SetCornerRadius(0);
401 def.SetBorderSize(1);
402
403 fEnv->GetAttPave("", def);
404
405 def.Copy(pave);
406
407 pave.SetCornerRadius(def.GetCornerRadius());
408 pave.SetLineColor(active ? kBlack : 15);
409
410 const char *fmt1 = active ? "Active" : "Inactive";
411 const char *fmt2 = active ? "Active.%d" : "Inactive.%d";
412
413 fEnv->GetAttributes( fmt1, &pave);
414 fEnv->GetAttributes(Form(fmt2, n), &pave);
415}
416
417//---------------------------------------------------------------------------
418//
419// Get the Moon setup for the given condition from the resources
420//
421void MCalendar::GetMoon(TAttText &text, TAttFill &fill, Bool_t active, Int_t n)
422{
423 TAttText txt(11, 0, gStyle->GetTextColor(), gStyle->GetTextFont(), 0.13);
424 TAttFill fil(0, 1001);
425
426 fEnv->GetAttText("Moon", txt);
427 fEnv->GetAttFill("Moon", fil);
428
429 txt.Copy(text);
430 fil.Copy(fill);
431
432 text.SetTextColor(active ? kRed : 15);
433 fill.SetFillColor(active ? kBlack : 15);
434
435 const char *fmt1 = active ? "Moon.Active" : "Moon.Inactive";
436 const char *fmt2 = active ? "Moon.Active.%d" : "Moon.Inactive.%d";
437
438 fEnv->GetAttText(fmt1, text);
439 fEnv->GetAttFill(fmt1, fill);
440
441 fEnv->GetAttText(Form(fmt2, n), text);
442 fEnv->GetAttFill(Form(fmt2, n), fill);
443}
444
445//---------------------------------------------------------------------------
446//
447// Get the Text setup for the given condition from the resources
448//
449void MCalendar::GetLatex(TLatex &latex, Bool_t active, Int_t n)
450{
451 const TString fmt = fEnv->GetValue(Form("%s.Format", latex.GetName()), "");
452 latex.SetTitle(fmt);
453
454 TAttText(0, 0, kBlack, gStyle->GetTextFont(), 0.3).Copy(latex);
455 fEnv->GetAttText(latex.GetName(), latex);
456
457 if (!active)
458 latex.SetTextColor(15);
459
460 const char *fmt1 = active ? "%s.Active" : "%s.Inactive";
461 const char *fmt2 = active ? "%s.Active.%d" : "%s.Inactive.%d";
462
463 fEnv->GetAttText(Form(fmt1, latex.GetName()), latex);
464 fEnv->GetAttText(Form(fmt2, latex.GetName(), n), latex);
465}
466
467//---------------------------------------------------------------------------
468//
469// Add a text. The name determins the identifier for which the resources
470// are searched, align the position in the pave (the convention is the same
471// as in TAttText). If a format fmt is given the date corresponding to the
472// pave is converted to a string using MTime::GetStringFmt. See MTime
473// for more details. If the format is empty the Holiday resources are
474// searched for an entry with the name. size defines the default height
475// of the text in units of the pave-height and color the default color in
476// case of active days.
477// eg.
478// Add("Day", 13, "%a", 0.3, kRed);
479// would produce a short WeekDay-name (%a) at the top left edge with
480// with a default height of 0.3*pave-height in Red. You can change
481// the behaviour from the resource file by:
482// Day.{TextAttribute}
483// Day.Active.{TextAttribute}
484// Day.Inctive.{TextAttribute}
485// Day.Active.i.{TextAttribute}
486// Day.Inctive.i.{TextAttribute}
487// for more details about TextAttribute see MEnv::GetAttText and TAttText.
488// i is a placeholder for the WeekDay number (starting with sunday=0)
489//
490void MCalendar::Add(const char *name, Int_t align, const char *fmt, Float_t size, Int_t col)
491{
492 TAttText att(align, 0, col, gStyle->GetTextFont(), size);
493 Add(name, fmt, att);
494}
495
496void MCalendar::Add(const char *name, const char *fmt, const TAttText &att)
497{
498 fEnv->SetAttText(name, att);
499 fEnv->SetValue(Form("%s.Format", name), fmt);
500
501 const TString cont = Form(" %s ", fEnv->GetValue("Contents", ""));
502 const TString form = Form(" %s ", name);
503 if (!cont.Contains(form))
504 fEnv->SetValue("Contents", Form("%s %s", cont.Strip(TString::kBoth).Data(), name));
505}
506
507//---------------------------------------------------------------------------
508//
509// Save the current layout to a resource file. If no filename is given
510// the filename of the current open resource file is used.
511//
512void MCalendar::SaveResourceFile(const char *fname)
513{
514 const TString name = fname ? fname : fEnv->GetName();
515
516 gSystem->Unlink(name);
517
518 MEnv env(name);
519
520 env.SetValue("FirstDay", fFirstDay);
521 env.SetValue("NumBlocks", fNumBlocks);
522
523 env.SetValue("Orientation", fOrientation);
524 env.SetValue("Rotation", fRotation);
525
526 env.SetValue("Moon.Graf.Align", fMoonAlignGraf);
527 env.SetValue("Moon.Text.Align", fMoonAlignText);
528 env.SetValue("Moon.Text.Type", fMoonTextType);
529 env.SetValue("Moon.Text.Continous", fMoonTextCont);
530 env.SetValue("Moon.Graf.Radius", fMoonRadius);
531
532 env.SetValue("MarginX", fMarginX);
533 env.SetValue("MarginY", fMarginY);
534 env.SetValue("CellSpace", fCellSpace);
535 env.SetValue("BlockSpace", fBlockSpace);
536
537 env.SetValue("Language", GetLanguage());
538
539 env.SetValue("HolidayFile", fEnvHolidays->GetName());
540
541 env.AddEnv(*fEnv);
542 env.Save();
543}
544
545//---------------------------------------------------------------------------
546//
547// Save the current holidays to a resource file. If no filename is given
548// the filename of the current open holiday file is used.
549//
550void MCalendar::SaveHolidayFile(const char *fname)
551{
552 const TString name = fname ? fname : fEnvHolidays->GetName();
553
554 gSystem->Unlink(name);
555
556 MEnv env(name);
557 env.AddEnv(*fEnvHolidays);
558 env.Save();
559}
560
561//---------------------------------------------------------------------------
562//
563// The Layout will be resetted and than restored from the specified
564// resource file. If no filename is given the filename of the current
565// open resource file is used.
566//
567void MCalendar::ReadResourceFile(const char *fname)
568{
569 const TString name = fname ? fname : fEnv->GetName();
570
571 ResetLayout(2);
572
573 delete fEnv;
574 fEnv = new MEnv(name);
575
576 fFirstDay = fEnv->GetValue("FirstDay", fFirstDay);
577 fNumBlocks = fEnv->GetValue("NumBlocks", fNumBlocks);
578
579 fOrientation = fEnv->GetValue("Orientation", fOrientation);
580 fRotation = fEnv->GetValue("Rotation", fOrientation);
581
582 fMoonAlignGraf = fEnv->GetValue("Moon.Graf.Align", fMoonAlignGraf);
583 fMoonAlignText = fEnv->GetValue("Moon.Text.Align", fMoonAlignText);
584 fMoonTextType = fEnv->GetValue("Moon.Text.Type", fMoonTextType);
585 fMoonTextCont = fEnv->GetValue("Moon.Text.Continous", fMoonTextCont);
586 fMoonRadius = fEnv->GetValue("Moon.Graf.Radius", fMoonRadius);
587
588 fMarginX = fEnv->GetValue("MarginX", fMarginX);
589 fMarginY = fEnv->GetValue("MarginY", fMarginY);
590 fCellSpace = fEnv->GetValue("CellSpace", fCellSpace);
591 fBlockSpace = fEnv->GetValue("BlockSpace", fBlockSpace);
592
593 SetLocal(fEnv->GetValue("Language", ""));
594 ReadHolidayFile();
595}
596
597//---------------------------------------------------------------------------
598//
599// The Holidays will be resetted and than restored from the specified
600// holiday file. If no filename is given the filename of the current
601// open holiday file is used.
602//
603void MCalendar::ReadHolidayFile(const char *fname)
604{
605 const TString name = fname ? fname : fEnvHolidays->GetName();
606
607 if (fEnvHolidays)
608 delete fEnvHolidays;
609 fEnvHolidays = new MEnv(name);
610}
611
612//---------------------------------------------------------------------------
613//
614// Reset the layout (remove everything)
615//
616// num is the number of default blocks (corresponding to NumBlocks).
617// A value smaller or equal 0 will leave the number of block unchanged
618// (which is the default)
619//
620void MCalendar::ResetLayout(Int_t num)
621{
622 fOrientation = kFALSE;
623 fRotation = kFALSE;
624
625 fFirstDay = 1;
626
627 if (num>0)
628 fNumBlocks = num;
629
630 fMoonAlignGraf = 0;
631 fMoonAlignText = 0;
632 fMoonTextType = 0;
633 fMoonTextCont = kFALSE;
634 fMoonRadius = 0.08;
635
636 fMarginX = 0.05;
637 fMarginY = 0.05;
638
639 fCellSpace = 0.01;
640 fBlockSpace = 0.1;
641
642 if (fEnv)
643 delete fEnv;
644
645 fEnv = new MEnv("/dev/null");
646}
647
648//---------------------------------------------------------------------------
649//
650// Reset the holidays (remove everything)
651//
652void MCalendar::ResetHolidays()
653{
654 if (fEnvHolidays)
655 delete fEnvHolidays;
656
657 fEnvHolidays = new MEnv("/dev/null");
658}
659
660//---------------------------------------------------------------------------
661//
662// Set the holidays to the default holidays
663//
664void MCalendar::SetDefaultHolidays()
665{
666 ResetHolidays();
667
668 fEnvHolidays->SetValue("Holiday.0", "Easter");
669 fEnvHolidays->SetValue("Holiday.01/01", "New Year");
670 fEnvHolidays->SetValue("Holiday.12/25", "Christmas");
671 fEnvHolidays->SetValue("Holiday.12/26", "Christmas");
672}
673
674//---------------------------------------------------------------------------
675//
676// Set the layout to the default layout
677//
678// num is the number of default blocks (corresponding to NumBlocks).
679// A value smaller or equal 0 will leave the number of block unchanged
680// (which is the default)
681//
682void MCalendar::SetDefaultLayout(Int_t num)
683{
684 ResetLayout(num);
685
686 fMoonAlignGraf = 11;
687 fMoonAlignText = 11;
688
689 fEnv->SetValue("Contents", "Day Date Week Holiday Birthday");
690
691 fEnv->SetValue("Day.TextAlign", "top left");
692 fEnv->SetValue("Day.Format", "%e");
693
694 fEnv->SetValue("Date.TextAlign", "bottom right");
695 fEnv->SetValue("Date.Format", "%a");
696
697 fEnv->SetValue("Week.TextAlign", "top right");
698 fEnv->SetValue("Week.Format", "KW%V");
699 fEnv->SetValue("Week.TextSize", 0.1);
700 fEnv->SetValue("Week.Restriction", 1);
701 fEnv->SetValue("Week.Active.TextColor", "Grey8");
702
703 fEnv->SetValue("Holiday.TextAlign", "center");
704 fEnv->SetValue("Holiday.TextSize", 0.13);
705 fEnv->SetValue("Holiday.TextColor", kBlue);
706
707 fEnv->SetValue("Birthday.TextAlign", "center");
708 fEnv->SetValue("Birthday.TextSize", 0.13);
709 fEnv->SetValue("Birthday.TextColor", kBlue);
710
711 // fEnv->SetValue("Easter.TextAlign", "center");
712 // fEnv->SetValue("Easter.TextSize", 0.13);
713 // fEnv->SetValue("Easter.TextColor", kBlue);
714
715 fEnv->SetValue("Date.Active.0.TextColor", kRed);
716
717 fEnv->SetValue("Date.Active.TextFont", 22);
718 fEnv->SetValue("Day.Active.TextFont", 22);
719 fEnv->SetValue("Date.Inactive.TextFont", 132);
720 fEnv->SetValue("Day.Inactive.TextFont", 132);
721
722 // fEnv->SetValue("Date.Inactive.LineStyle", kDashed);
723 // fEnv->SetValue("Date.Inactive.FillColor", kWhite);
724}
725
726//---------------------------------------------------------------------------
727//
728// Create a calendar piece for the given year and month. If a filename
729// is given the corresponding resource file is read. If no month and/or
730// no year is given the current date is used instead.
731//
732MCalendar::MCalendar(UShort_t y, Byte_t m, const char *fname)
733 : fYear(y==0?MTime(-1).Year():y), fMonth(m==0?MTime(-1).Month():m)
734{
735 fEnv =0;
736 fEnvHolidays=0;
737
738 //fUpdate = kFALSE;
739
740 SetDefaultLayout(2);
741 SetDefaultHolidays();
742
743 if (fname)
744 ReadResourceFile(fname);
745}
746
747//---------------------------------------------------------------------------
748//
749// Delete the two resource files
750//
751MCalendar::~MCalendar()
752{
753 delete fEnv;
754 delete fEnvHolidays;
755}
756
757//---------------------------------------------------------------------------
758//
759// Take the pave edges and the margin and calculate the new x and y
760// coordinates from it for the given alignment (as in TAttText),
761//
762TArrayD MCalendar::ConvertAlign(Int_t align, Double_t x[2], Double_t y[2], Double_t m[2]) const
763{
764 align = Rotate(align);
765
766 TArrayD p(2);
767 switch (align/10)
768 {
769 case 1: p[0] = x[0]+m[0]; break;
770 case 2: p[0] = (x[0]+x[1])/2; break;
771 case 3: p[0] = x[1]-m[0]; break;
772 }
773 switch (align%10)
774 {
775 case 1: p[1] = y[0]+m[1]; break;
776 case 2: p[1] = (y[0]+y[1])/2; break;
777 case 3: p[1] = y[1]-m[1]; break;
778 }
779 return p;
780}
781
782//---------------------------------------------------------------------------
783//
784// Rotate the aligment if the orientation is changed.
785//
786Int_t MCalendar::Rotate(Int_t align, Bool_t fwd) const
787{
788 if (fOrientation==fRotation)
789 return align;
790
791 static const Int_t b[4] = { 11, 31, 33, 13 };
792 static const Int_t a[4] = { 11, 13, 33, 31 };
793
794 const Int_t *c = fwd ? a :b;
795
796 for (int i=0; i<4; i++)
797 if (align==c[i])
798 return c[(i+1)%4];
799
800 return align;
801}
802
803//---------------------------------------------------------------------------
804//
805// Paint the text str at the position indirectly given by alignement, x and
806// y (see ConvertAlign for more details) with the attributes from TAttText.
807//
808void MCalendar::PaintLatex(TAttText &att, Int_t align, Double_t x[2], Double_t y[2], Double_t ratio[2], /*Double_t height,*/ TString str)
809{
810 TLatex tex;
811 att.Copy(tex);
812
813 Double_t m[2] = {
814 fMarginX*ratio[0],
815 fMarginY*ratio[1]
816 };
817
818 const TArrayD p = ConvertAlign(align, x, y, m);
819 /*
820 tex.SetText(p[0], p[1], str);
821 tex.SetTextAngle(0);
822 tex.SetTextSize(att.GetTextSize()*height);
823
824 while (1)
825 {
826 Double_t w = tex.GetXsize();
827 Double_t h = tex.GetYsize();
828 if (w<width-2*m[0] && h<height-2*m[1])
829 break;
830
831 tex.SetTextSize(tex.GetTextSize()*0.99);
832 }
833
834 tex.Paint();
835 */
836
837 const Double_t scale = fOrientation ? x[1]-x[0] : y[1]-y[0];
838 const Double_t phi = fOrientation!=fRotation ? -90 : 0;
839
840 Convert2Latex(str);
841
842 tex.SetTextAlign(align);
843 tex.PaintLatex(p[0], p[1], phi, att.GetTextSize()*scale, str);
844}
845
846//---------------------------------------------------------------------------
847//
848// Paint a clock as a symbol for summer-/wintertime
849//
850void MCalendar::PaintClock(Double_t x[2], Double_t y[2], Double_t r[2], Int_t fill, char dir)
851{
852 Double_t k[2] = { (x[0]+x[1])/2, (y[0]+y[1])/2 };
853
854 TEllipse e(k[0], k[1], r[0]*2.5, r[1]*2.5, 30, 360, 0);
855 e.SetLineColor(kBlack);
856 e.SetLineStyle(kSolid);
857 e.SetFillColor(fill);
858 e.Paint();
859
860 TMarker m;
861 m.SetMarkerStyle(kFullDotSmall);
862 for (int i=2; i<12; i++)
863 m.PaintMarker(k[0]+r[0]*2*cos(TMath::TwoPi()*i/12),
864 k[1]+r[1]*2*sin(TMath::TwoPi()*i/12));
865
866 TArrow a(k[0]+r[0]*3, k[1], k[0]+r[0]*2.7, k[1]+r[1]*1.5, r[1]/2);
867 a.Paint(dir=='-'?"->":"<-");
868}
869
870//---------------------------------------------------------------------------
871//
872// Check the holiday resources for a holiday matching the the resource name:
873// name.mm/dd
874// while name is the name of the TObject, mm and dd are month and day
875// of the MTime.
876//
877TString MCalendar::GetHoliday(const TObject &o, const MTime &tm)
878{
879 const Int_t easter = (Int_t)MTime::GetEaster(fYear).GetMjd();
880
881 const TString fmt = o.GetTitle();
882
883 if (!fmt.IsNull())
884 return tm.GetStringFmt(fmt, GetLanguage());
885
886 TString env(o.GetName());
887
888 const TString post1 = Form(".%d", (Int_t)tm.GetMjd()-easter);
889 const TString post2 = Form(".%02d/%02d", tm.Month(), tm.Day());
890
891 TString rc;
892 for (int i=0; i<7; i++)
893 {
894 MTime tx(tm.GetMjd()+i);
895 const TString post3 = Form(".%02d/%02d-%d", tx.Month(), tx.Day(), (7-tm.WeekDay())%7);
896 rc = fEnvHolidays->GetValue(env+post3, rc);
897 }
898
899 rc = fEnvHolidays->GetValue(env+post1, rc);
900 rc = fEnvHolidays->GetValue(env+post2, rc);
901/*
902 if (fLanguage=="de_DE")
903 {
904 MTime t;
905 t.Set(fYear, 5, 14);
906 t.SetMjd(t.GetMjd()-t.WeekDay());
907
908 if ((Int_t)t.GetMjd() == easter + 49)
909 t.SetMjd(t.GetMjd()-7);
910
911 if ((Int_t)tm.GetMjd()==(Int_t)t.GetMjd())
912 return "Muttertag";
913 }
914
915 */
916 return rc;
917}
918
919void MCalendar::Paint(Option_t *opt)
920{
921 /*
922 if (fUpdate)
923 {
924 fEnv->SetAttLine(fActive?"Date.Active":"Date.Inactive", *this);
925 fUpdate = kFALSE;
926 }
927 */
928
929 // How should this be done?
930 //fOrientation = gPad->PixeltoX(1)>-gPad->PixeltoY(1);
931
932 MTime t;
933 t.Set(fYear, fMonth, 1);
934
935 Int_t n = t.WeekDay();
936
937 Int_t diff = (7-fFirstDay)%7;
938 n += diff;
939 n %= 7;
940
941 t.SetMjd(t.GetMjd()-n);
942 n = 0;
943
944 for (; n<99; n++)
945 {
946 const MTime tm(t.GetMjd()+n);
947
948 const Bool_t active = tm.Month()==(UInt_t)fMonth;
949
950 Double_t x[2], y[2], ratio[2];
951 const Bool_t rc = GetBox(n, x, y, ratio);
952
953 if (!active && rc)
954 break;
955
956 // Get part of string for this day
957 const Int_t day = (n+7-diff)%7;
958
959 TPave pave;
960 pave.SetName("Date");
961 GetPave(pave, active, day);
962
963 // ---------- Paint Border and fill area ----------
964 pave.SetX1NDC(x[0]);
965 pave.SetY1NDC(y[0]);
966 pave.SetX2NDC(x[1]);
967 pave.SetY2NDC(y[1]);
968 pave.Paint(pave.GetOption());
969
970 Double_t r[2] = {
971 fMoonRadius*ratio[0],
972 fMoonRadius*ratio[1]
973 };
974
975 // ---------- Paint Text ----------
976 const TString contents = fEnv->GetValue("Contents", "");
977 TObjArray *arr = contents.Tokenize(" ");
978
979 TIter Next(arr);
980 TObject *o=0;
981 while ((o=Next()))
982 {
983 TLatex latex;
984 latex.SetName(o->GetName());
985
986 const TString res = fEnv->GetValue(Form("%s.Restriction", o->GetName()), "0123456");
987 if (res.First('0'+tm.WeekDay())<0)
988 continue;
989
990 GetLatex(latex, active, day);
991
992 const TString text = GetHoliday(latex, tm);
993
994 if (text=="T+" || text=="T-")
995 {
996 PaintClock(x, y, r, pave.GetFillColor(), text[1]);
997 continue;
998 }
999
1000 if (!text.IsNull())
1001 PaintLatex(latex, latex.GetTextAlign(), x, y, ratio, text);
1002 }
1003
1004 delete arr;
1005
1006 // ---------- Paint Moon Phase -----------
1007 //Double_t r[2] = {
1008 // fMoonRadius*ratio[0],
1009 // fMoonRadius*ratio[1]
1010 //};
1011 Double_t m[2] = {
1012 fMarginX*ratio[0] + r[0],
1013 fMarginY*ratio[1] + r[1]
1014 };
1015
1016 TAttText text;
1017 TAttFill fill;
1018 GetMoon(text, fill, active, day);
1019
1020 // Shift if grafic and moon should be displayed at the same
1021 // location, the text is a discrete number and it is
1022 // switched to continous.
1023 const Bool_t rot = fOrientation!=fRotation;
1024 const Float_t phi = rot ? -90 : 0;
1025 const Int_t dx = rot;
1026 const Int_t dy = (rot+1)%2;
1027 const Bool_t cont = fMoonTextType==0 || fMoonTextCont;
1028 if (fMoonAlignGraf)
1029 {
1030 TArrayD p = ConvertAlign(fMoonAlignGraf, x, y, m);
1031
1032 if (fMoonAlignGraf==fMoonAlignText && cont && fMoonAlignGraf==22)
1033 p[dy] += rot ? -m[dy]/2 : m[dy]/2;
1034
1035 TEllipse e(p[0], p[1], r[0], r[1], -90+phi, 90+phi, 0);
1036 fill.Copy(e);
1037 e.SetLineStyle(0);
1038 e.Paint();
1039 if (tm.GetMoonPhase()<0.5)
1040 {
1041 e.SetLineStyle(kSolid);
1042 e.SetLineColor(pave.GetFillColor());
1043 e.SetFillColor(pave.GetFillColor());
1044 }
1045 else
1046 {
1047 e.SetPhimin(90+phi); // bug in PaintEllipse!
1048 e.SetPhimax(270+phi); // bug in PaintEllipse!
1049 }
1050 const Double_t R = tm.GetMoonPhase()<0.5 ? 1-tm.GetMoonPhase() : tm.GetMoonPhase();
1051 const Double_t r0 = 1.0-TMath::Sqrt(2.0-2.0*R);
1052 if (rot)
1053 e.SetR2(r[1]*r0); // bug in PaintEllipse!
1054 else
1055 e.SetR1(r[0]*r0); // bug in PaintEllipse!
1056 e.Paint();
1057 }
1058
1059 if (fMoonAlignGraf==fMoonAlignText && !cont && tm.GetMoonPhase()>0.004)
1060 continue;
1061
1062 // ---------- Paint Moon Text -----------
1063 if (fMoonAlignText)
1064 {
1065 if (fMoonAlignGraf!=fMoonAlignText || (fMoonAlignGraf==fMoonAlignText && !cont))
1066 m[dx] -= r[dx];
1067
1068 TArrayD p = ConvertAlign(fMoonAlignText, x, y, m);
1069
1070 if (fMoonAlignGraf==fMoonAlignText && cont)
1071 {
1072 if (rot)
1073 {
1074 m[dx] = -m[dx];
1075 m[dy] = -m[dy];
1076 }
1077
1078 switch (fMoonAlignGraf/10)
1079 {
1080 case 1: p[dx] += m[dx]; break;
1081 case 2: p[dy] += fMoonAlignGraf%10==1 ? m[dy]*1.25 : -m[dy]*1.25; break;
1082 case 3: p[dx] -= m[dx]; break;
1083 }
1084 }
1085
1086 TString num;
1087 switch (fMoonTextType)
1088 {
1089 case 0:// kMoonPhase:
1090 num = Form("%d%%", TMath::Nint(tm.GetMoonPhase()*100));
1091 break;
1092 case 1://kMoonPeriod:
1093 num = Form("%d", (Int_t)tm.GetMoonPeriod());
1094 break;
1095 case 2://kMagicPeriod:
1096 num = Form("%d", tm.GetMagicPeriod());
1097 break;
1098 }
1099
1100 const Double_t scale = fOrientation ? x[1]-x[0] : y[1]-y[0];
1101
1102 TLatex tex;
1103 text.Copy(tex);
1104 tex.SetTextAlign(10*(fMoonAlignText/10)+2); // 12
1105 tex.PaintLatex(p[0], p[1], phi, text.GetTextSize()*scale, num);
1106 }
1107 }
1108
1109 /*
1110 TASImage img;
1111 img.FromPad(gPad);
1112 img.Flip(90);
1113 img.Paint();
1114 */
1115}
1116
1117Bool_t MCalendar::GetBox(Int_t n, Double_t x[2], Double_t y[2], Double_t *ratio)
1118{
1119 //const Int_t maxrows = 6; //28/(7*fNumBlocks) + 1;
1120 const Float_t addrows = 0;
1121
1122 Int_t maxrows;
1123 switch(fNumBlocks)
1124 {
1125 case 0:
1126 case 1: maxrows=6; break;
1127 case 2: maxrows=3; break;
1128 case 3: maxrows=2; break;
1129 case 4: maxrows=2; break;
1130 default: maxrows=1; break;
1131 }
1132
1133 const Float_t ratio0 = -gPad->PixeltoX(1)/gPad->PixeltoY(1);
1134
1135 // Cellspace
1136 const Float_t celly = fCellSpace;
1137 const Float_t cellx = fOrientation ? fCellSpace/ratio0 : fCellSpace*ratio0;
1138
1139 // Blockspace
1140 //Float_t blockspacey = fBlockSpace;
1141 const Float_t blockx = fOrientation ? fBlockSpace/ratio0 : fBlockSpace*ratio0;
1142
1143 const Float_t w = (0.99-cellx*(7*fNumBlocks-1)-(fNumBlocks-1)*blockx)/(fNumBlocks*7);
1144 const Float_t h = (0.99-celly*(maxrows-1)/*-blockspacey*/)/(maxrows+addrows);
1145
1146
1147 const Int_t ix = n%(7*fNumBlocks);
1148 const Int_t iy = n/(7*fNumBlocks);
1149
1150 const Int_t col = ix/7;
1151
1152 const Double_t p0 = 0.005 - col*(cellx - blockx);
1153
1154 TArrayD a(2), b(2);
1155
1156 a[0] = p0 + ix*(cellx + w);
1157 a[1] = p0 + ix*(cellx + w) + w;
1158
1159 b[0] = 0.995 - iy*(celly + h) - h;
1160 b[1] = 0.995 - iy*(celly + h);
1161
1162 if (ratio)
1163 {
1164 ratio[0] = ratio0>1 ? h : h*ratio0;
1165 ratio[1] = ratio0>1 ? h/ratio0 : h;
1166 }
1167
1168 if (fOrientation)
1169 {
1170 x[0] = b[0];
1171 x[1] = b[1];
1172 y[0] = a[0];
1173 y[1] = a[1];
1174 }
1175 else
1176 {
1177 x[0] = a[0];
1178 x[1] = a[1];
1179 y[0] = b[0];
1180 y[1] = b[1];
1181 }
1182
1183 if (fOrientation)
1184 {
1185 TArrayD d(2,y);
1186 y[0] = 1-d[1];
1187 y[1] = 1-d[0];
1188 }
1189
1190 if (fRotation)
1191 {
1192 TArrayD d(2,x);
1193 x[0] = 1-d[1];
1194 x[1] = 1-d[0];
1195 }
1196
1197 return ix==0 && iy>0;
1198}
1199
1200//---------------------------------------------------------------------------
1201//
1202// Determine the absolute number of the day from the event (mouse)
1203// position.
1204//
1205Int_t MCalendar::GetN(Double_t x[2], Double_t y[2])
1206{
1207 if (!gPad)
1208 return 0;
1209
1210 const Double_t px = gPad->AbsPixeltoX(gPad->GetEventX());
1211 const Double_t py = gPad->AbsPixeltoY(gPad->GetEventY());
1212
1213 int n=0;
1214 for (n=0; n<99; n++)
1215 {
1216 GetBox(n, x, y);
1217 if (x[0]<px && px<x[1] && y[0]<py && py<y[1])
1218 break;
1219 }
1220
1221 return n==99 ? -1 : n;
1222}
1223
1224//---------------------------------------------------------------------------
1225//
1226// Determine the date of the day from the event (mouse) position.
1227//
1228MTime MCalendar::GetDate()
1229{
1230 const Int_t n = GetN();
1231 if (n<0)
1232 return MTime();
1233
1234 MTime t;
1235 t.Set(fYear, fMonth, 1);
1236
1237 Int_t k = t.WeekDay();
1238
1239 k += (7-fFirstDay)%7;
1240 k %= 7;
1241
1242 return MTime(t.GetMjd()-k+n);
1243}
1244
1245//---------------------------------------------------------------------------
1246//
1247// Determin the alignment of the event (mouse) position.
1248//
1249Int_t MCalendar::GetAlign()
1250{
1251 Double_t x[2], y[2];
1252 if (GetN(x, y)<0)
1253 return 0;
1254
1255 const Double_t px = gPad->AbsPixeltoX(gPad->GetEventX());
1256 const Double_t py = gPad->AbsPixeltoY(gPad->GetEventY());
1257
1258 const Int_t alignx = (Int_t)(3*(px-x[0])/(x[1]-x[0]))+1;
1259 const Int_t aligny = (Int_t)(3*(py-y[0])/(y[1]-y[0]))+1;
1260
1261 return Derotate(alignx*10+aligny);
1262}
1263
1264//---------------------------------------------------------------------------
1265//
1266// Remove the text entry at the event (mouse) position.
1267//
1268void MCalendar::Remove(Int_t align)
1269{
1270 TObjArray *arr = TString(fEnv->GetValue("Contents", "")).Tokenize(" ");
1271
1272 TIter Next(arr);
1273 TObject *o=0;
1274 while ((o=Next()))
1275 {
1276 TAttText att;
1277 fEnv->GetAttText(o->GetName(), att);
1278
1279 if (att.GetTextAlign()!=align)
1280 continue;
1281
1282 TString cont = Form(" %s ", fEnv->GetValue("Contents", ""));
1283 cont.ReplaceAll(Form(" %s ", o->GetName()), " ");
1284 fEnv->SetValue("Contents", cont.Strip(TString::kBoth).Data());
1285
1286 RemoveEnv(o->GetName());
1287 }
1288
1289 delete arr;
1290}
1291
1292Int_t MCalendar::DistancetoPrimitive(Int_t x, Int_t y)
1293{
1294 const Double_t px = gPad->AbsPixeltoX(x);
1295 const Double_t py = gPad->AbsPixeltoY(y);
1296
1297 return px>0.01 && px<0.99 && py>0.01 && py<0.99 ? 0 : 99999;
1298}
1299
1300//---------------------------------------------------------------------------
1301//
1302// Add a holiday named "text" at the event (mouse) position.
1303//
1304void MCalendar::AddHoliday(const char *text)
1305{
1306 MTime t = GetDate();
1307 if (!t)
1308 return;
1309
1310 const TString str = Form("Holiday.%02d/%02d", t.Month(), t.Day());
1311
1312 fEnvHolidays->SetValue(str, text);
1313}
1314
1315//---------------------------------------------------------------------------
1316//
1317// Add a birthday named "text" at the event (mouse) position.
1318//
1319void MCalendar::AddBirthday(const char *text)
1320{
1321 MTime t = GetDate();
1322 if (!t)
1323 return;
1324
1325 const TString str = Form("Birthday.%02d/%02d", t.Month(), t.Day());
1326
1327 fEnvHolidays->SetValue(str, text);
1328}
1329
1330//---------------------------------------------------------------------------
1331//
1332// Add a easterday named "text" at the event (mouse) position. The special
1333// thing is that the holiday is relative to easter and will shift with
1334// easter for other years.
1335//
1336void MCalendar::AddEaster(const char *text)
1337{
1338 MTime t = GetDate();
1339 if (!t)
1340 return;
1341
1342 const Int_t easter = (Int_t)MTime::GetEaster(fYear).GetMjd();
1343
1344 const TString str = Form("Holiday.%d", (Int_t)t.GetMjd()-easter);
1345
1346 fEnvHolidays->SetValue(str, text);
1347}
1348
1349//---------------------------------------------------------------------------
1350//
1351// Print the current resources.
1352//
1353void MCalendar::PrintEnv() const
1354{
1355 fEnv->Print();
1356}
1357
1358//---------------------------------------------------------------------------
1359//
1360// Set a new resource.
1361//
1362void MCalendar::SetEnv(const char *VariableName, const char *Value) const
1363{
1364 fEnv->SetValue(VariableName, Value);
1365}
1366
1367//---------------------------------------------------------------------------
1368//
1369// Remove a resource and all subsequent resources
1370//
1371void MCalendar::RemoveEnv(const char *name) const
1372{
1373 const TString n1 = name;
1374 const TString n2 = Form("%s.", name);
1375
1376 TCollection *table = fEnv->GetTable();
1377
1378 TIter Next(table);
1379 TObject *o=0;
1380 while ((o=Next()))
1381 if (n1==o->GetName() || TString(o->GetName()).BeginsWith(n2))
1382 delete table->Remove(o);
1383}
1384
1385//---------------------------------------------------------------------------
1386//
1387// Create a pad with the given coordinates, Draw a clone of the image
1388// into it and resize the pad to the image properties such that it is
1389// centered in the original area.
1390//
1391// DrawImage cd()'s to the new pad.
1392//
1393TASImage *MCalendar::DrawImage(const TASImage &img, Float_t x1, Float_t y1, Float_t x2, Float_t y2, Bool_t rot)
1394{
1395 TPad *pad=new TPad("Img", "Image", x1, y1, x2, y2);
1396 pad->SetBorderMode(0);
1397 pad->SetFillColor(gPad?gPad->GetFillColor():kWhite);
1398 pad->SetBit(kCanDelete);
1399 pad->SetTopMargin(0);
1400 pad->SetRightMargin(0);
1401 pad->SetLeftMargin(0);
1402 pad->SetBottomMargin(0);
1403 pad->Draw();
1404
1405 gROOT->SetSelectedPad(0);
1406
1407 pad->cd();
1408
1409 TASImage *clone = (TASImage*)img.DrawClone();
1410 clone->SetBit(kCanDelete);
1411
1412 pad->Modified();
1413 pad->Update();
1414
1415 const Int_t wi = clone->GetScaledWidth();
1416 const Int_t hi = clone->GetScaledHeight();
1417
1418 TCanvas *c = pad->GetCanvas();
1419
1420 const Float_t x = (x1+x2)/2;
1421 const Float_t y = (y1+y2)/2;
1422
1423 Float_t w = TMath::Abs(x2-x1)/2;
1424 Float_t h = TMath::Abs(y2-y1)/2;
1425
1426 const Float_t ri = TMath::Abs(c->PixeltoX(wi)/c->PixeltoY(hi));
1427 const Float_t rp = TMath::Abs(w/h);
1428
1429 if (ri>rp)
1430 h = w/ri;
1431 else
1432 w = h*ri;
1433
1434 pad->SetPad(x-w, y-h, x+w, y+h);
1435 pad->SetFixedAspectRatio();
1436
1437 return clone;
1438}
1439
1440//---------------------------------------------------------------------------
1441//
1442// Small helper for GetImage: Allocate a new TASImage. If it is valid
1443// return the pointer, if not delete the object and return NULL.
1444//
1445TASImage *MCalendar::ReturnFile(const char *file) const
1446{
1447 TASImage *img = new TASImage(file);
1448 if (img->IsValid())
1449 return img;
1450
1451 delete img;
1452 return NULL;
1453}
1454
1455//---------------------------------------------------------------------------
1456//
1457// Get a TASImage from a TEnv (if no TEnv is given as argument the
1458// default resource file os used). The TEnv is searched for the following
1459// tags in the following order:
1460//
1461// %B: The month name as defined by the local (try GetStringFmt("%B"))
1462// %b: The abbreviation of the month name as defined by the local (try GetStringFmt("%b"))
1463// %02d: The number of the month with leading zeros.
1464//
1465// If no tag could be found or the image read is invalid NULL is returned.
1466// Otherwise a newly allocated TASImage is returned (the used is responsible
1467// of deleting it)
1468//
1469TASImage *MCalendar::GetImage(TEnv *env, const char *pwd)
1470{
1471 if (!env)
1472 env = fEnv;
1473
1474 TString fStrMonth = GetStringFmt("%B");
1475 TString fStrMonth3 = GetStringFmt("%b");
1476
1477 ConvertUTF8(fStrMonth3, kFALSE);
1478 ConvertUTF8(fStrMonth, kFALSE);
1479
1480 const TString path(pwd);
1481
1482 TString file = env->GetValue(fStrMonth, "");
1483 if (!file.Strip(TString::kBoth).IsNull())
1484 return ReturnFile(path+file);
1485
1486 file = env->GetValue(fStrMonth3, "");
1487 if (!file.Strip(TString::kBoth).IsNull())
1488 return ReturnFile(path+file);
1489
1490 file = env->GetValue(Form("%02d", fMonth), "");
1491 if (!file.Strip(TString::kBoth).IsNull())
1492 return ReturnFile(path+file);
1493
1494 return NULL;
1495}
1496
1497//---------------------------------------------------------------------------
1498//
1499// Draw a Latex (after conversion with Convert2Latex, to support Umlauts,
1500// etc) text text at the coordinates x and y with the attributes att.
1501//
1502// To use a date format string (see GetStringFmt()) instead of a plain
1503// text use DrawDate instead.
1504//
1505void MCalendar::DrawLatex(Float_t x, Float_t y, const char *text, const TAttText &att)
1506{
1507 TString str(text);
1508 Convert2Latex(str);
1509
1510 TLatex *latex = new TLatex(x, y, text);
1511 att.Copy(*latex);
1512 latex->SetBit(kCanDelete);
1513 latex->Draw();
1514}
1515
1516const char *MCalendar::GetTTFontPath(const char *file) const
1517{
1518 const TString p1 = gEnv->GetValue("Root.TTFontPath", "");
1519 const TString p2 = "/usr/X11R6/lib/X11/fonts/truetype";
1520 // const TString p3 = path;
1521
1522 TString n(file);
1523
1524 if (n.First('.')<0 && n.First('/')<0)
1525 n.Append(".ttf");
1526
1527 return gSystem->Which(p1+":"+p2/*+":"+p3*/, n, kReadPermission);
1528}
1529
1530//---------------------------------------------------------------------------
1531//
1532// Draw a Text text into your image. For more details see TASImage::DrawText.
1533//
1534// This is a wrapper to simplify access to TrueType Fonts.
1535//
1536// You can just skip the path and the extension, eg "comic" is enough for
1537// the TTF "comic.ttf".
1538//
1539// The search path is "*.*.Root.TTFontPath" from gEnv (.rootrc),
1540// "/usr/X11R6/lib/X11/fonts/truetype" and path.
1541//
1542// For available fonts see eg. $ROOTSYS/fonts
1543//
1544void MCalendar::DrawText(TASImage &img, Int_t x, Int_t y, const char *txt,
1545 Int_t size, const char *color, const char *font,
1546 TImage::EText3DType type, const char *path)
1547{
1548 const char *file = GetTTFontPath(font);
1549 if (!file)
1550 return;
1551
1552 img.DrawText(x, y, txt, size, color, file, type);
1553
1554 delete file;
1555}
1556
1557#define __CINT__
1558#include <TTF.h>
1559TASImage *MCalendar::DrawTTF(Float_t x1, Float_t x2, Float_t y1, Float_t y2,
1560 const char *text, Float_t sz, const char *font)
1561{
1562 const char *file = GetTTFontPath(font);
1563 if (!file)
1564 return NULL;
1565
1566 const UInt_t size = TMath::Nint(sz*941);
1567
1568 delete file;
1569
1570 const Double_t x = (x1+x2)/2;
1571 const Double_t y = (y1+y2)/2;
1572
1573 TASImage img;
1574 DrawDate(img, 0, 0, text, size, "#000000", font);
1575
1576 const Double_t w = gPad->PixeltoX(img.GetWidth())/2;
1577 const Double_t h = gPad->PixeltoY(img.GetHeight())/2;
1578
1579 return DrawImage(img, x-w, y-h, x+w, y+h);
1580}
1581
1582/*
1583void MCalendar::Update()
1584{
1585 cout << "Update" << endl;
1586 fUpdate=kTRUE;
1587}
1588
1589void MCalendar::Selected(TVirtualPad *pad,TObject *o,Int_t event)
1590{
1591 if (event==kButton1Down && pad)
1592 {
1593 pad->cd();
1594 fAlign = GetAlign();
1595 fActive = GetDate().Month()==fMonth;
1596 fEnv->GetAttLine(fActive?"Date.Active":"Date.Inactive", *this);
1597 fEnv->GetAttLine(Form(fActive?"Date.Active.%d":"Date.Inactive.%d", fDay), *this);
1598 }
1599
1600 cout << "SetModel " << gPad << " " << pad << " " << o << " " << event << endl;
1601 //Picked(fSelectedPad, fSelected, fEvent); // emit signal
1602
1603}
1604
1605void MCalendar::SetAttributes()
1606{
1607 if (!gPad)
1608 return;
1609
1610 TAttLine::SetLineAttributes();
1611
1612 cout << "gPad " << gPad << endl;
1613
1614 fAlign = GetAlign();
1615 fActive = GetDate().Month()==fMonth;
1616 fDay = GetDate().WeekDay();
1617
1618 fEnv->GetAttLine(fActive?"Date.Active":"Date.Inactive", *this);
1619 fEnv->GetAttLine(Form(fActive?"Date.Active.%d":"Date.Inactive.%d", fDay), *this);
1620
1621 TQObject::Connect("TCanvas", "Selected(TVirtualPad*,TObject*,Int_t)",
1622 "MCalendar", this, "Selected(TVirtualPad*,TObject*,Int_t)");
1623
1624 TQObject::Connect("TGedPatternSelect", "PatternSelected(Style_t)", "MCalendar", this, "Update()");
1625 TQObject::Connect("TGColorSelect", "ColorSelected(Pixel_t)", "MCalendar", this, "Update()");
1626 TQObject::Connect("TGListBox", "Selected(Int_t)", "MCalendar", this, "Update()");
1627}
1628*/
1629
Note: See TracBrowser for help on using the repository browser.