mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-06 14:00:55 +03:00
ToolBar: support arrow-keys-only navigation within focusable buttons of toolbar:
- arrow keys move focus within toolbar (provided by `BasicToolBarUI`) - tab-key moves focus out of toolbar - if moving focus into the toolbar, focus recently focused toolbar button (issue #346)
This commit is contained in:
@@ -20,6 +20,11 @@ FlatLaf Change Log
|
||||
- Skip components with empty input map (e.g. `JLabel`) when using arrow keys
|
||||
to navigate in focusable buttons (if UI value `ToolBar.focusableButtons` is
|
||||
`true`).
|
||||
- Support arrow-keys-only navigation within focusable buttons of toolbar (if
|
||||
UI value `ToolBar.focusableButtons` is `true`):
|
||||
- arrow keys move focus within toolbar
|
||||
- tab-key moves focus out of toolbar
|
||||
- if moving focus into the toolbar, focus recently focused toolbar button
|
||||
- Added more color functions to class `ColorFunctions` for easy use in
|
||||
applications: `lighten()`, `darken()`, `saturate()`, `desaturate()`, `spin()`,
|
||||
`tint()`, `shade()` and `luma()`.
|
||||
|
||||
@@ -18,6 +18,8 @@ package com.formdev.flatlaf.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.FocusTraversalPolicy;
|
||||
import java.awt.Insets;
|
||||
import java.awt.event.ContainerEvent;
|
||||
import java.awt.event.ContainerListener;
|
||||
@@ -26,6 +28,7 @@ import java.util.Map;
|
||||
import javax.swing.AbstractButton;
|
||||
import javax.swing.InputMap;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.LayoutFocusTraversalPolicy;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
@@ -52,6 +55,7 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
||||
* <!-- FlatToolBarUI -->
|
||||
*
|
||||
* @uiDefault ToolBar.focusableButtons boolean
|
||||
* @uiDefault ToolBar.arrowKeysOnlyNavigation boolean
|
||||
* @uiDefault ToolBar.floatable boolean
|
||||
*
|
||||
* <!-- FlatToolBarBorder -->
|
||||
@@ -65,13 +69,14 @@ public class FlatToolBarUI
|
||||
extends BasicToolBarUI
|
||||
implements StyleableUI
|
||||
{
|
||||
/** @since 1.4 */
|
||||
@Styleable protected boolean focusableButtons;
|
||||
/** @since 1.4 */ @Styleable protected boolean focusableButtons;
|
||||
/** @since 2 */ @Styleable protected boolean arrowKeysOnlyNavigation;
|
||||
|
||||
// for FlatToolBarBorder
|
||||
@Styleable protected Insets borderMargins;
|
||||
@Styleable protected Color gripColor;
|
||||
|
||||
private FocusTraversalPolicy focusTraversalPolicy;
|
||||
private Boolean oldFloatable;
|
||||
private Map<String, Object> oldStyleValues;
|
||||
|
||||
@@ -83,6 +88,8 @@ public class FlatToolBarUI
|
||||
public void installUI( JComponent c ) {
|
||||
super.installUI( c );
|
||||
|
||||
installFocusTraversalPolicy();
|
||||
|
||||
installStyle();
|
||||
|
||||
// disable focusable state of buttons (when switching from another Laf)
|
||||
@@ -100,6 +107,8 @@ public class FlatToolBarUI
|
||||
if( !focusableButtons )
|
||||
setButtonsFocusable( true );
|
||||
|
||||
uninstallFocusTraversalPolicy();
|
||||
|
||||
oldStyleValues = null;
|
||||
}
|
||||
|
||||
@@ -108,6 +117,7 @@ public class FlatToolBarUI
|
||||
super.installDefaults();
|
||||
|
||||
focusableButtons = UIManager.getBoolean( "ToolBar.focusableButtons" );
|
||||
arrowKeysOnlyNavigation = UIManager.getBoolean( "ToolBar.arrowKeysOnlyNavigation" );
|
||||
|
||||
// floatable
|
||||
if( !UIManager.getBoolean( "ToolBar.floatable" ) ) {
|
||||
@@ -165,11 +175,18 @@ public class FlatToolBarUI
|
||||
/** @since 2 */
|
||||
protected void applyStyle( Object style ) {
|
||||
boolean oldFocusableButtons = focusableButtons;
|
||||
boolean oldArrowKeysOnlyNavigation = arrowKeysOnlyNavigation;
|
||||
|
||||
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
|
||||
|
||||
if( focusableButtons != oldFocusableButtons )
|
||||
setButtonsFocusable( focusableButtons );
|
||||
if( arrowKeysOnlyNavigation != oldArrowKeysOnlyNavigation || focusableButtons != oldFocusableButtons ) {
|
||||
if( arrowKeysOnlyNavigation )
|
||||
installFocusTraversalPolicy();
|
||||
else
|
||||
uninstallFocusTraversalPolicy();
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
@@ -194,6 +211,32 @@ public class FlatToolBarUI
|
||||
c.setFocusable( focusable );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void installFocusTraversalPolicy() {
|
||||
if( !arrowKeysOnlyNavigation || !focusableButtons || toolBar.getFocusTraversalPolicy() != null )
|
||||
return;
|
||||
|
||||
focusTraversalPolicy = createFocusTraversalPolicy();
|
||||
if( focusTraversalPolicy != null ) {
|
||||
toolBar.setFocusTraversalPolicy( focusTraversalPolicy );
|
||||
toolBar.setFocusTraversalPolicyProvider( true );
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected void uninstallFocusTraversalPolicy() {
|
||||
if( focusTraversalPolicy != null && toolBar.getFocusTraversalPolicy() == focusTraversalPolicy ) {
|
||||
toolBar.setFocusTraversalPolicy( null );
|
||||
toolBar.setFocusTraversalPolicyProvider( false );
|
||||
}
|
||||
focusTraversalPolicy = null;
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected FocusTraversalPolicy createFocusTraversalPolicy() {
|
||||
return new FlatToolBarFocusTraversalPolicy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the same as super.navigateFocusedComp() with the exception that components
|
||||
* with empty input map (e.g. JLabel) are skipped.
|
||||
@@ -262,4 +305,51 @@ public class FlatToolBarUI
|
||||
|
||||
super.setOrientation( orientation );
|
||||
}
|
||||
|
||||
//---- class FlatToolBarFocusTraversalPolicy ------------------------------
|
||||
|
||||
/**
|
||||
* Focus traversal policy used for toolbar to modify traversal behaviour:
|
||||
* <ul>
|
||||
* <li>Tab-key moves focus out of toolbar.</li>
|
||||
* <li>If moving focus into the toolbar, focus recently focused toolbar button.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
protected class FlatToolBarFocusTraversalPolicy
|
||||
extends LayoutFocusTraversalPolicy
|
||||
{
|
||||
@Override
|
||||
public Component getComponentAfter( Container aContainer, Component aComponent ) {
|
||||
// move focus out of toolbar
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getComponentBefore( Container aContainer, Component aComponent ) {
|
||||
// move focus out of toolbar
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getFirstComponent( Container aContainer ) {
|
||||
return getRecentComponent( aContainer, true );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getLastComponent( Container aContainer ) {
|
||||
return getRecentComponent( aContainer, false );
|
||||
}
|
||||
|
||||
private Component getRecentComponent( Container aContainer, boolean first ) {
|
||||
// if moving focus into the toolbar, focus recently focused toolbar button
|
||||
if( focusedCompIndex >= 0 && focusedCompIndex < toolBar.getComponentCount() )
|
||||
return toolBar.getComponent( focusedCompIndex );
|
||||
|
||||
return first
|
||||
? super.getFirstComponent( aContainer )
|
||||
: super.getLastComponent( aContainer );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -760,8 +760,9 @@ ToggleButton.tab.focusBackground = $TabbedPane.focusColor
|
||||
ToolBar.border = com.formdev.flatlaf.ui.FlatToolBarBorder
|
||||
ToolBar.borderMargins = 2,2,2,2
|
||||
ToolBar.isRollover = true
|
||||
ToolBar.floatable = false
|
||||
ToolBar.focusableButtons = false
|
||||
ToolBar.arrowKeysOnlyNavigation = true
|
||||
ToolBar.floatable = false
|
||||
ToolBar.gripColor = @icon
|
||||
ToolBar.dockingBackground = darken($ToolBar.background,5%)
|
||||
ToolBar.dockingForeground = $Component.borderColor
|
||||
|
||||
@@ -1262,6 +1262,7 @@ ToggleButtonUI com.formdev.flatlaf.ui.FlatToggleButtonUI
|
||||
|
||||
#---- ToolBar ----
|
||||
|
||||
ToolBar.arrowKeysOnlyNavigation true
|
||||
ToolBar.background #3c3f41 HSL 204 4 25 javax.swing.plaf.ColorUIResource [UI]
|
||||
ToolBar.border [lazy] 2,2,2,2 false com.formdev.flatlaf.ui.FlatToolBarBorder [UI]
|
||||
ToolBar.borderMargins 2,2,2,2 javax.swing.plaf.InsetsUIResource [UI]
|
||||
|
||||
@@ -1267,6 +1267,7 @@ ToggleButtonUI com.formdev.flatlaf.ui.FlatToggleButtonUI
|
||||
|
||||
#---- ToolBar ----
|
||||
|
||||
ToolBar.arrowKeysOnlyNavigation true
|
||||
ToolBar.background #f2f2f2 HSL 0 0 95 javax.swing.plaf.ColorUIResource [UI]
|
||||
ToolBar.border [lazy] 2,2,2,2 false com.formdev.flatlaf.ui.FlatToolBarBorder [UI]
|
||||
ToolBar.borderMargins 2,2,2,2 javax.swing.plaf.InsetsUIResource [UI]
|
||||
|
||||
@@ -1275,6 +1275,7 @@ ToggleButtonUI com.formdev.flatlaf.ui.FlatToggleButtonUI
|
||||
|
||||
#---- ToolBar ----
|
||||
|
||||
ToolBar.arrowKeysOnlyNavigation true
|
||||
ToolBar.background #ccffcc HSL 120 100 90 javax.swing.plaf.ColorUIResource [UI]
|
||||
ToolBar.border [lazy] 2,2,2,2 false com.formdev.flatlaf.ui.FlatToolBarBorder [UI]
|
||||
ToolBar.borderMargins 2,2,2,2 javax.swing.plaf.InsetsUIResource [UI]
|
||||
|
||||
@@ -983,6 +983,7 @@ ToggleButton.toolbar.pressedBackground
|
||||
ToggleButton.toolbar.selectedBackground
|
||||
ToggleButtonUI
|
||||
ToolBar.ancestorInputMap
|
||||
ToolBar.arrowKeysOnlyNavigation
|
||||
ToolBar.background
|
||||
ToolBar.border
|
||||
ToolBar.borderMargins
|
||||
|
||||
Reference in New Issue
Block a user