Add the Edit Channel dialog
Recovers the official client's CreateChannelDialog layout so the widget set, labels and tab order match: name/icon/password/topic/description above Standard, Audio, Permissions and Advanced tabs. Core gains ChannelSettings (diffed against the original so channeledit only carries changed properties) and ChannelAdmin (channelinfo/edit, channel permissions, the server icon store). TeamspeakConnection now owns the event executor so it can drain queued notify events before reading a command's result, which channelpermlist needs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
package com.ts3client.ui;
|
||||
|
||||
import com.ts3client.net.ChannelSettings;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.Box;
|
||||
import javax.swing.BoxLayout;
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JRadioButton;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.GridBagConstraints;
|
||||
import java.awt.GridBagLayout;
|
||||
import java.awt.Insets;
|
||||
|
||||
/**
|
||||
* The channel editor's "Advanced" tab: the phonetic name, the delete delay of a temporary
|
||||
* channel, voice encryption, and the two client limits.
|
||||
*/
|
||||
final class ChannelAdvancedPanel extends JPanel implements ChannelEditDialog.Tab {
|
||||
|
||||
/** TeamSpeak's ceiling for {@code channel_delete_delay}, in seconds. */
|
||||
private static final int MAX_DELETE_DELAY = 604800;
|
||||
|
||||
private final JTextField phoneticName = new JTextField();
|
||||
private final JSpinner deleteDelay =
|
||||
Spinners.compact(new JSpinner(new SpinnerNumberModel(0, 0, MAX_DELETE_DELAY, 1)));
|
||||
private final JButton deleteDelayMax = new JButton("max");
|
||||
private final JCheckBox encrypted = new JCheckBox("Voice Data encrypted");
|
||||
|
||||
private final JRadioButton maxUsersUnlimited = new JRadioButton("Unlimited");
|
||||
private final JRadioButton maxUsersLimited = new JRadioButton("Limited");
|
||||
private final JSpinner maxUsers = Spinners.compact(new JSpinner(new SpinnerNumberModel(16, 0, 65535, 1)));
|
||||
|
||||
private final JRadioButton familyInherited = new JRadioButton("Inherited");
|
||||
private final JRadioButton familyUnlimited = new JRadioButton("Unlimited");
|
||||
private final JRadioButton familyLimited = new JRadioButton("Limited");
|
||||
private final JSpinner familyMaxUsers =
|
||||
Spinners.compact(new JSpinner(new SpinnerNumberModel(16, 0, 65535, 1)));
|
||||
|
||||
ChannelAdvancedPanel() {
|
||||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||
setBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8));
|
||||
|
||||
phoneticName.setToolTipText("Set phonetic nickname used for this channel by text-to-speech.");
|
||||
deleteDelay.setToolTipText("<html><p>Delay in seconds after temporary channels are deleted"
|
||||
+ " after the last user left the channel.</p></html>");
|
||||
deleteDelayMax.setToolTipText("Set delete delay to maximum value");
|
||||
deleteDelayMax.addActionListener(a -> deleteDelay.setValue(MAX_DELETE_DELAY));
|
||||
encrypted.setToolTipText("Voice data in this channel will be encrypted.");
|
||||
|
||||
ButtonGroup users = new ButtonGroup();
|
||||
users.add(maxUsersUnlimited);
|
||||
users.add(maxUsersLimited);
|
||||
maxUsersUnlimited.setToolTipText("Unlimited number of clients can join this channel.");
|
||||
maxUsersLimited.setToolTipText("Limit number of clients in this channel.");
|
||||
maxUsersUnlimited.addActionListener(a -> syncLimits());
|
||||
maxUsersLimited.addActionListener(a -> syncLimits());
|
||||
|
||||
ButtonGroup family = new ButtonGroup();
|
||||
family.add(familyInherited);
|
||||
family.add(familyUnlimited);
|
||||
family.add(familyLimited);
|
||||
familyInherited.setToolTipText("Inherit the client limit by parent channel.");
|
||||
familyUnlimited.setToolTipText("The channel subtree can be joined by unlimited number of clients.");
|
||||
familyLimited.setToolTipText("Limit the number of clients in the channel subtree.");
|
||||
for (JRadioButton radio : new JRadioButton[]{familyInherited, familyUnlimited, familyLimited}) {
|
||||
radio.addActionListener(a -> syncLimits());
|
||||
}
|
||||
|
||||
JPanel other = otherSettings();
|
||||
other.setAlignmentX(0f);
|
||||
add(other);
|
||||
add(Box.createVerticalStrut(6));
|
||||
|
||||
JPanel limits = new JPanel();
|
||||
limits.setLayout(new BoxLayout(limits, BoxLayout.X_AXIS));
|
||||
limits.add(limitBox("Max Users", new JRadioButton[]{maxUsersUnlimited, maxUsersLimited}, maxUsers));
|
||||
limits.add(Box.createHorizontalStrut(8));
|
||||
limits.add(limitBox("Family Max Users",
|
||||
new JRadioButton[]{familyInherited, familyUnlimited, familyLimited}, familyMaxUsers));
|
||||
limits.setAlignmentX(0f);
|
||||
add(limits);
|
||||
add(Box.createVerticalGlue());
|
||||
}
|
||||
|
||||
/** The delete delay only means anything for a channel that disappears on its own. */
|
||||
void setChannelType(ChannelSettings.Type type) {
|
||||
boolean temporary = type == ChannelSettings.Type.TEMPORARY;
|
||||
deleteDelay.setEnabled(temporary);
|
||||
deleteDelayMax.setEnabled(temporary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(ChannelSettings settings) {
|
||||
phoneticName.setText(settings.phoneticName);
|
||||
deleteDelay.setValue(Math.min(MAX_DELETE_DELAY, Math.max(0, settings.deleteDelay)));
|
||||
encrypted.setSelected(settings.encrypted);
|
||||
|
||||
if (settings.maxClientsUnlimited) maxUsersUnlimited.setSelected(true);
|
||||
else maxUsersLimited.setSelected(true);
|
||||
maxUsers.setValue(settings.maxClients);
|
||||
|
||||
if (settings.familyInherited) familyInherited.setSelected(true);
|
||||
else if (settings.familyUnlimited) familyUnlimited.setSelected(true);
|
||||
else familyLimited.setSelected(true);
|
||||
familyMaxUsers.setValue(settings.maxFamilyClients);
|
||||
|
||||
setChannelType(settings.type);
|
||||
syncLimits();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(ChannelSettings settings) {
|
||||
settings.phoneticName = phoneticName.getText();
|
||||
settings.deleteDelay = (Integer) deleteDelay.getValue();
|
||||
settings.encrypted = encrypted.isSelected();
|
||||
settings.maxClientsUnlimited = maxUsersUnlimited.isSelected();
|
||||
settings.maxClients = (Integer) maxUsers.getValue();
|
||||
settings.familyInherited = familyInherited.isSelected();
|
||||
settings.familyUnlimited = familyUnlimited.isSelected();
|
||||
settings.maxFamilyClients = (Integer) familyMaxUsers.getValue();
|
||||
}
|
||||
|
||||
private void syncLimits() {
|
||||
maxUsers.setEnabled(maxUsersLimited.isSelected());
|
||||
familyMaxUsers.setEnabled(familyLimited.isSelected());
|
||||
}
|
||||
|
||||
private JPanel otherSettings() {
|
||||
JPanel panel = new JPanel(new GridBagLayout());
|
||||
panel.setBorder(BorderFactory.createTitledBorder("Other Settings"));
|
||||
GridBagConstraints c = new GridBagConstraints();
|
||||
c.insets = new Insets(3, 4, 3, 4);
|
||||
c.anchor = GridBagConstraints.WEST;
|
||||
c.fill = GridBagConstraints.HORIZONTAL;
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 0;
|
||||
panel.add(new JLabel("Phonetic Name:"), c);
|
||||
c.gridx = 1;
|
||||
c.weightx = 1;
|
||||
panel.add(phoneticName, c);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 1;
|
||||
c.weightx = 0;
|
||||
panel.add(new JLabel("Delete delay:"), c);
|
||||
JPanel delay = new JPanel(new FlowLayout(FlowLayout.LEFT, 4, 0));
|
||||
delay.add(deleteDelay);
|
||||
delay.add(deleteDelayMax);
|
||||
c.gridx = 1;
|
||||
c.weightx = 1;
|
||||
panel.add(delay, c);
|
||||
|
||||
c.gridx = 1;
|
||||
c.gridy = 2;
|
||||
panel.add(encrypted, c);
|
||||
|
||||
c.gridx = 0;
|
||||
c.gridy = 3;
|
||||
c.weighty = 1;
|
||||
panel.add(Box.createGlue(), c);
|
||||
return panel;
|
||||
}
|
||||
|
||||
private JPanel limitBox(String title, JRadioButton[] choices, JSpinner spinner) {
|
||||
JPanel box = new JPanel();
|
||||
box.setLayout(new BoxLayout(box, BoxLayout.Y_AXIS));
|
||||
box.setBorder(BorderFactory.createTitledBorder(title));
|
||||
for (JRadioButton radio : choices) {
|
||||
radio.setAlignmentX(0f);
|
||||
box.add(radio);
|
||||
}
|
||||
spinner.setAlignmentX(0f);
|
||||
box.add(Box.createVerticalStrut(4));
|
||||
box.add(spinner);
|
||||
box.add(Box.createVerticalGlue());
|
||||
return box;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user