mirror of
https://github.com/JFormDesigner/FlatLaf.git
synced 2025-12-06 22:10:54 +03:00
TabbedPane: fixed "endless" layouting and repainting when using nested tabbed panes (top and bottom tab placement) and RSyntaxTextArea (with enabled line-wrapping) as tab content (see https://github.com/skylot/jadx/issues/2030)
instead of using `BasicTabbedPaneUI.TabbedPaneLayout.layoutContainer()`, now layouting all components ourself and avoid double moving/resizing of some components
This commit is contained in:
@@ -28,12 +28,16 @@ FlatLaf Change Log
|
|||||||
colors. (issue #780)
|
colors. (issue #780)
|
||||||
- TableHeader: No longer temporary replace header cell renderer while painting.
|
- TableHeader: No longer temporary replace header cell renderer while painting.
|
||||||
This avoids a `StackOverflowError` in case that custom renderer does this too.
|
This avoids a `StackOverflowError` in case that custom renderer does this too.
|
||||||
(see [NetBeans issue #6835](https://github.com/apache/netbeans/issues/6835)).
|
(see [NetBeans issue #6835](https://github.com/apache/netbeans/issues/6835))
|
||||||
This also improves compatibility with custom table header implementations.
|
This also improves compatibility with custom table header implementations.
|
||||||
- TabbedPane:
|
- TabbedPane:
|
||||||
- Avoid unnecessary repainting whole tabbed pane content area when layouting
|
- Avoid unnecessary repainting whole tabbed pane content area when layouting
|
||||||
leading/trailing components.
|
leading/trailing components.
|
||||||
- Avoid unnecessary repainting of selected tab on temporary changes.
|
- Avoid unnecessary repainting of selected tab on temporary changes.
|
||||||
|
- Fixed "endless" layouting and repainting when using nested tabbed panes (top
|
||||||
|
and bottom tab placement) and RSyntaxTextArea (with enabled line-wrapping)
|
||||||
|
as tab content. (see
|
||||||
|
[jadx issue #2030](https://github.com/skylot/jadx/issues/2030))
|
||||||
- Fixed broken rendering after resizing window to minimum size and then
|
- Fixed broken rendering after resizing window to minimum size and then
|
||||||
increasing size again. (issue #767)
|
increasing size again. (issue #767)
|
||||||
|
|
||||||
|
|||||||
@@ -2230,11 +2230,6 @@ debug*/
|
|||||||
// fix x location in rects
|
// fix x location in rects
|
||||||
rects[i].x += sx;
|
rects[i].x += sx;
|
||||||
rects[i].y += sy;
|
rects[i].y += sy;
|
||||||
|
|
||||||
// fix tab component location
|
|
||||||
Component c = tabPane.getTabComponentAt( i );
|
|
||||||
if( c != null )
|
|
||||||
c.setLocation( c.getX() + sx, c.getY() + sy );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2242,11 +2237,6 @@ debug*/
|
|||||||
int rsw = sw / rects.length;
|
int rsw = sw / rects.length;
|
||||||
int x = rects[0].x - (leftToRight ? 0 : rsw);
|
int x = rects[0].x - (leftToRight ? 0 : rsw);
|
||||||
for( int i = 0; i < rects.length; i++ ) {
|
for( int i = 0; i < rects.length; i++ ) {
|
||||||
// fix tab component location
|
|
||||||
Component c = tabPane.getTabComponentAt( i );
|
|
||||||
if( c != null )
|
|
||||||
c.setLocation( x + (c.getX() - rects[i].x) + (rsw / 2), c.getY() );
|
|
||||||
|
|
||||||
// fix x location and width in rects
|
// fix x location and width in rects
|
||||||
rects[i].x = x;
|
rects[i].x = x;
|
||||||
rects[i].width += rsw;
|
rects[i].width += rsw;
|
||||||
@@ -2268,11 +2258,6 @@ debug*/
|
|||||||
int rsh = sh / rects.length;
|
int rsh = sh / rects.length;
|
||||||
int y = rects[0].y;
|
int y = rects[0].y;
|
||||||
for( int i = 0; i < rects.length; i++ ) {
|
for( int i = 0; i < rects.length; i++ ) {
|
||||||
// fix tab component location
|
|
||||||
Component c = tabPane.getTabComponentAt( i );
|
|
||||||
if( c != null )
|
|
||||||
c.setLocation( c.getX(), y + (c.getY() - rects[i].y) + (rsh / 2) );
|
|
||||||
|
|
||||||
// fix y location and height in rects
|
// fix y location and height in rects
|
||||||
rects[i].y = y;
|
rects[i].y = y;
|
||||||
rects[i].height += rsh;
|
rects[i].height += rsh;
|
||||||
@@ -3218,6 +3203,29 @@ debug*/
|
|||||||
|
|
||||||
//---- class FlatTabbedPaneLayout -----------------------------------------
|
//---- class FlatTabbedPaneLayout -----------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Layout manager for wrap tab layout policy (and base class for scroll tab layout policy).
|
||||||
|
* <p>
|
||||||
|
* Component hierarchy for wrap tab layout policy:
|
||||||
|
* <pre>{@code
|
||||||
|
* JTabbedPane
|
||||||
|
* +- 1...n tab content components
|
||||||
|
* +- (optional) BasicTabbedPaneUI.TabContainer (extends JPanel)
|
||||||
|
* | +- 1..n tab components (shown in tab area)
|
||||||
|
* +- (optional) ContainerUIResource (extends JPanel)
|
||||||
|
* | +- leading component
|
||||||
|
* +- (optional) ContainerUIResource (extends JPanel)
|
||||||
|
* +- trailing component
|
||||||
|
* }</pre>
|
||||||
|
* <p>
|
||||||
|
* Instead of using {@code super.layoutContainer(Container)} and fixing some
|
||||||
|
* component bounds, this class implements {@code layoutContainer(Container)}
|
||||||
|
* and moves/resizes components only once.
|
||||||
|
* This avoids that some components are moved/resized twice, which would unnecessary
|
||||||
|
* repaint and relayout tabbed pane. In some special case this resulted in
|
||||||
|
* "endless" layouting and repainting when using nested tabbed panes (top and
|
||||||
|
* bottom tab placement) and RSyntaxTextArea (with enabled line-wrapping) as tab content.
|
||||||
|
*/
|
||||||
protected class FlatTabbedPaneLayout
|
protected class FlatTabbedPaneLayout
|
||||||
extends TabbedPaneLayout
|
extends TabbedPaneLayout
|
||||||
{
|
{
|
||||||
@@ -3252,6 +3260,10 @@ debug*/
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate preferred size of the tab area.
|
||||||
|
* Used only if {@link #isContentEmpty()} returns {@code true}.
|
||||||
|
*/
|
||||||
protected Dimension calculateTabAreaSize() {
|
protected Dimension calculateTabAreaSize() {
|
||||||
int tabPlacement = tabPane.getTabPlacement();
|
int tabPlacement = tabPane.getTabPlacement();
|
||||||
boolean horizontal = isHorizontalTabPlacement( tabPlacement );
|
boolean horizontal = isHorizontalTabPlacement( tabPlacement );
|
||||||
@@ -3286,15 +3298,44 @@ debug*/
|
|||||||
height + insets.bottom + insets.top + tabAreaInsets.top + tabAreaInsets.bottom );
|
height + insets.bottom + insets.top + tabAreaInsets.top + tabAreaInsets.bottom );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings( "deprecation" )
|
||||||
@Override
|
@Override
|
||||||
public void layoutContainer( Container parent ) {
|
public void layoutContainer( Container parent ) {
|
||||||
inBasicLayoutContainer = true;
|
setRolloverTab( -1 );
|
||||||
try {
|
calculateLayoutInfo();
|
||||||
super.layoutContainer( parent );
|
|
||||||
} finally {
|
// update visible component
|
||||||
inBasicLayoutContainer = false;
|
boolean shouldChangeFocus = false;
|
||||||
|
int selectedIndex = tabPane.getSelectedIndex();
|
||||||
|
if( selectedIndex >= 0 ) {
|
||||||
|
// change visible component only if tab content is not null
|
||||||
|
// (see comments in JTabbedPane.fireStateChanged()
|
||||||
|
// and in BasicTabbedPaneUI.TabbedPaneLayout.layoutContainer())
|
||||||
|
Component oldComp = getVisibleComponent();
|
||||||
|
Component newComp = tabPane.getComponentAt( selectedIndex );
|
||||||
|
if( newComp != null && newComp != oldComp ) {
|
||||||
|
shouldChangeFocus = (SwingUtilities.findFocusOwner( oldComp ) != null);
|
||||||
|
setVisibleComponent( newComp );
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
setVisibleComponent( null );
|
||||||
|
|
||||||
|
// layout
|
||||||
|
layoutContainerImpl();
|
||||||
|
|
||||||
|
// for compatibility with super class; usually not done here
|
||||||
|
// because already done in JTabbedPane.fireStateChanged()
|
||||||
|
if( shouldChangeFocus ) {
|
||||||
|
// use action because BasicTabbedPaneUI.requestFocusForVisibleComponent()
|
||||||
|
// and SwingUtilities2.tabbedPaneChangeFocusTo() are internal methods
|
||||||
|
Action action = tabPane.getActionMap().get( "requestFocusForVisibleComponent" );
|
||||||
|
if( action != null )
|
||||||
|
action.actionPerformed( new ActionEvent( tabPane, ActionEvent.ACTION_PERFORMED, null ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3.3 */
|
||||||
|
protected void layoutContainerImpl() {
|
||||||
int tabPlacement = tabPane.getTabPlacement();
|
int tabPlacement = tabPane.getTabPlacement();
|
||||||
int tabAreaAlignment = getTabAreaAlignment();
|
int tabAreaAlignment = getTabAreaAlignment();
|
||||||
Insets tabAreaInsets = getRealTabAreaInsets( tabPlacement );
|
Insets tabAreaInsets = getRealTabAreaInsets( tabPlacement );
|
||||||
@@ -3315,11 +3356,149 @@ debug*/
|
|||||||
// layout top and bottom components
|
// layout top and bottom components
|
||||||
layoutTopAndBottomComponents( tr, tabAreaAlignment, tabAreaInsets, (runCount == 1), true );
|
layoutTopAndBottomComponents( tr, tabAreaAlignment, tabAreaInsets, (runCount == 1), true );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// layout content area components
|
||||||
|
// (must be done after layouting tab area, which updates tab rectangles,
|
||||||
|
// which are used to layout tab components in layoutTabComponents())
|
||||||
|
layoutChildComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle getTabAreaLayoutBounds( int tabPlacement, Insets tabAreaInsets ) {
|
/** @since 3.3 */
|
||||||
|
protected void layoutChildComponents() {
|
||||||
|
if( tabPane.getComponentCount() == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
Rectangle contentAreaBounds = getContentAreaLayoutBounds( tabPane.getTabPlacement(), tabAreaInsets );
|
||||||
|
for( Component c : tabPane.getComponents() )
|
||||||
|
layoutChildComponent( c, contentAreaBounds );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @since 3.3 */
|
||||||
|
protected void layoutChildComponent( Component c, Rectangle contentAreaBounds ) {
|
||||||
|
if( c == leadingComponent || c == trailingComponent )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( isTabContainer( c ) )
|
||||||
|
layoutTabContainer( c );
|
||||||
|
else
|
||||||
|
c.setBounds( contentAreaBounds );
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isTabContainer( Component c ) {
|
||||||
|
return c.getClass().getName().equals( "javax.swing.plaf.basic.BasicTabbedPaneUI$TabContainer" );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Layouts container used for custom components in tabs.
|
||||||
|
*/
|
||||||
|
private void layoutTabContainer( Component tabContainer ) {
|
||||||
|
int tabPlacement = tabPane.getTabPlacement();
|
||||||
Rectangle bounds = tabPane.getBounds();
|
Rectangle bounds = tabPane.getBounds();
|
||||||
Insets insets = tabPane.getInsets();
|
Insets insets = tabPane.getInsets();
|
||||||
|
Insets contentInsets = getContentBorderInsets( tabPlacement );
|
||||||
|
|
||||||
|
boolean horizontal = isHorizontalTabPlacement( tabPlacement );
|
||||||
|
int tabAreaWidth = !horizontal ? calculateTabAreaWidth( tabPlacement, runCount, maxTabWidth ) : 0;
|
||||||
|
int tabAreaHeight = horizontal ? calculateTabAreaHeight( tabPlacement, runCount, maxTabHeight ) : 0;
|
||||||
|
int w = (tabAreaWidth != 0)
|
||||||
|
? tabAreaWidth + insets.left + insets.right + contentInsets.left + contentInsets.right
|
||||||
|
: bounds.width;
|
||||||
|
int h = (tabAreaHeight != 0)
|
||||||
|
? tabAreaHeight + insets.top + insets.bottom + contentInsets.top + contentInsets.bottom
|
||||||
|
: bounds.height;
|
||||||
|
|
||||||
|
int x = (tabPlacement == RIGHT) ? bounds.width - w : 0;
|
||||||
|
int y = (tabPlacement == BOTTOM) ? bounds.height - h : 0;
|
||||||
|
|
||||||
|
tabContainer.setBounds( x, y, w, h );
|
||||||
|
|
||||||
|
// layout tab components in tab container
|
||||||
|
layoutTabComponents( tabContainer );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Layouts custom components in tabs.
|
||||||
|
*/
|
||||||
|
void layoutTabComponents( Component tabContainer ) {
|
||||||
|
if( tabContainer instanceof Container && ((Container)tabContainer).getComponentCount() == 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
int tabPlacement = tabPane.getTabPlacement();
|
||||||
|
int selectedTabIndex = tabPane.getSelectedIndex();
|
||||||
|
Rectangle r = new Rectangle();
|
||||||
|
int deltaX = -tabContainer.getX();
|
||||||
|
int deltaY = -tabContainer.getY();
|
||||||
|
|
||||||
|
if( isScrollTabLayout() ) {
|
||||||
|
// convert delta x,y from JTabbedPane coordinate space to ScrollableTabPanel coordinate space
|
||||||
|
Point viewPosition = tabViewport.getViewPosition();
|
||||||
|
deltaX = deltaX - tabViewport.getX() + viewPosition.x;
|
||||||
|
deltaY = deltaY - tabViewport.getY() + viewPosition.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tabCount = tabPane.getTabCount();
|
||||||
|
for( int i = 0; i < tabCount; i++ ) {
|
||||||
|
Component c = tabPane.getTabComponentAt( i );
|
||||||
|
if( c == null )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// outer bounds
|
||||||
|
Rectangle tabBounds = getTabBounds( i, r );
|
||||||
|
Insets tabInsets = getTabInsets( tabPlacement, i );
|
||||||
|
int ox = tabBounds.x + tabInsets.left + deltaX;
|
||||||
|
int oy = tabBounds.y + tabInsets.top + deltaY;
|
||||||
|
int ow = tabBounds.width - tabInsets.left - tabInsets.right;
|
||||||
|
int oh = tabBounds.height - tabInsets.top - tabInsets.bottom;
|
||||||
|
|
||||||
|
// center
|
||||||
|
Dimension prefSize = c.getPreferredSize();
|
||||||
|
int x = ox + ((ow - prefSize.width) / 2);
|
||||||
|
int y = oy + ((oh - prefSize.height) / 2);
|
||||||
|
|
||||||
|
// shift
|
||||||
|
boolean selected = (i == selectedTabIndex);
|
||||||
|
x += getTabLabelShiftX( tabPlacement, i, selected );
|
||||||
|
y += getTabLabelShiftY( tabPlacement, i, selected );
|
||||||
|
|
||||||
|
c.setBounds( x, y, prefSize.width, prefSize.height );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns bounds for content components.
|
||||||
|
*/
|
||||||
|
Rectangle getContentAreaLayoutBounds( int tabPlacement, Insets tabAreaInsets ) {
|
||||||
|
int tabPaneWidth = tabPane.getWidth();
|
||||||
|
int tabPaneHeight = tabPane.getHeight();
|
||||||
|
Insets insets = tabPane.getInsets();
|
||||||
|
Insets contentInsets = getContentBorderInsets( tabPlacement );
|
||||||
|
|
||||||
|
boolean horizontal = isHorizontalTabPlacement( tabPlacement );
|
||||||
|
int tabAreaWidth = !horizontal ? calculateTabAreaWidth( tabPlacement, runCount, maxTabWidth ) : 0;
|
||||||
|
int tabAreaHeight = horizontal ? calculateTabAreaHeight( tabPlacement, runCount, maxTabHeight ) : 0;
|
||||||
|
|
||||||
|
Rectangle cr = new Rectangle();
|
||||||
|
cr.x = insets.left + contentInsets.left;
|
||||||
|
cr.y = insets.top + contentInsets.top;
|
||||||
|
cr.width = tabPaneWidth - insets.left - insets.right - contentInsets.left - contentInsets.right - tabAreaWidth;
|
||||||
|
cr.height = tabPaneHeight - insets.top - insets.bottom - contentInsets.top - contentInsets.bottom - tabAreaHeight;
|
||||||
|
if( tabPlacement == TOP )
|
||||||
|
cr.y += tabAreaHeight;
|
||||||
|
else if( tabPlacement == LEFT )
|
||||||
|
cr.x += tabAreaWidth;
|
||||||
|
return cr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns bounds for leading/trailing components and tab area.
|
||||||
|
*
|
||||||
|
* Note: Returns bounds for first tabs row only.
|
||||||
|
* For multi-rows tabs in wrap mode, the returned bounds does not include full tab area.
|
||||||
|
*/
|
||||||
|
Rectangle getTabAreaLayoutBounds( int tabPlacement, Insets tabAreaInsets ) {
|
||||||
|
int tabPaneWidth = tabPane.getWidth();
|
||||||
|
int tabPaneHeight = tabPane.getHeight();
|
||||||
|
Insets insets = tabPane.getInsets();
|
||||||
|
|
||||||
Rectangle tr = new Rectangle();
|
Rectangle tr = new Rectangle();
|
||||||
if( tabPlacement == TOP || tabPlacement == BOTTOM ) {
|
if( tabPlacement == TOP || tabPlacement == BOTTOM ) {
|
||||||
@@ -3334,8 +3513,8 @@ debug*/
|
|||||||
tr.x = insets.left;
|
tr.x = insets.left;
|
||||||
tr.y = (tabPlacement == TOP)
|
tr.y = (tabPlacement == TOP)
|
||||||
? insets.top + tabAreaInsets.top
|
? insets.top + tabAreaInsets.top
|
||||||
: (bounds.height - insets.bottom - tabAreaInsets.bottom - tabAreaHeight);
|
: (tabPaneHeight - insets.bottom - tabAreaInsets.bottom - tabAreaHeight);
|
||||||
tr.width = bounds.width - insets.left - insets.right;
|
tr.width = tabPaneWidth - insets.left - insets.right;
|
||||||
tr.height = tabAreaHeight;
|
tr.height = tabAreaHeight;
|
||||||
} else { // LEFT and RIGHT tab placement
|
} else { // LEFT and RIGHT tab placement
|
||||||
// tab area width (maxTabWidth is zero if tab count is zero)
|
// tab area width (maxTabWidth is zero if tab count is zero)
|
||||||
@@ -3346,10 +3525,10 @@ debug*/
|
|||||||
// tab area bounds
|
// tab area bounds
|
||||||
tr.x = (tabPlacement == LEFT)
|
tr.x = (tabPlacement == LEFT)
|
||||||
? insets.left + tabAreaInsets.left
|
? insets.left + tabAreaInsets.left
|
||||||
: (bounds.width - insets.right - tabAreaInsets.right - tabAreaWidth);
|
: (tabPaneWidth - insets.right - tabAreaInsets.right - tabAreaWidth);
|
||||||
tr.y = insets.top;
|
tr.y = insets.top;
|
||||||
tr.width = tabAreaWidth;
|
tr.width = tabAreaWidth;
|
||||||
tr.height = bounds.height - insets.top - insets.bottom;
|
tr.height = tabPaneHeight - insets.top - insets.bottom;
|
||||||
}
|
}
|
||||||
return tr;
|
return tr;
|
||||||
}
|
}
|
||||||
@@ -3468,7 +3647,32 @@ debug*/
|
|||||||
/**
|
/**
|
||||||
* 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
|
* Component hierarchy for scroll tab layout policy:
|
||||||
|
* <pre>{@code
|
||||||
|
* JTabbedPane
|
||||||
|
* +- 1...n tab content components
|
||||||
|
* +- BasicTabbedPaneUI.ScrollableTabViewport (extends JViewport)
|
||||||
|
* | +- BasicTabbedPaneUI.ScrollableTabPanel (extends JPanel)
|
||||||
|
* | +- (optional) BasicTabbedPaneUI.TabContainer (extends JPanel)
|
||||||
|
* | +- 1..n tab components (shown in tab area)
|
||||||
|
* +- FlatScrollableTabButton (scroll forward)
|
||||||
|
* +- FlatScrollableTabButton (scroll backward)
|
||||||
|
* +- FlatMoreTabsButton
|
||||||
|
* +- (optional) ContainerUIResource (extends JPanel)
|
||||||
|
* | +- leading component
|
||||||
|
* +- (optional) ContainerUIResource (extends JPanel)
|
||||||
|
* +- trailing component
|
||||||
|
* }</pre>
|
||||||
|
* <p>
|
||||||
|
* Instead of using {@code super.layoutContainer(Container)} and fixing some
|
||||||
|
* component bounds, this class implements {@code layoutContainer(Container)}
|
||||||
|
* and moves/resizes components only once.
|
||||||
|
* This avoids that some components are moved/resized twice, which would unnecessary
|
||||||
|
* repaint and relayout tabbed pane. In some special case this resulted in
|
||||||
|
* "endless" layouting and repainting when using nested tabbed panes (top and
|
||||||
|
* bottom tab placement) and RSyntaxTextArea (with enabled line-wrapping) as tab content.
|
||||||
|
* <p>
|
||||||
|
* Although this class delegates nearly all methods to the original layout manager
|
||||||
* {@code 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}
|
||||||
@@ -3529,20 +3733,11 @@ debug*/
|
|||||||
delegate.removeLayoutComponent( comp );
|
delegate.removeLayoutComponent( comp );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3.3 */
|
||||||
@Override
|
@Override
|
||||||
public void layoutContainer( Container parent ) {
|
protected void layoutContainerImpl() {
|
||||||
// delegate to original layout manager and let it layout tabs and buttons
|
// layout content area components
|
||||||
//
|
layoutChildComponents();
|
||||||
// runWithOriginalLayoutManager() is necessary for correct locations
|
|
||||||
// of tab components layed out in TabbedPaneLayout.layoutTabComponents()
|
|
||||||
runWithOriginalLayoutManager( () -> {
|
|
||||||
inBasicLayoutContainer = true;
|
|
||||||
try {
|
|
||||||
delegate.layoutContainer( parent );
|
|
||||||
} finally {
|
|
||||||
inBasicLayoutContainer = false;
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
int tabsPopupPolicy = getTabsPopupPolicy();
|
int tabsPopupPolicy = getTabsPopupPolicy();
|
||||||
int scrollButtonsPolicy = getScrollButtonsPolicy();
|
int scrollButtonsPolicy = getScrollButtonsPolicy();
|
||||||
@@ -3737,6 +3932,17 @@ debug*/
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// layout tab components in tab container
|
||||||
|
Component view = tabViewport.getView();
|
||||||
|
if( view instanceof Container && ((Container)view).getComponentCount() > 0 ) {
|
||||||
|
for( Component c : ((Container)view).getComponents() ) {
|
||||||
|
if( isTabContainer( c ) ) {
|
||||||
|
layoutTabComponents( c );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// show/hide viewport and buttons
|
// show/hide viewport and buttons
|
||||||
tabViewport.setVisible( rects.length > 0 );
|
tabViewport.setVisible( rects.length > 0 );
|
||||||
moreTabsButton.setVisible( moreTabsButtonVisible );
|
moreTabsButton.setVisible( moreTabsButtonVisible );
|
||||||
@@ -3745,6 +3951,15 @@ debug*/
|
|||||||
|
|
||||||
scrollBackwardButtonPrefSize = backwardButton.getPreferredSize();
|
scrollBackwardButtonPrefSize = backwardButton.getPreferredSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @since 3.3 */
|
||||||
|
@Override
|
||||||
|
protected void layoutChildComponent( Component c, Rectangle contentAreaBounds ) {
|
||||||
|
if( c == tabViewport || c instanceof FlatTabAreaButton || c == leadingComponent || c == trailingComponent )
|
||||||
|
return;
|
||||||
|
|
||||||
|
c.setBounds( contentAreaBounds );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//---- class RunWithOriginalLayoutManagerDelegateAction -------------------
|
//---- class RunWithOriginalLayoutManagerDelegateAction -------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user