2 *******************************************************************************
\r
3 * Copyright (C) 1997-2007, International Business Machines Corporation and *
\r
4 * others. All Rights Reserved. *
\r
5 *******************************************************************************
\r
8 package com.ibm.icu.dev.demo.calendar;
\r
10 import java.awt.BorderLayout;
\r
11 import java.awt.Button;
\r
12 import java.awt.Choice;
\r
13 import java.awt.Color;
\r
14 import java.awt.Component;
\r
15 import java.awt.Container;
\r
16 import java.awt.Dimension;
\r
17 import java.awt.FlowLayout;
\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.Rectangle;
\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.WindowAdapter;
\r
32 import java.awt.event.WindowEvent;
\r
33 import java.util.Date;
\r
34 import java.util.Locale;
\r
36 import com.ibm.icu.dev.demo.impl.DemoApplet;
\r
37 import com.ibm.icu.dev.demo.impl.DemoUtility;
\r
38 import com.ibm.icu.text.DateFormat;
\r
39 import com.ibm.icu.util.BuddhistCalendar;
\r
40 import com.ibm.icu.util.Calendar;
\r
41 import com.ibm.icu.util.GregorianCalendar;
\r
42 import com.ibm.icu.util.HebrewCalendar;
\r
43 import com.ibm.icu.util.IslamicCalendar;
\r
44 import com.ibm.icu.util.JapaneseCalendar;
\r
45 import com.ibm.icu.util.SimpleTimeZone;
\r
48 * A Frame is a top-level window with a title. The default layout for a frame
\r
49 * is BorderLayout. The CalendarFrame class defines the window layout of
\r
52 class CalendarFrame extends Frame
\r
57 private static final long serialVersionUID = -4289697663503820619L;
\r
59 private static final boolean DEBUG = false;
\r
61 private DemoApplet applet;
\r
64 * Constructs a new CalendarFrame that is initially invisible.
\r
66 public CalendarFrame(DemoApplet myApplet)
\r
68 super("Calendar Demo");
\r
69 this.applet = myApplet;
\r
72 // When the window is closed, we want to shut down the applet or application
\r
74 new WindowAdapter() {
\r
75 public void windowClosing(WindowEvent e) {
\r
79 if (applet != null) {
\r
80 applet.demoClosed();
\r
81 } else System.exit(0);
\r
86 private Choice displayMenu;
\r
87 private Locale[] locales = DemoUtility.getG7Locales();
\r
89 private Calendar calendars[] = new Calendar[2];
\r
90 private Choice calMenu[] = new Choice[2];
\r
91 private ColoredLabel monthLabel[] = new ColoredLabel[2];
\r
92 private DateFormat monthFormat[] = new DateFormat[2];
\r
94 private Button prevYear;
\r
95 private Button prevMonth;
\r
96 private Button gotoToday;
\r
97 private Button nextMonth;
\r
98 private Button nextYear;
\r
99 private CalendarPanel calendarPanel;
\r
101 private static void add(Container container, Component component,
\r
102 GridBagLayout g, GridBagConstraints c,
\r
103 int gridwidth, int weightx)
\r
105 c.gridwidth = gridwidth;
\r
106 c.weightx = weightx;
\r
107 g.setConstraints(component, c);
\r
108 container.add(component);
\r
112 * Initializes the applet. You never need to call this directly, it
\r
113 * is called automatically by the system once the applet is created.
\r
115 public void init() {
\r
116 setBackground(DemoUtility.bgColor);
\r
117 setLayout(new BorderLayout(10,10));
\r
119 Panel topPanel = new Panel();
\r
120 GridBagLayout g = new GridBagLayout();
\r
121 topPanel.setLayout(g);
\r
122 GridBagConstraints c = new GridBagConstraints();
\r
123 c.fill = GridBagConstraints.HORIZONTAL;
\r
125 // Build the two menus for selecting which calendar is displayed,
\r
126 // plus the month/year label for each calendar
\r
127 for (int i = 0; i < 2; i++) {
\r
128 calMenu[i] = new Choice();
\r
129 for (int j = 0; j < CALENDARS.length; j++) {
\r
130 calMenu[i].addItem(CALENDARS[j].name);
\r
132 calMenu[i].setBackground(DemoUtility.choiceColor);
\r
133 calMenu[i].select(i);
\r
134 calMenu[i].addItemListener(new CalMenuListener());
\r
136 // Label for the current month name
\r
137 monthLabel[i] = new ColoredLabel("", COLORS[i]);
\r
138 monthLabel[i].setFont(DemoUtility.titleFont);
\r
140 // And the default calendar to use for this slot
\r
141 calendars[i] = CALENDARS[i].calendar;
\r
143 add(topPanel, calMenu[i], g, c, 5, 0);
\r
144 add(topPanel, monthLabel[i], g, c, GridBagConstraints.REMAINDER, 1);
\r
147 // Now add the next/previous year/month buttons:
\r
148 prevYear = new Button("<<");
\r
149 prevYear.addActionListener(new AddAction(Calendar.YEAR, -1));
\r
151 prevMonth = new Button("<");
\r
152 prevMonth.addActionListener(new AddAction(Calendar.MONTH, -1));
\r
154 gotoToday = new Button("Today");
\r
155 gotoToday.addActionListener( new ActionListener()
\r
157 public void actionPerformed(ActionEvent e) {
\r
158 calendarPanel.setDate( new Date() );
\r
163 nextMonth = new Button(">");
\r
164 nextMonth.addActionListener(new AddAction(Calendar.MONTH, 1));
\r
166 nextYear = new Button(">>");
\r
167 nextYear.addActionListener(new AddAction(Calendar.YEAR, 1));
\r
169 c.fill = GridBagConstraints.NONE;
\r
170 add(topPanel, prevYear, g, c, 1, 0);
\r
171 add(topPanel, prevMonth, g, c, 1, 0);
\r
172 add(topPanel, gotoToday, g, c, 1, 0);
\r
173 add(topPanel, nextMonth, g, c, 1, 0);
\r
174 add(topPanel, nextYear, g, c, 1, 0);
\r
176 // Now add the menu for selecting the display language
\r
177 Panel displayPanel = new Panel();
\r
179 displayMenu = new Choice();
\r
180 Locale defaultLocale = Locale.getDefault();
\r
181 int bestMatch = -1, thisMatch = -1;
\r
184 for (int i = 0; i < locales.length; i++) {
\r
186 locales[i].getLanguage().equals(locales[i-1].getLanguage()) ||
\r
187 i < locales.length - 1 &&
\r
188 locales[i].getLanguage().equals(locales[i+1].getLanguage()))
\r
190 displayMenu.addItem( locales[i].getDisplayName() );
\r
192 displayMenu.addItem( locales[i].getDisplayLanguage());
\r
195 thisMatch = DemoUtility.compareLocales(locales[i], defaultLocale);
\r
197 if (thisMatch >= bestMatch) {
\r
198 bestMatch = thisMatch;
\r
203 displayMenu.setBackground(DemoUtility.choiceColor);
\r
204 displayMenu.select(selectMe);
\r
206 displayMenu.addItemListener( new ItemListener()
\r
208 public void itemStateChanged(ItemEvent e) {
\r
209 Locale loc = locales[displayMenu.getSelectedIndex()];
\r
210 calendarPanel.setLocale( loc );
\r
211 monthFormat[0] = monthFormat[1] = null;
\r
217 Label l1 = new Label("Display Language:", Label.RIGHT);
\r
218 l1.setFont(DemoUtility.labelFont);
\r
220 displayPanel.setLayout(new FlowLayout());
\r
221 displayPanel.add(l1);
\r
222 displayPanel.add(displayMenu);
\r
225 c.fill = GridBagConstraints.NONE;
\r
226 c.anchor = GridBagConstraints.EAST;
\r
228 add(topPanel, displayPanel, g, c, GridBagConstraints.REMAINDER, 0);
\r
230 // The title, buttons, etc. go in a panel at the top of the window
\r
231 add("North", topPanel);
\r
233 // The copyright notice goes at the bottom of the window
\r
234 Label copyright = new Label(DemoUtility.copyright1, Label.LEFT);
\r
235 copyright.setFont(DemoUtility.creditFont);
\r
236 add("South", copyright);
\r
238 // Now create the big calendar panel and stick it in the middle
\r
239 calendarPanel = new CalendarPanel( locales[displayMenu.getSelectedIndex()] );
\r
240 add("Center", calendarPanel);
\r
242 for (int i = 0; i < 2; i++) {
\r
243 calendarPanel.setCalendar(i, calendars[i]);
\r
244 calendarPanel.setColor(i, COLORS[i]);
\r
251 private void updateMonthName()
\r
253 for (int i = 0; i < 2; i++) {
\r
255 if (monthFormat[i] == null) { // TODO: optimize
\r
256 DateFormat f = DateFormat.getDateTimeInstance(
\r
257 calendars[i], DateFormat.MEDIUM, -1,
\r
258 locales[displayMenu.getSelectedIndex()]);
\r
259 if (f instanceof com.ibm.icu.text.SimpleDateFormat) {
\r
260 com.ibm.icu.text.SimpleDateFormat f1 = (com.ibm.icu.text.SimpleDateFormat) f;
\r
261 f1.applyPattern("MMMM, yyyy G");
\r
262 f1.setTimeZone(new SimpleTimeZone(0, "UTC"));
\r
264 monthFormat[i] = f;
\r
266 } catch (ClassCastException e) {
\r
267 //hey {lw} - there's something wrong in this routine that cuases exceptions.
\r
268 System.out.println(e);
\r
271 monthLabel[i].setText( monthFormat[i].format( calendarPanel.firstOfMonth() ));
\r
276 * CalMenuListener responds to events in the two popup menus that select
\r
277 * the calendar systems to be used in the display. It figures out which
\r
278 * of the two menus the event occurred in and updates the corresponding
\r
279 * element of the calendars[] array to match the new selection.
\r
281 private class CalMenuListener implements ItemListener
\r
283 public void itemStateChanged(ItemEvent e)
\r
285 for (int i = 0; i < calMenu.length; i++)
\r
287 if (e.getItemSelectable() == calMenu[i])
\r
289 // We found the menu that the event happened in.
\r
290 // Figure out which new calendar they selected.
\r
291 Calendar newCal = CALENDARS[ calMenu[i].getSelectedIndex() ].calendar;
\r
293 if (newCal != calendars[i])
\r
295 // If any of the other menus are set to the same new calendar
\r
296 // we're about to use for this menu, set them to the current
\r
297 // calendar from *this* menu so we won't have two the same
\r
298 for (int j = 0; j < calendars.length; j++) {
\r
299 if (j != i && calendars[j] == newCal) {
\r
300 calendars[j] = calendars[i];
\r
301 calendarPanel.setCalendar(j, calendars[j]);
\r
302 monthFormat[j] = null;
\r
304 for (int k = 0; k < CALENDARS.length; k++) {
\r
305 if (calendars[j] == CALENDARS[k].calendar) {
\r
306 calMenu[j].select(k);
\r
312 // Now update this menu to use the new calendar the user selected
\r
313 calendars[i] = newCal;
\r
314 calendarPanel.setCalendar(i, newCal);
\r
315 monthFormat[i] = null;
\r
326 * AddAction handles the next/previous year/month buttons...
\r
328 private class AddAction implements ActionListener {
\r
329 AddAction(int field, int amount) {
\r
330 this.field = field;
\r
331 this.amount = amount;
\r
334 public void actionPerformed(ActionEvent e) {
\r
335 calendarPanel.add(field, amount);
\r
339 private int field, amount;
\r
343 * ColoredLabel is similar to java.awt.Label, with two differences:
\r
345 * - You can set its text color
\r
347 * - It draws text using drawString rather than using a host-specific
\r
348 * "Peer" object like AWT does. On 1.2, using drawString gives
\r
349 * us Bidi reordering for free.
\r
351 static private class ColoredLabel extends Component {
\r
353 * For serialization
\r
355 private static final long serialVersionUID = 5004484960341875722L;
\r
356 public ColoredLabel(String label) {
\r
360 public ColoredLabel(String label, Color c) {
\r
365 public void setText(String label) {
\r
370 public void setFont(Font f) {
\r
375 public void paint(Graphics g) {
\r
376 FontMetrics fm = g.getFontMetrics(font);
\r
378 Rectangle bounds = getBounds();
\r
382 g.drawString(text, fm.stringWidth("\u00a0"),
\r
383 bounds.height/2 + fm.getHeight()
\r
384 - fm.getAscent() + fm.getLeading()/2);
\r
387 public Dimension getPreferredSize() {
\r
388 return getMinimumSize();
\r
391 public Dimension getMinimumSize() {
\r
392 FontMetrics fm = getFontMetrics(font);
\r
394 return new Dimension( fm.stringWidth(text) + 2*fm.stringWidth("\u00a0"),
\r
395 fm.getHeight() + fm.getLeading()*2);
\r
399 Color color = Color.black;
\r
400 Font font = DemoUtility.labelFont;
\r
404 * Print out the error message while debugging this program.
\r
406 public void errorText(String s)
\r
410 System.out.println(s);
\r
414 class CalendarRec {
\r
415 public CalendarRec(String nameStr, Calendar cal)
\r
425 private final CalendarRec[] CALENDARS = {
\r
426 new CalendarRec("Gregorian Calendar", new GregorianCalendar()),
\r
427 new CalendarRec("Hebrew Calendar", new HebrewCalendar()),
\r
428 new CalendarRec("Islamic Calendar", makeIslamic(false)),
\r
429 new CalendarRec("Islamic Civil Calendar ", makeIslamic(true)),
\r
430 new CalendarRec("Buddhist Calendar", new BuddhistCalendar()),
\r
431 new CalendarRec("Japanese Calendar", new JapaneseCalendar()),
\r
434 static private final Calendar makeIslamic(boolean civil) {
\r
435 IslamicCalendar cal = new IslamicCalendar();
\r
436 cal.setCivil(civil);
\r
440 static final Color[] COLORS = { Color.blue, Color.black };
\r