]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/demos/src/com/ibm/icu/dev/demo/holiday/HolidayCalendarDemo.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / demos / src / com / ibm / icu / dev / demo / holiday / HolidayCalendarDemo.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 1996-2007, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 \r
8 package com.ibm.icu.dev.demo.holiday;\r
9 \r
10 import java.awt.BorderLayout;\r
11 import java.awt.Button;\r
12 import java.awt.Canvas;\r
13 import java.awt.Choice;\r
14 import java.awt.Color;\r
15 import java.awt.Component;\r
16 import java.awt.Container;\r
17 import java.awt.Dimension;\r
18 import java.awt.Font;\r
19 import java.awt.FontMetrics;\r
20 import java.awt.Frame;\r
21 import java.awt.Graphics;\r
22 import java.awt.GridBagConstraints;\r
23 import java.awt.GridBagLayout;\r
24 import java.awt.Label;\r
25 import java.awt.Panel;\r
26 import java.awt.Point;\r
27 import java.awt.event.ActionEvent;\r
28 import java.awt.event.ActionListener;\r
29 import java.awt.event.ItemEvent;\r
30 import java.awt.event.ItemListener;\r
31 import java.awt.event.WindowEvent;\r
32 import java.text.DateFormatSymbols;\r
33 import java.util.Date;\r
34 import java.util.Locale;\r
35 import java.util.Vector;\r
36 \r
37 import com.ibm.icu.dev.demo.impl.DemoApplet;\r
38 import com.ibm.icu.dev.demo.impl.DemoTextBox;\r
39 import com.ibm.icu.dev.demo.impl.DemoUtility;\r
40 import com.ibm.icu.text.SimpleDateFormat;\r
41 import com.ibm.icu.util.Calendar;\r
42 import com.ibm.icu.util.Holiday;\r
43 import com.ibm.icu.util.SimpleTimeZone;\r
44 \r
45 /**\r
46  * CalendarDemo demonstrates how Calendar works.\r
47  */\r
48 public class HolidayCalendarDemo extends DemoApplet \r
49 {\r
50     /**\r
51      * For serialization\r
52      */\r
53     private static final long serialVersionUID = 4546085430817359372L;\r
54 \r
55     /**\r
56      * The main function which defines the behavior of the CalendarDemo\r
57      * applet when an applet is started.\r
58      */\r
59     public static void main(String argv[]) {\r
60 \r
61         new HolidayCalendarDemo().showDemo();\r
62     }\r
63 \r
64     /* This creates a CalendarFrame for the demo applet. */\r
65     public Frame createDemoFrame(DemoApplet applet) {\r
66         return new CalendarFrame(applet);\r
67     }\r
68 \r
69     /**\r
70     * A Frame is a top-level window with a title. The default layout for a frame\r
71     * is BorderLayout.  The CalendarFrame class defines the window layout of\r
72     * CalendarDemo.\r
73     */\r
74     private static class CalendarFrame extends Frame implements ActionListener,\r
75                                                                 ItemListener\r
76     {\r
77         /**\r
78          * For serialization\r
79          */\r
80         private static final long serialVersionUID = -7023296782393042761L;\r
81 \r
82         private static final boolean DEBUG = false;\r
83 \r
84         //private Locale curLocale = Locale.US; // unused\r
85 \r
86         private DemoApplet applet;\r
87 \r
88         private static final Locale[] calendars = {\r
89             //new Locale("de","AT"),\r
90             Locale.CANADA,\r
91             Locale.CANADA_FRENCH,\r
92             Locale.FRANCE,\r
93             Locale.GERMANY,\r
94             new Locale("iw","IL"),\r
95             new Locale("el","GR"),\r
96             //new Locale("es","MX"),\r
97             Locale.UK,\r
98             Locale.US,\r
99         };\r
100         private static final Locale[] displays = {\r
101             Locale.CANADA,\r
102             Locale.UK,\r
103             Locale.US,\r
104             Locale.FRANCE,\r
105             Locale.CANADA_FRENCH,\r
106             //new Locale("de","AT"),\r
107             Locale.GERMAN,\r
108             new Locale("el","GR"),\r
109             //new Locale("iw","IL"),\r
110             new Locale("es","MX"),\r
111         };\r
112 \r
113         /**\r
114         * Constructs a new CalendarFrame that is initially invisible.\r
115         */\r
116         public CalendarFrame(DemoApplet applet)\r
117         {\r
118             super("Calendar Demo");\r
119             this.applet = applet;\r
120             init();\r
121             start();\r
122             enableEvents(WindowEvent.WINDOW_CLOSING);\r
123         }\r
124 \r
125         /**\r
126         * Initializes the applet. You never need to call this directly, it\r
127         * is called automatically by the system once the applet is created.\r
128         */\r
129         public void init()\r
130         {\r
131             // Get G7 locales only for demo purpose. To get all the locales\r
132             // supported, switch to calling Calendar.getAvailableLocales().\r
133             // commented\r
134             locales = displays;\r
135 \r
136             buildGUI();\r
137         }\r
138 \r
139         //------------------------------------------------------------\r
140         // package private\r
141         //------------------------------------------------------------\r
142         void addWithFont(Container container, Component foo, Font font) {\r
143             if (font != null)\r
144                 foo.setFont(font);\r
145             container.add(foo);\r
146         }\r
147 \r
148         /**\r
149         * Called to start the applet. You never need to call this method\r
150         * directly, it is called when the applet's document is visited.\r
151         */\r
152         public void start()\r
153         {\r
154             // do nothing\r
155         }\r
156 \r
157         private Choice          localeMenu;\r
158         private Choice          displayMenu;\r
159         private Locale[]        locales;\r
160 \r
161         private Label           monthLabel;\r
162         private Button          prevYear;\r
163         private Button          prevMonth;\r
164         private Button          gotoToday;\r
165         private Button          nextMonth;\r
166         private Button          nextYear;\r
167         private CalendarPanel   calendarPanel;\r
168 \r
169         private static final Locale kFirstLocale = Locale.US;\r
170 \r
171         private static void add(Container container, Component component,\r
172                                 GridBagLayout g, GridBagConstraints c)\r
173         {\r
174             g.setConstraints(component, c);\r
175             container.add(component);\r
176         }\r
177 \r
178         public void buildGUI()\r
179         {\r
180             setBackground(DemoUtility.bgColor);\r
181             setLayout(new BorderLayout(10,10));\r
182 \r
183             // Label for the demo's title\r
184             Label titleLabel = new Label("Calendar Demo", Label.CENTER);\r
185             titleLabel.setFont(DemoUtility.titleFont);\r
186 \r
187             // Label for the current month name\r
188             monthLabel = new Label("", Label.LEFT);\r
189             monthLabel.setFont(new Font(DemoUtility.titleFont.getName(),\r
190                                         DemoUtility.titleFont.getStyle(),\r
191                                         (DemoUtility.titleFont.getSize() * 3)/2));\r
192 \r
193             // Make the locale popup menus\r
194             localeMenu= new Choice();\r
195             localeMenu.addItemListener(this);\r
196             int selectMe = 0;\r
197             \r
198             for (int i = 0; i < calendars.length; i++) {\r
199                 if (i > 0 &&\r
200                         calendars[i].getCountry().equals(calendars[i-1].getCountry()) ||\r
201                     i < calendars.length - 1 &&\r
202                         calendars[i].getCountry().equals(calendars[i+1].getCountry()))\r
203                 {\r
204                     localeMenu.addItem(calendars[i].getDisplayCountry() + " (" +\r
205                                     calendars[i].getDisplayLanguage() + ")");\r
206                 } else {\r
207                     localeMenu.addItem( calendars[i].getDisplayCountry() );\r
208                 }\r
209                 \r
210                 if (calendars[i].equals(kFirstLocale)) {\r
211                     selectMe = i;\r
212                 }\r
213             }\r
214             \r
215             localeMenu.setBackground(DemoUtility.choiceColor);\r
216             localeMenu.select(selectMe);\r
217 \r
218             displayMenu = new Choice();\r
219             displayMenu.addItemListener(this);\r
220             \r
221             selectMe = 0;\r
222             for (int i = 0; i < locales.length; i++) {\r
223                 if (i > 0 &&\r
224                         locales[i].getLanguage().equals(locales[i-1].getLanguage()) ||\r
225                     i < locales.length - 1 &&\r
226                         locales[i].getLanguage().equals(locales[i+1].getLanguage()))\r
227                 {\r
228                     displayMenu.addItem( locales[i].getDisplayName() );\r
229                 } else {\r
230                     displayMenu.addItem( locales[i].getDisplayLanguage());\r
231                 }\r
232                 \r
233                 if (locales[i].equals(kFirstLocale)) {\r
234                     selectMe = i;\r
235                 }\r
236             }\r
237             \r
238             displayMenu.setBackground(DemoUtility.choiceColor);\r
239             displayMenu.select(selectMe);\r
240 \r
241             // Make all the next/previous/today buttons\r
242             prevYear = new Button("<<");\r
243             prevYear.addActionListener(this);\r
244             prevMonth = new Button("<");\r
245             prevMonth.addActionListener(this);\r
246             gotoToday = new Button("Today");\r
247             gotoToday.addActionListener(this);\r
248             nextMonth = new Button(">");\r
249             nextMonth.addActionListener(this);\r
250             nextYear = new Button(">>");\r
251             nextYear.addActionListener(this);\r
252 \r
253             // The month name and the control buttons are bunched together\r
254             Panel monthPanel = new Panel();\r
255             {\r
256                 GridBagLayout g = new GridBagLayout();\r
257                 GridBagConstraints c = new GridBagConstraints();\r
258                 monthPanel.setLayout(g);\r
259 \r
260                 c.weightx = 1;\r
261                 c.weighty = 1;\r
262 \r
263                 c.gridwidth = 1;\r
264                 c.fill = GridBagConstraints.HORIZONTAL;\r
265                 c.gridwidth = GridBagConstraints.REMAINDER;\r
266                 add(monthPanel, monthLabel, g, c);\r
267 \r
268                 c.gridwidth = 1;\r
269                 add(monthPanel, prevYear, g, c);\r
270                 add(monthPanel, prevMonth, g, c);\r
271                 add(monthPanel, gotoToday, g, c);\r
272                 add(monthPanel, nextMonth, g, c);\r
273                 c.gridwidth = GridBagConstraints.REMAINDER;\r
274                 add(monthPanel, nextYear, g, c);\r
275             }\r
276 \r
277             // Stick the menu and buttons in a little "control panel"\r
278             Panel menuPanel = new Panel();\r
279             {\r
280                 GridBagLayout g = new GridBagLayout();\r
281                 GridBagConstraints c = new GridBagConstraints();\r
282                 menuPanel.setLayout(g);\r
283 \r
284                 c.weightx = 1;\r
285                 c.weighty = 1;\r
286 \r
287                 c.fill = GridBagConstraints.HORIZONTAL;\r
288 \r
289                 c.gridwidth = GridBagConstraints.RELATIVE;\r
290                 Label l1 = new Label("Holidays");\r
291                 l1.setFont(DemoUtility.labelFont);\r
292                 add(menuPanel, l1, g, c);\r
293 \r
294                 c.gridwidth = GridBagConstraints.REMAINDER;\r
295                 add(menuPanel, localeMenu, g, c);\r
296 \r
297                 c.gridwidth = GridBagConstraints.RELATIVE;\r
298                 Label l2 = new Label("Display:");\r
299                 l2.setFont(DemoUtility.labelFont);\r
300                 add(menuPanel, l2, g, c);\r
301 \r
302                 c.gridwidth = GridBagConstraints.REMAINDER;\r
303                 add(menuPanel, displayMenu, g, c);\r
304             }\r
305 \r
306             // The title, buttons, etc. go in a panel at the top of the window\r
307             Panel topPanel = new Panel();\r
308             {\r
309                 topPanel.setLayout(new BorderLayout());\r
310 \r
311                 //topPanel.add("North", titleLabel);\r
312                 topPanel.add("Center", monthPanel);\r
313                 topPanel.add("East", menuPanel);\r
314             }\r
315             add("North", topPanel);\r
316 \r
317             // The copyright notice goes at the bottom of the window\r
318             Label copyright = new Label(DemoUtility.copyright1, Label.LEFT);\r
319             copyright.setFont(DemoUtility.creditFont);\r
320             add("South", copyright);\r
321 \r
322             // Now create the big calendar panel and stick it in the middle\r
323             calendarPanel = new CalendarPanel( kFirstLocale );\r
324             add("Center", calendarPanel);\r
325 \r
326             updateMonthName();\r
327         }\r
328 \r
329         private void updateMonthName()\r
330         {\r
331             SimpleDateFormat f = new SimpleDateFormat("MMMM yyyyy",\r
332                                                         calendarPanel.getDisplayLocale());\r
333             f.setCalendar(calendarPanel.getCalendar());\r
334             f.setTimeZone(new SimpleTimeZone(0, "UTC"));        // JDK 1.1.2 workaround\r
335             monthLabel.setText( f.format( calendarPanel.firstOfMonth() ));\r
336         }\r
337         \r
338         /**\r
339         * Handles the event. Returns true if the event is handled and should not\r
340         * be passed to the parent of this component. The default event handler\r
341         * calls some helper methods to make life easier on the programmer.\r
342         */\r
343         public void actionPerformed(ActionEvent e)\r
344         {\r
345             Object obj = e.getSource();\r
346             \r
347             // *** Button events are handled here.\r
348             if (obj instanceof Button) {\r
349                 if (obj == nextMonth) {\r
350                     calendarPanel.add(Calendar.MONTH, +1);\r
351                 }\r
352                 else\r
353                 if (obj == prevMonth) {\r
354                     calendarPanel.add(Calendar.MONTH, -1);\r
355                 }\r
356                 else\r
357                 if (obj == prevYear) {\r
358                     calendarPanel.add(Calendar.YEAR, -1);\r
359                 }\r
360                 else\r
361                 if (obj == nextYear) {\r
362                     calendarPanel.add(Calendar.YEAR, +1);\r
363                 }\r
364                 else\r
365                 if (obj == gotoToday) {\r
366                     calendarPanel.set( new Date() );\r
367                 }\r
368                 updateMonthName();\r
369             }\r
370         }\r
371         \r
372         public void itemStateChanged(ItemEvent e)\r
373         {\r
374             Object obj = e.getSource();\r
375             if (obj == localeMenu) {\r
376                 calendarPanel.setCalendarLocale(calendars[localeMenu.getSelectedIndex()]);\r
377                 updateMonthName();\r
378             }\r
379             else \r
380                 if (obj == displayMenu) {\r
381                     calendarPanel.setDisplayLocale(locales[displayMenu.getSelectedIndex()]);\r
382                     updateMonthName();\r
383                 }\r
384         }\r
385         \r
386         /**\r
387         * Print out the error message while debugging this program.\r
388         */\r
389         public void errorText(String s)\r
390         {\r
391             if (DEBUG)\r
392             {\r
393                 System.out.println(s);\r
394             }\r
395         }\r
396         \r
397         protected void processWindowEvent(WindowEvent e)\r
398         {\r
399             System.out.println("event " + e);\r
400             if (e.getID() == WindowEvent.WINDOW_CLOSING) {\r
401                 this.hide();\r
402                 this.dispose();\r
403 \r
404                 if (applet != null) {\r
405                     applet.demoClosed();\r
406                 } else {\r
407                     System.exit(0);\r
408                 }\r
409             }\r
410         }\r
411     }\r
412 \r
413 \r
414     private static class CalendarPanel extends Canvas {\r
415 \r
416         /**\r
417          * For serialization\r
418          */\r
419         private static final long serialVersionUID = 1521099412250120821L;\r
420 \r
421         public CalendarPanel( Locale locale ) {\r
422             set(locale, locale, new Date());\r
423         }\r
424 \r
425         public void setCalendarLocale(Locale locale) {\r
426             set(locale, fDisplayLocale, fCalendar.getTime());\r
427         }\r
428 \r
429         public void setDisplayLocale(Locale locale) {\r
430             set(fCalendarLocale, locale, fCalendar.getTime());\r
431         }\r
432 \r
433         public void set(Date date) {\r
434             set(fCalendarLocale, fDisplayLocale, date);\r
435         }\r
436 \r
437         public void set(Locale loc, Locale display, Date date)\r
438         {\r
439             if (fCalendarLocale == null || !loc.equals(fCalendarLocale)) {\r
440                 fCalendarLocale = loc;\r
441                 fCalendar = Calendar.getInstance(fCalendarLocale);\r
442                 fAllHolidays = Holiday.getHolidays(fCalendarLocale);\r
443             }\r
444             if (fDisplayLocale == null || !display.equals(fDisplayLocale)) {\r
445                 fDisplayLocale = display;\r
446                 fSymbols = new DateFormatSymbols(fDisplayLocale);\r
447             }\r
448 \r
449             fStartOfMonth = date;\r
450 \r
451             dirty = true;\r
452             repaint();\r
453         }\r
454 \r
455         public void add(int field, int delta)\r
456         {\r
457             synchronized(fCalendar) {\r
458                 fCalendar.setTime(fStartOfMonth);\r
459                 fCalendar.add(field, delta);\r
460                 fStartOfMonth = fCalendar.getTime();\r
461             }\r
462             dirty = true;\r
463             repaint();\r
464         }\r
465 \r
466         public com.ibm.icu.util.Calendar getCalendar() {\r
467             return fCalendar;\r
468         }\r
469 \r
470         public Locale getCalendarLocale() {\r
471             return fCalendarLocale;\r
472         }\r
473 \r
474         public Locale getDisplayLocale() {\r
475             return fDisplayLocale;\r
476         }\r
477 \r
478 \r
479         public Date firstOfMonth() {\r
480             return fStartOfMonth;\r
481         }\r
482 \r
483         private Date startOfMonth(Date dateInMonth)\r
484         {\r
485             synchronized(fCalendar) {\r
486                 fCalendar.setTime(dateInMonth);             // TODO: synchronization\r
487 \r
488                 int era = fCalendar.get(Calendar.ERA);\r
489                 int year = fCalendar.get(Calendar.YEAR);\r
490                 int month = fCalendar.get(Calendar.MONTH);\r
491 \r
492                 fCalendar.clear();\r
493                 fCalendar.set(Calendar.ERA, era);\r
494                 fCalendar.set(Calendar.YEAR, year);\r
495                 fCalendar.set(Calendar.MONTH, month);\r
496                 fCalendar.set(Calendar.DATE, 1);\r
497 \r
498                 return fCalendar.getTime();\r
499             }\r
500         }\r
501 \r
502         private void calculate()\r
503         {\r
504             //\r
505             // As a workaround for JDK 1.1.3 and below, where Calendars and time\r
506             // zones are a bit goofy, always set my calendar's time zone to UTC.\r
507             // You would think I would want to do this in the "set" function above,\r
508             // but if I do that, the program hangs when this class is loaded,\r
509             // perhaps due to some sort of static initialization ordering problem.\r
510             // So I do it here instead.\r
511             //\r
512             fCalendar.setTimeZone(new SimpleTimeZone(0, "UTC"));\r
513 \r
514             Calendar c = (Calendar)fCalendar.clone(); // Temporary copy\r
515 \r
516             fStartOfMonth = startOfMonth(fStartOfMonth);\r
517 \r
518             // Stash away a few useful constants for this calendar and display\r
519             minDay = c.getMinimum(Calendar.DAY_OF_WEEK);\r
520             daysInWeek = c.getMaximum(Calendar.DAY_OF_WEEK) - minDay + 1;\r
521 \r
522             firstDayOfWeek = Calendar.getInstance(fDisplayLocale).getFirstDayOfWeek();\r
523 \r
524             // Stash away a Date for the start of this month\r
525 \r
526             // Find the day of week of the first day in this month\r
527             c.setTime(fStartOfMonth);\r
528             firstDayInMonth = c.get(Calendar.DAY_OF_WEEK);\r
529 \r
530             // Now find the # of days in the month\r
531             c.roll(Calendar.DATE, false);\r
532             daysInMonth = c.get(Calendar.DATE);\r
533 \r
534             // Finally, find the end of the month, i.e. the start of the next one\r
535             c.roll(Calendar.DATE, true);\r
536             c.add(Calendar.MONTH, 1);\r
537             c.getTime();        // JDK 1.1.2 bug workaround\r
538             c.add(Calendar.SECOND, -1);\r
539             Date endOfMonth = c.getTime();\r
540 \r
541             //\r
542             // Calculate the number of full or partial weeks in this month.\r
543             // To do this I can just reuse the code that calculates which\r
544             // calendar cell contains a given date.\r
545             //\r
546             numWeeks = dateToCell(daysInMonth).y - dateToCell(1).y + 1;\r
547 \r
548             // Remember which holidays fall on which days in this month,\r
549             // to save the trouble of having to do it later\r
550             fHolidays.setSize(0);\r
551 \r
552             for (int h = 0; h < fAllHolidays.length; h++)\r
553             {\r
554                 Date d = fStartOfMonth;\r
555                 while ( (d = fAllHolidays[h].firstBetween(d, endOfMonth) ) != null)\r
556                 {\r
557                     c.setTime(d);\r
558                     fHolidays.addElement( new HolidayInfo(c.get(Calendar.DATE),\r
559                                             fAllHolidays[h],\r
560                                             fAllHolidays[h].getDisplayName(fDisplayLocale) ));\r
561 \r
562                     d.setTime( d.getTime() + 1000 );    // "d++"\r
563                 }\r
564             }\r
565             dirty = false;\r
566         }\r
567 \r
568         static final int INSET = 2;\r
569 \r
570         /*\r
571         * Convert from the day number within a month (1-based)\r
572         * to the cell coordinates on the calendar (0-based)\r
573         */\r
574         private void dateToCell(int date, Point pos)\r
575         {\r
576             int cell = (date + firstDayInMonth - firstDayOfWeek - minDay);\r
577             if (firstDayInMonth < firstDayOfWeek) {\r
578                 cell += daysInWeek;\r
579             }\r
580 \r
581             pos.x = cell % daysInWeek;\r
582             pos.y = cell / daysInWeek;\r
583         }\r
584         private Point dateToCell(int date) {\r
585             Point p = new Point(0,0);\r
586             dateToCell(date, p);\r
587             return p;\r
588         }\r
589 \r
590         public void paint(Graphics g) {\r
591 \r
592             if (dirty) {\r
593                 calculate();\r
594             }\r
595 \r
596             Point cellPos = new Point(0,0);     // Temporary variable\r
597             Dimension d = getSize();\r
598 \r
599             g.setColor(DemoUtility.bgColor);\r
600             g.fillRect(0,0,d.width,d.height);\r
601 \r
602             // Draw the day names at the top\r
603             g.setColor(Color.black);\r
604             g.setFont(DemoUtility.labelFont);\r
605             FontMetrics fm = g.getFontMetrics();\r
606             int labelHeight = fm.getHeight() + INSET * 2;\r
607 \r
608             int v = fm.getAscent() + INSET;\r
609             for (int i = 0; i < daysInWeek; i++) {\r
610                 int dayNum = (i + minDay + firstDayOfWeek - 2) % daysInWeek + 1;\r
611                 String dayName = fSymbols.getWeekdays()[dayNum];\r
612 \r
613                 int h = (int) (d.width * (i + 0.5)) / daysInWeek;\r
614                 h -= fm.stringWidth(dayName) / 2;\r
615 \r
616                 g.drawString(dayName, h, v);\r
617             }\r
618 \r
619             double cellHeight = (d.height - labelHeight - 1) / numWeeks;\r
620             double cellWidth = (double)(d.width - 1) / daysInWeek;\r
621 \r
622             // Draw a white background in the part of the calendar\r
623             // that displays this month.\r
624             // First figure out how much of the first week should be shaded.\r
625             {\r
626                 g.setColor(Color.white);\r
627                 dateToCell(1, cellPos);\r
628                 int width = (int)(cellPos.x*cellWidth);  // Width of unshaded area\r
629 \r
630                 g.fillRect((int)(width), labelHeight ,\r
631                         (int)(d.width - width), (int)cellHeight);\r
632 \r
633                 // All of the intermediate weeks get shaded completely\r
634                 g.fillRect(0, (int)(labelHeight + cellHeight),\r
635                             d.width, (int)(cellHeight * (numWeeks - 2)));\r
636 \r
637                 // Now figure out the last week.\r
638                 dateToCell(daysInMonth, cellPos);\r
639                 width = (int)((cellPos.x+1)*cellWidth);  // Width of shaded area\r
640 \r
641                 g.fillRect(0, (int)(labelHeight + (numWeeks-1) * cellHeight),\r
642                             width, (int)(cellHeight));\r
643 \r
644             }\r
645             // Draw the X/Y grid lines\r
646             g.setColor(Color.black);\r
647             for (int i = 0; i <= numWeeks; i++) {\r
648                 int y = (int)(labelHeight + i * cellHeight);\r
649                 g.drawLine(0, y, d.width - 1, y);\r
650             }\r
651             for (int i = 0; i <= daysInWeek; i++) {\r
652                 int x = (int)(i * cellWidth);\r
653                 g.drawLine(x, labelHeight, x, d.height - 1);\r
654             }\r
655 \r
656             // Now loop through all of the days in the month, figure out where\r
657             // they go in the grid, and draw the day # for each one\r
658             Font numberFont = new Font("Helvetica",Font.PLAIN,12);\r
659             // not used Font holidayFont = DemoUtility.creditFont;\r
660 \r
661             Calendar c = (Calendar)fCalendar.clone();\r
662             c.setTime(fStartOfMonth);\r
663 \r
664             for (int i = 1, h = 0; i <= daysInMonth; i++) {\r
665                 g.setFont(numberFont);\r
666                 g.setColor(Color.black);\r
667                 fm = g.getFontMetrics();\r
668 \r
669                 dateToCell(i, cellPos);\r
670                 int x = (int)((cellPos.x + 1) * cellWidth);\r
671                 int y = (int)(cellPos.y * cellHeight + labelHeight);\r
672 \r
673                 StringBuffer buffer = new StringBuffer();\r
674                 buffer.append(i);\r
675                 String dayNum = buffer.toString();\r
676 \r
677                 x = x - INSET - fm.stringWidth(dayNum);\r
678                 y = y + fm.getAscent() + INSET;\r
679 \r
680                 g.drawString(dayNum, x, y);\r
681 \r
682                 // See if any of the holidays land on this day....\r
683                 HolidayInfo info = null;\r
684                 int count = 0;\r
685 \r
686                 // Coordinates of lower-left corner of cell.\r
687                 x = (int)((cellPos.x) * cellWidth);\r
688                 y = (int)((cellPos.y+1) * cellHeight) + labelHeight;\r
689 \r
690                 while (h < fHolidays.size() &&\r
691                         (info = (HolidayInfo)fHolidays.elementAt(h)).date <= i)\r
692                 {\r
693                     if (info.date == i) {\r
694                         // Draw the holiday here.\r
695                         g.setFont(numberFont);\r
696                         g.setColor(Color.red);\r
697 \r
698                         DemoTextBox box = new DemoTextBox(g, info.name, (int)(cellWidth - INSET));\r
699                         box.draw(g, x + INSET, y - INSET - box.getHeight());\r
700 \r
701                         y -= (box.getHeight() + INSET);\r
702                         count++;\r
703                     }\r
704                     h++;\r
705                 }\r
706             }\r
707         }\r
708 \r
709         // Important state variables\r
710         private Locale              fCalendarLocale;    // Whose calendar\r
711         private Calendar            fCalendar;          // Calendar for calculations\r
712 \r
713         private Locale              fDisplayLocale;     // How to display it\r
714         private DateFormatSymbols   fSymbols;           // Symbols for drawing\r
715 \r
716         private Date                fStartOfMonth;      // 00:00:00 on first day of month\r
717 \r
718         // Cached calculations to make drawing faster.\r
719         private transient int minDay;           // Minimum legal day #\r
720         private transient int daysInWeek;       // # of days in a week\r
721         private transient int firstDayOfWeek;   // First day to display in week\r
722         private transient int numWeeks;         // # full or partial weeks in month\r
723         private transient int daysInMonth;      // # days in this month\r
724         private transient int firstDayInMonth;  // Day of week of first day in month\r
725 \r
726         private transient Holiday[] fAllHolidays;\r
727         private transient Vector    fHolidays = new Vector(5,5);\r
728 \r
729         private transient boolean dirty = true;\r
730     }\r
731 \r
732     private static class HolidayInfo {\r
733         public HolidayInfo(int date, Holiday holiday, String name) {\r
734             this.date = date;\r
735             this.holiday = holiday;\r
736             this.name = name;\r
737         }\r
738 \r
739         public Holiday holiday;\r
740         public int date;\r
741         public String name;\r
742     }\r
743 }\r
744 \r