• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.BorderLayout;
11 import java.awt.Button;
12 import java.awt.Choice;
13 import java.awt.Color;
14 import java.awt.Component;
15 import java.awt.Container;
16 import java.awt.Dimension;
17 import java.awt.FlowLayout;
18 import java.awt.Font;
19 import java.awt.FontMetrics;
20 import java.awt.Frame;
21 import java.awt.Graphics;
22 import java.awt.GridBagConstraints;
23 import java.awt.GridBagLayout;
24 import java.awt.Label;
25 import java.awt.Panel;
26 import java.awt.Rectangle;
27 import java.awt.event.ActionEvent;
28 import java.awt.event.ActionListener;
29 import java.awt.event.ItemEvent;
30 import java.awt.event.ItemListener;
31 import java.awt.event.WindowAdapter;
32 import java.awt.event.WindowEvent;
33 import java.util.Date;
34 import java.util.Locale;
35 
36 import com.ibm.icu.dev.demo.impl.DemoApplet;
37 import com.ibm.icu.dev.demo.impl.DemoUtility;
38 import com.ibm.icu.text.DateFormat;
39 import com.ibm.icu.util.BuddhistCalendar;
40 import com.ibm.icu.util.Calendar;
41 import com.ibm.icu.util.GregorianCalendar;
42 import com.ibm.icu.util.HebrewCalendar;
43 import com.ibm.icu.util.IslamicCalendar;
44 import com.ibm.icu.util.JapaneseCalendar;
45 import com.ibm.icu.util.SimpleTimeZone;
46 
47 /**
48  * A Frame is a top-level window with a title. The default layout for a frame
49  * is BorderLayout.  The CalendarFrame class defines the window layout of
50  * CalendarDemo.
51  */
52 class CalendarFrame extends Frame
53 {
54     /**
55      * For serialization
56      */
57     private static final long serialVersionUID = -4289697663503820619L;
58 
59     private static final boolean DEBUG = false;
60 
61     private DemoApplet applet;
62 
63     /**
64      * Constructs a new CalendarFrame that is initially invisible.
65      */
CalendarFrame(DemoApplet myApplet)66     public CalendarFrame(DemoApplet myApplet)
67     {
68         super("Calendar Demo");
69         this.applet = myApplet;
70         init();
71 
72         // When the window is closed, we want to shut down the applet or application
73         addWindowListener(
74             new WindowAdapter() {
75                 public void windowClosing(WindowEvent e) {
76                     setVisible(false);
77                     dispose();
78 
79                     if (applet != null) {
80                         applet.demoClosed();
81                     } else System.exit(0);
82                 }
83             } );
84     }
85 
86     private Choice          displayMenu;
87     private Locale[]        locales = DemoUtility.getG7Locales();
88 
89     private Calendar        calendars[]   = new Calendar[2];
90     private Choice          calMenu[]     = new Choice[2];
91     private ColoredLabel    monthLabel[]  = new ColoredLabel[2];
92     private DateFormat      monthFormat[] = new DateFormat[2];
93 
94     private Button          prevYear;
95     private Button          prevMonth;
96     private Button          gotoToday;
97     private Button          nextMonth;
98     private Button          nextYear;
99     private CalendarPanel   calendarPanel;
100 
add(Container container, Component component, GridBagLayout g, GridBagConstraints c, int gridwidth, int weightx)101     private static void add(Container container, Component component,
102                             GridBagLayout g, GridBagConstraints c,
103                             int gridwidth, int weightx)
104     {
105         c.gridwidth = gridwidth;
106         c.weightx = weightx;
107         g.setConstraints(component, c);
108         container.add(component);
109     }
110 
111     /**
112      * Initializes the applet. You never need to call this directly, it
113      * is called automatically by the system once the applet is created.
114      */
init()115     public void init() {
116         setBackground(DemoUtility.bgColor);
117         setLayout(new BorderLayout(10,10));
118 
119         Panel topPanel = new Panel();
120         GridBagLayout g = new GridBagLayout();
121         topPanel.setLayout(g);
122         GridBagConstraints c = new GridBagConstraints();
123         c.fill = GridBagConstraints.HORIZONTAL;
124 
125         // Build the two menus for selecting which calendar is displayed,
126         // plus the month/year label for each calendar
127         for (int i = 0; i < 2; i++) {
128             calMenu[i] = new Choice();
129             for (int j = 0; j < CALENDARS.length; j++) {
130                 calMenu[i].addItem(CALENDARS[j].name);
131             }
132             calMenu[i].setBackground(DemoUtility.choiceColor);
133             calMenu[i].select(i);
134             calMenu[i].addItemListener(new CalMenuListener());
135 
136             // Label for the current month name
137             monthLabel[i] = new ColoredLabel("", COLORS[i]);
138             monthLabel[i].setFont(DemoUtility.titleFont);
139 
140             // And the default calendar to use for this slot
141             calendars[i] = CALENDARS[i].calendar;
142 
143             add(topPanel, calMenu[i], g, c, 5, 0);
144             add(topPanel, monthLabel[i], g, c, GridBagConstraints.REMAINDER, 1);
145         }
146 
147         // Now add the next/previous year/month buttons:
148         prevYear = new Button("<<");
149         prevYear.addActionListener(new AddAction(Calendar.YEAR, -1));
150 
151         prevMonth = new Button("<");
152         prevMonth.addActionListener(new AddAction(Calendar.MONTH, -1));
153 
154         gotoToday = new Button("Today");
155         gotoToday.addActionListener( new ActionListener()
156         {
157             public void actionPerformed(ActionEvent e) {
158                 calendarPanel.setDate( new Date() );
159                 updateMonthName();
160             }
161         } );
162 
163         nextMonth = new Button(">");
164         nextMonth.addActionListener(new AddAction(Calendar.MONTH, 1));
165 
166         nextYear = new Button(">>");
167         nextYear.addActionListener(new AddAction(Calendar.YEAR, 1));
168 
169         c.fill = GridBagConstraints.NONE;
170         add(topPanel, prevYear,  g, c, 1, 0);
171         add(topPanel, prevMonth, g, c, 1, 0);
172         add(topPanel, gotoToday, g, c, 1, 0);
173         add(topPanel, nextMonth, g, c, 1, 0);
174         add(topPanel, nextYear,  g, c, 1, 0);
175 
176         // Now add the menu for selecting the display language
177         Panel displayPanel = new Panel();
178         {
179             displayMenu = new Choice();
180             Locale defaultLocale = Locale.getDefault();
181             int bestMatch = -1, thisMatch = -1;
182             int selectMe = 0;
183 
184             for (int i = 0; i < locales.length; i++) {
185                 if (i > 0 &&
186                         locales[i].getLanguage().equals(locales[i-1].getLanguage()) ||
187                     i < locales.length - 1 &&
188                         locales[i].getLanguage().equals(locales[i+1].getLanguage()))
189                 {
190                     displayMenu.addItem( locales[i].getDisplayName() );
191                 } else {
192                     displayMenu.addItem( locales[i].getDisplayLanguage());
193                 }
194 
195                 thisMatch = DemoUtility.compareLocales(locales[i], defaultLocale);
196 
197                 if (thisMatch >= bestMatch) {
198                     bestMatch = thisMatch;
199                     selectMe = i;
200                 }
201             }
202 
203             displayMenu.setBackground(DemoUtility.choiceColor);
204             displayMenu.select(selectMe);
205 
206             displayMenu.addItemListener( new ItemListener()
207             {
208                  public void itemStateChanged(ItemEvent e) {
209                     Locale loc = locales[displayMenu.getSelectedIndex()];
210                     calendarPanel.setLocale( loc );
211                     monthFormat[0] = monthFormat[1] = null;
212                     updateMonthName();
213                     repaint();
214                 }
215             } );
216 
217             Label l1 = new Label("Display Language:", Label.RIGHT);
218             l1.setFont(DemoUtility.labelFont);
219 
220             displayPanel.setLayout(new FlowLayout());
221             displayPanel.add(l1);
222             displayPanel.add(displayMenu);
223 
224         }
225         c.fill = GridBagConstraints.NONE;
226         c.anchor = GridBagConstraints.EAST;
227 
228         add(topPanel, displayPanel, g, c, GridBagConstraints.REMAINDER, 0);
229 
230         // The title, buttons, etc. go in a panel at the top of the window
231         add("North", topPanel);
232 
233         // The copyright notice goes at the bottom of the window
234         Label copyright = new Label(DemoUtility.copyright1, Label.LEFT);
235         copyright.setFont(DemoUtility.creditFont);
236         add("South", copyright);
237 
238         // Now create the big calendar panel and stick it in the middle
239         calendarPanel = new CalendarPanel( locales[displayMenu.getSelectedIndex()] );
240         add("Center", calendarPanel);
241 
242         for (int i = 0; i < 2; i++) {
243             calendarPanel.setCalendar(i, calendars[i]);
244             calendarPanel.setColor(i, COLORS[i]);
245         }
246 
247         updateMonthName();
248     }
249 
250 
updateMonthName()251     private void updateMonthName()
252     {
253             for (int i = 0; i < 2; i++) {
254                 try {
255                     if (monthFormat[i] == null) {     // TODO: optimize
256                         DateFormat f = DateFormat.getDateTimeInstance(
257                                                 calendars[i], DateFormat.MEDIUM, -1,
258                                                 locales[displayMenu.getSelectedIndex()]);
259                         if (f instanceof com.ibm.icu.text.SimpleDateFormat) {
260                             com.ibm.icu.text.SimpleDateFormat f1 = (com.ibm.icu.text.SimpleDateFormat) f;
261                             f1.applyPattern("MMMM, yyyy G");
262                             f1.setTimeZone(new SimpleTimeZone(0, "UTC"));
263                         }
264                         monthFormat[i] = f;
265                     }
266                 } catch (ClassCastException e) {
267                     //hey {lw} - there's something wrong in this routine that cuases exceptions.
268                     System.out.println(e);
269                 }
270 
271                 monthLabel[i].setText( monthFormat[i].format( calendarPanel.firstOfMonth() ));
272             }
273     }
274 
275     /**
276      * CalMenuListener responds to events in the two popup menus that select
277      * the calendar systems to be used in the display.  It figures out which
278      * of the two menus the event occurred in and updates the corresponding
279      * element of the calendars[] array to match the new selection.
280      */
281     private class CalMenuListener implements ItemListener
282     {
itemStateChanged(ItemEvent e)283          public void itemStateChanged(ItemEvent e)
284          {
285             for (int i = 0; i < calMenu.length; i++)
286             {
287                 if (e.getItemSelectable() == calMenu[i])
288                 {
289                     // We found the menu that the event happened in.
290                     // Figure out which new calendar they selected.
291                     Calendar newCal = CALENDARS[ calMenu[i].getSelectedIndex() ].calendar;
292 
293                     if (newCal != calendars[i])
294                     {
295                         // If any of the other menus are set to the same new calendar
296                         // we're about to use for this menu, set them to the current
297                         // calendar from *this* menu so we won't have two the same
298                         for (int j = 0; j < calendars.length; j++) {
299                             if (j != i && calendars[j] == newCal) {
300                                 calendars[j] = calendars[i];
301                                 calendarPanel.setCalendar(j, calendars[j]);
302                                 monthFormat[j] = null;
303 
304                                 for (int k = 0; k < CALENDARS.length; k++) {
305                                     if (calendars[j] == CALENDARS[k].calendar) {
306                                         calMenu[j].select(k);
307                                         break;
308                                     }
309                                 }
310                             }
311                         }
312                         // Now update this menu to use the new calendar the user selected
313                         calendars[i] = newCal;
314                         calendarPanel.setCalendar(i, newCal);
315                         monthFormat[i] = null;
316 
317                         updateMonthName();
318                     }
319                     break;
320                 }
321             }
322          }
323     }
324 
325     /**
326      * AddAction handles the next/previous year/month buttons...
327      */
328     private class AddAction implements ActionListener {
AddAction(int field, int amount)329         AddAction(int field, int amount) {
330             this.field = field;
331             this.amount = amount;
332         }
333 
actionPerformed(ActionEvent e)334         public void actionPerformed(ActionEvent e) {
335             calendarPanel.add(field, amount);
336             updateMonthName();
337         }
338 
339         private int field, amount;
340     }
341 
342     /**
343      * ColoredLabel is similar to java.awt.Label, with two differences:
344      *
345      *  - You can set its text color
346      *
347      *  - It draws text using drawString rather than using a host-specific
348      *    "Peer" object like AWT does.  On 1.2, using drawString gives
349      *    us Bidi reordering for free.
350      */
351     static private class ColoredLabel extends Component {
352         /**
353          * For serialization
354          */
355         private static final long serialVersionUID = 5004484960341875722L;
ColoredLabel(String label)356         public ColoredLabel(String label) {
357             text = label;
358         }
359 
ColoredLabel(String label, Color c)360         public ColoredLabel(String label, Color c) {
361             text = label;
362             color = c;
363         }
364 
setText(String label)365         public void setText(String label) {
366             text = label;
367             repaint();
368         }
369 
setFont(Font f)370         public void setFont(Font f) {
371             font = f;
372             repaint();
373         }
374 
paint(Graphics g)375         public void paint(Graphics g) {
376             FontMetrics fm = g.getFontMetrics(font);
377 
378             Rectangle bounds = getBounds();
379 
380             g.setColor(color);
381             g.setFont(font);
382             g.drawString(text, fm.stringWidth("\u00a0"),
383                          bounds.height/2 + fm.getHeight()
384                          - fm.getAscent() + fm.getLeading()/2);
385         }
386 
getPreferredSize()387         public Dimension getPreferredSize() {
388             return getMinimumSize();
389         }
390 
getMinimumSize()391         public Dimension getMinimumSize() {
392             FontMetrics fm = getFontMetrics(font);
393 
394             return new Dimension( fm.stringWidth(text) + 2*fm.stringWidth("\u00a0"),
395                                   fm.getHeight() + fm.getLeading()*2);
396         }
397 
398         String text;
399         Color color = Color.black;
400         Font font = DemoUtility.labelFont;
401     }
402 
403     /**
404      * Print out the error message while debugging this program.
405      */
errorText(String s)406     public void errorText(String s)
407     {
408         if (DEBUG)
409         {
410             System.out.println(s);
411         }
412     }
413 
414     class CalendarRec {
CalendarRec(String nameStr, Calendar cal)415         public CalendarRec(String nameStr, Calendar cal)
416         {
417             name = nameStr;
418             calendar = cal;
419         }
420 
421         Calendar  calendar;
422         String              name;
423     }
424 
425     private final CalendarRec[] CALENDARS = {
426         new CalendarRec("Gregorian Calendar",       new GregorianCalendar()),
427         new CalendarRec("Hebrew Calendar",          new HebrewCalendar()),
428         new CalendarRec("Islamic Calendar",         makeIslamic(false)),
429         new CalendarRec("Islamic Civil Calendar ",  makeIslamic(true)),
430         new CalendarRec("Buddhist Calendar",        new BuddhistCalendar()),
431         new CalendarRec("Japanese Calendar",        new JapaneseCalendar()),
432     };
433 
makeIslamic(boolean civil)434     static private final Calendar makeIslamic(boolean civil) {
435         IslamicCalendar cal = new IslamicCalendar();
436         cal.setCivil(civil);
437         return cal;
438     }
439 
440     static final Color[] COLORS = { Color.blue, Color.black };
441 }
442 
443