JDK-4801177 : Ctrl-Tab does not traverse Components with JSplitPane
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 1.4.1
  • Priority: P4
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_nt
  • CPU: x86
  • Submitted: 2003-01-09
  • Updated: 2003-01-16
  • Resolved: 2003-01-16
Related Reports
Relates :  
Description
	      "David Karlton", "Dave Kloba",
				      "Dave Moore", "Hans Muller",
				      "Rick Levenson", "Tim Prinzing",
				      "Chester Rose", "Ray Ryan",
				      "Georges Saab", "Scott Violet",
				      "Kathy Walrath", "Arnaud Weber" };
	}
	nameCount = (float)names.length;
	nameGen = new Random(System.currentTimeMillis());
    }


    /** Have the children of this node been loaded yet? */
    protected boolean           hasLoaded;

    /**
      * Constructs a new DynamicTreeNode instance with o as the user
      * object.
      */
    public DynamicTreeNode(Object o) {
	super(o);
    }

    public boolean isLeaf() {
	return false;
    }

    /**
      * If hasLoaded is false, meaning the children have not yet been
      * loaded, loadChildren is messaged and super is messaged for
      * the return value.
      */
    public int getChildCount() {
	if(!hasLoaded) {
	    loadChildren();
	}
	return super.getChildCount();
    }

    /**
      * Messaged the first time getChildCount is messaged.  Creates
      * children with random names from names.
      */
    protected void loadChildren() {
	DynamicTreeNode             newNode;
	int                         randomIndex;

	for(int counter = 0; counter < DynamicTreeNode.DefaultChildrenCount;
	    counter++) {
	    randomIndex = (int)(nameGen.nextFloat() * nameCount);
	    newNode = new DynamicTreeNode(names[randomIndex]);
	    /* Don't use add() here, add calls insert(newNode, getChildCount())
	       so if you want to use add, just be sure to set hasLoaded = true
	       first. */
	    insert(newNode, counter);
	}
	/* This node has now been loaded, mark it so. */
	hasLoaded = true;
    }
}


---------- END SOURCE ----------
(Review ID: 178834) 
======================================================================


Name: jk109818			Date: 01/09/2003


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

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

A DESCRIPTION OF THE PROBLEM :
With pressing the "Cntr-Tab", it does not go to the next
field in a JSplitPane.


REGRESSION.  Last worked in version 1.4.1

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Open a frame "NewSplit Tree/attributes
2 (Optional). Open some children of the tree to get a
scroll bar.
3. Use "Ctrl-tab" to go to the next field.
-> It does not go to the next field

EXPECTED VERSUS ACTUAL BEHAVIOR :
The expected result is same as the "Tab"-function.
It works when you open a frame "New Tree" or "New Tree
attributes".  These are none SplitPane panels.


REPRODUCIBILITY :
This bug can be reproduced always.

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

//The code is taken from the demo version of JDK 1.4 "SampleTree"

//SampleTee.java
/*
 * Copyright (c) 2002 Sun Microsystems, Inc. All  Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * -Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduct the above copyright
 *  notice, this list of conditions and the following disclaimer in
 *  the documentation and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT
 * BE LIABLE FOR ANY DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT
 * OF OR RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN
 * IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that Software is not designed, licensed or intended for
 * use in the design, construction, operation or maintenance of any nuclear
 * facility.
 */

 /*
  * Changes made, to generate some bugs
  * The Tree is now under MyInternalFrame
  */

/*
 * @(#)SampleTree.java	1.21 02/06/13
 */

import javax.swing.JDesktopPane;
import javax.swing.JInternalFrame;
import javax.swing.DefaultDesktopManager;
import java.awt.Container;

import javax.swing.*;
import javax.swing.event.*;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.*;
import javax.swing.tree.*;

/**
  * A demo for illustrating how to do different things with JTree.
  * The data that this displays is rather boring, that is each node will
  * have 7 children that have random names ...
  *
  * @version 1.21 06/13/02
  * @author Scott Violet
  */

public class SampleTree
{
    protected JFrame            frame;
    private JDesktopPane  desktop = new JDesktopPane(); //a specialized layered pane

    /**
      * Constructs a new instance of SampleTree.
      */

    public SampleTree() {
	// Force SampleTree to come up in the Cross Platform L&F
	try {
	    UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
	    // If you want the System L&F instead, comment out the above line and
	    // uncomment the following:
	    // UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
	} catch (Exception exc) {
	    System.err.println("Error loading L&F: " + exc);
	}


	JMenuBar         menuBar = constructMenuBar();


	frame = new JFrame("SampleTree");
	frame.setJMenuBar(menuBar);
	frame.setBackground(Color.lightGray);

        desktop.setDesktopManager(new DefaultDesktopManager());
        setContentPane(frame, desktop);

	frame.addWindowListener( new WindowAdapter() {
	    public void windowClosing(WindowEvent e) {System.exit(0);}});

//	frame.pack();
//        this.createFrame();
        frame.setSize(500, 500);
	frame.show();
    }

