The toolbar gains an away toggle with a drop-down: it toggles away on the
current server with no message, while the menu carries the global actions
("Set Globally Away", "Set Globally Away Status"), the saved presets and
their editor. Presets live in ~/.ts3jclient/away.properties and are
managed in a list with add/remove and double-click renaming.
Clients in the channel tree now show their away message in brackets after
the nickname instead of their primary server group.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
116 lines
3.6 KiB
Java
116 lines
3.6 KiB
Java
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.
|
|
*
|
|
* <p>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<JPopupMenu> 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;
|
|
}
|
|
}
|
|
}
|