]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/demos/src/com/ibm/icu/dev/demo/calendar/CalendarPanel.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / demos / src / com / ibm / icu / dev / demo / calendar / CalendarPanel.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 1997-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.calendar;\r
9 \r
10 import java.awt.Canvas;\r
11 import java.awt.Color;\r
12 import java.awt.Dimension;\r
13 import java.awt.FontMetrics;\r
14 import java.awt.Graphics;\r
15 import java.awt.Point;\r
16 import java.util.Date;\r
17 import java.util.Locale;\r
18 \r
19 import com.ibm.icu.dev.demo.impl.DemoUtility;\r
20 import com.ibm.icu.text.DateFormatSymbols;\r
21 import com.ibm.icu.util.Calendar;\r
22 import com.ibm.icu.util.SimpleTimeZone;\r
23 \r
24 class CalendarPanel extends Canvas {\r
25 \r
26     /**\r
27      * For serialization\r
28      */\r
29     private static final long serialVersionUID = 625400018027387141L;\r
30 \r
31     public CalendarPanel( Locale locale ) {\r
32         setLocale(locale);\r
33     }\r
34 \r
35     public void setLocale(Locale locale) {\r
36         if (fDisplayLocale == null || !fDisplayLocale.equals(locale)) {\r
37             fDisplayLocale = locale;\r
38             dirty = true;\r
39 \r
40             for (int i = 0; i < fCalendar.length; i++) {\r
41                 if (fCalendar[i] != null) {\r
42                     fSymbols[i] = new DateFormatSymbols(fCalendar[i],\r
43                                                         fDisplayLocale);\r
44                 }\r
45             }\r
46             String lang = locale.getLanguage();\r
47             leftToRight = !(lang.equals("iw") || lang.equals("ar"));\r
48 \r
49             repaint();\r
50         }\r
51     }\r
52 \r
53     public void setDate(Date date) {\r
54         fStartOfMonth = date;\r
55         dirty = true;\r
56         repaint();\r
57     }\r
58 \r
59     public void add(int field, int delta)\r
60     {\r
61         synchronized(fCalendar) {\r
62             fCalendar[0].setTime(fStartOfMonth);\r
63             fCalendar[0].add(field, delta);\r
64             fStartOfMonth = fCalendar[0].getTime();\r
65         }\r
66         dirty = true;\r
67         repaint();\r
68     }\r
69 \r
70     public void setColor(int index, Color c) {\r
71         fColor[index] = c;\r
72         repaint();\r
73     }\r
74 \r
75     public void setCalendar(int index, Calendar c) {\r
76         Date date = (fCalendar[index] == null) ? new Date()\r
77                                                : fCalendar[index].getTime();\r
78 \r
79         fCalendar[index] = c;\r
80         fCalendar[index].setTime(date);\r
81 \r
82         fSymbols[index] = new DateFormatSymbols(c, fDisplayLocale);\r
83         dirty = true;\r
84         repaint();\r
85     }\r
86 \r
87     public Calendar getCalendar(int index) {\r
88         return fCalendar[index];\r
89     }\r
90 \r
91     public Locale getDisplayLocale() {\r
92         return fDisplayLocale;\r
93     }\r
94 \r
95     public Date firstOfMonth() {\r
96         return fStartOfMonth;\r
97     }\r
98 \r
99     private Date startOfMonth(Date dateInMonth)\r
100     {\r
101         synchronized(fCalendar) {\r
102             fCalendar[0].setTime(dateInMonth);\r
103 \r
104             int era = fCalendar[0].get(Calendar.ERA);\r
105             int year = fCalendar[0].get(Calendar.YEAR);\r
106             int month = fCalendar[0].get(Calendar.MONTH);\r
107 \r
108             fCalendar[0].clear();\r
109             fCalendar[0].set(Calendar.ERA, era);\r
110             fCalendar[0].set(Calendar.YEAR, year);\r
111             fCalendar[0].set(Calendar.MONTH, month);\r
112             fCalendar[0].set(Calendar.DATE, 1);\r
113 \r
114             return fCalendar[0].getTime();\r
115         }\r
116     }\r
117 \r
118     private void calculate()\r
119     {\r
120         //\r
121         // As a workaround for JDK 1.1.3 and below, where Calendars and time\r
122         // zones are a bit goofy, always set my calendar's time zone to UTC.\r
123         // You would think I would want to do this in the "set" function above,\r
124         // but if I do that, the program hangs when this class is loaded,\r
125         // perhaps due to some sort of static initialization ordering problem.\r
126         // So I do it here instead.\r
127         //\r
128         fCalendar[0].setTimeZone(new SimpleTimeZone(0, "UTC"));\r
129 \r
130         Calendar c = (Calendar)fCalendar[0].clone(); // Temporary copy\r
131 \r
132         fStartOfMonth = startOfMonth(fStartOfMonth);\r
133 \r
134         // Stash away a few useful constants for this calendar and display\r
135         minDay = c.getMinimum(Calendar.DAY_OF_WEEK);\r
136         daysInWeek = c.getMaximum(Calendar.DAY_OF_WEEK) - minDay + 1;\r
137 \r
138         firstDayOfWeek = Calendar.getInstance(fDisplayLocale).getFirstDayOfWeek();\r
139 \r
140         // Stash away a Date for the start of this month\r
141 \r
142         // Find the day of week of the first day in this month\r
143         c.setTime(fStartOfMonth);\r
144         firstDayInMonth = c.get(Calendar.DAY_OF_WEEK);\r
145         int firstWeek = c.get(Calendar.WEEK_OF_MONTH);\r
146 \r
147         // Now find the # of days in the month\r
148         c.roll(Calendar.DATE, false);\r
149         daysInMonth = c.get(Calendar.DATE);\r
150 \r
151         // Finally, find the end of the month, i.e. the start of the next one\r
152         c.roll(Calendar.DATE, true);\r
153         c.add(Calendar.MONTH, 1);\r
154         c.getTime();        // JDK 1.1.2 bug workaround\r
155         c.add(Calendar.SECOND, -1);\r
156         Date endOfMonth = c.getTime();\r
157         if(endOfMonth==null){\r
158          //do nothing\r
159         }\r
160         endOfMonth = null;\r
161         int lastWeek = c.get(Calendar.WEEK_OF_MONTH);\r
162         \r
163         // Calculate the number of full or partial weeks in this month.\r
164         numWeeks = lastWeek - firstWeek + 1;\r
165 \r
166         dirty = false;\r
167     }\r
168 \r
169     static final int XINSET = 4;\r
170     static final int YINSET = 2;\r
171 \r
172     /*\r
173      * Convert from the day number within a month (1-based)\r
174      * to the cell coordinates on the calendar (0-based)\r
175      */\r
176     private void dateToCell(int date, Point pos)\r
177     {\r
178         int cell = (date + firstDayInMonth - firstDayOfWeek - minDay);\r
179         if (firstDayInMonth < firstDayOfWeek) {\r
180             cell += daysInWeek;\r
181         }\r
182 \r
183         pos.x = cell % daysInWeek;\r
184         pos.y = cell / daysInWeek;\r
185     }\r
186     //private Point dateToCell(int date) {\r
187     //    Point p = new Point(0,0);\r
188     //    dateToCell(date, p);\r
189     //    return p;\r
190     //}\r
191 \r
192     public void paint(Graphics g) {\r
193 \r
194         if (dirty) {\r
195             calculate();\r
196         }\r
197 \r
198         Point cellPos = new Point(0,0);     // Temporary variable\r
199         Dimension d = this.getSize();\r
200 \r
201         g.setColor(Color.lightGray);\r
202         g.fillRect(0,0,d.width,d.height);\r
203 \r
204         // Draw the day names at the top\r
205         g.setColor(Color.black);\r
206         g.setFont(DemoUtility.labelFont);\r
207         FontMetrics fm = g.getFontMetrics();\r
208         int labelHeight = fm.getHeight() + YINSET * 2;\r
209 \r
210         int v = fm.getAscent() + YINSET;\r
211         for (int i = 0; i < daysInWeek; i++) {\r
212             int dayNum = (i + minDay + firstDayOfWeek - 2) % daysInWeek + 1;\r
213             String dayName = fSymbols[0].getWeekdays()[dayNum];\r
214 \r
215 \r
216             double h;\r
217             if (leftToRight) {\r
218                 h = d.width*(i + 0.5) / daysInWeek;\r
219             } else {\r
220                 h = d.width*(daysInWeek - i - 0.5) / daysInWeek;\r
221             }\r
222             h -= fm.stringWidth(dayName) / 2;\r
223 \r
224             g.drawString(dayName, (int)h, v);\r
225         }\r
226 \r
227         double cellHeight = (d.height - labelHeight - 1) / numWeeks;\r
228         double cellWidth = (double)(d.width - 1) / daysInWeek;\r
229 \r
230         // Draw a white background in the part of the calendar\r
231         // that displays this month.\r
232         // First figure out how much of the first week should be shaded.\r
233         {\r
234             g.setColor(Color.white);\r
235             dateToCell(1, cellPos);\r
236             int width = (int)(cellPos.x*cellWidth);  // Width of unshaded area\r
237 \r
238             if (leftToRight) {\r
239                 g.fillRect((int)(width), labelHeight ,\r
240                            d.width - width, (int)cellHeight);\r
241             } else {\r
242                 g.fillRect(0, labelHeight ,\r
243                            d.width - width, (int)cellHeight);\r
244             }\r
245 \r
246             // All of the intermediate weeks get shaded completely\r
247             g.fillRect(0, (int)(labelHeight + cellHeight),\r
248                         d.width, (int)(cellHeight * (numWeeks - 2)));\r
249 \r
250             // Now figure out the last week.\r
251             dateToCell(daysInMonth, cellPos);\r
252             width = (int)((cellPos.x+1)*cellWidth);  // Width of shaded area\r
253 \r
254             if (leftToRight) {\r
255                 g.fillRect(0, (int)(labelHeight + (numWeeks-1) * cellHeight),\r
256                            width, (int)cellHeight);\r
257             } else {\r
258                 g.fillRect(d.width - width, (int)(labelHeight + (numWeeks-1) * cellHeight),\r
259                            width, (int)cellHeight);\r
260             }\r
261 \r
262         }\r
263         // Draw the X/Y grid lines\r
264         g.setColor(Color.black);\r
265         for (int i = 0; i <= numWeeks; i++) {\r
266             int y = (int)(labelHeight + i * cellHeight);\r
267             g.drawLine(0, y, d.width - 1, y);\r
268         }\r
269         for (int i = 0; i <= daysInWeek; i++) {\r
270             int x = (int)(i * cellWidth);\r
271             g.drawLine(x, labelHeight, x, d.height - 1);\r
272         }\r
273 \r
274         // Now loop through all of the days in the month, figure out where\r
275         // they go in the grid, and draw the day # for each one\r
276 \r
277         // Figure out the date of the first cell in the calendar display\r
278         int cell = (1 + firstDayInMonth - firstDayOfWeek - minDay);\r
279         if (firstDayInMonth < firstDayOfWeek) {\r
280             cell += daysInWeek;\r
281         }\r
282 \r
283         Calendar c = (Calendar)fCalendar[0].clone();\r
284         c.setTime(fStartOfMonth);\r
285         c.add(Calendar.DATE, -cell);\r
286 \r
287         StringBuffer buffer = new StringBuffer();\r
288 \r
289         for (int row = 0; row < numWeeks; row++) {\r
290             for (int col = 0; col < daysInWeek; col++) {\r
291 \r
292                 g.setFont(DemoUtility.numberFont);\r
293                 g.setColor(Color.black);\r
294                 fm = g.getFontMetrics();\r
295 \r
296                 int cellx;\r
297                 if (leftToRight) {\r
298                     cellx = (int)((col) * cellWidth);\r
299                 } else {\r
300                     cellx = (int)((daysInWeek - col - 1) * cellWidth);\r
301                 }\r
302 \r
303                 int celly = (int)(row * cellHeight + labelHeight);\r
304 \r
305                 for (int i = 0; i < 2; i++) {\r
306                     fCalendar[i].setTime(c.getTime());\r
307 \r
308                     int date = fCalendar[i].get(Calendar.DATE);\r
309                     buffer.setLength(0);\r
310                     buffer.append(date);\r
311                     String dayNum = buffer.toString();\r
312 \r
313                     int x;\r
314 \r
315                     if (leftToRight) {\r
316                         x = cellx + (int)cellWidth - XINSET - fm.stringWidth(dayNum);\r
317                     } else {\r
318                         x = cellx + XINSET;\r
319                     }\r
320                     int y = celly + + fm.getAscent() + YINSET + i * fm.getHeight();\r
321 \r
322                     if (fColor[i] != null) {\r
323                         g.setColor(fColor[i]);\r
324                     }\r
325                     g.drawString(dayNum, x, y);\r
326 \r
327                     if (date == 1 || row == 0 && col == 0) {\r
328                         g.setFont(DemoUtility.numberFont);\r
329                         String month = fSymbols[i].getMonths()[\r
330                                             fCalendar[i].get(Calendar.MONTH)];\r
331 \r
332                         if (leftToRight) {\r
333                             x = cellx + XINSET;\r
334                         } else {\r
335                             x = cellx + (int)cellWidth - XINSET - fm.stringWidth(month);\r
336                         }\r
337                         g.drawString(month, x, y);\r
338                     }\r
339                 }\r
340 \r
341                 c.add(Calendar.DATE, 1);\r
342             }\r
343         }\r
344     }\r
345 \r
346     // Important state variables\r
347     private Calendar[]          fCalendar = new Calendar[4];\r
348     private Color[]             fColor = new Color[4];\r
349 \r
350     private Locale              fDisplayLocale;\r
351     private DateFormatSymbols[] fSymbols = new DateFormatSymbols[4];\r
352 \r
353     private Date                fStartOfMonth = new Date();     // 00:00:00 on first day of month\r
354 \r
355     // Cached calculations to make drawing faster.\r
356     private transient int       minDay;           // Minimum legal day #\r
357     private transient int       daysInWeek;       // # of days in a week\r
358     private transient int       firstDayOfWeek;   // First day to display in week\r
359     private transient int       numWeeks;         // # full or partial weeks in month\r
360     private transient int       daysInMonth;      // # days in this month\r
361     private transient int       firstDayInMonth;  // Day of week of first day in month\r
362     private transient boolean   leftToRight;\r
363 \r
364     private transient boolean dirty = true;\r
365 }\r