diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cdedfd1..9c2f01b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ FlatLaf Change Log - Use mapper function in color filter to dynamically map colors. (PR #303) - Color filter supports light and dark themes. - Getters for icon name, classloader, etc. +- Extras: UI Inspector: Show class hierarchies when pressing Alt key + and prettified class names (dimmed package name). #### Fixed bugs diff --git a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatInspector.java b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatInspector.java index bab67fb3..8bd74b3a 100644 --- a/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatInspector.java +++ b/flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatInspector.java @@ -56,6 +56,7 @@ import javax.swing.Popup; import javax.swing.PopupFactory; import javax.swing.RootPaneContainer; import javax.swing.SwingUtilities; +import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.border.EmptyBorder; import javax.swing.border.LineBorder; @@ -90,7 +91,11 @@ public class FlatInspector { private static final Integer HIGHLIGHT_LAYER = JLayeredPane.POPUP_LAYER - 1; - private static final int KEY_MODIFIERS_MASK = InputEvent.CTRL_DOWN_MASK | InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_DOWN_MASK | InputEvent.META_DOWN_MASK; + private static final int KEY_MODIFIERS_MASK = + InputEvent.CTRL_DOWN_MASK | + InputEvent.SHIFT_DOWN_MASK | + InputEvent.ALT_DOWN_MASK | + InputEvent.META_DOWN_MASK; private final JRootPane rootPane; private final MouseMotionListener mouseMotionListener; @@ -104,7 +109,8 @@ public class FlatInspector private int lastX; private int lastY; private int inspectParentLevel; - private boolean wasCtrlOrShiftKeyPressed; + private boolean wasModifierKeyPressed; + private boolean showClassHierarchy; private JComponent highlightFigure; private Popup popup; @@ -161,9 +167,9 @@ public class FlatInspector if( id == KeyEvent.KEY_PRESSED ) { // this avoids that the inspection level is changed when UI inspector // is enabled with keyboard shortcut (e.g. Ctrl+Shift+Alt+X) - if( keyCode == KeyEvent.VK_CONTROL || keyCode == KeyEvent.VK_SHIFT ) - wasCtrlOrShiftKeyPressed = true; - } else if( id == KeyEvent.KEY_RELEASED && wasCtrlOrShiftKeyPressed ) { + if( keyCode == KeyEvent.VK_CONTROL || keyCode == KeyEvent.VK_SHIFT || keyCode == KeyEvent.VK_ALT ) + wasModifierKeyPressed = true; + } else if( id == KeyEvent.KEY_RELEASED && wasModifierKeyPressed ) { if( keyCode == KeyEvent.VK_CONTROL ) { inspectParentLevel++; int parentLevel = inspect( lastX, lastY ); @@ -180,6 +186,9 @@ public class FlatInspector inspectParentLevel = Math.max( parentLevel - 1, 0 ); inspect( lastX, lastY ); } + } else if( keyCode == KeyEvent.VK_ALT && lastComponent != null) { + showClassHierarchy = !showClassHierarchy; + showToolTip( lastComponent, lastX, lastY, inspectParentLevel ); } } @@ -402,7 +411,7 @@ public class FlatInspector return; JToolTip tip = new JToolTip(); - tip.setTipText( buildToolTipText( c, parentLevel ) ); + tip.setTipText( buildToolTipText( c, parentLevel, showClassHierarchy ) ); tip.putClientProperty( FlatClientProperties.POPUP_FORCE_HEAVY_WEIGHT, true ); Point pt = new Point( x, y ); @@ -428,16 +437,13 @@ public class FlatInspector popup.show(); } - private static String buildToolTipText( Component c, int parentLevel ) { + private static String buildToolTipText( Component c, int parentLevel, boolean classHierarchy ) { StringBuilder buf = new StringBuilder( 1500 ); buf.append( "" ); - String name = c.getClass().getName(); - name = name.substring( name.lastIndexOf( '.' ) + 1 ); - Package pkg = c.getClass().getPackage(); - appendRow( buf, "Class", name + " (" + (pkg != null ? pkg.getName() : "-") + ")" ); + appendRow( buf, "Class", toString( c.getClass(), classHierarchy ) ); appendRow( buf, "Size", c.getWidth() + ", " + c.getHeight() + "   @ " + c.getX() + ", " + c.getY() ); if( c instanceof Container ) @@ -464,7 +470,7 @@ public class FlatInspector appendRow( buf, "Max size", maxSize.width + ", " + maxSize.height ); if( c instanceof JComponent ) - appendRow( buf, "Border", toString( ((JComponent)c).getBorder() ) ); + appendRow( buf, "Border", toString( ((JComponent)c).getBorder(), classHierarchy ) ); appendRow( buf, "Background", toString( c.getBackground() ) ); appendRow( buf, "Foreground", toString( c.getForeground() ) ); @@ -475,7 +481,7 @@ public class FlatInspector Field f = JComponent.class.getDeclaredField( "ui" ); f.setAccessible( true ); Object ui = f.get( c ); - appendRow( buf, "UI", (ui != null ? ui.getClass().getName() : "null") ); + appendRow( buf, "UI", (ui != null ? toString( ui.getClass(), classHierarchy ) : "null") ); } catch( Exception ex ) { // ignore } @@ -484,7 +490,7 @@ public class FlatInspector if( c instanceof Container ) { LayoutManager layout = ((Container)c).getLayout(); if( layout != null ) - appendRow( buf, "Layout", layout.getClass().getName() ); + appendRow( buf, "Layout", toString( layout.getClass(), classHierarchy ) ); } appendRow( buf, "Enabled", String.valueOf( c.isEnabled() ) ); @@ -494,16 +500,23 @@ public class FlatInspector appendRow( buf, "ContentAreaFilled", String.valueOf( ((AbstractButton)c).isContentAreaFilled() ) ); appendRow( buf, "Focusable", String.valueOf( c.isFocusable() ) ); appendRow( buf, "Left-to-right", String.valueOf( c.getComponentOrientation().isLeftToRight() ) ); - appendRow( buf, "Parent", (c.getParent() != null ? c.getParent().getClass().getName() : "null") ); + appendRow( buf, "Parent", (c.getParent() != null ? toString( c.getParent().getClass(), classHierarchy ) : "null") ); + // append parent level buf.append( "" ); buf.append( "
" ); if( parentLevel > 0 ) buf.append( "
Parent level: " + parentLevel ); - if( parentLevel > 0 ) - buf.append( "
(press Ctrl/Shift to increase/decrease level)" ); - else - buf.append( "
(press Ctrl key to inspect parent)" ); + // append modifier keys hint + buf.append( "
(" ) + .append( (parentLevel > 0) + ? "press Ctrl/Shift to increase/decrease level" + : "press Ctrl key to inspect parent" ) + .append( ";  " ) + .append( classHierarchy + ? "press Alt key to hide class hierarchy" + : "press Alt key to show class hierarchy" ) + .append( ')' ); buf.append( "
" ); @@ -512,13 +525,43 @@ public class FlatInspector } private static void appendRow( StringBuilder buf, String key, String value ) { - buf.append( "" ) + buf.append( "" ) .append( key ) .append( ":" ) .append( value ) .append( "" ); } + private static String toString( Class cls, boolean classHierarchy ) { + StringBuilder buf = new StringBuilder( 100 ); + int level = 0; + + while( cls != null ) { + if( level > 0 ) { + if( cls == Object.class ) + break; + buf.append( "
 " ); + for( int i = 1; i < level; i++ ) + buf.append( "    " ); + buf.append( "\u2570 " ); + } + level++; + + String name = cls.getName(); + int dot = name.lastIndexOf( '.' ); + String pkg = (dot >= 0) ? name.substring( 0, dot ) : "-"; + String simpleName = (dot >= 0) ? name.substring( dot + 1 ) : name; + buf.append( simpleName ).append( ' ' ).append( toDimmedText( "(" + pkg + ")" ) ); + + if( !classHierarchy ) + break; + + cls = cls.getSuperclass(); + } + + return buf.toString(); + } + private static String toString( Insets insets ) { if( insets == null ) return "null"; @@ -564,11 +607,11 @@ public class FlatInspector + (f instanceof UIResource ? " UI" : ""); } - private static String toString( Border b ) { + private static String toString( Border b, boolean classHierarchy ) { if( b == null ) return "null"; - String s = b.getClass().getName(); + String s = toString( b.getClass(), classHierarchy ); if( b instanceof EmptyBorder ) s += '(' + toString( ((EmptyBorder)b).getBorderInsets() ) + ')'; @@ -578,4 +621,14 @@ public class FlatInspector return s; } + + private static String toDimmedText( String text ) { + Color color = UIManager.getColor( "Label.disabledForeground" ); + if( color == null ) + color = UIManager.getColor( "Label.disabledText" ); + if( color == null ) + color = Color.GRAY; + return String.format( "%s", + color.getRGB() & 0xffffff, text ); + } }