Swing desktop client (core/desktop/swing Maven modules) built on the ts3j protocol library, included as a submodule. Native Opus voice with voice-activation detection, push-to-talk, and audio pre-processing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
64 lines
2.2 KiB
Java
64 lines
2.2 KiB
Java
package com.ts3client.ui;
|
|
|
|
import java.util.regex.Matcher;
|
|
import java.util.regex.Pattern;
|
|
|
|
/**
|
|
* Parses TeamSpeak 3 "spacer" channel names — cosmetic root channels used as
|
|
* separators, e.g. {@code [spacer0]---}, {@code [*spacer1]=}, {@code [cspacer]Rules}.
|
|
* The tag selects alignment ({@code l}/{@code c}/{@code r}) or fill ({@code *}).
|
|
*/
|
|
public final class Spacers {
|
|
|
|
/** Result of parsing a spacer name. */
|
|
public static final class Spacer {
|
|
public final char align; // 'l', 'c', 'r', or '*' (repeat/fill)
|
|
public final String caption;
|
|
|
|
Spacer(char align, String caption) {
|
|
this.align = align;
|
|
this.caption = caption;
|
|
}
|
|
}
|
|
|
|
private static final Pattern PATTERN =
|
|
Pattern.compile("^\\[(\\*|[lcr])?spacer[^\\]]*\\](.*)$");
|
|
|
|
private Spacers() {
|
|
}
|
|
|
|
/** Returns spacer info if {@code channelName} is a spacer, else {@code null}. */
|
|
public static Spacer parse(String channelName) {
|
|
if (channelName == null) return null;
|
|
Matcher m = PATTERN.matcher(channelName);
|
|
if (!m.matches()) return null;
|
|
String tag = m.group(1);
|
|
char align = (tag == null || tag.isEmpty()) ? 'l' : tag.charAt(0);
|
|
return new Spacer(align, m.group(2));
|
|
}
|
|
|
|
public static boolean isSpacer(String channelName) {
|
|
return parse(channelName) != null;
|
|
}
|
|
|
|
/** Builds the visible label for a spacer at roughly the given character width. */
|
|
public static String render(Spacer s, int width) {
|
|
String caption = s.caption == null ? "" : s.caption;
|
|
if (s.align == '*') {
|
|
if (caption.isEmpty()) return "";
|
|
StringBuilder sb = new StringBuilder();
|
|
while (sb.length() < width) sb.append(caption);
|
|
return sb.substring(0, Math.max(caption.length(), Math.min(sb.length(), width)));
|
|
}
|
|
if (s.align == 'c') {
|
|
int pad = Math.max(0, (width - caption.length()) / 2);
|
|
return " ".repeat(pad) + caption;
|
|
}
|
|
if (s.align == 'r') {
|
|
int pad = Math.max(0, width - caption.length());
|
|
return " ".repeat(pad) + caption;
|
|
}
|
|
return caption;
|
|
}
|
|
}
|