Package com.eviware.soapui.support.swing

Source Code of com.eviware.soapui.support.swing.JXButtonPanel$JXButtonPanelFocusTraversalPolicy

/*
*  soapUI, copyright (C) 2004-2011 eviware.com
*
*  soapUI is free software; you can redistribute it and/or modify it under the
*  terms of version 2.1 of the GNU Lesser General Public License as published by
*  the Free Software Foundation.
*
*  soapUI 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 Lesser General Public License for more details at gnu.org.
*/

package com.eviware.soapui.support.swing;

import java.awt.Component;
import java.awt.Container;
import java.awt.FocusTraversalPolicy;
import java.awt.KeyboardFocusManager;
import java.awt.LayoutManager;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.DefaultButtonModel;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.LayoutFocusTraversalPolicy;

/**
* This is a JPanel subclass which provides a special functionality for its
* children buttons components. It makes it possible to transfer focus from
* button to button with help of arrows keys.
* <p>
* The following example shows how to enable cyclic focus transfer
*
* <pre>
* import org.jdesktop.swinghelper.buttonpanel.*;
* import javax.swing.*;
*
* public class SimpleDemo
* {
*   public static void main( String[] args ) throws Exception
*   {
*     SwingUtilities.invokeLater( new Runnable()
*     {
*       public void run()
*       {
*         final JFrame frame = new JFrame();
*         frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
*
*         JXButtonPanel panel = new JXButtonPanel();
*         panel.setCyclic( true );
*
*         panel.add( new JButton( &quot;One&quot; ) );
*         panel.add( new JButton( &quot;Two&quot; ) );
*         panel.add( new JButton( &quot;Three&quot; ) );
*
*         frame.add( panel );
*         frame.setSize( 200, 200 );
*         frame.setLocationRelativeTo( null );
*         frame.setVisible( true );
*       }
*     } );
*   }
* }
* </pre>
*
* If your buttons inside JXButtonPanel are added to one ButtonGroup arrow keys
* will transfer selection between them as well as they do it for focus
* <p>
* Note: you can control this behaviour with
* setGroupSelectionFollowFocus(boolean)
*
* <pre>
* import org.jdesktop.swinghelper.buttonpanel.*;
* import javax.swing.*;
*
* public class RadioButtonDemo
* {
*   public static void main( String[] args ) throws Exception
*   {
*     SwingUtilities.invokeLater( new Runnable()
*     {
*       public void run()
*       {
*         final JFrame frame = new JFrame();
*         frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
*
*         JXButtonPanel panel = new JXButtonPanel();
*         ButtonGroup group = new ButtonGroup();
*
*         JRadioButton rb1 = new JRadioButton( &quot;One&quot; );
*         panel.add( rb1 );
*         group.add( rb1 );
*         JRadioButton rb2 = new JRadioButton( &quot;Two&quot; );
*         panel.add( rb2 );
*         group.add( rb2 );
*         JRadioButton rb3 = new JRadioButton( &quot;Three&quot; );
*         panel.add( rb3 );
*         group.add( rb3 );
*
*         rb1.setSelected( true );
*         frame.add( panel );
*
*         frame.setSize( 200, 200 );
*         frame.setLocationRelativeTo( null );
*         frame.setVisible( true );
*       }
*     } );
*   }
* }
* </pre>
*
* @author Alexander Potochkin
*
*         https://swinghelper.dev.java.net/
*         http://weblogs.java.net/blog/alexfromsun/
*/
public class JXButtonPanel extends JPanel
{
  private boolean isCyclic;
  private boolean isGroupSelectionFollowFocus;

  /**
   * {@inheritDoc}
   */
  public JXButtonPanel()
  {
    super();
    init();
  }

  /**
   * {@inheritDoc}
   */
  public JXButtonPanel( LayoutManager layout )
  {
    super( layout );
    init();
  }

  /**
   * {@inheritDoc}
   */
  public JXButtonPanel( boolean isDoubleBuffered )
  {
    super( isDoubleBuffered );
    init();
  }

  /**
   * {@inheritDoc}
   */
  public JXButtonPanel( LayoutManager layout, boolean isDoubleBuffered )
  {
    super( layout, isDoubleBuffered );
    init();
  }

