Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-4805829

Tabbing from single focusable field doesn't trigger verify

XMLWordPrintable

    • beta
    • x86
    • windows_2000



      Name: jk109818 Date: 01/21/2003


      FULL PRODUCT VERSION :
      java version "1.4.1_01"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
      Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)

      FULL OPERATING SYSTEM VERSION :
      Windows NT 4 SP6

      ADDITIONAL OPERATING SYSTEMS :

      Windows 2000, SP2


      A DESCRIPTION OF THE PROBLEM :
      When a frame has a single focussable field, pressing TAB
      does not trigger the shouldYieldFocus() method - which kind
      of makes sense, except that that is where the call to the
      verify() method is made and where you can output any
      suitable error messages. (In our application we often do
      this, before deciding which secondary fields to enable.)

      This worked exactly as I had hoped it would fine in version
      1.4.0, so I assume someone decided it needed to be "fixed".
      Please unfix it !

      REGRESSION. Last worked in version 1.4

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1.Create a frame with a single focussable field
      2.Check whether tabbing out of it causes shouldYieldFocus()
      to be called.
      3.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      I think that pressing tab while in a field should always
      trigger a single point of validation whether there is
      another field to traverse to or not.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------

      import java.awt.*;
      import java.awt.image.*;
      import java.net.*;
      import java.awt.event.*;
      import javax.swing.*;
      import javax.swing.text.*;

      //==========================================================================

      class FocusTester extends JFrame
      {
      //====================================================================
      // Fields
      //====================================================================

      BaseTextField field1 = null;
      BaseTextField field2 = null;

      //====================================================================
      // Main
      //====================================================================

      public static void main (String args[])
      {
      if (args.length != 0)
      {
      System.out.println("---------------------------------------------------------");
      System.out.println("usage: java FocusTester");
      System.out.println("---------------------------------------------------------");
      System.exit(0);
      }

      new FocusTester();
      }

      //====================================================================
      // Constructors
      //====================================================================

      public FocusTester()
      {
      showVersion();

      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      JPanel panel = new JPanel();

      field1 = new BaseTextField("field1", 3)
      {
      String getStatus()
      {
      String s = "";

      if ( ! getText().equals("x"))
      s = "This field is only valid if \"x\" is entered.";

      return s;
      }

      void actionIfValid()
      {
      field2.setChangeable(true);
      field2.requestFocus();
      setChangeable(false);
      }
      };

      field2 = new BaseTextField("field2", 3)
      {
      String getStatus()
      {
      String s = "";

      if ( ! getText().equals("y"))
      s = "This field is only valid if \"y\" is entered.";

      return s;
      }

      void actionIfValid()
      {
      field1.setChangeable(true);
      field1.requestFocus();
      setChangeable(false);
      }
      };

      field2.setChangeable(false);

      panel.add(field1);
      panel.add(field2);

      getContentPane().add(panel);

      setFocusManager();

      pack();
      setLocationRelativeTo(null);
      show();
      }

      //====================================================================
      // Methods
      //====================================================================

      private void showVersion()
      {
      debug("version = \"" + System.getProperty("java.version") + "\"");
      }

      //--------------------------------------------------------------------

      private void setFocusManager()
      {
      DefaultKeyboardFocusManager fm = new DefaultKeyboardFocusManager()
      {
      public void focusNextComponent(Component c)
      {
      debug(" >>>focusNextComponent()");

      super.focusNextComponent(c);

      debug(" <<<focusNextComponent()");
      }
      };


      KeyboardFocusManager.setCurrentKeyboardFocusManager(fm);
      }



      //====================================================================
      // Debug
      //====================================================================

      private void debug(String s)
      {
      System.out.println("FocusTester - " + s);
      System.out.flush();
      }

      //====================================================================
      // Inner Classes - BaseTextField
      //====================================================================

      abstract class BaseTextField extends JTextField
      {
      //====================================================================
      // Fields
      //====================================================================

      private int maxCharacters = 0;
      private String name = "";

      //====================================================================
      // Constructors
      //====================================================================

      public BaseTextField(String name, int size)
      {
      super(size + 1); // create the field with 1 extra column

      this.name = name;
      maxCharacters = size;

      setFont(new Font("Monospaced", Font.PLAIN, getFont().getSize()));

      /*
      **
      */

      setInputVerifier(new InputVerifier()
      {
      boolean recursion = false;

      /*
      ** The API states this shouldn't have side-effects, so
      ** just do the minimum.
      */
      public boolean verify(JComponent theField)
      {
      debug("In verify - though always returns true");
      return true;
      }

      /*
      ** According to the API, this can have side-effects, though
      ** the reasoning behind this is unclear. Anyway, unless
      ** we're careful, trying to do an information popup also
      ** triggers another attempt at validating the field,
      ** which repeats another attempt and so on till we
      ** get a stack dump.
      */
      public boolean shouldYieldFocus(JComponent theField)
      {

      boolean okToYield = true;

      if (! recursion)
      {
      recursion = true;

      debug("checking whether to yield focus");
      debug("text=\"" + getText() + "\"");
      new Throwable().printStackTrace();

      String s = getStatus();

      if (s.equals(""))
      actionIfValid();
      else
      {
      showMessage(s);
      okToYield = false;
      }

      recursion = false;
      }

      return okToYield;
      }
      });

      /*
      ** set the document for the field to one which will not allow more than the
      ** maximum number of characters.
      */

      setDocument(new PlainDocument()
      {
      public void insertString(int offs, String str, AttributeSet a)
      throws BadLocationException
      {
      if ((getLength() + str.length()) <= maxCharacters)
      {
      super.insertString(offs, str, a);
      }
      else
      Toolkit.getDefaultToolkit().beep();
      }

      });



      /*
      * Add focus listener
      */
      addFocusListener(new FocusAdapter()
      {
      public void focusGained(FocusEvent e)
      {
      debug(getName() + " - Focus gained !");
      }
      });

      /*
      ** This action listener only "hears" CR.
      */
      addActionListener(new ActionListener()
      {
      public void actionPerformed(ActionEvent e)
      {
      debug(">>Action " + e);
      }
      });

      }

      //====================================================================
      // Methods
      //====================================================================

      public void setChangeable(boolean b)
      {
      super.setEditable(b);
      super.setFocusable(b);
      }

      //--------------------------------------------------------------------

      public void requestFocus()
      {
      debug("requesting focus - " + this);
      if (isFocusOwner())
      {
      debug("already focus owner so skipping request");
      }
      else
      {
      debug("requesting");
      super.requestFocus();
      }
      }

      //--------------------------------------------------------------------

      public void showMessage(String message)
      {
      debug("showMessage() - " + message);

      JOptionPane.showMessageDialog(
      null,
      message,
      "Error",
      JOptionPane.ERROR_MESSAGE);

      }

      //--------------------------------------------------------------------

      public void transferFocus()
      {
      debug(" >>>transferFocus()");

      super.transferFocus();

      debug(" <<<transferFocus()");
      }

      //--------------------------------------------------------------------

      abstract String getStatus();

      //--------------------------------------------------------------------

      abstract void actionIfValid();

      //====================================================================
      // Debug
      //====================================================================

      private void debugNext()
      {
      KeyboardFocusManager kfm = KeyboardFocusManager.getCurrentKeyboardFocusManager();
      Container fcr = kfm.getCurrentFocusCycleRoot();
      FocusTraversalPolicy ftp = kfm.getDefaultFocusTraversalPolicy();
      Component n = ftp.getComponentAfter(fcr, BaseTextField.this);

      if (n == BaseTextField.this)
      debug("Next Field is this one!");
      else
      debug("Next=" + n);
      }

      //--------------------------------------------------------------------

      private void debug(String s)
      {
      System.out.println("BaseTextField \"" + name + "\" - " + s);
      System.out.flush();
      }

      //--------------------------------------------------------------------
      }
      }

      //==========================================================================
      //==========================================================================



      ---------- END SOURCE ----------

      CUSTOMER WORKAROUND :
      None found - but desperately needed
      (Review ID: 179554)
      ======================================================================

            draskinsunw Daniel Raskin (Inactive)
            jkimsunw Jeffrey Kim (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: