/* This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV This program is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program; if not, see http://www.gnu.org/licenses or write to the Free Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 */ package com.servoy.j2db.smart.dataui; import java.awt.Component; import java.awt.Container; import java.awt.DefaultFocusTraversalPolicy; import java.util.List; import com.servoy.j2db.util.IFocusCycleRoot; /** * Focus traversal policy that takes into account the defined tab sequence. */ public class ServoyFocusTraversalPolicy extends DefaultFocusTraversalPolicy { public static final DefaultFocusTraversalPolicy defaultPolicy = new DefaultFocusTraversalPolicy(); public static final ServoyFocusTraversalPolicy datarenderPolicy = new ServoyFocusTraversalPolicy(); @Override public Component getComponentAfter(Container focusCycleRoot, Component aComponent) { Component next = getNeighborComponent(focusCycleRoot, aComponent, false); if (next != null) return next; else return super.getComponentAfter(focusCycleRoot, aComponent); } @Override public Component getComponentBefore(Container focusCycleRoot, Component aComponent) { Component prev = getNeighborComponent(focusCycleRoot, aComponent, true); if (prev != null) return prev; else return super.getComponentBefore(focusCycleRoot, aComponent); } private Component getNeighborComponent(Container focusCycleRoot, Component aComponent, boolean moveBackwards) { if (focusCycleRoot instanceof IFocusCycleRoot) { if (!((IFocusCycleRoot)focusCycleRoot).isTraversalPolicyEnabled()) return null; List<Component> componentSet = ((IFocusCycleRoot<Component>)focusCycleRoot).getTabSeqComponents(); if (componentSet != null) { Object[] componentList = componentSet.toArray(); // editable combobox; the editor (aComponent) is a text field that is not in the component list if (aComponent.getParent() instanceof DataComboBox) aComponent = aComponent.getParent(); Component neighbor = null; int index = -1; for (int i = 0; i < componentList.length; i++) { Component entry = (Component)componentList[i]; if (entry.equals(aComponent)) { index = i; break; } } int startIndex = index; while (index != -1) { if (moveBackwards) index--; else index++; if (index < 0) index = componentList.length - 1; if (index >= componentList.length) index = 0; Component comp = ((Component)componentList[index]); if (comp.isEnabled() && comp.isVisible()) { neighbor = comp; break; } if (startIndex == index) break; } if ((neighbor != null) && (neighbor instanceof IFocusCycleRoot) && getImplicitDownCycleTraversal()) { neighbor = traverseDownAsMuchAsPossible(neighbor, moveBackwards); } return neighbor; } } return null; } @Override public Component getDefaultComponent(Container focusCycleRoot) { if (focusCycleRoot instanceof IFocusCycleRoot) { if (!((IFocusCycleRoot)focusCycleRoot).isTraversalPolicyEnabled()) return null; return traverseDownAsMuchAsPossible(focusCycleRoot, false); } return super.getDefaultComponent(focusCycleRoot); } @Override public Component getFirstComponent(Container focusCycleRoot) { if (focusCycleRoot instanceof IFocusCycleRoot) { if (!((IFocusCycleRoot)focusCycleRoot).isTraversalPolicyEnabled()) return null; return traverseDownAsMuchAsPossible(focusCycleRoot, false); } return super.getFirstComponent(focusCycleRoot); } @Override public Component getLastComponent(Container focusCycleRoot) { if (focusCycleRoot instanceof IFocusCycleRoot) { if (!((IFocusCycleRoot)focusCycleRoot).isTraversalPolicyEnabled()) return null; return traverseDownAsMuchAsPossible(focusCycleRoot, true); } return super.getLastComponent(focusCycleRoot); } private Component traverseDownAsMuchAsPossible(Component c, boolean moveBackwards) { if (c instanceof IFocusCycleRoot) { IFocusCycleRoot root = (IFocusCycleRoot)c; if (root.isTraversalPolicyEnabled()) { Component firstChild; if (moveBackwards) firstChild = (Component)root.getLastFocusableField(); else firstChild = (Component)root.getFirstFocusableField(); if (firstChild != null) { return traverseDownAsMuchAsPossible(firstChild, moveBackwards); } } } else { if (c != null && (!c.isEnabled() || !c.isVisible())) { return getNeighborComponent(c.getFocusCycleRootAncestor(), c, moveBackwards); } } return c; } }