Home | History | Annotate | Download | only in rbnf
      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      */
     65     public static void main(String[] argv) {
     66         new RbnfDemo().showDemo();
     67     }
     68 
     69     protected Dimension getDefaultFrameSize(DemoApplet applet, Frame f) {
     70         return new Dimension(430,270);
     71     }
     72 
     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 
    385     void roll(int delta) {
    386         theNumber += delta;
    387         redisplay();
    388     }
    389 
    390     void redisplay() {
    391         numberField.setText(numberFormatter.format(theNumber));
    392         textField.setText(spelloutFormatter.format(theNumber, ruleSetName));
    393     }
    394 
    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 
    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;
    462     public DemoTextField() {
    463     }
    464 
    465     public void setText(String text) {
    466         this.text = text;
    467         this.repaint();
    468     }
    469 
    470     public String getText() {
    471         return text;
    472     }
    473 
    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;
    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 
    545     public void addFocusListener(FocusListener l) {
    546         tf1.addFocusListener(l);
    547     }
    548 
    549     public void addKeyListener(KeyListener l) {
    550         tf1.addKeyListener(l);
    551     }
    552 
    553     public void setText(String text) {
    554         tf1.setText(text);
    555         tf2.setText(text);
    556     }
    557 
    558     public String getText() {
    559         return tf1.getText();
    560     }
    561 
    562     public void select(int start, int end) {
    563         tf1.select(start, end);
    564     }
    565 
    566     public void selectAll() {
    567         tf1.selectAll();
    568     }
    569 
    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