@Override
	protected void paintRow( Graphics g, Rectangle clipBounds, Insets insets, Rectangle bounds,
		TreePath path, int row, boolean isExpanded, boolean hasBeenExpanded, boolean isLeaf )
	{
		boolean isEditing = (editingComponent != null && editingRow == row);
		boolean isSelected = tree.isRowSelected( row );
		boolean isDropRow = isDropRow( row );
		boolean needsSelectionPainting = (isSelected || isDropRow) && isPaintSelection();

		// paint alternating rows
		if( alternateRowColor != null && row % 2 != 0 ) {
			g.setColor( alternateRowColor );

			float arc = UIScale.scale( selectionArc / 2f );
			FlatUIUtils.paintSelection( (Graphics2D) g, 0, bounds.y, tree.getWidth(), bounds.height,
				UIScale.scale( selectionInsets ), arc, arc, arc, arc, 0 );
		}

		// update bounds for wide cell renderer
		if( isWideSelection() && isWideCellRenderer() ) {
			Rectangle wideBounds = new Rectangle( bounds );
			if( tree.getComponentOrientation().isLeftToRight() )
				wideBounds.width = tree.getWidth() - bounds.x - insets.right;
			else {
				wideBounds.x = insets.left;
				wideBounds.width = bounds.x + bounds.width - insets.left;
			}
			bounds = wideBounds;
		}

		// do not paint row if editing
		if( isEditing ) {
			// paint wide selection
			// (do not access cell renderer here to avoid side effect
			// if renderer component is also used as editor component)
			if( isSelected && isWideSelection() ) {
				Color oldColor = g.getColor();
				g.setColor( selectionInactiveBackground );
				paintWideSelection( g, bounds, row );
				g.setColor( oldColor );
			}
			return;
		}

		boolean hasFocus = FlatUIUtils.isPermanentFocusOwner( tree );
		boolean cellHasFocus = hasFocus && (row == getLeadSelectionRow());

		// if tree is used as cell renderer in another component (e.g. in Rhino JavaScript debugger),
		// check whether that component is focused to get correct selection colors
		if( !hasFocus && isSelected && tree.getParent() instanceof CellRendererPane )
			hasFocus = FlatUIUtils.isPermanentFocusOwner( tree.getParent().getParent() );

		// get renderer component
		Component rendererComponent = currentCellRenderer.getTreeCellRendererComponent( tree,
			path.getLastPathComponent(), isSelected, isExpanded, isLeaf, row, cellHasFocus );

		// renderer background/foreground
		Color oldBackgroundSelectionColor = null;
		if( isSelected && !hasFocus && !isDropRow ) {
			// apply inactive selection background/foreground if tree is not focused
			oldBackgroundSelectionColor = setRendererBackgroundSelectionColor( rendererComponent, selectionInactiveBackground );
			setRendererForeground( rendererComponent, selectionInactiveForeground );

		} else if( isSelected ) {
			// update background/foreground if set via style
			if( selectionBackground != defaultSelectionBackground )
				oldBackgroundSelectionColor = setRendererBackgroundSelectionColor( rendererComponent, selectionBackground );
			if( selectionForeground != defaultSelectionForeground )
				setRendererForeground( rendererComponent, selectionForeground );
		}

		// update focus selection border
		Color oldBorderSelectionColor = null;
		if( isSelected && hasFocus &&
			(!showCellFocusIndicator || tree.getMinSelectionRow() == tree.getMaxSelectionRow()) )
		{
			// remove focus selection border if exactly one item is selected or if showCellFocusIndicator is false
			oldBorderSelectionColor = setRendererBorderSelectionColor( rendererComponent, null );

		} else if( hasFocus && selectionBorderColor != defaultSelectionBorderColor ) {
			// update focus selection border if set via style
			oldBorderSelectionColor = setRendererBorderSelectionColor( rendererComponent, selectionBorderColor );
		}

		// paint selection background
		if( needsSelectionPainting ) {
			// set selection color
			Color oldColor = g.getColor();
			g.setColor( isDropRow
				? UIManager.getColor( "Tree.dropCellBackground" )
				: (rendererComponent instanceof DefaultTreeCellRenderer
					? ((DefaultTreeCellRenderer)rendererComponent).getBackgroundSelectionColor()
					: (hasFocus ? selectionBackground : selectionInactiveBackground)) );

			if( isWideSelection() ) {
				// wide selection
				paintWideSelection( g, bounds, row );
			} else {
				// non-wide selection
				paintCellBackground( g, rendererComponent, bounds, row, true );
			}

			// this is actually not necessary because renderer should always set color
			// before painting, but doing anyway to avoid any side effect (in bad renderers)
			g.setColor( oldColor );
		} else {
			// paint cell background if DefaultTreeCellRenderer.getBackgroundNonSelectionColor() is set
			if( rendererComponent instanceof DefaultTreeCellRenderer ) {
				DefaultTreeCellRenderer renderer = (DefaultTreeCellRenderer) rendererComponent;
				Color bg = renderer.getBackgroundNonSelectionColor();
				if( bg != null && !bg.equals( defaultCellNonSelectionBackground ) ) {
					Color oldColor = g.getColor();
					g.setColor( bg );
					paintCellBackground( g, rendererComponent, bounds, row, false );
					g.setColor( oldColor );
				}
			}
		}

		// paint renderer
		rendererPane.paintComponent( g, rendererComponent, tree, bounds.x, bounds.y, bounds.width, bounds.height, true );

		// restore background selection color and border selection color
		if( oldBackgroundSelectionColor != null )
			((DefaultTreeCellRenderer)rendererComponent).setBackgroundSelectionColor( oldBackgroundSelectionColor );
		if( oldBorderSelectionColor != null )
			((DefaultTreeCellRenderer)rendererComponent).setBorderSelectionColor( oldBorderSelectionColor );
	}
Similar to super.paintRow(), but supports wide selection and uses
inactive selection background/foreground if tree is not focused.
flatlaf-core/src/main/java/com/formdev/flatlaf/ui/FlatTreeUI.java