mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-12 15:07:11 -06:00
TabbedPane: completed review of PR #343 (active tab border painting style)
- replaced `activeTabBorder` with `tabType` - added `TabbedPane.cardTabSelectionHeight`
This commit is contained in:
@@ -14,8 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package com.formdev.flatlaf;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.Objects;
|
||||
import javax.swing.JComponent;
|
||||
@@ -324,6 +324,35 @@ public interface FlatClientProperties
|
||||
|
||||
//---- JTabbedPane --------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Specifies type of the selected tab.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.String}<br>
|
||||
* <strong>Allowed Values</strong>
|
||||
* {@link #TABBED_PANE_TAB_TYPE_UNDERLINED} or
|
||||
* {@link #TABBED_PANE_TAB_TYPE_CARD}
|
||||
*
|
||||
* @since 2
|
||||
*/
|
||||
String TABBED_PANE_TAB_TYPE = "JTabbedPane.tabType";
|
||||
|
||||
/**
|
||||
* Paint the selected tab underlined.
|
||||
*
|
||||
* @see #TABBED_PANE_TAB_TYPE
|
||||
* @since 2
|
||||
*/
|
||||
String TABBED_PANE_TAB_TYPE_UNDERLINED = "underlined";
|
||||
|
||||
/**
|
||||
* Paint the selected tab as card.
|
||||
*
|
||||
* @see #TABBED_PANE_TAB_TYPE
|
||||
* @since 2
|
||||
*/
|
||||
String TABBED_PANE_TAB_TYPE_CARD = "card";
|
||||
|
||||
/**
|
||||
* Specifies whether separators are shown between tabs.
|
||||
* <p>
|
||||
@@ -332,15 +361,6 @@ public interface FlatClientProperties
|
||||
*/
|
||||
String TABBED_PANE_SHOW_TAB_SEPARATORS = "JTabbedPane.showTabSeparators";
|
||||
|
||||
/**
|
||||
* Specifies whether a border is painted around the active tab.
|
||||
* This also changes position of the active tab indicator.
|
||||
* <p>
|
||||
* <strong>Component</strong> {@link javax.swing.JTabbedPane}<br>
|
||||
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||
*/
|
||||
String TABBED_PANE_ACTIVE_TAB_BORDER = "JTabbedPane.activeTabBorder";
|
||||
|
||||
/**
|
||||
* Specifies whether the separator between tabs area and content area should be shown.
|
||||
* <p>
|
||||
|
||||
@@ -97,7 +97,6 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
*
|
||||
* @clientProperty JTabbedPane.showTabSeparators boolean
|
||||
* @clientProperty JTabbedPane.hasFullBorder boolean
|
||||
* @clientProperty JTabbedPane.activeTabBorder boolean
|
||||
*
|
||||
* <!-- BasicTabbedPaneUI -->
|
||||
*
|
||||
@@ -131,6 +130,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault TabbedPane.maximumTabWidth int optional
|
||||
* @uiDefault TabbedPane.tabHeight int
|
||||
* @uiDefault TabbedPane.tabSelectionHeight int
|
||||
* @uiDefault TabbedPane.cardTabSelectionHeight int
|
||||
* @uiDefault TabbedPane.contentSeparatorHeight int
|
||||
* @uiDefault TabbedPane.showTabSeparators boolean
|
||||
* @uiDefault TabbedPane.tabSeparatorsFullHeight boolean
|
||||
@@ -138,6 +138,7 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
* @uiDefault TabbedPane.activeTabBorder boolean
|
||||
*
|
||||
* @uiDefault TabbedPane.tabLayoutPolicy String wrap (default) or scroll
|
||||
* @uiDefault TabbedPane.tabType String underlined (default) or card
|
||||
* @uiDefault TabbedPane.tabsPopupPolicy String never or asNeeded (default)
|
||||
* @uiDefault TabbedPane.scrollButtonsPolicy String never, asNeeded or asNeededSingle (default)
|
||||
* @uiDefault TabbedPane.scrollButtonsPlacement String both (default) or trailing
|
||||
@@ -161,6 +162,10 @@ import com.formdev.flatlaf.util.UIScale;
|
||||
public class FlatTabbedPaneUI
|
||||
extends BasicTabbedPaneUI
|
||||
{
|
||||
// tab type
|
||||
/** @since 2 */ protected static final int TAB_TYPE_UNDERLINED = 0;
|
||||
/** @since 2 */ protected static final int TAB_TYPE_CARD = 1;
|
||||
|
||||
// tabs popup policy / scroll arrows policy
|
||||
protected static final int NEVER = 0;
|
||||
// protected static final int ALWAYS = 1;
|
||||
@@ -196,13 +201,14 @@ public class FlatTabbedPaneUI
|
||||
protected int maximumTabWidth;
|
||||
protected int tabHeight;
|
||||
protected int tabSelectionHeight;
|
||||
/** @since 2 */ protected int cardTabSelectionHeight;
|
||||
protected int contentSeparatorHeight;
|
||||
protected boolean showTabSeparators;
|
||||
protected boolean tabSeparatorsFullHeight;
|
||||
protected boolean hasFullBorder;
|
||||
protected boolean tabsOpaque = true;
|
||||
protected boolean activeTabBorder;
|
||||
|
||||
private int tabType;
|
||||
private int tabsPopupPolicy;
|
||||
private int scrollButtonsPolicy;
|
||||
private int scrollButtonsPlacement;
|
||||
@@ -304,13 +310,14 @@ public class FlatTabbedPaneUI
|
||||
maximumTabWidth = UIManager.getInt( "TabbedPane.maximumTabWidth" );
|
||||
tabHeight = UIManager.getInt( "TabbedPane.tabHeight" );
|
||||
tabSelectionHeight = UIManager.getInt( "TabbedPane.tabSelectionHeight" );
|
||||
cardTabSelectionHeight = UIManager.getInt( "TabbedPane.cardTabSelectionHeight" );
|
||||
contentSeparatorHeight = UIManager.getInt( "TabbedPane.contentSeparatorHeight" );
|
||||
showTabSeparators = UIManager.getBoolean( "TabbedPane.showTabSeparators" );
|
||||
tabSeparatorsFullHeight = UIManager.getBoolean( "TabbedPane.tabSeparatorsFullHeight" );
|
||||
hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" );
|
||||
tabsOpaque = UIManager.getBoolean( "TabbedPane.tabsOpaque" );
|
||||
activeTabBorder = UIManager.getBoolean( "TabbedPane.activeTabBorder" );
|
||||
|
||||
tabType = parseTabType( UIManager.getString( "TabbedPane.tabType" ) );
|
||||
tabsPopupPolicy = parseTabsPopupPolicy( UIManager.getString( "TabbedPane.tabsPopupPolicy" ) );
|
||||
scrollButtonsPolicy = parseScrollButtonsPolicy( UIManager.getString( "TabbedPane.scrollButtonsPolicy" ) );
|
||||
scrollButtonsPlacement = parseScrollButtonsPlacement( UIManager.getString( "TabbedPane.scrollButtonsPlacement" ) );
|
||||
@@ -625,7 +632,7 @@ public class FlatTabbedPaneUI
|
||||
|
||||
// increase size of repaint region to include part of content border
|
||||
if( contentSeparatorHeight > 0 &&
|
||||
clientPropertyBoolean( tabPane, TABBED_PANE_ACTIVE_TAB_BORDER, activeTabBorder ) &&
|
||||
getTabType() == TAB_TYPE_CARD &&
|
||||
clientPropertyBoolean( tabPane, TABBED_PANE_SHOW_CONTENT_SEPARATOR, true ) )
|
||||
{
|
||||
int sh = scale( contentSeparatorHeight );
|
||||
@@ -980,6 +987,7 @@ public class FlatTabbedPaneUI
|
||||
g.fillRect( x, y, w, h );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected Color getTabBackground( int tabPlacement, int tabIndex, boolean isSelected ) {
|
||||
boolean enabled = tabPane.isEnabled();
|
||||
return enabled && tabPane.isEnabledAt( tabIndex ) && getRolloverTab() == tabIndex
|
||||
@@ -999,8 +1007,8 @@ public class FlatTabbedPaneUI
|
||||
if( clientPropertyBoolean( tabPane, TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators ) &&
|
||||
!isLastInRun( tabIndex ) )
|
||||
{
|
||||
if( clientPropertyBoolean( tabPane, TABBED_PANE_ACTIVE_TAB_BORDER, activeTabBorder ) ) {
|
||||
// Some separators need to be omitted when activeTabBorder is enabled
|
||||
if( getTabType() == TAB_TYPE_CARD ) {
|
||||
// some separators need to be omitted if selected tab is painted as card
|
||||
int selectedIndex = tabPane.getSelectedIndex();
|
||||
if( tabIndex != selectedIndex - 1 && tabIndex != selectedIndex )
|
||||
paintTabSeparator( g, tabPlacement, x, y, w, h );
|
||||
@@ -1009,11 +1017,12 @@ public class FlatTabbedPaneUI
|
||||
}
|
||||
|
||||
// paint active tab border
|
||||
if( isSelected && clientPropertyBoolean( tabPane, TABBED_PANE_ACTIVE_TAB_BORDER, activeTabBorder ) )
|
||||
paintSelectedTabBorder( g, tabPlacement, tabIndex, x, y, w, h );
|
||||
if( isSelected && getTabType() == TAB_TYPE_CARD )
|
||||
paintCardTabBorder( g, tabPlacement, tabIndex, x, y, w, h );
|
||||
}
|
||||
|
||||
protected void paintSelectedTabBorder( Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h ) {
|
||||
/** @since 2 */
|
||||
protected void paintCardTabBorder( Graphics g, int tabPlacement, int tabIndex, int x, int y, int w, int h ) {
|
||||
Graphics2D g2 = (Graphics2D) g;
|
||||
|
||||
float borderWidth = scale( (float) contentSeparatorHeight );
|
||||
@@ -1035,8 +1044,8 @@ public class FlatTabbedPaneUI
|
||||
break;
|
||||
}
|
||||
|
||||
if( tabSelectionHeight <= 0 ) {
|
||||
//If there is no tab selection indicator, paint a top border as well
|
||||
if( cardTabSelectionHeight <= 0 ) {
|
||||
// if there is no tab selection indicator, paint a top border as well
|
||||
switch( tabPlacement ) {
|
||||
default:
|
||||
case TOP:
|
||||
@@ -1098,9 +1107,9 @@ public class FlatTabbedPaneUI
|
||||
g.setColor( tabPane.isEnabled() ? underlineColor : disabledUnderlineColor );
|
||||
|
||||
// paint underline selection
|
||||
boolean atBottom = !clientPropertyBoolean( tabPane, TABBED_PANE_ACTIVE_TAB_BORDER, activeTabBorder );
|
||||
boolean atBottom = (getTabType() != TAB_TYPE_CARD);
|
||||
Insets contentInsets = getContentBorderInsets( tabPlacement );
|
||||
int tabSelectionHeight = scale( this.tabSelectionHeight );
|
||||
int tabSelectionHeight = scale( atBottom ? this.tabSelectionHeight : cardTabSelectionHeight );
|
||||
int sx, sy;
|
||||
switch( tabPlacement ) {
|
||||
case TOP:
|
||||
@@ -1189,7 +1198,7 @@ public class FlatTabbedPaneUI
|
||||
w - (ci.left / 100f) - (ci.right / 100f), h - (ci.top / 100f) - (ci.bottom / 100f) ), false );
|
||||
|
||||
// add gap for selected tab to path
|
||||
if( clientPropertyBoolean( tabPane, TABBED_PANE_ACTIVE_TAB_BORDER, activeTabBorder ) ) {
|
||||
if( getTabType() == TAB_TYPE_CARD ) {
|
||||
float csh = scale( (float) contentSeparatorHeight );
|
||||
|
||||
Rectangle tabRect = getTabBounds( tabPane, selectedIndex );
|
||||
@@ -1426,6 +1435,15 @@ public class FlatTabbedPaneUI
|
||||
clientPropertyBoolean( tabPane, TABBED_PANE_HIDE_TAB_AREA_WITH_ONE_TAB, false );
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected int getTabType() {
|
||||
Object value = tabPane.getClientProperty( TABBED_PANE_TAB_TYPE );
|
||||
|
||||
return (value instanceof String)
|
||||
? parseTabType( (String) value )
|
||||
: tabType;
|
||||
}
|
||||
|
||||
protected int getTabsPopupPolicy() {
|
||||
Object value = tabPane.getClientProperty( TABBED_PANE_TABS_POPUP_POLICY );
|
||||
|
||||
@@ -1478,6 +1496,18 @@ public class FlatTabbedPaneUI
|
||||
: tabWidthMode;
|
||||
}
|
||||
|
||||
/** @since 2 */
|
||||
protected static int parseTabType( String str ) {
|
||||
if( str == null )
|
||||
return TAB_TYPE_UNDERLINED;
|
||||
|
||||
switch( str ) {
|
||||
default:
|
||||
case TABBED_PANE_TAB_TYPE_UNDERLINED: return TAB_TYPE_UNDERLINED;
|
||||
case TABBED_PANE_TAB_TYPE_CARD: return TAB_TYPE_CARD;
|
||||
}
|
||||
}
|
||||
|
||||
protected static int parseTabsPopupPolicy( String str ) {
|
||||
if( str == null )
|
||||
return AS_NEEDED;
|
||||
@@ -2445,7 +2475,7 @@ public class FlatTabbedPaneUI
|
||||
break;
|
||||
|
||||
case TABBED_PANE_SHOW_TAB_SEPARATORS:
|
||||
case TABBED_PANE_ACTIVE_TAB_BORDER:
|
||||
case TABBED_PANE_TAB_TYPE:
|
||||
tabPane.repaint();
|
||||
break;
|
||||
|
||||
|
||||
@@ -569,9 +569,9 @@ SplitPaneDivider.gripGap = 2
|
||||
|
||||
TabbedPane.tabHeight = 32
|
||||
TabbedPane.tabSelectionHeight = 3
|
||||
TabbedPane.cardTabSelectionHeight = 2
|
||||
TabbedPane.contentSeparatorHeight = 1
|
||||
TabbedPane.showTabSeparators = false
|
||||
TabbedPane.activeTabBorder = false
|
||||
TabbedPane.tabSeparatorsFullHeight = false
|
||||
TabbedPane.hasFullBorder = false
|
||||
TabbedPane.tabInsets = 4,12,4,12
|
||||
@@ -591,6 +591,9 @@ TabbedPane.tabAlignment = center
|
||||
# allowed values: preferred, equal or compact
|
||||
TabbedPane.tabWidthMode = preferred
|
||||
|
||||
# allowed values: underlined or card
|
||||
TabbedPane.tabType = underlined
|
||||
|
||||
# allowed values: chevron or triangle
|
||||
TabbedPane.arrowType = chevron
|
||||
TabbedPane.buttonInsets = 2,1,2,1
|
||||
|
||||
Reference in New Issue
Block a user