001: /*
002: *******************************************************************************
003: * Copyright (C) 1997-2005, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *******************************************************************************
006: */
007:
008: package com.ibm.icu.dev.demo.calendar;
009:
010: import java.awt.BorderLayout;
011: import java.awt.Button;
012: import java.awt.Choice;
013: import java.awt.Color;
014: import java.awt.Component;
015: import java.awt.Container;
016: import java.awt.Dimension;
017: import java.awt.FlowLayout;
018: import java.awt.Font;
019: import java.awt.FontMetrics;
020: import java.awt.Frame;
021: import java.awt.Graphics;
022: import java.awt.GridBagConstraints;
023: import java.awt.GridBagLayout;
024: import java.awt.Label;
025: import java.awt.Panel;
026: import java.awt.Rectangle;
027: import java.awt.event.ActionEvent;
028: import java.awt.event.ActionListener;
029: import java.awt.event.ItemEvent;
030: import java.awt.event.ItemListener;
031: import java.awt.event.WindowAdapter;
032: import java.awt.event.WindowEvent;
033: import java.util.Date;
034: import java.util.Locale;
035:
036: import com.ibm.icu.dev.demo.impl.DemoApplet;
037: import com.ibm.icu.dev.demo.impl.DemoUtility;
038: import com.ibm.icu.text.DateFormat;
039: import com.ibm.icu.util.BuddhistCalendar;
040: import com.ibm.icu.util.Calendar;
041: import com.ibm.icu.util.GregorianCalendar;
042: import com.ibm.icu.util.HebrewCalendar;
043: import com.ibm.icu.util.IslamicCalendar;
044: import com.ibm.icu.util.JapaneseCalendar;
045: import com.ibm.icu.util.SimpleTimeZone;
046:
047: /**
048: * A Frame is a top-level window with a title. The default layout for a frame
049: * is BorderLayout. The CalendarFrame class defines the window layout of
050: * CalendarDemo.
051: */
052: class CalendarFrame extends Frame {
053: private static final boolean DEBUG = false;
054:
055: private DemoApplet applet;
056:
057: /**
058: * Constructs a new CalendarFrame that is initially invisible.
059: */
060: public CalendarFrame(DemoApplet myApplet) {
061: super ("Calendar Demo");
062: this .applet = myApplet;
063: init();
064:
065: // When the window is closed, we want to shut down the applet or application
066: addWindowListener(new WindowAdapter() {
067: public void windowClosing(WindowEvent e) {
068: setVisible(false);
069: dispose();
070:
071: if (applet != null) {
072: applet.demoClosed();
073: } else
074: System.exit(0);
075: }
076: });
077: }
078:
079: private Choice displayMenu;
080: private Locale[] locales = DemoUtility.getG7Locales();
081:
082: private Calendar calendars[] = new Calendar[2];
083: private Choice calMenu[] = new Choice[2];
084: private ColoredLabel monthLabel[] = new ColoredLabel[2];
085: private DateFormat monthFormat[] = new DateFormat[2];
086:
087: private Button prevYear;
088: private Button prevMonth;
089: private Button gotoToday;
090: private Button nextMonth;
091: private Button nextYear;
092: private CalendarPanel calendarPanel;
093:
094: private static void add(Container container, Component component,
095: GridBagLayout g, GridBagConstraints c, int gridwidth,
096: int weightx) {
097: c.gridwidth = gridwidth;
098: c.weightx = weightx;
099: g.setConstraints(component, c);
100: container.add(component);
101: }
102:
103: /**
104: * Initializes the applet. You never need to call this directly, it
105: * is called automatically by the system once the applet is created.
106: */
107: public void init() {
108: setBackground(DemoUtility.bgColor);
109: setLayout(new BorderLayout(10, 10));
110:
111: Panel topPanel = new Panel();
112: GridBagLayout g = new GridBagLayout();
113: topPanel.setLayout(g);
114: GridBagConstraints c = new GridBagConstraints();
115: c.fill = GridBagConstraints.HORIZONTAL;
116:
117: // Build the two menus for selecting which calendar is displayed,
118: // plus the month/year label for each calendar
119: for (int i = 0; i < 2; i++) {
120: calMenu[i] = new Choice();
121: for (int j = 0; j < CALENDARS.length; j++) {
122: calMenu[i].addItem(CALENDARS[j].name);
123: }
124: calMenu[i].setBackground(DemoUtility.choiceColor);
125: calMenu[i].select(i);
126: calMenu[i].addItemListener(new CalMenuListener());
127:
128: // Label for the current month name
129: monthLabel[i] = new ColoredLabel("", COLORS[i]);
130: monthLabel[i].setFont(DemoUtility.titleFont);
131:
132: // And the default calendar to use for this slot
133: calendars[i] = CALENDARS[i].calendar;
134:
135: add(topPanel, calMenu[i], g, c, 5, 0);
136: add(topPanel, monthLabel[i], g, c,
137: GridBagConstraints.REMAINDER, 1);
138: }
139:
140: // Now add the next/previous year/month buttons:
141: prevYear = new Button("<<");
142: prevYear.addActionListener(new AddAction(Calendar.YEAR, -1));
143:
144: prevMonth = new Button("<");
145: prevMonth.addActionListener(new AddAction(Calendar.MONTH, -1));
146:
147: gotoToday = new Button("Today");
148: gotoToday.addActionListener(new ActionListener() {
149: public void actionPerformed(ActionEvent e) {
150: calendarPanel.setDate(new Date());
151: updateMonthName();
152: }
153: });
154:
155: nextMonth = new Button(">");
156: nextMonth.addActionListener(new AddAction(Calendar.MONTH, 1));
157:
158: nextYear = new Button(">>");
159: nextYear.addActionListener(new AddAction(Calendar.YEAR, 1));
160:
161: c.fill = GridBagConstraints.NONE;
162: add(topPanel, prevYear, g, c, 1, 0);
163: add(topPanel, prevMonth, g, c, 1, 0);
164: add(topPanel, gotoToday, g, c, 1, 0);
165: add(topPanel, nextMonth, g, c, 1, 0);
166: add(topPanel, nextYear, g, c, 1, 0);
167:
168: // Now add the menu for selecting the display language
169: Panel displayPanel = new Panel();
170: {
171: displayMenu = new Choice();
172: Locale defaultLocale = Locale.getDefault();
173: int bestMatch = -1, this Match = -1;
174: int selectMe = 0;
175:
176: for (int i = 0; i < locales.length; i++) {
177: if (i > 0
178: && locales[i].getLanguage().equals(
179: locales[i - 1].getLanguage())
180: || i < locales.length - 1
181: && locales[i].getLanguage().equals(
182: locales[i + 1].getLanguage())) {
183: displayMenu.addItem(locales[i].getDisplayName());
184: } else {
185: displayMenu
186: .addItem(locales[i].getDisplayLanguage());
187: }
188:
189: this Match = DemoUtility.compareLocales(locales[i],
190: defaultLocale);
191:
192: if (this Match >= bestMatch) {
193: bestMatch = this Match;
194: selectMe = i;
195: }
196: }
197:
198: displayMenu.setBackground(DemoUtility.choiceColor);
199: displayMenu.select(selectMe);
200:
201: displayMenu.addItemListener(new ItemListener() {
202: public void itemStateChanged(ItemEvent e) {
203: Locale loc = locales[displayMenu.getSelectedIndex()];
204: calendarPanel.setLocale(loc);
205: monthFormat[0] = monthFormat[1] = null;
206: updateMonthName();
207: repaint();
208: }
209: });
210:
211: Label l1 = new Label("Display Language:", Label.RIGHT);
212: l1.setFont(DemoUtility.labelFont);
213:
214: displayPanel.setLayout(new FlowLayout());
215: displayPanel.add(l1);
216: displayPanel.add(displayMenu);
217:
218: }
219: c.fill = GridBagConstraints.NONE;
220: c.anchor = GridBagConstraints.EAST;
221:
222: add(topPanel, displayPanel, g, c, GridBagConstraints.REMAINDER,
223: 0);
224:
225: // The title, buttons, etc. go in a panel at the top of the window
226: add("North", topPanel);
227:
228: // The copyright notice goes at the bottom of the window
229: Label copyright = new Label(DemoUtility.copyright1, Label.LEFT);
230: copyright.setFont(DemoUtility.creditFont);
231: add("South", copyright);
232:
233: // Now create the big calendar panel and stick it in the middle
234: calendarPanel = new CalendarPanel(locales[displayMenu
235: .getSelectedIndex()]);
236: add("Center", calendarPanel);
237:
238: for (int i = 0; i < 2; i++) {
239: calendarPanel.setCalendar(i, calendars[i]);
240: calendarPanel.setColor(i, COLORS[i]);
241: }
242:
243: updateMonthName();
244: }
245:
246: private void updateMonthName() {
247: for (int i = 0; i < 2; i++) {
248: try {
249: if (monthFormat[i] == null) { // TODO: optimize
250: DateFormat f = DateFormat.getDateTimeInstance(
251: calendars[i], DateFormat.MEDIUM, -1,
252: locales[displayMenu.getSelectedIndex()]);
253: if (f instanceof com.ibm.icu.text.SimpleDateFormat) {
254: com.ibm.icu.text.SimpleDateFormat f1 = (com.ibm.icu.text.SimpleDateFormat) f;
255: f1.applyPattern("MMMM, yyyy G");
256: f1.setTimeZone(new SimpleTimeZone(0, "UTC"));
257: }
258: monthFormat[i] = f;
259: }
260: } catch (ClassCastException e) {
261: //hey {lw} - there's something wrong in this routine that cuases exceptions.
262: System.out.println(e);
263: }
264:
265: monthLabel[i].setText(monthFormat[i].format(calendarPanel
266: .firstOfMonth()));
267: }
268: }
269:
270: /**
271: * CalMenuListener responds to events in the two popup menus that select
272: * the calendar systems to be used in the display. It figures out which
273: * of the two menus the event occurred in and updates the corresponding
274: * element of the calendars[] array to match the new selection.
275: */
276: private class CalMenuListener implements ItemListener {
277: public void itemStateChanged(ItemEvent e) {
278: for (int i = 0; i < calMenu.length; i++) {
279: if (e.getItemSelectable() == calMenu[i]) {
280: // We found the menu that the event happened in.
281: // Figure out which new calendar they selected.
282: Calendar newCal = CALENDARS[calMenu[i]
283: .getSelectedIndex()].calendar;
284:
285: if (newCal != calendars[i]) {
286: // If any of the other menus are set to the same new calendar
287: // we're about to use for this menu, set them to the current
288: // calendar from *this* menu so we won't have two the same
289: for (int j = 0; j < calendars.length; j++) {
290: if (j != i && calendars[j] == newCal) {
291: calendars[j] = calendars[i];
292: calendarPanel.setCalendar(j,
293: calendars[j]);
294: monthFormat[j] = null;
295:
296: for (int k = 0; k < CALENDARS.length; k++) {
297: if (calendars[j] == CALENDARS[k].calendar) {
298: calMenu[j].select(k);
299: break;
300: }
301: }
302: }
303: }
304: // Now update this menu to use the new calendar the user selected
305: calendars[i] = newCal;
306: calendarPanel.setCalendar(i, newCal);
307: monthFormat[i] = null;
308:
309: updateMonthName();
310: }
311: break;
312: }
313: }
314: }
315: }
316:
317: /**
318: * AddAction handles the next/previous year/month buttons...
319: */
320: private class AddAction implements ActionListener {
321: AddAction(int field, int amount) {
322: this .field = field;
323: this .amount = amount;
324: }
325:
326: public void actionPerformed(ActionEvent e) {
327: calendarPanel.add(field, amount);
328: updateMonthName();
329: }
330:
331: private int field, amount;
332: }
333:
334: /**
335: * ColoredLabel is similar to java.awt.Label, with two differences:
336: *
337: * - You can set its text color
338: *
339: * - It draws text using drawString rather than using a host-specific
340: * "Peer" object like AWT does. On 1.2, using drawString gives
341: * us Bidi reordering for free.
342: */
343: static private class ColoredLabel extends Component {
344: public ColoredLabel(String label) {
345: text = label;
346: }
347:
348: public ColoredLabel(String label, Color c) {
349: text = label;
350: color = c;
351: }
352:
353: public void setText(String label) {
354: text = label;
355: repaint();
356: }
357:
358: public void setFont(Font f) {
359: font = f;
360: repaint();
361: }
362:
363: public void paint(Graphics g) {
364: FontMetrics fm = g.getFontMetrics(font);
365:
366: Rectangle bounds = getBounds();
367:
368: g.setColor(color);
369: g.setFont(font);
370: g.drawString(text, fm.stringWidth("\u00a0"), bounds.height
371: / 2 + fm.getHeight() - fm.getAscent()
372: + fm.getLeading() / 2);
373: }
374:
375: public Dimension getPreferredSize() {
376: return getMinimumSize();
377: }
378:
379: public Dimension getMinimumSize() {
380: FontMetrics fm = getFontMetrics(font);
381:
382: return new Dimension(fm.stringWidth(text) + 2
383: * fm.stringWidth("\u00a0"), fm.getHeight()
384: + fm.getLeading() * 2);
385: }
386:
387: String text;
388: Color color = Color.black;
389: Font font = DemoUtility.labelFont;
390: }
391:
392: /**
393: * Print out the error message while debugging this program.
394: */
395: public void errorText(String s) {
396: if (DEBUG) {
397: System.out.println(s);
398: }
399: }
400:
401: class CalendarRec {
402: public CalendarRec(String nameStr, Calendar cal) {
403: name = nameStr;
404: calendar = cal;
405: }
406:
407: Calendar calendar;
408: String name;
409: }
410:
411: private final CalendarRec[] CALENDARS = {
412: new CalendarRec("Gregorian Calendar",
413: new GregorianCalendar()),
414: new CalendarRec("Hebrew Calendar", new HebrewCalendar()),
415: new CalendarRec("Islamic Calendar", makeIslamic(false)),
416: new CalendarRec("Islamic Civil Calendar ",
417: makeIslamic(true)),
418: new CalendarRec("Buddhist Calendar", new BuddhistCalendar()),
419: new CalendarRec("Japanese Calendar", new JapaneseCalendar()), };
420:
421: static private final Calendar makeIslamic(boolean civil) {
422: IslamicCalendar cal = new IslamicCalendar();
423: cal.setCivil(civil);
424: return cal;
425: }
426:
427: static final Color[] COLORS = { Color.blue, Color.black };
428: }
|