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

JList and JTree should scroll automatically with first-letter navigation

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: P4 P4
    • 5.0
    • 1.4.0, 1.4.1
    • client-libs
    • tiger
    • x86
    • windows_nt, windows_2000, windows_xp



      Name: jk109818 Date: 03/19/2002


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


      FULL OPERATING SYSTEM VERSION :
      Microsoft Windows 2000 [Version 5.00.2195]



      A DESCRIPTION OF THE PROBLEM :
      According to the article:
      http://java.sun.com/products/jfc/tsc/articles/merlin/index.h
      tml#JList

      "JList should support first letter key navigation-#4284709"

      This is implemented in Merlin, but incomplete, however.
      Although the selection does happen by typing the key, the
      scrolling to the related item is missing, what makes it
      pointless.

      The method:
      getNextMatch(prefix, startIndex, Position.Bias.Forward);

      has been added to JList;
      BasicListUI.KeyHandler.keyTyped() contains the line:

      src.setSelectedIndex(index);, but
      src.ensureIndexIsVisible(index); is missing.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1.Please run the attached program
      2.Type the first letter of the last list item (W)
      3.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      The selection of the item does happen correctly but the
      scrolling to it is missing by JList.

      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.util.*;

      import java.awt.*;

      import javax.swing.*;
      import javax.swing.border.*;


      public class TestList extends JPanel {

          private JList list;
          private Vector listvector;
          DefaultListModel listmodel = new DefaultListModel();

          TestList() {

              createDataModel();
              createList();
              createGUI();
              setBorder();
          }

          void createDataModel() {

              listvector = new Vector();

              listvector.addElement("Penrose");
              listvector.addElement("Hawking");
              listvector.addElement("Green");
              listvector.addElement("Heisenberg ");
              listvector.addElement("Feynman");
              listvector.addElement("Curie");
              listvector.addElement("Newton");
              listvector.addElement("Prigogine");
              listvector.addElement("Planck");
              listvector.addElement("Witten");
              listvector.addElement("Asimov");
              listvector.addElement("Bruno");
              System.out.println("Before sorting:\n ");

              Iterator it = listvector.iterator();

              while (it.hasNext()) {
                  System.out.println(it.next());
              }

              Collections.sort(listvector);
          }

          void createList() {

              for (int i = 0; i < listvector.size(); i++) {
                  listmodel.addElement(listvector.elementAt(i));
              }

              list = new JList(listmodel);
          }

          void createGUI() {
              setBackground(Color.white);
              add(new JScrollPane(list));
          }

          void setBorder() {

              Border line = BorderFactory.createLineBorder(Color.lightGray);
              TitledBorder title = BorderFactory.createTitledBorder(line,
                                       "TestList");

              title.setTitleFont(list.getFont().deriveFont(Font.PLAIN, 16));
              title.setTitleColor((Color) UIManager.get("ScrollBar.thumb"));
              setBorder(title);
          }

          public static void main(String[] args) {

              JFrame f = new JFrame("Test");
              Container cont = f.getContentPane();

              cont.add(new TestList(), "Center");
              cont.add(new JLabel("Please type W"), "South");
              f.pack();
              f.setLocationRelativeTo(null);
              f.setVisible(true);
          }
      }
      ---------- END SOURCE ----------

      CUSTOMER WORKAROUND :
      I wrote my own ListUI to overcome this. To support the
      scrolling correctly please add the missing lines to
      BasicListUI (marked by // line added ):

      int index = src.getNextMatch(prefix, startIndex,
                                 Position.Bias.Forward);

      if (index >= 0) {
          src.setSelectedIndex(index);
          src.ensureIndexIsVisible(index); // line added
      } else if (startingFromSelection) {
          index = src.getNextMatch(prefix, 0,
      Position.Bias.Forward);

          if (index >= 0) {
              src.setSelectedIndex(index);
              src.ensureIndexIsVisible(index); // line added
          }
      }



      Thank you
      (Review ID: 138838)
      ======================================================================

      Name: jk109818 Date: 07/11/2002


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


      FULL OPERATING SYSTEM VERSION :
      Microsoft Windows 2000 [Version 5.00.2195]
      Service pack 2

      A DESCRIPTION OF THE PROBLEM :
      This bug would only take a few lines of code to fix, and it
      would make this new feature much more usable. In other
      words, lots of bang for not much buck.

      In the JTree KeyListener for first-letter navigation, when
      it changes the selected path, it should also call
      scrollPathToVisible. Likewise, in the JList KeyListener,
      when it changes the selected index, it should call
      ensureIndexIsVisible. This way users are not surprised
      when they press a key and the selection appears to vanish.
      This improvement would mirror how native Windows controls
      work.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Compile and execute the included code.
      2. With the window open and keyboard focus on the list (as
      should happen by default), type single letters and watch
      what happens to the selection.

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      Expected result: the list automatically scrolls so that the
      newly-selected row is fully visible.

      Actual result: the list does not scroll, even if the newly-
      selected row is not visible at all.

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      import java.awt.*;
      import javax.swing.*;

      public class JListTest
      {
        public static void main (String[] args)
        {
          JFrame frame = new JFrame("Frame");

          Container conPane = frame.getContentPane();
          conPane.setLayout(new BorderLayout());

          String strings[] = new String[26];
          int i;
          char c = 'A';
          for (i = 0; i < 26; ++i, ++c) {
              strings[i] = String.valueOf(c);
          }

          JList list = new JList(strings);
          list.setSelectedIndex(0);
          JScrollPane scroll = new JScrollPane(list);

          conPane.add(scroll, BorderLayout.CENTER);

          frame.pack();
          frame.show();
        }
      }

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

      CUSTOMER WORKAROUND :
      It's a big hack, but here it is. Copy Sun's KeyListener
      code for first-letter navigation and add the lines to
      scroll to the selected index/row, then subclass the JList
      to prevent Sun's KeyListener from being added:

      public void addKeyListener(KeyListener l) {
          if (l == null ||
              !l.getClass().getName().startsWith(
                  "javax.swing.plaf")) {
              super.addKeyListener(l);
          }
      }

      This is because BasicListUI.createKeyListener is private,
      rather than protected like its cousin in BasicTreeUI or the
      other BasicListUI.createXxxListener methods. I'll write up
      another bug report for that inconvenience.

      JTree is easier to work around because its UI's inner
      KeyListener class is public and the method to create it is
      protected.
      (Review ID: 159233)
      ======================================================================

            apikalev Andrey Pikalev
            jkimsunw Jeffrey Kim (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: