package com.ts3client.ui;
import javax.swing.BorderFactory;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JToggleButton;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.RenderingHints;
import java.awt.event.ActionListener;
import java.util.function.Supplier;
/**
* A toolbar toggle button with a small arrow next to it that opens a menu:
* clicking the button toggles, clicking the arrow offers the related actions.
*
*
The menu is built on every click by the supplier, so it can reflect the
* current state (checked items, the presets that exist right now).
*/
public final class DropDownToggleButton extends JPanel {
private final JToggleButton button = new JToggleButton();
private final JButton arrow = new JButton(new ArrowIcon());
public DropDownToggleButton(Icon icon, String tooltip, Supplier menu) {
super(new BorderLayout());
setOpaque(false);
button.setIcon(icon);
button.setToolTipText(tooltip);
arrow.setToolTipText(tooltip);
arrow.setMargin(new Insets(0, 2, 0, 2));
arrow.setFocusable(false);
arrow.addActionListener(e -> {
JPopupMenu popup = menu.get();
if (popup != null) popup.show(this, 0, getHeight());
});
// Keep the whole control the size of a plain toolbar button: the arrow's
// width comes out of the toggle half instead of being added to it.
Dimension plain = button.getPreferredSize();
button.setPreferredSize(new Dimension(
Math.max(icon.getIconWidth() + 8, plain.width - arrow.getPreferredSize().width),
plain.height));
add(button, BorderLayout.CENTER);
add(arrow, BorderLayout.EAST);
}
/** Listener for the toggle half only; the arrow half opens the menu instead. */
public void addActionListener(ActionListener l) {
button.addActionListener(l);
}
public boolean isSelected() {
return button.isSelected();
}
public void setSelected(boolean selected) {
button.setSelected(selected);
}
public void setIcon(Icon icon) {
button.setIcon(icon);
}
@Override
public void setEnabled(boolean enabled) {
super.setEnabled(enabled);
button.setEnabled(enabled);
arrow.setEnabled(enabled);
}
/** Disables the toggle half on its own, leaving the menu reachable. */
public void setToggleEnabled(boolean enabled) {
button.setEnabled(enabled);
}
@Override
public Dimension getMaximumSize() {
return getPreferredSize(); // keep the toolbar from stretching us
}
/** The downward triangle on the menu half of the button. */
private static final class ArrowIcon implements Icon {
@Override
public void paintIcon(Component c, Graphics g0, int x, int y) {
Graphics2D g = (Graphics2D) g0.create();
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(c.isEnabled() ? Color.DARK_GRAY : Color.GRAY);
int[] xs = {x, x + getIconWidth(), x + getIconWidth() / 2};
int[] ys = {y, y, y + getIconHeight()};
g.fillPolygon(xs, ys, 3);
g.dispose();
}
@Override
public int getIconWidth() {
return 7;
}
@Override
public int getIconHeight() {
return 4;
}
}
}