TabbedPane: more fallbacks to find tab name for "more tabs" popup in case that tab title is not set (issue #207; PR #190)

This commit is contained in:
Karl Tauber
2020-11-13 11:48:03 +01:00
parent 8594e78287
commit cbc1fe27ef
2 changed files with 62 additions and 18 deletions

View File

@@ -56,6 +56,8 @@ import java.util.Locale;
import java.util.Set; import java.util.Set;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import java.util.function.IntConsumer; import java.util.function.IntConsumer;
import javax.accessibility.Accessible;
import javax.accessibility.AccessibleContext;
import javax.swing.ButtonModel; import javax.swing.ButtonModel;
import javax.swing.Icon; import javax.swing.Icon;
import javax.swing.JButton; import javax.swing.JButton;
@@ -83,6 +85,7 @@ import com.formdev.flatlaf.FlatLaf;
import com.formdev.flatlaf.util.Animator; import com.formdev.flatlaf.util.Animator;
import com.formdev.flatlaf.util.CubicBezierEasing; import com.formdev.flatlaf.util.CubicBezierEasing;
import com.formdev.flatlaf.util.JavaCompatibility; import com.formdev.flatlaf.util.JavaCompatibility;
import com.formdev.flatlaf.util.StringUtils;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
/** /**
@@ -1527,7 +1530,7 @@ public class FlatTabbedPaneUI
lastIndex = i; lastIndex = i;
// create menu item for tab // create menu item for tab
popupMenu.add( createMenuItem( i ) ); popupMenu.add( createTabMenuItem( i ) );
} }
} }
@@ -1550,29 +1553,44 @@ public class FlatTabbedPaneUI
popupMenu.show( this, x, y ); popupMenu.show( this, x, y );
} }
protected JMenuItem createMenuItem( int index ) { protected JMenuItem createTabMenuItem( int tabIndex ) {
String title = tabPane.getTitleAt( index ); // search for tab name in this places
if( title == null || title.isEmpty() ) // 1. tab title
title = findTabTitle( tabPane.getTabComponentAt( index ) ); // 2. text of label or text component in custom tab component (including children)
// 3. accessible name of tab
// 4. accessible name of custom tab component (including children)
// 5. string "n. Tab"
String title = tabPane.getTitleAt( tabIndex );
if( StringUtils.isEmpty( title ) ) {
Component tabComp = tabPane.getTabComponentAt( tabIndex );
if( tabComp != null )
title = findTabTitle( tabComp );
if( StringUtils.isEmpty( title ) )
title = tabPane.getAccessibleContext().getAccessibleChild( tabIndex ).getAccessibleContext().getAccessibleName();
if( StringUtils.isEmpty( title ) && tabComp instanceof Accessible )
title = findTabTitleInAccessible( (Accessible) tabComp );
if( StringUtils.isEmpty( title ) )
title = (tabIndex + 1) + ". Tab";
}
JMenuItem menuItem = new JMenuItem( title, tabPane.getIconAt( index ) ); JMenuItem menuItem = new JMenuItem( title, tabPane.getIconAt( tabIndex ) );
menuItem.setDisabledIcon( tabPane.getDisabledIconAt( index ) ); menuItem.setDisabledIcon( tabPane.getDisabledIconAt( tabIndex ) );
menuItem.setToolTipText( tabPane.getToolTipTextAt( index ) ); menuItem.setToolTipText( tabPane.getToolTipTextAt( tabIndex ) );
Color foregroundAt = tabPane.getForegroundAt( index ); Color foregroundAt = tabPane.getForegroundAt( tabIndex );
if( foregroundAt != tabPane.getForeground() ) if( foregroundAt != tabPane.getForeground() )
menuItem.setForeground( foregroundAt ); menuItem.setForeground( foregroundAt );
Color backgroundAt = tabPane.getBackgroundAt( index ); Color backgroundAt = tabPane.getBackgroundAt( tabIndex );
if( backgroundAt != tabPane.getBackground() ) { if( backgroundAt != tabPane.getBackground() ) {
menuItem.setBackground( backgroundAt ); menuItem.setBackground( backgroundAt );
menuItem.setOpaque( true ); menuItem.setOpaque( true );
} }
if( !tabPane.isEnabledAt( index ) ) if( !tabPane.isEnabledAt( tabIndex ) )
menuItem.setEnabled( false ); menuItem.setEnabled( false );
menuItem.addActionListener( e -> selectTab( index ) ); menuItem.addActionListener( e -> selectTab( tabIndex ) );
return menuItem; return menuItem;
} }
@@ -1580,16 +1598,13 @@ public class FlatTabbedPaneUI
* Search for label or text component in custom tab component and return its text. * Search for label or text component in custom tab component and return its text.
*/ */
private String findTabTitle( Component c ) { private String findTabTitle( Component c ) {
if( c == null )
return null;
String title = null; String title = null;
if( c instanceof JLabel ) if( c instanceof JLabel )
title = ((JLabel)c).getText(); title = ((JLabel)c).getText();
else if( c instanceof JTextComponent ) else if( c instanceof JTextComponent )
title = ((JTextComponent)c).getText(); title = ((JTextComponent)c).getText();
if( title != null && !title.isEmpty() ) if( !StringUtils.isEmpty( title ) )
return title; return title;
if( c instanceof Container ) { if( c instanceof Container ) {
@@ -1603,8 +1618,30 @@ public class FlatTabbedPaneUI
return null; return null;
} }
protected void selectTab( int index ) { /**
tabPane.setSelectedIndex( index ); * Search for accessible name.
*/
private String findTabTitleInAccessible( Accessible accessible ) {
AccessibleContext context = accessible.getAccessibleContext();
if( context == null )
return null;
String title = context.getAccessibleName();
if( !StringUtils.isEmpty( title ) )
return title;
int childrenCount = context.getAccessibleChildrenCount();
for( int i = 0; i < childrenCount; i++ ) {
title = findTabTitleInAccessible( context.getAccessibleChild( i ) );
if( title != null )
return title;
}
return null;
}
protected void selectTab( int tabIndex ) {
tabPane.setSelectedIndex( tabIndex );
ensureSelectedTabIsVisible(); ensureSelectedTabIsVisible();
} }

View File

@@ -26,6 +26,13 @@ import java.util.List;
*/ */
public class StringUtils public class StringUtils
{ {
/**
* Returns {@code true} if given string is {@code null} or length is zero.
*/
public static boolean isEmpty( String string ) {
return string == null || string.isEmpty();
}
public static String removeLeading( String string, String leading ) { public static String removeLeading( String string, String leading ) {
return string.startsWith( leading ) return string.startsWith( leading )
? string.substring( leading.length() ) ? string.substring( leading.length() )