mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-13 23:37:13 -06:00
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:
@@ -4,6 +4,8 @@ FlatLaf Change Log
|
|||||||
## Unreleased
|
## Unreleased
|
||||||
|
|
||||||
- PasswordField: Warn about enabled Caps Lock.
|
- 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
|
- TextField, FormattedTextField and PasswordField: Support round borders (see UI
|
||||||
default value `TextComponent.arc`). (issue #65)
|
default value `TextComponent.arc`). (issue #65)
|
||||||
- IntelliJ Themes: Added Gradianto themes to demo.
|
- IntelliJ Themes: Added Gradianto themes to demo.
|
||||||
|
|||||||
@@ -69,7 +69,14 @@ class FlatInputMaps
|
|||||||
"ctrl PAGE_DOWN", "negativeBlockIncrement",
|
"ctrl PAGE_DOWN", "negativeBlockIncrement",
|
||||||
"ctrl PAGE_UP", "positiveBlockIncrement"
|
"ctrl PAGE_UP", "positiveBlockIncrement"
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
modifyInputMap( defaults, "TabbedPane.ancestorInputMap",
|
||||||
|
"ctrl TAB", "navigateNext",
|
||||||
|
"shift ctrl TAB", "navigatePrevious"
|
||||||
|
);
|
||||||
|
|
||||||
|
if( !SystemInfo.IS_MAC ) {
|
||||||
modifyInputMap( defaults, "Tree.focusInputMap",
|
modifyInputMap( defaults, "Tree.focusInputMap",
|
||||||
"ADD", "expand",
|
"ADD", "expand",
|
||||||
"SUBTRACT", "collapse"
|
"SUBTRACT", "collapse"
|
||||||
|
|||||||
@@ -26,15 +26,21 @@ import java.awt.FontMetrics;
|
|||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Insets;
|
import java.awt.Insets;
|
||||||
|
import java.awt.KeyboardFocusManager;
|
||||||
import java.awt.Rectangle;
|
import java.awt.Rectangle;
|
||||||
import java.awt.Shape;
|
import java.awt.Shape;
|
||||||
|
import java.awt.event.InputEvent;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
import java.beans.PropertyChangeEvent;
|
import java.beans.PropertyChangeEvent;
|
||||||
import java.beans.PropertyChangeListener;
|
import java.beans.PropertyChangeListener;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JTabbedPane;
|
import javax.swing.JTabbedPane;
|
||||||
|
import javax.swing.KeyStroke;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.plaf.ComponentUI;
|
import javax.swing.plaf.ComponentUI;
|
||||||
import javax.swing.plaf.UIResource;
|
import javax.swing.plaf.UIResource;
|
||||||
@@ -90,6 +96,9 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
public class FlatTabbedPaneUI
|
public class FlatTabbedPaneUI
|
||||||
extends BasicTabbedPaneUI
|
extends BasicTabbedPaneUI
|
||||||
{
|
{
|
||||||
|
private static Set<KeyStroke> focusForwardTraversalKeys;
|
||||||
|
private static Set<KeyStroke> focusBackwardTraversalKeys;
|
||||||
|
|
||||||
protected Color disabledForeground;
|
protected Color disabledForeground;
|
||||||
protected Color selectedBackground;
|
protected Color selectedBackground;
|
||||||
protected Color selectedForeground;
|
protected Color selectedForeground;
|
||||||
@@ -142,11 +151,27 @@ public class FlatTabbedPaneUI
|
|||||||
tabHeight = scale( tabHeight );
|
tabHeight = scale( tabHeight );
|
||||||
tabSelectionHeight = scale( tabSelectionHeight );
|
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 );
|
MigLayoutVisualPadding.install( tabPane, null );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void uninstallDefaults() {
|
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();
|
super.uninstallDefaults();
|
||||||
|
|
||||||
disabledForeground = null;
|
disabledForeground = null;
|
||||||
|
|||||||
@@ -81,7 +81,11 @@ public class FlatContainerTest
|
|||||||
JSplitPane splitPane3 = new JSplitPane();
|
JSplitPane splitPane3 = new JSplitPane();
|
||||||
JSplitPane splitPane1 = new JSplitPane();
|
JSplitPane splitPane1 = new JSplitPane();
|
||||||
JPanel panel10 = new JPanel();
|
JPanel panel10 = new JPanel();
|
||||||
|
JTextField textField2 = new JTextField();
|
||||||
|
JButton button1 = new JButton();
|
||||||
JPanel panel11 = new JPanel();
|
JPanel panel11 = new JPanel();
|
||||||
|
JTextField textField3 = new JTextField();
|
||||||
|
JButton button2 = new JButton();
|
||||||
JSplitPane splitPane2 = new JSplitPane();
|
JSplitPane splitPane2 = new JSplitPane();
|
||||||
JPanel panel12 = new JPanel();
|
JPanel panel12 = new JPanel();
|
||||||
JPanel panel13 = new JPanel();
|
JPanel panel13 = new JPanel();
|
||||||
@@ -89,7 +93,11 @@ public class FlatContainerTest
|
|||||||
tabbedPane1 = new JTabbedPane();
|
tabbedPane1 = new JTabbedPane();
|
||||||
JPanel panel1 = new JPanel();
|
JPanel panel1 = new JPanel();
|
||||||
JLabel label1 = new JLabel();
|
JLabel label1 = new JLabel();
|
||||||
|
JTextField textField4 = new JTextField();
|
||||||
|
JButton button3 = new JButton();
|
||||||
JPanel panel2 = new JPanel();
|
JPanel panel2 = new JPanel();
|
||||||
|
JTextField textField5 = new JTextField();
|
||||||
|
JButton button4 = new JButton();
|
||||||
JLabel label2 = new JLabel();
|
JLabel label2 = new JLabel();
|
||||||
tabbedPane3 = new JTabbedPane();
|
tabbedPane3 = new JTabbedPane();
|
||||||
JPanel panel5 = new JPanel();
|
JPanel panel5 = new JPanel();
|
||||||
@@ -145,6 +153,14 @@ public class FlatContainerTest
|
|||||||
{
|
{
|
||||||
panel10.setBackground(Color.orange);
|
panel10.setBackground(Color.orange);
|
||||||
panel10.setLayout(new FlowLayout());
|
panel10.setLayout(new FlowLayout());
|
||||||
|
|
||||||
|
//---- textField2 ----
|
||||||
|
textField2.setText("some text");
|
||||||
|
panel10.add(textField2);
|
||||||
|
|
||||||
|
//---- button1 ----
|
||||||
|
button1.setText("...");
|
||||||
|
panel10.add(button1);
|
||||||
}
|
}
|
||||||
splitPane1.setLeftComponent(panel10);
|
splitPane1.setLeftComponent(panel10);
|
||||||
|
|
||||||
@@ -152,6 +168,14 @@ public class FlatContainerTest
|
|||||||
{
|
{
|
||||||
panel11.setBackground(Color.magenta);
|
panel11.setBackground(Color.magenta);
|
||||||
panel11.setLayout(new FlowLayout());
|
panel11.setLayout(new FlowLayout());
|
||||||
|
|
||||||
|
//---- textField3 ----
|
||||||
|
textField3.setText("some text");
|
||||||
|
panel11.add(textField3);
|
||||||
|
|
||||||
|
//---- button2 ----
|
||||||
|
button2.setText("...");
|
||||||
|
panel11.add(button2);
|
||||||
}
|
}
|
||||||
splitPane1.setRightComponent(panel11);
|
splitPane1.setRightComponent(panel11);
|
||||||
}
|
}
|
||||||
@@ -195,6 +219,14 @@ public class FlatContainerTest
|
|||||||
//---- label1 ----
|
//---- label1 ----
|
||||||
label1.setText("TOP");
|
label1.setText("TOP");
|
||||||
panel1.add(label1);
|
panel1.add(label1);
|
||||||
|
|
||||||
|
//---- textField4 ----
|
||||||
|
textField4.setText("some text");
|
||||||
|
panel1.add(textField4);
|
||||||
|
|
||||||
|
//---- button3 ----
|
||||||
|
button3.setText("...");
|
||||||
|
panel1.add(button3);
|
||||||
}
|
}
|
||||||
tabbedPane1.addTab("Tab 1", panel1);
|
tabbedPane1.addTab("Tab 1", panel1);
|
||||||
|
|
||||||
@@ -202,6 +234,14 @@ public class FlatContainerTest
|
|||||||
{
|
{
|
||||||
panel2.setBorder(new LineBorder(Color.magenta));
|
panel2.setBorder(new LineBorder(Color.magenta));
|
||||||
panel2.setLayout(new FlowLayout());
|
panel2.setLayout(new FlowLayout());
|
||||||
|
|
||||||
|
//---- textField5 ----
|
||||||
|
textField5.setText("some text");
|
||||||
|
panel2.add(textField5);
|
||||||
|
|
||||||
|
//---- button4 ----
|
||||||
|
button4.setText("...");
|
||||||
|
panel2.add(button4);
|
||||||
}
|
}
|
||||||
tabbedPane1.addTab("Tab 2", panel2);
|
tabbedPane1.addTab("Tab 2", panel2);
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
new FormModel {
|
||||||
contentType: "form/swing"
|
contentType: "form/swing"
|
||||||
@@ -32,12 +32,28 @@ new FormModel {
|
|||||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
|
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
|
||||||
name: "panel10"
|
name: "panel10"
|
||||||
"background": sfield java.awt.Color orange
|
"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 ) {
|
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||||
"value": "left"
|
"value": "left"
|
||||||
} )
|
} )
|
||||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
|
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
|
||||||
name: "panel11"
|
name: "panel11"
|
||||||
"background": sfield java.awt.Color magenta
|
"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 ) {
|
}, new FormLayoutConstraints( class java.lang.String ) {
|
||||||
"value": "right"
|
"value": "right"
|
||||||
} )
|
} )
|
||||||
@@ -86,12 +102,28 @@ new FormModel {
|
|||||||
name: "label1"
|
name: "label1"
|
||||||
"text": "TOP"
|
"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 ) {
|
}, new FormLayoutConstraints( null ) {
|
||||||
"title": "Tab 1"
|
"title": "Tab 1"
|
||||||
} )
|
} )
|
||||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
|
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class java.awt.FlowLayout ) ) {
|
||||||
name: "panel2"
|
name: "panel2"
|
||||||
"border": &LineBorder0 new javax.swing.border.LineBorder( sfield java.awt.Color magenta, 1, false )
|
"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 ) {
|
}, new FormLayoutConstraints( null ) {
|
||||||
"title": "Tab 2"
|
"title": "Tab 2"
|
||||||
} )
|
} )
|
||||||
|
|||||||
@@ -536,11 +536,13 @@ SplitPane.ancestorInputMap [lazy] 14 javax.swing.plaf.InputMapUIResource
|
|||||||
|
|
||||||
#---- TabbedPane ----
|
#---- TabbedPane ----
|
||||||
|
|
||||||
TabbedPane.ancestorInputMap [lazy] 4 javax.swing.plaf.InputMapUIResource [UI]
|
TabbedPane.ancestorInputMap [lazy] 6 javax.swing.plaf.InputMapUIResource [UI]
|
||||||
ctrl KP_UP requestFocus
|
ctrl KP_UP requestFocus
|
||||||
ctrl PAGE_DOWN navigatePageDown
|
ctrl PAGE_DOWN navigatePageDown
|
||||||
ctrl PAGE_UP navigatePageUp
|
ctrl PAGE_UP navigatePageUp
|
||||||
|
ctrl TAB navigateNext
|
||||||
ctrl UP requestFocus
|
ctrl UP requestFocus
|
||||||
|
shift ctrl TAB navigatePrevious
|
||||||
TabbedPane.focusInputMap [lazy] 10 javax.swing.plaf.InputMapUIResource [UI]
|
TabbedPane.focusInputMap [lazy] 10 javax.swing.plaf.InputMapUIResource [UI]
|
||||||
ctrl DOWN requestFocusForVisibleComponent
|
ctrl DOWN requestFocusForVisibleComponent
|
||||||
ctrl KP_DOWN requestFocusForVisibleComponent
|
ctrl KP_DOWN requestFocusForVisibleComponent
|
||||||
|
|||||||
@@ -475,11 +475,13 @@ SplitPane.ancestorInputMap [lazy] 14 javax.swing.plaf.InputMapUIResource
|
|||||||
|
|
||||||
#---- TabbedPane ----
|
#---- TabbedPane ----
|
||||||
|
|
||||||
TabbedPane.ancestorInputMap [lazy] 4 javax.swing.plaf.InputMapUIResource [UI]
|
TabbedPane.ancestorInputMap [lazy] 6 javax.swing.plaf.InputMapUIResource [UI]
|
||||||
ctrl KP_UP requestFocus
|
ctrl KP_UP requestFocus
|
||||||
ctrl PAGE_DOWN navigatePageDown
|
ctrl PAGE_DOWN navigatePageDown
|
||||||
ctrl PAGE_UP navigatePageUp
|
ctrl PAGE_UP navigatePageUp
|
||||||
|
ctrl TAB navigateNext
|
||||||
ctrl UP requestFocus
|
ctrl UP requestFocus
|
||||||
|
shift ctrl TAB navigatePrevious
|
||||||
TabbedPane.focusInputMap [lazy] 10 javax.swing.plaf.InputMapUIResource [UI]
|
TabbedPane.focusInputMap [lazy] 10 javax.swing.plaf.InputMapUIResource [UI]
|
||||||
ctrl DOWN requestFocusForVisibleComponent
|
ctrl DOWN requestFocusForVisibleComponent
|
||||||
ctrl KP_DOWN requestFocusForVisibleComponent
|
ctrl KP_DOWN requestFocusForVisibleComponent
|
||||||
|
|||||||
Reference in New Issue
Block a user