|
|
|
@ -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> { |
|
|
|
|
@Override |
|
|
|
|
protected Void doInBackground() { |
|
|
|
|
Controller.getInstance().shutdown(); |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
|
private void createHiddenDialog() { |
|
|
|
|
if (hiddenDialog != null) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
protected void done() { |
|
|
|
|
System.exit(0); |
|
|
|
|
} |
|
|
|
|
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 PopupMenu createPopupMenu() { |
|
|
|
|
PopupMenu menu = new PopupMenu(); |
|
|
|
|
private void destroyHiddenDialog() { |
|
|
|
|
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() { |
|
|
|
|
@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(); |
|
|
|
|