mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-08 06:50:56 +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
|
- Skip components with empty input map (e.g. `JLabel`) when using arrow keys
|
||||||
to navigate in focusable buttons (if UI value `ToolBar.focusableButtons` is
|
to navigate in focusable buttons (if UI value `ToolBar.focusableButtons` is
|
||||||
`true`).
|
`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
|
- Added more color functions to class `ColorFunctions` for easy use in
|
||||||
applications: `lighten()`, `darken()`, `saturate()`, `desaturate()`, `spin()`,
|
applications: `lighten()`, `darken()`, `saturate()`, `desaturate()`, `spin()`,
|
||||||
`tint()`, `shade()` and `luma()`.
|
`tint()`, `shade()` and `luma()`.
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ package com.formdev.flatlaf.ui;
|
|||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.awt.Component;
|
import java.awt.Component;
|
||||||
|
import java.awt.Container;
|
||||||
|
import java.awt.FocusTraversalPolicy;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
import java.awt.event.ContainerEvent;
|
import java.awt.event.ContainerEvent;
|
||||||
import java.awt.event.ContainerListener;
|
import java.awt.event.ContainerListener;
|
||||||
@@ -26,6 +28,7 @@ import java.util.Map;
|
|||||||
import javax.swing.AbstractButton;
|
import javax.swing.AbstractButton;
|
||||||
import javax.swing.InputMap;
|
import javax.swing.InputMap;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.LayoutFocusTraversalPolicy;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.border.Border;
|
import javax.swing.border.Border;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
@@ -52,6 +55,7 @@ import com.formdev.flatlaf.util.LoggingFacade;
|
|||||||
* <!-- FlatToolBarUI -->
|
* <!-- FlatToolBarUI -->
|
||||||
*
|
*
|
||||||
* @uiDefault ToolBar.focusableButtons boolean
|
* @uiDefault ToolBar.focusableButtons boolean
|
||||||
|
* @uiDefault ToolBar.arrowKeysOnlyNavigation boolean
|
||||||
* @uiDefault ToolBar.floatable boolean
|
* @uiDefault ToolBar.floatable boolean
|
||||||
*
|
*
|
||||||
* <!-- FlatToolBarBorder -->
|
* <!-- FlatToolBarBorder -->
|
||||||
@@ -65,13 +69,14 @@ public class FlatToolBarUI
|
|||||||
extends BasicToolBarUI
|
extends BasicToolBarUI
|
||||||
implements StyleableUI
|
implements StyleableUI
|
||||||
{
|
{
|
||||||
/** @since 1.4 */
|
/** @since 1.4 */ @Styleable protected boolean focusableButtons;
|
||||||
@Styleable protected boolean focusableButtons;
|
/** @since 2 */ @Styleable protected boolean arrowKeysOnlyNavigation;
|
||||||
|
|
||||||
// for FlatToolBarBorder
|
// for FlatToolBarBorder
|
||||||
@Styleable protected Insets borderMargins;
|
@Styleable protected Insets borderMargins;
|
||||||
@Styleable protected Color gripColor;
|
@Styleable protected Color gripColor;
|
||||||
|
|
||||||
|
private FocusTraversalPolicy focusTraversalPolicy;
|
||||||
private Boolean oldFloatable;
|
private Boolean oldFloatable;
|
||||||
private Map<String, Object> oldStyleValues;
|
private Map<String, Object> oldStyleValues;
|
||||||
|
|
||||||
@@ -83,6 +88,8 @@ public class FlatToolBarUI
|
|||||||
public void installUI( JComponent c ) {
|
public void installUI( JComponent c ) {
|
||||||
super.installUI( c );
|
super.installUI( c );
|
||||||
|
|
||||||
|
installFocusTraversalPolicy();
|
||||||
|
|
||||||
installStyle();
|
installStyle();
|
||||||
|
|
||||||
// disable focusable state of buttons (when switching from another Laf)
|
// disable focusable state of buttons (when switching from another Laf)
|
||||||
@@ -100,6 +107,8 @@ public class FlatToolBarUI
|
|||||||
if( !focusableButtons )
|
if( !focusableButtons )
|
||||||
setButtonsFocusable( true );
|
setButtonsFocusable( true );
|
||||||
|
|
||||||
|
uninstallFocusTraversalPolicy();
|
||||||
|
|
||||||
oldStyleValues = null;
|
oldStyleValues = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +117,7 @@ public class FlatToolBarUI
|
|||||||
super.installDefaults();
|
super.installDefaults();
|
||||||
|
|
||||||
focusableButtons = UIManager.getBoolean( "ToolBar.focusableButtons" );
|
focusableButtons = UIManager.getBoolean( "ToolBar.focusableButtons" );
|
||||||
|
arrowKeysOnlyNavigation = UIManager.getBoolean( "ToolBar.arrowKeysOnlyNavigation" );
|
||||||
|
|
||||||
// floatable
|
// floatable
|
||||||
if( !UIManager.getBoolean( "ToolBar.floatable" ) ) {
|
if( !UIManager.getBoolean( "ToolBar.floatable" ) ) {
|
||||||
@@ -165,11 +175,18 @@ public class FlatToolBarUI
|
|||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
protected void applyStyle( Object style ) {
|
protected void applyStyle( Object style ) {
|
||||||
boolean oldFocusableButtons = focusableButtons;
|
boolean oldFocusableButtons = focusableButtons;
|
||||||
|
boolean oldArrowKeysOnlyNavigation = arrowKeysOnlyNavigation;
|
||||||
|
|
||||||
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
|
oldStyleValues = FlatStylingSupport.parseAndApply( oldStyleValues, style, this::applyStyleProperty );
|
||||||
|
|
||||||
if( focusableButtons != oldFocusableButtons )
|
if( focusableButtons != oldFocusableButtons )
|
||||||
setButtonsFocusable( focusableButtons );
|
setButtonsFocusable( focusableButtons );
|
||||||
|
if( arrowKeysOnlyNavigation != oldArrowKeysOnlyNavigation || focusableButtons != oldFocusableButtons ) {
|
||||||
|
if( arrowKeysOnlyNavigation )
|
||||||
|
installFocusTraversalPolicy();
|
||||||
|
else
|
||||||
|
uninstallFocusTraversalPolicy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @since 2 */
|
/** @since 2 */
|
||||||
@@ -194,6 +211,32 @@ public class FlatToolBarUI
|
|||||||
c.setFocusable( focusable );
|
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
|
* Does the same as super.navigateFocusedComp() with the exception that components
|
||||||
* with empty input map (e.g. JLabel) are skipped.
|
* with empty input map (e.g. JLabel) are skipped.
|
||||||
@@ -262,4 +305,51 @@ public class FlatToolBarUI
|
|||||||
|
|
||||||
super.setOrientation( orientation );
|
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.border = com.formdev.flatlaf.ui.FlatToolBarBorder
|
||||||
ToolBar.borderMargins = 2,2,2,2
|
ToolBar.borderMargins = 2,2,2,2
|
||||||
ToolBar.isRollover = true
|
ToolBar.isRollover = true
|
||||||
ToolBar.floatable = false
|
|
||||||
ToolBar.focusableButtons = false
|
ToolBar.focusableButtons = false
|
||||||
|
ToolBar.arrowKeysOnlyNavigation = true
|
||||||
|
ToolBar.floatable = false
|
||||||
ToolBar.gripColor = @icon
|
ToolBar.gripColor = @icon
|
||||||
ToolBar.dockingBackground = darken($ToolBar.background,5%)
|
ToolBar.dockingBackground = darken($ToolBar.background,5%)
|
||||||
ToolBar.dockingForeground = $Component.borderColor
|
ToolBar.dockingForeground = $Component.borderColor
|
||||||
|
|||||||
@@ -1262,6 +1262,7 @@ ToggleButtonUI com.formdev.flatlaf.ui.FlatToggleButtonUI
|
|||||||
|
|
||||||
#---- ToolBar ----
|
#---- ToolBar ----
|
||||||
|
|
||||||
|
ToolBar.arrowKeysOnlyNavigation true
|
||||||
ToolBar.background #3c3f41 HSL 204 4 25 javax.swing.plaf.ColorUIResource [UI]
|
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.border [lazy] 2,2,2,2 false com.formdev.flatlaf.ui.FlatToolBarBorder [UI]
|
||||||
ToolBar.borderMargins 2,2,2,2 javax.swing.plaf.InsetsUIResource [UI]
|
ToolBar.borderMargins 2,2,2,2 javax.swing.plaf.InsetsUIResource [UI]
|
||||||
|
|||||||
@@ -1267,6 +1267,7 @@ ToggleButtonUI com.formdev.flatlaf.ui.FlatToggleButtonUI
|
|||||||
|
|
||||||
#---- ToolBar ----
|
#---- ToolBar ----
|
||||||
|
|
||||||
|
ToolBar.arrowKeysOnlyNavigation true
|
||||||
ToolBar.background #f2f2f2 HSL 0 0 95 javax.swing.plaf.ColorUIResource [UI]
|
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.border [lazy] 2,2,2,2 false com.formdev.flatlaf.ui.FlatToolBarBorder [UI]
|
||||||
ToolBar.borderMargins 2,2,2,2 javax.swing.plaf.InsetsUIResource [UI]
|
ToolBar.borderMargins 2,2,2,2 javax.swing.plaf.InsetsUIResource [UI]
|
||||||
|
|||||||
@@ -1275,6 +1275,7 @@ ToggleButtonUI com.formdev.flatlaf.ui.FlatToggleButtonUI
|
|||||||
|
|
||||||
#---- ToolBar ----
|
#---- ToolBar ----
|
||||||
|
|
||||||
|
ToolBar.arrowKeysOnlyNavigation true
|
||||||
ToolBar.background #ccffcc HSL 120 100 90 javax.swing.plaf.ColorUIResource [UI]
|
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.border [lazy] 2,2,2,2 false com.formdev.flatlaf.ui.FlatToolBarBorder [UI]
|
||||||
ToolBar.borderMargins 2,2,2,2 javax.swing.plaf.InsetsUIResource [UI]
|
ToolBar.borderMargins 2,2,2,2 javax.swing.plaf.InsetsUIResource [UI]
|
||||||
|
|||||||
@@ -983,6 +983,7 @@ ToggleButton.toolbar.pressedBackground
|
|||||||
ToggleButton.toolbar.selectedBackground
|
ToggleButton.toolbar.selectedBackground
|
||||||
ToggleButtonUI
|
ToggleButtonUI
|
||||||
ToolBar.ancestorInputMap
|
ToolBar.ancestorInputMap
|
||||||
|
ToolBar.arrowKeysOnlyNavigation
|
||||||
ToolBar.background
|
ToolBar.background
|
||||||
ToolBar.border
|
ToolBar.border
|
||||||
ToolBar.borderMargins
|
ToolBar.borderMargins
|
||||||
|
|||||||
Reference in New Issue
Block a user