home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-03-20 | 11.8 KB | 315 lines |
- /*
- * @(#)DefaultFocusManager.java 1.6 98/01/30
- *
- * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
- *
- * This software is the confidential and proprietary information of Sun
- * Microsystems, Inc. ("Confidential Information"). You shall not
- * disclose such Confidential Information and shall use it only in
- * accordance with the terms of the license agreement you entered into
- * with Sun.
- *
- * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
- * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
- * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
- * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
- * THIS SOFTWARE OR ITS DERIVATIVES.
- *
- */
- package java.awt.swing;
-
- /**
- * Default swing focus manager implementation
- *
- * @version 1.6 01/30/98
- * @author Arnaud Weber
- */
- import java.awt.event.KeyEvent;
- import java.awt.Component;
- import java.awt.Container;
- import java.awt.event.ActionEvent;
- import java.awt.Window;
- import java.awt.Dialog;
- import java.awt.Rectangle;
- import java.util.Vector;
-
- public class DefaultFocusManager extends FocusManager {
-
- /** This method is called by JComponents when a key event occurs.
- * JComponent gives key events to the focus manager
- * first, then to key listeners, then to the keyboard UI dispatcher.
- * This method should look at the key event and change the focused
- * component if the key event matches the receiver's focus manager
- * hot keys. For example the default focus manager will change the
- * focus if the key event matches TAB or Shift + TAB.
- * The focus manager should call consume() on <b>anEvent</b> if
- * <code>anEvent</code> has been processed.
- * <code>focusedComponent</code> is the component that currently has
- * the focus.
- * Note: FocusManager will receive KEY_PRESSED, KEY_RELEASED and KEY_TYPED
- * key events. If one event is consumed, all other events type should be consumed.
- */
- public void processKeyEvent(Component focusedComponent,KeyEvent anEvent) {
- if(anEvent.getKeyCode() == KeyEvent.VK_TAB || anEvent.getKeyChar() == '\t') {
- /** If the focused component manages focus, let it do so
- * if control is not pressed
- */
- if(focusedComponent instanceof JComponent) {
- JComponent fc = (JComponent) focusedComponent;
- if(fc.isManagingFocus()) {
- if(!((anEvent.getModifiers() & ActionEvent.CTRL_MASK) ==
- ActionEvent.CTRL_MASK))
- return;
- }
- }
-
- /** If this is not a key press, consume and return **/
- if(anEvent.getID() != KeyEvent.KEY_PRESSED){
- anEvent.consume();
- return;
- }
-
- if((anEvent.getModifiers() & ActionEvent.SHIFT_MASK) == ActionEvent.SHIFT_MASK)
- focusPreviousComponent(focusedComponent);
- else
- focusNextComponent(focusedComponent);
- anEvent.consume();
- }
- }
-
- /** Cause the focus manager to set the focus on the next focusable component **/
- public void focusNextComponent(Component aComponent) {
- if(aComponent instanceof JComponent) {
- JComponent fc = (JComponent) aComponent;
- Component nc;
- Container root = getFocusRoot(fc);
- if(root != null) {
- nc = getFocusableComponentAfter(fc,root,true);
- if(nc != null) {
- if(nc instanceof JComponent)
- ((JComponent)nc).grabFocus();
- else
- nc.requestFocus();
- }
- }
- }
- }
-
- /** Cause the focus manager to set the focus on the previous focusable component **/
- public void focusPreviousComponent(Component aComponent) {
- if(aComponent instanceof JComponent) {
- JComponent fc = (JComponent) aComponent;
- Component nc;
- Container root = getFocusRoot(fc);
-
- if(root != null) {
- nc = getFocusableComponentAfter(fc,root,false);
- if(nc != null) {
- if(nc instanceof JComponent)
- ((JComponent)nc).grabFocus();
- else
- nc.requestFocus();
- }
- }
- }
- }
-
- Container getFocusRoot(Component c) {
- Container p;
- for(p = c.getParent() ; p != null ; p = p.getParent()) {
- if(((p instanceof JComponent) && ((JComponent)p).isFocusCycleRoot()) ||
- (p instanceof Window) || (p instanceof Dialog))
- return p;
- }
- return null;
- }
-
- private Component getFocusableComponentAfter(Component focusedComponent,
- Container rootContainer,
- boolean moveForward) {
- Component nextComponent;
- Component initialComponent;
-
- nextComponent = initialComponent = focusedComponent;
- do {
- if(moveForward)
- nextComponent = getNextComponent(nextComponent,rootContainer,true);
- else
- nextComponent = getPreviousComponent(nextComponent,rootContainer);
-
- if(nextComponent == null)
- break;
- if(nextComponent == initialComponent)
- break;
- } while(!(nextComponent.isFocusTraversable() && nextComponent.isEnabled()));
-
- return nextComponent;
- }
-
- private Component getNextComponent(Component component,
- Container root,
- boolean canGoDown) {
- Component nsv = null;
- if(canGoDown &&
- (((component instanceof JComponent) &&
- !((JComponent)component).isManagingFocus()) ||
- !(component instanceof JComponent)) &&
- ((component instanceof Container) && ((Container)component).getComponentCount() > 0)) {
- return getFirstComponent((Container)component);
- } else {
- Container parent = component.getParent();
- nsv = getComponentAfter(parent,component);
- if(nsv != null)
- return nsv;
- if(parent == root)
- return root;
- else
- return getNextComponent(parent,root,false);
- }
- }
-
- private Component getPreviousComponent(Component component,Container root) {
- Container parent = component.getParent();
- if(component == root)
- return getDeepestLastComponent(root);
- else {
- Component nsv = getComponentBefore(parent,component);
- if(nsv != null)
- return getDeepestLastComponent(nsv);
- else
- return parent;
- }
- }
-
- private Component getDeepestLastComponent(Component component) {
- if((((component instanceof JComponent) &&
- !((JComponent)component).isManagingFocus()) ||
- !(component instanceof JComponent)) &&
- ((component instanceof Container) && ((Container)component).getComponentCount() > 0)) {
- return getDeepestLastComponent(getLastComponent((Container) component));
- } else
- return component;
- }
-
- /** Return the first component that should receive the focus **/
- public Component getFirstComponent(Container aContainer) {
- Component orderedChildren[] = childrenTabOrder(aContainer);
- if(orderedChildren.length > 0)
- return orderedChildren[0];
- else
- return null;
- }
-
- /** Return the last component that should receive the focus **/
- public Component getLastComponent(Container aContainer) {
- Component orderedChildren[] = childrenTabOrder(aContainer);
- if(orderedChildren.length > 0)
- return orderedChildren[orderedChildren.length - 1];
- else
- return null;
- }
-
- /** Return the component that should receive the focus before aComponent **/
- public Component getComponentBefore(Container aContainer,Component aComponent) {
- Component orderedChildren[] = childrenTabOrder(aContainer);
- int i,c;
- for(i=1,c=orderedChildren.length ; i < c ; i++)
- if(orderedChildren[i] == aComponent)
- return orderedChildren[i-1];
- return null;
- }
-
- /** Return the component the should receive the focus after aComponent **/
- public Component getComponentAfter(Container aContainer,Component aComponent) {
- Component orderedChildren[] = childrenTabOrder(aContainer);
- int i,c;
- for(i=0,c=orderedChildren.length - 1; i < c ; i++)
- if(orderedChildren[i] == aComponent)
- return orderedChildren[i+1];
- return null;
- }
-
-
- /** Return true if <code>a</code> should be before <code>b</code> in the
- * "tab" order. Override this method if you want to change the automatic
- * "tab" order.
- * The default implementation will order tab to give a left to right, top
- * down order. Override this method if another order is required.
- */
- public boolean compareTabOrder(Component a,Component b) {
- Rectangle bounds;
- int ay,by;
- int ax,bx;
- if(a instanceof JComponent) {
- ay = ((JComponent)a).getY();
- ax = ((JComponent)a).getX();
- } else {
- bounds = a.getBounds();
- ay = bounds.y;
- ax = bounds.x;
- }
-
- if(b instanceof JComponent) {
- by = ((JComponent)b).getY();
- bx = ((JComponent)b).getX();
- } else {
- bounds = b.getBounds();
- by = bounds.y;
- bx = bounds.x;
- }
-
- if(Math.abs(ay - by) < 10) {
- return (ax < bx);
- }
- return (ay < by);
- }
-
- Component[] childrenTabOrder(Container co) {
- Component children[] = co.getComponents();
- Component tmp;
- int i,j,c;
- boolean hasLink = false;
-
- /** Get the tab order from the geometry **/
- for(i=0,c = children.length ; i < c ; i++) {
- if(!hasLink && (children[i] instanceof JComponent) &&
- ((JComponent)children[i]).getNextFocusableComponent() != null)
- hasLink = true;
- for(j=i ; j < c ; j++) {
- if(i==j)
- continue;
- if(compareTabOrder(children[j],children[i])) {
- tmp = children[i];
- children[i] = children[j];
- children[j] = tmp;
- }
- }
- }
-
- if(hasLink) {
- int index;
- Component nextComponent;
- Vector v = new Vector(c);
- for(i=0; i < c ; i++)
- v.addElement(children[i]);
-
- /** Take in account the next component link **/
- for(i=0 ; i < c ; i++) {
- if((children[i] instanceof JComponent) &&
- (nextComponent = ((JComponent)children[i]).getNextFocusableComponent()) != null) {
- if((index = v.indexOf(nextComponent)) != -1) {
- v.removeElementAt(index);
- v.insertElementAt(nextComponent,i+1);
- }
- }
- }
-
- for(i=0 ; i < c ; i++)
- children[i] = (Component) v.elementAt(i);
- }
-
- return children;
- }
- }
-