source: trunk/MagicSoft/Mars/mtools/MCalendar.cc@ 7979

Last change on this file since 7979 was 7923, checked in by tbretz, 18 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
265#include "MEnv.h"
266#include "MTime.h"
267
268ClassImp(MCalendar);
269
270// ****************+ ROOT Bugs *****************
271// fCornerRadius not handled in TPave::Copy
272// TEllipse::Paint(values) doesn't work at all
273// TEnv::SetValue crashes if created with default constructor
274// TEnv::Save doesn't take filename as an argument
275// TEnv::fRcName no Getter
276// DrawClone doesn't work for a canvas/pad containing a TASImage
277// TPave::GetCornerRadius not const
278// TPabe::GetBorderRadius not const
279// TEllipse is transparent if FillColor=kWhite
280// TLatex::PaintLatex also sets data members to arguments in
281// contradiction to all other graf-classes.
282// TEnv cannot be streamed from/to a file (means: cannot be cloned!)
283// Double_t TEnv::GetValue Typo: dobule
284// Support for TTF fonts in font directory in TText?
285// TASImage::DrawText doesn't search TTFonts in root ttfont-path
286// TTF::SetTextFont ttffont not deleted (see gSystem->Which)
287// TASImage doesn't support transparency?
288
289using namespace std;
290
291//---------------------------------------------------------------------------
292//
293// Convert Umlauts and other exotic characters to TLatex readable characters
294//
295void MCalendar::Convert2Latex(TString &str)
296{
297 str.ReplaceAll("\xe4", "\\ddot{a}");
298 str.ReplaceAll("\xf6", "\\ddot{o}");
299 str.ReplaceAll("\xfc", "\\ddot{u}");
300 str.ReplaceAll("\xc4", "\\ddot{A}");
301 str.ReplaceAll("\xd6", "\\ddot{O}");
302 str.ReplaceAll("\xdc", "\\ddot{U}");
303 str.ReplaceAll("\xdf", "\\beta");
304 str.ReplaceAll("\xe1", "\\acute{a}");
305 str.ReplaceAll("\xe9", "\\acute{e}");
306 str.ReplaceAll("\xec", "\\grave{i}");
307
308 str.ReplaceAll("\xc3\xa4", "\\ddot{a}");
309 str.ReplaceAll("\xc3\xb6", "\\ddot{o}");
310 str.ReplaceAll("\xc3\xbc", "\\ddot{u}");
311 str.ReplaceAll("\xc3\x84", "\\ddot{A}");
312 str.ReplaceAll("\xc3\x96", "\\ddot{O}");
313 str.ReplaceAll("\xc3\x9c", "\\ddot{U}");
314 str.ReplaceAll("\xc3\x9f", "\\beta");
315 str.ReplaceAll("\xc3\xa1", "\\acute{a}");
316 str.ReplaceAll("\xc3\xa9", "\\acute{e}");
317 str.ReplaceAll("\xc3\xac", "\\grave{i}");
318}
319
320void MCalendar::ConvertUTF8(TString &str, Bool_t fwd)
321{
322 if (fwd)
323 {
324 str.ReplaceAll("\xe4", "\xc3\xa4");
325 str.ReplaceAll("\xf6", "\xc3\xb6");
326 str.ReplaceAll("\xfc", "\xc3\xbc");
327 str.ReplaceAll("\xc4", "\xc3\x84");
328 str.ReplaceAll("\xd6", "\xc3\x96");
329 str.ReplaceAll("\xdc", "\xc3\x9c");
330 str.ReplaceAll("\xdf", "\xc3\x9f");
331 str.ReplaceAll("\xe1", "\xc3\xa1");
332 str.ReplaceAll("\xe9", "\xc3\xa9");
333 str.ReplaceAll("\xec", "\xc3\xac");
334 }
335 else
336 {
337 str.ReplaceAll("\xc3\xa4", "\xe4");
338 str.ReplaceAll("\xc3\xb6", "\xf6");
339 str.ReplaceAll("\xc3\xbc", "\xfc");
340 str.ReplaceAll("\xc3\x84", "\xc4");
341 str.ReplaceAll("\xc3\x96", "\xd6");
342 str.ReplaceAll("\xc3\x9c", "\xdc");
343 str.ReplaceAll("\xc3\x9f", "\xdf");
344 str.ReplaceAll("\xc3\xa1", "\xe1");
345 str.ReplaceAll("\xc3\xa9", "\xe9");
346 str.ReplaceAll("\xc3\xac", "\xec");
347 }
348}
349
350
351//---------------------------------------------------------------------------
352//
353// TEnv doesn't have a streamer so we have to make sure that the
354// resources get corretly cloned.
355//
356TObject *MCalendar::Clone(const char *newname) const
357{
358 MCalendar *cal = (MCalendar*)TObject::Clone(newname);
359
360 if (cal->fEnv)
361 delete cal->fEnv;
362 if (cal->fEnvHolidays)
363 delete cal->fEnvHolidays;
364
365 cal->fEnv = (MEnv*)fEnv->Clone();
366 cal->fEnvHolidays = (MEnv*)fEnvHolidays->Clone();
367
368 return cal;
369}
370
371//---------------------------------------------------------------------------
372//
373// return the StringFmt (see MTime::GetStringFmt or strftime)
374// corresponding to the Format fmt (Default="%B", LongMonthName).
375// For more complicated formatings day, hour, minutes and sec can
376// be given.
377//
378TString MCalendar::GetStringFmt(const char *fmt, Int_t day, Int_t h, Int_t m, Int_t s) const
379{
380 MTime t;
381 t.Set(fYear, fMonth, day, h, m, s);
382 return t.GetStringFmt(fmt, GetLanguage());
383}
384
385//---------------------------------------------------------------------------
386//
387// Get the Pave setup for the given condition from the resources
388//
389void MCalendar::GetPave(TPave &pave, Bool_t active, Int_t n)
390{
391 // ----- Default ----
392 TPave def;
393 def.SetName(pave.GetName());
394 def.SetLineStyle(kSolid);
395 def.SetLineColor(kBlack);
396 def.SetLineWidth(0);
397 def.SetFillColor(18);
398 def.SetFillStyle(1001);
399 def.SetCornerRadius(0);
400 def.SetBorderSize(1);
401
402 fEnv->GetAttPave("", def);
403
404 def.Copy(pave);
405
406 pave.SetCornerRadius(def.GetCornerRadius());
407 pave.SetLineColor(active ? kBlack : 15);
408
409 const char *fmt1 = active ? "Active" : "Inactive";
410 const char *fmt2 = active ? "Active.%d" : "Inactive.%d";
411
412 fEnv->GetAttributes( fmt1, &pave);
413 fEnv->GetAttributes(Form(fmt2, n), &pave);
414}
415
416//---------------------------------------------------------------------------
417//
418// Get the Moon setup for the given condition from the resources
419//
420void MCalendar::GetMoon(TAttText &text, TAttFill &fill, Bool_t active, Int_t n)
421{
422 TAttText txt(11, 0, gStyle->GetTextColor(), gStyle->GetTextFont(), 0.13);
423 TAttFill fil(0, 1001);
424
425 fEnv->GetAttText("Moon", txt);
426 fEnv->GetAttFill("Moon", fil);
427
428 txt.Copy(text);
429 fil.Copy(fill);
430
431 text.SetTextColor(active ? kRed : 15);
432 fill.SetFillColor(active ? kBlack : 15);
433
434 const char *fmt1 = active ? "Moon.Active" : "Moon.Inactive";
435 const char *fmt2 = active ? "Moon.Active.%d" : "Moon.Inactive.%d";
436
437 fEnv->GetAttText(fmt1, text);
438 fEnv->GetAttFill(fmt1, fill);
439
440 fEnv->GetAttText(Form(fmt2, n), text);
441 fEnv->GetAttFill(Form(fmt2, n), fill);
442}
443
444//---------------------------------------------------------------------------
445//
446// Get the Text setup for the given condition from the resources
447//
448void MCalendar::GetLatex(TLatex &latex, Bool_t active, Int_t n)
449{
450 const TString fmt = fEnv->GetValue(Form("%s.Format", latex.GetName()), "");
451 latex.SetTitle(fmt);
452
453 TAttText(0, 0, kBlack, gStyle->GetTextFont(), 0.3).Copy(latex);
454 fEnv->GetAttText(latex.GetName(), latex);
455
456 if (!active)
457 latex.SetTextColor(15);
458
459 const char *fmt1 = active ? "%s.Active" : "%s.Inactive";
460 const char *fmt2 = active ? "%s.Active.%d" : "%s.Inactive.%d";
461
462 fEnv->GetAttText(Form(fmt1, latex.GetName()), latex);
463 fEnv->GetAttText(Form(fmt2, latex.GetName(), n), latex);
464}
465
466//---------------------------------------------------------------------------
467//
468// Add a text. The name determins the identifier for which the resources
469// are searched, align the position in the pave (the convention is the same
470// as in TAttText). If a format fmt is given the date corresponding to the
471// pave is converted to a string using MTime::GetStringFmt. See MTime
472// for more details. If the format is empty the Holiday resources are
473// searched for an entry with the name. size defines the default height
474// of the text in units of the pave-height and color the default color in
475// case of active days.
476// eg.
477// Add("Day", 13, "%a", 0.3, kRed);
478// would produce a short WeekDay-name (%a) at the top left edge with
479// with a default height of 0.3*pave-height in Red. You can change
480// the behaviour from the resource file by:
481// Day.{TextAttribute}
482// Day.Active.{TextAttribute}
483// Day.Inctive.{TextAttribute}
484// Day.Active.i.{TextAttribute}
485// Day.Inctive.i.{TextAttribute}
486// for more details about TextAttribute see MEnv::GetAttText and TAttText.
487// i is a placeholder for the WeekDay number (starting with sunday=0)
488//
489void MCalendar::Add(const char *name, Int_t align, const char *fmt, Float_t size, Int_t col)
490{
491 TAttText att(align, 0, col, gStyle->GetTextFont(), size);
492 Add(name, fmt, att);
493}
494
495void MCalendar::Add(const char *name, const char *fmt, const TAttText &att)
496{
497 fEnv->SetAttText(name, att);
498 fEnv->SetValue(Form("%s.Format", name), fmt);
499
500 const TString cont = Form(" %s ", fEnv->GetValue("Contents", ""));
501 const TString form = Form(" %s ", name);
502 if (!cont.Contains(form))
503 fEnv->SetValue("Contents", Form("%s %s", cont.Strip(TString::kBoth).Data(), name));
504}
505
506//---------------------------------------------------------------------------
507//
508// Save the current layout to a resource file. If no filename is given
509// the filename of the current open resource file is used.
510//
511void MCalendar::SaveResourceFile(const char *fname)
512{
513 const TString name = fname ? fname : fEnv->GetName();
514
515 gSystem->Unlink(name);
516
517 MEnv env(name);
518
519 env.SetValue("FirstDay", fFirstDay);
520 env.SetValue("NumBlocks", fNumBlocks);
521
522 env.SetValue("Orientation", fOrientation);
523 env.SetValue("Rotation", fRotation);
524
525 env.SetValue("Moon.Graf.Align", fMoonAlignGraf);
526 env.SetValue("Moon.Text.Align", fMoonAlignText);
527 env.SetValue("Moon.Text.Type", fMoonTextType);
528 env.SetValue("Moon.Text.Continous", fMoonTextCont);
529 env.SetValue("Moon.Graf.Radius", fMoonRadius);
530
531 env.SetValue("MarginX", fMarginX);
532 env.SetValue("MarginY", fMarginY);
533 env.SetValue("CellSpace", fCellSpace);
534 env.SetValue("BlockSpace", fBlockSpace);
535
536 env.SetValue("Language", GetLanguage());
537
538 env.SetValue("HolidayFile", fEnvHolidays->GetName());
539
540 env.AddEnv(*fEnv);
541 env.Save();
542}
543
544//---------------------------------------------------------------------------
545//
546// Save the current holidays to a resource file. If no filename is given
547// the filename of the current open holiday file is used.
548//
549void MCalendar::SaveHolidayFile(const char *fname)
550{
551 const TString name = fname ? fname : fEnvHolidays->GetName();
552
553 gSystem->Unlink(name);
554
555 MEnv env(name);
556 env.AddEnv(*fEnvHolidays);
557 env.Save();
558}
559
560//---------------------------------------------------------------------------
561//
562// The Layout will be resetted and than restored from the specified
563// resource file. If no filename is given the filename of the current
564// open resource file is used.
565//
566void MCalendar::ReadResourceFile(const char *fname)
567{
568 const TString name = fname ? fname : fEnv->GetName();
569
570 ResetLayout(2);
571
572 delete fEnv;
573 fEnv = new MEnv(name);
574
575 fFirstDay = fEnv->GetValue("FirstDay", fFirstDay);
576 fNumBlocks = fEnv->GetValue("NumBlocks", fNumBlocks);
577
578 fOrientation = fEnv->GetValue("Orientation", fOrientation);
579 fRotation = fEnv->GetValue("Rotation", fOrientation);
580
581 fMoonAlignGraf = fEnv->GetValue("Moon.Graf.Align", fMoonAlignGraf);
582 fMoonAlignText = fEnv->GetValue("Moon.Text.Align", fMoonAlignText);
583 fMoonTextType = fEnv->GetValue("Moon.Text.Type", fMoonTextType);
584 fMoonTextCont = fEnv->GetValue("Moon.Text.Continous", fMoonTextCont);
585 fMoonRadius = fEnv->GetValue("Moon.Graf.Radius", fMoonRadius);
586
587 fMarginX = fEnv->GetValue("MarginX", fMarginX);
588 fMarginY = fEnv->GetValue("MarginY", fMarginY);
589 fCellSpace = fEnv->GetValue("CellSpace", fCellSpace);
590 fBlockSpace = fEnv->GetValue("BlockSpace", fBlockSpace);
591
592 SetLocal(fEnv->GetValue("Language", ""));
593 ReadHolidayFile();
594}
595
596//---------------------------------------------------------------------------
597//
598// The Holidays will be resetted and than restored from the specified
599// holiday file. If no filename is given the filename of the current
600// open holiday file is used.
601//
602void MCalendar::ReadHolidayFile(const char *fname)
603{
604 const TString name = fname ? fname : fEnvHolidays->GetName();
605
606 if (fEnvHolidays)
607 delete fEnvHolidays;
608 fEnvHolidays = new MEnv(name);
609}
610
611//---------------------------------------------------------------------------
612//
613// Reset the layout (remove everything)
614//
615// num is the number of default blocks (corresponding to NumBlocks).
616// A value smaller or equal 0 will leave the number of block unchanged
617// (which is the default)
618//
619void MCalendar::ResetLayout(Int_t num)
620{
621 fOrientation = kFALSE;
622 fRotation = kFALSE;
623
624 fFirstDay = 1;
625
626 if (num>0)
627 fNumBlocks = num;
628
629 fMoonAlignGraf = 0;
630 fMoonAlignText = 0;
631 fMoonTextType = 0;
632 fMoonTextCont = kFALSE;
633 fMoonRadius = 0.08;
634
635 fMarginX = 0.05;
636 fMarginY = 0.05;
637
638 fCellSpace = 0.01;
639 fBlockSpace = 0.1;
640
641 if (fEnv)
642 delete fEnv;
643
644 fEnv = new MEnv("/dev/null");
645}
646
647//---------------------------------------------------------------------------
648//
649// Reset the holidays (remove everything)
650//
651void MCalendar::ResetHolidays()
652{
653 if (fEnvHolidays)
654 delete fEnvHolidays;
655
656 fEnvHolidays = new MEnv("/dev/null");
657}
658
659//---------------------------------------------------------------------------
660//
661// Set the holidays to the default holidays
662//
663void MCalendar::SetDefaultHolidays()
664{
665 ResetHolidays();
666
667 fEnvHolidays->SetValue("Holiday.0", "Easter");
668 fEnvHolidays->SetValue("Holiday.01/01", "New Year");
669 fEnvHolidays->SetValue("Holiday.12/25", "Christmas");
670 fEnvHolidays->SetValue("Holiday.12/26", "Christmas");
671}
672
673//---------------------------------------------------------------------------
674//
675// Set the layout to the default layout
676//
677// num is the number of default blocks (corresponding to NumBlocks).
678// A value smaller or equal 0 will leave the number of block unchanged
679// (which is the default)
680//
681void MCalendar::SetDefaultLayout(Int_t num)
682{
683 ResetLayout(num);
684
685 fMoonAlignGraf = 11;
686 fMoonAlignText = 11;
687
688 fEnv->SetValue("Contents", "Day Date Week Holiday Birthday");
689
690 fEnv->SetValue("Day.TextAlign", "top left");
691 fEnv->SetValue("Day.Format", "%e");
692
693 fEnv->SetValue("Date.TextAlign", "bottom right");
694 fEnv->SetValue("Date.Format", "%a");
695
696 fEnv->SetValue("Week.TextAlign", "top right");
697 fEnv->SetValue("Week.Format", "KW%V");
698 fEnv->SetValue("Week.TextSize", 0.1);
699 fEnv->SetValue("Week.Restriction", 1);
700 fEnv->SetValue("Week.Active.TextColor", "Grey8");
701
702 fEnv->SetValue("Holiday.TextAlign", "center");
703 fEnv->SetValue("Holiday.TextSize", 0.13);
704 fEnv->SetValue("Holiday.TextColor", kBlue);
705
706 fEnv->SetValue("Birthday.TextAlign", "center");
707 fEnv->SetValue("Birthday.TextSize", 0.13);
708 fEnv->SetValue("Birthday.TextColor", kBlue);
709
710 // fEnv->SetValue("Easter.TextAlign", "center");
711 // fEnv->SetValue("Easter.TextSize", 0.13);
712 // fEnv->SetValue("Easter.TextColor", kBlue);
713
714 fEnv->SetValue("Date.Active.0.TextColor", kRed);
715
716 fEnv->SetValue("Date.Active.TextFont", 22);
717 fEnv->SetValue("Day.Active.TextFont", 22);
718 fEnv->SetValue("Date.Inactive.TextFont", 132);
719 fEnv->SetValue("Day.Inactive.TextFont", 132);
720
721 // fEnv->SetValue("Date.Inactive.LineStyle", kDashed);
722 // fEnv->SetValue("Date.Inactive.FillColor", kWhite);
723}
724
725//---------------------------------------------------------------------------
726//
727// Create a calendar piece for the given year and month. If a filename
728// is given the corresponding resource file is read. If no month and/or
729// no year is given the current date is used instead.
730//
731MCalendar::MCalendar(UShort_t y, Byte_t m, const char *fname)
732 : fYear(y==0?MTime(-1).Year():y), fMonth(m==0?MTime(-1).Month():m)
733{
734 fEnv =0;
735 fEnvHolidays=0;
736
737 //fUpdate = kFALSE;
738
739 SetDefaultLayout(2);
740 SetDefaultHolidays();
741
742 if (fname)
743 ReadResourceFile(fname);
744}
745
746//---------------------------------------------------------------------------
747//
748// Delete the two resource files
749//
750MCalendar::~MCalendar()
751{
752 delete fEnv;
753 delete fEnvHolidays;
754}
755
756//---------------------------------------------------------------------------
757//
758// Take the pave edges and the margin and calculate the new x and y
759// coordinates from it for the given alignment (as in TAttText),
760//
761TArrayD MCalendar::ConvertAlign(Int_t align, Double_t x[2], Double_t y[2], Double_t m[2]) const
762{
763 align = Rotate(align);
764
765 TArrayD p(2);
766 switch (align/10)
767 {
768 case 1: p[0] = x[0]+m[0]; break;
769 case 2: p[0] = (x[0]+x[1])/2; break;
770 case 3: p[0] = x[1]-m[0]; break;
771 }
772 switch (align%10)
773 {
774 case 1: p[1] = y[0]+m[1]; break;
775 case 2: p[1] = (y[0]+y[1])/2; break;
776 case 3: p[1] = y[1]-m[1]; break;
777 }
778 return p;
779}
780
781//---------------------------------------------------------------------------
782//
783// Rotate the aligment if the orientation is changed.
784//
785Int_t MCalendar::Rotate(Int_t align, Bool_t fwd) const
786{
787 if (fOrientation==fRotation)
788 return align;
789
790 static const Int_t b[4] = { 11, 31, 33, 13 };
791 static const Int_t a[4] = { 11, 13, 33, 31 };
792
793 const Int_t *c = fwd ? a :b;
794
795 for (int i=0; i<4; i++)
796 if (align==c[i])
797 return c[(i+1)%4];
798
799 return align;
800}
801
802//---------------------------------------------------------------------------
803//
804// Paint the text str at the position indirectly given by alignement, x and
805// y (see ConvertAlign for more details) with the attributes from TAttText.
806//
807void MCalendar::PaintLatex(TAttText &att, Int_t align, Double_t x[2], Double_t y[2], Double_t ratio[2], /*Double_t height,*/ TString str)
808{
809 TLatex tex;
810 att.Copy(tex);
811
812 Double_t m[2] = {
813 fMarginX*ratio[0],
814 fMarginY*ratio[1]
815 };
816
817 const TArrayD p = ConvertAlign(align, x, y, m);
818 /*
819 tex.SetText(p[0], p[1], str);
820 tex.SetTextAngle(0);
821 tex.SetTextSize(att.GetTextSize()*height);
822
823 while (1)
824 {
825 Double_t w = tex.GetXsize();
826 Double_t h = tex.GetYsize();
827 if (w<width-2*m[0] && h<height-2*m[1])
828 break;
829
830 tex.SetTextSize(tex.GetTextSize()*0.99);
831 }
832
833 tex.Paint();
834 */
835
836 const Double_t scale = fOrientation ? x[1]-x[0] : y[1]-y[0];
837 const Double_t phi = fOrientation!=fRotation ? -90 : 0;
838
839 Convert2Latex(str);
840
841 tex.SetTextAlign(align);
842 tex.PaintLatex(p[0], p[1], phi, att.GetTextSize()*scale, str);
843}
844
845//---------------------------------------------------------------------------
846//
847// Paint a clock as a symbol for summer-/wintertime
848//
849void MCalendar::PaintClock(Double_t x[2], Double_t y[2], Double_t r[2], Int_t fill, char dir)
850{
851 Double_t k[2] = { (x[0]+x[1])/2, (y[0]+y[1])/2 };
852
853 TEllipse e(k[0], k[1], r[0]*2.5, r[1]*2.5, 30, 360, 0);
854 e.SetLineColor(kBlack);
855 e.SetLineStyle(kSolid);
856 e.SetFillColor(fill);
857 e.Paint();
858
859 TMarker m;
860 m.SetMarkerStyle(kFullDotSmall);
861 for (int i=2; i<12; i++)
862 m.PaintMarker(k[0]+r[0]*2*cos(TMath::TwoPi()*i/12),
863 k[1]+r[1]*2*sin(TMath::TwoPi()*i/12));
864
865 TArrow a(k[0]+r[0]*3, k[1], k[0]+r[0]*2.7, k[1]+r[1]*1.5, r[1]/2);
866 a.Paint(dir=='-'?"->":"<-");
867}
868
869//---------------------------------------------------------------------------
870//
871// Check the holiday resources for a holiday matching the the resource name:
872// name.mm/dd
873// while name is the name of the TObject, mm and dd are month and day
874// of the MTime.
875//
876TString MCalendar::GetHoliday(const TObject &o, const MTime &tm)
877{
878 const Int_t easter = (Int_t)MTime::GetEaster(fYear).GetMjd();
879
880 const TString fmt = o.GetTitle();
881
882 if (!fmt.IsNull())
883 return tm.GetStringFmt(fmt, GetLanguage());
884
885 TString env(o.GetName());
886
887 const TString post1 = Form(".%d", (Int_t)tm.GetMjd()-easter);
888 const TString post2 = Form(".%02d/%02d", tm.Month(), tm.Day());
889
890 TString rc;
891 for (int i=0; i<7; i++)
892 {
893 MTime tx(tm.GetMjd()+i);
894 const TString post3 = Form(".%02d/%02d-%d", tx.Month(), tx.Day(), (7-tm.WeekDay())%7);
895 rc = fEnvHolidays->GetValue(env+post3, rc);
896 }
897
898 rc = fEnvHolidays->GetValue(env+post1, rc);
899 rc = fEnvHolidays->GetValue(env+post2, rc);
900/*
901 if (fLanguage=="de_DE")
902 {
903 MTime t;
904 t.Set(fYear, 5, 14);
905 t.SetMjd(t.GetMjd()-t.WeekDay());
906
907 if ((Int_t)t.GetMjd() == easter + 49)
908 t.SetMjd(t.GetMjd()-7);
909
910 if ((Int_t)tm.GetMjd()==(Int_t)t.GetMjd())
911 return "Muttertag";
912 }
913
914 */
915 return rc;
916}
917
918void MCalendar::Paint(Option_t *o)
919{
920 /*
921 if (fUpdate)
922 {
923 fEnv->SetAttLine(fActive?"Date.Active":"Date.Inactive", *this);
924 fUpdate = kFALSE;
925 }
926 */
927
928 // How should this be done?
929 //fOrientation = gPad->PixeltoX(1)>-gPad->PixeltoY(1);
930
931 MTime t;
932 t.Set(fYear, fMonth, 1);
933
934 Int_t n = t.WeekDay();
935
936 Int_t diff = (7-fFirstDay)%7;
937 n += diff;
938 n %= 7;
939
940 t.SetMjd(t.GetMjd()-n);
941 n = 0;
942
943 for (; n<99; n++)
944 {
945 const MTime tm(t.GetMjd()+n);
946
947 const Bool_t active = tm.Month()==(UInt_t)fMonth;
948
949 Double_t x[2], y[2], ratio[2];
950 const Bool_t rc = GetBox(n, x, y, ratio);
951
952 if (!active && rc)
953 break;
954
955 // Get part of string for this day
956 const Int_t day = (n+7-diff)%7;
957
958 TPave pave;
959 pave.SetName("Date");
960 GetPave(pave, active, day);
961
962 // ---------- Paint Border and fill area ----------
963 pave.SetX1NDC(x[0]);
964 pave.SetY1NDC(y[0]);
965 pave.SetX2NDC(x[1]);
966 pave.SetY2NDC(y[1]);
967 pave.Paint(pave.GetOption());
968
969 Double_t r[2] = {
970 fMoonRadius*ratio[0],
971 fMoonRadius*ratio[1]
972 };
973
974 // ---------- Paint Text ----------
975 const TString contents = fEnv->GetValue("Contents", "");
976 TObjArray *arr = contents.Tokenize(" ");
977
978 TIter Next(arr);
979 TObject *o=0;
980 while ((o=Next()))
981 {
982 TLatex latex;
983 latex.SetName(o->GetName());
984
985 const TString res = fEnv->GetValue(Form("%s.Restriction", o->GetName()), "0123456");
986 if (res.First('0'+tm.WeekDay())<0)
987 continue;
988
989 GetLatex(latex, active, day);
990
991 const TString text = GetHoliday(latex, tm);
992
993 if (text=="T+" || text=="T-")
994 {
995 PaintClock(x, y, r, pave.GetFillColor(), text[1]);
996 continue;
997 }
998
999 if (!text.IsNull())
1000 PaintLatex(latex, latex.GetTextAlign(), x, y, ratio, text);
1001 }
1002
1003 delete arr;
1004
1005 // ---------- Paint Moon Phase -----------
1006 //Double_t r[2] = {
1007 // fMoonRadius*ratio[0],
1008 // fMoonRadius*ratio[1]
1009 //};
1010 Double_t m[2] = {
1011 fMarginX*ratio[0] + r[0],
1012 fMarginY*ratio[1] + r[1]
1013 };
1014
1015 TAttText text;
1016 TAttFill fill;
1017 GetMoon(text, fill, active, day);
1018
1019 // Shift if grafic and moon should be displayed at the same
1020 // location, the text is a discrete number and it is
1021 // switched to continous.
1022 const Bool_t rot = fOrientation!=fRotation;
1023 const Float_t phi = rot ? -90 : 0;
1024 const Int_t dx = rot;
1025 const Int_t dy = (rot+1)%2;
1026 const Bool_t cont = fMoonTextType==0 || fMoonTextCont;
1027 if (fMoonAlignGraf)
1028 {
1029 TArrayD p = ConvertAlign(fMoonAlignGraf, x, y, m);
1030
1031 if (fMoonAlignGraf==fMoonAlignText && cont && fMoonAlignGraf==22)
1032 p[dy] += rot ? -m[dy]/2 : m[dy]/2;
1033
1034 TEllipse e(p[0], p[1], r[0], r[1], -90+phi, 90+phi, 0);
1035 fill.Copy(e);
1036 e.SetLineStyle(0);
1037 e.Paint();
1038 if (tm.GetMoonPhase()<0.5)
1039 {
1040 e.SetLineStyle(kSolid);
1041 e.SetLineColor(pave.GetFillColor());
1042 e.SetFillColor(pave.GetFillColor());
1043 }
1044 else
1045 {
1046 e.SetPhimin(90+phi); // bug in PaintEllipse!
1047 e.SetPhimax(270+phi); // bug in PaintEllipse!
1048 }
1049 const Double_t R = tm.GetMoonPhase()<0.5 ? 1-tm.GetMoonPhase() : tm.GetMoonPhase();
1050 const Double_t r0 = 1.0-TMath::Sqrt(2.0-2.0*R);
1051 if (rot)
1052 e.SetR2(r[1]*r0); // bug in PaintEllipse!
1053 else
1054 e.SetR1(r[0]*r0); // bug in PaintEllipse!
1055 e.Paint();
1056 }
1057
1058 if (fMoonAlignGraf==fMoonAlignText && !cont && tm.GetMoonPhase()>0.004)
1059 continue;
1060
1061 // ---------- Paint Moon Text -----------
1062 if (fMoonAlignText)
1063 {
1064 if (fMoonAlignGraf!=fMoonAlignText || (fMoonAlignGraf==fMoonAlignText && !cont))
1065 m[dx] -= r[dx];
1066
1067 TArrayD p = ConvertAlign(fMoonAlignText, x, y, m);
1068
1069 if (fMoonAlignGraf==fMoonAlignText && cont)
1070 {
1071 if (rot)
1072 {
1073 m[dx] = -m[dx];
1074 m[dy] = -m[dy];
1075 }
1076
1077 switch (fMoonAlignGraf/10)
1078 {
1079 case 1: p[dx] += m[dx]; break;
1080 case 2: p[dy] += fMoonAlignGraf%10==1 ? m[dy]*1.25 : -m[dy]*1.25; break;
1081 case 3: p[dx] -= m[dx]; break;
1082 }
1083 }
1084
1085 TString num;
1086 switch (fMoonTextType)
1087 {
1088 case 0:// kMoonPhase:
1089 num = Form("%d%%", TMath::Nint(tm.GetMoonPhase()*100));
1090 break;
1091 case 1://kMoonPeriod:
1092 num = Form("%d", (Int_t)tm.GetMoonPeriod());
1093 break;
1094 case 2://kMagicPeriod:
1095 num = Form("%d", tm.GetMagicPeriod());
1096 break;
1097 }
1098
1099 const Double_t scale = fOrientation ? x[1]-x[0] : y[1]-y[0];
1100
1101 TLatex tex;
1102 text.Copy(tex);
1103 tex.SetTextAlign(10*(fMoonAlignText/10)+2); // 12
1104 tex.PaintLatex(p[0], p[1], phi, text.GetTextSize()*scale, num);
1105 }
1106 }
1107
1108 /*
1109 TASImage img;
1110 img.FromPad(gPad);
1111 img.Flip(90);
1112 img.Paint();
1113 */
1114}
1115
1116Bool_t MCalendar::GetBox(Int_t n, Double_t x[2], Double_t y[2], Double_t *ratio)
1117{
1118 //const Int_t maxrows = 6; //28/(7*fNumBlocks) + 1;
1119 const Float_t addrows = 0;
1120
1121 Int_t maxrows;
1122 switch(fNumBlocks)
1123 {
1124 case 0:
1125 case 1: maxrows=6; break;
1126 case 2: maxrows=3; break;
1127 case 3: maxrows=2; break;
1128 case 4: maxrows=2; break;
1129 default: maxrows=1; break;
1130 }
1131
1132 const Float_t ratio0 = -gPad->PixeltoX(1)/gPad->PixeltoY(1);
1133
1134 // Cellspace
1135 const Float_t celly = fCellSpace;
1136 const Float_t cellx = fOrientation ? fCellSpace/ratio0 : fCellSpace*ratio0;
1137
1138 // Blockspace
1139 //Float_t blockspacey = fBlockSpace;
1140 const Float_t blockx = fOrientation ? fBlockSpace/ratio0 : fBlockSpace*ratio0;
1141
1142 const Float_t w = (0.99-cellx*(7*fNumBlocks-1)-(fNumBlocks-1)*blockx)/(fNumBlocks*7);
1143 const Float_t h = (0.99-celly*(maxrows-1)/*-blockspacey*/)/(maxrows+addrows);
1144
1145
1146 const Int_t ix = n%(7*fNumBlocks);
1147 const Int_t iy = n/(7*fNumBlocks);
1148
1149 const Int_t col = ix/7;
1150
1151 const Double_t p0 = 0.005 - col*(cellx - blockx);
1152
1153 TArrayD a(2), b(2);
1154
1155 a[0] = p0 + ix*(cellx + w);
1156 a[1] = p0 + ix*(cellx + w) + w;
1157
1158 b[0] = 0.995 - iy*(celly + h) - h;
1159 b[1] = 0.995 - iy*(celly + h);
1160
1161 if (ratio)
1162 {
1163 ratio[0] = ratio0>1 ? h : h*ratio0;
1164 ratio[1] = ratio0>1 ? h/ratio0 : h;
1165 }
1166
1167 if (fOrientation)
1168 {
1169 x[0] = b[0];
1170 x[1] = b[1];
1171 y[0] = a[0];
1172 y[1] = a[1];
1173 }
1174 else
1175 {
1176 x[0] = a[0];
1177 x[1] = a[1];
1178 y[0] = b[0];
1179 y[1] = b[1];
1180 }
1181
1182 if (fOrientation)
1183 {
1184 TArrayD d(2,y);
1185 y[0] = 1-d[1];
1186 y[1] = 1-d[0];
1187 }
1188
1189 if (fRotation)
1190 {
1191 TArrayD d(2,x);
1192 x[0] = 1-d[1];
1193 x[1] = 1-d[0];
1194 }
1195
1196 return ix==0 && iy>0;
1197}
1198
1199//---------------------------------------------------------------------------
1200//
1201// Determine the absolute number of the day from the event (mouse)
1202// position.
1203//
1204Int_t MCalendar::GetN(Double_t x[2], Double_t y[2])
1205{
1206 if (!gPad)
1207 return 0;
1208
1209 const Double_t px = gPad->AbsPixeltoX(gPad->GetEventX());
1210 const Double_t py = gPad->AbsPixeltoY(gPad->GetEventY());
1211
1212 int n=0;
1213 for (n=0; n<99; n++)
1214 {
1215 GetBox(n, x, y);
1216 if (x[0]<px && px<x[1] && y[0]<py && py<y[1])
1217 break;
1218 }
1219
1220 return n==99 ? -1 : n;
1221}
1222
1223//---------------------------------------------------------------------------
1224//
1225// Determine the date of the day from the event (mouse) position.
1226//
1227MTime MCalendar::GetDate()
1228{
1229 const Int_t n = GetN();
1230 if (n<0)
1231 return MTime();
1232
1233 MTime t;
1234 t.Set(fYear, fMonth, 1);
1235
1236 Int_t k = t.WeekDay();
1237
1238 k += (7-fFirstDay)%7;
1239 k %= 7;
1240
1241 return MTime(t.GetMjd()-k+n);
1242}
1243
1244//---------------------------------------------------------------------------
1245//
1246// Determin the alignment of the event (mouse) position.
1247//
1248Int_t MCalendar::GetAlign()
1249{
1250 Double_t x[2], y[2];
1251 if (GetN(x, y)<0)
1252 return 0;
1253
1254 const Double_t px = gPad->AbsPixeltoX(gPad->GetEventX());
1255 const Double_t py = gPad->AbsPixeltoY(gPad->GetEventY());
1256
1257 const Int_t alignx = (Int_t)(3*(px-x[0])/(x[1]-x[0]))+1;
1258 const Int_t aligny = (Int_t)(3*(py-y[0])/(y[1]-y[0]))+1;
1259
1260 return Derotate(alignx*10+aligny);
1261}
1262
1263//---------------------------------------------------------------------------
1264//
1265// Remove the text entry at the event (mouse) position.
1266//
1267void MCalendar::Remove(Int_t align)
1268{
1269 const TString cont = fEnv->GetValue("Contents", "");
1270 TObjArray *arr = cont.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) const
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.