TabbedPane: support Ctrl+TAB/Ctrl+Shift+TAB to switch to next/previous tab if a child of tabbedpane has focus

This commit is contained in:
Karl Tauber
2020-02-25 17:25:48 +01:00
parent 0d4f33ac6e
commit d1415a8c53
7 changed files with 113 additions and 3 deletions

View File

@@ -4,6 +4,8 @@ FlatLaf Change Log
## Unreleased
- PasswordField: Warn about enabled Caps Lock.
- TabbedPane: Support <kbd>Ctrl+TAB</kbd> / <kbd>Ctrl+Shift+TAB</kbd> to switch
to next / previous tab.
- TextField, FormattedTextField and PasswordField: Support round borders (see UI
default value `TextComponent.arc`). (issue #65)
- IntelliJ Themes: Added Gradianto themes to demo.

View File

@@ -69,7 +69,14 @@ class FlatInputMaps
"ctrl PAGE_DOWN", "negativeBlockIncrement",
"ctrl PAGE_UP", "positiveBlockIncrement"
);
}
modifyInputMap( defaults, "TabbedPane.ancestorInputMap",
"ctrl TAB", "navigateNext",
"shift ctrl TAB", "navigatePrevious"
);
if( !SystemInfo.IS_MAC ) {
modifyInputMap( defaults, "Tree.focusInputMap",
"ADD", "expand",
"SUBTRACT", "collapse"

View File

@@ -26,15 +26,21 @@ import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collections;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JTabbedPane;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.UIResource;
@@ -90,6 +96,9 @@ import com.formdev.flatlaf.util.UIScale;
public class FlatTabbedPaneUI
extends BasicTabbedPaneUI
{
private static Set<KeyStroke> focusForwardTraversalKeys;
private static Set<KeyStroke> focusBackwardTraversalKeys;
protected Color disabledForeground;
protected Color selectedBackground;
protected Color selectedForeground;
@@ -142,11 +151,27 @@ public class FlatTabbedPaneUI
tabHeight = scale( tabHeight );
tabSelectionHeight = scale( tabSelectionHeight );
// replace focus forward/backward traversal keys with TAB/Shift+TAB because
// the default also includes Ctrl+TAB/Ctrl+Shift+TAB, which we need to switch tabs
if( focusForwardTraversalKeys == null ) {
focusForwardTraversalKeys = Collections.singleton( KeyStroke.getKeyStroke( KeyEvent.VK_TAB, 0 ) );
focusBackwardTraversalKeys = Collections.singleton( KeyStroke.getKeyStroke( KeyEvent.VK_TAB, InputEvent.SHIFT_MASK ) );
}
// Ideally we should use `LookAndFeel.installProperty( tabPane, "focusTraversalKeysForward", keys )` here
// instead of `tabPane.setFocusTraversalKeys()`, but WindowsTabbedPaneUI also uses later method
// and switching from Windows LaF to FlatLaf would not replace the keys and Ctrl+TAB would not work.
tabPane.setFocusTraversalKeys( KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, focusForwardTraversalKeys );
tabPane.setFocusTraversalKeys( KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, focusBackwardTraversalKeys );
MigLayoutVisualPadding.install( tabPane, null );
}
@Override
protected void uninstallDefaults() {
// restore focus forward/backward traversal keys
tabPane.setFocusTraversalKeys( KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, null );
tabPane.setFocusTraversalKeys( KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS, null );
super.uninstallDefaults();
disabledForeground = null;

View File

@@ -81,7 +81,11 @@ public class FlatContainerTest
JSplitPane splitPane3 = new JSplitPane();
JSplitPane splitPane1 = new JSplitPane();
JPanel panel10 = new JPanel();
JTextField textField2 = new JTextField();
JButton button1 = new JButton();
JPanel panel11 = new JPanel();
JTextField textField3 = new JTextField();
JButton button2 = new JButton();
JSplitPane splitPane2 = new JSplitPane();
JPanel panel12 = new JPanel();
JPanel panel13 = new JPanel();
@@ -89,7 +93,11 @@ public class FlatContainerTest
tabbedPane1 = new JTabbedPane();
JPanel panel1 = new JPanel();
JLabel label1 = new JLabel();
JTextField textField4 = new JTextField();
JButton button3 = new JButton();
JPanel panel2 = new JPanel();
JTextField textField5 = new JTextField();
JButton button4 = new JButton();
JLabel label2 = new JLabel();
tabbedPane3 = new JTabbedPane();
JPanel panel5 = new JPanel();
@@ -145,6 +153,14 @@ public class FlatContainerTest
{
panel10.setBackground(Color.orange);
panel10.setLayout(new FlowLayout());
//---- textField2 ----
textField2.setText("some text");
panel10.add(textField2);
//---- button1 ----
button1.setText("...");
panel10.add(button1);
}
splitPane1.setLeftComponent(panel10);
@@ -152,6 +168,14 @@ public class FlatContainerTest
{
panel11.setBackground(Color.magenta);
panel11.setLayout(new FlowLayout());
//---- textField3 ----
textField3.setText("some text");
panel11.add(textField3);
//---- button2 ----
button2.setText("...");
panel11.add(button2);
}
splitPane1.setRightComponent(panel11);
}
@@ -195,6 +219,14 @@ public class FlatContainerTest
//---- label1 ----
label1.setText("TOP");
panel1.add(label1);
//---- textField4 ----
textField4.setText("some text");
panel1.add(textField4);
//---- button3 ----
button3.setText("...");
panel1.add(button3);
}
tabbedPane1.addTab("Tab 1", panel1);
@@ -202,6 +234,14 @@ public class FlatContainerTest
{
panel2.setBorder(new LineBorder(Color.magenta));
panel2.setLayout(new FlowLayout());
//---- textField5 ----
textField5.setText("some text");
panel2.add(textField5);
//---- button4 ----
button4.setText("...");
panel2.add(button4);
}
tabbedPane1.addTab("Tab 2", panel2);

View File

@@ -1,4 +1,4 @@
JFDML JFormDesigner: "7.0.0.0.194" Java: "11.0.2" encoding: "UTF-8"
JFDML JFormDesigner: "7.0.1.0.272" Java: "13.0.1" encoding: "UTF-8"
new FormModel {
contentType: "form/swing"
@@ -32,12 +32,28 @@ new FormModel {
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
name: "panel10"
"background": sfield java.awt.Color orange
add( new FormComponent( "javax.swing.JTextField" ) {
name: "textField2"
"text": "some text"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "button1"
"text": "..."
} )
}, new FormLayoutConstraints( class java.lang.String ) {
"value": "left"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
name: "panel11"
"background": sfield java.awt.Color magenta
add( new FormComponent( "javax.swing.JTextField" ) {
name: "textField3"
"text": "some text"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "button2"
"text": "..."
} )
}, new FormLayoutConstraints( class java.lang.String ) {
"value": "right"
} )
@@ -86,12 +102,28 @@ new FormModel {
name: "label1"
"text": "TOP"
} )
add( new FormComponent( "javax.swing.JTextField" ) {
name: "textField4"
"text": "some text"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "button3"
"text": "..."
} )
}, new FormLayoutConstraints( null ) {
"title": "Tab 1"
} )
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
name: "panel2"
"border": &LineBorder0 new javax.swing.border.LineBorder( sfield java.awt.Color magenta, 1, false )
add( new FormComponent( "javax.swing.JTextField" ) {
name: "textField5"
"text": "some text"
} )
add( new FormComponent( "javax.swing.JButton" ) {
name: "button4"
"text": "..."
} )
}, new FormLayoutConstraints( null ) {
"title": "Tab 2"
} )

