ToolBar: do not change floatable if it was changed from application code (issue #1075)

This commit is contained in:
Karl Tauber
2026-01-13 12:35:49 +01:00
parent 7680c3a817
commit ea2a985481
4 changed files with 87 additions and 82 deletions

View File

@@ -7,6 +7,7 @@ FlatLaf Change Log
#1068) #1068)
- Popup: Fixed scrolling popup painting issue on Windows 10 when a glass pane is - Popup: Fixed scrolling popup painting issue on Windows 10 when a glass pane is
visible and frame is maximized. (issue #1071) visible and frame is maximized. (issue #1071)
- ToolBar: Grip disappeared when switching between Look and Feels. (issue #1075)
## 3.7 ## 3.7

View File

@@ -34,7 +34,6 @@ import java.awt.event.ComponentListener;
import java.awt.event.FocusEvent; import java.awt.event.FocusEvent;
import java.awt.event.FocusListener; import java.awt.event.FocusListener;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.util.Map; import java.util.Map;
import javax.swing.Action; import javax.swing.Action;
@@ -66,6 +65,7 @@ import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.icons.FlatCheckBoxIcon; import com.formdev.flatlaf.icons.FlatCheckBoxIcon;
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable; import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
import com.formdev.flatlaf.ui.FlatUIUtils.FlatPropertyWatcher;
import com.formdev.flatlaf.util.Graphics2DProxy; import com.formdev.flatlaf.util.Graphics2DProxy;
import com.formdev.flatlaf.util.HiDPIUtils; import com.formdev.flatlaf.util.HiDPIUtils;
import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.LoggingFacade;
@@ -189,29 +189,26 @@ public class FlatTableUI
if( rowHeight > 0 ) if( rowHeight > 0 )
LookAndFeel.installProperty( table, "rowHeight", UIScale.scale( rowHeight ) ); LookAndFeel.installProperty( table, "rowHeight", UIScale.scale( rowHeight ) );
FlatTablePropertyWatcher watcher = FlatTablePropertyWatcher.get( table ); if( !showHorizontalLines ) {
if( watcher != null ) FlatPropertyWatcher.runIfNotChanged( table, "showHorizontalLines", () -> {
watcher.enabled = false; oldShowHorizontalLines = table.getShowHorizontalLines();
table.setShowHorizontalLines( false );
if( !showHorizontalLines && (watcher == null || !watcher.showHorizontalLinesChanged) ) { } );
oldShowHorizontalLines = table.getShowHorizontalLines();
table.setShowHorizontalLines( false );
} }
if( !showVerticalLines && (watcher == null || !watcher.showVerticalLinesChanged) ) { if( !showVerticalLines ) {
oldShowVerticalLines = table.getShowVerticalLines(); FlatPropertyWatcher.runIfNotChanged( table, "showVerticalLines", () -> {
table.setShowVerticalLines( false ); oldShowVerticalLines = table.getShowVerticalLines();
table.setShowVerticalLines( false );
} );
} }
if( intercellSpacing != null && (watcher == null || !watcher.intercellSpacingChanged) ) { if( intercellSpacing != null ) {
oldIntercellSpacing = table.getIntercellSpacing(); FlatPropertyWatcher.runIfNotChanged( table, "rowMargin", () -> {
table.setIntercellSpacing( intercellSpacing ); oldIntercellSpacing = table.getIntercellSpacing();
table.setIntercellSpacing( intercellSpacing );
} );
} }
if( watcher != null )
watcher.enabled = true;
else
table.addPropertyChangeListener( new FlatTablePropertyWatcher() );
// install boolean renderer // install boolean renderer
oldBooleanRenderer = table.getDefaultRenderer( Boolean.class ); oldBooleanRenderer = table.getDefaultRenderer( Boolean.class );
if( oldBooleanRenderer instanceof UIResource ) if( oldBooleanRenderer instanceof UIResource )
@@ -231,25 +228,24 @@ public class FlatTableUI
oldStyleValues = null; oldStyleValues = null;
FlatTablePropertyWatcher watcher = FlatTablePropertyWatcher.get( table );
if( watcher != null )
watcher.enabled = false;
// restore old show horizontal/vertical lines (if not modified) // restore old show horizontal/vertical lines (if not modified)
if( !showHorizontalLines && oldShowHorizontalLines && !table.getShowHorizontalLines() && if( !showHorizontalLines && oldShowHorizontalLines && !table.getShowHorizontalLines() ) {
(watcher == null || !watcher.showHorizontalLinesChanged) ) FlatPropertyWatcher.runIfNotChanged( table, "showHorizontalLines", () -> {
table.setShowHorizontalLines( true ); table.setShowHorizontalLines( true );
if( !showVerticalLines && oldShowVerticalLines && !table.getShowVerticalLines() && } );
(watcher == null || !watcher.showVerticalLinesChanged) ) }
table.setShowVerticalLines( true ); if( !showVerticalLines && oldShowVerticalLines && !table.getShowVerticalLines() ) {
FlatPropertyWatcher.runIfNotChanged( table, "showVerticalLines", () -> {
table.setShowVerticalLines( true );
} );
}
// restore old intercell spacing (if not modified) // restore old intercell spacing (if not modified)
if( intercellSpacing != null && table.getIntercellSpacing().equals( intercellSpacing ) && if( intercellSpacing != null && table.getIntercellSpacing().equals( intercellSpacing ) ) {
(watcher == null || !watcher.intercellSpacingChanged) ) FlatPropertyWatcher.runIfNotChanged( table, "rowMargin", () -> {
table.setIntercellSpacing( oldIntercellSpacing ); table.setIntercellSpacing( oldIntercellSpacing );
} );
if( watcher != null ) }
watcher.enabled = true;
// uninstall boolean renderer // uninstall boolean renderer
if( table.getDefaultRenderer( Boolean.class ) instanceof FlatBooleanRenderer ) { if( table.getDefaultRenderer( Boolean.class ) instanceof FlatBooleanRenderer ) {
@@ -938,48 +934,6 @@ public class FlatTableUI
} }
} }
//---- class FlatTablePropertyWatcher -------------------------------------
/**
* Listener that watches for change of some table properties from application code.
* This information is used in {@link FlatTableUI#installDefaults()} and
* {@link FlatTableUI#uninstallDefaults()} to decide whether FlatLaf modifies those properties.
* If they are modified in application code, FlatLaf no longer changes them.
*
* The listener is added once for each table, but never removed.
* So switching Laf/theme reuses existing listener.
*/
private static class FlatTablePropertyWatcher
implements PropertyChangeListener
{
boolean enabled = true;
boolean showHorizontalLinesChanged;
boolean showVerticalLinesChanged;
boolean intercellSpacingChanged;
static FlatTablePropertyWatcher get( JTable table ) {
for( PropertyChangeListener l : table.getPropertyChangeListeners() ) {
if( l instanceof FlatTablePropertyWatcher )
return (FlatTablePropertyWatcher) l;
}
return null;
}
//---- interface PropertyChangeListener ----
@Override
public void propertyChange( PropertyChangeEvent e ) {
if( !enabled )
return;
switch( e.getPropertyName() ) {
case "showHorizontalLines": showHorizontalLinesChanged = true; break;
case "showVerticalLines": showVerticalLinesChanged = true; break;
case "rowMargin": intercellSpacingChanged = true; break;
}
}
}
//---- class FlatBooleanRenderer ------------------------------------------ //---- class FlatBooleanRenderer ------------------------------------------
private static class FlatBooleanRenderer private static class FlatBooleanRenderer

View File

@@ -47,6 +47,7 @@ import javax.swing.plaf.basic.BasicToolBarUI;
import com.formdev.flatlaf.FlatClientProperties; import com.formdev.flatlaf.FlatClientProperties;
import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable; import com.formdev.flatlaf.ui.FlatStylingSupport.Styleable;
import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI; import com.formdev.flatlaf.ui.FlatStylingSupport.StyleableUI;
import com.formdev.flatlaf.ui.FlatUIUtils.FlatPropertyWatcher;
import com.formdev.flatlaf.util.HiDPIUtils; import com.formdev.flatlaf.util.HiDPIUtils;
import com.formdev.flatlaf.util.LoggingFacade; import com.formdev.flatlaf.util.LoggingFacade;
import com.formdev.flatlaf.util.UIScale; import com.formdev.flatlaf.util.UIScale;
@@ -144,11 +145,13 @@ public class FlatToolBarUI
hoverButtonGroupBackground = UIManager.getColor( "ToolBar.hoverButtonGroupBackground" ); hoverButtonGroupBackground = UIManager.getColor( "ToolBar.hoverButtonGroupBackground" );
// floatable // floatable
oldFloatable = null;
if( !UIManager.getBoolean( "ToolBar.floatable" ) ) { if( !UIManager.getBoolean( "ToolBar.floatable" ) ) {
oldFloatable = toolBar.isFloatable(); FlatPropertyWatcher.runIfNotChanged( toolBar, "floatable", () -> {
toolBar.setFloatable( false ); oldFloatable = toolBar.isFloatable();
} else toolBar.setFloatable( false );
oldFloatable = null; } );
}
} }
@Override @Override
@@ -158,7 +161,9 @@ public class FlatToolBarUI
hoverButtonGroupBackground = null; hoverButtonGroupBackground = null;
if( oldFloatable != null ) { if( oldFloatable != null ) {
toolBar.setFloatable( oldFloatable ); FlatPropertyWatcher.runIfNotChanged( toolBar, "floatable", () -> {
toolBar.setFloatable( oldFloatable );
} );
oldFloatable = null; oldFloatable = null;
} }
} }

