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. 118
      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

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

@ -1,15 +1,22 @@
package org.qora.gui;
import java.awt.AWTException;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
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 javax.swing.JDialog;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
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.Logger;
@ -24,15 +31,47 @@ public class SysTray {
private static SysTray instance;
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() {
if (!SystemTray.isSupported())
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);
@ -43,25 +82,58 @@ public class SysTray {
}
}
class ClosingWorker extends SwingWorker<Void, Void> {
private void createHiddenDialog() {
if (hiddenDialog != null)
return;
hiddenDialog = new JDialog();
hiddenDialog.setUndecorated(true);
hiddenDialog.setSize(10, 10);
hiddenDialog.addWindowFocusListener(new WindowFocusListener () {
@Override
protected Void doInBackground() {
Controller.getInstance().shutdown();
return null;
public void windowLostFocus (WindowEvent we ) {
destroyHiddenDialog();
}
@Override
protected void done() {
System.exit(0);
public void windowGainedFocus (WindowEvent we) {
}
});
}
private void destroyHiddenDialog() {
if (hiddenDialog == null)
return;
hiddenDialog.setVisible(false);
hiddenDialog.dispose();
hiddenDialog = null;
}
private JPopupMenu createJPopupMenu() {
JPopupMenu menu = new JPopupMenu();
menu.addPopupMenuListener(new PopupMenuListener() {
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
}
private PopupMenu createPopupMenu() {
PopupMenu menu = new PopupMenu();
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
destroyHiddenDialog();
}
MenuItem openUi = new MenuItem(Translator.INSTANCE.translate("SysTray", "OPEN_NODE_UI"));
@Override
public void popupMenuCanceled(PopupMenuEvent e) {
}
});
JMenuItem openUi = new JMenuItem(Translator.INSTANCE.translate("SysTray", "OPEN_NODE_UI"));
openUi.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
destroyHiddenDialog();
try {
URLViewer.openWebpage(new URL("http://localhost:" + Settings.getInstance().getUiPort()));
} catch (Exception e1) {
@ -71,9 +143,12 @@ public class SysTray {
});
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() {
@Override
public void actionPerformed(ActionEvent e) {
destroyHiddenDialog();
new ClosingWorker().execute();
}
});
@ -82,6 +157,19 @@ public class SysTray {
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() {
if (instance == null)
instance = new SysTray();

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

@ -1,7 +1,7 @@
# SysTray pop-up menu
OPEN_NODE_UI=开启界面
EXIT=退出软件
OPEN_NODE_UI=\u5F00\u542F\u754C\u9762
EXIT=\u9000\u51FA\u8F6F\u4EF6
# Nagging about lack of NTP time sync
NTP_NAG_CAPTION=没有连接上节点?
NTP_NAG_TEXT=请启用Windows自动时间同步。
NTP_NAG_CAPTION=\u6CA1\u6709\u8FDE\u63A5\u4E0A\u8282\u70B9\uFF1F
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.qora.gui.SplashFrame;
import org.qora.gui.SysTray;
public class GuiTests {
@ -14,4 +15,13 @@ public class GuiTests {
splashFrame.dispose();
}
@Test
public void testSysTray() throws InterruptedException {
SysTray.getInstance();
while(true) {
Thread.sleep(2000L);
}
}
}

Loading…
Cancel
Save