| /* |
| * Copyright 2000-2014 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.intellij.openapi.wm.ex; |
| |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.editor.impl.EditorComponentImpl; |
| import com.intellij.openapi.fileEditor.impl.EditorWindowHolder; |
| import com.intellij.openapi.util.Computable; |
| import com.intellij.util.ReflectionUtil; |
| import org.jetbrains.annotations.NotNull; |
| |
| import javax.swing.*; |
| import javax.swing.text.JTextComponent; |
| import java.awt.*; |
| |
| public class IdeFocusTraversalPolicy extends LayoutFocusTraversalPolicyExt { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy"); |
| |
| protected Component getDefaultComponentImpl(Container focusCycleRoot) { |
| if (!(focusCycleRoot instanceof JComponent)) { |
| return super.getDefaultComponent(focusCycleRoot); |
| } |
| return getPreferredFocusedComponent((JComponent)focusCycleRoot, this); |
| } |
| |
| public static JComponent getPreferredFocusedComponent(@NotNull final JComponent component) { |
| return getPreferredFocusedComponent(component, null); |
| } |
| |
| /** |
| * @return preferred focused component inside the specified <code>component</code>. |
| * Method can return component itself if the <code>component</code> is legal |
| * (JTextFiel)focusable |
| * |
| */ |
| public static JComponent getPreferredFocusedComponent(@NotNull final JComponent component, final FocusTraversalPolicy policyToIgnore) { |
| if (!component.isVisible()) { |
| return null; |
| } |
| |
| final FocusTraversalPolicy focusTraversalPolicy = getFocusTraversalPolicyAwtImpl(component); |
| if (focusTraversalPolicy != null && focusTraversalPolicy != policyToIgnore) { |
| if (focusTraversalPolicy.getClass().getName().indexOf("LegacyGlueFocusTraversalPolicy") >=0) { |
| return component; |
| } |
| |
| Component defaultComponent; |
| if (focusTraversalPolicy instanceof LayoutFocusTraversalPolicyExt) { |
| final LayoutFocusTraversalPolicyExt extPolicy = (LayoutFocusTraversalPolicyExt)focusTraversalPolicy; |
| defaultComponent = extPolicy.queryImpl(new Computable<Component>() { |
| @Override |
| public Component compute() { |
| return extPolicy.getDefaultComponent(component); |
| } |
| }); |
| } else { |
| defaultComponent = focusTraversalPolicy.getDefaultComponent(component); |
| } |
| |
| if (defaultComponent instanceof JComponent) { |
| return (JComponent)defaultComponent; |
| } |
| } |
| |
| if (component instanceof JTabbedPane) { |
| final JTabbedPane tabbedPane = (JTabbedPane)component; |
| final Component selectedComponent = tabbedPane.getSelectedComponent(); |
| if (selectedComponent instanceof JComponent) { |
| return getPreferredFocusedComponent((JComponent)selectedComponent); |
| } |
| return null; |
| } |
| |
| if(_accept(component)) { |
| return component; |
| } |
| |
| for (Component ca : component.getComponents()) { |
| if (!(ca instanceof JComponent)) { |
| continue; |
| } |
| final JComponent c = getPreferredFocusedComponent((JComponent)ca); |
| if (c != null) { |
| return c; |
| } |
| } |
| return null; |
| } |
| |
| private static FocusTraversalPolicy getFocusTraversalPolicyAwtImpl(final JComponent component) { |
| return ReflectionUtil.getField(Container.class, component, FocusTraversalPolicy.class, "focusTraversalPolicy"); |
| } |
| |
| protected final boolean accept(final Component aComponent) { |
| if (aComponent instanceof JComponent) { |
| return _accept((JComponent)aComponent); |
| } |
| return super.accept(aComponent); |
| } |
| |
| private static boolean _accept(final JComponent component) { |
| if (!component.isEnabled() || !component.isVisible() || !component.isFocusable()) { |
| return false; |
| } |
| |
| /** TODO[anton,vova] implement Policy in Editor component instead */ |
| if (component instanceof EditorComponentImpl || component instanceof EditorWindowHolder) { |
| return true; |
| } |
| |
| if(component instanceof JTextComponent){ |
| return ((JTextComponent)component).isEditable(); |
| } |
| |
| return |
| component instanceof AbstractButton || |
| component instanceof JList || |
| component instanceof JTree || |
| component instanceof JTable || |
| component instanceof JComboBox; |
| } |
| } |