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

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