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