diff --git a/ts3-client/README.md b/ts3-client/README.md index 6172397..2299844 100644 --- a/ts3-client/README.md +++ b/ts3-client/README.md @@ -292,7 +292,7 @@ swing/ com.ts3client ├── Spacers TS3 spacer-channel name parsing/rendering ├── InfoPanel channel description / client group + details view ├── ChatPanel chat log + input - ├── SettingsDialog the Options dialog: TS3-style page sidebar + banner; one panel per page (ApplicationPanel, …, ChatLogsPanel) + ├── SettingsDialog the Options dialog: TS3-style page sidebar; one panel per page (ApplicationPanel, …, ChatLogsPanel) ├── HotkeysPanel hotkey list (Options → Hotkeys) ├── HotkeyDialog add/edit one hotkey: action, combination, trigger, scope ├── HotkeyService bindings + engine + input hook, for the dialogs diff --git a/ts3-client/swing/src/main/java/com/ts3client/ui/OptionsBanner.java b/ts3-client/swing/src/main/java/com/ts3client/ui/OptionsBanner.java deleted file mode 100644 index 8a52a43..0000000 --- a/ts3-client/swing/src/main/java/com/ts3client/ui/OptionsBanner.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.ts3client.ui; - -import com.formdev.flatlaf.util.ScaledEmptyBorder; -import com.formdev.flatlaf.util.UIScale; - -import javax.swing.BoxLayout; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.UIManager; -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Font; -import java.awt.GradientPaint; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.RenderingHints; - -/** - * The heading over an Options page: its title and subtitle on an accent-tinted band, with - * the page's icon at the far end, after TS3's blue page banners. - */ -final class OptionsBanner extends JPanel { - - private final JLabel title = new JLabel() { - @Override - public void updateUI() { - super.updateUI(); - Font base = UIManager.getFont("Label.font"); - if (base != null) setFont(base.deriveFont(Font.BOLD, base.getSize2D() * 1.4f)); - } - }; - private final JLabel subtitle = new JLabel(); - private final JLabel icon = new JLabel(); - private OptionsPage page; - - OptionsBanner() { - super(new BorderLayout(UIScale.scale(12), 0)); - setOpaque(false); - setBorder(new ScaledEmptyBorder(8, 12, 8, 12)); - - JPanel text = new JPanel(); - text.setOpaque(false); - text.setLayout(new BoxLayout(text, BoxLayout.Y_AXIS)); - text.add(title); - text.add(subtitle); - add(text, BorderLayout.CENTER); - add(icon, BorderLayout.EAST); - } - - void show(OptionsPage page) { - this.page = page; - title.setText(page.title()); - subtitle.setText(page.subtitle()); - subtitle.setVisible(page.subtitle() != null && !page.subtitle().isEmpty()); - refreshIcon(); - } - - /** Picks the icon up again from the active pack, after it changed. */ - void refreshIcon() { - icon.setIcon(page == null ? null : page.icon(UIScale.scale(OptionsSidebar.ICON_SIZE))); - } - - @Override - protected void paintComponent(Graphics g) { - Color accent = UIManager.getColor("Component.accentColor"); - if (accent == null) accent = UIManager.getColor("List.selectionBackground"); - Graphics2D g2 = (Graphics2D) g.create(); - try { - g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2.setPaint(new GradientPaint(0, 0, withAlpha(accent, 70), 0, getHeight(), withAlpha(accent, 20))); - int arc = UIScale.scale(8); - g2.fillRoundRect(0, 0, getWidth(), getHeight(), arc, arc); - } finally { - g2.dispose(); - } - super.paintComponent(g); - } - - private static Color withAlpha(Color c, int alpha) { - return new Color(c.getRed(), c.getGreen(), c.getBlue(), alpha); - } -} diff --git a/ts3-client/swing/src/main/java/com/ts3client/ui/OptionsPage.java b/ts3-client/swing/src/main/java/com/ts3client/ui/OptionsPage.java index bf4af81..2852c19 100644 --- a/ts3-client/swing/src/main/java/com/ts3client/ui/OptionsPage.java +++ b/ts3-client/swing/src/main/java/com/ts3client/ui/OptionsPage.java @@ -5,14 +5,14 @@ import javax.swing.JComponent; import java.util.List; /** - * One page of the Options dialog, as the sidebar lists it and the banner introduces it. + * One page of the Options dialog, as the sidebar lists it. * * @param iconKeys TeamSpeak icon keys to try in turn, since packs differ in what they ship */ -record OptionsPage(String title, String subtitle, List iconKeys, JComponent content) { +record OptionsPage(String title, List iconKeys, JComponent content) { - OptionsPage(String title, String subtitle, JComponent content, String... iconKeys) { - this(title, subtitle, List.of(iconKeys), content); + OptionsPage(String title, JComponent content, String... iconKeys) { + this(title, List.of(iconKeys), content); } /** @return the page's icon at {@code size} pixels, or {@code null} when the pack has none */ diff --git a/ts3-client/swing/src/main/java/com/ts3client/ui/SettingsDialog.java b/ts3-client/swing/src/main/java/com/ts3client/ui/SettingsDialog.java index 9569cd6..98187e0 100644 --- a/ts3-client/swing/src/main/java/com/ts3client/ui/SettingsDialog.java +++ b/ts3-client/swing/src/main/java/com/ts3client/ui/SettingsDialog.java @@ -26,7 +26,7 @@ import java.util.List; /** * Options dialog, laid out like TS3's: a sidebar of pages on the left, the chosen page - * under its banner on the right, OK/Cancel/Apply below. Each page owns its controls and + * on the right, OK/Cancel/Apply below. Each page owns its controls and * writes {@link Settings} when applied; this class wires the audio pages, which preview * themselves live against the running audio subsystem, and owns the apply plumbing. */ @@ -68,26 +68,16 @@ public final class SettingsDialog extends JDialog { chatLogsPanel = new ChatLogsPanel(settings); List pages = List.of( - new OptionsPage("Application", "General Application Options", scrollable(applicationPanel), - "SETTINGS"), - new OptionsPage("myTeamSpeak", "Account and Synchronization", myTeamSpeak, - "MYTS_ACCOUNT"), - new OptionsPage("Playback", "Configure the Playback Sound System", scrollable(playbackPanel), - "PLAYBACK"), - new OptionsPage("Capture", "Configure the Capture Sound System", scrollable(capturePanel), - "CAPTURE"), - new OptionsPage("Design", "Configure the Design of TeamSpeak", designPanel, - "GUISETUP", "CHANNEL_EDIT"), - new OptionsPage("Hotkeys", "Configure Hotkeys", hotkeysPanel, - "HOTKEYS"), - new OptionsPage("Contacts", "Configure Contacts and Whispers", scrollable(contactsPanel), - "CONTACT", "EDIT_FRIEND_FOE_STATUS"), - new OptionsPage("Chat", "Configure the Chat Tabs", scrollable(chatLogsPanel), - "CHANNEL_CHAT", "PLAYER_CHAT"), - new OptionsPage("Notifications", "Configure the Notifications", notificationsPanel, - "NOTIFICATIONS")); + new OptionsPage("Application", scrollable(applicationPanel), "SETTINGS"), + new OptionsPage("myTeamSpeak", myTeamSpeak, "MYTS_ACCOUNT"), + new OptionsPage("Playback", scrollable(playbackPanel), "PLAYBACK"), + new OptionsPage("Capture", scrollable(capturePanel), "CAPTURE"), + new OptionsPage("Design", designPanel, "GUISETUP", "CHANNEL_EDIT"), + new OptionsPage("Hotkeys", hotkeysPanel, "HOTKEYS"), + new OptionsPage("Contacts", scrollable(contactsPanel), "CONTACT", "EDIT_FRIEND_FOE_STATUS"), + new OptionsPage("Chat", scrollable(chatLogsPanel), "CHANNEL_CHAT", "PLAYER_CHAT"), + new OptionsPage("Notifications", notificationsPanel, "NOTIFICATIONS")); - OptionsBanner banner = new OptionsBanner(); CardLayout cards = new CardLayout(); JPanel content = new JPanel(cards); for (OptionsPage page : pages) content.add(page.content(), page.title()); @@ -96,7 +86,6 @@ public final class SettingsDialog extends JDialog { sidebar.addListSelectionListener(e -> { OptionsPage page = sidebar.getSelectedValue(); if (page == null) return; - banner.show(page); cards.show(content, page.title()); lastPage = sidebar.getSelectedIndex(); }); @@ -104,23 +93,16 @@ public final class SettingsDialog extends JDialog { JScrollPane sidebarScroll = new JScrollPane(sidebar, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER); - JPanel page = new JPanel(new BorderLayout(0, UIScale.scale(4))); - page.add(banner, BorderLayout.NORTH); - page.add(content, BorderLayout.CENTER); - JPanel body = new JPanel(new BorderLayout(UIScale.scale(8), 0)); body.setBorder(new ScaledEmptyBorder(10, 10, 0, 10)); body.add(sidebarScroll, BorderLayout.WEST); - body.add(page, BorderLayout.CENTER); + body.add(content, BorderLayout.CENTER); getContentPane().setLayout(new BorderLayout()); getContentPane().add(body, BorderLayout.CENTER); getContentPane().add(buildButtons(), BorderLayout.SOUTH); - Runnable iconsChanged = () -> SwingUtilities.invokeLater(() -> { - sidebar.repaint(); - banner.refreshIcon(); - }); + Runnable iconsChanged = () -> SwingUtilities.invokeLater(sidebar::repaint); IconTheme.get().addListener(iconsChanged); // The microphone test hears typing too, so typing attenuation can be tried out here.