/*
* Copyright (c) 2005-2016 Substance Kirill Grouchnikov. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* o Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* o Neither the name of Substance Kirill Grouchnikov nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package tools.uidebug;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Dialog.ModalityType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.TransferHandler;
import javax.swing.UIManager;
import org.pushingpixels.lafwidget.LafWidgetAdapter;
import org.pushingpixels.lafwidget.animation.AnimationConfigurationManager;
import org.pushingpixels.lafwidget.animation.effects.GhostPaintingUtils;
import org.pushingpixels.substance.api.ColorSchemeTransform;
import org.pushingpixels.substance.api.ComponentState;
import org.pushingpixels.substance.api.SubstanceColorScheme;
import org.pushingpixels.substance.api.SubstanceLookAndFeel;
import org.pushingpixels.substance.api.SubstanceSkin;
import org.pushingpixels.substance.api.SubstanceConstants.FocusKind;
import org.pushingpixels.substance.internal.utils.LazyResettableHashMap;
import org.pushingpixels.substance.internal.utils.SubstanceCoreUtilities;
public class RootPaneTitlePaneUiDebugger extends LafWidgetAdapter<JRootPane> {
protected MouseListener substanceDebugUiListener;
protected JComponent titlePane;
@Override
public boolean requiresCustomLafSupport() {
return false;
}
@Override
public void installUI() {
SwingUtilities.invokeLater(() -> {
if (!(UIManager.getLookAndFeel() instanceof SubstanceLookAndFeel))
return;
titlePane = SubstanceLookAndFeel.getTitlePaneComponent(SwingUtilities.getWindowAncestor(jcomp));
if (titlePane != null) {
substanceDebugUiListener = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
process(e);
}
@Override
public void mouseReleased(MouseEvent e) {
process(e);
}
protected void process(MouseEvent e) {
if (!e.isPopupTrigger())
return;
JPopupMenu popup = new JPopupMenu();
JMenu cbMenu = new JMenu("Color blindness");
JMenuItem protanopiaCurrent = new JMenuItem("Protanopia current");
protanopiaCurrent.addActionListener(new SkinChanger(
(SubstanceColorScheme scheme) -> new ProtanopiaColorScheme(scheme),
"Protanopia current"));
cbMenu.add(protanopiaCurrent);
JMenuItem deuteranopiaCurrent = new JMenuItem("Deuteranopia current");
deuteranopiaCurrent.addActionListener(new SkinChanger(
(SubstanceColorScheme scheme) -> new DeuteranopiaColorScheme(scheme),
"Deuteranopia current"));
cbMenu.add(deuteranopiaCurrent);
JMenuItem tritanopiaCurrent = new JMenuItem("Tritanopia current");
tritanopiaCurrent.addActionListener(new SkinChanger(
(SubstanceColorScheme scheme) -> new TritanopiaColorScheme(scheme),
"Tritanopia current"));
cbMenu.add(tritanopiaCurrent);
cbMenu.addSeparator();
JMenuItem restoreOriginal = new JMenuItem("Restore original");
if (SubstanceLookAndFeel.getCurrentSkin(null).getColorScheme(null,
ComponentState.ENABLED) instanceof ColorBlindColorScheme) {
restoreOriginal.addActionListener(new SkinChanger((SubstanceColorScheme scheme) -> {
if (scheme instanceof ColorBlindColorScheme)
return ((ColorBlindColorScheme) scheme).getOrigScheme();
return scheme;
}, "Current"));
} else {
restoreOriginal.setEnabled(false);
}
cbMenu.add(restoreOriginal);
popup.add(cbMenu);
JMenu animMenu = new JMenu("Animation rate");
JMenuItem debugNone = new JMenuItem("None");
debugNone.addActionListener(new AnimationChanger(0));
animMenu.add(debugNone);
JMenuItem debugAnim = new JMenuItem("Debug rate (extra slow)");
debugAnim.addActionListener(new AnimationChanger(5000));
animMenu.add(debugAnim);
JMenuItem debugAnimFast = new JMenuItem("Debug rate (faster)");
debugAnimFast.addActionListener(new AnimationChanger(2500));
animMenu.add(debugAnimFast);
JMenuItem debugSlow = new JMenuItem("Slow rate");
debugSlow.addActionListener(new AnimationChanger(1000));
animMenu.add(debugSlow);
JMenuItem debugRegular = new JMenuItem("Regular rate");
debugRegular.addActionListener(new AnimationChanger(250));
animMenu.add(debugRegular);
JMenuItem debugFast = new JMenuItem("Fast rate");
debugFast.addActionListener(new AnimationChanger(100));
animMenu.add(debugFast);
popup.add(animMenu);
JMenu focusMenu = new JMenu("Focus kind");
for (FocusKind fKind : FocusKind.values()) {
JMenuItem focusMenuItem = new JMenuItem(fKind.name().toLowerCase());
focusMenuItem.addActionListener(new FocusKindChanger(fKind));
focusMenu.add(focusMenuItem);
}
popup.add(focusMenu);
JMenuItem dumpHierarchy = new JMenuItem("Dump hierarchy");
dumpHierarchy.addActionListener((ActionEvent event) -> dump(jcomp, 0));
popup.add(dumpHierarchy);
final JCheckBoxMenuItem ltrChange = new JCheckBoxMenuItem("Is left-to-right");
ltrChange.setSelected(jcomp.getComponentOrientation().isLeftToRight());
ltrChange.addActionListener((ActionEvent event) -> SwingUtilities
.invokeLater(() -> jcomp.applyComponentOrientation(ltrChange.isSelected()
? ComponentOrientation.LEFT_TO_RIGHT : ComponentOrientation.RIGHT_TO_LEFT)));
popup.add(ltrChange);
final JCheckBoxMenuItem useThemedIcons = new JCheckBoxMenuItem("Use themed icons");
useThemedIcons.setSelected(SubstanceCoreUtilities.useThemedDefaultIcon(null));
useThemedIcons.addActionListener((ActionEvent event) -> SwingUtilities.invokeLater(() -> {
UIManager.put(SubstanceLookAndFeel.USE_THEMED_DEFAULT_ICONS,
useThemedIcons.isSelected() ? Boolean.TRUE : null);
jcomp.repaint();
}));
popup.add(useThemedIcons);
final JCheckBoxMenuItem ghostDebugMode = new JCheckBoxMenuItem("Ghost debug mode");
ghostDebugMode.addActionListener((ActionEvent event) -> SwingUtilities.invokeLater(() -> {
ghostDebugMode.setEnabled(false);
GhostPaintingUtils.MAX_ICON_GHOSTING_ALPHA = 0.8f;
GhostPaintingUtils.MIN_ICON_GHOSTING_ALPHA = 0.6f;
GhostPaintingUtils.MAX_PRESS_GHOSTING_ALPHA = 0.8f;
GhostPaintingUtils.MIN_PRESS_GHOSTING_ALPHA = 0.6f;
GhostPaintingUtils.DECAY_FACTOR = 0.7f;
}));
popup.add(ghostDebugMode);
JMenuItem showCacheStats = new JMenuItem("Show cache stats");
showCacheStats.addActionListener((ActionEvent event) -> SwingUtilities.invokeLater(() -> {
final JTextArea textArea = new JTextArea();
java.util.List<String> stats = LazyResettableHashMap.getStats();
if (stats != null) {
for (String stat : stats) {
textArea.append(stat + "\n");
}
}
final JDialog dialog = new JDialog(SwingUtilities.getWindowAncestor(jcomp),
ModalityType.APPLICATION_MODAL);
dialog.setTitle("Substance cache stats");
dialog.setLayout(new BorderLayout());
dialog.add(new JScrollPane(textArea), BorderLayout.CENTER);
JButton dismiss = new JButton("Dismiss");
dismiss.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dialog.dispose();
}
});
JButton copyToClipboard = new JButton("Copy to clipboard");
copyToClipboard.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
textArea.selectAll();
TransferHandler.getCopyAction().actionPerformed(
new ActionEvent(textArea, ActionEvent.ACTION_PERFORMED, "Copy"));
}
});
JPanel controls = new JPanel(new FlowLayout(FlowLayout.RIGHT));
controls.add(copyToClipboard);
controls.add(dismiss);
dialog.add(controls, BorderLayout.SOUTH);
dialog.setSize(500, 400);
dialog.setLocationRelativeTo(SwingUtilities.getRootPane(jcomp));
dialog.setVisible(true);
}));
popup.add(showCacheStats);
popup.show(titlePane, e.getX(), e.getY());
}
};
titlePane.addMouseListener(substanceDebugUiListener);
}
});
}
@Override
public void uninstallUI() {
if (this.substanceDebugUiListener != null) {
titlePane.removeMouseListener(this.substanceDebugUiListener);
this.substanceDebugUiListener = null;
}
}
protected static class SkinChanger implements ActionListener {
protected ColorSchemeTransform transform;
protected String name;
public SkinChanger(ColorSchemeTransform transform, String name) {
super();
this.transform = transform;
this.name = name;
}
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(() -> {
SubstanceSkin newSkin = SubstanceLookAndFeel.getCurrentSkin(null).transform(transform, name);
SubstanceLookAndFeel.setSkin(newSkin);
});
}
}
protected static class AnimationChanger implements ActionListener {
protected long newAnimationDuration;
public AnimationChanger(long newAnimationDuration) {
super();
this.newAnimationDuration = newAnimationDuration;
}
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(
() -> AnimationConfigurationManager.getInstance().setTimelineDuration(newAnimationDuration));
}
}
protected static class FocusKindChanger implements ActionListener {
protected FocusKind newFocusKind;
public FocusKindChanger(FocusKind newFocusKind) {
super();
this.newFocusKind = newFocusKind;
}
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(() -> UIManager.put(SubstanceLookAndFeel.FOCUS_KIND, newFocusKind));
}
}
public static void dump(Component comp, int level) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < level; i++)
sb.append(" ");
sb.append(comp.toString());
System.out.println(sb);
if (comp instanceof Container) {
Container cont = (Container) comp;
for (int i = 0; i < cont.getComponentCount(); i++) {
dump(cont.getComponent(i), level + 1);
}
}
}
}