View File

@@ -536,11 +536,13 @@ SplitPane.ancestorInputMap [lazy] 14 javax.swing.plaf.InputMapUIResource
#---- TabbedPane ----
TabbedPane.ancestorInputMap [lazy] 4 javax.swing.plaf.InputMapUIResource [UI]
TabbedPane.ancestorInputMap [lazy] 6 javax.swing.plaf.InputMapUIResource [UI]
ctrl KP_UP requestFocus
ctrl PAGE_DOWN navigatePageDown
ctrl PAGE_UP navigatePageUp
ctrl TAB navigateNext
ctrl UP requestFocus
shift ctrl TAB navigatePrevious
TabbedPane.focusInputMap [lazy] 10 javax.swing.plaf.InputMapUIResource [UI]
ctrl DOWN requestFocusForVisibleComponent
ctrl KP_DOWN requestFocusForVisibleComponent

View File

@@ -475,11 +475,13 @@ SplitPane.ancestorInputMap [lazy] 14 javax.swing.plaf.InputMapUIResource
#---- TabbedPane ----
TabbedPane.ancestorInputMap [lazy] 4 javax.swing.plaf.InputMapUIResource [UI]
TabbedPane.ancestorInputMap [lazy] 6 javax.swing.plaf.InputMapUIResource [UI]
ctrl KP_UP requestFocus
ctrl PAGE_DOWN navigatePageDown
ctrl PAGE_UP navigatePageUp
ctrl TAB navigateNext
ctrl UP requestFocus
shift ctrl TAB navigatePrevious
TabbedPane.focusInputMap [lazy] 10 javax.swing.plaf.InputMapUIResource [UI]
ctrl DOWN requestFocusForVisibleComponent
ctrl KP_DOWN requestFocusForVisibleComponent