TextField.java
上传用户:haobig99
上传日期:2022-06-15
资源大小:369k
文件大小:47k
源码类别:

J2ME

开发平台:

Java

  1. /*
  2.  * Copyright 2008 Sun Microsystems, Inc.  All Rights Reserved.
  3.  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4.  *
  5.  * This code is free software; you can redistribute it and/or modify it
  6.  * under the terms of the GNU General Public License version 2 only, as
  7.  * published by the Free Software Foundation.  Sun designates this
  8.  * particular file as subject to the "Classpath" exception as provided
  9.  * by Sun in the LICENSE file that accompanied this code.
  10.  *
  11.  * This code is distributed in the hope that it will be useful, but WITHOUT
  12.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14.  * version 2 for more details (a copy is included in the LICENSE file that
  15.  * accompanied this code).
  16.  *
  17.  * You should have received a copy of the GNU General Public License version
  18.  * 2 along with this work; if not, write to the Free Software Foundation,
  19.  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20.  *
  21.  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22.  * CA 95054 USA or visit www.sun.com if you need additional information or
  23.  * have any questions.
  24.  */
  25. package com.sun.lwuit;
  26. import com.sun.lwuit.util.EventDispatcher;
  27. import com.sun.lwuit.events.ActionEvent;
  28. import com.sun.lwuit.events.ActionListener;
  29. import com.sun.lwuit.events.DataChangedListener;
  30. import com.sun.lwuit.geom.Dimension;
  31. import com.sun.lwuit.layouts.GridLayout;
  32. import com.sun.lwuit.plaf.UIManager;
  33. import java.util.Hashtable;
  34. import java.util.Vector;
  35. /**
  36.  * Allows in place editing using a lightweight API without necessarily moving to
  37.  * the external native text box. The main drawback in this approach is that editing
  38.  * can't support features such as T9 and might not have the same keymapping or
  39.  * behavior of the native text input.
  40.  * <p>Notice that due to limitations of text area and text field input modes in
  41.  * text area aren't properly supported since they won't work properly across devices.
  42.  * To limit input modes please use the setInputModeOrder method. All constants 
  43.  * declated in TextArea are ignored with the exception of PASSWORD.
  44.  * 
  45.  * @author Shai Almog
  46.  */
  47. public class TextField extends TextArea {
  48.     private static boolean replaceMenuDefault = true;
  49.     private long cursorBlinkTime = System.currentTimeMillis();
  50.     private boolean drawCursor = true;
  51.     private int cursorCharPosition = -1;
  52.     private boolean pressedAndNotReleased;
  53.     private long pressTime;
  54.     private boolean useSoftkeys = true;
  55.     private long releaseTime;
  56.     private String previousText;
  57.     private int commitTimeout = 1000;
  58.     private boolean pendingCommit;
  59.     private int pressCount = 0;
  60.     private int lastKeyCode;
  61.     private int pressedKeyCode;
  62.     private static String clearText = "Clear";
  63.     private static String t9Text = "T9";
  64.     private boolean longClick;
  65.     private Command originalClearCommand;
  66.     private static Hashtable inputModes;    
  67.     private static String[] defaultInputModeOrder = {"Abc", "ABC", "abc", "123"};
  68.     private String inputMode = defaultInputModeOrder[0];
  69.     private String[] inputModeOrder = defaultInputModeOrder;
  70.     private static Vector firstUppercaseInputMode = new Vector();
  71.     private int blinkOnTime = 800;
  72.     private int blinkOffTime = 200;
  73.     private static boolean qwertyAutoDetect = true;
  74.     private boolean qwertyInitialized;
  75.     private static boolean qwertyDevice;
  76.     private boolean qwerty = qwertyDevice;
  77.     private boolean replaceMenu = replaceMenuDefault;
  78.     private Command[] originalCommands;
  79.     private EventDispatcher listeners = new EventDispatcher();
  80.     private boolean overwriteMode;
  81.     private boolean enableInputScroll = true;
  82.     private int keyFwd = Display.GAME_RIGHT;
  83.     private int keyBack = Display.GAME_LEFT;
  84.     
  85.     /**
  86.      * Indicates whether the left/right keys will trigger editing, this is true by default.
  87.      * Left and right key edit trigger might be disabled for cases such as text field
  88.      * positioned horizontally one next to the other.
  89.      */
  90.     private boolean leftAndRightEditingTrigger = true;
  91.     /**
  92.      * Key to change the input mode on the device
  93.      */
  94.     private static int defaultChangeInputModeKey = '#';
  95.     
  96.     /**
  97.      * The default key for poping open the symbol dialog
  98.      */
  99.     private static int defaultSymbolDialogKey = '*';
  100.     private Command selectCommand;
  101.     
  102.     /**
  103.      * Set the text that should appear on the clear softkey
  104.      * 
  105.      * @param text localized text for the clear softbutton
  106.      */
  107.     public static void setClearText(String text) {
  108.         clearText = text;
  109.     }
  110.     /**
  111.      * Set the text that should appear on the T9 softkey
  112.      * 
  113.      * @param text text for the T9 softbutton
  114.      */
  115.     public static void setT9Text(String text) {
  116.         t9Text = text;
  117.     }
  118.     /**
  119.      * @inheritDoc
  120.      */
  121.     public boolean isEnableInputScroll() {
  122.         return enableInputScroll;
  123.     }
  124.     /**
  125.      * Indicates whether text field input should scroll to the right side when no
  126.      * more room for the input is present.
  127.      *
  128.      * @param enableInputScroll true to enable scrolling to the side
  129.      */
  130.     public void setEnableInputScroll(boolean enableInputScroll) {
  131.         this.enableInputScroll = enableInputScroll;
  132.     }
  133.     class CommandHandler extends Command {
  134.         CommandHandler(String title, int id) {
  135.             super(title, id);
  136.         }
  137.         public void actionPerformed(ActionEvent ev) {
  138.             ev.consume();
  139.             switch(getId()) {
  140.                 case 1:
  141.                     // key press for activating clear causes keyRelease never to be 
  142.                     // called triggering a long click, this code disables the long click
  143.                     releaseTime = System.currentTimeMillis();
  144.                     pressedAndNotReleased = false;
  145.                     longClick = false;
  146.                     deleteChar();
  147.                     break;
  148.                 case 2:
  149.                     ev.consume();
  150.                     editString();
  151.                     break;
  152.             }
  153.         }
  154.     }
  155.     private Command DELETE_COMMAND = new CommandHandler(clearText, 1);
  156.     private Command T9_COMMAND = new CommandHandler(t9Text, 2);
  157.     private static final char[] DEFAULT_SYMBOL_TABLE = new char[] {
  158.         '.', ',', '?', '!', '$', '@', ''', '-',
  159.         '_', ')', '(', ':', ';', '&', '/', '~',
  160.         '\', '%', '*', '#', '+', '>', '=', '<',
  161.         '"'
  162.     };
  163.     
  164.     private static char[] symbolTable = DEFAULT_SYMBOL_TABLE;
  165.     
  166.     private static final String[] DEFAULT_KEY_CODES = {
  167.         // 0
  168.         " 0",
  169.         // 1
  170.         ".,?!'"1-()@/:_",
  171.         // 2
  172.         "ABC2",
  173.         // 3
  174.         "DEF3",
  175.         // 4
  176.         "GHI4",
  177.         // 5
  178.         "JKL5",
  179.         // 6
  180.         "MNO6",
  181.         // 7
  182.         "PQRS7",
  183.         // 8
  184.         "TUV8",
  185.         // 9
  186.         "WXYZ9",
  187.     };
  188.     /**
  189.      * Default constructor
  190.      */
  191.     public TextField() {
  192.         super(1, 20);
  193.         setUIID("TextField");
  194.     }
  195.     
  196.     /**
  197.      * Construct a text field with space reserved for columns
  198.      * 
  199.      * @param columns - the number of columns
  200.      */
  201.     public TextField(int columns) {
  202.         super(1, columns);
  203.         setUIID("TextField");
  204.     }
  205.     
  206.     /**
  207.      * Construct text field 
  208.      * 
  209.      * @param text the text of the field
  210.      */
  211.     public TextField(String text) {
  212.         super(text, 1, 20);
  213.         setUIID("TextField");
  214.     }
  215.     
  216.     /**
  217.      * Performs a backspace operation
  218.      */
  219.     public void deleteChar() {
  220.         String text = getText();
  221.         if(text.length() > 0) {
  222.             if(cursorCharPosition > 0) {
  223.                 cursorCharPosition--;
  224.                 if(!overwriteMode) {
  225.                     text = text.substring(0, cursorCharPosition) +
  226.                         text.substring(cursorCharPosition + 1, text.length());
  227.                     super.setText(text);
  228.                     commitChange();
  229.                     fireDataChanged(DataChangedListener.REMOVED, cursorCharPosition);
  230.                 }
  231.             }
  232.         }
  233.     }
  234.     
  235.     /**
  236.      * Construct text field 
  237.      * 
  238.      * @param text the text of the field
  239.      * @param columns - the number of columns
  240.      */
  241.     public TextField(String text, int columns) {
  242.         super(text, 1, columns);
  243.     }
  244.     
  245.     /**
  246.      * Construct text field/area depending on whether native in place editing is supported 
  247.      * 
  248.      * @param text the text of the field
  249.      * @param columns - the number of columns
  250.      * @return a text field if native in place editing is unsupported and a text area if it is
  251.      */
  252.     public static TextArea create(String text, int columns) {
  253.         if(Display.getInstance().getImplementation().isNativeInputSupported()) {
  254.             return new TextArea(text, 1, columns);
  255.         }
  256.         return new TextField(text, columns);
  257.     }
  258.     
  259.     
  260.     /**
  261.      * Default factory method
  262.      * 
  263.      * @return a text field if native in place editing is unsupported and a text area if it is
  264.      */
  265.     public static TextArea create() {
  266.         return create(20);
  267.     }
  268.     
  269.     /**
  270.      * Construct text field/area depending on whether native in place editing is supported 
  271.      * 
  272.      * @param columns - the number of columns
  273.      * @return a text field if native in place editing is unsupported and a text area if it is
  274.      */
  275.     public static TextArea create(int columns) {
  276.         return create("", columns);
  277.     }
  278.     
  279.     /**
  280.      * Construct text field/area depending on whether native in place editing is supported 
  281.      * 
  282.      * @param text the text of the field
  283.      * @return a text field if native in place editing is unsupported and a text area if it is
  284.      */
  285.     public static TextArea create(String text) {
  286.         return create(text, 20);
  287.     }
  288.         
  289.     /**
  290.      * Commit the changes made to the text field as a complete edit operation. This
  291.      * is used in a numeric keypad to allow the user to repeatedly press a number
  292.      * to change values.
  293.      */
  294.     protected void commitChange() {
  295.         pendingCommit = false;
  296.         previousText = null;
  297.         pressCount = 0;
  298.     }
  299.     /**
  300.      * @inheritDoc
  301.      */
  302.     public boolean isPendingCommit() {
  303.         return pendingCommit;
  304.     }
  305.     
  306.     /**
  307.      * The amount of time in milliseconds it will take for a change to get committed into
  308.      * the field.
  309.      * 
  310.      * @param commitTimeout indicates the amount of time that should elapse for a commit
  311.      * to automatically occur
  312.      */
  313.     public void setCommitTimeout(int commitTimeout) {
  314.         this.commitTimeout = commitTimeout;
  315.     }
  316.     
  317.     /**
  318.      * The amount of time in milliseconds it will take for a change to get committed into
  319.      * the field.
  320.      * 
  321.      * @return the time for a commit timeout
  322.      */
  323.     public int getCommitTimeout() {
  324.         return commitTimeout;
  325.     }
  326.     
  327.     /**
  328.      * Sets the current selected input mode matching one of the existing input
  329.      * modes
  330.      * 
  331.      * @param inputMode the display name of the input mode by default the following modes
  332.      * are supported: Abc, ABC, abc, 123
  333.      */
  334.     public void setInputMode(String inputMode) {
  335.         this.inputMode = inputMode;
  336.         repaint();
  337.     }
  338.     
  339.     /**
  340.      * @inheritDoc
  341.      */
  342.     public String getInputMode() {
  343.         return inputMode;
  344.     }
  345.     
  346.     /**
  347.      * Indicates whether the key changes the current input mode
  348.      * 
  349.      * @param keyCode the code
  350.      * @return true for the hash (#) key code
  351.      */
  352.     protected boolean isChangeInputMode(int keyCode) {
  353.         return keyCode == defaultChangeInputModeKey;
  354.     }
  355.     private static void initInputModes() {
  356.         if(inputModes == null) {
  357.             firstUppercaseInputMode.addElement("Abc");
  358.             inputModes = new Hashtable();
  359.             Hashtable upcase = new Hashtable();
  360.             for(int iter = 0 ; iter < DEFAULT_KEY_CODES.length ; iter++) {
  361.                 upcase.put(new Integer('0' + iter), DEFAULT_KEY_CODES[iter]);
  362.             }
  363.             
  364.             inputModes.put("ABC", upcase);
  365.             Hashtable lowcase = new Hashtable();
  366.             for(int iter = 0 ; iter < DEFAULT_KEY_CODES.length ; iter++) {
  367.                 lowcase.put(new Integer('0' + iter), DEFAULT_KEY_CODES[iter].toLowerCase());
  368.             }
  369.             inputModes.put("abc", lowcase);
  370.             Hashtable numbers = new Hashtable();
  371.             for(int iter = 0 ; iter < 10 ; iter++) {
  372.                 numbers.put(new Integer('0' + iter), "" + iter);
  373.             }
  374.             inputModes.put("123", numbers);
  375.         }
  376.     }
  377.     
  378.     /**
  379.      * Adds a new inputmode hashtable with the given name and set of values
  380.      * 
  381.      * @param name a unique display name for the input mode e.g. ABC, 123 etc...
  382.      * @param values The key for the hashtable is an Integer keyCode and the value
  383.      * is a String containing the characters to toggle between for the given keycode
  384.      * @param firstUpcase indicates if this input mode in an input mode used for the special
  385.      * case where the first letter is an upper case letter
  386.      */
  387.     public static void addInputMode(String name, Hashtable values, boolean firstUpcase) {
  388.         initInputModes();
  389.         inputModes.put(name, values);
  390.         if(firstUpcase) {
  391.             firstUppercaseInputMode.addElement(name);
  392.         }
  393.     }
  394.     
  395.     /**
  396.      * @inheritDoc
  397.      */
  398.     public String[] getInputModeOrder() {
  399.         return inputModeOrder;
  400.     }
  401.     
  402.     /**
  403.      * Sets the order in which input modes are toggled and allows disabling/hiding
  404.      * an input mode
  405.      * 
  406.      * @param order the order for the input modes in this field
  407.      */
  408.     public void setInputModeOrder(String[] order) {
  409.         inputModeOrder = order;
  410.         inputMode = order[0];
  411.     }
  412.     
  413.     /**
  414.      * Returns the order in which input modes are toggled by default
  415.      * 
  416.      * @return the default order of the input mode
  417.      */
  418.     public static String[] getDefaultInputModeOrder() {
  419.         return defaultInputModeOrder;
  420.     }
  421.     
  422.     /**
  423.      * Sets the order in which input modes are toggled by default and allows 
  424.      * disabling/hiding an input mode
  425.      * 
  426.      * @param order the order for the input modes in all future created fields
  427.      */
  428.     public static void setDefaultInputModeOrder(String[] order) {
  429.         defaultInputModeOrder = order;
  430.     }
  431.     
  432.     /**
  433.      * Used for the case of first sentence character should be upper case
  434.      */
  435.     private String pickLowerOrUpper(String inputMode) {
  436.         // check the character before the cursor..
  437.         int pos = cursorCharPosition - 1;
  438.         // we have input which has moved the cursor position further
  439.         if(pendingCommit) {
  440.             pos--;
  441.         }
  442.         String text = getText();
  443.         if(pos >= text.length()) {
  444.             pos = text.length() - 1;
  445.         }
  446.         while(pos > -1) {
  447.             if(text.charAt(pos) == '.') {
  448.                 return inputMode.toUpperCase();
  449.             }
  450.             if(text.charAt(pos) != ' ') {
  451.                 return inputMode.toLowerCase();
  452.             }
  453.             pos--;
  454.         }
  455.         return inputMode.toUpperCase();
  456.     }
  457.     
  458.     /**
  459.      * Returns the input mode for the ong click mode
  460.      * 
  461.      * @return returns 123 by default
  462.      */
  463.     protected String getLongClickInputMode() {
  464.         return "123";
  465.     }
  466.     
  467.     /**
  468.      * Returns the character matching the given key code after the given amount
  469.      * of user presses
  470.      * 
  471.      * @param pressCount number of times this keycode was pressed
  472.      * @param keyCode the actual keycode input by the user
  473.      * @param longClick does this click constitute a long click
  474.      * @return the char mapping to this key or 0 if no appropriate char was found 
  475.      * (navigation, input mode change etc...).
  476.      */
  477.     protected char getCharPerKeyCode(int pressCount, int keyCode, boolean longClick) {
  478.         initInputModes();
  479.         String input = inputMode;
  480.         
  481.         // if this is a first letter uppercase input mode then we need to pick either
  482.         // the upper case mode or the lower case mode...
  483.         if(longClick) {
  484.             input = getLongClickInputMode();
  485.         } else {
  486.             if(firstUppercaseInputMode.contains(input)) {
  487.                 input = pickLowerOrUpper(input);
  488.             }
  489.         }
  490.         
  491.         Hashtable mode = (Hashtable)inputModes.get(input);
  492.         String s = (String)mode.get(new Integer(keyCode));
  493.         if(s != null) {
  494.             pressCount = pressCount % s.length();
  495.             return s.charAt(pressCount);
  496.         }
  497.         return 0;
  498.     }
  499.     
  500.     /**
  501.      * Blocks the text area from opening the native text box editing on touchscreen click
  502.      */
  503.     void onClick() {
  504.     }
  505.     /**
  506.      * Set the position of the cursor
  507.      * 
  508.      * @param pos the cursor position
  509.      */
  510.     public void setCursorPosition(int pos) {
  511.         if(pos < -1 || pos > getText().length()) {
  512.             throw new IllegalArgumentException("Illegal cursor position: " + pos);
  513.         }
  514.         cursorCharPosition = pos;
  515.     }
  516.     
  517.     /**
  518.      * @inheritDoc
  519.      */
  520.     public int getCursorPosition() {
  521.         if(getText() == null) {
  522.             return 0;
  523.         }
  524.         return Math.min(getText().length(), cursorCharPosition);
  525.     }
  526.     
  527.     /**
  528.      * @inheritDoc
  529.      */
  530.     public void setText(String text) {
  531.         super.setText(text);
  532.         fireDataChanged(DataChangedListener.CHANGED, -1);
  533.         if(cursorCharPosition < 0) {
  534.             cursorCharPosition = text.length();
  535.         } else {
  536.             if(cursorCharPosition > text.length()) {
  537.                 cursorCharPosition = text.length();
  538.             }
  539.         }
  540.     }
  541.     
  542.     
  543.     /**
  544.      * Cleares the text from the TextField
  545.      */
  546.     public void clear(){
  547.         setText("");
  548.         commitChange();
  549.     }   
  550.     
  551.     /**
  552.      * Invoked on a long click by the user
  553.      */
  554.     private void longClick(int keyCode) {
  555.         longClick = true;
  556.         keyReleaseOrLongClick(keyCode, true);
  557.     }
  558.     /**
  559.      * Returns true if this is the clear key on the device, many devices don't contain
  560.      * a clear key and even in those that contain it this might be an issue
  561.      * 
  562.      * @param keyCode the key code that might be the clear key
  563.      * @return true if this is the clear key.
  564.      */
  565.     protected boolean isClearKey(int keyCode) {
  566.         return keyCode == Form.clearSK || keyCode == Form.backspaceSK;
  567.     }
  568.     
  569.     /**
  570.      * @inheritDoc
  571.      */
  572.     public boolean isQwertyInput() {
  573.         if(!qwertyInitialized) {
  574.             qwertyInitialized = true;
  575.             int type = Display.getInstance().getKeyboardType();
  576.             qwerty = type == Display.KEYBOARD_TYPE_QWERTY ||
  577.                     type == Display.KEYBOARD_TYPE_VIRTUAL;
  578.             qwertyDevice = qwerty;
  579.         }
  580.         return qwerty;
  581.     }
  582.     /**
  583.      * True is this is a qwerty device or a device that is currently in
  584.      * qwerty mode.
  585.      * 
  586.      * @param qwerty the value of qwerty mode
  587.      */
  588.     public void setQwertyInput(boolean qwerty) {
  589.         this.qwerty = qwerty;
  590.     }
  591.     
  592.     private boolean keyReleaseOrLongClick(int keyCode, boolean longClick) {
  593.         // user pressed a different key, autocommit everything
  594.         if(lastKeyCode != keyCode && pendingCommit) {
  595.             commitChange();
  596.         }
  597.         lastKeyCode = keyCode;
  598.         boolean isClearKey = isClearKey(keyCode);
  599.         if(isQwertyInput() && !isClearKey) {
  600.             if(keyCode > 0) {
  601.                 if(previousText == null) {
  602.                     previousText = getText();
  603.                 }
  604.                 if(cursorCharPosition < 0) {
  605.                     cursorCharPosition = 0;
  606.                 }
  607.                 
  608.                 insertChars("" + (char)keyCode);
  609.                 commitChange();
  610.                 fireDataChanged(DataChangedListener.ADDED, cursorCharPosition);
  611.                 return true;
  612.             }
  613.         } else {
  614.             char c = getCharPerKeyCode(pressCount, keyCode, longClick);
  615.             cursorCharPosition = Math.max(cursorCharPosition, 0);
  616.             if (c != 0) {
  617.                 String text;
  618.                 if(previousText == null) {
  619.                     previousText = getText();
  620.                 }
  621.                 if(!pendingCommit) {
  622.                     insertChars("" + c);
  623.                     pendingCommit = true;
  624.                     pressCount++;
  625.                 } else {
  626.                     if(overwriteMode) {
  627.                         //neutralize incrementation within *insertChars*
  628.                         cursorCharPosition--;
  629.                         //overwrite the character of previous keystroke
  630.                         insertChars("" + c);
  631.                         pressCount++;
  632.              } else {
  633.                         text = previousText.substring(0, cursorCharPosition - 1) + c +
  634.                             previousText.substring(cursorCharPosition - 1, previousText.length());
  635.                         pendingCommit = true;
  636.                         pressCount++;
  637.                         super.setText(text);
  638.                     }
  639.                 }
  640.                 if(inputMode.equals("123")) {
  641.                     commitChange();
  642.                     fireDataChanged(DataChangedListener.ADDED, cursorCharPosition);
  643.                 } else {
  644.                     if(pressCount == 1) {
  645.                         fireDataChanged(DataChangedListener.ADDED, cursorCharPosition);
  646.                     } else {
  647.                         fireDataChanged(DataChangedListener.CHANGED, cursorCharPosition);
  648.                     }
  649.                 }
  650.                 return true;
  651.             }
  652.         }
  653.         int game = Display.getInstance().getGameAction(keyCode);
  654.         if(game == keyFwd) {
  655.             cursorCharPosition++;
  656.             if(cursorCharPosition > getText().length()) {
  657.                 if(isCursorPositionCycle()) {
  658.                     cursorCharPosition = 0;
  659.                 } else {
  660.                     cursorCharPosition = getText().length();
  661.                 }
  662.             }
  663.             repaint();
  664.             return true;
  665.         } else {
  666.             if(game == keyBack) {
  667.                 cursorCharPosition--;
  668.                 if(cursorCharPosition < 0) {
  669.                     if(isCursorPositionCycle()) {
  670.                         cursorCharPosition = getText().length();
  671.                     } else {
  672.                         cursorCharPosition = 0;
  673.                     }
  674.                 }
  675.                 repaint();
  676.                 return true;
  677.             }
  678.         }
  679.         if(isChangeInputMode(keyCode)) {
  680.             for(int iter = 0 ; iter < inputModeOrder.length ; iter++) {
  681.                 if(inputModeOrder[iter].equals(inputMode)) {
  682.                     iter++;
  683.                     if(iter < inputModeOrder.length) {
  684.                         setInputMode(inputModeOrder[iter]);
  685.                     } else {
  686.                         setInputMode(inputModeOrder[0]);
  687.                     }
  688.                     return true;
  689.                 }
  690.             }
  691.             return true;
  692.         }
  693.         if(isClearKey) {
  694.             if(longClick) {
  695.                 // long click on the clear key should erase the field entirely
  696.                 setText("");
  697.                 commitChange();
  698.             } else {
  699.                 deleteChar();
  700.             }
  701.             return true;
  702.         }
  703.         if(isSymbolDialogKey(keyCode)) {
  704.             showSymbolDialog();
  705.             return true;
  706.         }
  707.         return false;
  708.     }
  709.     /**
  710.      * This method is responsible for adding a character into the field and is 
  711.      * the focal point for all input. It can be overriden to prevent a particular
  712.      * char from insertion or provide a different behavior for char insertion.
  713.      * It is the responsibility of this method to shift the cursor and invoke
  714.      * setText...
  715.      * <p>This method accepts a string for the more elaborate cases such as multi-char
  716.      * input and paste.
  717.      * 
  718.      * @param c character for insertion
  719.      */
  720.     public void insertChars(String c) {
  721.         String currentText = getText();
  722.         //if the contraint is numeric only, don't insert a char that isn't 
  723.         //numeric
  724.         if ((getConstraint() & TextArea.NUMERIC) != 0) {
  725.             if(c.charAt(0) < '0' || c.charAt(0) > '9'){
  726.                 return;
  727.             }
  728.         }
  729.         cursorCharPosition++;
  730.         if(overwriteMode && cursorCharPosition <= currentText.length()) {
  731.             setText(currentText.substring(0, cursorCharPosition - 1) + c + 
  732.                 currentText.substring(cursorCharPosition, currentText.length()));
  733.         } else {
  734.             if(currentText.length() + c.length() > getMaxSize()) {
  735.                 cursorCharPosition--;
  736.                 return;
  737.             }
  738.             setText(currentText.substring(0, cursorCharPosition - 1) + c + 
  739.                 currentText.substring(cursorCharPosition - 1, currentText.length()));
  740.         }
  741.         if(c.length() > 1) {
  742.             cursorCharPosition += c.length() - 1;
  743.         }
  744.     }
  745.     
  746.     /**
  747.      * Invoked to show the symbol dialog, this method can be overriden by subclasses to
  748.      * manipulate the symbol table
  749.      */
  750.     protected void showSymbolDialog() {
  751.         Command cancel = new Command("Cancel");
  752.         Command r = Dialog.show(null, createSymbolTable(), new Command[] {cancel});
  753.         if(r != null && r != cancel) {
  754.             insertChars(r.getCommandName());
  755.         }
  756.     }
  757.     /**
  758.      * Creates a symbol table container used by the showSymbolDialog method.
  759.      * This method is designed for subclases to override and customize.
  760.      * 
  761.      * @return container for the symbol table.
  762.      */
  763.     protected Container createSymbolTable() {
  764.         char[] symbolArray = getSymbolTable();
  765.         Container symbols = new Container(new GridLayout(symbolArray.length / 5, 5));
  766.         for(int iter = 0 ; iter < symbolArray.length ; iter++) {
  767.             Button button = new Button(new Command("" + symbolArray[iter]));
  768.             button.setAlignment(CENTER);
  769.             symbols.addComponent(button);
  770.         }
  771.         return symbols;
  772.     }
  773.     /**
  774.      * @inheritDoc
  775.      */
  776.     public void keyReleased(int keyCode) {
  777.         if(!isEditable()) {
  778.             return;
  779.         }
  780.         pressedAndNotReleased = false;
  781.         releaseTime = System.currentTimeMillis();
  782.         if(!longClick) {
  783.             if(keyReleaseOrLongClick(keyCode, false)) {
  784.                 return;
  785.             }
  786.         }
  787.         longClick = false;
  788.         super.keyReleased(keyCode);
  789.     }
  790.     
  791.     /**
  792.      * The amount of time considered as a "long click" causing the long click method
  793.      * to be invoked.
  794.      * 
  795.      * @return currently defaults to 800
  796.      */
  797.     protected int getLongClickDuration() {
  798.         return 800;
  799.     }
  800.     /**
  801.      * Returns the symbol table for the device
  802.      * 
  803.      * @return the symbol table of the device for the symbol table input
  804.      */
  805.     public static char[] getSymbolTable() {
  806.         return symbolTable;
  807.     }
  808.     /**
  809.      * Sets the symbol table to show when the user clicks the symbol table key
  810.      * 
  811.      * @param table the symbol table of the device for the symbol table input
  812.      */
  813.     public static void setSymbolTable(char[] table) {
  814.         symbolTable = table;;
  815.     }
  816.     
  817.     /**
  818.      * Returns true if the cursor should cycle to the beginning of the text when the
  819.      * user navigates beyond the edge of the text and visa versa.
  820.      * @return true by default
  821.      */
  822.     protected boolean isCursorPositionCycle() {
  823.         return true;
  824.     }
  825.     
  826.     /**
  827.      * Returns true if this keycode is the one mapping to the symbol dialog popup
  828.      * 
  829.      * @param keyCode the keycode to check
  830.      * @return true if this is the star symbol *
  831.      */
  832.     protected boolean isSymbolDialogKey(int keyCode) {
  833.         return keyCode == defaultSymbolDialogKey;
  834.     }
  835.     /**
  836.      * @inheritDoc
  837.      */
  838.     protected void deinitialize() {
  839.         // if the text field is removed without restoring the commands we need to restore them
  840.         if(handlesInput()) {
  841.             if(useSoftkeys) {
  842.                 removeCommands(DELETE_COMMAND, T9_COMMAND, originalClearCommand);
  843.             } else {
  844.                 Form f = getComponentForm();
  845.                 if(f != null) {
  846.                     f.setClearCommand(originalClearCommand);
  847.                 }
  848.                 originalClearCommand = null;
  849.             }
  850.             pressedAndNotReleased = false;
  851.         }
  852.     }
  853.     /**
  854.      * @inheritDoc
  855.      */
  856.     public void setEditable(boolean b) {
  857.         super.setEditable(b);
  858.         if(!b && handlesInput()) {
  859.             setHandlesInput(false);
  860.             if(useSoftkeys) {
  861.                 removeCommands(DELETE_COMMAND, T9_COMMAND, originalClearCommand);
  862.             } else {
  863.                 Form f = getComponentForm();
  864.                 f.setClearCommand(originalClearCommand);
  865.                 originalClearCommand = null;
  866.             }
  867.             pressedAndNotReleased = false;
  868.         }
  869.     }
  870.     /**
  871.      * @inheritDoc
  872.      */
  873.     public void keyRepeated(int keyCode) {
  874.         // the default implementation interfears with long press
  875.         if(isQwertyDevice()) {
  876.             super.keyRepeated(keyCode);
  877.         }
  878.     }
  879.     /**
  880.      * @inheritDoc
  881.      */
  882.     public void keyPressed(int keyCode) {
  883.         if(!isEditable()) {
  884.             return;
  885.         }
  886.         pressedAndNotReleased = true;
  887.         pressedKeyCode = keyCode;
  888.         pressTime = System.currentTimeMillis();
  889.         
  890.         // try to autodetect a qwerty device
  891.         if(qwertyAutoDetect) {
  892.             if((!qwerty) && ((keyCode >= 'a' && keyCode <= 'z') || (keyCode >= 'A' && keyCode <= 'Z'))) {
  893.                 qwertyDevice = true;
  894.                 qwerty = true;
  895.             }
  896.         }
  897.         
  898.         if((!handlesInput()) && isEditingTrigger(keyCode)) {
  899.             setHandlesInput(true);
  900.             if(useSoftkeys) {
  901.                 T9_COMMAND.setDisposesDialog(false);
  902.                 DELETE_COMMAND.setDisposesDialog(false);
  903.                 originalClearCommand = installCommands(DELETE_COMMAND, T9_COMMAND);
  904.             } else {
  905.                 Form f = getComponentForm();
  906.                 originalClearCommand = f.getClearCommand();
  907.                 f.setClearCommand(DELETE_COMMAND);
  908.             }
  909.             return;
  910.         }
  911.         if(handlesInput() && isEditingEndTrigger(keyCode)) {
  912.             setHandlesInput(false);
  913.             if(useSoftkeys) {
  914.                 removeCommands(DELETE_COMMAND, T9_COMMAND, originalClearCommand);
  915.             } else {
  916.                 Form f = getComponentForm();
  917.                 f.setClearCommand(originalClearCommand);
  918.                 originalClearCommand = null;
  919.             }
  920.             fireActionEvent();
  921.             return;
  922.         } else {
  923.             if(handlesInput()) {
  924.                 return;
  925.             }
  926.         }
  927.         super.keyPressed(keyCode);
  928.     }
  929.     
  930.     /**
  931.      * Installs the clear and t9 commands onto the parent form, this method can
  932.      * be overriden to provide device specific placement for these commands
  933.      * 
  934.      * @param clear the clear command
  935.      * @param t9 the t9 command
  936.      * @param keyboard the keyboard command
  937.      * @return clear command already installed in the form if applicable, none if no
  938.      * clear command was installed before or not applicable.
  939.      */
  940.     protected Command installCommands(Command clear, Command t9) {
  941.         Form f = getComponentForm();
  942.         if(f != null) {
  943.             Command original = f.getClearCommand();
  944.             if(original instanceof CommandHandler) {
  945.                 original = originalClearCommand;
  946.             }
  947.             if(replaceMenu && originalCommands == null) {
  948.                 originalCommands = new Command[f.getCommandCount()];
  949.                 for(int iter = 0 ; iter < originalCommands.length ; iter++) {
  950.                     originalCommands[iter] = f.getCommand(iter);
  951.                 }
  952.                 f.removeAllCommands();
  953.                 if(Display.getInstance().isThirdSoftButton()) {
  954.                     getComponentForm().addSelectCommand(getSelectCommandText());
  955.                     selectCommand = getComponentForm().getCommand(0);
  956.                 }
  957.             }
  958.             
  959.             f.addCommand(clear, 0);
  960.             f.addCommand(t9, 0);
  961.             f.setClearCommand(clear);
  962.             return original;
  963.         }
  964.         return null;
  965.     }
  966.     /**
  967.      * @inheritDoc
  968.      */
  969.     protected boolean isSelectableInteraction() {
  970.         return true;
  971.     }
  972.     
  973.     /**
  974.      * @inheritDoc
  975.      */
  976.     protected void fireClicked() {
  977.         if((!handlesInput())) {
  978.             setHandlesInput(true);
  979.             if(useSoftkeys) {
  980.                 T9_COMMAND.setDisposesDialog(false);
  981.                 DELETE_COMMAND.setDisposesDialog(false);
  982.                 originalClearCommand = installCommands(DELETE_COMMAND, T9_COMMAND);
  983.             } else {
  984.                 Form f = getComponentForm();
  985.                 originalClearCommand = f.getClearCommand();
  986.                 f.setClearCommand(DELETE_COMMAND);
  987.             }
  988.             return;
  989.         }
  990.         if(handlesInput()) {
  991.             setHandlesInput(false);
  992.             if(useSoftkeys) {
  993.                 removeCommands(DELETE_COMMAND, T9_COMMAND, originalClearCommand);
  994.             } else {
  995.                 Form f = getComponentForm();
  996.                 f.setClearCommand(originalClearCommand);
  997.                 originalClearCommand = null;
  998.             }
  999.             fireActionEvent();
  1000.             return;
  1001.         } else {
  1002.             if(handlesInput()) {
  1003.                 return;
  1004.             }
  1005.         }
  1006.     }
  1007.     /**
  1008.      * Removes the clear and t9 commands from the parent form, this method can
  1009.      * be overriden to provide device specific placement for these commands
  1010.      * 
  1011.      * @param clear the clear command
  1012.      * @param t9 the t9 command
  1013.      * @param originalClear the command originally assigned as the clear command (or null if no command was assigned before)
  1014.      * @param keyboard toggle keyboard command
  1015.      */
  1016.     protected void removeCommands(Command clear, Command t9, Command originalClear) {
  1017.         Form f = getComponentForm();
  1018.         if(f != null) {
  1019.             f.removeCommand(clear);
  1020.             f.removeCommand(t9);
  1021.             if(selectCommand != null) {
  1022.                 f.removeCommand(selectCommand);
  1023.             }
  1024.             f.setClearCommand(originalClearCommand);
  1025.             if(replaceMenu && originalCommands != null) {
  1026.                 for(int iter = originalCommands.length - 1 ; iter >= 0 ; iter--) {
  1027.                     f.addCommand(originalCommands[iter]);
  1028.                 }
  1029.                 originalCommands = null;
  1030.             }
  1031.         }
  1032.     }
  1033.     
  1034.     void focusLostInternal() {
  1035.         if(handlesInput() || pressedAndNotReleased || pendingCommit) {
  1036.             setHandlesInput(false);
  1037.             Form f = getComponentForm();
  1038.             if(f != null) {
  1039.                 if (useSoftkeys) {
  1040.                     removeCommands(DELETE_COMMAND, T9_COMMAND, originalClearCommand);
  1041.                 } else {
  1042.                     f.setClearCommand(originalClearCommand);
  1043.                 }
  1044.             }
  1045.             releaseTime = System.currentTimeMillis();
  1046.             commitChange();
  1047.             pressedAndNotReleased = false;
  1048.             longClick = false;
  1049.         }
  1050.         if(Display.getInstance().isVirtualKeyboardShowingSupported()) {
  1051.             Display.getInstance().setShowVirtualKeyboard(false);
  1052.         }
  1053.     }
  1054.     void focusGainedInternal() {
  1055.         releaseTime = System.currentTimeMillis();
  1056.         pressedAndNotReleased = false;
  1057.         longClick = false;
  1058.     }
  1059.     
  1060.     /**
  1061.      * Indicates whether the given key code should be ignored or should trigger
  1062.      * editing, by default fire or any numeric key should trigger editing implicitly.
  1063.      * This method is only called when handles input is false.
  1064.      * 
  1065.      * @param keyCode the keycode passed to the keyPressed method
  1066.      * @return true if this key code should cause a switch to editing mode.
  1067.      */
  1068.     protected boolean isEditingTrigger(int keyCode) {
  1069.         if(!isEditable()) {
  1070.             return false;
  1071.         }
  1072.         int gk = Display.getInstance().getGameAction(keyCode);
  1073.         if(isQwertyInput()) {
  1074.             return keyCode > 0 || (gk == Display.GAME_FIRE) || isClearKey(keyCode) || isEnterKey(keyCode)
  1075.                      || (leftAndRightEditingTrigger && ((gk == Display.GAME_LEFT) || (gk == Display.GAME_RIGHT)));
  1076.         }
  1077.         return (keyCode >= '0' && keyCode <= '9') || isClearKey(keyCode) ||
  1078.             (gk == Display.GAME_FIRE)
  1079.             || (leftAndRightEditingTrigger && ((gk == Display.GAME_LEFT) || (gk == Display.GAME_RIGHT)));
  1080.     }
  1081.     
  1082.     /**
  1083.      * Indicates whether the given key code should be ignored or should trigger
  1084.      * cause editing to end. By default the fire key, up or down will trigger
  1085.      * the end of editing.
  1086.      * 
  1087.      * @param keyCode the keycode passed to the keyPressed method
  1088.      * @return true if this key code should cause a switch to editing mode.
  1089.      */
  1090.     protected boolean isEditingEndTrigger(int keyCode) {
  1091.         int k =Display.getInstance().getGameAction(keyCode);
  1092.         if(isQwertyInput()) {
  1093.             return keyCode < 0 && (k == Display.GAME_FIRE || k == Display.GAME_UP || k == Display.GAME_DOWN || isEnterKey(keyCode));
  1094.         }
  1095.         return (k == Display.GAME_FIRE || k == Display.GAME_UP || k == Display.GAME_DOWN);
  1096.     }
  1097.     
  1098.     /**
  1099.      * @inheritDoc
  1100.      */
  1101.     public void paint(Graphics g) {
  1102.         UIManager.getInstance().getLookAndFeel().drawTextField(g, this);
  1103.         if (drawCursor && hasFocus() && isEditable()) {
  1104.             UIManager.getInstance().getLookAndFeel().drawTextFieldCursor(g, this);
  1105.         }
  1106.     }
  1107.     /**
  1108.      * @inheritDoc
  1109.      */
  1110.     protected Dimension calcPreferredSize() {
  1111.         return UIManager.getInstance().getLookAndFeel().getTextFieldPreferredSize(this);
  1112.     }
  1113.     
  1114.     /**
  1115.      * @inheritDoc
  1116.      */
  1117.     protected void initComponent() {
  1118.         boolean rtl = isRTL();
  1119.         keyFwd = rtl ? Display.GAME_LEFT : Display.GAME_RIGHT;
  1120.         keyBack = rtl ? Display.GAME_RIGHT : Display.GAME_LEFT;
  1121.         // text field relies too much on animation to use internal animations
  1122.         getComponentForm().registerAnimated(this);
  1123.     }
  1124.     
  1125.     /**
  1126.      * The amount of time in milliseconds in which the cursor is visible
  1127.      * 
  1128.      * @param time for the cursor to stay "on"
  1129.      */
  1130.     public void setCursorBlinkTimeOn(int time) {
  1131.         blinkOnTime = time;
  1132.     }
  1133.     /**
  1134.      * The amount of time in milliseconds in which the cursor is invisible
  1135.      * 
  1136.      * @param time for the cursor to stay "off"
  1137.      */
  1138.     public void setCursorBlinkTimeOff(int time) {
  1139.         blinkOffTime = time;
  1140.     }
  1141.     
  1142.     /**
  1143.      * The amount of time in milliseconds in which the cursor is visible
  1144.      * 
  1145.      * @return time for the cursor to stay "on"
  1146.      */
  1147.     public int getCursorBlinkTimeOn() {
  1148.         return blinkOnTime;
  1149.     }
  1150.     /**
  1151.      * The amount of time in milliseconds in which the cursor is invisible
  1152.      * 
  1153.      * @return time for the cursor to stay "off"
  1154.      */
  1155.     public int getCursorBlinkTimeOff() {
  1156.         return blinkOffTime;
  1157.     }
  1158.     /**
  1159.      * @inheritDoc
  1160.      */
  1161.     public boolean animate() {
  1162.         boolean ani = super.animate();
  1163.         if(hasFocus()) {
  1164.             long currentTime = System.currentTimeMillis();
  1165.             if (drawCursor) {
  1166.                 if ((currentTime - cursorBlinkTime) > blinkOnTime) {
  1167.                     cursorBlinkTime = currentTime;
  1168.                     drawCursor = false;
  1169.                     return true;
  1170.                 }
  1171.             } else {
  1172.                 if ((currentTime - cursorBlinkTime) > blinkOffTime) {
  1173.                     cursorBlinkTime = currentTime;
  1174.                     drawCursor = true;
  1175.                     return true;
  1176.                 }
  1177.             }
  1178.             if(pressedAndNotReleased) { 
  1179.                 if(currentTime - pressTime >= getLongClickDuration()) {
  1180.                     longClick(pressedKeyCode);
  1181.                 }
  1182.             } else {
  1183.                 if(pendingCommit && currentTime - releaseTime > commitTimeout) {
  1184.                     commitChange();
  1185.                 }
  1186.             }
  1187.         } else {
  1188.             drawCursor = false;
  1189.         }
  1190.         return ani;
  1191.     }
  1192.     
  1193.     /**
  1194.      * @inheritDoc
  1195.      */
  1196.     public void pointerReleased(int x, int y) {
  1197.         // unlike text area the text field supports shifting the cursor with the touch screen
  1198.         String text = getText();
  1199.         int textLength = text.length();
  1200.         int position = 0;
  1201.         Font f = getStyle().getFont();
  1202.         x -= getAbsoluteX();
  1203.         for(int iter = 0 ; iter < textLength ; iter++) {
  1204.             int width = f.substringWidth(text, 0, iter);
  1205.             if(x > width) {
  1206.                 position = iter;
  1207.             } else {
  1208.                 break;
  1209.             }
  1210.         }
  1211.         if(position == textLength - 1) {
  1212.             if(f.stringWidth(text) < x) {
  1213.                 position = textLength;
  1214.             }
  1215.         }
  1216.         setCursorPosition(position);
  1217.         if(!isEditable()){
  1218.             return;
  1219.         }
  1220.         if(Display.getInstance().isVirtualKeyboardShowingSupported()) {
  1221.             Display.getInstance().setShowVirtualKeyboard(!Display.getInstance().isVirtualKeyboardShowing());
  1222.         } 
  1223.         if(!handlesInput()) {
  1224.             fireClicked();
  1225.         } else {
  1226.             repaint();
  1227.         }
  1228.     }
  1229.     /**
  1230.      * When set to true softkeys are used to enable delete functionality
  1231.      * 
  1232.      * @return true if softkeys should be used
  1233.      */
  1234.     public boolean isUseSoftkeys() {
  1235.         return useSoftkeys;
  1236.     }
  1237.     /**
  1238.      * When set to true softkeys are used to enable delete functionality
  1239.      * 
  1240.      * @param useSoftkeys true if softkeys should be used
  1241.      */
  1242.     public void setUseSoftkeys(boolean useSoftkeys) {
  1243.         this.useSoftkeys = useSoftkeys;
  1244.     }
  1245.     
  1246.     /**
  1247.      * Adds a listener for data change events it will be invoked for every change
  1248.      * made to the text field
  1249.      * 
  1250.      * @param d the listener
  1251.      */
  1252.     public void addDataChangeListener(DataChangedListener d) {
  1253.         listeners.addListener(d);
  1254.     }
  1255.     /**
  1256.      * Removes the listener for data change events 
  1257.      * 
  1258.      * @param d the listener
  1259.      */
  1260.     public void removeDataChangeListener(DataChangedListener d) {
  1261.         listeners.removeListener(d);
  1262.     }
  1263.     
  1264.     private void fireDataChanged(int type, int index) {
  1265.         if(listeners != null) {
  1266.             listeners.fireDataChangeEvent(index, type);
  1267.         }
  1268.     }
  1269.     
  1270.     /**
  1271.      * @inheritDoc
  1272.      */
  1273.     void onEditComplete(String text) {
  1274.         super.onEditComplete(text);
  1275.         setCursorPosition(text.length());
  1276.     }
  1277.     /**
  1278.      * Indicates whether the menu of the form should be replaced with the T9/Clear
  1279.      * commands for the duration of interactivity with the text field
  1280.      * 
  1281.      * @return true if the menu should be replaced
  1282.      */
  1283.     public boolean isReplaceMenu() {
  1284.         return replaceMenu;
  1285.     }
  1286.     /**
  1287.      * Indicates whether the menu of the form should be replaced with the T9/Clear
  1288.      * commands for the duration of interactivity with the text field
  1289.      * 
  1290.      * @param replaceMenu  true if the menu should be replaced
  1291.      */
  1292.     public void setReplaceMenu(boolean replaceMenu) {
  1293.         this.replaceMenu = replaceMenu;
  1294.     }
  1295.     /**
  1296.      * Indicates whether the menu of the form should be replaced with the T9/Clear
  1297.      * commands for the duration of interactivity with the text field
  1298.      * 
  1299.      * @return true if the menu should be replaced
  1300.      */
  1301.     public static boolean isReplaceMenuDefault() {
  1302.         return replaceMenuDefault;
  1303.     }
  1304.     /**
  1305.      * Indicates whether the menu of the form should be replaced with the T9/Clear
  1306.      * commands for the duration of interactivity with the text field
  1307.      * 
  1308.      * @param replaceMenu  true if the menu should be replaced
  1309.      */
  1310.     public static void setReplaceMenuDefault(boolean replaceMenu) {
  1311.         replaceMenuDefault = replaceMenu;
  1312.     }
  1313.     
  1314.     /**
  1315.      * Indicates whether the text field should try to auto detect qwerty and 
  1316.      * switch the qwerty device flag implicitly
  1317.      * 
  1318.      * @param v true for qwerty auto detection
  1319.      */
  1320.     public static void setQwertyAutoDetect(boolean v) {
  1321.         qwertyAutoDetect = v;
  1322.     }
  1323.     
  1324.     /**
  1325.      * The default value for the qwerty flag so it doesn't need setting for every
  1326.      * text field individually.
  1327.      * 
  1328.      * @param v true for qwerty device
  1329.      */
  1330.     public static void setQwertyDevice(boolean v) {
  1331.         qwertyDevice = v;
  1332.     }
  1333.     /**
  1334.      * Indicates whether the text field should try to auto detect qwerty and 
  1335.      * switch the qwerty device flag implicitly
  1336.      * 
  1337.      * @return true for qwerty auto detection
  1338.      */
  1339.     public static boolean isQwertyAutoDetect() {
  1340.         return qwertyAutoDetect;
  1341.     }
  1342.     
  1343.     /**
  1344.      * The default value for the qwerty flag so it doesn't need setting for every
  1345.      * text field individually.
  1346.      * 
  1347.      * @return true for qwerty devices
  1348.      */
  1349.     public static boolean isQwertyDevice() {
  1350.         return qwertyDevice;
  1351.     }
  1352.     /**
  1353.      * Key to change the input mode on the device
  1354.      * 
  1355.      * @param k key to change the input mode
  1356.      */
  1357.     public static void setDefaultChangeInputModeKey(int k) {
  1358.         defaultChangeInputModeKey = k;
  1359.     }
  1360.     
  1361.     /**
  1362.      * Key to change the input mode on the device
  1363.      * 
  1364.      * @return key to change the input mode
  1365.      */
  1366.     public static int getDefaultChangeInputModeKey() {
  1367.         return defaultChangeInputModeKey;
  1368.     }
  1369.     /**
  1370.      * The default key for poping open the symbol dialog
  1371.      *
  1372.      * @param d new key value
  1373.      */
  1374.     public static void setDefaultSymbolDialogKey(int d) {
  1375.         defaultSymbolDialogKey = d;
  1376.     }
  1377.     /**
  1378.      * The default key for poping open the symbol dialog
  1379.      *
  1380.      * @return the default key
  1381.      */
  1382.     public static int getDefaultSymbolDialogKey() {
  1383.         return defaultSymbolDialogKey;
  1384.     }
  1385.     /**
  1386.      * Indicates that this is the overwrite mode 
  1387.      * 
  1388.      * @param overwriteMode set to true if input with overwrite characters
  1389.      */
  1390.     public void setOverwriteMode(boolean overwriteMode) {
  1391.         this.overwriteMode = overwriteMode;
  1392.     }
  1393.     
  1394.     /**
  1395.      * Indicates that this is the overwrite mode 
  1396.      * 
  1397.      * @return true if input with overwrite characters
  1398.      */
  1399.     public boolean isOverwriteMode() {
  1400.         return overwriteMode;
  1401.     }
  1402.     /**
  1403.      * Indicates whether the left/right keys will trigger editing, this is true by default.
  1404.      * Left and right key edit trigger might be disabled for cases such as text field
  1405.      * positioned horizontally one next to the other.
  1406.      *
  1407.      * @param leftAndRightEditingTrigger Indicates whether the left/right keys will trigger editing
  1408.      */
  1409.     public void setLeftAndRightEditingTrigger(boolean leftAndRightEditingTrigger) {
  1410.         this.leftAndRightEditingTrigger = leftAndRightEditingTrigger;
  1411.     }
  1412.     /**
  1413.      * Indicates whether the left/right keys will trigger editing, this is true by default.
  1414.      * Left and right key edit trigger might be disabled for cases such as text field
  1415.      * positioned horizontally one next to the other.
  1416.      *
  1417.      * @return leftAndRightEditingTrigger Indicates whether the left/right keys will trigger editing
  1418.      */
  1419.     public boolean isLeftAndRightEditingTrigger() {
  1420.         return leftAndRightEditingTrigger;
  1421.     }
  1422.     /**
  1423.      * @inheritDoc
  1424.      */
  1425.     public boolean isSingleLineTextArea() {
  1426.         return true;
  1427.     }
  1428.     /**
  1429.      * @inheritDoc
  1430.      */
  1431.     public void setAlignment(int align) {
  1432.      if(align == Component.CENTER) {
  1433.      throw new IllegalArgumentException("CENTER alignment is not supported in TextField.");
  1434.      } else {
  1435.      super.setAlignment(align);
  1436.      }
  1437.     }
  1438. }