Browse Source

Convert SysTray to use JPopupMenu for Unicode support

Correct Systray_zh.properties to ISO 8859-1 instead of UTF-8.

Added SysTray test to GuiTests
pull/67/head
catbref 5 years ago
parent
commit
f8b496ff3c
  1. 126
      src/main/java/org/qora/gui/SysTray.java
  2. 8
      src/main/resources/i18n/SysTray_zh.properties
  3. 10
      src/test/java/org/qora/test/GuiTests.java

126
src/main/java/org/qora/gui/SysTray.java

@ -1,15 +1,22 @@
package org.qora.gui; package org.qora.gui;
import java.awt.AWTException; import java.awt.AWTException;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray; import java.awt.SystemTray;
import java.awt.TrayIcon; import java.awt.TrayIcon;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.net.URL; import java.net.URL;
import javax.swing.JDialog;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -24,15 +31,47 @@ public class SysTray {
private static SysTray instance; private static SysTray instance;
private TrayIcon trayIcon = null; private TrayIcon trayIcon = null;
private PopupMenu popupMenu = null; private JPopupMenu popupMenu = null;
/** The hidden dialog has 'focus' when menu displayed so closes the menu when user clicks elsewhere. */
private JDialog hiddenDialog = null;
private SysTray() { private SysTray() {
if (!SystemTray.isSupported()) if (!SystemTray.isSupported())
return; return;
this.popupMenu = createPopupMenu(); this.popupMenu = createJPopupMenu();
this.trayIcon = new TrayIcon(Gui.loadImage("icons/icon32.png"), "qora-core", popupMenu); // Build TrayIcon without AWT PopupMenu (which doesn't support Unicode)...
this.trayIcon = new TrayIcon(Gui.loadImage("icons/icon32.png"), "qora-core", null);
// ...and attach mouse listener instead so we can use JPopupMenu (which does support Unicode)
this.trayIcon.addMouseListener(new MouseAdapter() {
@Override
public void mousePressed (MouseEvent me) {
this.maybePopupMenu(me);
}
@Override
public void mouseReleased (MouseEvent me) {
this.maybePopupMenu(me);
}
private void maybePopupMenu(MouseEvent me) {
if (me.isPopupTrigger()) {
// We destroy, then recreate, the hidden dialog to prevent taskbar entries on X11
if (!popupMenu.isVisible())
destroyHiddenDialog();
createHiddenDialog();
hiddenDialog.setLocation(me.getX() + 1, me.getY() - 1);
popupMenu.setLocation(me.getX() + 1, me.getY() - 1);
popupMenu.setInvoker(hiddenDialog);
hiddenDialog.setVisible(true);
popupMenu.setVisible(true);
}
}
});
this.trayIcon.setImageAutoSize(true); this.trayIcon.setImageAutoSize(true);
@ -43,25 +82,58 @@ public class SysTray {
} }
} }
class ClosingWorker extends SwingWorker<Void, Void> { private void createHiddenDialog() {
@Override if (hiddenDialog != null)
protected Void doInBackground() { return;
Controller.getInstance().shutdown();
return null;
}
@Override hiddenDialog = new JDialog();
protected void done() { hiddenDialog.setUndecorated(true);
System.exit(0); hiddenDialog.setSize(10, 10);
} hiddenDialog.addWindowFocusListener(new WindowFocusListener () {
@Override
public void windowLostFocus (WindowEvent we ) {
destroyHiddenDialog();
}
@Override
public void windowGainedFocus (WindowEvent we) {
}
});
} }
private PopupMenu createPopupMenu() { private void destroyHiddenDialog() {
PopupMenu menu = new PopupMenu(); if (hiddenDialog == null)
return;
MenuItem openUi = new MenuItem(Translator.INSTANCE.translate("SysTray", "OPEN_NODE_UI")); hiddenDialog.setVisible(false);
hiddenDialog.dispose();
hiddenDialog = null;
}
private JPopupMenu createJPopupMenu() {
JPopupMenu menu = new JPopupMenu();
menu.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
destroyHiddenDialog();
}
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
});
JMenuItem openUi = new JMenuItem(Translator.INSTANCE.translate("SysTray", "OPEN_NODE_UI"));
openUi.addActionListener(new ActionListener() { openUi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
destroyHiddenDialog();
try { try {
URLViewer.openWebpage(new URL("http://localhost:" + Settings.getInstance().getUiPort())); URLViewer.openWebpage(new URL("http://localhost:" + Settings.getInstance().getUiPort()));
} catch (Exception e1) { } catch (Exception e1) {
@ -71,9 +143,12 @@ public class SysTray {
}); });
menu.add(openUi); menu.add(openUi);
MenuItem exit = new MenuItem(Translator.INSTANCE.translate("SysTray", "EXIT")); JMenuItem exit = new JMenuItem(Translator.INSTANCE.translate("SysTray", "EXIT"));
exit.addActionListener(new ActionListener() { exit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
destroyHiddenDialog();
new ClosingWorker().execute(); new ClosingWorker().execute();
} }
}); });
@ -82,6 +157,19 @@ public class SysTray {
return menu; return menu;
} }
class ClosingWorker extends SwingWorker<Void, Void> {
@Override
protected Void doInBackground() {
Controller.getInstance().shutdown();
return null;
}
@Override
protected void done() {
System.exit(0);
}
}
public static SysTray getInstance() { public static SysTray getInstance() {
if (instance == null) if (instance == null)
instance = new SysTray(); instance = new SysTray();

8
src/main/resources/i18n/SysTray_zh.properties

@ -1,7 +1,7 @@
# SysTray pop-up menu # SysTray pop-up menu
OPEN_NODE_UI=开启界面 OPEN_NODE_UI=\u5F00\u542F\u754C\u9762
EXIT=退出软件 EXIT=\u9000\u51FA\u8F6F\u4EF6
# Nagging about lack of NTP time sync # Nagging about lack of NTP time sync
NTP_NAG_CAPTION=没有连接上节点? NTP_NAG_CAPTION=\u6CA1\u6709\u8FDE\u63A5\u4E0A\u8282\u70B9\uFF1F
NTP_NAG_TEXT=请启用Windows自动时间同步。 NTP_NAG_TEXT=\u8BF7\u542F\u7528Windows\u81EA\u52A8\u65F6\u95F4\u540C\u6B65\u3002

10
src/test/java/org/qora/test/GuiTests.java

@ -2,6 +2,7 @@ package org.qora.test;
import org.junit.Test; import org.junit.Test;
import org.qora.gui.SplashFrame; import org.qora.gui.SplashFrame;
import org.qora.gui.SysTray;
public class GuiTests { public class GuiTests {
@ -14,4 +15,13 @@ public class GuiTests {
splashFrame.dispose(); splashFrame.dispose();
} }
@Test
public void testSysTray() throws InterruptedException {
SysTray.getInstance();
while(true) {
Thread.sleep(2000L);
}
}
} }

Loading…
Cancel
Save