mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2026-02-12 06:57:13 -06:00
@@ -16,6 +16,7 @@ FlatLaf Change Log
|
|||||||
- TabbedPane: Support adding custom components to left and right sides of tabs
|
- TabbedPane: Support adding custom components to left and right sides of tabs
|
||||||
area. (set client property `JTabbedPane.leadingComponent` or
|
area. (set client property `JTabbedPane.leadingComponent` or
|
||||||
`JTabbedPane.trailingComponent` to a `java.awt.Component`) (issue #40)
|
`JTabbedPane.trailingComponent` to a `java.awt.Component`) (issue #40)
|
||||||
|
- TabbedPane: Support closable tabs. (issues #31 and #40)
|
||||||
- Support painting separator line between window title and content (use UI value
|
- Support painting separator line between window title and content (use UI value
|
||||||
`TitlePane.borderColor`). (issue #184)
|
`TitlePane.borderColor`). (issue #184)
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ import javax.swing.JComponent;
|
|||||||
*/
|
*/
|
||||||
public interface FlatClientProperties
|
public interface FlatClientProperties
|
||||||
{
|
{
|
||||||
|
//---- JButton ------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies type of a button.
|
* Specifies type of a button.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -104,6 +106,8 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String SQUARE_SIZE = "JButton.squareSize";
|
String SQUARE_SIZE = "JButton.squareSize";
|
||||||
|
|
||||||
|
//---- JComponent ---------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies minimum width of a component.
|
* Specifies minimum width of a component.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -158,6 +162,8 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String COMPONENT_ROUND_RECT = "JComponent.roundRect";
|
String COMPONENT_ROUND_RECT = "JComponent.roundRect";
|
||||||
|
|
||||||
|
//---- Popup --------------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether a drop shadow is painted if the component is shown in a popup
|
* Specifies whether a drop shadow is painted if the component is shown in a popup
|
||||||
* or if the component is the owner of another component that is shown in a popup.
|
* or if the component is the owner of another component that is shown in a popup.
|
||||||
@@ -167,6 +173,8 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String POPUP_DROP_SHADOW_PAINTED = "Popup.dropShadowPainted";
|
String POPUP_DROP_SHADOW_PAINTED = "Popup.dropShadowPainted";
|
||||||
|
|
||||||
|
//---- JProgressBar -------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether the progress bar has always the larger height even if no string is painted.
|
* Specifies whether the progress bar has always the larger height even if no string is painted.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -183,6 +191,8 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String PROGRESS_BAR_SQUARE = "JProgressBar.square";
|
String PROGRESS_BAR_SQUARE = "JProgressBar.square";
|
||||||
|
|
||||||
|
//---- JRootPane ----------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether the menu bar is embedded into the title pane if custom
|
* Specifies whether the menu bar is embedded into the title pane if custom
|
||||||
* window decorations are enabled. Default is {@code true}.
|
* window decorations are enabled. Default is {@code true}.
|
||||||
@@ -192,6 +202,8 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String MENU_BAR_EMBEDDED = "JRootPane.menuBarEmbedded";
|
String MENU_BAR_EMBEDDED = "JRootPane.menuBarEmbedded";
|
||||||
|
|
||||||
|
//---- JScrollBar ---------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether the decrease/increase arrow buttons of a scrollbar are shown.
|
* Specifies whether the decrease/increase arrow buttons of a scrollbar are shown.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -208,6 +220,8 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String SCROLL_PANE_SMOOTH_SCROLLING = "JScrollPane.smoothScrolling";
|
String SCROLL_PANE_SMOOTH_SCROLLING = "JScrollPane.smoothScrolling";
|
||||||
|
|
||||||
|
//---- JTabbedPane --------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether separators are shown between tabs.
|
* Specifies whether separators are shown between tabs.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -240,6 +254,78 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TABBED_PANE_TAB_HEIGHT = "JTabbedPane.tabHeight";
|
String TABBED_PANE_TAB_HEIGHT = "JTabbedPane.tabHeight";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the insets of a tab.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTabbedPane}
|
||||||
|
* or tab content components (see {@link javax.swing.JTabbedPane#setComponentAt(int, java.awt.Component)})<br>
|
||||||
|
* <strong>Value type</strong> {@link java.awt.Insets}
|
||||||
|
*/
|
||||||
|
String TABBED_PANE_TAB_INSETS = "JTabbedPane.tabInsets";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies whether tabs are closable.
|
||||||
|
* If set to {@code true} on a tabbed pane component, all tabs in that tabbed pane are closable.
|
||||||
|
* To make individual tabs closable, set it to {@code true} on a tab content component.
|
||||||
|
* <p>
|
||||||
|
* Note that you have to specify a callback (see {@link #TABBED_PANE_TAB_CLOSABLE})
|
||||||
|
* that is invoked when the user clicks a tab close button.
|
||||||
|
* The callback is responsible for closing the tab.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTabbedPane}
|
||||||
|
* or tab content components (see {@link javax.swing.JTabbedPane#setComponentAt(int, java.awt.Component)})<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.Boolean}
|
||||||
|
*
|
||||||
|
* @see #TABBED_PANE_TAB_CLOSE_CALLBACK
|
||||||
|
*/
|
||||||
|
String TABBED_PANE_TAB_CLOSABLE = "JTabbedPane.tabClosable";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the tooltip text used for tab close buttons.
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTabbedPane}
|
||||||
|
* or tab content components (see {@link javax.swing.JTabbedPane#setComponentAt(int, java.awt.Component)})<br>
|
||||||
|
* <strong>Value type</strong> {@link java.lang.String}
|
||||||
|
*/
|
||||||
|
String TABBED_PANE_TAB_CLOSE_TOOLTIPTEXT = "JTabbedPane.tabCloseToolTipText";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the callback that is invoked when a tab close button is clicked.
|
||||||
|
* The callback is responsible for closing the tab.
|
||||||
|
* <p>
|
||||||
|
* Either use a {@link java.util.function.IntConsumer} that received the tab index as parameter:
|
||||||
|
* <pre>{@code
|
||||||
|
* myTabbedPane.putClientProperty( "JTabbedPane.tabCloseCallback",
|
||||||
|
* (IntConsumer) tabIndex -> {
|
||||||
|
* // close tab here
|
||||||
|
* } );
|
||||||
|
* }</pre>
|
||||||
|
* Or use a {@link java.util.function.BiConsumer}<javax.swing.JTabbedPane, Integer>
|
||||||
|
* that received the tabbed pane and the tab index as parameters:
|
||||||
|
* <pre>{@code
|
||||||
|
* myTabbedPane.putClientProperty( "JTabbedPane.tabCloseCallback",
|
||||||
|
* (BiConsumer<JTabbedPane, Integer>) (tabbedPane, tabIndex) -> {
|
||||||
|
* // close tab here
|
||||||
|
* } );
|
||||||
|
* }</pre>
|
||||||
|
* If you need to check whether a modifier key (e.g. Alt or Shift) was pressed
|
||||||
|
* while the user clicked the tab close button, use {@link java.awt.EventQueue#getCurrentEvent}
|
||||||
|
* to get current event, check whether it is a {@link java.awt.event.MouseEvent}
|
||||||
|
* and invoke its methods. E.g.
|
||||||
|
* <pre>{@code
|
||||||
|
* AWTEvent e = EventQueue.getCurrentEvent();
|
||||||
|
* boolean shift = (e instanceof MouseEvent) ? ((MouseEvent)e).isShiftDown() : false;
|
||||||
|
* }</pre>
|
||||||
|
* <p>
|
||||||
|
* <strong>Component</strong> {@link javax.swing.JTabbedPane}
|
||||||
|
* or tab content components (see {@link javax.swing.JTabbedPane#setComponentAt(int, java.awt.Component)})<br>
|
||||||
|
* <strong>Value type</strong> {@link java.util.function.IntConsumer}
|
||||||
|
* or {@link java.util.function.BiConsumer}<javax.swing.JTabbedPane, Integer>
|
||||||
|
*
|
||||||
|
* @see #TABBED_PANE_TAB_CLOSABLE
|
||||||
|
*/
|
||||||
|
String TABBED_PANE_TAB_CLOSE_CALLBACK = "JTabbedPane.tabCloseCallback";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies how to navigate to hidden tabs.
|
* Specifies how to navigate to hidden tabs.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -280,6 +366,8 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TABBED_PANE_TRAILING_COMPONENT = "JTabbedPane.trailingComponent";
|
String TABBED_PANE_TRAILING_COMPONENT = "JTabbedPane.trailingComponent";
|
||||||
|
|
||||||
|
//---- JTextField ---------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether all text is selected when the text component gains focus.
|
* Specifies whether all text is selected when the text component gains focus.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -322,6 +410,8 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String PLACEHOLDER_TEXT = "JTextField.placeholderText";
|
String PLACEHOLDER_TEXT = "JTextField.placeholderText";
|
||||||
|
|
||||||
|
//---- JToggleButton ------------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Height of underline if toggle button type is {@link #BUTTON_TYPE_TAB}.
|
* Height of underline if toggle button type is {@link #BUTTON_TYPE_TAB}.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -346,6 +436,8 @@ public interface FlatClientProperties
|
|||||||
*/
|
*/
|
||||||
String TAB_BUTTON_SELECTED_BACKGROUND = "JToggleButton.tab.selectedBackground";
|
String TAB_BUTTON_SELECTED_BACKGROUND = "JToggleButton.tab.selectedBackground";
|
||||||
|
|
||||||
|
//---- helper methods -----------------------------------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether a client property of a component has the given value.
|
* Checks whether a client property of a component has the given value.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2020 FormDev Software GmbH
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.formdev.flatlaf.icons;
|
||||||
|
|
||||||
|
import java.awt.BasicStroke;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.awt.geom.Line2D;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
import com.formdev.flatlaf.ui.FlatButtonUI;
|
||||||
|
import com.formdev.flatlaf.ui.FlatUIUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* "close" icon for closable tabs in {@link javax.swing.JTabbedPane}.
|
||||||
|
*
|
||||||
|
* @uiDefault TabbedPane.closeSize Dimension
|
||||||
|
* @uiDefault TabbedPane.closeArc int
|
||||||
|
* @uiDefault TabbedPane.closeCrossPlainSize float
|
||||||
|
* @uiDefault TabbedPane.closeCrossFilledSize float
|
||||||
|
* @uiDefault TabbedPane.closeCrossLineWidth float
|
||||||
|
* @uiDefault TabbedPane.closeBackground Color
|
||||||
|
* @uiDefault TabbedPane.closeForeground Color
|
||||||
|
* @uiDefault TabbedPane.closeHoverBackground Color
|
||||||
|
* @uiDefault TabbedPane.closeHoverForeground Color
|
||||||
|
* @uiDefault TabbedPane.closePressedBackground Color
|
||||||
|
* @uiDefault TabbedPane.closePressedForeground Color
|
||||||
|
*
|
||||||
|
* @author Karl Tauber
|
||||||
|
*/
|
||||||
|
public class FlatTabbedPaneCloseIcon
|
||||||
|
extends FlatAbstractIcon
|
||||||
|
{
|
||||||
|
protected final Dimension size = UIManager.getDimension( "TabbedPane.closeSize" );
|
||||||
|
protected final int arc = UIManager.getInt( "TabbedPane.closeArc" );
|
||||||
|
protected final float crossPlainSize = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossPlainSize", 7.5f );
|
||||||
|
protected final float crossFilledSize = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossFilledSize", crossPlainSize );
|
||||||
|
protected final float closeCrossLineWidth = FlatUIUtils.getUIFloat( "TabbedPane.closeCrossLineWidth", 1f );
|
||||||
|
protected final Color background = UIManager.getColor( "TabbedPane.closeBackground" );
|
||||||
|
protected final Color foreground = UIManager.getColor( "TabbedPane.closeForeground" );
|
||||||
|
protected final Color hoverBackground = UIManager.getColor( "TabbedPane.closeHoverBackground" );
|
||||||
|
protected final Color hoverForeground = UIManager.getColor( "TabbedPane.closeHoverForeground" );
|
||||||
|
protected final Color pressedBackground = UIManager.getColor( "TabbedPane.closePressedBackground" );
|
||||||
|
protected final Color pressedForeground = UIManager.getColor( "TabbedPane.closePressedForeground" );
|
||||||
|
|
||||||
|
public FlatTabbedPaneCloseIcon() {
|
||||||
|
super( 16, 16, null );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void paintIcon( Component c, Graphics2D g ) {
|
||||||
|
// paint background
|
||||||
|
Color bg = FlatButtonUI.buttonStateColor( c, background, null, null, hoverBackground, pressedBackground );
|
||||||
|
if( bg != null ) {
|
||||||
|
g.setColor( bg );
|
||||||
|
g.fillRoundRect( (width - size.width) / 2, (height - size.height) / 2,
|
||||||
|
size.width, size.height, arc, arc );
|
||||||
|
}
|
||||||
|
|
||||||
|
// set cross color
|
||||||
|
g.setColor( FlatButtonUI.buttonStateColor( c, foreground, null, null, hoverForeground, pressedForeground ) );
|
||||||
|
|
||||||
|
float mx = width / 2;
|
||||||
|
float my = height / 2;
|
||||||
|
float r = ((bg != null) ? crossFilledSize : crossPlainSize) / 2;
|
||||||
|
|
||||||
|
// paint cross
|
||||||
|
Path2D path = new Path2D.Float( Path2D.WIND_EVEN_ODD );
|
||||||
|
path.append( new Line2D.Float( mx - r, my - r, mx + r, my + r ), false );
|
||||||
|
path.append( new Line2D.Float( mx - r, my + r, mx + r, my - r ), false );
|
||||||
|
g.setStroke( new BasicStroke( closeCrossLineWidth ) );
|
||||||
|
g.draw( path );
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -38,11 +38,14 @@ import java.awt.event.ActionEvent;
|
|||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.ComponentEvent;
|
import java.awt.event.ComponentEvent;
|
||||||
import java.awt.event.ComponentListener;
|
import java.awt.event.ComponentListener;
|
||||||
|
import java.awt.event.ContainerEvent;
|
||||||
|
import java.awt.event.ContainerListener;
|
||||||
import java.awt.event.InputEvent;
|
import java.awt.event.InputEvent;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.awt.event.MouseAdapter;
|
import java.awt.event.MouseAdapter;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
import java.awt.event.MouseListener;
|
import java.awt.event.MouseListener;
|
||||||
|
import java.awt.event.MouseMotionListener;
|
||||||
import java.awt.event.MouseWheelEvent;
|
import java.awt.event.MouseWheelEvent;
|
||||||
import java.awt.geom.Path2D;
|
import java.awt.geom.Path2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
@@ -51,6 +54,10 @@ import java.beans.PropertyChangeListener;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.IntConsumer;
|
||||||
|
import javax.swing.ButtonModel;
|
||||||
|
import javax.swing.Icon;
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JComponent;
|
import javax.swing.JComponent;
|
||||||
import javax.swing.JMenuItem;
|
import javax.swing.JMenuItem;
|
||||||
@@ -90,7 +97,7 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault TabbedPane.shadow Color used for scroll arrows and cropped line
|
* @uiDefault TabbedPane.shadow Color used for scroll arrows and cropped line
|
||||||
* @uiDefault TabbedPane.textIconGap int
|
* @uiDefault TabbedPane.textIconGap int
|
||||||
* @uiDefault TabbedPane.tabInsets Insets
|
* @uiDefault TabbedPane.tabInsets Insets
|
||||||
* @uiDefault TabbedPane.selectedTabPadInsets Insets
|
* @uiDefault TabbedPane.selectedTabPadInsets Insets unused
|
||||||
* @uiDefault TabbedPane.tabAreaInsets Insets
|
* @uiDefault TabbedPane.tabAreaInsets Insets
|
||||||
* @uiDefault TabbedPane.tabsOverlapBorder boolean
|
* @uiDefault TabbedPane.tabsOverlapBorder boolean
|
||||||
* @uiDefault TabbedPane.tabRunOverlay int
|
* @uiDefault TabbedPane.tabRunOverlay int
|
||||||
@@ -119,6 +126,7 @@ import com.formdev.flatlaf.util.UIScale;
|
|||||||
* @uiDefault TabbedPane.hasFullBorder boolean
|
* @uiDefault TabbedPane.hasFullBorder boolean
|
||||||
* @uiDefault TabbedPane.hiddenTabsNavigation String moreTabsButton (default) or arrowButtons
|
* @uiDefault TabbedPane.hiddenTabsNavigation String moreTabsButton (default) or arrowButtons
|
||||||
* @uiDefault ScrollPane.smoothScrolling boolean
|
* @uiDefault ScrollPane.smoothScrolling boolean
|
||||||
|
* @uiDefault TabbedPane.closeIcon Icon
|
||||||
*
|
*
|
||||||
* @uiDefault TabbedPane.moreTabsButtonToolTipText String
|
* @uiDefault TabbedPane.moreTabsButtonToolTipText String
|
||||||
*
|
*
|
||||||
@@ -144,6 +152,7 @@ public class FlatTabbedPaneUI
|
|||||||
protected Color tabSeparatorColor;
|
protected Color tabSeparatorColor;
|
||||||
protected Color contentAreaColor;
|
protected Color contentAreaColor;
|
||||||
|
|
||||||
|
private int textIconGapUnscaled;
|
||||||
protected int tabHeight;
|
protected int tabHeight;
|
||||||
protected int tabSelectionHeight;
|
protected int tabSelectionHeight;
|
||||||
protected int contentSeparatorHeight;
|
protected int contentSeparatorHeight;
|
||||||
@@ -152,18 +161,22 @@ public class FlatTabbedPaneUI
|
|||||||
protected boolean hasFullBorder;
|
protected boolean hasFullBorder;
|
||||||
|
|
||||||
private String hiddenTabsNavigationStr;
|
private String hiddenTabsNavigationStr;
|
||||||
|
protected Icon closeIcon;
|
||||||
|
|
||||||
protected String moreTabsButtonToolTipText;
|
protected String moreTabsButtonToolTipText;
|
||||||
|
|
||||||
protected JViewport tabViewport;
|
protected JViewport tabViewport;
|
||||||
protected FlatWheelTabScroller wheelTabScroller;
|
protected FlatWheelTabScroller wheelTabScroller;
|
||||||
|
|
||||||
|
private JButton tabCloseButton;
|
||||||
private JButton moreTabsButton;
|
private JButton moreTabsButton;
|
||||||
private Container leadingComponent;
|
private Container leadingComponent;
|
||||||
private Container trailingComponent;
|
private Container trailingComponent;
|
||||||
|
|
||||||
private Handler handler;
|
private Handler handler;
|
||||||
private boolean blockRollover;
|
private boolean blockRollover;
|
||||||
|
private boolean rolloverTabClose;
|
||||||
|
private boolean pressedTabClose;
|
||||||
|
|
||||||
public static ComponentUI createUI( JComponent c ) {
|
public static ComponentUI createUI( JComponent c ) {
|
||||||
return new FlatTabbedPaneUI();
|
return new FlatTabbedPaneUI();
|
||||||
@@ -203,6 +216,7 @@ public class FlatTabbedPaneUI
|
|||||||
tabSeparatorColor = UIManager.getColor( "TabbedPane.tabSeparatorColor" );
|
tabSeparatorColor = UIManager.getColor( "TabbedPane.tabSeparatorColor" );
|
||||||
contentAreaColor = UIManager.getColor( "TabbedPane.contentAreaColor" );
|
contentAreaColor = UIManager.getColor( "TabbedPane.contentAreaColor" );
|
||||||
|
|
||||||
|
textIconGapUnscaled = UIManager.getInt( "TabbedPane.textIconGap" );
|
||||||
tabHeight = UIManager.getInt( "TabbedPane.tabHeight" );
|
tabHeight = UIManager.getInt( "TabbedPane.tabHeight" );
|
||||||
tabSelectionHeight = UIManager.getInt( "TabbedPane.tabSelectionHeight" );
|
tabSelectionHeight = UIManager.getInt( "TabbedPane.tabSelectionHeight" );
|
||||||
contentSeparatorHeight = UIManager.getInt( "TabbedPane.contentSeparatorHeight" );
|
contentSeparatorHeight = UIManager.getInt( "TabbedPane.contentSeparatorHeight" );
|
||||||
@@ -210,17 +224,13 @@ public class FlatTabbedPaneUI
|
|||||||
tabSeparatorsFullHeight = UIManager.getBoolean( "TabbedPane.tabSeparatorsFullHeight" );
|
tabSeparatorsFullHeight = UIManager.getBoolean( "TabbedPane.tabSeparatorsFullHeight" );
|
||||||
hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" );
|
hasFullBorder = UIManager.getBoolean( "TabbedPane.hasFullBorder" );
|
||||||
hiddenTabsNavigationStr = UIManager.getString( "TabbedPane.hiddenTabsNavigation" );
|
hiddenTabsNavigationStr = UIManager.getString( "TabbedPane.hiddenTabsNavigation" );
|
||||||
|
closeIcon = UIManager.getIcon( "TabbedPane.closeIcon" );
|
||||||
|
|
||||||
Locale l = tabPane.getLocale();
|
Locale l = tabPane.getLocale();
|
||||||
moreTabsButtonToolTipText = UIManager.getString( "TabbedPane.moreTabsButtonToolTipText", l );
|
moreTabsButtonToolTipText = UIManager.getString( "TabbedPane.moreTabsButtonToolTipText", l );
|
||||||
|
|
||||||
// scale
|
// scale
|
||||||
textIconGap = scale( textIconGap );
|
textIconGap = scale( textIconGapUnscaled );
|
||||||
tabInsets = scale( tabInsets );
|
|
||||||
selectedTabPadInsets = scale( selectedTabPadInsets );
|
|
||||||
tabAreaInsets = scale( tabAreaInsets );
|
|
||||||
tabHeight = scale( tabHeight );
|
|
||||||
tabSelectionHeight = scale( tabSelectionHeight );
|
|
||||||
|
|
||||||
// replace focus forward/backward traversal keys with TAB/Shift+TAB because
|
// 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
|
// the default also includes Ctrl+TAB/Ctrl+Shift+TAB, which we need to switch tabs
|
||||||
@@ -255,6 +265,8 @@ public class FlatTabbedPaneUI
|
|||||||
tabSeparatorColor = null;
|
tabSeparatorColor = null;
|
||||||
contentAreaColor = null;
|
contentAreaColor = null;
|
||||||
|
|
||||||
|
closeIcon = null;
|
||||||
|
|
||||||
MigLayoutVisualPadding.uninstall( tabPane );
|
MigLayoutVisualPadding.uninstall( tabPane );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,6 +274,11 @@ public class FlatTabbedPaneUI
|
|||||||
protected void installComponents() {
|
protected void installComponents() {
|
||||||
super.installComponents();
|
super.installComponents();
|
||||||
|
|
||||||
|
// create tab close button
|
||||||
|
tabCloseButton = new TabCloseButton();
|
||||||
|
tabCloseButton.setVisible( false );
|
||||||
|
tabPane.add( tabCloseButton );
|
||||||
|
|
||||||
// find scrollable tab viewport
|
// find scrollable tab viewport
|
||||||
tabViewport = null;
|
tabViewport = null;
|
||||||
if( isScrollTabLayout() ) {
|
if( isScrollTabLayout() ) {
|
||||||
@@ -288,6 +305,11 @@ public class FlatTabbedPaneUI
|
|||||||
|
|
||||||
super.uninstallComponents();
|
super.uninstallComponents();
|
||||||
|
|
||||||
|
if( tabCloseButton != null ) {
|
||||||
|
tabPane.remove( tabCloseButton );
|
||||||
|
tabCloseButton = null;
|
||||||
|
}
|
||||||
|
|
||||||
tabViewport = null;
|
tabViewport = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,9 +376,7 @@ public class FlatTabbedPaneUI
|
|||||||
protected void installListeners() {
|
protected void installListeners() {
|
||||||
super.installListeners();
|
super.installListeners();
|
||||||
|
|
||||||
tabPane.addMouseListener( getHandler() );
|
getHandler().installListeners();
|
||||||
tabPane.addMouseMotionListener( getHandler() );
|
|
||||||
tabPane.addComponentListener( getHandler() );
|
|
||||||
|
|
||||||
if( tabViewport != null && (wheelTabScroller = createWheelTabScroller()) != null ) {
|
if( tabViewport != null && (wheelTabScroller = createWheelTabScroller()) != null ) {
|
||||||
// ideally we would add the mouse listeners to the viewport, but then the
|
// ideally we would add the mouse listeners to the viewport, but then the
|
||||||
@@ -373,9 +393,7 @@ public class FlatTabbedPaneUI
|
|||||||
super.uninstallListeners();
|
super.uninstallListeners();
|
||||||
|
|
||||||
if( handler != null ) {
|
if( handler != null ) {
|
||||||
tabPane.removeMouseListener( handler );
|
handler.uninstallListeners();
|
||||||
tabPane.removeMouseMotionListener( handler );
|
|
||||||
tabPane.removeComponentListener( handler );
|
|
||||||
handler = null;
|
handler = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,6 +417,13 @@ public class FlatTabbedPaneUI
|
|||||||
return new FlatWheelTabScroller();
|
return new FlatWheelTabScroller();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MouseListener createMouseListener() {
|
||||||
|
Handler handler = getHandler();
|
||||||
|
handler.mouseDelegate = super.createMouseListener();
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PropertyChangeListener createPropertyChangeListener() {
|
protected PropertyChangeListener createPropertyChangeListener() {
|
||||||
Handler handler = getHandler();
|
Handler handler = getHandler();
|
||||||
@@ -454,6 +479,30 @@ public class FlatTabbedPaneUI
|
|||||||
repaintTab( index );
|
repaintTab( index );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean isRolloverTabClose() {
|
||||||
|
return rolloverTabClose;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setRolloverTabClose( boolean rollover ) {
|
||||||
|
if( rolloverTabClose == rollover )
|
||||||
|
return;
|
||||||
|
|
||||||
|
rolloverTabClose = rollover;
|
||||||
|
repaintTab( getRolloverTab() );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isPressedTabClose() {
|
||||||
|
return pressedTabClose;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setPressedTabClose( boolean pressed ) {
|
||||||
|
if( pressedTabClose == pressed )
|
||||||
|
return;
|
||||||
|
|
||||||
|
pressedTabClose = pressed;
|
||||||
|
repaintTab( getRolloverTab() );
|
||||||
|
}
|
||||||
|
|
||||||
private void repaintTab( int tabIndex ) {
|
private void repaintTab( int tabIndex ) {
|
||||||
if( tabIndex < 0 || tabIndex >= tabPane.getTabCount() )
|
if( tabIndex < 0 || tabIndex >= tabPane.getTabCount() )
|
||||||
return;
|
return;
|
||||||
@@ -465,15 +514,34 @@ public class FlatTabbedPaneUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int calculateTabWidth( int tabPlacement, int tabIndex, FontMetrics metrics ) {
|
protected int calculateTabWidth( int tabPlacement, int tabIndex, FontMetrics metrics ) {
|
||||||
return super.calculateTabWidth( tabPlacement, tabIndex, metrics ) - 3 /* was added by superclass */;
|
// update textIconGap before used in super class
|
||||||
|
textIconGap = scale( textIconGapUnscaled );
|
||||||
|
|
||||||
|
int tabWidth = super.calculateTabWidth( tabPlacement, tabIndex, metrics ) - 3 /* was added by superclass */;
|
||||||
|
if( isTabClosable( tabIndex ) )
|
||||||
|
tabWidth += closeIcon.getIconWidth();
|
||||||
|
return tabWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int calculateTabHeight( int tabPlacement, int tabIndex, int fontHeight ) {
|
protected int calculateTabHeight( int tabPlacement, int tabIndex, int fontHeight ) {
|
||||||
int tabHeight = clientPropertyInt( tabPane, TABBED_PANE_TAB_HEIGHT, this.tabHeight );
|
int tabHeight = scale( clientPropertyInt( tabPane, TABBED_PANE_TAB_HEIGHT, this.tabHeight ) );
|
||||||
return Math.max( tabHeight, super.calculateTabHeight( tabPlacement, tabIndex, fontHeight ) - 2 /* was added by superclass */ );
|
return Math.max( tabHeight, super.calculateTabHeight( tabPlacement, tabIndex, fontHeight ) - 2 /* was added by superclass */ );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Insets getTabInsets( int tabPlacement, int tabIndex ) {
|
||||||
|
Object value = getTabClientProperty( tabIndex, TABBED_PANE_TAB_INSETS );
|
||||||
|
return scale( (value instanceof Insets)
|
||||||
|
? (Insets) value
|
||||||
|
: super.getTabInsets( tabPlacement, tabIndex ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Insets getSelectedTabPadInsets( int tabPlacement ) {
|
||||||
|
return new Insets( 0, 0, 0, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Insets getTabAreaInsets( int tabPlacement ) {
|
protected Insets getTabAreaInsets( int tabPlacement ) {
|
||||||
Insets currentTabAreaInsets = super.getTabAreaInsets( tabPlacement );
|
Insets currentTabAreaInsets = super.getTabAreaInsets( tabPlacement );
|
||||||
@@ -486,6 +554,9 @@ public class FlatTabbedPaneUI
|
|||||||
// Giving it large values clips painting of the cropped edge and makes it invisible.
|
// Giving it large values clips painting of the cropped edge and makes it invisible.
|
||||||
currentTabAreaInsets.top = currentTabAreaInsets.left = -10000;
|
currentTabAreaInsets.top = currentTabAreaInsets.left = -10000;
|
||||||
|
|
||||||
|
// scale insets (before adding leading/trailing component sizes)
|
||||||
|
insets = scale( insets );
|
||||||
|
|
||||||
// increase insets for wrap layout if using leading/trailing components
|
// increase insets for wrap layout if using leading/trailing components
|
||||||
if( tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT ) {
|
if( tabPane.getTabLayoutPolicy() == JTabbedPane.WRAP_TAB_LAYOUT ) {
|
||||||
if( leadingComponent != null ) {
|
if( leadingComponent != null ) {
|
||||||
@@ -528,6 +599,10 @@ public class FlatTabbedPaneUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getTabLabelShiftX( int tabPlacement, int tabIndex, boolean isSelected ) {
|
protected int getTabLabelShiftX( int tabPlacement, int tabIndex, boolean isSelected ) {
|
||||||
|
if( isTabClosable( tabIndex ) ) {
|
||||||
|
int shift = closeIcon.getIconWidth() / 2;
|
||||||
|
return isLeftToRight() ? -shift : shift;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -619,6 +694,10 @@ public class FlatTabbedPaneUI
|
|||||||
protected void paintTabBorder( Graphics g, int tabPlacement, int tabIndex,
|
protected void paintTabBorder( Graphics g, int tabPlacement, int tabIndex,
|
||||||
int x, int y, int w, int h, boolean isSelected )
|
int x, int y, int w, int h, boolean isSelected )
|
||||||
{
|
{
|
||||||
|
// paint tab close button
|
||||||
|
if( isTabClosable( tabIndex ) )
|
||||||
|
paintTabCloseButton( g, tabIndex, x, y, w, h );
|
||||||
|
|
||||||
// paint tab separators
|
// paint tab separators
|
||||||
if( clientPropertyBoolean( tabPane, TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators ) &&
|
if( clientPropertyBoolean( tabPane, TABBED_PANE_SHOW_TAB_SEPARATORS, showTabSeparators ) &&
|
||||||
!isLastInRun( tabIndex ) )
|
!isLastInRun( tabIndex ) )
|
||||||
@@ -628,6 +707,18 @@ public class FlatTabbedPaneUI
|
|||||||
paintTabSelection( g, tabPlacement, x, y, w, h );
|
paintTabSelection( g, tabPlacement, x, y, w, h );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void paintTabCloseButton( Graphics g, int tabIndex, int x, int y, int w, int h ) {
|
||||||
|
// update state of tab close button
|
||||||
|
boolean rollover = (tabIndex == getRolloverTab());
|
||||||
|
ButtonModel bm = tabCloseButton.getModel();
|
||||||
|
bm.setRollover( rollover && isRolloverTabClose() );
|
||||||
|
bm.setPressed( rollover && isPressedTabClose() );
|
||||||
|
|
||||||
|
// paint tab close icon
|
||||||
|
Rectangle tabCloseRect = getTabCloseBounds( x, y, w, h, calcRect );
|
||||||
|
closeIcon.paintIcon( tabCloseButton, g, tabCloseRect.x, tabCloseRect.y );
|
||||||
|
}
|
||||||
|
|
||||||
protected void paintTabSeparator( Graphics g, int tabPlacement, int x, int y, int w, int h ) {
|
protected void paintTabSeparator( Graphics g, int tabPlacement, int x, int y, int w, int h ) {
|
||||||
float sepWidth = UIScale.scale( 1f );
|
float sepWidth = UIScale.scale( 1f );
|
||||||
float offset = tabSeparatorsFullHeight ? 0 : UIScale.scale( 5f );
|
float offset = tabSeparatorsFullHeight ? 0 : UIScale.scale( 5f );
|
||||||
@@ -636,7 +727,7 @@ public class FlatTabbedPaneUI
|
|||||||
if( tabPlacement == LEFT || tabPlacement == RIGHT ) {
|
if( tabPlacement == LEFT || tabPlacement == RIGHT ) {
|
||||||
// paint tab separator at bottom side
|
// paint tab separator at bottom side
|
||||||
((Graphics2D)g).fill( new Rectangle2D.Float( x + offset, y + h - sepWidth, w - (offset * 2), sepWidth ) );
|
((Graphics2D)g).fill( new Rectangle2D.Float( x + offset, y + h - sepWidth, w - (offset * 2), sepWidth ) );
|
||||||
} else if( tabPane.getComponentOrientation().isLeftToRight() ) {
|
} else if( isLeftToRight() ) {
|
||||||
// paint tab separator at right side
|
// paint tab separator at right side
|
||||||
((Graphics2D)g).fill( new Rectangle2D.Float( x + w - sepWidth, y + offset, sepWidth, h - (offset * 2) ) );
|
((Graphics2D)g).fill( new Rectangle2D.Float( x + w - sepWidth, y + offset, sepWidth, h - (offset * 2) ) );
|
||||||
} else {
|
} else {
|
||||||
@@ -682,6 +773,7 @@ public class FlatTabbedPaneUI
|
|||||||
Insets contentInsets = getContentBorderInsets( tabPlacement );
|
Insets contentInsets = getContentBorderInsets( tabPlacement );
|
||||||
|
|
||||||
// paint underline selection
|
// paint underline selection
|
||||||
|
int tabSelectionHeight = scale( this.tabSelectionHeight );
|
||||||
switch( tabPlacement ) {
|
switch( tabPlacement ) {
|
||||||
case TOP:
|
case TOP:
|
||||||
default:
|
default:
|
||||||
@@ -788,6 +880,16 @@ public class FlatTabbedPaneUI
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void layoutLabel( int tabPlacement, FontMetrics metrics, int tabIndex, String title, Icon icon,
|
||||||
|
Rectangle tabRect, Rectangle iconRect, Rectangle textRect, boolean isSelected )
|
||||||
|
{
|
||||||
|
// update textIconGap before used in super class
|
||||||
|
textIconGap = scale( textIconGapUnscaled );
|
||||||
|
|
||||||
|
super.layoutLabel( tabPlacement, metrics, tabIndex, title, icon, tabRect, iconRect, textRect, isSelected );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int tabForCoordinate( JTabbedPane pane, int x, int y ) {
|
public int tabForCoordinate( JTabbedPane pane, int x, int y ) {
|
||||||
if( moreTabsButton != null ) {
|
if( moreTabsButton != null ) {
|
||||||
@@ -819,6 +921,55 @@ public class FlatTabbedPaneUI
|
|||||||
return super.getTabBounds( tabIndex, dest );
|
return super.getTabBounds( tabIndex, dest );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Rectangle getTabCloseBounds( int x, int y, int w, int h, Rectangle dest ) {
|
||||||
|
dest.width = closeIcon.getIconWidth();
|
||||||
|
dest.height = closeIcon.getIconHeight();
|
||||||
|
int xoffset = (h - dest.width) / 2;
|
||||||
|
int yoffset = (h - dest.height) / 2;
|
||||||
|
dest.x = isLeftToRight() ? (x + w - xoffset - dest.width) : (x + xoffset);
|
||||||
|
dest.y = y + yoffset;
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Rectangle getTabCloseHitArea( int tabIndex ) {
|
||||||
|
Rectangle tabRect = getTabBounds( tabPane, tabIndex );
|
||||||
|
Rectangle tabCloseRect = getTabCloseBounds( tabRect.x, tabRect.y, tabRect.width, tabRect.height, calcRect );
|
||||||
|
return new Rectangle( tabCloseRect.x, tabRect.y, tabCloseRect.width, tabRect.height );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isTabClosable( int tabIndex ) {
|
||||||
|
Object value = getTabClientProperty( tabIndex, TABBED_PANE_TAB_CLOSABLE );
|
||||||
|
return (value instanceof Boolean) ? (boolean) value : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings( { "unchecked" } )
|
||||||
|
protected void closeTab( int tabIndex ) {
|
||||||
|
Object callback = getTabClientProperty( tabIndex, TABBED_PANE_TAB_CLOSE_CALLBACK );
|
||||||
|
if( callback instanceof IntConsumer )
|
||||||
|
((IntConsumer)callback).accept( tabIndex );
|
||||||
|
else if( callback instanceof BiConsumer )
|
||||||
|
((BiConsumer<JTabbedPane, Integer>)callback).accept( tabPane, tabIndex );
|
||||||
|
else {
|
||||||
|
throw new RuntimeException( "Missing tab close callback. "
|
||||||
|
+ "Set client property 'JTabbedPane.tabCloseCallback' "
|
||||||
|
+ "to a 'java.util.function.IntConsumer' "
|
||||||
|
+ "or 'java.util.function.BiConsumer<JTabbedPane, Integer>'" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Object getTabClientProperty( int tabIndex, String key ) {
|
||||||
|
if( tabIndex < 0 )
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Component c = tabPane.getComponentAt( tabIndex );
|
||||||
|
if( c instanceof JComponent ) {
|
||||||
|
Object value = ((JComponent)c).getClientProperty( key );
|
||||||
|
if( value != null )
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return tabPane.getClientProperty( key );
|
||||||
|
}
|
||||||
|
|
||||||
protected void ensureCurrentLayout() {
|
protected void ensureCurrentLayout() {
|
||||||
// since super.ensureCurrentLayout() is private,
|
// since super.ensureCurrentLayout() is private,
|
||||||
// use super.getTabRunCount() as workaround
|
// use super.getTabRunCount() as workaround
|
||||||
@@ -834,6 +985,10 @@ public class FlatTabbedPaneUI
|
|||||||
return tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT;
|
return tabPane.getTabLayoutPolicy() == JTabbedPane.SCROLL_TAB_LAYOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isLeftToRight() {
|
||||||
|
return tabPane.getComponentOrientation().isLeftToRight();
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean isHorizontalTabPlacement() {
|
protected boolean isHorizontalTabPlacement() {
|
||||||
int tabPlacement = tabPane.getTabPlacement();
|
int tabPlacement = tabPane.getTabPlacement();
|
||||||
return tabPlacement == TOP || tabPlacement == BOTTOM;
|
return tabPlacement == TOP || tabPlacement == BOTTOM;
|
||||||
@@ -914,6 +1069,16 @@ public class FlatTabbedPaneUI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---- class TabCloseButton -----------------------------------------------
|
||||||
|
|
||||||
|
private class TabCloseButton
|
||||||
|
extends JButton
|
||||||
|
implements UIResource
|
||||||
|
{
|
||||||
|
private TabCloseButton() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//---- class ContainerUIResource ------------------------------------------
|
//---- class ContainerUIResource ------------------------------------------
|
||||||
|
|
||||||
private class ContainerUIResource
|
private class ContainerUIResource
|
||||||
@@ -1011,9 +1176,8 @@ public class FlatTabbedPaneUI
|
|||||||
int buttonWidth = getWidth();
|
int buttonWidth = getWidth();
|
||||||
int buttonHeight = getHeight();
|
int buttonHeight = getHeight();
|
||||||
Dimension popupSize = popupMenu.getPreferredSize();
|
Dimension popupSize = popupMenu.getPreferredSize();
|
||||||
boolean leftToRight = tabPane.getComponentOrientation().isLeftToRight();
|
|
||||||
|
|
||||||
int x = leftToRight ? buttonWidth - popupSize.width : 0;
|
int x = isLeftToRight() ? buttonWidth - popupSize.width : 0;
|
||||||
int y = buttonHeight - popupSize.height;
|
int y = buttonHeight - popupSize.height;
|
||||||
switch( tabPane.getTabPlacement() ) {
|
switch( tabPane.getTabPlacement() ) {
|
||||||
default:
|
default:
|
||||||
@@ -1185,8 +1349,7 @@ public class FlatTabbedPaneUI
|
|||||||
int y = viewPosition.y;
|
int y = viewPosition.y;
|
||||||
int tabPlacement = tabPane.getTabPlacement();
|
int tabPlacement = tabPane.getTabPlacement();
|
||||||
if( tabPlacement == TOP || tabPlacement == BOTTOM ) {
|
if( tabPlacement == TOP || tabPlacement == BOTTOM ) {
|
||||||
boolean leftToRight = tabPane.getComponentOrientation().isLeftToRight();
|
x += isLeftToRight() ? amount : -amount;
|
||||||
x += leftToRight ? amount : -amount;
|
|
||||||
x = Math.min( Math.max( x, 0 ), viewSize.width - tabViewport.getWidth() );
|
x = Math.min( Math.max( x, 0 ), viewSize.width - tabViewport.getWidth() );
|
||||||
} else {
|
} else {
|
||||||
y += amount;
|
y += amount;
|
||||||
@@ -1360,18 +1523,73 @@ public class FlatTabbedPaneUI
|
|||||||
//---- class Handler ------------------------------------------------------
|
//---- class Handler ------------------------------------------------------
|
||||||
|
|
||||||
private class Handler
|
private class Handler
|
||||||
extends MouseAdapter
|
implements MouseListener, MouseMotionListener, PropertyChangeListener,
|
||||||
implements PropertyChangeListener, ChangeListener, ComponentListener
|
ChangeListener, ComponentListener, ContainerListener
|
||||||
{
|
{
|
||||||
|
MouseListener mouseDelegate;
|
||||||
PropertyChangeListener propertyChangeDelegate;
|
PropertyChangeListener propertyChangeDelegate;
|
||||||
ChangeListener changeDelegate;
|
ChangeListener changeDelegate;
|
||||||
|
|
||||||
|
private final PropertyChangeListener contentListener = this::contentPropertyChange;
|
||||||
|
|
||||||
|
private int pressedTabIndex = -1;
|
||||||
|
private int lastTipTabIndex = -1;
|
||||||
|
private String lastTip;
|
||||||
|
|
||||||
|
void installListeners() {
|
||||||
|
tabPane.addMouseMotionListener( this );
|
||||||
|
tabPane.addComponentListener( this );
|
||||||
|
tabPane.addContainerListener( this );
|
||||||
|
|
||||||
|
for( Component c : tabPane.getComponents() ) {
|
||||||
|
if( !(c instanceof UIResource) )
|
||||||
|
c.addPropertyChangeListener( contentListener );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void uninstallListeners() {
|
||||||
|
tabPane.removeMouseMotionListener( this );
|
||||||
|
tabPane.removeComponentListener( this );
|
||||||
|
tabPane.removeContainerListener( this );
|
||||||
|
|
||||||
|
for( Component c : tabPane.getComponents() ) {
|
||||||
|
if( !(c instanceof UIResource) )
|
||||||
|
c.removePropertyChangeListener( contentListener );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//---- interface MouseListener ----
|
//---- interface MouseListener ----
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseClicked( MouseEvent e ) {
|
||||||
|
mouseDelegate.mouseClicked( e );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mousePressed( MouseEvent e ) {
|
||||||
|
updateRollover( e );
|
||||||
|
|
||||||
|
if( !isPressedTabClose() )
|
||||||
|
mouseDelegate.mousePressed( e );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseReleased( MouseEvent e ) {
|
||||||
|
if( isPressedTabClose() ) {
|
||||||
|
updateRollover( e );
|
||||||
|
if( pressedTabIndex >= 0 && pressedTabIndex == getRolloverTab() )
|
||||||
|
closeTab( pressedTabIndex );
|
||||||
|
} else
|
||||||
|
mouseDelegate.mouseReleased( e );
|
||||||
|
|
||||||
|
pressedTabIndex = -1;
|
||||||
|
updateRollover( e );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseEntered( MouseEvent e ) {
|
public void mouseEntered( MouseEvent e ) {
|
||||||
// this is necessary for "more tabs" button
|
// this is necessary for "more tabs" button
|
||||||
setRolloverTab( e.getX(), e.getY() );
|
updateRollover( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1379,15 +1597,68 @@ public class FlatTabbedPaneUI
|
|||||||
// this event occurs also if mouse is moved to a custom tab component
|
// this event occurs also if mouse is moved to a custom tab component
|
||||||
// that handles mouse events (e.g. a close button)
|
// that handles mouse events (e.g. a close button)
|
||||||
// --> make sure that the tab stays highlighted
|
// --> make sure that the tab stays highlighted
|
||||||
setRolloverTab( e.getX(), e.getY() );
|
updateRollover( e );
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- interface MouseMotionListener ----
|
//---- interface MouseMotionListener ----
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseDragged( MouseEvent e ) {
|
||||||
|
updateRollover( e );
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void mouseMoved( MouseEvent e ) {
|
public void mouseMoved( MouseEvent e ) {
|
||||||
// this is necessary for "more tabs" button
|
updateRollover( e );
|
||||||
setRolloverTab( e.getX(), e.getY() );
|
}
|
||||||
|
|
||||||
|
private void updateRollover( MouseEvent e ) {
|
||||||
|
int x = e.getX();
|
||||||
|
int y = e.getY();
|
||||||
|
|
||||||
|
int tabIndex = tabForCoordinate( tabPane, x, y );
|
||||||
|
|
||||||
|
setRolloverTab( tabIndex );
|
||||||
|
|
||||||
|
// check whether mouse hit tab close area
|
||||||
|
boolean hitClose = isTabClosable( tabIndex )
|
||||||
|
? getTabCloseHitArea( tabIndex ).contains( x, y )
|
||||||
|
: false;
|
||||||
|
if( e.getID() == MouseEvent.MOUSE_PRESSED )
|
||||||
|
pressedTabIndex = hitClose ? tabIndex : -1;
|
||||||
|
setRolloverTabClose( hitClose );
|
||||||
|
setPressedTabClose( hitClose && tabIndex == pressedTabIndex );
|
||||||
|
|
||||||
|
// update tooltip
|
||||||
|
if( tabIndex >= 0 && hitClose ) {
|
||||||
|
Object closeTip = getTabClientProperty( tabIndex, TABBED_PANE_TAB_CLOSE_TOOLTIPTEXT );
|
||||||
|
if( closeTip instanceof String )
|
||||||
|
setCloseToolTip( tabIndex, (String) closeTip );
|
||||||
|
else
|
||||||
|
restoreTabToolTip();
|
||||||
|
} else
|
||||||
|
restoreTabToolTip();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCloseToolTip( int tabIndex, String closeTip ) {
|
||||||
|
if( tabIndex == lastTipTabIndex )
|
||||||
|
return; // closeTip already set
|
||||||
|
|
||||||
|
if( tabIndex != lastTipTabIndex )
|
||||||
|
restoreTabToolTip();
|
||||||
|
|
||||||
|
lastTipTabIndex = tabIndex;
|
||||||
|
lastTip = tabPane.getToolTipTextAt( lastTipTabIndex );
|
||||||
|
tabPane.setToolTipTextAt( lastTipTabIndex, closeTip );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void restoreTabToolTip() {
|
||||||
|
if( lastTipTabIndex < 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
tabPane.setToolTipTextAt( lastTipTabIndex, lastTip );
|
||||||
|
lastTip = null;
|
||||||
|
lastTipTabIndex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- interface PropertyChangeListener ----
|
//---- interface PropertyChangeListener ----
|
||||||
@@ -1425,7 +1696,9 @@ public class FlatTabbedPaneUI
|
|||||||
case TABBED_PANE_SHOW_CONTENT_SEPARATOR:
|
case TABBED_PANE_SHOW_CONTENT_SEPARATOR:
|
||||||
case TABBED_PANE_HAS_FULL_BORDER:
|
case TABBED_PANE_HAS_FULL_BORDER:
|
||||||
case TABBED_PANE_TAB_HEIGHT:
|
case TABBED_PANE_TAB_HEIGHT:
|
||||||
|
case TABBED_PANE_TAB_INSETS:
|
||||||
case TABBED_PANE_HIDDEN_TABS_NAVIGATION:
|
case TABBED_PANE_HIDDEN_TABS_NAVIGATION:
|
||||||
|
case TABBED_PANE_TAB_CLOSABLE:
|
||||||
tabPane.revalidate();
|
tabPane.revalidate();
|
||||||
tabPane.repaint();
|
tabPane.repaint();
|
||||||
break;
|
break;
|
||||||
@@ -1459,6 +1732,16 @@ public class FlatTabbedPaneUI
|
|||||||
ensureSelectedTabIsVisible();
|
ensureSelectedTabIsVisible();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void contentPropertyChange( PropertyChangeEvent e ) {
|
||||||
|
switch( e.getPropertyName() ) {
|
||||||
|
case TABBED_PANE_TAB_INSETS:
|
||||||
|
case TABBED_PANE_TAB_CLOSABLE:
|
||||||
|
tabPane.revalidate();
|
||||||
|
tabPane.repaint();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//---- interface ComponentListener ----
|
//---- interface ComponentListener ----
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1470,6 +1753,22 @@ public class FlatTabbedPaneUI
|
|||||||
@Override public void componentMoved( ComponentEvent e ) {}
|
@Override public void componentMoved( ComponentEvent e ) {}
|
||||||
@Override public void componentShown( ComponentEvent e ) {}
|
@Override public void componentShown( ComponentEvent e ) {}
|
||||||
@Override public void componentHidden( ComponentEvent e ) {}
|
@Override public void componentHidden( ComponentEvent e ) {}
|
||||||
|
|
||||||
|
//---- interface ContainerListener ----
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentAdded( ContainerEvent e ) {
|
||||||
|
Component c = e.getChild();
|
||||||
|
if( !(c instanceof UIResource) )
|
||||||
|
c.addPropertyChangeListener( contentListener );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void componentRemoved( ContainerEvent e ) {
|
||||||
|
Component c = e.getChild();
|
||||||
|
if( !(c instanceof UIResource) )
|
||||||
|
c.removePropertyChangeListener( contentListener );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class FlatTabbedPaneLayout -----------------------------------------
|
//---- class FlatTabbedPaneLayout -----------------------------------------
|
||||||
@@ -1485,7 +1784,7 @@ public class FlatTabbedPaneUI
|
|||||||
Insets insets = tabPane.getInsets();
|
Insets insets = tabPane.getInsets();
|
||||||
int tabPlacement = tabPane.getTabPlacement();
|
int tabPlacement = tabPane.getTabPlacement();
|
||||||
Insets tabAreaInsets = getTabAreaInsets( tabPlacement );
|
Insets tabAreaInsets = getTabAreaInsets( tabPlacement );
|
||||||
boolean leftToRight = tabPane.getComponentOrientation().isLeftToRight();
|
boolean leftToRight = isLeftToRight();
|
||||||
|
|
||||||
// layout leading and trailing components in tab area
|
// layout leading and trailing components in tab area
|
||||||
if( tabPlacement == TOP || tabPlacement == BOTTOM ) {
|
if( tabPlacement == TOP || tabPlacement == BOTTOM ) {
|
||||||
@@ -1556,7 +1855,7 @@ public class FlatTabbedPaneUI
|
|||||||
* Layout manager used for scroll tab layout policy.
|
* Layout manager used for scroll tab layout policy.
|
||||||
* <p>
|
* <p>
|
||||||
* Although this class delegates all methods to the original layout manager
|
* Although this class delegates all methods to the original layout manager
|
||||||
* {@link BasicTabbedPaneUI.TabbedPaneScrollLayout}, which extends
|
* {@code BasicTabbedPaneUI.TabbedPaneScrollLayout}, which extends
|
||||||
* {@link BasicTabbedPaneUI.TabbedPaneLayout}, it is necessary that this class
|
* {@link BasicTabbedPaneUI.TabbedPaneLayout}, it is necessary that this class
|
||||||
* also extends {@link TabbedPaneLayout} to avoid a {@code ClassCastException}
|
* also extends {@link TabbedPaneLayout} to avoid a {@code ClassCastException}
|
||||||
* in {@link BasicTabbedPaneUI}.ensureCurrentLayout().
|
* in {@link BasicTabbedPaneUI}.ensureCurrentLayout().
|
||||||
@@ -1603,7 +1902,7 @@ public class FlatTabbedPaneUI
|
|||||||
// for right-to-left always use "more tabs" button for horizontal scrolling
|
// for right-to-left always use "more tabs" button for horizontal scrolling
|
||||||
// because methods scrollForward() and scrollBackward() in class
|
// because methods scrollForward() and scrollBackward() in class
|
||||||
// BasicTabbedPaneUI.ScrollableTabSupport do not work for right-to-left
|
// BasicTabbedPaneUI.ScrollableTabSupport do not work for right-to-left
|
||||||
boolean leftToRight = tabPane.getComponentOrientation().isLeftToRight();
|
boolean leftToRight = isLeftToRight();
|
||||||
if( !leftToRight && !useMoreButton && isHorizontalTabPlacement() )
|
if( !leftToRight && !useMoreButton && isHorizontalTabPlacement() )
|
||||||
useMoreButton = true;
|
useMoreButton = true;
|
||||||
|
|
||||||
@@ -1623,6 +1922,13 @@ public class FlatTabbedPaneUI
|
|||||||
if( !useMoreButton && (backwardButton == null || forwardButton == null) )
|
if( !useMoreButton && (backwardButton == null || forwardButton == null) )
|
||||||
return; // should never occur
|
return; // should never occur
|
||||||
|
|
||||||
|
if( rects.length == 0 ) {
|
||||||
|
moreTabsButton.setVisible( false );
|
||||||
|
backwardButton.setVisible( false );
|
||||||
|
forwardButton.setVisible( false );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle bounds = tabPane.getBounds();
|
Rectangle bounds = tabPane.getBounds();
|
||||||
Insets insets = tabPane.getInsets();
|
Insets insets = tabPane.getInsets();
|
||||||
int tabPlacement = tabPane.getTabPlacement();
|
int tabPlacement = tabPane.getTabPlacement();
|
||||||
|
|||||||
@@ -258,6 +258,13 @@ TabbedPane.hoverColor=#2e3133
|
|||||||
TabbedPane.focusColor=#3d4b5c
|
TabbedPane.focusColor=#3d4b5c
|
||||||
TabbedPane.contentAreaColor=#646464
|
TabbedPane.contentAreaColor=#646464
|
||||||
|
|
||||||
|
TabbedPane.closeBackground=null
|
||||||
|
TabbedPane.closeForeground=@disabledText
|
||||||
|
TabbedPane.closeHoverBackground=lighten($TabbedPane.hoverColor,10%)
|
||||||
|
TabbedPane.closeHoverForeground=@foreground
|
||||||
|
TabbedPane.closePressedBackground=lighten($TabbedPane.hoverColor,15%)
|
||||||
|
TabbedPane.closePressedForeground=$TabbedPane.closeHoverForeground
|
||||||
|
|
||||||
|
|
||||||
#---- Table ----
|
#---- Table ----
|
||||||
|
|
||||||
|
|||||||
@@ -552,6 +552,13 @@ TabbedPane.shadow=@background
|
|||||||
TabbedPane.contentBorderInsets=null
|
TabbedPane.contentBorderInsets=null
|
||||||
TabbedPane.hiddenTabsNavigation=moreTabsButton
|
TabbedPane.hiddenTabsNavigation=moreTabsButton
|
||||||
|
|
||||||
|
TabbedPane.closeIcon=com.formdev.flatlaf.icons.FlatTabbedPaneCloseIcon
|
||||||
|
TabbedPane.closeSize=16,16
|
||||||
|
TabbedPane.closeArc=4
|
||||||
|
TabbedPane.closeCrossPlainSize={float}7.5
|
||||||
|
TabbedPane.closeCrossFilledSize=$TabbedPane.closeCrossPlainSize
|
||||||
|
TabbedPane.closeCrossLineWidth={float}1
|
||||||
|
|
||||||
|
|
||||||
#---- Table ----
|
#---- Table ----
|
||||||
|
|
||||||
|
|||||||
@@ -270,6 +270,13 @@ TabbedPane.hoverColor=#d9d9d9
|
|||||||
TabbedPane.focusColor=#dae4ed
|
TabbedPane.focusColor=#dae4ed
|
||||||
TabbedPane.contentAreaColor=#bfbfbf
|
TabbedPane.contentAreaColor=#bfbfbf
|
||||||
|
|
||||||
|
TabbedPane.closeBackground=null
|
||||||
|
TabbedPane.closeForeground=@disabledText
|
||||||
|
TabbedPane.closeHoverBackground=darken($TabbedPane.hoverColor,10%)
|
||||||
|
TabbedPane.closeHoverForeground=@foreground
|
||||||
|
TabbedPane.closePressedBackground=darken($TabbedPane.hoverColor,15%)
|
||||||
|
TabbedPane.closePressedForeground=$TabbedPane.closeHoverForeground
|
||||||
|
|
||||||
|
|
||||||
#---- Table ----
|
#---- Table ----
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,19 @@ public class TriStateCheckBox
|
|||||||
repaint();
|
repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getValue() {
|
||||||
|
switch( state ) {
|
||||||
|
default:
|
||||||
|
case INDETERMINATE: return null;
|
||||||
|
case SELECTED: return true;
|
||||||
|
case UNSELECTED: return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue( Boolean value ) {
|
||||||
|
setState( value == null ? State.INDETERMINATE : (value ? State.SELECTED : State.UNSELECTED) );
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isThirdStateEnabled() {
|
public boolean isThirdStateEnabled() {
|
||||||
return thirdStateEnabled;
|
return thirdStateEnabled;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -905,6 +905,17 @@ SplitPaneUI com.formdev.flatlaf.ui.FlatSplitPaneUI
|
|||||||
#---- TabbedPane ----
|
#---- TabbedPane ----
|
||||||
|
|
||||||
TabbedPane.background #3c3f41 javax.swing.plaf.ColorUIResource [UI]
|
TabbedPane.background #3c3f41 javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closeArc 4
|
||||||
|
TabbedPane.closeCrossFilledSize 7.5
|
||||||
|
TabbedPane.closeCrossLineWidth 1.0
|
||||||
|
TabbedPane.closeCrossPlainSize 7.5
|
||||||
|
TabbedPane.closeForeground #888888 javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closeHoverBackground #464b4e javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closeHoverForeground #bbbbbb javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closeIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatTabbedPaneCloseIcon [UI]
|
||||||
|
TabbedPane.closePressedBackground #52585b javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closePressedForeground #bbbbbb javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closeSize 16,16 javax.swing.plaf.DimensionUIResource [UI]
|
||||||
TabbedPane.contentAreaColor #646464 javax.swing.plaf.ColorUIResource [UI]
|
TabbedPane.contentAreaColor #646464 javax.swing.plaf.ColorUIResource [UI]
|
||||||
TabbedPane.contentOpaque true
|
TabbedPane.contentOpaque true
|
||||||
TabbedPane.contentSeparatorHeight 1
|
TabbedPane.contentSeparatorHeight 1
|
||||||
|
|||||||
@@ -910,6 +910,17 @@ SplitPaneUI com.formdev.flatlaf.ui.FlatSplitPaneUI
|
|||||||
#---- TabbedPane ----
|
#---- TabbedPane ----
|
||||||
|
|
||||||
TabbedPane.background #f2f2f2 javax.swing.plaf.ColorUIResource [UI]
|
TabbedPane.background #f2f2f2 javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closeArc 4
|
||||||
|
TabbedPane.closeCrossFilledSize 7.5
|
||||||
|
TabbedPane.closeCrossLineWidth 1.0
|
||||||
|
TabbedPane.closeCrossPlainSize 7.5
|
||||||
|
TabbedPane.closeForeground #8c8c8c javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closeHoverBackground #c0c0c0 javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closeHoverForeground #000000 javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closeIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatTabbedPaneCloseIcon [UI]
|
||||||
|
TabbedPane.closePressedBackground #b3b3b3 javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closePressedForeground #000000 javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closeSize 16,16 javax.swing.plaf.DimensionUIResource [UI]
|
||||||
TabbedPane.contentAreaColor #bfbfbf javax.swing.plaf.ColorUIResource [UI]
|
TabbedPane.contentAreaColor #bfbfbf javax.swing.plaf.ColorUIResource [UI]
|
||||||
TabbedPane.contentOpaque true
|
TabbedPane.contentOpaque true
|
||||||
TabbedPane.contentSeparatorHeight 1
|
TabbedPane.contentSeparatorHeight 1
|
||||||
|
|||||||
@@ -898,6 +898,17 @@ SplitPaneUI com.formdev.flatlaf.ui.FlatSplitPaneUI
|
|||||||
#---- TabbedPane ----
|
#---- TabbedPane ----
|
||||||
|
|
||||||
TabbedPane.background #ccffcc javax.swing.plaf.ColorUIResource [UI]
|
TabbedPane.background #ccffcc javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closeArc 999
|
||||||
|
TabbedPane.closeCrossFilledSize 6.5
|
||||||
|
TabbedPane.closeCrossLineWidth 2.0
|
||||||
|
TabbedPane.closeCrossPlainSize 12.0
|
||||||
|
TabbedPane.closeForeground #ff0000 javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closeHoverBackground #aa0000 javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closeHoverForeground #ffffff javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closeIcon [lazy] 16,16 com.formdev.flatlaf.icons.FlatTabbedPaneCloseIcon [UI]
|
||||||
|
TabbedPane.closePressedBackground #00ff00 javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closePressedForeground #000000 javax.swing.plaf.ColorUIResource [UI]
|
||||||
|
TabbedPane.closeSize 16,16 javax.swing.plaf.DimensionUIResource [UI]
|
||||||
TabbedPane.contentAreaColor #bbbbbb javax.swing.plaf.ColorUIResource [UI]
|
TabbedPane.contentAreaColor #bbbbbb javax.swing.plaf.ColorUIResource [UI]
|
||||||
TabbedPane.contentOpaque true
|
TabbedPane.contentOpaque true
|
||||||
TabbedPane.contentSeparatorHeight 1
|
TabbedPane.contentSeparatorHeight 1
|
||||||
|
|||||||
@@ -18,9 +18,12 @@ package com.formdev.flatlaf.testing;
|
|||||||
|
|
||||||
import static com.formdev.flatlaf.FlatClientProperties.*;
|
import static com.formdev.flatlaf.FlatClientProperties.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import javax.swing.border.*;
|
import javax.swing.border.*;
|
||||||
import com.formdev.flatlaf.FlatLaf;
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
|
import com.formdev.flatlaf.extras.TriStateCheckBox;
|
||||||
import com.formdev.flatlaf.icons.FlatInternalFrameCloseIcon;
|
import com.formdev.flatlaf.icons.FlatInternalFrameCloseIcon;
|
||||||
import com.formdev.flatlaf.util.ScaledImageIcon;
|
import com.formdev.flatlaf.util.ScaledImageIcon;
|
||||||
import com.jgoodies.forms.layout.*;
|
import com.jgoodies.forms.layout.*;
|
||||||
@@ -49,6 +52,10 @@ public class FlatContainerTest
|
|||||||
addInitialTabs( tabbedPane1, tabbedPane2, tabbedPane3, tabbedPane4 );
|
addInitialTabs( tabbedPane1, tabbedPane2, tabbedPane3, tabbedPane4 );
|
||||||
initialTabCount = tabbedPane1.getTabCount();
|
initialTabCount = tabbedPane1.getTabCount();
|
||||||
|
|
||||||
|
tabsClosableCheckBox.setSelected( true );
|
||||||
|
tabsClosableChanged();
|
||||||
|
putTabbedPanesClientProperty( TABBED_PANE_TAB_CLOSE_TOOLTIPTEXT, "Close" );
|
||||||
|
|
||||||
tabScrollCheckBox.setSelected( true );
|
tabScrollCheckBox.setSelected( true );
|
||||||
tabScrollChanged();
|
tabScrollChanged();
|
||||||
}
|
}
|
||||||
@@ -123,14 +130,15 @@ public class FlatContainerTest
|
|||||||
|
|
||||||
private void addInitialTabs( JTabbedPane... tabbedPanes ) {
|
private void addInitialTabs( JTabbedPane... tabbedPanes ) {
|
||||||
for( JTabbedPane tabbedPane : tabbedPanes ) {
|
for( JTabbedPane tabbedPane : tabbedPanes ) {
|
||||||
tabbedPane.addTab( "Tab 1", new Panel1() );
|
tabbedPane.addTab( "Tab 1", null, new Panel1(), "First tab." );
|
||||||
|
|
||||||
JComponent tab2 = new Panel2();
|
JComponent tab2 = new Panel2();
|
||||||
tab2.setBorder( new LineBorder( Color.magenta ) );
|
tab2.setBorder( new LineBorder( Color.magenta ) );
|
||||||
tabbedPane.addTab( "Second Tab", tab2 );
|
tabbedPane.addTab( "Second Tab", null, tab2, "This is the second tab." );
|
||||||
|
|
||||||
addTab( tabbedPane, "Disabled", "tab content 3" );
|
addTab( tabbedPane, "Disabled", "tab content 3" );
|
||||||
tabbedPane.setEnabledAt( 2, false );
|
tabbedPane.setEnabledAt( 2, false );
|
||||||
|
tabbedPane.setToolTipTextAt( 2, "Disabled tab." );
|
||||||
|
|
||||||
tabbedPane.addTab( "Tab 4", new JLabel( "non-opaque content", SwingConstants.CENTER ) );
|
tabbedPane.addTab( "Tab 4", new JLabel( "non-opaque content", SwingConstants.CENTER ) );
|
||||||
}
|
}
|
||||||
@@ -236,10 +244,7 @@ public class FlatContainerTest
|
|||||||
case "arrowButtons": value = TABBED_PANE_HIDDEN_TABS_NAVIGATION_ARROW_BUTTONS; break;
|
case "arrowButtons": value = TABBED_PANE_HIDDEN_TABS_NAVIGATION_ARROW_BUTTONS; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
tabbedPane1.putClientProperty( TABBED_PANE_HIDDEN_TABS_NAVIGATION, value );
|
putTabbedPanesClientProperty( TABBED_PANE_HIDDEN_TABS_NAVIGATION, value );
|
||||||
tabbedPane2.putClientProperty( TABBED_PANE_HIDDEN_TABS_NAVIGATION, value );
|
|
||||||
tabbedPane3.putClientProperty( TABBED_PANE_HIDDEN_TABS_NAVIGATION, value );
|
|
||||||
tabbedPane4.putClientProperty( TABBED_PANE_HIDDEN_TABS_NAVIGATION, value );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tabBackForegroundChanged() {
|
private void tabBackForegroundChanged() {
|
||||||
@@ -270,6 +275,52 @@ public class FlatContainerTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void tabsClosableChanged() {
|
||||||
|
boolean closable = tabsClosableCheckBox.isSelected();
|
||||||
|
putTabbedPanesClientProperty( TABBED_PANE_TAB_CLOSABLE, closable ? true : null );
|
||||||
|
|
||||||
|
if( closable ) {
|
||||||
|
putTabbedPanesClientProperty( TABBED_PANE_TAB_CLOSE_CALLBACK,
|
||||||
|
(BiConsumer<JTabbedPane, Integer>) (tabbedPane, tabIndex) -> {
|
||||||
|
AWTEvent e = EventQueue.getCurrentEvent();
|
||||||
|
int modifiers = (e instanceof MouseEvent) ? ((MouseEvent)e).getModifiers() : 0;
|
||||||
|
JOptionPane.showMessageDialog( this, "Closed tab '" + tabbedPane.getTitleAt( tabIndex ) + "'."
|
||||||
|
+ "\n\n(modifiers: " + MouseEvent.getMouseModifiersText( modifiers ) + ")",
|
||||||
|
"Tab Closed", JOptionPane.PLAIN_MESSAGE );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void secondTabClosableChanged() {
|
||||||
|
Boolean value = secondTabClosableCheckBox.getValue();
|
||||||
|
|
||||||
|
JTabbedPane[] tabbedPanes = new JTabbedPane[] { tabbedPane1, tabbedPane2, tabbedPane3, tabbedPane4 };
|
||||||
|
for( JTabbedPane tabbedPane : tabbedPanes ) {
|
||||||
|
Component c = tabbedPane.getComponentAt( 1 );
|
||||||
|
((JComponent)c).putClientProperty( TABBED_PANE_TAB_CLOSABLE, value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void smallerTabHeightChanged() {
|
||||||
|
Integer tabHeight = smallerTabHeightCheckBox.isSelected() ? 26 : null;
|
||||||
|
putTabbedPanesClientProperty( TABBED_PANE_TAB_HEIGHT, tabHeight );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void smallerInsetsChanged() {
|
||||||
|
Insets insets = smallerInsetsCheckBox.isSelected() ? new Insets( 2, 2, 2, 2 ) : null;
|
||||||
|
putTabbedPanesClientProperty( TABBED_PANE_TAB_INSETS, insets );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void secondTabWiderChanged() {
|
||||||
|
Insets insets = secondTabWiderCheckBox.isSelected() ? new Insets( 4, 20, 4, 20 ) : null;
|
||||||
|
|
||||||
|
JTabbedPane[] tabbedPanes = new JTabbedPane[] { tabbedPane1, tabbedPane2, tabbedPane3, tabbedPane4 };
|
||||||
|
for( JTabbedPane tabbedPane : tabbedPanes ) {
|
||||||
|
Component c = tabbedPane.getComponentAt( 1 );
|
||||||
|
((JComponent)c).putClientProperty( TABBED_PANE_TAB_INSETS, insets );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void initComponents() {
|
private void initComponents() {
|
||||||
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
// JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents
|
||||||
JPanel panel9 = new JPanel();
|
JPanel panel9 = new JPanel();
|
||||||
@@ -306,6 +357,11 @@ public class FlatContainerTest
|
|||||||
tabBackForegroundCheckBox = new JCheckBox();
|
tabBackForegroundCheckBox = new JCheckBox();
|
||||||
leadingComponentCheckBox = new JCheckBox();
|
leadingComponentCheckBox = new JCheckBox();
|
||||||
trailingComponentCheckBox = new JCheckBox();
|
trailingComponentCheckBox = new JCheckBox();
|
||||||
|
tabsClosableCheckBox = new JCheckBox();
|
||||||
|
secondTabClosableCheckBox = new TriStateCheckBox();
|
||||||
|
smallerTabHeightCheckBox = new JCheckBox();
|
||||||
|
smallerInsetsCheckBox = new JCheckBox();
|
||||||
|
secondTabWiderCheckBox = new JCheckBox();
|
||||||
CellConstraints cc = new CellConstraints();
|
CellConstraints cc = new CellConstraints();
|
||||||
|
|
||||||
//======== this ========
|
//======== this ========
|
||||||
@@ -420,6 +476,7 @@ public class FlatContainerTest
|
|||||||
"[center]" +
|
"[center]" +
|
||||||
"[]" +
|
"[]" +
|
||||||
"[]" +
|
"[]" +
|
||||||
|
"[]" +
|
||||||
"[]"));
|
"[]"));
|
||||||
|
|
||||||
//---- moreTabsCheckBox ----
|
//---- moreTabsCheckBox ----
|
||||||
@@ -518,6 +575,31 @@ public class FlatContainerTest
|
|||||||
trailingComponentCheckBox.setText("Trailing");
|
trailingComponentCheckBox.setText("Trailing");
|
||||||
trailingComponentCheckBox.addActionListener(e -> trailingComponentChanged());
|
trailingComponentCheckBox.addActionListener(e -> trailingComponentChanged());
|
||||||
panel14.add(trailingComponentCheckBox, "cell 1 3");
|
panel14.add(trailingComponentCheckBox, "cell 1 3");
|
||||||
|
|
||||||
|
//---- tabsClosableCheckBox ----
|
||||||
|
tabsClosableCheckBox.setText("Tabs closable");
|
||||||
|
tabsClosableCheckBox.addActionListener(e -> tabsClosableChanged());
|
||||||
|
panel14.add(tabsClosableCheckBox, "cell 2 3");
|
||||||
|
|
||||||
|
//---- secondTabClosableCheckBox ----
|
||||||
|
secondTabClosableCheckBox.setText("Second Tab closable");
|
||||||
|
secondTabClosableCheckBox.addActionListener(e -> secondTabClosableChanged());
|
||||||
|
panel14.add(secondTabClosableCheckBox, "cell 3 3");
|
||||||
|
|
||||||
|
//---- smallerTabHeightCheckBox ----
|
||||||
|
smallerTabHeightCheckBox.setText("Smaller tab height");
|
||||||
|
smallerTabHeightCheckBox.addActionListener(e -> smallerTabHeightChanged());
|
||||||
|
panel14.add(smallerTabHeightCheckBox, "cell 0 4 2 1");
|
||||||
|
|
||||||
|
//---- smallerInsetsCheckBox ----
|
||||||
|
smallerInsetsCheckBox.setText("Smaller insets");
|
||||||
|
smallerInsetsCheckBox.addActionListener(e -> smallerInsetsChanged());
|
||||||
|
panel14.add(smallerInsetsCheckBox, "cell 2 4");
|
||||||
|
|
||||||
|
//---- secondTabWiderCheckBox ----
|
||||||
|
secondTabWiderCheckBox.setText("Second Tab wider");
|
||||||
|
secondTabWiderCheckBox.addActionListener(e -> secondTabWiderChanged());
|
||||||
|
panel14.add(secondTabWiderCheckBox, "cell 3 4");
|
||||||
}
|
}
|
||||||
panel9.add(panel14, cc.xywh(1, 11, 3, 1));
|
panel9.add(panel14, cc.xywh(1, 11, 3, 1));
|
||||||
}
|
}
|
||||||
@@ -545,6 +627,11 @@ public class FlatContainerTest
|
|||||||
private JCheckBox tabBackForegroundCheckBox;
|
private JCheckBox tabBackForegroundCheckBox;
|
||||||
private JCheckBox leadingComponentCheckBox;
|
private JCheckBox leadingComponentCheckBox;
|
||||||
private JCheckBox trailingComponentCheckBox;
|
private JCheckBox trailingComponentCheckBox;
|
||||||
|
private JCheckBox tabsClosableCheckBox;
|
||||||
|
private TriStateCheckBox secondTabClosableCheckBox;
|
||||||
|
private JCheckBox smallerTabHeightCheckBox;
|
||||||
|
private JCheckBox smallerInsetsCheckBox;
|
||||||
|
private JCheckBox secondTabWiderCheckBox;
|
||||||
// JFormDesigner - End of variables declaration //GEN-END:variables
|
// JFormDesigner - End of variables declaration //GEN-END:variables
|
||||||
|
|
||||||
//---- class Tab1Panel ----------------------------------------------------
|
//---- class Tab1Panel ----------------------------------------------------
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ new FormModel {
|
|||||||
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
add( new FormContainer( "javax.swing.JPanel", new FormLayoutManager( class net.miginfocom.swing.MigLayout ) {
|
||||||
"$layoutConstraints": "insets 0,hidemode 3"
|
"$layoutConstraints": "insets 0,hidemode 3"
|
||||||
"$columnConstraints": "[][fill][][][fill]"
|
"$columnConstraints": "[][fill][][][fill]"
|
||||||
"$rowConstraints": "[center][][][]"
|
"$rowConstraints": "[center][][][][]"
|
||||||
} ) {
|
} ) {
|
||||||
name: "panel14"
|
name: "panel14"
|
||||||
"opaque": false
|
"opaque": false
|
||||||
@@ -327,6 +327,56 @@ new FormModel {
|
|||||||
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
"value": "cell 1 3"
|
"value": "cell 1 3"
|
||||||
} )
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "tabsClosableCheckBox"
|
||||||
|
"text": "Tabs closable"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "tabsClosableChanged", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 2 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "com.formdev.flatlaf.extras.TriStateCheckBox" ) {
|
||||||
|
name: "secondTabClosableCheckBox"
|
||||||
|
"text": "Second Tab closable"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "secondTabClosableChanged", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 3 3"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "smallerTabHeightCheckBox"
|
||||||
|
"text": "Smaller tab height"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "smallerTabHeightChanged", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 0 4 2 1"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "smallerInsetsCheckBox"
|
||||||
|
"text": "Smaller insets"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "smallerInsetsChanged", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 2 4"
|
||||||
|
} )
|
||||||
|
add( new FormComponent( "javax.swing.JCheckBox" ) {
|
||||||
|
name: "secondTabWiderCheckBox"
|
||||||
|
"text": "Second Tab wider"
|
||||||
|
auxiliary() {
|
||||||
|
"JavaCodeGenerator.variableLocal": false
|
||||||
|
}
|
||||||
|
addEvent( new FormEvent( "java.awt.event.ActionListener", "actionPerformed", "secondTabWiderChanged", false ) )
|
||||||
|
}, new FormLayoutConstraints( class net.miginfocom.layout.CC ) {
|
||||||
|
"value": "cell 3 4"
|
||||||
|
} )
|
||||||
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
|
}, new FormLayoutConstraints( class com.jgoodies.forms.layout.CellConstraints ) {
|
||||||
"gridY": 11
|
"gridY": 11
|
||||||
"gridWidth": 3
|
"gridWidth": 3
|
||||||
|
|||||||
@@ -284,6 +284,18 @@ TabbedPane.focusColor=#ddd
|
|||||||
TabbedPane.tabSeparatorColor=#00f
|
TabbedPane.tabSeparatorColor=#00f
|
||||||
TabbedPane.contentAreaColor=#bbb
|
TabbedPane.contentAreaColor=#bbb
|
||||||
|
|
||||||
|
TabbedPane.closeSize=16,16
|
||||||
|
TabbedPane.closeArc=999
|
||||||
|
TabbedPane.closeCrossPlainSize={float}12
|
||||||
|
TabbedPane.closeCrossFilledSize={float}6.5
|
||||||
|
TabbedPane.closeCrossLineWidth={float}2
|
||||||
|
#TabbedPane.closeBackground=#faa
|
||||||
|
TabbedPane.closeForeground=#f00
|
||||||
|
TabbedPane.closeHoverBackground=#a00
|
||||||
|
TabbedPane.closeHoverForeground=#fff
|
||||||
|
TabbedPane.closePressedBackground=#0f0
|
||||||
|
TabbedPane.closePressedForeground=#000
|
||||||
|
|
||||||
|
|
||||||
#---- Table ----
|
#---- Table ----
|
||||||
|
|
||||||
|
|||||||
@@ -634,6 +634,17 @@ SplitPaneDivider.oneTouchHoverArrowColor
|
|||||||
SplitPaneUI
|
SplitPaneUI
|
||||||
TabbedPane.ancestorInputMap
|
TabbedPane.ancestorInputMap
|
||||||
TabbedPane.background
|
TabbedPane.background
|
||||||
|
TabbedPane.closeArc
|
||||||
|
TabbedPane.closeCrossFilledSize
|
||||||
|
TabbedPane.closeCrossLineWidth
|
||||||
|
TabbedPane.closeCrossPlainSize
|
||||||
|
TabbedPane.closeForeground
|
||||||
|
TabbedPane.closeHoverBackground
|
||||||
|
TabbedPane.closeHoverForeground
|
||||||
|
TabbedPane.closeIcon
|
||||||
|
TabbedPane.closePressedBackground
|
||||||
|
TabbedPane.closePressedForeground
|
||||||
|
TabbedPane.closeSize
|
||||||
TabbedPane.contentAreaColor
|
TabbedPane.contentAreaColor
|
||||||
TabbedPane.contentOpaque
|
TabbedPane.contentOpaque
|
||||||
TabbedPane.contentSeparatorHeight
|
TabbedPane.contentSeparatorHeight
|
||||||
|
|||||||
Reference in New Issue
Block a user