From 27ae5d2bd9a9ba614440f47d88a0e2f31e95cc2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?lillie=E2=84=A2?= <66176496+lilliepad1@users.noreply.github.com> Date: Thu, 11 Jul 2024 00:36:30 -0400 Subject: [PATCH] Implement #1330 https://github.com/jagrosh/MusicBot/pull/1330 --- .../java/com/jagrosh/jmusicbot/gui/GUI.java | 102 ++++++++++++++---- .../jagrosh/jmusicbot/gui/OptionsPanel.java | 58 ++++++++++ src/main/resources/icon16.png | Bin 0 -> 877 bytes 3 files changed, 141 insertions(+), 19 deletions(-) create mode 100644 src/main/java/com/jagrosh/jmusicbot/gui/OptionsPanel.java create mode 100644 src/main/resources/icon16.png diff --git a/src/main/java/com/jagrosh/jmusicbot/gui/GUI.java b/src/main/java/com/jagrosh/jmusicbot/gui/GUI.java index e3f47ae7a..3a82a07fb 100644 --- a/src/main/java/com/jagrosh/jmusicbot/gui/GUI.java +++ b/src/main/java/com/jagrosh/jmusicbot/gui/GUI.java @@ -15,11 +15,10 @@ */ package com.jagrosh.jmusicbot.gui; -import java.awt.event.WindowEvent; -import java.awt.event.WindowListener; -import javax.swing.JFrame; -import javax.swing.JTabbedPane; -import javax.swing.WindowConstants; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + import com.jagrosh.jmusicbot.Bot; @@ -27,41 +26,37 @@ * * @author John Grosh */ -public class GUI extends JFrame +public class GUI extends JFrame { private final ConsolePanel console; private final Bot bot; - - public GUI(Bot bot) + private final OptionsPanel optionsPanel; + + public GUI(Bot bot) { super(); this.bot = bot; console = new ConsolePanel(); + optionsPanel = new OptionsPanel(); } - + public void init() { setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); setTitle("JMusicBot"); JTabbedPane tabs = new JTabbedPane(); tabs.add("Console", console); + tabs.add("Options", optionsPanel); getContentPane().add(tabs); pack(); setLocationRelativeTo(null); setVisible(true); - addWindowListener(new WindowListener() + addWindowListener(new WindowListener() { @Override public void windowOpened(WindowEvent e) { /* unused */ } - @Override public void windowClosing(WindowEvent e) + @Override public void windowClosing(WindowEvent e) { - try - { - bot.shutdown(); - } - catch(Exception ex) - { - System.exit(0); - } + shutdown(); } @Override public void windowClosed(WindowEvent e) { /* unused */ } @Override public void windowIconified(WindowEvent e) { /* unused */ } @@ -69,5 +64,74 @@ public void init() @Override public void windowActivated(WindowEvent e) { /* unused */ } @Override public void windowDeactivated(WindowEvent e) { /* unused */ } }); + + if (SystemTray.isSupported()) + { + setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + setupMinimizeToTray(); + } + } + + private void setupMinimizeToTray() + { + Image icon = Toolkit.getDefaultToolkit().getImage(getClass().getResource("/icon16.png")); + MenuItem exit = new MenuItem("Exit"); + exit.addActionListener(e -> shutdown()); + + MenuItem nameLabel = new MenuItem("JMusicBot"); + nameLabel.setEnabled(false); + + PopupMenu menu = new PopupMenu(); + menu.add(nameLabel); + menu.addSeparator(); + menu.add(exit); + + SystemTray tray = SystemTray.getSystemTray(); + TrayIcon trayIcon = new TrayIcon(icon, "JMusicBot", menu); + + // Restore the window when the user clicks the tray icon + trayIcon.addMouseListener(new MouseAdapter() + { + @Override public void mouseClicked(MouseEvent e) + { + if (e.getButton() != MouseEvent.BUTTON1) + { + return; + } + + setVisible(true); + setExtendedState(JFrame.NORMAL); + tray.remove(trayIcon); + } + }); + + // Minimize the window to the system tray when the user clicks the minimize button + // and the option "minimize to tray" is active + addWindowStateListener(e -> { + if (e.getNewState() == JFrame.ICONIFIED && optionsPanel.isMinimizeToTraySelected()) + { + try + { + setVisible(false); + tray.add(trayIcon); + } + catch (AWTException ex) + { + System.err.println("TrayIcon could not be added."); + } + } + }); + } + + private void shutdown() + { + try + { + bot.shutdown(); + } + catch(Exception ex) + { + System.exit(0); + } } } diff --git a/src/main/java/com/jagrosh/jmusicbot/gui/OptionsPanel.java b/src/main/java/com/jagrosh/jmusicbot/gui/OptionsPanel.java new file mode 100644 index 000000000..3734f8d24 --- /dev/null +++ b/src/main/java/com/jagrosh/jmusicbot/gui/OptionsPanel.java @@ -0,0 +1,58 @@ +/* + * Copyright 2016 John Grosh . + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.jagrosh.jmusicbot.gui; + +import javax.swing.*; +import java.util.prefs.Preferences; + +/** + * @author Wolfgang Schwendtbauer + */ +public class OptionsPanel extends JPanel +{ + private static final String KEY_MINIMIZE_TO_SYSTEM_TRAY = "minimizeToSystemTray"; + + private final Preferences prefs; + private final JCheckBox minimizeToTrayCheckbox; + + public OptionsPanel() + { + prefs = Preferences.userNodeForPackage(getClass()); + + setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); + + minimizeToTrayCheckbox = new JCheckBox("Minimize to system tray"); + add(minimizeToTrayCheckbox); + + loadPreferences(); + addListeners(); + } + + private void loadPreferences() + { + minimizeToTrayCheckbox.setSelected(prefs.getBoolean(KEY_MINIMIZE_TO_SYSTEM_TRAY, false)); + } + + private void addListeners() + { + minimizeToTrayCheckbox.addActionListener(e -> prefs.putBoolean(KEY_MINIMIZE_TO_SYSTEM_TRAY, minimizeToTrayCheckbox.isSelected())); + } + + public boolean isMinimizeToTraySelected() + { + return minimizeToTrayCheckbox.isSelected(); + } +} diff --git a/src/main/resources/icon16.png b/src/main/resources/icon16.png new file mode 100644 index 0000000000000000000000000000000000000000..08ad06ea5282590e5c0a46a0071095615e45b4fa GIT binary patch literal 877 zcmV-z1CsoSP) zU2IfE9L0Zg_wMa>zi74#;UkEaQa~}m#1|8^E$xeB3p9j^ps6NCNRe33NTQJ%2~Bta zlr%sUQZ;G-<)uJ^l_(GciN=Hnv}nQQdsh}wyUXt0-MM$1d#evVG09~9b92v`nRCux zG&eUZ(=-W(!<0%Ts?{pqh{xk7rN|cw{ytPwgJoG1^xkz{gb>7HF+^Kio9gO%hLMpG z?%c_dOeQf50~L(W-@lizD{z$H+n;an@y?h22bNMIIyySk-uDi1Z#;;tMrml6#gX$C zf7&JiL(o_!i3J5?cNO1%^ErS2o+h6?j|VOmi-`92cI7w@13L~;pNw++>pvK~tgz}W z>gLy@9EIym3CkaINYqMpe)Jt@zuN9UO>}m4`UHD+9p>~81+L^=x)&9hHr3+jr6|8- zLmKSjNJaZ2E)hF~v}}4eEg=#KBktbLtL(KPQ)Wm8PgK~vC`TYR32JJQ!esk!0H>mG zs>;93+NTXL9oDU1qlMIB_HF4?w{B*6b?t6);~ARg8Hk8>AXtM|ldYdP*d;WHzJ(@o zZS-`weDQhm`8*<(N-3{+w(mHke zHVZEYzR#f$``_Hc^ri-kaGbnj5~~%QJ}3ENxaxytS(B9XbISL){?~H^0)YvFmlr?9 zvnx6ny^!X&vdxFR@AG7;h1Wjl=f*AQd#Cs>fudS+Nkpskbf4nwp@WDQmM&5IdwVbz zJc_!K=60^Y=+I{*8XqJuvxzyYR?)pCuYu^4g01Z|gK+FXhGRqf5M9fcsZV=e#GF4D z`O^i=-HOnYlW1MjCqBEhVOUng_*M>5yGWMNYy zkI!k)0dhEaase09ZAcwQDQqk=%R@6ZPBc?XON;V~|FZ2l5{X27g*|&ctGxQx>jPSc z>CBtGOn(dNZVgRD*=wfzfjvUow)NCuK=~(o!#m&~C`*%44139E00000NkvXXu0mjf D?q!*5 literal 0 HcmV?d00001