From 395f04254287be73bf31644c58b75186e102269d Mon Sep 17 00:00:00 2001 From: Wolfgang Schwendtbauer Date: Sun, 19 Mar 2023 15:15:10 +0100 Subject: [PATCH] Add 'minimize to system tray' toggle --- .../java/com/jagrosh/jmusicbot/gui/GUI.java | 102 ++++++++++++++---- .../jagrosh/jmusicbot/gui/OptionsPanel.java | 58 ++++++++++ src/main/resources/icon16.png | Bin 0 -> 2048 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..1003990c2e7dff149cc68a9cbe3d3ea4435a0555 GIT binary patch literal 2048 zcmah~Yfuwc6kd!}gfj9H5oui(P!N+%f&{ZB5eU!9BG2*=A0gS0ElD;eO9-G9QBaGb zh}tPtDM(R@U`3&|ylU}T1Zf>QqP1%2j7p2jbc&B^=}kZo(e}qCd++z1@0@$ixo5XU zMTS~iI$J^zWE~zB6a)TkjE}_>@Vl#6!GoZw$H}-vIuVb+q?C#!kx{7x%b?N#9D)Q( z4H}6wouJ`VB8^lFkq1p}2u#X^NP;iU#x-I>L55{(iP-GOIB9melrKY;iYx^N3<#(Q zS^^tXO0^C%2oaMm2HuU^C<2=(bh;2p#G_y_r6pirmM@Eqh%8}&Rwl<{f+pU+3xT$IaY0tQo;rKTkYrdsD_lo-(nB6LzMsi8?q4I4Ej zsZ<6nL=b?(qvA9vA6HlFMvo5?ff^B%!(yW^(+LCl2D%ZMMAs-Nn$jsK&Da4ZxEO;c z8G`h^-ozl$ypD|H|4mn^CLBXY2kSv1Mw2=rrWX!$aakGyjUjYYhE_@h>j^dOX3B&y zFIc!rl14-j>NHv*L^!-xfCN(Z>b_A(nPIF%yqW~Ax#K2@wxN56ysph8$dCoq_nZ1tqEXc@-l$Mf{N`UEN zLIdIOU@?!w=kb_a)`$!!8U}1hc~+2w1}rX{>%(OGFgg4<4j1$B!+f~jY!1d|o0Ls# za2I3}TJnEGqj7g-%tP2s1mXc*i z37N?`kQ+gDl$_3#Xo-L{P+%bvAeWP%K3Q;-v2$TA%w@4zizb?6DhMF==EI?*p`per z_aZg{Iw^XAiSW`L1$HBQ;O>JVf{slQuo#;|gc=MVEtoQKLn$*M$ZR7C>N2Sw5ad~$ zQQWkQ5n!{W&HcR~H``Q+#MUF(<5xx=&vAOIKXbQ5h-$ab4A-4~tbn}QHFKhDRO@Cw zou%+jw92cnNUdq8*ioSCvascxxYYGk+l|@!wA0QPJ(F6>=hmOfb1b#^`pzLM_22fq zl#{p0y{qo_M;HWwD|6b;rk+bLORD+j)P`DuU+%qzw0k!`t`-(}30jh)@L%lI2|peu zZre+a&70-W%K6K%w+xSre{w~}w6n}>z^@*7dUkO2(aMISUpBie=f%c-cwgFjruaf< zzK6arv%)?#4^me-xos^o3y}@=Nq32oqUW~_FWIoK`L_k!nmyf#uEC{KRz(-a2wgc| z*?}PiyL*S**7uZ%H}&)vL5oDr=hA0f^(&9zZQsdgKjM-%VAiE;c=k;6cH6d9b>u;z zrmp>7FkVQt_r68{T*F}wF?-L{UUYAE5vMz(By=|?4)k6Yg=X3$l^pwK^MRFj_x{=S zIjS#B8~DD_tp$l_ci+C zJNvif+&6#R*UdTTQZ#K-G@j#&_a)@k`DLBgD?%I%hpMWD#oNuCJL}7@tQ&kkIRZ|e z&)Di%v}gLZ(n}{?qUSMg=WkB#=q&vGqvj_M4Sr^~7I)n#=`YLA9qt^cZoFRGD!R6j z{gXLV*u(6soyxGQj~wK;-xOGLWe)zIcAAA9`OHG^QPKptf013+l2Gu;TwKXJcHKK) zUeaUdT}`gsUlQlRTO3)m{Bm90mF{W=44dB_su=dYX{*UeIan{gZv1eE2S*0g1+K~a E7w_2JtpET3 literal 0 HcmV?d00001