forked from Qortal/qortal
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
This commit is contained in:
parent
6942c02700
commit
f8b496ff3c
@ -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,6 +82,81 @@ public class SysTray {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createHiddenDialog() {
|
||||||
|
if (hiddenDialog != null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hiddenDialog = new JDialog();
|
||||||
|
hiddenDialog.setUndecorated(true);
|
||||||
|
hiddenDialog.setSize(10, 10);
|
||||||
|
hiddenDialog.addWindowFocusListener(new WindowFocusListener () {
|
||||||
|
@Override
|
||||||
|
public void windowLostFocus (WindowEvent we ) {
|
||||||
|
destroyHiddenDialog();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@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() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
destroyHiddenDialog();
|
||||||
|
|
||||||
|
try {
|
||||||
|
URLViewer.openWebpage(new URL("http://localhost:" + Settings.getInstance().getUiPort()));
|
||||||
|
} catch (Exception e1) {
|
||||||
|
LOGGER.error("Unable to open node UI in browser");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
menu.add(openUi);
|
||||||
|
|
||||||
|
JMenuItem exit = new JMenuItem(Translator.INSTANCE.translate("SysTray", "EXIT"));
|
||||||
|
exit.addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
destroyHiddenDialog();
|
||||||
|
|
||||||
|
new ClosingWorker().execute();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
menu.add(exit);
|
||||||
|
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
class ClosingWorker extends SwingWorker<Void, Void> {
|
class ClosingWorker extends SwingWorker<Void, Void> {
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground() {
|
protected Void doInBackground() {
|
||||||
@ -56,32 +170,6 @@ public class SysTray {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private PopupMenu createPopupMenu() {
|
|
||||||
PopupMenu menu = new PopupMenu();
|
|
||||||
|
|
||||||
MenuItem openUi = new MenuItem(Translator.INSTANCE.translate("SysTray", "OPEN_NODE_UI"));
|
|
||||||
openUi.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
try {
|
|
||||||
URLViewer.openWebpage(new URL("http://localhost:" + Settings.getInstance().getUiPort()));
|
|
||||||
} catch (Exception e1) {
|
|
||||||
LOGGER.error("Unable to open node UI in browser");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
menu.add(openUi);
|
|
||||||
|
|
||||||
MenuItem exit = new MenuItem(Translator.INSTANCE.translate("SysTray", "EXIT"));
|
|
||||||
exit.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
new ClosingWorker().execute();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
menu.add(exit);
|
|
||||||
|
|
||||||
return menu;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SysTray getInstance() {
|
public static SysTray getInstance() {
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
instance = new SysTray();
|
instance = new SysTray();
|
||||||
|
@ -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
|
||||||
|
@ -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…
x
Reference in New Issue
Block a user