~ubuntu-branches/ubuntu/vivid/icu4j-4.4/vivid

« back to all changes in this revision

Viewing changes to demos/src/com/ibm/icu/dev/demo/calendar/CalendarPanel.java

  • Committer: Bazaar Package Importer
  • Author(s): Niels Thykier
  • Date: 2011-08-02 15:50:33 UTC
  • Revision ID: james.westby@ubuntu.com-20110802155033-itjzsl21y2lqdonn
Tags: upstream-4.4.2
ImportĀ upstreamĀ versionĀ 4.4.2

Show diffs side-by-side

added added

removed removed

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