Hide/gray client-menu items that can't do anything useful right now
"Find Client in Channel Tree" only makes sense when the menu was opened somewhere other than the tree itself (chat log links, etc.), so it's hidden when opened from the tree, and disabled elsewhere if the client's channel isn't currently subscribed (so the tree wouldn't actually show them). Adds "Join Channel of Client" above "Move Client to own Channel", disabled under the same visibility condition plus a full channel. Both use the CHANNEL_SWITCH icon. Note: TS3 doesn't expose a channel's join-power threshold as a plain property (only group membership powers work that way); it's a permission resolved through channel/channel-group/server-group inheritance that a regular client can't query, so join-power itself isn't part of this check.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package com.ts3client.ui;
|
||||
|
||||
import com.ts3client.net.ChannelNode;
|
||||
import com.ts3client.net.ClientEntry;
|
||||
import com.ts3client.net.Group;
|
||||
import com.ts3client.net.ServerModel;
|
||||
@@ -19,8 +20,13 @@ final class ClientMenu {
|
||||
private ClientMenu() {
|
||||
}
|
||||
|
||||
static JPopupMenu build(ClientEntry client, boolean self, ServerModel model, GroupIcons groupIcons,
|
||||
ServerTreePanel.Actions actions) {
|
||||
/**
|
||||
* @param fromTree whether this menu was opened from the server tree itself, as
|
||||
* opposed to a client link elsewhere (chat log, etc.) — "Find
|
||||
* Client in Channel Tree" is redundant in the former case.
|
||||
*/
|
||||
static JPopupMenu build(ClientEntry client, boolean self, boolean fromTree, ServerModel model,
|
||||
GroupIcons groupIcons, ServerTreePanel.Actions actions) {
|
||||
JPopupMenu menu = new JPopupMenu();
|
||||
if (!self) {
|
||||
JMenuItem pm = new JMenuItem("Open text chat", Icons.of("PLAYER_CHAT"));
|
||||
@@ -53,14 +59,21 @@ final class ClientMenu {
|
||||
menu.add(buildServerGroupMenu(client, model, groupIcons, actions));
|
||||
menu.add(buildChannelGroupMenu(client, model, groupIcons, actions));
|
||||
menu.addSeparator();
|
||||
JMenuItem findInTree = new JMenuItem("Find Client in Channel Tree", Icons.of("PLAYER_ON"));
|
||||
findInTree.addActionListener(a -> actions.findClientInTree(client));
|
||||
menu.add(findInTree);
|
||||
if (!fromTree) {
|
||||
JMenuItem findInTree = new JMenuItem("Find Client in Channel Tree", Icons.of("CHANNEL_SWITCH"));
|
||||
findInTree.setEnabled(isVisible(client, model));
|
||||
findInTree.addActionListener(a -> actions.findClientInTree(client));
|
||||
menu.add(findInTree);
|
||||
}
|
||||
JMenuItem info = new JMenuItem("Connection Info", Icons.of("INFO"));
|
||||
info.addActionListener(a -> actions.showConnectionInfo(client));
|
||||
menu.add(info);
|
||||
if (!self) {
|
||||
menu.addSeparator();
|
||||
JMenuItem joinChannel = new JMenuItem("Join Channel of Client", Icons.of("CHANNEL_SWITCH"));
|
||||
joinChannel.setEnabled(canJoinChannelOf(client, model));
|
||||
joinChannel.addActionListener(a -> actions.joinChannel(client.channelId));
|
||||
menu.add(joinChannel);
|
||||
JMenuItem moveHere = new JMenuItem("Move Client to own Channel", Icons.of("MOVE_CLIENT_TO_OWN_CHANNEL"));
|
||||
moveHere.addActionListener(a -> actions.moveClientToOwnChannel(client));
|
||||
menu.add(moveHere);
|
||||
@@ -68,6 +81,28 @@ final class ClientMenu {
|
||||
return menu;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the client's channel is actually rendered in the tree — it won't be if
|
||||
* we're not subscribed to it (e.g. it needs more subscribe power than we have).
|
||||
*/
|
||||
private static boolean isVisible(ClientEntry client, ServerModel model) {
|
||||
ChannelNode channel = model.getChannel(client.channelId);
|
||||
return channel != null && channel.subscribed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether we can expect a join to succeed: the channel must be visible to us, and
|
||||
* not already full. This can't account for a join-power permission requirement —
|
||||
* unlike group membership, TS3 doesn't expose a channel's join-power threshold as
|
||||
* a plain property, only as a permission resolved through channel/channel-group/
|
||||
* server-group inheritance, which isn't something a regular client can query.
|
||||
*/
|
||||
private static boolean canJoinChannelOf(ClientEntry client, ServerModel model) {
|
||||
ChannelNode channel = model.getChannel(client.channelId);
|
||||
if (channel == null || !channel.subscribed) return false;
|
||||
return channel.maxClients < 0 || channel.clients.size() < channel.maxClients;
|
||||
}
|
||||
|
||||
private static JMenu buildServerGroupMenu(ClientEntry client, ServerModel model, GroupIcons groupIcons,
|
||||
ServerTreePanel.Actions actions) {
|
||||
JMenu menu = new JMenu("Set Server Groups");
|
||||
|
||||
@@ -84,7 +84,7 @@ final class ServerTabTreeActions implements ServerTreePanel.Actions {
|
||||
chatPanel.appendSystem("That client is no longer on the server.");
|
||||
return;
|
||||
}
|
||||
ClientMenu.build(client, client.id == conn.getSelfClientId(), conn.getModel(), groupIcons, this)
|
||||
ClientMenu.build(client, client.id == conn.getSelfClientId(), false, conn.getModel(), groupIcons, this)
|
||||
.show(source, x, y);
|
||||
}
|
||||
|
||||
|
||||
@@ -197,7 +197,8 @@ public final class ServerTreePanel extends JScrollPane {
|
||||
}
|
||||
|
||||
private void showClientMenu(ClientEntry client, MouseEvent e) {
|
||||
ClientMenu.build(client, client.id == selfClientId, model, groupIcons, actions).show(tree, e.getX(), e.getY());
|
||||
ClientMenu.build(client, client.id == selfClientId, true, model, groupIcons, actions)
|
||||
.show(tree, e.getX(), e.getY());
|
||||
}
|
||||
|
||||
private void showChannelMenu(ChannelNode channel, MouseEvent e) {
|
||||
|
||||
Reference in New Issue
Block a user