View File

@@ -44,6 +44,8 @@ import java.awt.geom.Path2D;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D; import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D; import java.awt.geom.RoundRectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.IdentityHashMap; import java.util.IdentityHashMap;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import java.util.function.Predicate; import java.util.function.Predicate;
@@ -1413,4 +1415,47 @@ debug*/
return delegate.isBorderOpaque(); return delegate.isBorderOpaque();
} }
} }
//---- class FlatPropertyWatcher ------------------------------------------
/**
* Listener that watches for change of a property from application code.
* This information can be used to decide whether FlatLaf modifies the property.
* If it is modified in application code, FlatLaf no longer changes it.
* <p>
* The listener is added once for a property, but never removed.
* So switching Laf/theme reuses existing listener.
*/
static class FlatPropertyWatcher
implements PropertyChangeListener
{
private boolean changed;
static void runIfNotChanged( JComponent c, String propName, Runnable runnable ) {
FlatPropertyWatcher watcher = getOrInstall( c, propName );
if( watcher.changed )
return;
runnable.run();
watcher.changed = false;
}
private static FlatPropertyWatcher getOrInstall( JComponent c, String propName ) {
for( PropertyChangeListener l : c.getPropertyChangeListeners( propName ) ) {
if( l instanceof FlatPropertyWatcher )
return (FlatPropertyWatcher) l;
}
FlatPropertyWatcher watcher = new FlatPropertyWatcher();
c.addPropertyChangeListener( propName, watcher );
return watcher;
}
//---- interface PropertyChangeListener ----
@Override
public void propertyChange( PropertyChangeEvent e ) {
changed = true;
}
}
} }