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; } }