001: /*
002: *******************************************************************************
003: * Copyright (C) 1996-2004, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *******************************************************************************
006: */
007: package com.ibm.icu.dev.demo.rbnf;
008:
009: import java.awt.*;
010: import java.awt.event.*;
011: import java.text.DecimalFormat;
012: import java.text.BreakIterator;
013: import java.text.ParsePosition;
014: import java.util.Locale;
015: import com.ibm.icu.dev.demo.impl.*;
016: import com.ibm.icu.text.RuleBasedNumberFormat;
017:
018: public class RbnfDemo extends DemoApplet {
019: /**
020: * Puts a copyright in the .class file
021: */
022: private static final String copyrightNotice = "Copyright \u00a91997-1998 IBM Corp. All rights reserved.";
023:
024: /*
025: * code to run the demo as an application
026: */
027: public static void main(String[] argv) {
028: new RbnfDemo().showDemo();
029: }
030:
031: protected Dimension getDefaultFrameSize(DemoApplet applet, Frame f) {
032: return new Dimension(430, 270);
033: }
034:
035: protected Frame createDemoFrame(DemoApplet applet) {
036: final Frame window = new Frame("Number Spellout Demo");
037: window.setSize(800, 600);
038: window.setLayout(new BorderLayout());
039:
040: Panel mainPanel = new Panel();
041: mainPanel.setLayout(new GridLayout(1, 2));
042:
043: commentaryField = new TextArea("", 0, 0,
044: TextArea.SCROLLBARS_VERTICAL_ONLY);
045: commentaryField.setSize(800, 50);
046: commentaryField
047: .setText(RbnfSampleRuleSets.sampleRuleSetCommentary[0]);
048: commentaryField.setEditable(false);
049: commentaryField.setFont(new Font("Helvetica", Font.PLAIN, 14));
050:
051: spelloutFormatter = new RuleBasedNumberFormat(
052: RbnfSampleRuleSets.usEnglish, Locale.US);
053: spelloutFormatter.setLenientParseMode(lenientParse);
054: populateRuleSetMenu();
055: numberFormatter = new DecimalFormat("#,##0.##########");
056: parsePosition = new ParsePosition(0);
057: theNumber = 0;
058:
059: numberField = new TextField();
060: numberField.setFont(new Font("Serif", Font.PLAIN, 24));
061: textField = new DemoTextFieldHolder();
062: textField.setFont(new Font("Serif", Font.PLAIN, 24));
063: rulesField = new DemoTextFieldHolder();
064: rulesField.setFont(new Font("Serif", Font.PLAIN, 14));
065: lenientParseButton = new Checkbox("Lenient parse", lenientParse);
066:
067: numberField.addTextListener(new TextListener() {
068: public void textValueChanged(TextEvent e) {
069: if (!numberFieldHasFocus)
070: return;
071:
072: String fieldText = ((TextComponent) (e.getSource()))
073: .getText();
074: parsePosition.setIndex(0);
075: Number temp = numberFormatter.parse(fieldText,
076: parsePosition);
077: if (temp == null || parsePosition.getIndex() == 0) {
078: theNumber = 0;
079: textField.setText("PARSE ERROR");
080: } else {
081: theNumber = temp.doubleValue();
082: textField.setText(spelloutFormatter.format(
083: theNumber, ruleSetName));
084: }
085: }
086: });
087:
088: numberField.addFocusListener(new FocusAdapter() {
089: public void focusLost(FocusEvent e) {
090: numberFieldHasFocus = false;
091: numberField.setText(numberFormatter.format(theNumber));
092: }
093:
094: public void focusGained(FocusEvent e) {
095: numberFieldHasFocus = true;
096: numberField.selectAll();
097: }
098: });
099:
100: textField.addKeyListener(new KeyAdapter() {
101: public void keyTyped(KeyEvent e) {
102: if (e.getKeyChar() == '\t') {
103: String fieldText = ((TextComponent) (e.getSource()))
104: .getText();
105: parsePosition.setIndex(0);
106: theNumber = spelloutFormatter.parse(fieldText,
107: parsePosition).doubleValue();
108: if (parsePosition.getIndex() == 0) {
109: theNumber = 0;
110: numberField.setText("PARSE ERROR");
111: textField.selectAll();
112: } else if (parsePosition.getIndex() < fieldText
113: .length()) {
114: textField.select(parsePosition.getIndex(),
115: fieldText.length());
116: numberField.setText(numberFormatter
117: .format(theNumber));
118: } else {
119: textField.selectAll();
120: numberField.setText(numberFormatter
121: .format(theNumber));
122: }
123: e.consume();
124: }
125: }
126: });
127:
128: textField.addFocusListener(new FocusAdapter() {
129: public void focusLost(FocusEvent e) {
130: String fieldText = ((TextComponent) (e.getSource()))
131: .getText();
132: parsePosition.setIndex(0);
133: theNumber = spelloutFormatter.parse(fieldText,
134: parsePosition).doubleValue();
135: if (parsePosition.getIndex() == 0)
136: numberField.setText("PARSE ERROR");
137: else
138: numberField.setText(numberFormatter
139: .format(theNumber));
140: textField.setText(textField.getText()); // textField.repaint() didn't work right
141: }
142:
143: public void focusGained(FocusEvent e) {
144: textField.selectAll();
145: }
146: });
147:
148: rulesField.addKeyListener(new KeyAdapter() {
149: public void keyTyped(KeyEvent e) {
150: if (e.getKeyChar() == '\t') {
151: String fieldText = ((TextComponent) (e.getSource()))
152: .getText();
153: if (formatterMenu.getSelectedItem()
154: .equals("Custom")
155: || !fieldText
156: .equals(RbnfSampleRuleSets.sampleRuleSets[formatterMenu
157: .getSelectedIndex()])) {
158: try {
159: RuleBasedNumberFormat temp = new RuleBasedNumberFormat(
160: fieldText);
161: temp.setLenientParseMode(lenientParse);
162: populateRuleSetMenu();
163: spelloutFormatter = temp;
164: customRuleSet = fieldText;
165: formatterMenu.select("Custom");
166: commentaryField
167: .setText(RbnfSampleRuleSets.sampleRuleSetCommentary[RbnfSampleRuleSets.sampleRuleSetCommentary.length - 1]);
168: redisplay();
169: } catch (Exception x) {
170: textField.setText(x.toString());
171: }
172: }
173: e.consume();
174: }
175: }
176: });
177:
178: rulesField.addFocusListener(new FocusAdapter() {
179: public void focusLost(FocusEvent e) {
180: String fieldText = ((TextComponent) (e.getSource()))
181: .getText();
182: if (formatterMenu.getSelectedItem().equals("Custom")
183: || !fieldText
184: .equals(RbnfSampleRuleSets.sampleRuleSets[formatterMenu
185: .getSelectedIndex()])) {
186: try {
187: RuleBasedNumberFormat temp = new RuleBasedNumberFormat(
188: fieldText);
189: temp.setLenientParseMode(lenientParse);
190: populateRuleSetMenu();
191: spelloutFormatter = temp;
192: customRuleSet = fieldText;
193: formatterMenu.select("Custom");
194: redisplay();
195: } catch (Exception x) {
196: textField.setText(x.toString());
197: }
198: }
199: rulesField.setText(rulesField.getText()); // rulesField.repaint() didn't work right
200: }
201: });
202:
203: lenientParseButton.addItemListener(new ItemListener() {
204: public void itemStateChanged(ItemEvent e) {
205: lenientParse = lenientParseButton.getState();
206: spelloutFormatter.setLenientParseMode(lenientParse);
207: }
208: });
209:
210: numberField.setText(numberFormatter.format(theNumber));
211: numberField.selectAll();
212: textField.setText(spelloutFormatter.format(theNumber,
213: ruleSetName));
214:
215: Panel leftPanel = new Panel();
216: leftPanel.setLayout(new BorderLayout());
217: Panel panel = new Panel();
218: panel.setLayout(new BorderLayout());
219: Panel panel1 = new Panel();
220: panel1.setLayout(new GridLayout(3, 1));
221: panel1.add(new Panel());
222: panel1.add(numberField, "Center");
223: panel1.add(lenientParseButton);
224: panel.add(panel1, "Center");
225: Panel panel2 = new Panel();
226: panel2.setLayout(new GridLayout(3, 3));
227: Button button = new Button("+100");
228: button.addActionListener(new ActionListener() {
229: public void actionPerformed(ActionEvent e) {
230: roll(100);
231: }
232: });
233: panel2.add(button);
234: button = new Button("+10");
235: button.addActionListener(new ActionListener() {
236: public void actionPerformed(ActionEvent e) {
237: roll(10);
238: }
239: });
240: panel2.add(button);
241: button = new Button("+1");
242: button.addActionListener(new ActionListener() {
243: public void actionPerformed(ActionEvent e) {
244: roll(1);
245: }
246: });
247: panel2.add(button);
248: button = new Button("<");
249: button.addActionListener(new ActionListener() {
250: public void actionPerformed(ActionEvent e) {
251: theNumber *= 10;
252: redisplay();
253: }
254: });
255: panel2.add(button);
256: panel2.add(new Panel());
257: button = new Button(">");
258: button.addActionListener(new ActionListener() {
259: public void actionPerformed(ActionEvent e) {
260: theNumber /= 10;
261: redisplay();
262: }
263: });
264: panel2.add(button);
265: button = new Button("-100");
266: button.addActionListener(new ActionListener() {
267: public void actionPerformed(ActionEvent e) {
268: roll(-100);
269: }
270: });
271: panel2.add(button);
272: button = new Button("-10");
273: button.addActionListener(new ActionListener() {
274: public void actionPerformed(ActionEvent e) {
275: roll(-10);
276: }
277: });
278: panel2.add(button);
279: button = new Button("-1");
280: button.addActionListener(new ActionListener() {
281: public void actionPerformed(ActionEvent e) {
282: roll(-1);
283: }
284: });
285: panel2.add(button);
286: panel.add(panel2, "East");
287: leftPanel.add(panel, "North");
288: leftPanel.add(textField, "Center");
289:
290: Panel rightPanel = new Panel();
291: rightPanel.setLayout(new BorderLayout());
292: formatterMenu = new Choice();
293: for (int i = 0; i < RbnfSampleRuleSets.sampleRuleSetNames.length; i++)
294: formatterMenu
295: .addItem(RbnfSampleRuleSets.sampleRuleSetNames[i]);
296: formatterMenu.addItem("Custom");
297: formatterMenu.addItemListener(new ItemListener() {
298: public void itemStateChanged(ItemEvent e) {
299: Choice source = (Choice) (e.getSource());
300: int item = source.getSelectedIndex();
301: Locale locale = RbnfSampleRuleSets.sampleRuleSetLocales[item];
302:
303: commentaryField
304: .setText(RbnfSampleRuleSets.sampleRuleSetCommentary[item]);
305:
306: if (locale != null
307: && (locale.getLanguage().equals("iw")
308: || locale.getLanguage().equals("ru")
309: || locale.getLanguage().equals("ja")
310: || locale.getLanguage().equals("el") || locale
311: .getLanguage().equals("zh"))) {
312: textField.togglePanes(false);
313: rulesField.togglePanes(false);
314: } else {
315: textField.togglePanes(true);
316: rulesField.togglePanes(true);
317: }
318:
319: makeNewSpelloutFormatter();
320: redisplay();
321: }
322: });
323:
324: ruleSetMenu = new Choice();
325: populateRuleSetMenu();
326:
327: ruleSetMenu.addItemListener(new ItemListener() {
328: public void itemStateChanged(ItemEvent e) {
329: ruleSetName = ruleSetMenu.getSelectedItem();
330: redisplay();
331: }
332: });
333:
334: Panel menuPanel = new Panel();
335: menuPanel.setLayout(new GridLayout(1, 2));
336: menuPanel.add(formatterMenu);
337: menuPanel.add(ruleSetMenu);
338: rightPanel.add(menuPanel, "North");
339:
340: rulesField
341: .setText(RbnfSampleRuleSets.sampleRuleSets[formatterMenu
342: .getSelectedIndex()]);
343: rightPanel.add(rulesField, "Center");
344:
345: mainPanel.add(leftPanel);
346: mainPanel.add(rightPanel);
347:
348: window.add(mainPanel, "Center");
349: window.add(commentaryField, "South");
350:
351: window.doLayout();
352: window.show();
353: return window;
354: }
355:
356: void roll(int delta) {
357: theNumber += delta;
358: redisplay();
359: }
360:
361: void redisplay() {
362: numberField.setText(numberFormatter.format(theNumber));
363: textField.setText(spelloutFormatter.format(theNumber,
364: ruleSetName));
365: }
366:
367: void makeNewSpelloutFormatter() {
368: int item = formatterMenu.getSelectedIndex();
369: String formatterMenuItem = formatterMenu.getSelectedItem();
370:
371: if (formatterMenuItem.equals("Custom")) {
372: rulesField.setText(customRuleSet);
373: spelloutFormatter = new RuleBasedNumberFormat(customRuleSet);
374: } else {
375: rulesField.setText(RbnfSampleRuleSets.sampleRuleSets[item]);
376:
377: Locale locale = RbnfSampleRuleSets.sampleRuleSetLocales[item];
378: if (locale == null)
379: locale = Locale.getDefault();
380:
381: spelloutFormatter = new RuleBasedNumberFormat(
382: RbnfSampleRuleSets.sampleRuleSets[item], locale);
383: }
384: spelloutFormatter.setLenientParseMode(lenientParse);
385: populateRuleSetMenu();
386: }
387:
388: void populateRuleSetMenu() {
389: String[] ruleSetNames = spelloutFormatter.getRuleSetNames();
390:
391: if (ruleSetMenu != null) {
392: ruleSetMenu.removeAll();
393: for (int i = 0; i < ruleSetNames.length; i++)
394: ruleSetMenu.addItem(ruleSetNames[i]);
395:
396: ruleSetName = ruleSetMenu.getSelectedItem();
397: } else
398: ruleSetName = ruleSetNames[0];
399: }
400:
401: private Frame demoWindow = null;
402:
403: private TextComponent numberField;
404: private DemoTextFieldHolder textField;
405: private DemoTextFieldHolder rulesField;
406: private TextComponent commentaryField;
407: private Checkbox lenientParseButton;
408:
409: private boolean numberFieldHasFocus = true;
410:
411: private RuleBasedNumberFormat spelloutFormatter;
412: private DecimalFormat numberFormatter;
413: private ParsePosition parsePosition;
414:
415: private boolean lenientParse = true;
416:
417: private double theNumber = 0;
418: private boolean canEdit = true;
419:
420: private Choice formatterMenu;
421: private Choice ruleSetMenu;
422: private String ruleSetName;
423:
424: private String customRuleSet = "NO RULES!";
425: }
426:
427: class DemoTextField extends Component {
428: public DemoTextField() {
429: }
430:
431: public void setText(String text) {
432: this .text = text;
433: this .repaint();
434: }
435:
436: public String getText() {
437: return text;
438: }
439:
440: public void paint(Graphics g) {
441: Font font = getFont();
442: FontMetrics fm = g.getFontMetrics();
443: g.setFont(font);
444: String text = getText();
445: BreakIterator bi = BreakIterator.getLineInstance();
446: bi.setText(text);
447: int lineHeight = fm.getHeight();
448: int width = getSize().width;
449: int penY = fm.getAscent();
450: int lineStart = 0;
451: int tempLineEnd = bi.first();
452: int lineEnd = 0;
453: int maxLineEnd = 0;
454: totalHeight = 0;
455:
456: while (lineStart < text.length()) {
457: maxLineEnd = text.indexOf('\n', lineStart);
458: if (maxLineEnd == -1)
459: maxLineEnd = Integer.MAX_VALUE;
460: while (tempLineEnd != BreakIterator.DONE
461: && fm.stringWidth(text.substring(lineStart,
462: tempLineEnd)) < width) {
463: lineEnd = tempLineEnd;
464: tempLineEnd = bi.next();
465: }
466: if (lineStart >= lineEnd) {
467: if (tempLineEnd == BreakIterator.DONE)
468: lineEnd = text.length();
469: else
470: lineEnd = tempLineEnd;
471: }
472: if (lineEnd > maxLineEnd)
473: lineEnd = maxLineEnd;
474: g.drawString(text.substring(lineStart, lineEnd), 0, penY);
475: penY += lineHeight;
476: totalHeight += lineHeight;
477: lineStart = lineEnd;
478: if (lineStart < text.length()
479: && text.charAt(lineStart) == '\n')
480: ++lineStart;
481: }
482: }
483:
484: /*
485: public Dimension getPreferredSize() {
486: Dimension size = getParent().getSize();
487: return new Dimension(size.width, totalHeight);
488: }
489: */
490:
491: private String text;
492: private int totalHeight;
493: }
494:
495: class DemoTextFieldHolder extends Panel {
496: public DemoTextFieldHolder() {
497: tf1 = new TextArea("", 0, 0, TextArea.SCROLLBARS_VERTICAL_ONLY);
498: tf2 = new DemoTextField();
499: sp = new ScrollPane();
500:
501: setLayout(new CardLayout());
502:
503: sp.add(tf2, "TextField1");
504: sp.setVisible(false);
505: add(tf1, "TestField2");
506: add(sp, "ScrollPane");
507: }
508:
509: public void addFocusListener(FocusListener l) {
510: tf1.addFocusListener(l);
511: }
512:
513: public void addKeyListener(KeyListener l) {
514: tf1.addKeyListener(l);
515: }
516:
517: public void setText(String text) {
518: tf1.setText(text);
519: tf2.setText(text);
520: }
521:
522: public String getText() {
523: return tf1.getText();
524: }
525:
526: public void select(int start, int end) {
527: tf1.select(start, end);
528: }
529:
530: public void selectAll() {
531: tf1.selectAll();
532: }
533:
534: public void togglePanes(boolean canShowRealTextField) {
535: if (canShowRealTextField != showingRealTextField) {
536: CardLayout layout = (CardLayout) (getLayout());
537: layout.next(this );
538: showingRealTextField = canShowRealTextField;
539: }
540: }
541:
542: private TextArea tf1 = null;
543: private DemoTextField tf2 = null;
544: private ScrollPane sp = null;
545: private boolean showingRealTextField = true;
546: }
|