blob: d64b6c33f19b6acc9fc79d149c4570dad75b7167 [file] [log] [blame]
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
*******************************************************************************
* Copyright (C) 1997-2007, International Business Machines Corporation and *
* others. All Rights Reserved. *
*******************************************************************************
*/
package com.ibm.icu.dev.demo.calendar;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Choice;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Date;
import java.util.Locale;
import com.ibm.icu.dev.demo.impl.DemoApplet;
import com.ibm.icu.dev.demo.impl.DemoUtility;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.util.BuddhistCalendar;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.GregorianCalendar;
import com.ibm.icu.util.HebrewCalendar;
import com.ibm.icu.util.IslamicCalendar;
import com.ibm.icu.util.JapaneseCalendar;
import com.ibm.icu.util.SimpleTimeZone;
/**
* A Frame is a top-level window with a title. The default layout for a frame
* is BorderLayout. The CalendarFrame class defines the window layout of
* CalendarDemo.
*/
class CalendarFrame extends Frame
{
/**
* For serialization
*/
private static final long serialVersionUID = -4289697663503820619L;
private static final boolean DEBUG = false;
private DemoApplet applet;
/**
* Constructs a new CalendarFrame that is initially invisible.
*/
public CalendarFrame(DemoApplet myApplet)
{
super("Calendar Demo");
this.applet = myApplet;
init();
// When the window is closed, we want to shut down the applet or application
addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
setVisible(false);
dispose();
if (applet != null) {
applet.demoClosed();
} else System.exit(0);
}
} );
}
private Choice displayMenu;
private Locale[] locales = DemoUtility.getG7Locales();
private Calendar calendars[] = new Calendar[2];
private Choice calMenu[] = new Choice[2];
private ColoredLabel monthLabel[] = new ColoredLabel[2];
private DateFormat monthFormat[] = new DateFormat[2];
private Button prevYear;
private Button prevMonth;
private Button gotoToday;
private Button nextMonth;
private Button nextYear;
private CalendarPanel calendarPanel;
private static void add(Container container, Component component,
GridBagLayout g, GridBagConstraints c,
int gridwidth, int weightx)
{
c.gridwidth = gridwidth;
c.weightx = weightx;
g.setConstraints(component, c);
container.add(component);
}
/**
* Initializes the applet. You never need to call this directly, it
* is called automatically by the system once the applet is created.
*/
public void init() {
setBackground(DemoUtility.bgColor);
setLayout(new BorderLayout(10,10));
Panel topPanel = new Panel();
GridBagLayout g = new GridBagLayout();
topPanel.setLayout(g);
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
// Build the two menus for selecting which calendar is displayed,
// plus the month/year label for each calendar
for (int i = 0; i < 2; i++) {
calMenu[i] = new Choice();
for (int j = 0; j < CALENDARS.length; j++) {
calMenu[i].addItem(CALENDARS[j].name);
}
calMenu[i].setBackground(DemoUtility.choiceColor);
calMenu[i].select(i);
calMenu[i].addItemListener(new CalMenuListener());
// Label for the current month name
monthLabel[i] = new ColoredLabel("", COLORS[i]);
monthLabel[i].setFont(DemoUtility.titleFont);
// And the default calendar to use for this slot
calendars[i] = CALENDARS[i].calendar;
add(topPanel, calMenu[i], g, c, 5, 0);
add(topPanel, monthLabel[i], g, c, GridBagConstraints.REMAINDER, 1);
}
// Now add the next/previous year/month buttons:
prevYear = new Button("<<");
prevYear.addActionListener(new AddAction(Calendar.YEAR, -1));
prevMonth = new Button("<");
prevMonth.addActionListener(new AddAction(Calendar.MONTH, -1));
gotoToday = new Button("Today");
gotoToday.addActionListener( new ActionListener()
{
public void actionPerformed(ActionEvent e) {
calendarPanel.setDate( new Date() );
updateMonthName();
}
} );
nextMonth = new Button(">");
nextMonth.addActionListener(new AddAction(Calendar.MONTH, 1));
nextYear = new Button(">>");
nextYear.addActionListener(new AddAction(Calendar.YEAR, 1));
c.fill = GridBagConstraints.NONE;
add(topPanel, prevYear, g, c, 1, 0);
add(topPanel, prevMonth, g, c, 1, 0);
add(topPanel, gotoToday, g, c, 1, 0);
add(topPanel, nextMonth, g, c, 1, 0);
add(topPanel, nextYear, g, c, 1, 0);
// Now add the menu for selecting the display language
Panel displayPanel = new Panel();
{
displayMenu = new Choice();
Locale defaultLocale = Locale.getDefault();
int bestMatch = -1, thisMatch = -1;
int selectMe = 0;
for (int i = 0; i < locales.length; i++) {
if (i > 0 &&
locales[i].getLanguage().equals(locales[i-1].getLanguage()) ||
i < locales.length - 1 &&
locales[i].getLanguage().equals(locales[i+1].getLanguage()))
{
displayMenu.addItem( locales[i].getDisplayName() );
} else {
displayMenu.addItem( locales[i].getDisplayLanguage());
}
thisMatch = DemoUtility.compareLocales(locales[i], defaultLocale);
if (thisMatch >= bestMatch) {
bestMatch = thisMatch;
selectMe = i;
}
}
displayMenu.setBackground(DemoUtility.choiceColor);
displayMenu.select(selectMe);
displayMenu.addItemListener( new ItemListener()
{
public void itemStateChanged(ItemEvent e) {
Locale loc = locales[displayMenu.getSelectedIndex()];
calendarPanel.setLocale( loc );
monthFormat[0] = monthFormat[1] = null;
updateMonthName();
repaint();
}
} );
Label l1 = new Label("Display Language:", Label.RIGHT);
l1.setFont(DemoUtility.labelFont);
displayPanel.setLayout(new FlowLayout());
displayPanel.add(l1);
displayPanel.add(displayMenu);
}
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.EAST;
add(topPanel, displayPanel, g, c, GridBagConstraints.REMAINDER, 0);
// The title, buttons, etc. go in a panel at the top of the window
add("North", topPanel);
// The copyright notice goes at the bottom of the window
Label copyright = new Label(DemoUtility.copyright1, Label.LEFT);
copyright.setFont(DemoUtility.creditFont);
add("South", copyright);
// Now create the big calendar panel and stick it in the middle
calendarPanel = new CalendarPanel( locales[displayMenu.getSelectedIndex()] );
add("Center", calendarPanel);
for (int i = 0; i < 2; i++) {
calendarPanel.setCalendar(i, calendars[i]);
calendarPanel.setColor(i, COLORS[i]);
}
updateMonthName();
}
private void updateMonthName()
{
for (int i = 0; i < 2; i++) {
try {
if (monthFormat[i] == null) { // TODO: optimize
DateFormat f = DateFormat.getDateTimeInstance(
calendars[i], DateFormat.MEDIUM, -1,
locales[displayMenu.getSelectedIndex()]);
if (f instanceof com.ibm.icu.text.SimpleDateFormat) {
com.ibm.icu.text.SimpleDateFormat f1 = (com.ibm.icu.text.SimpleDateFormat) f;
f1.applyPattern("MMMM, yyyy G");
f1.setTimeZone(new SimpleTimeZone(0, "UTC"));
}
monthFormat[i] = f;
}
} catch (ClassCastException e) {
//hey {lw} - there's something wrong in this routine that causes exceptions.
System.out.println(e);
}
monthLabel[i].setText( monthFormat[i].format( calendarPanel.firstOfMonth() ));
}
}
/**
* CalMenuListener responds to events in the two popup menus that select
* the calendar systems to be used in the display. It figures out which
* of the two menus the event occurred in and updates the corresponding
* element of the calendars[] array to match the new selection.
*/
private class CalMenuListener implements ItemListener
{
public void itemStateChanged(ItemEvent e)
{
for (int i = 0; i < calMenu.length; i++)
{
if (e.getItemSelectable() == calMenu[i])
{
// We found the menu that the event happened in.
// Figure out which new calendar they selected.
Calendar newCal = CALENDARS[ calMenu[i].getSelectedIndex() ].calendar;
if (newCal != calendars[i])
{
// If any of the other menus are set to the same new calendar
// we're about to use for this menu, set them to the current
// calendar from *this* menu so we won't have two the same
for (int j = 0; j < calendars.length; j++) {
if (j != i && calendars[j] == newCal) {
calendars[j] = calendars[i];
calendarPanel.setCalendar(j, calendars[j]);
monthFormat[j] = null;
for (int k = 0; k < CALENDARS.length; k++) {
if (calendars[j] == CALENDARS[k].calendar) {
calMenu[j].select(k);
break;
}
}
}
}
// Now update this menu to use the new calendar the user selected
calendars[i] = newCal;
calendarPanel.setCalendar(i, newCal);
monthFormat[i] = null;
updateMonthName();
}
break;
}
}
}
}
/**
* AddAction handles the next/previous year/month buttons...
*/
private class AddAction implements ActionListener {
AddAction(int field, int amount) {
this.field = field;
this.amount = amount;
}
public void actionPerformed(ActionEvent e) {
calendarPanel.add(field, amount);
updateMonthName();
}
private int field, amount;
}
/**
* ColoredLabel is similar to java.awt.Label, with two differences:
*
* - You can set its text color
*
* - It draws text using drawString rather than using a host-specific
* "Peer" object like AWT does. On 1.2, using drawString gives
* us Bidi reordering for free.
*/
static private class ColoredLabel extends Component {
/**
* For serialization
*/
private static final long serialVersionUID = 5004484960341875722L;
public ColoredLabel(String label) {
text = label;
}
public ColoredLabel(String label, Color c) {
text = label;
color = c;
}
public void setText(String label) {
text = label;
repaint();
}
public void setFont(Font f) {
font = f;
repaint();
}
public void paint(Graphics g) {
FontMetrics fm = g.getFontMetrics(font);
Rectangle bounds = getBounds();
g.setColor(color);
g.setFont(font);
g.drawString(text, fm.stringWidth("\u00a0"),
bounds.height/2 + fm.getHeight()
- fm.getAscent() + fm.getLeading()/2);
}
public Dimension getPreferredSize() {
return getMinimumSize();
}
public Dimension getMinimumSize() {
FontMetrics fm = getFontMetrics(font);
return new Dimension( fm.stringWidth(text) + 2*fm.stringWidth("\u00a0"),
fm.getHeight() + fm.getLeading()*2);
}
String text;
Color color = Color.black;
Font font = DemoUtility.labelFont;
}
/**
* Print out the error message while debugging this program.
*/
public void errorText(String s)
{
if (DEBUG)
{
System.out.println(s);
}
}
class CalendarRec {
public CalendarRec(String nameStr, Calendar cal)
{
name = nameStr;
calendar = cal;
}
Calendar calendar;
String name;
}
private final CalendarRec[] CALENDARS = {
new CalendarRec("Gregorian Calendar", new GregorianCalendar()),
new CalendarRec("Hebrew Calendar", new HebrewCalendar()),
new CalendarRec("Islamic Calendar", makeIslamic(false)),
new CalendarRec("Islamic Civil Calendar ", makeIslamic(true)),
new CalendarRec("Buddhist Calendar", new BuddhistCalendar()),
new CalendarRec("Japanese Calendar", new JapaneseCalendar()),
};
static private final Calendar makeIslamic(boolean civil) {
IslamicCalendar cal = new IslamicCalendar();
cal.setCivil(civil);
return cal;
}
static final Color[] COLORS = { Color.blue, Color.black };
}