private static String buildToolTipText( Component c, int parentLevel, boolean classHierarchy ) {
		StringBuilder buf = new StringBuilder( 1500 );
		buf.append( "<html><style>" );
		buf.append( "td { padding: 0 10 0 0; }" );
		buf.append( "</style><table>" );

		appendRow( buf, "Class", toString( c.getClass(), classHierarchy ) );
		appendRow( buf, "Size", c.getWidth() + ", " + c.getHeight() + "&nbsp;&nbsp; @ " + c.getX() + ", " + c.getY() );

		if( c instanceof Container )
			appendRow( buf, "Insets", toString( ((Container)c).getInsets() ) );

		Insets margin = null;
		if( c instanceof AbstractButton )
			margin = ((AbstractButton) c).getMargin();
		else if( c instanceof JTextComponent )
			margin = ((JTextComponent) c).getMargin();
		else if( c instanceof JMenuBar )
			margin = ((JMenuBar) c).getMargin();
		else if( c instanceof JToolBar )
			margin = ((JToolBar) c).getMargin();

		if( margin != null )
			appendRow( buf, "Margin", toString( margin ) );

		if( c instanceof JComponent ) {
			Object value = ((JComponent)c).getClientProperty( MigLayoutVisualPadding.VISUAL_PADDING_PROPERTY );
			Insets visualPadding = (value instanceof int[])
				? new Insets( ((int[])value)[0], ((int[])value)[1], ((int[])value)[2], ((int[])value)[3] )
				: (value instanceof Insets ? (Insets) value : null);
			if( visualPadding != null )
				appendRow( buf, "Mig visual padding", toString( visualPadding ) );
		}

		Dimension prefSize = c.getPreferredSize();
		Dimension minSize = c.getMinimumSize();
		Dimension maxSize = c.getMaximumSize();
		appendRow( buf, "Pref size", prefSize.width + ", " + prefSize.height );
		appendRow( buf, "Min size", minSize.width + ", " + minSize.height );
		appendRow( buf, "Max size", maxSize.width + ", " + maxSize.height );

		if( c instanceof JComponent )
			appendRow( buf, "Border", toString( ((JComponent)c).getBorder(), classHierarchy ) );

		appendRow( buf, "Background", toString( c.getBackground() ) + (c.isBackgroundSet() ? "" : "  NOT SET") );
		appendRow( buf, "Foreground", toString( c.getForeground() ) + (c.isForegroundSet() ? "" : "  NOT SET") );
		appendRow( buf, "Font", toString( c.getFont() ) + (c.isFontSet() ? "" : "  NOT SET") );

		if( c instanceof JComponent ) {
			try {
				Object ui;
				if( SystemInfo.isJava_9_orLater ) {
					// Java 9+: use public method JComponent.getUI()
					Method m = JComponent.class.getMethod( "getUI" );
					ui = m.invoke( c );
				} else {
					// Java 8: read protected field 'ui'
					Field f = JComponent.class.getDeclaredField( "ui" );
					f.setAccessible( true );
					ui = f.get( c );
				}
				appendRow( buf, "UI", (ui != null ? toString( ui.getClass(), classHierarchy ) : "null") );
			} catch( Exception ex ) {
				// ignore
			}
		}

		if( c instanceof Container ) {
			LayoutManager layout = ((Container)c).getLayout();
			if( layout != null )
				appendRow( buf, "Layout", toString( layout.getClass(), classHierarchy ) );
		}

		appendRow( buf, "Enabled", String.valueOf( c.isEnabled() ) );
		appendRow( buf, "Opaque", String.valueOf( c.isOpaque() )
			+ (c instanceof JComponent && FlatUIUtils.hasOpaqueBeenExplicitlySet( (JComponent) c ) ? " EXPLICIT" : "") );
		if( c instanceof AbstractButton )
			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 ? toString( c.getParent().getClass(), classHierarchy ) : "null") );

		if( c instanceof JComponent ) {
			Object style = ((JComponent)c).getClientProperty( FlatClientProperties.STYLE );
			if( style != null )
				appendRow( buf, "FlatLaf Style", style.toString() );
		}

		// append parent level
		buf.append( "<tr><td colspan=\"2\">" );
		if( parentLevel > 0 )
			buf.append( "<br>Parent level: " + parentLevel );

		// append modifier keys hint
		buf.append( "<br>(" )
			.append( (parentLevel > 0)
				? "press <b>Ctrl/Shift</b> to increase/decrease level"
				: "press <b>Ctrl</b> key to inspect parent" )
			.append( "; &nbsp;" )
			.append( classHierarchy
				? "press <b>Alt</b> key to hide class hierarchy"
				: "press <b>Alt</b> key to show class hierarchy" )
			.append( ')' );

		buf.append( "</td></tr>" );
		buf.append( "</table></html>" );

		return buf.toString();
	}
Installs a key listener into the application that allows enabling and disabling
the UI inspector with the given keystroke (e.g. "ctrl shift alt X").

@param activationKeys a keystroke (e.g. "ctrl shift alt X"), or {@code null} to use "ctrl shift alt X"
flatlaf-extras/src/main/java/com/formdev/flatlaf/extras/FlatInspector.java