1 /* 2 ******************************************************************************* 3 * Copyright (C) 1996-2010, International Business Machines Corporation and * 4 * others. All Rights Reserved. * 5 ******************************************************************************* 6 */ 7 package com.ibm.icu.dev.demo.rbnf; 8 9 import java.awt.BorderLayout; 10 import java.awt.Button; 11 import java.awt.CardLayout; 12 import java.awt.Checkbox; 13 import java.awt.Choice; 14 import java.awt.Component; 15 import java.awt.Dimension; 16 import java.awt.Font; 17 import java.awt.FontMetrics; 18 import java.awt.Frame; 19 import java.awt.Graphics; 20 import java.awt.GridLayout; 21 import java.awt.Panel; 22 import java.awt.ScrollPane; 23 import java.awt.TextArea; 24 import java.awt.TextComponent; 25 import java.awt.TextField; 26 import java.awt.event.ActionEvent; 27 import java.awt.event.ActionListener; 28 import java.awt.event.FocusAdapter; 29 import java.awt.event.FocusEvent; 30 import java.awt.event.FocusListener; 31 import java.awt.event.ItemEvent; 32 import java.awt.event.ItemListener; 33 import java.awt.event.KeyAdapter; 34 import java.awt.event.KeyEvent; 35 import java.awt.event.KeyListener; 36 import java.awt.event.TextEvent; 37 import java.awt.event.TextListener; 38 import java.awt.event.WindowAdapter; 39 import java.awt.event.WindowEvent; 40 import java.text.BreakIterator; 41 import java.text.DecimalFormat; 42 import java.text.ParsePosition; 43 import java.util.Locale; 44 45 import com.ibm.icu.dev.demo.impl.DemoApplet; 46 import com.ibm.icu.text.RuleBasedNumberFormat; 47 48 public class RbnfDemo extends DemoApplet { 49 /** 50 * For serialization 51 */ 52 private static final long serialVersionUID = -9119861296873763536L; 53 54 /** 55 * Puts a copyright in the .class file 56 */ 57 // private static final String copyrightNotice 58 // = "Copyright \u00a91997-1998 IBM Corp. All rights reserved."; 59 60 /* 61 * code to run the demo as an application 62 */ main(String[] argv)63 public static void main(String[] argv) { 64 new RbnfDemo().showDemo(); 65 } 66 getDefaultFrameSize(DemoApplet applet, Frame f)67 protected Dimension getDefaultFrameSize(DemoApplet applet, Frame f) { 68 return new Dimension(430,270); 69 } 70 createDemoFrame(DemoApplet applet)71 protected Frame createDemoFrame(DemoApplet applet) { 72 final Frame window = new Frame("Number Spellout Demo"); 73 window.setSize(800, 600); 74 window.setLayout(new BorderLayout()); 75 76 Panel mainPanel = new Panel(); 77 mainPanel.setLayout(new GridLayout(1,2)); 78 79 commentaryField = new TextArea("", 0, 0, TextArea.SCROLLBARS_VERTICAL_ONLY); 80 commentaryField.setSize(800, 50); 81 commentaryField.setText(RbnfSampleRuleSets.sampleRuleSetCommentary[0]); 82 commentaryField.setEditable(false); 83 commentaryField.setFont(new Font("Helvetica", Font.PLAIN, 14)); 84 85 spelloutFormatter = new RuleBasedNumberFormat(RbnfSampleRuleSets.usEnglish, Locale.US); 86 spelloutFormatter.setLenientParseMode(lenientParse); 87 populateRuleSetMenu(); 88 numberFormatter = new DecimalFormat("#,##0.##########"); 89 parsePosition = new ParsePosition(0); 90 theNumber = 0; 91 92 numberField = new TextField(); 93 numberField.setFont(new Font("Serif", Font.PLAIN, 24)); 94 textField = new DemoTextFieldHolder(); 95 textField.setFont(new Font("Serif", Font.PLAIN, 24)); 96 rulesField = new DemoTextFieldHolder(); 97 rulesField.setFont(new Font("Serif", Font.PLAIN, 14)); 98 lenientParseButton = new Checkbox("Lenient parse", lenientParse); 99 100 numberField.addTextListener(new TextListener() { 101 public void textValueChanged(TextEvent e) { 102 if (!numberFieldHasFocus) 103 return; 104 105 String fieldText = ((TextComponent)(e.getSource())).getText(); 106 parsePosition.setIndex(0); 107 Number temp = numberFormatter.parse(fieldText, parsePosition); 108 if (temp == null || parsePosition.getIndex() == 0) { 109 theNumber = 0; 110 textField.setText("PARSE ERROR"); 111 } 112 else { 113 theNumber = temp.doubleValue(); 114 textField.setText(spelloutFormatter.format(theNumber, ruleSetName)); 115 } 116 } 117 } ); 118 119 numberField.addFocusListener(new FocusAdapter() { 120 public void focusLost(FocusEvent e) { 121 numberFieldHasFocus = false; 122 numberField.setText(numberFormatter.format(theNumber)); 123 } 124 125 public void focusGained(FocusEvent e) { 126 numberFieldHasFocus = true; 127 numberField.selectAll(); 128 } 129 } ); 130 131 textField.addKeyListener(new KeyAdapter() { 132 public void keyTyped(KeyEvent e) { 133 if (e.getKeyChar() == '\t') { 134 String fieldText = ((TextComponent)(e.getSource())).getText(); 135 parsePosition.setIndex(0); 136 theNumber = spelloutFormatter.parse(fieldText, parsePosition) 137 .doubleValue(); 138 if (parsePosition.getIndex() == 0) { 139 theNumber = 0; 140 numberField.setText("PARSE ERROR"); 141 textField.selectAll(); 142 } 143 else if (parsePosition.getIndex() < fieldText.length()) { 144 textField.select(parsePosition.getIndex(), fieldText.length()); 145 numberField.setText(numberFormatter.format(theNumber)); 146 } 147 else { 148 textField.selectAll(); 149 numberField.setText(numberFormatter.format(theNumber)); 150 } 151 e.consume(); 152 } 153 } 154 } ); 155 156 textField.addFocusListener(new FocusAdapter() { 157 public void focusLost(FocusEvent e) { 158 String fieldText = ((TextComponent)(e.getSource())).getText(); 159 parsePosition.setIndex(0); 160 theNumber = spelloutFormatter.parse(fieldText, parsePosition) 161 .doubleValue(); 162 if (parsePosition.getIndex() == 0) 163 numberField.setText("PARSE ERROR"); 164 else 165 numberField.setText(numberFormatter.format(theNumber)); 166 textField.setText(textField.getText()); // textField.repaint() didn't work right 167 } 168 169 public void focusGained(FocusEvent e) { 170 textField.selectAll(); 171 } 172 } ); 173 174 rulesField.addKeyListener(new KeyAdapter() { 175 public void keyTyped(KeyEvent e) { 176 if (e.getKeyChar() == '\t') { 177 String fieldText = ((TextComponent)(e.getSource())).getText(); 178 if (formatterMenu.getSelectedItem().equals("Custom") || !fieldText.equals( 179 RbnfSampleRuleSets.sampleRuleSets[formatterMenu.getSelectedIndex()])) { 180 try { 181 RuleBasedNumberFormat temp = new RuleBasedNumberFormat(fieldText); 182 temp.setLenientParseMode(lenientParse); 183 populateRuleSetMenu(); 184 spelloutFormatter = temp; 185 customRuleSet = fieldText; 186 formatterMenu.select("Custom"); 187 commentaryField.setText(RbnfSampleRuleSets. 188 sampleRuleSetCommentary[RbnfSampleRuleSets. 189 sampleRuleSetCommentary.length - 1]); 190 redisplay(); 191 } 192 catch (Exception x) { 193 textField.setText(x.toString()); 194 } 195 } 196 e.consume(); 197 } 198 } 199 } ); 200 201 rulesField.addFocusListener(new FocusAdapter() { 202 public void focusLost(FocusEvent e) { 203 String fieldText = ((TextComponent)(e.getSource())).getText(); 204 if (formatterMenu.getSelectedItem().equals("Custom") || !fieldText.equals( 205 RbnfSampleRuleSets.sampleRuleSets[formatterMenu.getSelectedIndex()])) { 206 try { 207 RuleBasedNumberFormat temp = new RuleBasedNumberFormat(fieldText); 208 temp.setLenientParseMode(lenientParse); 209 populateRuleSetMenu(); 210 spelloutFormatter = temp; 211 customRuleSet = fieldText; 212 formatterMenu.select("Custom"); 213 redisplay(); 214 } 215 catch (Exception x) { 216 textField.setText(x.toString()); 217 } 218 } 219 rulesField.setText(rulesField.getText()); // rulesField.repaint() didn't work right 220 } 221 } ); 222 223 lenientParseButton.addItemListener(new ItemListener() { 224 public void itemStateChanged(ItemEvent e) { 225 lenientParse = lenientParseButton.getState(); 226 spelloutFormatter.setLenientParseMode(lenientParse); 227 } 228 } ); 229 230 numberField.setText(numberFormatter.format(theNumber)); 231 numberField.selectAll(); 232 textField.setText(spelloutFormatter.format(theNumber, ruleSetName)); 233 234 Panel leftPanel = new Panel(); 235 leftPanel.setLayout(new BorderLayout()); 236 Panel panel = new Panel(); 237 panel.setLayout(new BorderLayout()); 238 Panel panel1 = new Panel(); 239 panel1.setLayout(new GridLayout(3, 1)); 240 panel1.add(new Panel()); 241 panel1.add(numberField, "Center"); 242 panel1.add(lenientParseButton); 243 panel.add(panel1, "Center"); 244 Panel panel2 = new Panel(); 245 panel2.setLayout(new GridLayout(3, 3)); 246 Button button = new Button("+100"); 247 button.addActionListener( new ActionListener() { 248 public void actionPerformed(ActionEvent e) { 249 roll(100); 250 } 251 } ); 252 panel2.add(button); 253 button = new Button("+10"); 254 button.addActionListener( new ActionListener() { 255 public void actionPerformed(ActionEvent e) { 256 roll(10); 257 } 258 } ); 259 panel2.add(button); 260 button = new Button("+1"); 261 button.addActionListener( new ActionListener() { 262 public void actionPerformed(ActionEvent e) { 263 roll(1); 264 } 265 } ); 266 panel2.add(button); 267 button = new Button("<"); 268 button.addActionListener( new ActionListener() { 269 public void actionPerformed(ActionEvent e) { 270 theNumber *= 10; 271 redisplay(); 272 } 273 } ); 274 panel2.add(button); 275 panel2.add(new Panel()); 276 button = new Button(">"); 277 button.addActionListener( new ActionListener() { 278 public void actionPerformed(ActionEvent e) { 279 theNumber /= 10; 280 redisplay(); 281 } 282 } ); 283 panel2.add(button); 284 button = new Button("-100"); 285 button.addActionListener( new ActionListener() { 286 public void actionPerformed(ActionEvent e) { 287 roll(-100); 288 } 289 } ); 290 panel2.add(button); 291 button = new Button("-10"); 292 button.addActionListener( new ActionListener() { 293 public void actionPerformed(ActionEvent e) { 294 roll(-10); 295 } 296 } ); 297 panel2.add(button); 298 button = new Button("-1"); 299 button.addActionListener( new ActionListener() { 300 public void actionPerformed(ActionEvent e) { 301 roll(-1); 302 } 303 } ); 304 panel2.add(button); 305 panel.add(panel2, "East"); 306 leftPanel.add(panel, "North"); 307 leftPanel.add(textField, "Center"); 308 309 Panel rightPanel = new Panel(); 310 rightPanel.setLayout(new BorderLayout()); 311 formatterMenu = new Choice(); 312 for (int i = 0; i < RbnfSampleRuleSets.sampleRuleSetNames.length; i++) 313 formatterMenu.addItem(RbnfSampleRuleSets.sampleRuleSetNames[i]); 314 formatterMenu.addItem("Custom"); 315 formatterMenu.addItemListener(new ItemListener() { 316 public void itemStateChanged(ItemEvent e) { 317 Choice source = (Choice)(e.getSource()); 318 int item = source.getSelectedIndex(); 319 Locale locale = RbnfSampleRuleSets.sampleRuleSetLocales[item]; 320 321 commentaryField.setText(RbnfSampleRuleSets. 322 sampleRuleSetCommentary[item]); 323 324 if (locale != null && (locale.getLanguage().equals("iw") 325 || locale.getLanguage().equals("ru") || locale.getLanguage().equals("ja") 326 || locale.getLanguage().equals("el") 327 || locale.getLanguage().equals("zh"))) { 328 textField.togglePanes(false); 329 rulesField.togglePanes(false); 330 } 331 else { 332 textField.togglePanes(true); 333 rulesField.togglePanes(true); 334 } 335 336 makeNewSpelloutFormatter(); 337 redisplay(); 338 } 339 } ); 340 341 ruleSetMenu = new Choice(); 342 populateRuleSetMenu(); 343 344 ruleSetMenu.addItemListener(new ItemListener() { 345 public void itemStateChanged(ItemEvent e) { 346 ruleSetName = ruleSetMenu.getSelectedItem(); 347 redisplay(); 348 } 349 } ); 350 351 Panel menuPanel = new Panel(); 352 menuPanel.setLayout(new GridLayout(1, 2)); 353 menuPanel.add(formatterMenu); 354 menuPanel.add(ruleSetMenu); 355 rightPanel.add(menuPanel, "North"); 356 357 rulesField.setText(RbnfSampleRuleSets.sampleRuleSets[formatterMenu.getSelectedIndex()]); 358 rightPanel.add(rulesField, "Center"); 359 360 mainPanel.add(leftPanel); 361 mainPanel.add(rightPanel); 362 363 window.add(mainPanel, "Center"); 364 window.add(commentaryField, "South"); 365 366 window.doLayout(); 367 window.show(); 368 final DemoApplet theApplet = applet; 369 window.addWindowListener( 370 new WindowAdapter() { 371 public void windowClosing(WindowEvent e) { 372 setVisible(false); 373 window.dispose(); 374 375 if (theApplet != null) { 376 theApplet.demoClosed(); 377 } else System.exit(0); 378 } 379 } ); 380 return window; 381 } 382 roll(int delta)383 void roll(int delta) { 384 theNumber += delta; 385 redisplay(); 386 } 387 redisplay()388 void redisplay() { 389 numberField.setText(numberFormatter.format(theNumber)); 390 textField.setText(spelloutFormatter.format(theNumber, ruleSetName)); 391 } 392 makeNewSpelloutFormatter()393 void makeNewSpelloutFormatter() { 394 int item = formatterMenu.getSelectedIndex(); 395 String formatterMenuItem = formatterMenu.getSelectedItem(); 396 397 if (formatterMenuItem.equals("Custom")) { 398 rulesField.setText(customRuleSet); 399 spelloutFormatter = new RuleBasedNumberFormat(customRuleSet); 400 } 401 else { 402 rulesField.setText(RbnfSampleRuleSets.sampleRuleSets[item]); 403 404 Locale locale = RbnfSampleRuleSets.sampleRuleSetLocales[item]; 405 if (locale == null) 406 locale = Locale.getDefault(); 407 408 spelloutFormatter = new RuleBasedNumberFormat(RbnfSampleRuleSets. 409 sampleRuleSets[item], locale); 410 } 411 spelloutFormatter.setLenientParseMode(lenientParse); 412 populateRuleSetMenu(); 413 } 414 populateRuleSetMenu()415 void populateRuleSetMenu() { 416 String[] ruleSetNames = spelloutFormatter.getRuleSetNames(); 417 418 if (ruleSetMenu != null) { 419 ruleSetMenu.removeAll(); 420 for (int i = 0; i < ruleSetNames.length; i++) 421 ruleSetMenu.addItem(ruleSetNames[i]); 422 423 ruleSetName = ruleSetMenu.getSelectedItem(); 424 } 425 else 426 ruleSetName = ruleSetNames[0]; 427 } 428 429 // private Frame demoWindow = null; 430 431 private TextComponent numberField; 432 private DemoTextFieldHolder textField; 433 private DemoTextFieldHolder rulesField; 434 private TextComponent commentaryField; 435 private Checkbox lenientParseButton; 436 437 private boolean numberFieldHasFocus = true; 438 439 private RuleBasedNumberFormat spelloutFormatter; 440 private DecimalFormat numberFormatter; 441 private ParsePosition parsePosition; 442 443 private boolean lenientParse = true; 444 445 private double theNumber = 0; 446 // private boolean canEdit = true; 447 448 private Choice formatterMenu; 449 private Choice ruleSetMenu; 450 private String ruleSetName; 451 452 private String customRuleSet = "NO RULES!"; 453 } 454 455 class DemoTextField extends Component { 456 /** 457 * For serialization 458 */ 459 private static final long serialVersionUID = -7947090021239472658L; DemoTextField()460 public DemoTextField() { 461 } 462 setText(String text)463 public void setText(String text) { 464 this.text = text; 465 this.repaint(); 466 } 467 getText()468 public String getText() { 469 return text; 470 } 471 paint(Graphics g)472 public void paint(Graphics g) { 473 Font font = getFont(); 474 FontMetrics fm = g.getFontMetrics(); 475 g.setFont(font); 476 String txt = getText(); 477 BreakIterator bi = BreakIterator.getLineInstance(); 478 bi.setText(txt); 479 int lineHeight = fm.getHeight(); 480 int width = getSize().width; 481 int penY = fm.getAscent(); 482 int lineStart = 0; 483 int tempLineEnd = bi.first(); 484 int lineEnd = 0; 485 int maxLineEnd = 0; 486 totalHeight = 0; 487 488 while (lineStart < txt.length()) { 489 maxLineEnd = txt.indexOf('\n', lineStart); 490 if (maxLineEnd == -1) 491 maxLineEnd = Integer.MAX_VALUE; 492 while (tempLineEnd != BreakIterator.DONE && fm.stringWidth(txt.substring( 493 lineStart, tempLineEnd)) < width) { 494 lineEnd = tempLineEnd; 495 tempLineEnd = bi.next(); 496 } 497 if (lineStart >= lineEnd) { 498 if (tempLineEnd == BreakIterator.DONE) 499 lineEnd = txt.length(); 500 else 501 lineEnd = tempLineEnd; 502 } 503 if (lineEnd > maxLineEnd) 504 lineEnd = maxLineEnd; 505 g.drawString(txt.substring(lineStart, lineEnd), 0, penY); 506 penY += lineHeight; 507 totalHeight += lineHeight; 508 lineStart = lineEnd; 509 if (lineStart < txt.length() && txt.charAt(lineStart) == '\n') 510 ++lineStart; 511 } 512 } 513 514 /* 515 public Dimension getPreferredSize() { 516 Dimension size = getParent().getSize(); 517 return new Dimension(size.width, totalHeight); 518 } 519 */ 520 521 private String text; 522 private int totalHeight; 523 } 524 525 class DemoTextFieldHolder extends Panel { 526 /** 527 * For serialization 528 */ 529 private static final long serialVersionUID = 7514498764062569858L; DemoTextFieldHolder()530 public DemoTextFieldHolder() { 531 tf1 = new TextArea("", 0, 0, TextArea.SCROLLBARS_VERTICAL_ONLY); 532 tf2 = new DemoTextField(); 533 sp = new ScrollPane(); 534 535 setLayout(new CardLayout()); 536 537 sp.add(tf2, "TextField1"); 538 sp.setVisible(false); 539 add(tf1, "TestField2"); 540 add(sp, "ScrollPane"); 541 } 542 addFocusListener(FocusListener l)543 public void addFocusListener(FocusListener l) { 544 tf1.addFocusListener(l); 545 } 546 addKeyListener(KeyListener l)547 public void addKeyListener(KeyListener l) { 548 tf1.addKeyListener(l); 549 } 550 setText(String text)551 public void setText(String text) { 552 tf1.setText(text); 553 tf2.setText(text); 554 } 555 getText()556 public String getText() { 557 return tf1.getText(); 558 } 559 select(int start, int end)560 public void select(int start, int end) { 561 tf1.select(start, end); 562 } 563 selectAll()564 public void selectAll() { 565 tf1.selectAll(); 566 } 567 togglePanes(boolean canShowRealTextField)568 public void togglePanes(boolean canShowRealTextField) { 569 if (canShowRealTextField != showingRealTextField) { 570 CardLayout layout = (CardLayout)(getLayout()); 571 layout.next(this); 572 showingRealTextField = canShowRealTextField; 573 } 574 } 575 576 private TextArea tf1 = null; 577 private DemoTextField tf2 = null; 578 private ScrollPane sp = null; 579 private boolean showingRealTextField = true; 580 } 581