home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / WDESAMPL.BIN / MessageFormatDemo.java < prev    next >
Text File  |  1997-03-17  |  30KB  |  953 lines

  1. /*
  2.  * @(#)MessageFormatDemo.java    1.1 96/11/23
  3.  *
  4.  * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  5.  * (C) Copyright IBM Corp. 1996 - All Rights Reserved
  6.  *
  7.  * Portions copyright (c) 1996 Sun Microsystems, Inc. All Rights Reserved.
  8.  *
  9.  *   The original version of this source code and documentation is copyrighted
  10.  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  11.  * materials are provided under terms of a License Agreement between Taligent
  12.  * and Sun. This technology is protected by multiple US and International
  13.  * patents. This notice and attribution to Taligent may not be removed.
  14.  *   Taligent is a registered trademark of Taligent, Inc.
  15.  *
  16.  * Permission to use, copy, modify, and distribute this software
  17.  * and its documentation for NON-COMMERCIAL purposes and without
  18.  * fee is hereby granted provided that this copyright notice
  19.  * appears in all copies. Please refer to the file "copyright.html"
  20.  * for further important copyright and licensing information.
  21.  *
  22.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  23.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  24.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  25.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  26.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  27.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  28.  *
  29.  */
  30.  
  31. import java.applet.Applet;
  32. import java.awt.event.*;
  33. import java.awt.*;
  34. import java.util.*;
  35. import java.lang.*;
  36. import java.text.*;
  37.  
  38. /**
  39.  * <P> Pattern formats are used to put together sequences of strings, numbers,
  40.  * dates, and other formats to create messages.  The pattern formatters
  41.  * facilitate localization because they prevent both hard-coding of message
  42.  * strings, <I> and </I> hard-coding of the concatenation sequence for portions
  43.  * of message strings.  This means localizers can change the content, format,
  44.  * and order of any text as appropriate for any language.
  45.  * </P>
  46.  * <P><CENTER>
  47.  * <A HREF="#format">About the Pattern Format</A> 
  48.  * <A HREF="#arguments">Formatting Arguments</A><BR>
  49.  * <A HREF="#choices">Supporting Multiple Choices</A>
  50.  * </CENTER></P>
  51.  * <HR>
  52.  * <H3><A NAME="format">About the Pattern Format </A></H3>
  53.  * <P> The pattern is a sequence of text and arguments, all of which can be
  54.  * edited.  The positions of the arguments within the sequence are indicated
  55.  * by a "%" followed by a digit <I> n </I> identifying the
  56.  * argument.  The pattern in the demo applet has three arguments, numbered 0,
  57.  * 1, and 2.  The arguments can appear in any order within the sequence, which
  58.  * can be edited and modified.
  59.  * </P>
  60.  * <TABLE WIDTH=100% CELLPADDING=5>
  61.  * <TR>
  62.  * <TH ALIGN=left VALIGN=bottom>To See This...</TH>
  63.  * <TH ALIGN=left VALIGN=bottom>Do This...</TH>
  64.  * </TR>
  65.  * <TR>
  66.  * <TD WIDTH=50% VALIGN=top> You can move arguments freely within the sequence
  67.  * or delete arguments.  You can also edit or translate any of the unformatted
  68.  * text.
  69.  * </TD>
  70.  * <TD VALIGN=top>
  71.  * <TABLE CELLSPACING=0 CELLPADDING=0>
  72.  * <TR>
  73.  * <TD WIDTH=10 VALIGN=top> 1.
  74.  * </TD>
  75.  * <TD> Move the string "on %2" from the end of the pattern to
  76.  * the front and correct the capitalization
  77.  * </TD>
  78.  * </TR>
  79.  * </TABLE>
  80.  * </TD>
  81.  * </TR>
  82.  * <TD WIDTH=50% VALIGN=top> Translations are provided in the demo applet for
  83.  * the G7 countries.
  84.  * </TD>
  85.  * <TD VALIGN=top>
  86.  * <TABLE CELLSPACING=0 CELLPADDING=0>
  87.  * <TR>
  88.  * <TD WIDTH=10 VALIGN=top> 1.
  89.  * </TD>
  90.  * <TD> Pull down the Locale menu
  91.  * </TD>
  92.  * </TR>
  93.  * <TR>
  94.  * <TD WIDTH=10 VALIGN=top> 2.
  95.  * </TD>
  96.  * <TD> Try several different locales with the up and down arrow keys (on
  97.  * Windows) or the mouse button (on Macintosh)
  98.  * </TD>
  99.  * </TR>
  100.  * </TABLE>
  101.  * </TD>
  102.  * </TR>
  103.  * </TABLE>
  104.  * <P><STRONG><I>Note:</I></STRONG> To add a real percentage character to the
  105.  * pattern, enter "%%".
  106.  * </P>
  107.  * <HR WIDTH=50% ALIGN=left>
  108.  * <H3><A NAME="arguments"> Formatting Arguments </A></H3>
  109.  * <P> The arguments can be either simple text strings or formattable,
  110.  * localizable objects.  The pattern in the demo applet, for example, includes
  111.  * a date, an unformatted string, and a more complex format called a <I> choice
  112.  * </I> format (described below).  You can edit these arguments at will.  When
  113.  * localizing, you can also select any format to be associated with an
  114.  * argument.
  115.  * </P>
  116.  * <TABLE WIDTH=100% CELLPADDING=5>
  117.  * <TR>
  118.  * <TH ALIGN=left VALIGN=bottom>To See This... </TH>
  119.  * <TH ALIGN=left VALIGN=bottom>Do This...</TH>
  120.  * </TR>
  121.  * <TR>
  122.  * <TD WIDTH=50% VALIGN=top> You can modify the value of any argument.
  123.  * </TD>
  124.  * <TD VALIGN=top>
  125.  * <TABLE CELLSPACING=0 CELLPADDING=0>
  126.  * <TR>
  127.  * <TD WIDTH=10 VALIGN=top> 1.
  128.  * </TD>
  129.  * <TD> Select the "3" in argument 2 and change it to another number
  130.  * —the formatted date adjusts to the new value
  131.  * </TD>
  132.  * </TR>
  133.  * </TABLE>
  134.  * </TD>
  135.  * </TR>
  136.  * <TR>
  137.  * <TD WIDTH=50% VALIGN=top> You can change the format of any argument, and can
  138.  * specify "unformatted" arguments that are not localized.
  139.  * </TD>
  140.  * <TD VALIGN=top>
  141.  * <TABLE CELLSPACING=0 CELLPADDING=0>
  142.  * <TR>
  143.  * <TD WIDTH=10 VALIGN=top> 1.
  144.  * </TD>
  145.  * <TD> Change the format type for argument 2 to <I> None </I>
  146.  * </TD>
  147.  * </TR>
  148.  * <TR>
  149.  * <TD WIDTH=10 VALIGN=top> 2.
  150.  * </TD>
  151.  * <TD> Try different locales and notice that the date does not reformat for
  152.  * different locales
  153.  * </TD>
  154.  * </TR>
  155.  * <TR>
  156.  * <TD WIDTH=10 VALIGN=top> 3.
  157.  * </TD>
  158.  * <TD> Return the format back to <I>Date </I> and try different locales again.
  159.  * The date reformats.
  160.  * </TD>
  161.  * </TR>
  162.  * </TABLE>
  163.  * </TD>
  164.  * </TR>
  165.  * </TABLE>
  166.  * <HR WIDTH=50% ALIGN=left>
  167.  * <H3> <A NAME="choices">Supporting Multiple Choices </A></H3>
  168.  * <P> Choice formats, like that used for argument 0, let localizers create
  169.  * more natural messages, avoiding phrases like "3 file(s)".  As
  170.  * shown here, the correct text can be chosen for different numbers.  This
  171.  * works even in more complicated contexts, such as Slavic languages which
  172.  * have more than one plural format based on the number involved.  A particular
  173.  * choice is chosen based on the value of the argument, and each choice can be
  174.  * edited individually.
  175.  * </P>
  176.  * <P> Look also at the format for the choice associated with values of 2 and
  177.  * higher, "%0|3".  The vertical bar indicates that the choice
  178.  * uses the value for argument 0, but the format for argument 3 (in this case,
  179.  * a Number).  This allows for a degree of flexibility in using different
  180.  * formats.
  181.  * </P>
  182.  * <TABLE WIDTH=100% CELLPADDING=5>
  183.  * <TR>
  184.  * <TH ALIGN=left VALIGN=bottom>To See This...</TH>
  185.  * <TH ALIGN=left VALIGN=bottom>Do This... </TH>
  186.  * </TR>
  187.  * <TR>
  188.  * <TD WIDTH=50% VALIGN=top> You can edit the value of any of the choice
  189.  * options.
  190.  * </TD>
  191.  * <TD VALIGN=top>
  192.  * <TABLE CELLSPACING=0 CELLPADDING=0>
  193.  * <TR>
  194.  * <TD WIDTH=10 VALIGN=top> 1.
  195.  * </TD>
  196.  * <TD> Select the Choice String "no files" and type in "not a
  197.  * single file"
  198.  * </TD>
  199.  * </TR>
  200.  * <TR>
  201.  * <TD WIDTH=10 VALIGN=top> 2.
  202.  * </TD>
  203.  * <TD> Select the value for argument 0 and type in "0"
  204.  * </TD>
  205.  * </TR>
  206.  * </TABLE>
  207.  * </TD>
  208.  * </TR>
  209.  * <TR>
  210.  * <TD WIDTH=50% VALIGN=top> You can establish different choices for parameters
  211.  * based on the value of an argument, so that strings are substituted that
  212.  * agree numerically.
  213.  * </TD>
  214.  * <TD VALIGN=top>
  215.  * <TABLE CELLSPACING=0 CELLPADDING=0>
  216.  * <TR>
  217.  * <TD WIDTH=10 VALIGN=top> 1.
  218.  * </TD>
  219.  * <TD> Select the value for argument 0 and type in "0", then replace
  220.  * it with a "1", and then with a "2".  The string changes
  221.  * correspondingly.
  222.  * </TD>
  223.  * </TR>
  224.  * <TR>
  225.  * <TD WIDTH=10 VALIGN=top> 2.
  226.  * </TD>
  227.  * <TD> Select argument 0 and return the value to "0".  Choose the
  228.  * French or German locale and notice that it makes correct substitutions in
  229.  * any language.
  230.  * </TD>
  231.  * </TR>
  232.  * </TABLE>
  233.  * </TD>
  234.  * </TR>
  235.  * <TR>
  236.  * <TD WIDTH=50% VALIGN=top> You can add as many alternatives as you need for
  237.  * different value ranges.
  238.  * </TD>
  239.  * <TD VALIGN=top>
  240.  * <TABLE CELLSPACING=0 CELLPADDING=0>
  241.  * <TR>
  242.  * <TD WIDTH=10 VALIGN=top> 1.
  243.  * </TD>
  244.  * <TD> Select the U.S. English locale
  245.  * </TD>
  246.  * </TR>
  247.  * <TR>
  248.  * <TD WIDTH=10 VALIGN=top> 2.
  249.  * </TD>
  250.  * <TD> Select the empty choice value box (under the "2") and type
  251.  * in "10"
  252.  * </TD>
  253.  * </TR>
  254.  * <TR>
  255.  * <TD WIDTH=10 VALIGN=top> 3.
  256.  * </TD>
  257.  * <TD> Type in "many files" in the corresponding <I> Choice Strings
  258.  * </I> field
  259.  * </TD>
  260.  * </TR>
  261.  * <TR>
  262.  * <TD WIDTH=10 VALIGN=top> 4.
  263.  * </TD>
  264.  * <TD> Enter a number larger than10 for the value of argument 0—"
  265.  * many files" is substituted in the resulting message
  266.  * </TD>
  267.  * </TR>
  268.  * </TABLE>
  269.  * </TD>
  270.  * </TR>
  271.  * </TABLE>
  272.  * <P>  You can type in other text in the pattern, arguments, or choices fields
  273.  * to  see different formatting behaviors.  Try it out!
  274.  * </P>
  275.  * @see        java.util.Format
  276.  * @see        java.util.MessageFormat
  277.  * @version    1.1 11/23/96
  278.  * @author     Laura Werner, Mark Davis
  279. */
  280.  
  281. public class MessageFormatDemo extends DemoApplet
  282. {
  283.     /**
  284.      * The main function which defines the behavior of the MessageFormatDemo
  285.      * applet when an applet is started.
  286.      */
  287.     public static void main(String argv[]) {
  288.         DemoApplet.showDemo(new MessageFormatFrame(null));
  289.     }
  290.  
  291.     /**
  292.      * This creates a MessageFormatFrame for the demo applet.
  293.      */
  294.     public Frame createDemoFrame(DemoApplet applet) {
  295.         return new MessageFormatFrame(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 MessageFormatFrame class defines the window layout of
  302.  * MessageFormatDemo.
  303.  */
  304.  class MessageFormatFrame extends Frame implements WindowListener, ItemListener, KeyListener {
  305.  
  306.     /**
  307.      * Constructs a new MessageFormatFrame that is initially invisible.
  308.      */
  309.     public MessageFormatFrame(DemoApplet applet)
  310.     {
  311.         super("Message Formatting Demo");
  312.         this.applet = applet;
  313.     addWindowListener(this);
  314.         init();
  315.         start();
  316.     }
  317.  
  318.     /**
  319.      * Initializes the applet. You never need to call this directly, it
  320.      * is called automatically by the system once the applet is created.
  321.      */
  322.     public void init() {
  323.  
  324.         //Get all locales for debugging, but only get G7 locales for demos.
  325.         if (DEBUG == true)
  326.              locales = NumberFormat.getAvailableLocales();
  327.         else locales = Utility.getG7Locales();
  328.  
  329.         buildGUI();
  330.  
  331.     }
  332.  
  333.     /**
  334.      * Called to start the applet. You never need to call this method
  335.      * directly, it is called when the applet's document is visited.
  336.      */
  337.     public void start() {
  338.  
  339.         // Stick some initial data into the controls....
  340.         arg1Text.setText("3");
  341.         arg1Type.select(CHOICE);
  342.  
  343.         arg2Text.setText("MyDisk");
  344.         arg2Type.select(NONE);
  345.  
  346.         arg3Text.setText("3 Mar 96");
  347.         arg3Type.select(DATE);
  348.  
  349.         arg4Text.setText("");
  350.         arg4Type.select(NUMBER);
  351.  
  352.         patternText.setText("The disk '%1' contained %0 on %2.");
  353.  
  354.         // Set up the choice format controls too
  355.         choice1Num.setText("0");
  356.         choice2Num.setText("1");
  357.         choice3Num.setText("2");
  358.         resetFormat();
  359.         doFormatting();
  360.  
  361.     }
  362.  
  363.     /**
  364.      * Reset to the default message format using the ResourceBundle mechanism.
  365.      * @see java.util.ResourceBundle
  366.      * @see java.util.ListResourceBundle
  367.      */
  368.     public void resetFormat() {
  369.         Locale locale = locales[localeMenu.getSelectedIndex()];
  370.  
  371.     ClassLoader classLoader = this.getClass().getClassLoader();
  372.  
  373.         choice4Num.setText("");
  374.         choice4Text.setText("");
  375.  
  376.         ResourceBundle choiceResources =
  377.              ResourceBundle.getBundle("ChoiceResource", locale);
  378.  
  379.     patternText.setText(choiceResources.getString("patternText"));
  380.         choice1Text.setText(choiceResources.getString("choice1"));
  381.         choice2Text.setText(choiceResources.getString("choice2"));
  382.         choice3Text.setText(choiceResources.getString("choice3"));
  383.     }
  384.  
  385.     /**
  386.      * Create a new format based on the selected type.  For example, a new
  387.      * format needs to be created if a different locale or format type is
  388.      * selected.
  389.      */
  390.     public Format createFormat(Choice typeMenu)
  391.     {
  392.         int type = typeMenu.getSelectedIndex();
  393.         Locale locale = locales[localeMenu.getSelectedIndex()];
  394.  
  395.         Format result = null;
  396.         if (type == NUMBER) {
  397.             result = NumberFormat.getInstance(locale);
  398.         }
  399.         else if (type == DATE) {
  400.             result = DateFormat.getDateInstance(DateFormat.DEFAULT, locale);
  401.         }
  402.         else if (type == CHOICE) {
  403.             result = choiceFormat;    // XXX
  404.         }
  405.         return result;
  406.     }
  407.  
  408.     /**
  409.      * Create a new format based on the selection changes and update the
  410.      * output text area.
  411.      */
  412.     public void doFormatting() {
  413.  
  414.         // Create a ChoiceFormat based on the settings in the choice field
  415.         double[] limits = new double[4];
  416.         limits[0] = doubleValue(choice1Num.getText());
  417.         limits[1] = doubleValue(choice2Num.getText());
  418.         limits[2] = doubleValue(choice3Num.getText());
  419.         limits[3] = doubleValue(choice4Num.getText());
  420.  
  421.         String[] choices = new String[4];
  422.         choices[0] = choice1Text.getText();
  423.         choices[1] = choice2Text.getText();
  424.         choices[2] = choice3Text.getText();
  425.         choices[3] = choice4Text.getText();
  426.  
  427.  
  428.         choiceFormat = new ChoiceFormat(limits, choices);    // XXX
  429.  
  430.         // Create the individual formatters for the items in the pattern....
  431.         Format[] formats = new Format[4];
  432.         formats[0] = createFormat(arg1Type);
  433.         formats[1] = createFormat(arg2Type);
  434.         formats[2] = createFormat(arg3Type);
  435.         formats[3] = createFormat(arg4Type);
  436.  
  437.         // Now create the Message Formatter itself
  438.         MessageFormat format = new MessageFormat(patternText.getText());
  439.  
  440.         // Create the array of objects to format....
  441.         Object[] objects = new Object[4];
  442.         objects[0] = createObject(arg1Type, arg1Text);
  443.         objects[1] = createObject(arg2Type, arg2Text);
  444.         objects[2] = createObject(arg3Type, arg3Text);
  445.         objects[3] = createObject(arg4Type, arg4Text);
  446.  
  447.         String result = null;
  448.         try {
  449.             result = format.format(objects);
  450.         }
  451.         catch (Exception e)
  452.         {
  453.             errorText("format threw an exception: " + e.toString());
  454.             result = "ERROR";
  455.         }
  456.         resultText.setText(result);
  457.     }
  458.  
  459.   /* ItemListener method */
  460.   public void itemStateChanged(ItemEvent e) {
  461.     if((e.getSource() == arg1Type) || (e.getSource() == arg2Type) || (e.getSource() == arg3Type)
  462.        || (e.getSource() == arg4Type)) {
  463.       doFormatting();
  464.     } else if (e.getSource() == localeMenu) {
  465.       resetFormat();
  466.       doFormatting();
  467.     }
  468.   }
  469.   
  470.   /* KeyListener methods */
  471.   public void keyPressed(KeyEvent e) {
  472.   }
  473.  
  474.   public void keyReleased(KeyEvent e) {
  475.     if ((e.getSource() == choice1Text) || (e.getSource() == choice2Text) || 
  476.     (e.getSource() == choice3Text) || (e.getSource() == choice4Text)) {
  477.       e.consume();
  478.       doFormatting();
  479.     } else if ((e.getSource() == choice1Num) ||(e.getSource() == choice2Num) ||
  480.            (e.getSource() == choice3Num) ||(e.getSource() == choice4Num)) {
  481.       e.consume();
  482.       doFormatting();
  483.     } else if ((e.getSource() == arg1Text) ||(e.getSource() == arg2Text) ||
  484.            (e.getSource() == arg3Text) ||(e.getSource() == arg4Text)) {
  485.       e.consume();
  486.       doFormatting();
  487.     } else if (e.getSource() == patternText) {
  488.       e.consume();
  489.       doFormatting();
  490.     }
  491.       
  492.   }
  493.  
  494.   public void keyTyped(KeyEvent e) {
  495.   }
  496.   
  497.   /* Window Listener methods */
  498.   public void windowClosed(WindowEvent e) {
  499.   }
  500.  
  501.   public void windowDeiconified(WindowEvent e) {
  502.   }
  503.  
  504.   public void windowIconified(WindowEvent e) {
  505.   }
  506.  
  507.   public void windowActivated(WindowEvent e) {
  508.   }
  509.  
  510.   public void windowDeactivated(WindowEvent e) {
  511.   }
  512.  
  513.   public void windowOpened(WindowEvent e) {
  514.   }
  515.  
  516.   public void windowClosing(WindowEvent e) {
  517.     setVisible(false);
  518.     dispose();
  519.  
  520.     if (applet != null) {
  521.       applet.demoClosed();
  522.     } else System.exit(0);
  523.  
  524.   }
  525.  
  526.     //------------------------------------------------------------
  527.     // package private
  528.     //------------------------------------------------------------
  529.  
  530.     double doubleValue(String s) {
  531.         try {
  532.             return Double.valueOf(s).doubleValue();
  533.         } catch (Exception foo) {
  534.             return Double.POSITIVE_INFINITY;
  535.         }
  536.     }
  537.  
  538.     void constrainedAdd(GridBagConstraints c,
  539.                         Container container,
  540.                         Component foo,
  541.                         Font font) {
  542.         GridBagLayout gridbag = (GridBagLayout)container.getLayout();
  543.         if (font != null)
  544.             foo.setFont(font);
  545.         gridbag.setConstraints(foo, c);
  546.         container.add(foo);
  547.     }
  548.  
  549.     Choice cloneChoice (Choice source) {
  550.         Choice result = new Choice();
  551.         for (int i = 0; i < source.getItemCount(); ++i)
  552.             result.addItem(source.getItem(i));
  553.         result.setFont(source.getFont());
  554.         return result;
  555.     }
  556.  
  557.  
  558.     void addWithFont(Container container, Component foo, Font font) {
  559.         if (font != null)
  560.             foo.setFont(font);
  561.         container.add(foo);
  562.     }
  563.  
  564.     //{{DECLARE_CONTROLS
  565.     Label label1;
  566.     Label label2;
  567.     TextField patternText;
  568.     Label label3;
  569.     Label label4;
  570.     Label label5;
  571.     Label labelArg;
  572.     Label labelForm;
  573.     TextField arg1Text;
  574.     TextField arg2Text;
  575.     TextField arg3Text;
  576.     Choice arg1Type;
  577.     Choice arg2Type;
  578.     Choice arg3Type;
  579.     Label label6;
  580.     Choice localeMenu;
  581.     Label localeLabel;
  582.     Label label13;
  583.     Label label14;
  584.     TextField resultText;
  585.     Label label7;
  586.     Label label8;
  587.     Label label9;
  588.     TextField choice1Num;
  589.     TextField choice2Num;
  590.     TextField choice3Num;
  591.     TextField choice4Num;
  592.     TextField choice1Text;
  593.     TextField choice2Text;
  594.     TextField choice3Text;
  595.     TextField choice4Text;
  596.     Label label10;
  597.     Label label11;
  598.     Label label12;
  599.     TextField arg4Text;
  600.     Choice arg4Type;
  601.     //}}
  602.  
  603.     //------------------------------------------------------------
  604.     // private
  605.     //------------------------------------------------------------
  606.     private void buildGUI() {
  607.  
  608.         //{{INIT_CONTROLS
  609.         setLayout(new FlowLayout(FlowLayout.CENTER,2,2));   // MD 8/7
  610.         setBackground(Color.white); // MD 8/7
  611.  
  612.         // Main Title
  613.  
  614.         Panel titleCreditPanel = new Panel();
  615.         label6=new Label("Message Format Demo", Label.CENTER);
  616.         label6.setFont(Utility.titleFont);
  617.         titleCreditPanel.add(label6);
  618.  
  619.         Panel creditPanel = new Panel();
  620.         label13=new Label(creditString);
  621.         label13.setFont(Utility.creditFont);
  622.         creditPanel.add(label13);
  623.  
  624.         titleCreditPanel.add(creditPanel);
  625.  
  626.         Utility.fixGrid(titleCreditPanel,1);
  627.  
  628.         // result text
  629.  
  630.         Panel patternResultPanel = new Panel();
  631.  
  632.         addWithFont(patternResultPanel,new
  633.             Label("Result", Label.RIGHT),Utility.labelFont);
  634.         addWithFont(patternResultPanel,resultText= new
  635.             TextField(FIELD_COLUMNS),Utility.editFont);
  636.  
  637.         addWithFont(patternResultPanel,new
  638.             Label("Pattern", Label.RIGHT),Utility.labelFont);
  639.         addWithFont(patternResultPanel,patternText=new
  640.             TextField(FIELD_COLUMNS),Utility.editFont);
  641.  
  642.     patternText.addKeyListener(this);
  643.         Utility.fixGrid(patternResultPanel,2);
  644.  
  645.         // Locale and credits
  646.  
  647.         Panel localeCreditPanel = new Panel();
  648.         // localeCreditPanel.setLayout(new GridBagLayout());
  649.  
  650.         localeLabel=new Label("Locale:",Label.LEFT);
  651.         localeLabel.setFont(Utility.labelFont);
  652.         //localeCreditPanel.add("loc",localeLabel);
  653.  
  654.         // LOCALE
  655.         localeMenu= new Choice();
  656.     localeMenu.addItemListener(this);
  657.         // Stick the names of the locales into the locale popup menu
  658.         Locale displayLocale = Locale.getDefault();
  659.         for (int i = 0; i < locales.length; i++) {
  660.             if (locales[i].getCountry().length() > 0) {
  661.                 localeMenu.addItem( locales[i].getDisplayName() );
  662.                 if (locales[i].equals(Locale.getDefault())) {
  663.                     localeMenu.select(i);
  664.                 }
  665.             }
  666.         }
  667.            localeMenu.setFont(Utility.choiceFont);
  668.  
  669.         Panel localePanel=new Panel();
  670.         localePanel.add(localeLabel);
  671.         localePanel.add(localeMenu);
  672.         localeCreditPanel.add(localePanel);
  673.  
  674.         arg1Type= new Choice();
  675.            arg1Type.setFont(Utility.choiceFont);
  676.         arg1Type.addItem("Number");
  677.         arg1Type.addItem("Date");
  678.         arg1Type.addItem("Choice");
  679.         arg1Type.addItem("None");
  680.     arg1Type.addItemListener(this);
  681.  
  682.         // PUT THE ARGUMENTS/ FORMATS into GRID
  683.         Panel allArgs = new Panel();
  684.  
  685.         addWithFont(allArgs,new Label(" "),Utility.labelFont);
  686.         addWithFont(allArgs,new Label("Arguments", Label.LEFT),
  687.                                       Utility.labelFont);
  688.         addWithFont(allArgs,new Label("0",Label.RIGHT),Utility.labelFont);
  689.         addWithFont(allArgs,arg1Text=new TextField(12),Utility.editFont);
  690.         addWithFont(allArgs,new Label("1",Label.RIGHT),Utility.labelFont);
  691.         addWithFont(allArgs,arg2Text=new TextField(12),Utility.editFont);
  692.         addWithFont(allArgs,new Label("2",Label.RIGHT),Utility.labelFont);
  693.         addWithFont(allArgs,arg3Text=new TextField(12),Utility.editFont);
  694.         addWithFont(allArgs,new Label("3",Label.RIGHT),Utility.labelFont);
  695.         addWithFont(allArgs,arg4Text=new TextField(12),Utility.editFont);
  696.  
  697.     arg1Text.addKeyListener(this);
  698.     arg2Text.addKeyListener(this);
  699.     arg3Text.addKeyListener(this);
  700.     arg4Text.addKeyListener(this);
  701.  
  702.         Utility.fixGrid(allArgs,2);
  703.  
  704.         Panel formatPanel = new Panel();
  705.         addWithFont(formatPanel,new Label(" "),Utility.labelFont);
  706.         addWithFont(formatPanel,new Label("Formats", Label.LEFT),
  707.                     Utility.labelFont);
  708.  
  709.         addWithFont(formatPanel,new Label("0",Label.RIGHT),Utility.labelFont);
  710.         addWithFont(formatPanel,arg1Type,Utility.choiceFont);
  711.  
  712.         addWithFont(formatPanel,new Label("1",Label.RIGHT),Utility.labelFont);
  713.         addWithFont(formatPanel,arg2Type = cloneChoice(arg1Type),
  714.                     Utility.choiceFont);
  715.  
  716.         addWithFont(formatPanel,new Label("2",Label.RIGHT),Utility.labelFont);
  717.         addWithFont(formatPanel,arg3Type = cloneChoice(arg1Type),
  718.                     Utility.choiceFont);
  719.  
  720.         addWithFont(formatPanel,new Label("3",Label.RIGHT),Utility.labelFont);
  721.         addWithFont(formatPanel,arg4Type = cloneChoice(arg1Type),
  722.                     Utility.choiceFont);
  723.  
  724.     arg2Type.addItemListener(this);
  725.     arg3Type.addItemListener(this);
  726.     arg4Type.addItemListener(this);
  727.  
  728.         Utility.fixGrid(formatPanel,2);
  729.  
  730.         // Choices panel
  731.  
  732.         Panel choicesPanel = new Panel();
  733.         addWithFont(choicesPanel,new Label(">=", Label.LEFT),
  734.                     Utility.labelFont);
  735.         addWithFont(choicesPanel,new Label("Choice Strings", Label.LEFT),
  736.                     Utility.labelFont);
  737.  
  738.         addWithFont(choicesPanel,choice1Num=new TextField(4),
  739.                     Utility.editFont);
  740.         addWithFont(choicesPanel,choice1Text=new TextField(16),
  741.                     Utility.editFont);
  742.         addWithFont(choicesPanel,choice2Num=new TextField(4),
  743.                     Utility.editFont);
  744.         addWithFont(choicesPanel,choice2Text=new TextField(16),
  745.                     Utility.editFont);
  746.         addWithFont(choicesPanel,choice3Num=new TextField(4),
  747.                     Utility.editFont);
  748.         addWithFont(choicesPanel,choice3Text=new TextField(16),
  749.                     Utility.editFont);
  750.         addWithFont(choicesPanel,choice4Num=new TextField(4),
  751.                     Utility.editFont);
  752.         addWithFont(choicesPanel,choice4Text=new TextField(16),
  753.                     Utility.editFont);
  754.  
  755.     choice1Text.addKeyListener(this);
  756.     choice2Text.addKeyListener(this);
  757.     choice3Text.addKeyListener(this);
  758.     choice4Text.addKeyListener(this);
  759.     choice1Num.addKeyListener(this);
  760.     choice2Num.addKeyListener(this);
  761.     choice3Num.addKeyListener(this);
  762.     choice4Num.addKeyListener(this);
  763.  
  764.         Utility.fixGrid(choicesPanel,2);
  765.         add(titleCreditPanel);
  766.         add(patternResultPanel);
  767.         add(localeCreditPanel);
  768.         Panel bottomPanel = new Panel();
  769.         bottomPanel.add(allArgs);
  770.  
  771.         XBorderPanel x = new XBorderPanel(); // MD 8/7
  772.         x.setBackground(Color.lightGray);
  773.         x.setLayout(null);
  774.         x.setSize(8,130);
  775.         bottomPanel.add(x);
  776.  
  777.         bottomPanel.add(formatPanel);
  778.  
  779.         XBorderPanel x1 = new XBorderPanel(); // MD 8/7
  780.         x1.setBackground(Color.lightGray);
  781.         x1.setLayout(null);
  782.         x1.setSize(8,130);
  783.         bottomPanel.add(x1);
  784.  
  785.         bottomPanel.add(choicesPanel);
  786.         Utility.fixGrid(bottomPanel,5);
  787.         // MD 8/7 only after fixGrid
  788.         Utility.setInsets(bottomPanel,x,new Insets(20,20,2,2));
  789.         Utility.setInsets(bottomPanel,x1,new Insets(20,20,2,20));
  790.  
  791.         add(bottomPanel);
  792.  
  793.         Panel copyrightPanel = new Panel();
  794.         addWithFont (copyrightPanel,new Label(copyrightString, Label.LEFT),
  795.                      Utility.creditFont);
  796.         addWithFont (copyrightPanel,new Label(copyrightString2, Label.LEFT),
  797.                      Utility.creditFont);
  798.         Utility.fixGrid(copyrightPanel,1);
  799.         add(copyrightPanel);
  800.  
  801.     }
  802.  
  803.     private Object createObject(Choice typeMenu, TextField textField )
  804.     {
  805.         int type = typeMenu.getSelectedIndex();
  806.         String text = textField.getText();
  807.  
  808.         Object result = null;
  809.  
  810.         try {
  811.             if (type == NUMBER || type == CHOICE)
  812.             {
  813.                 result = new Double(text);
  814.             }
  815.             else if (type == DATE)
  816.             {
  817.           // Still use the deprecated new Date(text) until 
  818.           // the DateFormat.parse(text) is working properly.
  819.           result = new Long( (new Date(text)).getTime() + 1);
  820.           // 1 millisecond was added to display the date correctly.
  821.           // This is done to fix the following scenario, eg,
  822.           // "27 Sept 96" ==> "26 Sept 96 12:00 AM PDT" which is
  823.           // equvalent to "27 Sept 96 00:00 AM PDT".  -- CLH 9/27/96
  824.             }
  825.             else if (type == NONE)
  826.             {
  827.                 result = text;
  828.             }
  829.         }
  830.         catch (RuntimeException e) {
  831.         }
  832.         return result;
  833.     }
  834.  
  835.     private void errorText(String s)
  836.     {
  837.         if (DEBUG)
  838.         {
  839.            System.out.println(s);
  840.  
  841.         }
  842.     }
  843.     private static final String creditString =
  844.         "v1.1a7, Demos";
  845.     private static final String copyrightString =
  846.         "";
  847.     private static final String copyrightString2 =
  848.         "";
  849.     private static final int FIELD_COLUMNS = 60;
  850.  
  851.     static private final int NUMBER = 0;
  852.     static private final int DATE = 1;
  853.     static private final int CHOICE = 2;
  854.     static private final int NONE = 3;
  855.  
  856.     private static final boolean DEBUG = false;
  857.  
  858.     private Locale[] locales;
  859.  
  860.     private DemoApplet applet;
  861.  
  862.     private ChoiceFormat choiceFormat;    // XXX
  863. }
  864.  
  865. // MD 8/7 whole class, from Ralf. Use different name!
  866. class XBorderPanel extends Panel
  867. {
  868.    /**
  869.     * Panel shadow border width
  870.     */
  871.    protected int shadow = 4;
  872.  
  873.    /**
  874.     * Panel raised vs depressed look
  875.     */
  876.    protected boolean raised = true;
  877.  
  878.     public XBorderPanel() {
  879.         this.raised=true;
  880.     }
  881.  
  882.     public XBorderPanel(boolean raised) {
  883.         this.raised=raised;
  884.     }
  885.  
  886.  
  887.    /**
  888.     * Re-layout parent. Called when a panel changes
  889.     * size etc.
  890.     */
  891.    protected void layoutParent() {
  892.       Container parent = getParent();
  893.       if (parent != null) {
  894.      parent.doLayout();
  895.       }
  896.    }
  897.  
  898.    public void paint(Graphics g) {
  899.         super.paint(g);
  900.         Dimension size = getSize();
  901.         paintBorder(g, size);
  902.     }
  903.  
  904.    protected void paintBorder(Graphics g, Dimension size) {
  905.       Color c = getBackground();
  906.       g.setColor(c);
  907.       g.fillRect(0, 0, size.width, size.height);
  908.       draw3DRect(g, 0, 0, size.width, size.height, raised);
  909.    }
  910.  
  911.    /**
  912.     * Draw a 3D Rectangle.
  913.     * @param g the specified Graphics window
  914.     * @param x, y, width, height
  915.     * @param raised - true if border should be painted as raised.
  916.     * @see #paint
  917.     */
  918.    public void draw3DRect(Graphics g, int x, int y, int width, int height,
  919.               boolean raised) {
  920.       Color c = g.getColor();
  921.       Color brighter = avgColor(c,Color.white);
  922.       Color darker = avgColor(c,Color.black);
  923.  
  924.  
  925.       // upper left corner
  926.       g.setColor(raised ? brighter : darker);
  927.       for (int i=0; i<shadow; i++) {
  928.       g.drawLine(x+i, y+i, x+width-1-i, y+i);
  929.       g.drawLine(x+i, y+i, x+i, y+height-1-i);
  930.       }
  931.       // lower right corner
  932.       g.setColor(raised ? darker : brighter);
  933.       for (int i=0; i<shadow; i++) {
  934.       g.drawLine(x+i, y+height-1-i, x+width-1-i, y+height-1-i);
  935.       g.drawLine(x+width-1-i, y+height-1-i, x+width-1-i, y+i);
  936.       }
  937.       g.setColor(c);
  938.       // added by rip.
  939.       g.setColor(Color.black);
  940.       g.drawRect(x,y,width+2,height+2);
  941.  
  942.    }
  943.  
  944.    public static Color avgColor(Color c1, Color c2) {
  945.     return new Color(
  946.         (c1.getRed()+c2.getRed())/2,
  947.         (c1.getGreen()+c2.getGreen())/2,
  948.         (c1.getBlue()+c2.getBlue())/2
  949.         );
  950.    }
  951.  
  952. }
  953.