package com.revivius.nb.darcula.ui; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Graphics; import java.beans.PropertyChangeEvent; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.border.Border; import javax.swing.border.CompoundBorder; import javax.swing.border.EmptyBorder; import javax.swing.border.LineBorder; import javax.swing.plaf.ComponentUI; import javax.swing.plaf.metal.MetalLabelUI; import org.netbeans.swing.plaf.LFCustoms; /** * https://praxisintermedia.wordpress.com/2011/09/29/the-dark-arts-of-netbeans-hackery/ * * @author Revivius */ public class OptionsAwareLabelUI extends MetalLabelUI { private static final String OPTIONS_PANEL_NAME = "org.netbeans.modules.options.OptionsPanel"; private static boolean bgReplaced = false; public static ComponentUI createUI(JComponent c) { if (c.getClass().getName().startsWith(OPTIONS_PANEL_NAME)) { return new OptionsAwareLabelUI(); } return MetalLabelUI.createUI(c); } private static final Color oldHighlighted = new Color(224, 232, 246); private final Color fgNormal = UIManager.getColor("textText"); private final Color bgNormal = UIManager.getColor("List.background"); private final Color bgSelected = UIManager.getColor("List.selectionBackground"); private final Color bgHighlighted = new Color(13, 41, 62); private final Border normalBorder = new EmptyBorder(6, 8, 6, 8); private final Border highlightBorder = new CompoundBorder( new LineBorder(bgNormal), new EmptyBorder(4, 7, 4, 7) ); private boolean ignoreChanges; @Override public void update(Graphics g, JComponent c) { super.update(g, c); if (bgReplaced) { return; } // In NB 8.1 CategoryButtons are in a JScrollPane Container parent = SwingUtilities.getAncestorOfClass(JScrollPane.class, c); if (parent == null) { parent = SwingUtilities.getAncestorOfClass(JPanel.class, c); } // In NB 8.0 CategoryButtons are in a JPanel if (parent != null) { parent = parent.getParent(); } if (parent != null && (parent instanceof JPanel)) { JPanel panel = (JPanel) parent; replaceBg(panel); panel.setBorder(BorderFactory.createMatteBorder( 0, 0, 1, 0, UIManager.getColor(LFCustoms.SCROLLPANE_BORDER_COLOR))); bgReplaced = true; } } private void replaceBg(JComponent component) { component.setBackground(bgNormal); if (component instanceof JScrollPane) { JScrollPane sc = (JScrollPane) component; sc.getViewport().setBackground(bgNormal); sc.getViewport().getView().setBackground(bgNormal); } Component[] components = component.getComponents(); for (Component c : components) { if (c instanceof JPanel || c instanceof JScrollPane) { replaceBg((JComponent) c); } } } @Override public void propertyChange(PropertyChangeEvent e) { if (ignoreChanges) { super.propertyChange(e); return; } if (!(e.getSource() instanceof JLabel)) { super.propertyChange(e); return; } JLabel c = (JLabel) e.getSource(); if ("background".equals(e.getPropertyName())) { ignoreChanges = true; Color bgCurrent = c.getBackground(); if (Color.WHITE.equals(bgCurrent)) { c.setBackground(bgNormal); } else if (oldHighlighted.equals(bgCurrent)) { c.setBackground(bgHighlighted); } else if (!bgNormal.equals(bgCurrent)) { c.setBackground(bgSelected); } ignoreChanges = false; } else if ("foreground".equals(e.getPropertyName())) { ignoreChanges = true; if (!fgNormal.equals(c.getForeground())) { c.setForeground(fgNormal); } ignoreChanges = false; } else if ("border".equals(e.getPropertyName())) { ignoreChanges = true; Border current = c.getBorder(); if (current instanceof EmptyBorder) { c.setBorder(normalBorder); } else { c.setBorder(highlightBorder); } ignoreChanges = false; } else { super.propertyChange(e); } } }