home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgLangD.iso / VCAFE.3.0A / Main.bin / JMaskedTextField.java < prev    next >
Text File  |  1998-12-11  |  14KB  |  412 lines

  1. package com.symantec.itools.swing;
  2.  
  3. import java.awt.event.KeyEvent;
  4. import java.awt.event.KeyAdapter;
  5. import java.awt.event.FocusEvent;
  6. import java.awt.event.FocusAdapter;
  7. import java.awt.datatransfer.*;
  8. import com.sun.java.swing.text.Document;
  9. import com.sun.java.swing.text.PlainDocument;
  10. import com.sun.java.swing.event.DocumentListener;
  11. import com.sun.java.swing.event.DocumentEvent;
  12.  
  13. public class JMaskedTextField extends com.sun.java.swing.JTextField {
  14.  
  15.     /* These constants are used to specify the data type information needed
  16.         to specialize input time behavior based on data type.
  17.         For now, the only such difference is between text and numeric:
  18.         In numeric fields, an empty field is initialzed to zero, and input of
  19.         a decimal point when the mask contains one and the cartet is to its left
  20.         causes the caret to move to the right of the decimal point position.
  21.     */
  22.     public static final int texttype = MaskEngine.texttype;
  23.     public static final int numbtype = MaskEngine.numbtype;
  24.     public static final int datetype = MaskEngine.datetype;
  25.     public static final int timetype = MaskEngine.timetype;
  26.  
  27.     // ctors
  28.     public JMaskedTextField (                   ) { this(""         , 0              ); }
  29.     public JMaskedTextField (int numberOfColumns) { this(""         , numberOfColumns); }
  30.     public JMaskedTextField (String initialText ) { this(initialText, 256            ); }
  31.     public JMaskedTextField (String initialText, int numberOfColumns)    {
  32.       this(null, initialText, numberOfColumns);
  33.     }
  34.  
  35.     // All other constructors call this one
  36.     public JMaskedTextField(Document doc, String initialText, int numberOfColumns) {
  37.         super(doc, initialText, numberOfColumns);
  38.     }
  39.   
  40.     //over-ride 
  41.     public synchronized void setText ( String t ) {
  42.         if ( t != null && t.length() > 0 ) {
  43.             super.setText ( getMatchedText ( t ) ) ;
  44.         }
  45.         else {
  46.             super.setText( t );
  47.         }
  48.     }
  49.  
  50.     /**
  51.         Initialize the field
  52.     */
  53.     public synchronized void setMaskedText(String t) {
  54.         if(getMask().equals("")){
  55.             super.setText(t);
  56.         }else{
  57.             StringBuffer newData = new StringBuffer();
  58.             _firstInputPos = _maskEngine.initDisplay(t, newData);
  59.             super.setText(newData.toString());
  60.             if (_haveFocus && isEditable()) { 
  61.                 select(_firstInputPos, _firstInputPos + 1);
  62.             }
  63.         }
  64.     }
  65.  
  66.     // Returns current text with mask characters removed
  67.     public synchronized String getUnmaskedText() {
  68.         if(getMask().equals("")) { 
  69.             return getText();
  70.         }
  71.         StringBuffer newData = new StringBuffer();
  72.         _dataComplete = _maskEngine.stripMask(getText(), newData);
  73.         return newData.toString();
  74.     }
  75.  
  76.    /**
  77.     * This is a standard AWT method which gets called when
  78.     * this component is added to a container.
  79.     *
  80.     * @see #removeNotify
  81.     */
  82.     public synchronized void addNotify() {
  83.         if (_focusListener == null) {
  84.             _focusListener = new FocusAdapter() {
  85.                                 public void focusGained(FocusEvent e) { gotFocus (e); }
  86.                                 public void focusLost  (FocusEvent e) { lostFocus(e); }
  87.                             };
  88.             addFocusListener(_focusListener);
  89.         }
  90.         super.addNotify();
  91.     }
  92.  
  93.    /**
  94.     * This method gets called when this component is removed from a
  95.     * container.
  96.     *
  97.     * @see #addNotify
  98.     */
  99.     public synchronized void removeNotify() {
  100.         if (_focusListener != null) {
  101.             removeFocusListener(_focusListener);
  102.             _focusListener = null;
  103.         }
  104.         super.removeNotify();
  105.     }
  106.  
  107.     public synchronized void cut(Clipboard clipboard) {
  108.         if (!isEditable()) {
  109.             return;
  110.         }
  111.         _activity = true;
  112.         StringBuffer newData = new StringBuffer();
  113.         int selStart = getSelectionStart();
  114.         String clipboardData = _maskEngine.cut(getText(), selStart,
  115.                                             getSelectionEnd(),
  116.                                             newData);
  117.         StringSelection ss = new StringSelection(clipboardData);
  118.         clipboard.setContents(ss, ss);
  119.         super.setText(newData.toString());
  120.         setCaretPosition(selStart);
  121.     }
  122.  
  123.     public synchronized void paste(Clipboard clipboard) {
  124.         
  125.         if (!isEditable()) { 
  126.             return;
  127.         }
  128.         
  129.         _activity = true;
  130.         StringBuffer newData = new StringBuffer();
  131.         String data = "";
  132.         
  133.         try {
  134.             data = (String)clipboard.getContents(this).getTransferData(DataFlavor.stringFlavor);
  135.         } catch (Exception e) {}
  136.         
  137.         int pos = getCaretPosition();
  138.         int selStart = getSelectionStart();
  139.         int selEnd = getSelectionEnd();
  140.         int newpos = _maskEngine.paste(getText(), data, pos, newData,
  141.                                     selStart, selEnd);
  142.         if (newpos < 0)   { // beep if paste failed
  143.             getToolkit().beep();
  144.         }
  145.         if (newpos == -2)  { // quit if filter mismatch
  146.             return;
  147.         }
  148.         
  149.         super.setText(newData.toString());
  150.         
  151.         if (newpos >= 0) {              // if good new caret position
  152.             select(newpos, newpos + 1);  // select this position
  153.         } 
  154.         else {
  155.             select(0, 0);  // turn off selection
  156.             newpos = newpos - getNumberOfCaseConvertors();
  157.             if (newpos != -1) { // cursor just moved out of range
  158.                 setCaretPosition(newpos + 1000);  // move one past last filter
  159.             }
  160.         }
  161.     }
  162.  
  163.     // Override of JTextComponent
  164.     public void cut() {
  165.         //vasu start
  166.         if(getMask().equals("")){
  167.             super.cut();
  168.         }else{
  169.         //vasu end
  170.             cut(java.awt.Toolkit.getDefaultToolkit().getSystemClipboard());
  171.         }
  172.     }
  173.  
  174.     // Override of JTextComponent
  175.     public void paste() {
  176.         //vasu start
  177.         if(getMask().equals("")) {
  178.             super.paste();
  179.         }else{
  180.         //vasu end
  181.             paste(java.awt.Toolkit.getDefaultToolkit().getSystemClipboard());
  182.         }
  183.     }
  184.  
  185.     public void   setMask    (String mask) {
  186.         _maskEngine.setMask( mask ); 
  187.         setText ( getText() );
  188.     }
  189.     
  190.     public String getMask    (           ) { return _maskEngine.getMask    (    ); }
  191.     public void   setDatatype(int    type) {        _maskEngine.setDatatype(type); }
  192.     public int    getDatatype(           ) { return _maskEngine.getDatatype(    ); }
  193.  
  194.     public boolean isDataComplete() {
  195.         //vasu start
  196.         if(getMask().equals(""))  {
  197.             return true;
  198.         }
  199.         //vasu end
  200.         if (!_dataComplete) {
  201.             if (!_activity) { 
  202.                 return true;
  203.             }
  204.             _dataComplete = _maskEngine.stripMask(getText(), new StringBuffer());
  205.         }
  206.         return _dataComplete;
  207.     }
  208.     
  209.     protected String  getMatchedText ( String t ) {
  210.     
  211.         return  _maskEngine.getMatchedText ( t );
  212.     
  213.     }
  214.  
  215.     protected void gotFocus(FocusEvent e) {
  216.         _activity = false;
  217.         _haveFocus = true;
  218.         if (getText().length() == 0) { 
  219.             setMaskedText("");  // show the mask literals if field is empty
  220.         }
  221.         else if (isEditable() && !getMask().equals("")) { //vasu
  222.             select(_firstInputPos, _firstInputPos + 1);
  223.         }
  224.     }
  225.  
  226.     protected void lostFocus(FocusEvent e) {
  227.         //select(0, 0);//vasu
  228.         _haveFocus = false;
  229.         if (isEditable() && _activity) {
  230.             try {
  231.                 _docListenerDisabled = true;
  232.                 _document.remove(0, _document.getLength());
  233.                 _document.insertString(0, getUnmaskedText(), null);
  234.             } catch (com.sun.java.swing.text.BadLocationException ex) {
  235.                 badLocException();
  236.             } finally {
  237.                 _docListenerDisabled = false;
  238.             }
  239.         }
  240.     }
  241.  
  242.     // Override JTextComponent
  243.     protected void processComponentKeyEvent(KeyEvent e) {
  244.         //vasu start - because we check whether or not something
  245.         //             was done before we update the model
  246.         _activity = true;
  247.         //vasu end
  248.  
  249.         switch(e.getID()) {
  250.         
  251.         case KeyEvent.KEY_TYPED:
  252.             if (_maskEngine.isHandledKey(e) && isEditable()) { 
  253.                 processKey(e);
  254.             }
  255.             else { 
  256.                 super.processComponentKeyEvent(e);
  257.             }
  258.             break;
  259.         
  260.         case KeyEvent.KEY_PRESSED:
  261.             if (_maskEngine.isHandledKey(e) && isEditable()) {
  262.                 e.consume();
  263.                 if (_keyPressed) { // key must be auto-repeating
  264.                     if (Character.isISOControl(e.getKeyChar())) { 
  265.                         processKey(e);
  266.                     }
  267.                     
  268.                 } 
  269.                 else { 
  270.                     _keyPressed = true;
  271.                 }
  272.             }
  273.             else { 
  274.                 super.processComponentKeyEvent(e);
  275.             }
  276.             break;
  277.         
  278.         case KeyEvent.KEY_RELEASED:
  279.             _keyPressed = false;
  280.             if (_maskEngine.isHandledKey(e) && isEditable()) {
  281.                 if (Character.isISOControl(e.getKeyChar())) { 
  282.                     processKey(e);
  283.                 }
  284.             } else { 
  285.                 super.processComponentKeyEvent(e);
  286.             }
  287.             break;
  288.         }
  289.     }
  290.  
  291.     protected void processKey(KeyEvent e) {
  292.         _activity = true;
  293.         e.consume();
  294.         //use zero if -1 for caretPos
  295.         int caretPos = Math.max( 0 , getCaretPosition() - 1 );
  296.         StringBuffer newData = new StringBuffer("");
  297.         String data = getText();
  298.         int selStart = getSelectionStart();
  299.         int newpos = _maskEngine.processKey(e, caretPos, data, newData,
  300.                                             selStart, getSelectionEnd());
  301.         if (newpos == -2)   { // quit if filter mismatch
  302.             return;
  303.         }
  304.         
  305.         super.setText(newData.toString());
  306.         
  307.         if (newpos >= 0) {              // if good new caret position
  308.             select(newpos, newpos + 1);  // select this position
  309.         } 
  310.         else if (newpos == -1) {
  311.             getToolkit().beep();
  312.             select(0, 0);
  313.         } 
  314.         else {  // cursor just moved out of range
  315.             select(0, 0);  // turn off selection
  316.             newpos = newpos - getNumberOfCaseConvertors();
  317.             setCaretPosition(newpos + 1000);  // move one past last filter
  318.         }
  319.     }
  320.  
  321.     // Override
  322.     // This gets called during superclass construction!
  323.     public void setDocument(Document d) {
  324.         
  325.         if (_docListener == null) { 
  326.             _docListener = new DocumentListener() {
  327.                 public void changedUpdate(DocumentEvent e) { docChange(e); }
  328.                 public void removeUpdate (DocumentEvent e) { docRemove(e); }
  329.                 public void insertUpdate (DocumentEvent e) { docInsert(e); }
  330.             };
  331.         }
  332.  
  333.         if (_document != null) {
  334.             _document.removeDocumentListener(_docListener);
  335.         }
  336.         
  337.         _document = d;
  338.         _document.addDocumentListener(_docListener);
  339.         
  340.         if (_myDoc == null) { 
  341.             _myDoc = new PlainDocument();
  342.         }
  343.         super.setDocument(_myDoc);
  344.     }
  345.  
  346.     // These shouldn't get called
  347.     protected void docChange(DocumentEvent e) {
  348.         if (_docListenerDisabled) { 
  349.             return;
  350.         }
  351.     //    System.out.println("Masked Doc Listener Change Called");
  352.     }
  353.  
  354.     protected void docRemove(DocumentEvent e) {
  355.         if (_docListenerDisabled) { 
  356.             return;
  357.         }
  358.     //  System.out.println("Masked Remove Called");
  359.         super.setText("");
  360.     }
  361.  
  362.     // This gets called on data insertion into the field
  363.     protected void docInsert(DocumentEvent e) {
  364.         if (_docListenerDisabled) { 
  365.             return;
  366.         }
  367.         int len = e.getLength();
  368.         String data = "";
  369.         
  370.         try {
  371.             data = _document.getText(0, len);
  372.         } catch(com.sun.java.swing.text.BadLocationException ex) {
  373.             badLocException();
  374.         }
  375.         
  376.         setMaskedText(data);
  377.     }
  378.  
  379.     protected void badLocException() {
  380.         getToolkit().beep();
  381.         System.out.println("Bad Location Exception in JMaskedTextField");
  382.     }
  383.   
  384.     private int getNumberOfCaseConvertors() {
  385.         int retInt = 0;
  386.  
  387.         java.text.StringCharacterIterator iter =  new java.text.StringCharacterIterator ( getMask() );
  388.         while ( iter.next() != iter.DONE ) {
  389.             if ( iter.current() == '<' || iter.current() == '>' ) {
  390.                 retInt++;
  391.             }
  392.         }
  393.         
  394.         return retInt;
  395.     }
  396.  
  397.     private PlainDocument    _myDoc         = null;
  398.     private DocumentListener _docListener   = null;
  399.     private Document         _document      = null;
  400.     private boolean          _docListenerDisabled = false;
  401.     private boolean          _dataComplete  = true;    // true iff no mandatory filters are empty
  402.     private boolean          _haveFocus     = false;   // true if this component has input focus
  403.     private boolean          _keyPressed    = false;   // true if a key is down
  404.     private boolean          _activity      = false;
  405.     private int              _firstInputPos = 0;       // position of first filter
  406.     private MaskEngine       _maskEngine    = new MaskEngine();
  407.     private FocusAdapter     _focusListener = null;
  408.       
  409.         //debug flag
  410.     private boolean          debug          = false;
  411. }
  412.