FlatPopupFactory: use method handles instead of reflection

This commit is contained in:
Karl Tauber
2022-08-13 11:18:47 +02:00
parent 2dd75c4a64
commit fee7cf6265

View File

@@ -36,7 +36,9 @@ import java.awt.Window;
import java.awt.event.ComponentEvent; import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener; import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.lang.reflect.InvocationTargetException; import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import javax.swing.JComponent; import javax.swing.JComponent;
import javax.swing.JLayeredPane; import javax.swing.JLayeredPane;
@@ -64,8 +66,8 @@ import com.formdev.flatlaf.util.UIScale;
public class FlatPopupFactory public class FlatPopupFactory
extends PopupFactory extends PopupFactory
{ {
private Method java8getPopupMethod; private MethodHandle java8getPopupMethod;
private Method java9getPopupMethod; private MethodHandle java9getPopupMethod;
@Override @Override
public Popup getPopup( Component owner, Component contents, int x, int y ) public Popup getPopup( Component owner, Component contents, int x, int y )
@@ -192,23 +194,25 @@ public class FlatPopupFactory
{ {
try { try {
if( SystemInfo.isJava_9_orLater ) { if( SystemInfo.isJava_9_orLater ) {
// Java 9: protected Popup getPopup( Component owner, Component contents, int x, int y, boolean isHeavyWeightPopup )
if( java9getPopupMethod == null ) { if( java9getPopupMethod == null ) {
java9getPopupMethod = PopupFactory.class.getDeclaredMethod( MethodType mt = MethodType.methodType( Popup.class, Component.class, Component.class, int.class, int.class, boolean.class );
"getPopup", Component.class, Component.class, int.class, int.class, boolean.class ); java9getPopupMethod = MethodHandles.lookup().findVirtual( PopupFactory.class, "getPopup", mt );
} }
return (Popup) java9getPopupMethod.invoke( this, owner, contents, x, y, true ); return (Popup) java9getPopupMethod.invoke( this, owner, contents, x, y, true );
} else { } else {
// Java 8 // Java 8: private Popup getPopup( Component owner, Component contents, int ownerX, int ownerY, int popupType )
if( java8getPopupMethod == null ) { if( java8getPopupMethod == null ) {
java8getPopupMethod = PopupFactory.class.getDeclaredMethod( Method m = PopupFactory.class.getDeclaredMethod(
"getPopup", Component.class, Component.class, int.class, int.class, int.class ); "getPopup", Component.class, Component.class, int.class, int.class, int.class );
java8getPopupMethod.setAccessible( true ); m.setAccessible( true );
java8getPopupMethod = MethodHandles.lookup().unreflect( m );
} }
return (Popup) java8getPopupMethod.invoke( this, owner, contents, x, y, /*HEAVY_WEIGHT_POPUP*/ 2 ); return (Popup) java8getPopupMethod.invoke( this, owner, contents, x, y, /*HEAVY_WEIGHT_POPUP*/ 2 );
} }
} catch( NoSuchMethodException | SecurityException | IllegalAccessException | InvocationTargetException ex ) { } catch( Throwable ex ) {
// ignore // fallback
return null; return super.getPopup( owner, contents, x, y );
} }
} }