    /** Construct a menu. */
    private JMenuBar constructMenuBar() {
	JMenu            menu;
	JMenuBar         menuBar = new JMenuBar();
	JMenuItem        menuItem;

	/* Good ol exit. */
	menu = new JMenu("File");
	menuBar.add(menu);

	menuItem = menu.add(new JMenuItem("Exit"));
	menuItem.addActionListener(new ActionListener() {
	    public void actionPerformed(ActionEvent e) {
		System.exit(0);
	    }});

	menu = new JMenu("Tree");
        menu.setMnemonic('T');
	menuBar.add(menu);

	menuItem = menu.add(new JMenuItem("New Tree"));
	menuItem.addActionListener(new NewOnlyTreeAction());
	menuItem = menu.add(new JMenuItem("New Tree attributes"));
	menuItem.addActionListener(new NewAction());
	menuItem = menu.add(new JMenuItem("NewSpilt Tree/attributes"));
	menuItem.addActionListener(new NewSplitAction());

	return menuBar;
    }

    class NewOnlyTreeAction extends Object implements ActionListener
    {
	public void actionPerformed(ActionEvent e)
        {
          SampleTree.this.createFrame(true, false);
        }
    }

    class NewAction extends Object implements ActionListener
    {
	public void actionPerformed(ActionEvent e)
        {
          SampleTree.this.createFrame(false, false);
        }
    }

    class NewSplitAction extends Object implements ActionListener
    {
	public void actionPerformed(ActionEvent e)
        {
          SampleTree.this.createFrame(false, true);
        }
    }

    static public void main(String args[]) {
      new SampleTree();
    }

    private void setContentPane(JFrame  frame, Container contentPane) {
        frame.getRootPane().setContentPane(contentPane);
    }

    private void createFrame(boolean onlyTree,
                             boolean  split) {
        MyInternalFrame frame = new MyInternalFrame(onlyTree, split);
	frame.setVisible(true); //necessary as of 1.3; OK to use before
        desktop.add(frame);
        try {
            frame.setSelected(true);
        } catch (java.beans.PropertyVetoException e) {}
    }
}


//MyInternalFrame.java
/**
 * Created for generating testing purposes
 * Most of the code is taken fram SampleTree
 */

class MyInternalFrame extends JInternalFrame
{
  static int openFrameCount = 0;
  static final int xOffset = 30, yOffset = 30;
  /* Create the tree. */
  protected JTree             tree;
  /** Tree model. */
  protected DefaultTreeModel        treeModel;

  public MyInternalFrame(boolean onlyTree,
                         boolean split)
  {
    super("Document #" + (++openFrameCount),
          true, //resizable
          true, //closable
          true, //maximizable
          true);//iconifiable

    //...Create the GUI and put it in the window...

    //...Then set the window size or call pack...
    setSize(300,300);

    //Set the window's location.
    setLocation(xOffset*(openFrameCount % 8), yOffset*(openFrameCount%8));
    try
    {
      jbInit(onlyTree, split);
    }
    catch(Exception e)
    {
      e.printStackTrace();
    }
  }

  private void jbInit(boolean  onlyTree,
                      boolean  split) throws Exception
  {
    /* Create the JTreeModel. */
    DefaultMutableTreeNode root = createNewNode("Root");
    treeModel = new DefaultTreeModel(root);

    /* Create the tree. */
    tree = new JTree(treeModel);

    /* Enable tool tips for the tree, without this tool tips will not
       be picked up. */
    ToolTipManager.sharedInstance().registerComponent(tree);

    /* Make the tree use an instance of SampleTreeCellRenderer for
       drawing. */

    /* Make tree ask for the height of each row. */
    tree.setRowHeight(-1);

    Container  cont = this.getContentPane();
    cont.setLayout(new BorderLayout());

    JScrollPane        sp = new JScrollPane();
    sp.setPreferredSize(new Dimension(300, 300));
    sp.getViewport().add(tree);
    if (onlyTree)
    {
      cont.add("Center", sp);
    }
    else if (split)
    {
      /* Put the Tree in a scroller. */
      JSplitPane  splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
      cont.add(splitPane, BorderLayout.CENTER);

      splitPane.setContinuousLayout(true);
      splitPane.setDividerSize(3);
      cont.add(splitPane, BorderLayout.CENTER);

      splitPane.add(sp, JSplitPane.TOP);
      splitPane.setDividerLocation(200);
      splitPane.add(constructOptionsPanel(), JSplitPane.BOTTOM);
    }
    else
    {
      cont.add("Center", sp);
      cont.add("South", constructOptionsPanel());
    }
  }