  private void init()
  {
    setFocusTraversalPolicyProvider( true );
    setFocusTraversalPolicy( new JXButtonPanelFocusTraversalPolicy() );
    ActionListener actionHandler = new ActionHandler();
    registerKeyboardAction( actionHandler, ActionHandler.FORWARD, KeyStroke.getKeyStroke( KeyEvent.VK_RIGHT, 0 ),
        JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
    registerKeyboardAction( actionHandler, ActionHandler.FORWARD, KeyStroke.getKeyStroke( KeyEvent.VK_DOWN, 0 ),
        JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
    registerKeyboardAction( actionHandler, ActionHandler.BACKWARD, KeyStroke.getKeyStroke( KeyEvent.VK_LEFT, 0 ),
        JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
    registerKeyboardAction( actionHandler, ActionHandler.BACKWARD, KeyStroke.getKeyStroke( KeyEvent.VK_UP, 0 ),
        JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT );
    setGroupSelectionFollowFocus( true );
  }

  /**
   * Returns whether arrow keys should support cyclic focus traversal ordering
   * for for this JXButtonPanel.
   */
  public boolean isCyclic()
  {
    return isCyclic;
  }

  /**
   * Sets whether arrow keys should support cyclic focus traversal ordering for
   * this JXButtonPanel.
   */
  public void setCyclic( boolean isCyclic )
  {
    this.isCyclic = isCyclic;
  }

  /**
   * Returns whether arrow keys should transfer button's selection as well as
   * focus for this JXButtonPanel.
   * <p>
   *
   * Note: this property affects buttons which are added to a ButtonGroup
   */
  public boolean isGroupSelectionFollowFocus()
  {
    return isGroupSelectionFollowFocus;
  }

  /**
   * Sets whether arrow keys should transfer button's selection as well as
   * focus for this JXButtonPanel.
   * <p>
   *
   * Note: this property affects buttons which are added to a ButtonGroup
   */
  public void setGroupSelectionFollowFocus( boolean groupSelectionFollowFocus )
  {
    isGroupSelectionFollowFocus = groupSelectionFollowFocus;
  }

  private static ButtonGroup getButtonGroup( AbstractButton button )
  {
    ButtonModel model = button.getModel();
    if( model instanceof DefaultButtonModel )
    {
      return ( ( DefaultButtonModel )model ).getGroup();
    }
    return null;
  }

  private class ActionHandler implements ActionListener
  {
    private static final String FORWARD = "moveSelectionForward";
    private static final String BACKWARD = "moveSelectionBackward";

    public void actionPerformed( ActionEvent e )
    {
      FocusTraversalPolicy ftp = JXButtonPanel.this.getFocusTraversalPolicy();

      if( ftp instanceof JXButtonPanelFocusTraversalPolicy )
      {
        JXButtonPanelFocusTraversalPolicy xftp = ( JXButtonPanelFocusTraversalPolicy )ftp;

        String actionCommand = e.getActionCommand();
        Component fo = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
        Component next;

        xftp.setAlternativeFocusMode( true );

        if( FORWARD.equals( actionCommand ) )
        {
          next = xftp.getComponentAfter( JXButtonPanel.this, fo );
        }
        else if( BACKWARD.equals( actionCommand ) )
        {
          next = xftp.getComponentBefore( JXButtonPanel.this, fo );
        }
        else
        {
          throw new AssertionError( "Unexpected action command: " + actionCommand );
        }

        xftp.setAlternativeFocusMode( false );

        if( fo instanceof AbstractButton )
        {
          AbstractButton b = ( AbstractButton )fo;
          b.getModel().setPressed( false );
        }
        if( next != null )
        {
          if( fo instanceof AbstractButton && next instanceof AbstractButton )
          {
            ButtonGroup group = getButtonGroup( ( AbstractButton )fo );
            AbstractButton nextButton = ( AbstractButton )next;
            if( group != getButtonGroup( nextButton ) )
            {
              return;
            }
            if( isGroupSelectionFollowFocus() && group != null && group.getSelection() != null
                && !nextButton.isSelected() )
            {
              nextButton.setSelected( true );
            }
            next.requestFocusInWindow();
          }
        }
      }
    }
  }

  private class JXButtonPanelFocusTraversalPolicy extends LayoutFocusTraversalPolicy
  {
    private boolean isAlternativeFocusMode;

    public boolean isAlternativeFocusMode()
    {
      return isAlternativeFocusMode;
    }

    public void setAlternativeFocusMode( boolean alternativeFocusMode )
    {
      isAlternativeFocusMode = alternativeFocusMode;
    }

    protected boolean accept( Component c )
    {
      if( !isAlternativeFocusMode() && c instanceof AbstractButton )
      {
        AbstractButton button = ( AbstractButton )c;
        ButtonGroup group = JXButtonPanel.getButtonGroup( button );
        if( group != null && group.getSelection() != null && !button.isSelected() )
        {
          return false;
        }
      }
      return super.accept( c );
    }

    public Component getComponentAfter( Container aContainer, Component aComponent )
    {
      Component componentAfter = super.getComponentAfter( aContainer, aComponent );
      if( !isAlternativeFocusMode() )
      {
        return componentAfter;
      }
      if( JXButtonPanel.this.isCyclic() )
      {
        return componentAfter == null ? getFirstComponent( aContainer ) : componentAfter;
      }
      if( aComponent == getLastComponent( aContainer ) )
      {
        return aComponent;
      }
      return componentAfter;
    }

    public Component getComponentBefore( Container aContainer, Component aComponent )
    {
      Component componentBefore = super.getComponentBefore( aContainer, aComponent );
      if( !isAlternativeFocusMode() )
      {
        return componentBefore;
      }
      if( JXButtonPanel.this.isCyclic() )
      {
        return componentBefore == null ? getLastComponent( aContainer ) : componentBefore;
      }
      if( aComponent == getFirstComponent( aContainer ) )
      {
        return aComponent;
      }
      return componentBefore;
    }
  }
}
TOP

Related Classes of com.eviware.soapui.support.swing.JXButtonPanel$JXButtonPanelFocusTraversalPolicy

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.