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-2008, 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.Button; 13 import java.awt.Checkbox; 14 import java.awt.CheckboxGroup; 15 import java.awt.Choice; 16 import java.awt.Component; 17 import java.awt.Container; 18 import java.awt.FlowLayout; 19 import java.awt.Font; 20 import java.awt.Frame; 21 import java.awt.GridLayout; 22 import java.awt.Label; 23 import java.awt.Panel; 24 import java.awt.TextField; 25 import java.awt.event.ActionEvent; 26 import java.awt.event.ActionListener; 27 import java.awt.event.ItemEvent; 28 import java.awt.event.ItemListener; 29 import java.awt.event.KeyEvent; 30 import java.awt.event.WindowEvent; 31 import java.text.ParsePosition; 32 import java.util.Date; 33 import java.util.Locale; 34 35 import javax.swing.JTextField; 36 37 import com.ibm.icu.dev.demo.impl.DemoApplet; 38 import com.ibm.icu.dev.demo.impl.DemoUtility; 39 import com.ibm.icu.text.DateFormat; 40 import com.ibm.icu.text.SimpleDateFormat; 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.TimeZone; 48 49 /** 50 * CalendarCalc demonstrates how Date/Time formatter works. 51 */ 52 public class CalendarCalc extends DemoApplet 53 { 54 /** 55 * For serialization 56 */ 57 private static final long serialVersionUID = 4540103433916539296L; 58 59 /** 60 * The main function which defines the behavior of the MultiCalendarDemo 61 * applet when an applet is started. 62 */ 63 public static void main(String argv[]) { 64 new CalendarCalc().showDemo(); 65 } 66 67 /** 68 * This creates a CalendarCalcFrame for the demo applet. 69 */ 70 public Frame createDemoFrame(DemoApplet applet) { 71 return new CalendarCalcFrame(applet); 72 } 73 } 74 75 /** 76 * A Frame is a top-level window with a title. The default layout for a frame 77 * is BorderLayout. The CalendarCalcFrame class defines the window layout of 78 * MultiCalendarDemo. 79 */ 80 class CalendarCalcFrame extends Frame implements ActionListener 81 { 82 /** 83 * For serialization 84 */ 85 private static final long serialVersionUID = 8901485296258761846L; 86 87 static final Locale[] locales = DemoUtility.getG7Locales(); 88 89 private DemoApplet applet; 90 private long time = System.currentTimeMillis(); 91 92 private static final RollAddField kRollAddFields[] = { 93 new RollAddField(Calendar.YEAR, "Year" ), 94 new RollAddField(Calendar.MONTH, "Month" ), 95 new RollAddField(Calendar.WEEK_OF_MONTH, "Week of Month" ), 96 new RollAddField(Calendar.WEEK_OF_YEAR, "Week of Year" ), 97 new RollAddField(Calendar.DAY_OF_MONTH, "Day of Month" ), 98 new RollAddField(Calendar.DAY_OF_WEEK, "Day of Week" ), 99 new RollAddField(Calendar.DAY_OF_WEEK_IN_MONTH, "Day of Week in Month" ), 100 new RollAddField(Calendar.DAY_OF_YEAR, "Day of Year" ), 101 new RollAddField(Calendar.AM_PM, "AM/PM" ), 102 new RollAddField(Calendar.HOUR_OF_DAY, "Hour of day" ), 103 new RollAddField(Calendar.HOUR, "Hour" ), 104 new RollAddField(Calendar.MINUTE, "Minute" ), 105 new RollAddField(Calendar.SECOND, "Second" ), 106 }; 107 108 /** 109 * Constructs a new CalendarCalcFrame that is initially invisible. 110 */ 111 public CalendarCalcFrame(DemoApplet applet) 112 { 113 super("Multiple Calendar Demo"); 114 this.applet = applet; 115 init(); 116 start(); 117 } 118 119 /** 120 * Initializes the applet. You never need to call this directly, it 121 * is called automatically by the system once the applet is created. 122 */ 123 public void init() 124 { 125 buildGUI(); 126 127 patternText.setText( calendars[0].toPattern() ); 128 129 // Force an update of the display 130 cityChanged(); 131 millisFormat(); 132 enableEvents(KeyEvent.KEY_RELEASED); 133 enableEvents(WindowEvent.WINDOW_CLOSING); 134 } 135 136 //------------------------------------------------------------ 137 // package private 138 //------------------------------------------------------------ 139 void addWithFont(Container container, Component foo, Font font) { 140 if (font != null) 141 foo.setFont(font); 142 container.add(foo); 143 } 144 145 /** 146 * Called to start the applet. You never need to call this method 147 * directly, it is called when the applet's document is visited. 148 */ 149 public void start() 150 { 151 // do nothing 152 } 153 154 TextField patternText; 155 156 Choice dateMenu; 157 Choice localeMenu; 158 159 Button up; 160 Button down; 161 162 Checkbox getRoll; 163 Checkbox getAdd; 164 165 public void buildGUI() 166 { 167 setBackground(DemoUtility.bgColor); 168 setLayout(new FlowLayout()); // shouldn't be necessary, but it is. 169 170 // TITLE 171 Label label1=new Label("Calendar Converter", Label.CENTER); 172 label1.setFont(DemoUtility.titleFont); 173 add(label1); 174 add(DemoUtility.createSpacer()); 175 176 // IO Panel 177 Panel topPanel = new Panel(); 178 topPanel.setLayout(new FlowLayout()); 179 180 CheckboxGroup group1= new CheckboxGroup(); 181 182 // Set up the controls for each calendar we're demonstrating 183 for (int i = 0; i < calendars.length; i++) 184 { 185 Label label = new Label(calendars[i].name, Label.RIGHT); 186 label.setFont(DemoUtility.labelFont); 187 topPanel.add(label); 188 189 topPanel.add(calendars[i].text); 190 191 final int j = i; 192 calendars[i].text.addActionListener( new ActionListener() { 193 public void actionPerformed(ActionEvent e) { 194 textChanged(j); 195 } 196 } ); 197 198 calendars[i].rollAdd.setCheckboxGroup(group1); 199 topPanel.add(calendars[i].rollAdd); 200 } 201 calendars[0].rollAdd.setState(true); // Make the first one selected 202 203 Label label4=new Label("Pattern", Label.RIGHT); 204 label4.setFont(DemoUtility.labelFont); 205 topPanel.add(label4); 206 207 patternText=new TextField(FIELD_COLUMNS); 208 patternText.setFont(DemoUtility.editFont); 209 topPanel.add(patternText); 210 topPanel.add(new Label("")); 211 212 DemoUtility.fixGrid(topPanel,3); 213 add(topPanel); 214 add(DemoUtility.createSpacer()); 215 216 // ROLL / ADD 217 Panel rollAddPanel=new Panel(); 218 { 219 rollAddPanel.setLayout(new FlowLayout()); 220 221 Panel rollAddBoxes = new Panel(); 222 { 223 rollAddBoxes.setLayout(new GridLayout(2,1)); 224 CheckboxGroup group2= new CheckboxGroup(); 225 getRoll = new Checkbox("Roll",group2, false); 226 getAdd = new Checkbox("Add",group2, true); 227 228 rollAddBoxes.add(getRoll); 229 rollAddBoxes.add(getAdd); 230 } 231 232 Label dateLabel=new Label("Date Fields"); 233 dateLabel.setFont(DemoUtility.labelFont); 234 235 dateMenu= new Choice(); 236 dateMenu.setBackground(DemoUtility.choiceColor); 237 for (int i = 0; i < kRollAddFields.length; i++) { 238 dateMenu.addItem(kRollAddFields[i].name); 239 if (kRollAddFields[i].field == Calendar.MONTH) { 240 dateMenu.select(i); 241 } 242 } 243 244 Panel upDown = new Panel(); 245 { 246 upDown.setLayout(new GridLayout(2,1)); 247 248 // *** If the images are not found, we use the label. 249 up = new Button("^"); 250 down = new Button("v"); 251 up.setBackground(DemoUtility.bgColor); 252 down.setBackground(DemoUtility.bgColor); 253 upDown.add(up); 254 upDown.add(down); 255 up.addActionListener(this); 256 down.addActionListener(this); 257 } 258 259 rollAddPanel.add(dateLabel); 260 rollAddPanel.add(dateMenu); 261 rollAddPanel.add(rollAddBoxes); 262 rollAddPanel.add(upDown); 263 264 } 265 Panel localePanel = new Panel(); 266 { 267 // Make the locale popup menus 268 localeMenu= new Choice(); 269 Locale defaultLocale = Locale.getDefault(); 270 int bestMatch = -1, thisMatch = -1; 271 int selectMe = 0; 272 273 for (int i = 0; i < locales.length; i++) { 274 if (i > 0 && locales[i].getLanguage().equals(locales[i-1].getLanguage()) || 275 i < locales.length - 1 && 276 locales[i].getLanguage().equals(locales[i+1].getLanguage())) 277 { 278 localeMenu.addItem( locales[i].getDisplayName() ); 279 } else { 280 localeMenu.addItem( locales[i].getDisplayLanguage()); 281 } 282 283 thisMatch = DemoUtility.compareLocales(locales[i], defaultLocale); 284 285 if (thisMatch >= bestMatch) { 286 bestMatch = thisMatch; 287 selectMe = i; 288 } 289 } 290 291 localeMenu.setBackground(DemoUtility.choiceColor); 292 localeMenu.select(selectMe); 293 294 Label localeLabel =new Label("Display Locale"); 295 localeLabel.setFont(DemoUtility.labelFont); 296 297 localePanel.add(localeLabel); 298 localePanel.add(localeMenu); 299 DemoUtility.fixGrid(localePanel,2); 300 301 localeMenu.addItemListener( new ItemListener() { 302 public void itemStateChanged(ItemEvent e) { 303 Locale loc = locales[localeMenu.getSelectedIndex()]; 304 System.out.println("Change locale to " + loc.getDisplayName()); 305 306 for (int i = 0; i < calendars.length; i++) { 307 calendars[i].setLocale(loc); 308 } 309 millisFormat(); 310 } 311 } ); 312 } 313 add(rollAddPanel); 314 add(DemoUtility.createSpacer()); 315 add(localePanel); 316 add(DemoUtility.createSpacer()); 317 318 // COPYRIGHT 319 Panel copyrightPanel = new Panel(); 320 addWithFont (copyrightPanel,new Label(DemoUtility.copyright1, Label.LEFT), 321 DemoUtility.creditFont); 322 DemoUtility.fixGrid(copyrightPanel,1); 323 add(copyrightPanel); 324 } 325 326 /** 327 * This function is called when users change the pattern text. 328 */ 329 public void setFormatFromPattern() { 330 String timePattern = patternText.getText(); 331 332 for (int i = 0; i < calendars.length; i++) { 333 calendars[i].applyPattern(timePattern); 334 } 335 336 millisFormat(); 337 } 338 339 /** 340 * This function is called when it is necessary to parse the time 341 * string in one of the formatted date fields 342 */ 343 public void textChanged(int index) { 344 String rightString = calendars[index].text.getText(); 345 346 ParsePosition status = new ParsePosition(0); 347 348 if (rightString.length() == 0) 349 { 350 errorText("Error: no input to parse!"); 351 return; 352 } 353 354 try { 355 Date date = calendars[index].format.parse(rightString, status); 356 time = date.getTime(); 357 } 358 catch (Exception e) { 359 for (int i = 0; i < calendars.length; i++) { 360 if (i != index) { 361 calendars[i].text.setText("ERROR"); 362 } 363 } 364 errorText("Exception: " + e.getClass().toString() + " parsing: "+rightString); 365 return; 366 } 367 368 int start = calendars[index].text.getSelectionStart(); 369 int end = calendars[index].text.getSelectionEnd(); 370 371 millisFormat(); 372 373 calendars[index].text.select(start,end); 374 } 375 376 /** 377 * This function is called when it is necessary to format the time 378 * in the "Millis" text field. 379 */ 380 public void millisFormat() { 381 String out = ""; 382 383 for (int i = 0; i < calendars.length; i++) { 384 try { 385 out = calendars[i].format.format(new Date(time)); 386 calendars[i].text.setText(out); 387 } 388 catch (Exception e) { 389 calendars[i].text.setText("ERROR"); 390 errorText("Exception: " + e.getClass().toString() + " formatting " 391 + calendars[i].name + " " + time); 392 } 393 } 394 } 395 396 397 /** 398 * This function is called when users change the pattern text. 399 */ 400 public void patternTextChanged() { 401 setFormatFromPattern(); 402 } 403 404 /** 405 * This function is called when users select a new representative city. 406 */ 407 public void cityChanged() { 408 TimeZone timeZone = TimeZone.getDefault(); 409 410 for (int i = 0; i < calendars.length; i++) { 411 calendars[i].format.setTimeZone(timeZone); 412 } 413 millisFormat(); 414 } 415 416 /** 417 * This function is called when users select a new time field 418 * to add or roll its value. 419 */ 420 public void dateFieldChanged(boolean isUp) { 421 int field = kRollAddFields[dateMenu.getSelectedIndex()].field; 422 423 for (int i = 0; i < calendars.length; i++) 424 { 425 if (calendars[i].rollAdd.getState()) 426 { 427 Calendar c = calendars[i].calendar; 428 c.setTime(new Date(time)); 429 430 if (getAdd.getState()) { 431 c.add(field, isUp ? 1 : -1); 432 } else { 433 c.roll(field, isUp); 434 } 435 436 time = c.getTime().getTime(); 437 millisFormat(); 438 break; 439 } 440 } 441 } 442 443 /** 444 * Print out the error message while debugging this program. 445 */ 446 public void errorText(String s) 447 { 448 if (true) { 449 System.out.println(s); 450 } 451 } 452 453 /** 454 * Called if an action occurs in the CalendarCalcFrame object. 455 */ 456 public void actionPerformed(ActionEvent evt) 457 { 458 // *** Button events are handled here. 459 Object obj = evt.getSource(); 460 System.out.println("action " + obj); 461 if (obj instanceof Button) { 462 if (evt.getSource() == up) { 463 dateFieldChanged(false); 464 } else 465 if (evt.getSource() == down) { 466 dateFieldChanged(true); 467 } 468 } 469 } 470 471 /** 472 * Handles the event. Returns true if the event is handled and should not 473 * be passed to the parent of this component. The default event handler 474 * calls some helper methods to make life easier on the programmer. 475 */ 476 protected void processKeyEvent(KeyEvent evt) 477 { 478 System.out.println("key " + evt); 479 if (evt.getID() == KeyEvent.KEY_RELEASED) { 480 if (evt.getSource() == patternText) { 481 patternTextChanged(); 482 } 483 else { 484 for (int i = 0; i < calendars.length; i++) { 485 if (evt.getSource() == calendars[i].text) { 486 textChanged(i); 487 } 488 } 489 } 490 } 491 } 492 493 protected void processWindowEvent(WindowEvent evt) 494 { 495 System.out.println("window " + evt); 496 if (evt.getID() == WindowEvent.WINDOW_CLOSING && 497 evt.getSource() == this) { 498 this.hide(); 499 this.dispose(); 500 501 if (applet != null) { 502 applet.demoClosed(); 503 } else System.exit(0); 504 } 505 } 506 507 /* 508 protected void processEvent(AWTEvent evt) 509 { 510 if (evt.getID() == AWTEvent. Event.ACTION_EVENT && evt.target == up) { 511 dateFieldChanged(true); 512 return true; 513 } 514 else if (evt.id == Event.ACTION_EVENT && evt.target == down) { 515 dateFieldChanged(false); 516 return true; 517 } 518 } 519 */ 520 521 private static final int FIELD_COLUMNS = 35; 522 523 524 class CalendarRec { 525 public CalendarRec(String nameStr, Calendar cal) 526 { 527 name = nameStr; 528 calendar = cal; 529 rollAdd = new Checkbox(); 530 531 text = new JTextField("",FIELD_COLUMNS); 532 text.setFont(DemoUtility.editFont); 533 534 format = DateFormat.getDateInstance(cal, DateFormat.FULL, 535 Locale.getDefault()); 536 //format.applyPattern(DEFAULT_FORMAT); 537 } 538 539 public void setLocale(Locale loc) { 540 String pattern = toPattern(); 541 542 format = DateFormat.getDateInstance(calendar, DateFormat.FULL, 543 loc); 544 applyPattern(pattern); 545 } 546 547 public void applyPattern(String pattern) { 548 if (format instanceof SimpleDateFormat) { 549 ((SimpleDateFormat)format).applyPattern(pattern); 550 //hey {al} - 551 // } else if (format instanceof java.text.SimpleDateFormat) { 552 // ((java.text.SimpleDateFormat)format).applyPattern(pattern); 553 } 554 } 555 556 private String toPattern() { 557 if (format instanceof SimpleDateFormat) { 558 return ((SimpleDateFormat)format).toPattern(); 559 //hey {al} - 560 // } else if (format instanceof java.text.SimpleDateFormat) { 561 // return ((java.text.SimpleDateFormat)format).toPattern(); 562 } 563 return ""; 564 } 565 566 Calendar calendar; 567 DateFormat format; 568 String name; 569 JTextField text; 570 Checkbox rollAdd; 571 } 572 573 private final CalendarRec[] calendars = { 574 new CalendarRec("Gregorian", new GregorianCalendar()), 575 new CalendarRec("Hebrew", new HebrewCalendar()), 576 new CalendarRec("Islamic (civil)", makeIslamic(true)), 577 new CalendarRec("Islamic (true)", makeIslamic(false)), 578 new CalendarRec("Buddhist", new BuddhistCalendar()), 579 new CalendarRec("Japanese", new JapaneseCalendar()), 580 // new CalendarRec("Chinese", new ChineseCalendar()), 581 }; 582 583 static private final Calendar makeIslamic(boolean civil) { 584 IslamicCalendar cal = new IslamicCalendar(); 585 cal.setCivil(civil); 586 return cal; 587 } 588 } 589 590 class RollAddField { 591 RollAddField(int field, String name) { 592 this.field = field; 593 this.name = name; 594 } 595 int field; 596 String name; 597 } 598