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