All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.numdata.oss.ui.JXButtonPanel Maven / Gradle / Ivy

There is a newer version: 1.22
Show newest version
/*
 * Copyright 2006 Sun Microsystems, Inc., 4150 Network Circle,
 * Santa Clara, California 95054, U.S.A. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
package com.numdata.oss.ui;
//package org.jdesktop.swinghelper.buttonpanel;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

/**
 * 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.
 *
 * The following example shows how to enable cyclic focus transfer
 * 
 * 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("One"));
 *                 panel.add(new JButton("Two"));
 *                 panel.add(new JButton("Three"));
 *
 *                 frame.add(panel);
 *                 frame.setSize(200, 200);
 *                 frame.setLocationRelativeTo(null);
 *                 frame.setVisible(true);
 *             }
 *         });
 *     }
 * }
 * 
* * 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 * * Note: you can control this behaviour with setGroupSelectionFollowFocus(boolean) *
 * 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("One");
 *                 panel.add(rb1);
 *                 group.add(rb1);
 *                 JRadioButton rb2 = new JRadioButton("Two");
 *                 panel.add(rb2);
 *                 group.add(rb2);
 *                 JRadioButton rb3 = new JRadioButton("Three");
 *                 panel.add(rb3);
 *                 group.add(rb3);
 *
 *                 rb1.setSelected(true);
 *                 frame.add(panel);
 *
 *                 frame.setSize(200, 200);
 *                 frame.setLocationRelativeTo(null);
 *                 frame.setVisible(true);
 *             }
 *         });
 *     }
 * }
 * 
* * @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. * * 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. * * 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; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy