home *** CD-ROM | disk | FTP | other *** search
/ Java Developer's Companion / Java Developer's Companion.iso / documentation / tutorial / intl / datamgmt / demos-1.1 / NumberFormatDemo.java < prev    next >
Encoding:
Java Source  |  1997-07-13  |  29.9 KB  |  965 lines

  1. /*
  2.  * Copyright (c) 1995-1997 Sun Microsystems, Inc. All Rights Reserved.
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software
  5.  * and its documentation for NON-COMMERCIAL purposes and without
  6.  * fee is hereby granted provided that this copyright notice
  7.  * appears in all copies. Please refer to the file "copyright.html"
  8.  * for further important copyright and licensing information.
  9.  *
  10.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  11.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  12.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  13.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  14.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  15.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  16.  */
  17. /*
  18.  * @(#)NumberFormatDemo.java    1.1 96/11/23
  19.  *
  20.  * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  21.  * (C) Copyright IBM Corp. 1996 - All Rights Reserved
  22.  *
  23.  * Portions copyright (c) 1996 Sun Microsystems, Inc. All Rights Reserved.
  24.  *
  25.  *   The original version of this source code and documentation is copyrighted
  26.  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  27.  * materials are provided under terms of a License Agreement between Taligent
  28.  * and Sun. This technology is protected by multiple US and International
  29.  * patents. This notice and attribution to Taligent may not be removed.
  30.  *   Taligent is a registered trademark of Taligent, Inc.
  31.  *
  32.  * Permission to use, copy, modify, and distribute this software
  33.  * and its documentation for NON-COMMERCIAL purposes and without
  34.  * fee is hereby granted provided that this copyright notice
  35.  * appears in all copies. Please refer to the file "copyright.html"
  36.  * for further important copyright and licensing information.
  37.  *
  38.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  39.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  40.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  41.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  42.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  43.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  44.  *
  45.  */
  46.  
  47. import java.applet.Applet;
  48. import java.awt.*;
  49. import java.lang.*;
  50.  
  51. import java.util.*;
  52. import java.text.NumberFormat;
  53. import java.text.DecimalFormat;
  54. import java.text.ParsePosition;
  55.  
  56. import java.awt.event.KeyAdapter;
  57. import java.awt.event.KeyEvent;
  58.  
  59. import java.awt.event.ItemListener;
  60. import java.awt.event.ItemEvent;
  61.  
  62. import java.awt.event.WindowAdapter;
  63. import java.awt.event.WindowEvent;
  64.  
  65. /**
  66.  * Concrete class for demonstrating how to convert binary numbers into text
  67.  * strings for meaningful display.
  68.  * The following is the instruction on how to run the number format demo.
  69.  * <p>
  70.  * ===================
  71.  * <P>Number formatters convert binary numbers (integer or float data types)
  72.  * into text strings for meaningful display. The number formatters:
  73.  * <UL>
  74.  * <LI>Provide control over every aspect of the display, including separator
  75.  * characters, optional digits, maximum and minimum decimal and integer places,
  76.  * and optional prefixes and suffixes </LI>
  77.  * <LI>Can produce currency and percentage formats and can be extended to
  78.  * produce other formats </LI>
  79.  * <LI>Allow you to specify new formats with string patterns and can retrieve
  80.  * the normalized pattern </LI>
  81.  * <LI>Can parse anything they can format, for use when converting text input
  82.  * into binary data </LI>
  83.  * </UL>
  84.  * <P><CENTER>
  85.  * <A HREF="#localized">Localized Formats</A>  
  86.  * <A HREF="#patterns">Creating Formats with Patterns </A>  
  87.  * <A HREF="#parsing">Parsing Text </A>
  88.  * </CENTER></P>
  89.  * <HR>
  90.  * <H3><A NAME="localized">Localized Formats </A></H3>
  91.  * <P>The number formatters let you format numbers in the ways that are
  92.  * appropriate for any user's conventions, including country-specific formats
  93.  * such as currencies.  You can also specify other formatting options such as
  94.  * minimum and maximum number of digits displayed.
  95.  * </P>
  96.  * <P> The applet displays the number in two formats—the Java 1.0
  97.  * representation ("Java 1.0 Number"), and the localized format
  98.  * generated by the number formatters ("New Number").
  99.  * </P>
  100.  * <TABLE WIDTH=100% CELLPADDING=5>
  101.  * <TR>
  102.  * <TH ALIGN=left VALIGN=bottom>To See This...</TH>
  103.  * <TH ALIGN=left VALIGN=bottom>Do This...</TH>
  104.  * </TR>
  105.  * <TR>
  106.  * <TD WIDTH=50% VALIGN=top> Localized number formats.  In the international
  107.  * string, the separator characters change to reflect the conventions used by
  108.  * different countries.
  109.  * </TD>
  110.  * <TD VALIGN=top>
  111.  * <TABLE CELLSPACING=0 CELLPADDING=0>
  112.  * <TR>
  113.  * <TD WIDTH=10 VALIGN=top> 1.
  114.  * </TD>
  115.  * <TD> Pull down the Locale menu
  116.  * </TD>
  117.  * </TR>
  118.  * <TR>
  119.  * <TD WIDTH=10 VALIGN=top> 2.
  120.  * </TD>
  121.  * <TD> Try several different locales with the up and down arrow keys
  122.  * (on Windows) or the mouse button (on Macintosh)
  123.  * </TD>
  124.  * </TR>
  125.  * </TABLE>
  126.  * </TD>
  127.  * </TR>
  128.  * <TR>
  129.  * <TD WIDTH=50% VALIGN=top> Localized currency formats.  The formatter adds
  130.  * a prefix or suffix to indicate the currency unit.  It also uses a minus sign
  131.  * or parentheses to indicate negative numbers, as appropriate.
  132.  * </TD>
  133.  * <TD VALIGN=top>
  134.  * <TABLE CELLSPACING=0 CELLPADDING=0>
  135.  * <TR>
  136.  * <TD WIDTH=10 VALIGN=top> 1.
  137.  * </TD>
  138.  * <TD> Click on the <I> Currency </I> button
  139.  * </TD>
  140.  * </TR>
  141.  * <TR>
  142.  * <TD WIDTH=10 VALIGN=top> 2.
  143.  * </TD>
  144.  * <TD> Pull down the Locale menu and try several different locales
  145.  * </TD>
  146.  * </TR>
  147.  * </TABLE>
  148.  * </TD>
  149.  * </TR>
  150.  * <TR>
  151.  * <TD WIDTH=50% VALIGN=top> Setting formatting options, for example,
  152.  * specifying a precise  number of decimal places.
  153.  * </TD>
  154.  * <TD VALIGN=top>
  155.  * <TABLE CELLSPACING=0 CELLPADDING=0>
  156.  * <TR>
  157.  * <TD WIDTH=10 VALIGN=top> 1.
  158.  * </TD>
  159.  * <TD> Type "3" in the <I>Min </I> field for <I> Decimal Count </I>
  160.  * —the formatter appends zeroes to display the specified number of
  161.  * decimal places
  162.  * </TD>
  163.  * </TR>
  164.  * </TABLE>
  165.  * </TD>
  166.  * </TR>
  167.  * </TABLE>
  168.  * <HR WIDTH=50% ALIGN=left>
  169.  * <H3><A NAME="patterns">Creating Formats with Patterns </A></H3>
  170.  * <P> A string pattern can control the output format for a number formatter,
  171.  * making it easy for you to edit a format or provide an editing mechanism
  172.  * for end users.  The pattern also changes to reflect any changes you make
  173.  * programmatically.
  174.  * </P>
  175.  * <P> Patterns can either be invariant (for use only by programmers) or
  176.  * localized (for use by end users).  Click on the <I> Localized Pattern </I>
  177.  * box to change the state.
  178.  * <TABLE WIDTH=100% CELLPADDING=5>
  179.  * <TR>
  180.  * <TH ALIGN=left VALIGN=bottom>To See This...</TH>
  181.  * <TH ALIGN=left VALIGN=bottom>Do This...</TH>
  182.  * </TR>
  183.  * <TR>
  184.  * <TD WIDTH=50% VALIGN=top> You can edit the pattern to create a new format.
  185.  * </TD>
  186.  * <TD VALIGN=top>
  187.  * <TABLE CELLSPACING=0 CELLPADDING=0>
  188.  * <TR>
  189.  * <TD WIDTH=10 VALIGN=top> 1.
  190.  * </TD>
  191.  * <TD> Select the <I> Default Format </I> button and the <I>English
  192.  * (United States) </I> locale
  193.  * </TD>
  194.  * </TR>
  195.  * <TR>
  196.  * <TD WIDTH=10 VALIGN=top> 2.
  197.  * </TD>
  198.  * <TD> Increase the maximum number for <I>Decimal Count</I>
  199.  * </TD>
  200.  * </TR>
  201.  * <TR>
  202.  * <TD WIDTH=10 VALIGN=top> 3.
  203.  * </TD>
  204.  * <TD> Delete the "#" characters at the end of the <I>Pattern
  205.  * </I> field and type in zeroes—the decimal places in the <I>New Number
  206.  * </I> field change to zeroes
  207.  * </TD>
  208.  * </TR>
  209.  * </TABLE>
  210.  * </TD>
  211.  * </TR>
  212.  * <TR>
  213.  * <TD WIDTH=50% VALIGN=top> You can edit the prefix and suffix strings, and
  214.  * create different patterns for positive and negative numbers.
  215.  * </TD>
  216.  * <TD VALIGN=top>
  217.  * <TABLE CELLSPACING=0 CELLPADDING=0>
  218.  * <TR>
  219.  * <TD WIDTH=10 VALIGN=top> 1.
  220.  * </TD>
  221.  * <TD> Type a plus sign ("+") in the <I> Prefix </I> field for
  222.  * positive numbers to modify the positive number pattern
  223.  * </TD>
  224.  * </TR>
  225.  * <TR>
  226.  * <TD WIDTH=10 VALIGN=top> 2.
  227.  * </TD>
  228.  * <TD> Delete the minus sign from the Java 1.0 number
  229.  * </TD>
  230.  * </TR>
  231.  * </TABLE>
  232.  * </TD>
  233.  * </TR>
  234.  * </TABLE>
  235.  * <HR WIDTH=50% ALIGN=left>
  236.  * <H3><A NAME="parsing">Parsing Text </A></H3>
  237.  * <P>The number formatters not only format for any language, but can parse
  238.  * numbers displayed in any language back into binary format.
  239.  * </P>
  240.  * <TABLE WIDTH=100% CELLPADDING=5>
  241.  * <TR>
  242.  * <TH ALIGN=left VALIGN=bottom>To See This...</TH>
  243.  * <TH ALIGN=left VALIGN=bottom>Do This...</TH>
  244.  * </TR>
  245.  * <TR>
  246.  * <TD WIDTH=50% VALIGN=top> Changes to the international number are parsed
  247.  * and reflected in the <I> Java 1.0 Number </I> field.
  248.  * </TD>
  249.  * <TD VALIGN=top>
  250.  * <TABLE CELLSPACING=0 CELLPADDING=0>
  251.  * <TR>
  252.  * <TD WIDTH=10 VALIGN=top> 1.
  253.  * </TD>
  254.  * <TD> Select the thousands separator character in the <I>New Number </I>
  255.  * field (the comma if you are still in the U.S. locale) and replace it with
  256.  * a number
  257.  * </TD>
  258.  * </TR>
  259.  * </TABLE>
  260.  * </TD>
  261.  * </TR>
  262.  * </TABLE>
  263.  * <P>The parsing mechanism is somewhat lenient. For example, a thousands
  264.  * separator character can be misplaced and the parser still returns the
  265.  * correct value. </P>
  266.  * <P>Though not yet demonstrated here, the number formatters also handle
  267.  * IEEE number symbols such as the infinity sign and NaN (for example, 0/0),
  268.  * creating the correct results for both formatting and parsing. The formatters
  269.  * also return the alignment point so you can line up the end of integer
  270.  * portions correctly even without monospace fonts or with strange number
  271.  * conventions. </P>
  272.  * <P>You can type in other numbers in either number field or enter a
  273.  * completely new pattern to  see different formatting behaviors.  Try it out!
  274.  * </P>
  275.  * @see        java.util.Format
  276.  * @see        java.util.NumberFormat
  277.  * @version    1.1 11/23/96
  278.  * @author     Laura Werner, Mark Davis
  279. */
  280. // Change history:  Helena Shih 091996: Added comments prior spec review.
  281. public class NumberFormatDemo extends DemoApplet
  282. {
  283.     /**
  284.      * The main function which defines the behavior of the NumberFormatDemo
  285.      * applet when an applet is started.
  286.      */
  287.     public static void main(String argv[]) {
  288.         DemoApplet.showDemo(new NumberFormatFrame(null));
  289.     }
  290.  
  291.     /**
  292.      * This creates a NumberFormatFrame for the demo applet.
  293.      */
  294.     public Frame createDemoFrame(DemoApplet applet) {
  295.         return new NumberFormatFrame(applet);
  296.     }
  297. }
  298.  
  299. /**
  300.  * A Frame is a top-level window with a title. The default layout for a frame
  301.  * is BorderLayout.  The NumberFormatFrame class defines the window layout of
  302.  * NumberFormatDemo.
  303.  */
  304. class NumberFormatFrame extends Frame implements ItemListener
  305. {
  306.     /**
  307.      * Constructs a new NumberFormatFrame that is initially invisible.
  308.      */
  309.     public NumberFormatFrame(DemoApplet applet)
  310.     {
  311.         super("Number Formatting Demo");
  312.         this.applet = applet;
  313.         startInitialization();
  314.  
  315.     // set up event handling for text items
  316.         MyKeyAdapter keyListener = new MyKeyAdapter();
  317.         inputText.addKeyListener(keyListener);
  318.         patternText.addKeyListener(keyListener);
  319.         outputText.addKeyListener(keyListener);
  320.         posSuffix.addKeyListener(keyListener);
  321.         posPrefix.addKeyListener(keyListener);
  322.         negSuffix.addKeyListener(keyListener);
  323.         negPrefix.addKeyListener(keyListener);
  324.         decMax.addKeyListener(keyListener);
  325.         decMin.addKeyListener(keyListener);
  326.         intMax.addKeyListener(keyListener);
  327.         intMin.addKeyListener(keyListener);
  328.  
  329.     // set up event handling for "item events"
  330.         getPercent.addItemListener(this);
  331.         getCurrency.addItemListener(this);
  332.         getInstance.addItemListener(this);
  333.         getLocalized.addItemListener(this);
  334.         localeMenu.addItemListener(this);
  335.     
  336.     // set up event handling for window events
  337.         addWindowListener(new MyWindowAdapter());
  338.  
  339.         finishInitialization();
  340.     }
  341.  
  342.     /**
  343.      * Sets up the window.
  344.      */
  345.     public void startInitialization()
  346.     {
  347.         //Get all locales for debugging, but only get G7 locales for demos.
  348.         if (DEBUG == true)
  349.              locales = NumberFormat.getAvailableLocales();
  350.         else locales = Utility.getG7Locales();
  351.  
  352.         buildGUI();
  353.  
  354.         // Stick the names of the locales into the locale popup menu
  355.         Locale displayLocale = Locale.getDefault();
  356.         for (int i = 0; i < locales.length; i++) {
  357.             if (locales[i].getCountry().length() > 0) {
  358.                 localeMenu.addItem( locales[i].getDisplayName() );
  359.             }
  360.         }
  361.         localeMenu.select( Locale.US.getDisplayName());
  362.  
  363.         // For starters, use the default format for the selected locale in the
  364.         // menu
  365.         setFormatFromLocale();
  366.     }
  367.  
  368.     /**
  369.      * Set window's initial state.
  370.      */
  371.     public void finishInitialization()
  372.     {
  373.         inputText.setText("-1234.56");
  374.         clickedRightButton();
  375.     }
  376.  
  377.  
  378.     /**
  379.      * Handles keyboard events for all text items
  380.      */
  381.     class MyKeyAdapter extends KeyAdapter {
  382.         public void keyReleased(KeyEvent evt) {
  383.             if (evt.getSource() == inputText)  {
  384.                 inputChanged(evt);
  385.             } else if (evt.getSource() == patternText)  {
  386.                 patternChanged(evt);
  387.             } else if (evt.getSource() == outputText)  {
  388.                 outputChanged(evt);
  389.             } else if (evt.getSource() == posSuffix)  {
  390.                 posSuffixChanged(evt);
  391.             } else if (evt.getSource() == posPrefix)  {
  392.                 posPrefixChanged(evt);
  393.             } else if (evt.getSource() == negSuffix)  {
  394.                 negSuffixChanged(evt);
  395.             } else if (evt.getSource() == negPrefix)  {
  396.                 negPrefixChanged(evt);
  397.             } else if (evt.getSource() == decMax)  {
  398.                 decMaxChanged(evt);
  399.             } else if (evt.getSource() == decMin)  {
  400.                 decMinChanged(evt);
  401.             } else if (evt.getSource() == intMax)  {
  402.                 intMaxChanged(evt);
  403.             } else if (evt.getSource() == intMin)  {
  404.                 intMinChanged(evt);
  405.             }
  406.         }
  407.     }
  408.  
  409.     /**
  410.      * Handles state changes of the radio buttons and the locale menu
  411.      */
  412.     public void itemStateChanged(ItemEvent evt) {
  413.         if (evt.getSource() == getPercent) {
  414.                 clickedGetPercent();
  415.         } else if (evt.getSource() == getCurrency) {
  416.                 clickedGetCurrency();
  417.         } else if (evt.getSource() == getInstance) {
  418.                 clickedGetDefault();
  419.         } else if (evt.getSource() == getLocalized) {
  420.                 isLocalized = getLocalized.getState();
  421.                 handleNewFormat();
  422.         } else if (evt.getSource() == localeMenu) {
  423.                 selectedLocaleMenu();
  424.         }
  425.     }
  426.  
  427.  
  428.     /**
  429.      * Handles window events.
  430.      */
  431.     class MyWindowAdapter extends WindowAdapter {
  432.         public void windowClosing(WindowEvent e) {
  433.             setVisible(false);
  434.             dispose();
  435.             if (applet != null) {
  436.                 applet.demoClosed();
  437.             } else
  438.                 System.exit(0);
  439.         }
  440.     }
  441.  
  442.     /**
  443.      * This function is called when it is necessary to create a new number
  444.      * format.  For example, when a new locale is chosen, a new number
  445.      * format for that locale needs to be created.  Or, when a number
  446.      * format attributes have been changed.
  447.      */
  448.     public void handleNewFormat()
  449.     {
  450.         if (isLocalized == true) {
  451.            workaroundSetText(patternText,format.toLocalizedPattern() );
  452.         }else workaroundSetText(patternText,format.toPattern() );
  453.  
  454.         // force the text in the output area to use the new format
  455.         clickedRightButton();
  456.     }
  457.  
  458.     /**
  459.      * A new number format needs to be created if the attributes are changed.
  460.      */
  461.     public void handleAttributeChange()
  462.     {
  463.         handleNewFormat();
  464.     }
  465.  
  466.     /**
  467.      * Create a new number format if a new locale has been selected.
  468.      */
  469.     public void setFormatFromLocale() {
  470.         // Find the locale corresponding to the currently selected menu item
  471.         int index = localeMenu.getSelectedIndex();
  472.         Locale aLocale = locales[index];
  473.  
  474.         if (getPercent.getState()) {
  475.             format = (DecimalFormat) NumberFormat.getPercentInstance(aLocale);
  476.         } else if (getCurrency.getState()) {
  477.             format = (DecimalFormat) NumberFormat.getCurrencyInstance(aLocale);
  478.         } else {
  479.             format = (DecimalFormat) NumberFormat.getInstance(aLocale);
  480.         }
  481.  
  482.         handleNewFormat();
  483.  
  484.         updateAttributes();
  485.     }
  486.  
  487.     /**
  488.      * This is used to avoid goofy updates and misplaced cursors
  489.      */
  490.     public void workaroundSetText(TextComponent area, String newText) {
  491.         String foo = workaround(area.getText());
  492.         if (foo.equals(newText)) return;
  493.         area.setText(newText);
  494.         //if (area.gotFocus())
  495.         //    area.select(newText.length(),newText.length());
  496.     }
  497.  
  498.     /**
  499.      * Update the attributes.
  500.      */
  501.     public void updateAttributes() {
  502.         workaroundSetText(intMin,toString(format.getMinimumIntegerDigits()) );
  503.         workaroundSetText(intMax,toString(format.getMaximumIntegerDigits()) );
  504.         workaroundSetText(decMin,toString(format.getMinimumFractionDigits()) );
  505.         workaroundSetText(decMax,toString(format.getMaximumFractionDigits()) );
  506.  
  507.         workaroundSetText(negPrefix,format.getNegativePrefix() );
  508.         workaroundSetText(negSuffix,format.getNegativeSuffix() );
  509.         workaroundSetText(posPrefix,format.getPositivePrefix() );
  510.         workaroundSetText(posSuffix,format.getPositiveSuffix() );
  511.     }
  512.  
  513.     /**
  514.      * Get the default number formatter.
  515.      */
  516.     public void clickedGetDefault() {
  517.         setFormatFromLocale();
  518.     }
  519.     /**
  520.      * Update the number formatter with currency attribute.
  521.      */
  522.     public void clickedGetCurrency() {
  523.         setFormatFromLocale();
  524.     }
  525.     /**
  526.      * Update the number formatter with percentage attribute.
  527.      */
  528.     public void clickedGetPercent() {
  529.         setFormatFromLocale();
  530.     }
  531.     /**
  532.      * Update the number formatter when a new locale is selected.
  533.      */
  534.     public void selectedLocaleMenu() {
  535.         setFormatFromLocale();
  536.     }
  537.     /**
  538.      * If the user changes the input number, format it immediately
  539.      */
  540.     public void inputChanged(KeyEvent ev) {
  541.         clickedRightButton();
  542.     }
  543.     /**
  544.      * If the user changes the output number, format it immediately
  545.      */
  546.     public void outputChanged(KeyEvent ev) {
  547.         clickedLeftButton();
  548.     }
  549.  
  550.     /**
  551.      * Update the text in the input area to use the new number format.
  552.      */
  553.     public void clickedRightButton() {
  554.         String leftString = workaround(inputText.getText());
  555.         Number num;
  556.  
  557.         try {
  558.             num = new Double(leftString);
  559.         }
  560.         catch (IllegalArgumentException e) {
  561.             outputText.setText("");
  562.             inputText.selectAll();
  563.             return;
  564.         }
  565.         workaroundSetText(outputText,format.format(num));
  566.     }
  567.  
  568.     /**
  569.      * Update the text in the output area to use the new number format.
  570.      */
  571.     public void clickedLeftButton() {
  572.         String rightString = workaround(outputText.getText());
  573.         Number num;
  574.         ParsePosition status = new ParsePosition(0);
  575.  
  576.         try {
  577.             num = format.parse(rightString, status);
  578.         }
  579.         catch (IllegalArgumentException e) {
  580.             errorText("Exception: " + e.getClass() + e.getMessage());
  581.             inputText.setText("");
  582.             outputText.selectAll();
  583.             return;
  584.         }
  585.         if (status.getIndex() != rightString.length()) {
  586.             errorText("excess text: " +
  587.                       rightString.substring(status.getIndex(),
  588.                                             rightString.length()));
  589.         }
  590.         workaroundSetText(inputText, num.toString() );
  591.     }
  592.  
  593.     /**
  594.      * When the user changes the field containing the pattern, a new format
  595.      * needs to be constructed from the pattern, then redisplay everything.
  596.      */
  597.     public void patternChanged(KeyEvent ev) {
  598.         String foo = workaround(patternText.getText());
  599.         try {
  600.               if (isLocalized == true) {
  601.                    format.applyLocalizedPattern(foo);
  602.                    errorText("Pattern: " + foo + " -> " +
  603.                            format.toLocalizedPattern());
  604.               } else {
  605.                    format.applyPattern(foo);
  606.                    errorText("Pattern: " + foo + " -> " +
  607.                            format.toPattern());
  608.               }
  609.  
  610.         } catch (Exception bar) {
  611.             errorText("Exception: " + bar.getClass() + bar.getMessage());
  612.         }
  613.         updateAttributes();
  614.         clickedRightButton();
  615.     }
  616.     //------------------------------------------------------------
  617.     // package private
  618.     //------------------------------------------------------------
  619.     void addWithFont(Container container, Component foo, Font font) {
  620.         if (font != null)
  621.             foo.setFont(font);
  622.         container.add(foo);
  623.     }
  624.  
  625.     //{{DECLARE_CONTROLS
  626.     Panel localePanel;
  627.     CheckboxGroup group1;
  628.     Label label1;
  629.     Label label2;
  630.     Label label3;
  631.     Choice localeMenu;
  632.     Label localeLabel;
  633.     TextField inputText;
  634.     TextField outputText;
  635.     //Button rightButton;
  636.     //Button leftButton;
  637.     TextField patternText;
  638.     Label label4;
  639.     TextField negPrefix;
  640.     TextField negSuffix;
  641.     TextField posPrefix;
  642.     TextField posSuffix;
  643.     Label label5;
  644.     Label label6;
  645.     Label label7;
  646.     Label label8;
  647.     TextField intMin;
  648.     TextField intMax;
  649.     TextField decMin;
  650.     TextField decMax;
  651.     Label label9;
  652.     Label label10;
  653.     Label label11;
  654.     Label label12;
  655.     Checkbox getInstance;
  656.     Checkbox getCurrency;
  657.     Checkbox getPercent;
  658.     Checkbox getLocalized;
  659.     Label label13;
  660.     Label label14;
  661.     //}}
  662.     //------------------------------------------------------------
  663.     // private
  664.     //------------------------------------------------------------
  665.     private void buildGUI()
  666.     {
  667.         //{{INIT_CONTROLS
  668.         setBackground(Utility.bgColor); // MD 8/7
  669.         // shouldn't be necessary, but it is!
  670.         setLayout(new FlowLayout(FlowLayout.CENTER,2,2));
  671.  
  672.         // INPUT/OUTPUT/PATTERN
  673.  
  674.         Panel creditPanel = new Panel();
  675.         label1=new Label("Decimal Number Formatting Demo",
  676.                          Label.CENTER);
  677.         label1.setFont(Utility.titleFont);
  678.         creditPanel.add(label1);
  679.  
  680.         label13=new Label(creditString, Label.CENTER);
  681.         label13.setFont(Utility.creditFont);
  682.         creditPanel.add(label13);
  683.         Utility.fixGrid(creditPanel,1);
  684.  
  685.         add(creditPanel);
  686.  
  687.         // IO
  688.         Panel ioPanel = new Panel();
  689.  
  690.         label3=new Label("1.1 Number", Label.RIGHT);
  691.         label3.setFont(Utility.labelFont);
  692.         ioPanel.add(label3);
  693.  
  694.         outputText=new TextField(FIELD_COLUMNS);
  695.         outputText.setFont(Utility.editFont);
  696.         ioPanel.add(outputText);
  697.  
  698.         /*Panel gap1 = new Panel();
  699.         gap1.setLayout(null);
  700.         gap1.setSize(5,5);
  701.         gap1.add(outputText);
  702.  
  703.         Panel gap2 = new Panel();
  704.         gap2.setLayout(null);
  705.         gap2.setSize(5,5);
  706.         gap2.add(outputText);
  707.         */
  708.  
  709.         label2=new Label("1.0 Number", Label.RIGHT);
  710.         label2.setFont(Utility.labelFont);
  711.         ioPanel.add(label2);
  712.  
  713.         inputText=new TextField(FIELD_COLUMNS);
  714.         inputText.setFont(Utility.editFont);
  715.         ioPanel.add(inputText);
  716.  
  717.         label4=new Label("Pattern", Label.RIGHT);
  718.         label4.setFont(Utility.labelFont);
  719.         ioPanel.add(label4);
  720.  
  721.         patternText=new TextField(FIELD_COLUMNS);
  722.         patternText.setFont(Utility.editFont);
  723.         ioPanel.add(patternText);
  724.  
  725.         ioPanel.add(new Label(" "));
  726.  
  727.         getLocalized=new Checkbox("Localized Pattern");
  728.         getLocalized.setFont(Utility.labelFont);
  729.         ioPanel.add(getLocalized);
  730.  
  731.         Utility.fixGrid(ioPanel,2);
  732.         add(ioPanel);
  733.  
  734.          // LOCALE
  735.  
  736.         localePanel=new Panel();
  737.  
  738.         localeLabel=new Label("Locale:");
  739.         localeLabel.setFont(Utility.labelFont);
  740.         localePanel.add("loc",localeLabel);
  741.  
  742.         localeMenu= new Choice();
  743.         localeMenu.setBackground(Utility.choiceColor);
  744.         localeMenu.setFont(Utility.choiceFont);
  745.         localePanel.add(localeMenu);
  746.  
  747.         // FORMAT CHECKS
  748.  
  749.         group1= new CheckboxGroup();
  750.  
  751.         getInstance=new Checkbox("Default Format",group1, true);
  752.         getInstance.setFont(Utility.labelFont);
  753.         localePanel.add(getInstance);
  754.  
  755.         getCurrency=new Checkbox("Currency Format",group1, false);
  756.         getCurrency.setFont(Utility.labelFont);
  757.         localePanel.add(getCurrency);
  758.  
  759.         getPercent=new Checkbox("Percent Format",group1, false);
  760.         getPercent.setFont(Utility.labelFont);
  761.         localePanel.add(getPercent);
  762.  
  763.         Utility.fixGrid(localePanel,1);
  764.  
  765.         Panel bottomPanel = new Panel();
  766.  
  767.         bottomPanel.add(localePanel);
  768.  
  769.         BorderPanel x = new BorderPanel();
  770.         x.setBackground(Utility.bgColor);
  771.         x.setLayout(null);
  772.         x.setSize(8,130);
  773.         bottomPanel.add(x);
  774.  
  775.         // PARAMETERS
  776.  
  777.         Panel parameterPanel = new Panel();
  778.  
  779.         parameterPanel.add(new Label(" "));
  780.  
  781.         label11=new Label("Min", Label.CENTER);
  782.         label11.setFont(Utility.labelFont);
  783.         parameterPanel.add(label11);
  784.  
  785.         label12=new Label("Max", Label.CENTER);
  786.         label12.setFont(Utility.labelFont);
  787.         parameterPanel.add(label12);
  788.  
  789.  
  790.         label9=new Label("Integers", Label.RIGHT);
  791.         label9.setFont(Utility.labelFont);
  792.         parameterPanel.add(label9);
  793.  
  794.         intMin=new TextField(4);
  795.         intMin.setFont(Utility.editFont);
  796.         parameterPanel.add(intMin);
  797.  
  798.         intMax=new TextField(4);
  799.         intMax.setFont(Utility.editFont);
  800.         parameterPanel.add(intMax);
  801.  
  802.  
  803.         label10=new Label("Decimals", Label.RIGHT);
  804.         label10.setFont(Utility.labelFont);
  805.         parameterPanel.add(label10);
  806.  
  807.         decMin=new TextField(4);
  808.         decMin.setFont(Utility.editFont);
  809.         parameterPanel.add(decMin);
  810.  
  811.         decMax=new TextField(4);
  812.         decMax.setFont(Utility.editFont);
  813.         parameterPanel.add(decMax);
  814.  
  815.  
  816.         parameterPanel.add(new Label(" "));
  817.  
  818.         label7=new Label("Prefix", Label.CENTER);
  819.         label7.setFont(Utility.labelFont);
  820.         parameterPanel.add(label7);
  821.  
  822.         label8=new Label("Suffix", Label.CENTER);
  823.         label8.setFont(Utility.labelFont);
  824.         parameterPanel.add(label8);
  825.  
  826.  
  827.         label6=new Label("Positive", Label.RIGHT);
  828.         label6.setFont(Utility.labelFont);
  829.         parameterPanel.add(label6);
  830.  
  831.         posPrefix=new TextField(4);
  832.         posPrefix.setFont(Utility.editFont);
  833.         parameterPanel.add(posPrefix);
  834.  
  835.         posSuffix=new TextField(4);
  836.         posSuffix.setFont(Utility.editFont);
  837.         parameterPanel.add(posSuffix);
  838.  
  839.  
  840.         label5=new Label("Negative", Label.RIGHT);
  841.         label5.setFont(Utility.labelFont);
  842.         parameterPanel.add(label5);
  843.  
  844.         negPrefix=new TextField(4);
  845.         negPrefix.setFont(Utility.editFont);
  846.         parameterPanel.add(negPrefix);
  847.  
  848.         negSuffix=new TextField(4);
  849.         negSuffix.setFont(Utility.editFont);
  850.         parameterPanel.add(negSuffix);
  851.  
  852.         Utility.fixGrid(parameterPanel,3);
  853.  
  854.         bottomPanel.add(parameterPanel);
  855.         Utility.fixGrid(bottomPanel,3);
  856.         Utility.setInsets(bottomPanel,x,new Insets(20,20,2,2));
  857.         add(bottomPanel);
  858.  
  859.         Panel copyrightPanel = new Panel();
  860.         addWithFont (copyrightPanel,new Label(Utility.copyright1, Label.LEFT),
  861.                      Utility.creditFont);
  862.         addWithFont (copyrightPanel,new Label(Utility.copyright2, Label.LEFT),
  863.                      Utility.creditFont);
  864.         Utility.fixGrid(copyrightPanel,1);
  865.         add(copyrightPanel);
  866.     }
  867.  
  868.     private String toString( int anInt )
  869.     {
  870.         Integer intObj = new Integer(anInt);
  871.         return intObj.toString();
  872.     }
  873.  
  874.     private int parseIntField(TextComponent text) {
  875.         int result = 0;
  876.         try {
  877.             Integer value = new Integer(workaround(text.getText()));
  878.             result = value.intValue();
  879.         }
  880.         catch (NumberFormatException e) {
  881.         }
  882.         return result;
  883.     }
  884.  
  885.     private void intMinChanged(KeyEvent ev) {
  886.         format.setMinimumIntegerDigits(parseIntField(intMin));
  887.         updateAttributes();
  888.         handleAttributeChange();
  889.     }
  890.     private void intMaxChanged(KeyEvent ev) {
  891.         format.setMaximumIntegerDigits(parseIntField(intMax));
  892.         updateAttributes();
  893.         handleAttributeChange();
  894.     }
  895.     private void decMinChanged(KeyEvent ev) {
  896.         format.setMinimumFractionDigits(parseIntField(decMin));
  897.         updateAttributes();
  898.         handleAttributeChange();
  899.     }
  900.     private void decMaxChanged(KeyEvent ev) {
  901.         format.setMaximumFractionDigits(parseIntField(decMax));
  902.         updateAttributes();
  903.         handleAttributeChange();
  904.     }
  905.     private void negPrefixChanged(KeyEvent ev) {
  906.         format.setNegativePrefix(workaround(negPrefix.getText()));
  907.         updateAttributes();
  908.         handleAttributeChange();
  909.     }
  910.     private void negSuffixChanged(KeyEvent ev) {
  911.         format.setNegativeSuffix(workaround(negSuffix.getText()));
  912.         updateAttributes();
  913.         handleAttributeChange();
  914.     }
  915.     private void posPrefixChanged(KeyEvent ev) {
  916.         format.setPositivePrefix(workaround(posPrefix.getText()));
  917.         updateAttributes();
  918.         handleAttributeChange();
  919.     }
  920.     private void posSuffixChanged(KeyEvent ev) {
  921.         format.setPositiveSuffix(workaround(posSuffix.getText()));
  922.         updateAttributes();
  923.         handleAttributeChange();
  924.     }
  925.     /**
  926.      * Strips high bits, because of bug in Java
  927.      */
  928.     private static String workaround(String source) {
  929.         StringBuffer result = new StringBuffer();
  930.         for (int i = 0; i < source.length(); ++i)
  931.             result.append((char)(source.charAt(i) & 0xFF));
  932.         return result.toString();
  933.     }
  934.  
  935.     private void errorText(String s)
  936.     {
  937.         if (DEBUG)
  938.         {
  939.           System.out.println(s);
  940.         }
  941.     }
  942.  
  943.     private static final String creditString =
  944.         "v1.1a6, Demo:";
  945.  
  946.     private static final int FIELD_COLUMNS = 35;
  947.  
  948.     private static final boolean DEBUG = false;
  949.  
  950.     private static boolean isLocalized = false;
  951.  
  952.     // private Choice formatter, locale;
  953.  
  954.     private DecimalFormat format;
  955.     private Locale[] locales;
  956.  
  957.     //------------------------------------------------------------
  958.     // protected
  959.     //------------------------------------------------------------
  960.  
  961.     /* this must be protected so that the window adapter can access it */
  962.     protected DemoApplet applet;
  963.  
  964. }
  965.