mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-07 22:40:53 +03:00
TabbedPane: selected tab underline color now changes depending on whether the focus is within the tab content (issue #398)
This commit is contained in:
@@ -5,6 +5,8 @@ FlatLaf Change Log
|
||||
|
||||
#### New features and improvements
|
||||
|
||||
- TabbedPane: Selected tab underline color now changes depending on whether the
|
||||
focus is within the tab content. (issue #398)
|
||||
- IntelliJ Themes: TabbedPane now use different background color for selected
|
||||
tabs in all "Arc" themes, in "Hiberbee Dark" and in all "Material UI Lite"
|
||||
themes.
|
||||
|
||||
@@ -618,6 +618,7 @@ public class IntelliJTheme
|
||||
// TabbedPane
|
||||
uiKeyCopying.put( "TabbedPane.selectedBackground", "DefaultTabs.underlinedTabBackground" );
|
||||
uiKeyCopying.put( "TabbedPane.selectedForeground", "DefaultTabs.underlinedTabForeground" );
|
||||
uiKeyCopying.put( "TabbedPane.inactiveUnderlineColor", "DefaultTabs.inactiveUnderlineColor" );
|
||||
|
||||
// TitlePane
|
||||
uiKeyCopying.put( "TitlePane.inactiveBackground", "TitlePane.background" );
|
||||
|
||||
@@ -59,6 +59,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.function.Predicate;
|
||||
import javax.accessibility.Accessible;
|
||||
import javax.accessibility.AccessibleContext;
|
||||
import javax.swing.Action;
|
||||
@@ -82,10 +83,12 @@ import javax.swing.event.ChangeListener;
|
||||
import javax.swing.event.PopupMenuEvent;
|
||||
import javax.swing.event.PopupMenuListener;
|
||||
import javax.swing.plaf.ComponentUI;
|
||||
import javax.swing.plaf.TabbedPaneUI;
|
||||
import javax.swing.plaf.UIResource;
|
||||
import javax.swing.plaf.basic.BasicTabbedPaneUI;
|
||||
import javax.swing.text.JTextComponent;
|
||||
import javax.swing.text.View;
|
||||
import com.formdev.flatlaf.FlatClientProperties;
|
||||
import com.formdev.flatlaf.FlatLaf;
|
||||
import com.formdev.flatlaf.icons.FlatTabbedPaneCloseIcon;
|
||||
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
|
||||
@@ -127,6 +130,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault TabbedPane.selectedBackground Color optional
|
||||
* @uiDefault TabbedPane.selectedForeground Color
|
||||
* @uiDefault TabbedPane.underlineColor Color
|
||||
* @uiDefault TabbedPane.inactiveUnderlineColor Color
|
||||
* @uiDefault TabbedPane.disabledUnderlineColor Color
|
||||
* @uiDefault TabbedPane.hoverColor Color
|
||||
* @uiDefault TabbedPane.focusColor Color
|
||||
@@ -198,6 +202,7 @@ public class FlatTabbedPaneUI
|
||||
@Styleable protected Color selectedBackground;
|
||||
@Styleable protected Color selectedForeground;
|
||||
@Styleable protected Color underlineColor;
|
||||
/** @since 2.2 */ @Styleable protected Color inactiveUnderlineColor;
|
||||
@Styleable protected Color disabledUnderlineColor;
|
||||
@Styleable protected Color hoverColor;
|
||||
@Styleable protected Color focusColor;
|
||||
@@ -288,6 +293,7 @@ public class FlatTabbedPaneUI
|
||||
|
||||
super.installUI( c );
|
||||
|
||||
FlatSelectedTabRepainter.install();
|
||||
installStyle();
|
||||
}
|
||||
|
||||
@@ -318,6 +324,7 @@ public class FlatTabbedPaneUI
|
||||
selectedBackground = UIManager.getColor( "TabbedPane.selectedBackground" );
|
||||
selectedForeground = UIManager.getColor( "TabbedPane.selectedForeground" );
|
||||
underlineColor = UIManager.getColor( "TabbedPane.underlineColor" );
|
||||
inactiveUnderlineColor = FlatUIUtils.getUIColor( "TabbedPane.inactiveUnderlineColor", underlineColor );
|
||||
disabledUnderlineColor = UIManager.getColor( "TabbedPane.disabledUnderlineColor" );
|
||||
hoverColor = UIManager.getColor( "TabbedPane.hoverColor" );
|
||||
focusColor = UIManager.getColor( "TabbedPane.focusColor" );
|
||||
@@ -385,6 +392,7 @@ public class FlatTabbedPaneUI
|
||||
selectedBackground = null;
|
||||
selectedForeground = null;
|
||||
underlineColor = null;
|
||||
inactiveUnderlineColor = null;
|
||||
disabledUnderlineColor = null;
|
||||
hoverColor = null;
|
||||
focusColor = null;
|
||||
@@ -733,7 +741,6 @@ public class FlatTabbedPaneUI
|
||||
|
||||
// increase size of repaint region to include part of content border
|
||||
if( contentSeparatorHeight > 0 &&
|
||||
getTabType() == TAB_TYPE_CARD &&
|
||||
clientPropertyBoolean( tabPane, TABBED_PANE_SHOW_CONTENT_SEPARATOR, true ) )
|
||||
{
|
||||
int sh = scale( contentSeparatorHeight );
|
||||
@@ -1205,7 +1212,9 @@ public class FlatTabbedPaneUI
|
||||
}
|
||||
|
||||
protected void paintTabSelection( Graphics g, int tabPlacement, int x, int y, int w, int h ) {
|
||||
g.setColor( tabPane.isEnabled() ? underlineColor : disabledUnderlineColor );
|
||||
g.setColor( tabPane.isEnabled()
|
||||
? (isTabbedPaneOrChildFocused() ? underlineColor : inactiveUnderlineColor)
|
||||
: disabledUnderlineColor );
|
||||
|
||||
// paint underline selection
|
||||
boolean atBottom = (getTabType() != TAB_TYPE_CARD);
|
||||
@@ -1236,6 +1245,23 @@ public class FlatTabbedPaneUI
|
||||
}
|
||||
}
|
||||
|
||||
/** @since 2.2 */
|
||||
@SuppressWarnings( "unchecked" )
|
||||
protected boolean isTabbedPaneOrChildFocused() {
|
||||
KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||
|
||||
Object value = tabPane.getClientProperty( FlatClientProperties.COMPONENT_FOCUS_OWNER );
|
||||
if( value instanceof Predicate ) {
|
||||
return ((Predicate<JComponent>)value).test( tabPane ) &&
|
||||
FlatUIUtils.isInActiveWindow( tabPane, keyboardFocusManager.getActiveWindow() );
|
||||
}
|
||||
|
||||
Component focusOwner = keyboardFocusManager.getPermanentFocusOwner();
|
||||
return focusOwner != null &&
|
||||
SwingUtilities.isDescendingFrom( focusOwner, tabPane ) &&
|
||||
FlatUIUtils.isInActiveWindow( focusOwner, keyboardFocusManager.getActiveWindow() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Actually does nearly the same as super.paintContentBorder() but
|
||||
* - not using UIManager.getColor("TabbedPane.contentAreaColor") to be GUI builder friendly
|
||||
@@ -3341,4 +3367,77 @@ public class FlatTabbedPaneUI
|
||||
delegate.actionPerformed( e );
|
||||
}
|
||||
}
|
||||
|
||||
//---- class FlatSelectedTabRepainter -------------------------------------
|
||||
|
||||
private static class FlatSelectedTabRepainter
|
||||
implements PropertyChangeListener//, Runnable
|
||||
{
|
||||
private static FlatSelectedTabRepainter instance;
|
||||
|
||||
private KeyboardFocusManager keyboardFocusManager;
|
||||
|
||||
static void install() {
|
||||
synchronized( FlatSelectedTabRepainter.class ) {
|
||||
if( instance != null )
|
||||
return;
|
||||
|
||||
instance = new FlatSelectedTabRepainter();
|
||||
}
|
||||
}
|
||||
|
||||
FlatSelectedTabRepainter() {
|
||||
keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
|
||||
keyboardFocusManager.addPropertyChangeListener( this );
|
||||
}
|
||||
|
||||
private void uninstall() {
|
||||
synchronized( FlatSelectedTabRepainter.class ) {
|
||||
if( instance == null )
|
||||
return;
|
||||
|
||||
keyboardFocusManager.removePropertyChangeListener( this );
|
||||
keyboardFocusManager = null;
|
||||
instance = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyChange( PropertyChangeEvent e ) {
|
||||
// uninstall if no longer using FlatLaf
|
||||
if( !(UIManager.getLookAndFeel() instanceof FlatLaf) ) {
|
||||
uninstall();
|
||||
return;
|
||||
}
|
||||
|
||||
switch( e.getPropertyName() ) {
|
||||
case "permanentFocusOwner":
|
||||
Object oldValue = e.getOldValue();
|
||||
Object newValue = e.getNewValue();
|
||||
if( oldValue instanceof Component )
|
||||
repaintSelectedTabs( (Component) oldValue );
|
||||
if( newValue instanceof Component )
|
||||
repaintSelectedTabs( (Component) newValue );
|
||||
break;
|
||||
|
||||
case "activeWindow":
|
||||
repaintSelectedTabs( keyboardFocusManager.getPermanentFocusOwner() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void repaintSelectedTabs( Component c ) {
|
||||
if( c instanceof JTabbedPane )
|
||||
repaintSelectedTab( (JTabbedPane) c );
|
||||
|
||||
while( (c = SwingUtilities.getAncestorOfClass( JTabbedPane.class, c )) != null )
|
||||
repaintSelectedTab( (JTabbedPane) c );
|
||||
}
|
||||
|
||||
private void repaintSelectedTab( JTabbedPane tabbedPane ) {
|
||||
TabbedPaneUI ui = tabbedPane.getUI();
|
||||
if( ui instanceof FlatTabbedPaneUI )
|
||||
((FlatTabbedPaneUI) ui).repaintTab( tabbedPane.getSelectedIndex() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ public class FlatUIUtils
|
||||
isInActiveWindow( c, keyboardFocusManager.getActiveWindow() );
|
||||
}
|
||||
|
||||
private static boolean isInActiveWindow( Component c, Window activeWindow ) {
|
||||
static boolean isInActiveWindow( Component c, Window activeWindow ) {
|
||||
Window window = SwingUtilities.windowForComponent( c );
|
||||
return window == activeWindow ||
|
||||
(window != null && window.getType() == Window.Type.POPUP && window.getOwner() == activeWindow);
|
||||
|
||||
@@ -306,6 +306,7 @@ SplitPaneDivider.draggingColor = $Component.borderColor
|
||||
#---- TabbedPane ----
|
||||
|
||||
TabbedPane.underlineColor = @accentUnderlineColor
|
||||
TabbedPane.inactiveUnderlineColor = mix(@accentUnderlineColor,$TabbedPane.background,60%)
|
||||
TabbedPane.disabledUnderlineColor = lighten(@background,23%)
|
||||
TabbedPane.hoverColor = darken($TabbedPane.background,5%,derived noAutoInverse)
|
||||
TabbedPane.focusColor = mix(@selectionBackground,$TabbedPane.background,25%)
|
||||
|
||||
@@ -313,6 +313,7 @@ SplitPaneDivider.draggingColor = $Component.borderColor
|
||||
#---- TabbedPane ----
|
||||
|
||||
TabbedPane.underlineColor = @accentUnderlineColor
|
||||
TabbedPane.inactiveUnderlineColor = mix(@accentUnderlineColor,$TabbedPane.background,50%)
|
||||
TabbedPane.disabledUnderlineColor = darken(@background,28%)
|
||||
TabbedPane.hoverColor = darken($TabbedPane.background,7%,derived)
|
||||
TabbedPane.focusColor = mix(@selectionBackground,$TabbedPane.background,10%)
|
||||
|
||||
@@ -82,6 +82,13 @@ HelpButton.hoverBorderColor = null
|
||||
Slider.focusedColor = fade($Component.focusColor,40%,derived)
|
||||
|
||||
|
||||
#---- TabbedPane ----
|
||||
|
||||
# colors from JBUI.CurrentTheme.DefaultTabs.inactiveUnderlineColor()
|
||||
[light]TabbedPane.inactiveUnderlineColor = #9ca7b8
|
||||
[dark]TabbedPane.inactiveUnderlineColor = #747a80
|
||||
|
||||
|
||||
#---- ToggleButton ----
|
||||
|
||||
ToggleButton.startBackground = $ToggleButton.background
|
||||
|
||||
@@ -693,6 +693,7 @@ public class TestFlatStyleableInfo
|
||||
"selectedBackground", Color.class,
|
||||
"selectedForeground", Color.class,
|
||||
"underlineColor", Color.class,
|
||||
"inactiveUnderlineColor", Color.class,
|
||||
"disabledUnderlineColor", Color.class,
|
||||
"hoverColor", Color.class,
|
||||
"focusColor", Color.class,
|
||||
|
||||
@@ -862,6 +862,7 @@ public class TestFlatStyling
|
||||
ui.applyStyle( "selectedBackground: #fff" );
|
||||
ui.applyStyle( "selectedForeground: #fff" );
|
||||
ui.applyStyle( "underlineColor: #fff" );
|
||||
ui.applyStyle( "inactiveUnderlineColor: #fff" );
|
||||
ui.applyStyle( "disabledUnderlineColor: #fff" );
|
||||
ui.applyStyle( "hoverColor: #fff" );
|
||||
ui.applyStyle( "focusColor: #fff" );
|
||||
|
||||
@@ -1045,6 +1045,7 @@ TabbedPane.hasFullBorder false
|
||||
TabbedPane.hiddenTabsNavigation moreTabsButton
|
||||
TabbedPane.highlight #232324 HSL 240 1 14 javax.swing.plaf.ColorUIResource [UI]
|
||||
TabbedPane.hoverColor #303234 HSL 210 4 20 com.formdev.flatlaf.util.DerivedColor [UI] darken(5%)
|
||||
TabbedPane.inactiveUnderlineColor #466a92 HSL 212 35 42 javax.swing.plaf.ColorUIResource [UI]
|
||||
TabbedPane.labelShift 1
|
||||
TabbedPane.light #2f3031 HSL 210 2 19 javax.swing.plaf.ColorUIResource [UI]
|
||||
TabbedPane.scrollButtonsPlacement both
|
||||
|
||||
@@ -1050,6 +1050,7 @@ TabbedPane.hasFullBorder false
|
||||
TabbedPane.hiddenTabsNavigation moreTabsButton
|
||||
TabbedPane.highlight #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
|
||||
TabbedPane.hoverColor #e0e0e0 HSL 0 0 88 com.formdev.flatlaf.util.DerivedColor [UI] darken(7% autoInverse)
|
||||
TabbedPane.inactiveUnderlineColor #97bbdc HSL 209 50 73 javax.swing.plaf.ColorUIResource [UI]
|
||||
TabbedPane.labelShift 1
|
||||
TabbedPane.light #e1e1e1 HSL 0 0 88 javax.swing.plaf.ColorUIResource [UI]
|
||||
TabbedPane.scrollButtonsPlacement both
|
||||
|
||||
@@ -1060,6 +1060,7 @@ TabbedPane.hasFullBorder false
|
||||
TabbedPane.hiddenTabsNavigation moreTabsButton
|
||||
TabbedPane.highlight #ffffff HSL 0 0 100 javax.swing.plaf.ColorUIResource [UI]
|
||||
TabbedPane.hoverColor #eeeeee HSL 0 0 93 javax.swing.plaf.ColorUIResource [UI]
|
||||
TabbedPane.inactiveUnderlineColor #ff00ff HSL 300 100 50 javax.swing.plaf.ColorUIResource [UI]
|
||||
TabbedPane.labelShift 1
|
||||
TabbedPane.light #e3e3e3 HSL 0 0 89 javax.swing.plaf.ColorUIResource [UI]
|
||||
TabbedPane.scrollButtonsPlacement both
|
||||
|
||||
@@ -347,6 +347,7 @@ TabbedPane.disabledForeground = #777
|
||||
TabbedPane.selectedBackground = #0f0
|
||||
TabbedPane.selectedForeground = #00f
|
||||
TabbedPane.underlineColor = #ff0
|
||||
TabbedPane.inactiveUnderlineColor = #f0f
|
||||
TabbedPane.disabledUnderlineColor = #7a7a7a
|
||||
TabbedPane.hoverColor = #eee
|
||||
TabbedPane.focusColor = #ddd
|
||||
|
||||
@@ -821,6 +821,7 @@ TabbedPane.hasFullBorder
|
||||
TabbedPane.hiddenTabsNavigation
|
||||
TabbedPane.highlight
|
||||
TabbedPane.hoverColor
|
||||
TabbedPane.inactiveUnderlineColor
|
||||
TabbedPane.labelShift
|
||||
TabbedPane.light
|
||||
TabbedPane.scrollButtonsPlacement
|
||||
|
||||
Reference in New Issue
Block a user