    /** Constructs a JPanel containing check boxes for the different
      * options that tree supports. */
    private JPanel constructOptionsPanel() {
	JCheckBox               aCheckbox;
	JPanel           retPanel = new JPanel(false);
	JPanel           borderPane = new JPanel(false);

	borderPane.setLayout(new BorderLayout());
	retPanel.setLayout(new FlowLayout());

	aCheckbox = new JCheckBox("show handles");
	aCheckbox.setSelected(tree.getShowsRootHandles());
	aCheckbox.addChangeListener(new ShowHandlesChangeListener());
	retPanel.add(aCheckbox);

	aCheckbox = new JCheckBox("show root");
	aCheckbox.setSelected(tree.isRootVisible());
	aCheckbox.addChangeListener(new ShowRootChangeListener());
	retPanel.add(aCheckbox);

	borderPane.add(retPanel, BorderLayout.CENTER);
	return borderPane;
    }


    /**
      * ShowHandlesChangeListener implements the ChangeListener interface
      * to toggle the state of showing the handles in the tree.
      */
    class ShowHandlesChangeListener extends Object implements ChangeListener
    {
	public void stateChanged(ChangeEvent e) {
	    tree.setShowsRootHandles(((JCheckBox)e.getSource()).isSelected());
	}

    } // End of class SampleTree.ShowHandlesChangeListener

    /**
      * ShowRootChangeListener implements the ChangeListener interface
      * to toggle the state of showing the root node in the tree.
      */
    class ShowRootChangeListener extends Object implements ChangeListener
    {
	public void stateChanged(ChangeEvent e) {
	    tree.setRootVisible(((JCheckBox)e.getSource()).isSelected());
	}

    } // End of class SampleTree.ShowRootChangeListener


    protected DefaultMutableTreeNode createNewNode(String name) {
      return new DynamicTreeNode(name);
    }
}


//DynamicTree.java

/*
 * Copyright (c) 2002 Sun Microsystems, Inc. All  Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * -Redistributions of source code must retain the above copyright
 *  notice, this list of conditions and the following disclaimer.
 *
 * -Redistribution in binary form must reproduct the above copyright
 *  notice, this list of conditions and the following disclaimer in
 *  the documentation and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors
 * may be used to endorse or promote products derived from this software
 * without specific prior written permission.
 *
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT
 * BE LIABLE FOR ANY DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT
 * OF OR RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN
 * IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that Software is not designed, licensed or intended for
 * use in the design, construction, operation or maintenance of any nuclear
 * facility.
 */

/*
 * @(#)DynamicTreeNode.java	1.9 02/06/13
 */


/**
  * DynamicTreeNode illustrates one of the possible ways in which dynamic
  * loading can be used in tree.  The basic premise behind this is that
  * getChildCount() will be messaged from JTreeModel before any children
  * are asked for.  So, the first time getChildCount() is issued the
  * children are loaded.<p>
  * It should be noted that isLeaf will also be messaged from the model.
  * The default behavior of TreeNode is to message getChildCount to
  * determine this. As such, isLeaf is subclassed to always return false.<p>
  * There are others ways this could be accomplished as well.  Instead of
  * subclassing TreeNode you could subclass JTreeModel and do the same
  * thing in getChildCount().  Or, if you aren't using TreeNode you could
  * write your own TreeModel implementation.
  * Another solution would be to listen for TreeNodeExpansion events and
  * the first time a node has been expanded post the appropriate insertion
  * events.  I would not recommend this approach though, the other two
  * are much simpler and cleaner (and are faster from the perspective of
  * how tree deals with it).
  *
  * NOTE: getAllowsChildren() can be messaged before getChildCount().
  *       For this example the nodes always allow children, so it isn't
  *       a problem, but if you do support true leaf nodes you may want
  *       to check for loading in getAllowsChildren too.
  *
  * @version 1.9 06/13/02
  * @author Scott Violet
  */

class DynamicTreeNode extends DefaultMutableTreeNode
{
//    // Class stuff.
    /** Number of names. */
    static protected float                    nameCount;

    /** Names to use for children. */
    static protected String[]                 names;

    /** Used to generate the names. */
    static protected Random                   nameGen;

    /** Number of children to create for each node. */
    static protected final int                DefaultChildrenCount = 7;

    static {
        {
	    names = new String[] {"Mark Andrews", "Tom Ball", "Alan Chung",
				      "Rob Davis", "Jeff Dinkins",
				      "Amy Fowler", "James Gosling",
			

Comments
EVALUATION Name: apR10133 Date: 01/15/2003 Due to the fix for bug #4164779 the Ctrl+Tab is supposed to move focus from whatever component inside the JSplitPane that has the focus to the next component outside the JSplitPane. So the Ctrl+Tab behavior is correct. ###@###.### ======================================================================
24-08-2004