diff options
author | Tom Tromey <tromey@gcc.gnu.org> | 2005-07-16 00:30:23 +0000 |
---|---|---|
committer | Tom Tromey <tromey@gcc.gnu.org> | 2005-07-16 00:30:23 +0000 |
commit | f911ba985aa7fe0096c386c5be385ac5825ea527 (patch) | |
tree | a0b991cf5866ae1d616639b906ac001811d74508 /libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java | |
parent | 6f4434b39b261de5317dc81ddfdd94d2e1d62b11 (diff) | |
download | gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.zip gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.tar.gz gcc-f911ba985aa7fe0096c386c5be385ac5825ea527.tar.bz2 |
Initial revision
From-SVN: r102074
Diffstat (limited to 'libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java')
-rw-r--r-- | libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java | 413 |
1 files changed, 413 insertions, 0 deletions
diff --git a/libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java b/libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java new file mode 100644 index 0000000..152482c --- /dev/null +++ b/libjava/classpath/java/awt/ContainerOrderFocusTraversalPolicy.java @@ -0,0 +1,413 @@ +/* ContainerOrderFocusTraversalPolicy.java -- + Copyright (C) 2002, 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package java.awt; + +import java.io.Serializable; + +/** + * ContainerOrderFocusTraversalPolicy defines a focus traversal order + * based on the order in which Components were packed in a Container. + * This policy performs a pre-order traversal of the Component + * hierarchy starting from a given focus cycle root. Portions of the + * hierarchy that are not visible and displayable are skipped. + * + * By default, this policy transfers focus down-cycle implicitly. + * That is, if a forward traversal is requested on a focus cycle root + * and the focus cycle root has focusable children, the focus will + * automatically be transfered down to the lower focus cycle. + * + * The default implementation of accept accepts only Components that + * are visible, displayable, enabled and focusable. Derived classes + * can override these acceptance criteria by overriding accept. + * + * @author Michael Koch + * @author Thomas Fitzsimmons (fitzsim@redhat.com) + * @since 1.4 + */ +public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy + implements Serializable +{ + /** + * Compatible to JDK 1.4+ + */ + static final long serialVersionUID = 486933713763926351L; + + /** + * True if implicit down cycling is enabled. + */ + private boolean implicitDownCycleTraversal = true; + + /** + * Creates the <code>ContainerOrderFocusTraversalPolicy</code> object. + */ + public ContainerOrderFocusTraversalPolicy () + { + // Nothing to do here + } + + /** + * Returns the Component that should receive the focus after current. + * root must be a focus cycle root of current. + * + * @param root a focus cycle root of current + * @param current a (possibly indirect) child of root, or root itself + * + * @return the next Component in the focus traversal order for root, + * or null if no acceptable Component exists. + * + * @exception IllegalArgumentException If root is not a focus cycle + * root of current, or if either root or current is null. + */ + public Component getComponentAfter (Container root, Component current) + { + if (root == null) + throw new IllegalArgumentException ("focus cycle root is null"); + if (current == null) + throw new IllegalArgumentException ("current component is null"); + + if (!root.isFocusCycleRoot ()) + throw new IllegalArgumentException ("root is not a focus cycle root"); + + Container ancestor = current.getFocusCycleRootAncestor (); + Container prevAncestor = ancestor; + while (ancestor != root) + { + ancestor = current.getFocusCycleRootAncestor (); + if (ancestor == prevAncestor) + { + // We've reached the top focus cycle root ancestor. Check + // if it is root. + if (ancestor != root) + throw new IllegalArgumentException ("the given container is not" + + " a focus cycle root of the" + + " current component"); + else + break; + } + prevAncestor = ancestor; + } + + // FIXME: is this the right thing to do here? It moves the context + // for traversal up one focus traversal cycle. We'll need a test + // for this. + if ((Component) root == current) + root = current.getFocusCycleRootAncestor (); + + // Check if we've reached the top of the component hierarchy. If + // so then we want to loop around to the first component in the + // focus traversal cycle. + if (current instanceof Window) + return getFirstComponent ((Container) current); + + Container parent = current.getParent (); + + synchronized (parent.getTreeLock ()) + { + Component[] components = parent.getComponents (); + int componentIndex = 0; + int numComponents = parent.getComponentCount (); + + // Find component's index. + for (int i = 0; i < numComponents; i++) + { + if (components[i] == current) + componentIndex = i; + } + + // Search forward for the next acceptable component. + for (int i = componentIndex + 1; i < numComponents; i++) + { + if (accept (components[i])) + return components[i]; + + if (components[i] instanceof Container) + { + Component result = getFirstComponent ((Container) components[i]); + + if (result != null + && implicitDownCycleTraversal) + return result; + } + } + + // No focusable components after current in its Container. So go + // to the next Component after current's Container (parent). + Component result = getComponentAfter (root, parent); + + return result; + } + } + + /** + * Returns the Component that should receive the focus before + * <code>current</code>. <code>root</code> must be a focus cycle + * root of current. + * + * @param root a focus cycle root of current + * @param current a (possibly indirect) child of root, or root itself + * + * @return the previous Component in the focus traversal order for + * root, or null if no acceptable Component exists. + * + * @exception IllegalArgumentException If root is not a focus cycle + * root of current, or if either root or current is null. + */ + public Component getComponentBefore (Container root, Component current) + { + if (root == null) + throw new IllegalArgumentException ("focus cycle root is null"); + if (current == null) + throw new IllegalArgumentException ("current component is null"); + + if (!root.isFocusCycleRoot ()) + throw new IllegalArgumentException ("root is not a focus cycle root"); + + Container ancestor = current.getFocusCycleRootAncestor (); + Container prevAncestor = ancestor; + while (ancestor != root) + { + ancestor = current.getFocusCycleRootAncestor (); + if (ancestor == prevAncestor) + { + // We've reached the top focus cycle root ancestor. Check + // if it is root. + if (ancestor != root) + throw new IllegalArgumentException ("the given container is not" + + " a focus cycle root of the" + + " current component"); + else + break; + } + prevAncestor = ancestor; + } + + // FIXME: is this the right thing to do here? It moves the context + // for traversal up one focus traversal cycle. We'll need a test + // for this. + if ((Component) root == current) + root = current.getFocusCycleRootAncestor (); + + // Check if we've reached the top of the component hierarchy. If + // so then we want to loop around to the last component in the + // focus traversal cycle. + if (current instanceof Window) + return getLastComponent ((Container) current); + + Container parent = current.getParent (); + + synchronized (parent.getTreeLock ()) + { + Component[] components = parent.getComponents (); + int componentIndex = 0; + int numComponents = parent.getComponentCount (); + + // Find component's index. + for (int i = 0; i < numComponents; i++) + { + if (components[i] == current) + componentIndex = i; + } + + // Search backward for the next acceptable component. + for (int i = componentIndex - 1; i >= 0; i--) + { + if (accept (components[i])) + return components[i]; + + if (components[i] instanceof Container) + { + Component result = getLastComponent ((Container) components[i]); + + if (result != null) + return result; + } + } + + // No focusable components before current in its Container. So go + // to the previous Component before current's Container (parent). + Component result = getComponentBefore (root, parent); + + return result; + } + } + + /** + * Returns the first Component of root that should receive the focus. + * + * @param root a focus cycle root + * + * @return the first Component in the focus traversal order for + * root, or null if no acceptable Component exists. + * + * @exception IllegalArgumentException If root is null. + */ + public Component getFirstComponent(Container root) + { + if (root == null) + throw new IllegalArgumentException (); + + if (!root.isVisible () + || !root.isDisplayable ()) + return null; + + if (accept (root)) + return root; + + Component[] componentArray = root.getComponents (); + + for (int i = 0; i < componentArray.length; i++) + { + Component component = componentArray [i]; + + if (accept (component)) + return component; + + if (component instanceof Container) + { + Component result = getFirstComponent ((Container) component); + + if (result != null) + return result; + } + } + + return null; + } + + /** + * Returns the last Component of root that should receive the focus. + * + * @param root a focus cycle root + * + * @return the last Component in the focus traversal order for + * root, or null if no acceptable Component exists. + * + * @exception IllegalArgumentException If root is null. + */ + public Component getLastComponent (Container root) + { + if (root == null) + throw new IllegalArgumentException (); + + if (!root.isVisible () + || !root.isDisplayable ()) + return null; + + if (accept (root)) + return root; + + Component[] componentArray = root.getComponents (); + + for (int i = componentArray.length - 1; i >= 0; i--) + { + Component component = componentArray [i]; + + if (accept (component)) + return component; + + if (component instanceof Container) + { + Component result = getLastComponent ((Container) component); + + if (result != null) + return result; + } + } + + return null; + } + + /** + * Returns the default Component of root that should receive the focus. + * + * @param root a focus cycle root + * + * @return the default Component in the focus traversal order for + * root, or null if no acceptable Component exists. + * + * @exception IllegalArgumentException If root is null. + */ + public Component getDefaultComponent (Container root) + { + return getFirstComponent (root); + } + + /** + * Set whether or not implicit down cycling is enabled. If it is, + * then initiating a forward focus traversal operation onto a focus + * cycle root, the focus will be implicitly transferred into the + * root container's focus cycle. + * + * @param value the setting for implicit down cycling + */ + public void setImplicitDownCycleTraversal (boolean value) + { + implicitDownCycleTraversal = value; + } + + /** + * Check whether or not implicit down cycling is enabled. If it is, + * then initiating a forward focus traversal operation onto a focus + * cycle root, the focus will be implicitly transferred into the + * root container's focus cycle. + * + * @return true if the focus will be transferred down-cycle + * implicitly + */ + public boolean getImplicitDownCycleTraversal () + { + return implicitDownCycleTraversal; + } + + /** + * Check whether the given Component is an acceptable target for the + * keyboard input focus. + * + * @param current the Component to check + * + * @return true if current is acceptable, false otherwise + */ + protected boolean accept (Component current) + { + return (current.visible + && current.isDisplayable () + && current.enabled + && current.focusable); + } +} |