Added SWT compatible tray type (it is just a wrapper for SWT SystemTray)
This commit is contained in:
parent
bb0eb87e90
commit
444562f3c6
|
@ -21,6 +21,7 @@ import dorkbox.systemTray.linux.GtkSystemTray;
|
|||
import dorkbox.systemTray.linux.jna.AppIndicator;
|
||||
import dorkbox.systemTray.linux.jna.GtkSupport;
|
||||
import dorkbox.systemTray.swing.SwingSystemTray;
|
||||
import dorkbox.systemTray.swt.SwtSystemTray;
|
||||
import dorkbox.util.OS;
|
||||
import dorkbox.util.Property;
|
||||
import dorkbox.util.process.ShellProcessBuilder;
|
||||
|
@ -76,7 +77,10 @@ class SystemTray {
|
|||
// maybe we should load the SWT version? (SWT's use of GTK is incompatible with how we use GTK)
|
||||
|
||||
if (isSwtLoaded) {
|
||||
|
||||
try {
|
||||
trayType = SwtSystemTray.class;
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Note: AppIndicators DO NOT support tooltips. We could try to create one, by creating a GTK widget and attaching it on
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Copyright 2016 dorkbox, llc
|
||||
*
|
||||
* 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 dorkbox.systemTray.swt;
|
||||
|
||||
import dorkbox.systemTray.ImageUtil;
|
||||
import dorkbox.systemTray.MenuEntry;
|
||||
import dorkbox.systemTray.SystemTray;
|
||||
import dorkbox.systemTray.SystemTrayMenuAction;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
import org.eclipse.swt.widgets.Event;
|
||||
import org.eclipse.swt.widgets.Listener;
|
||||
import org.eclipse.swt.widgets.Menu;
|
||||
import org.eclipse.swt.widgets.MenuItem;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
class SwtMenuEntry implements MenuEntry {
|
||||
private final Menu parent;
|
||||
private final SystemTray systemTray;
|
||||
private final MenuItem menuItem;
|
||||
private final Listener selectionListener;
|
||||
|
||||
private volatile String text;
|
||||
String imagePath;
|
||||
private Image image;
|
||||
volatile SystemTrayMenuAction callback;
|
||||
|
||||
public
|
||||
SwtMenuEntry(final Menu parentMenu,
|
||||
final String label,
|
||||
final String imagePath,
|
||||
final Image image,
|
||||
final SystemTrayMenuAction callback,
|
||||
final SystemTray systemTray) {
|
||||
|
||||
this.parent = parentMenu;
|
||||
this.text = label;
|
||||
this.imagePath = imagePath;
|
||||
this.image = image;
|
||||
this.callback = callback;
|
||||
this.systemTray = systemTray;
|
||||
|
||||
menuItem = new MenuItem(parentMenu, SWT.PUSH);
|
||||
menuItem.setText(label);
|
||||
|
||||
selectionListener = new Listener() {
|
||||
public
|
||||
void handleEvent(Event event) {
|
||||
handle();
|
||||
}
|
||||
};
|
||||
menuItem.addListener(SWT.Selection, selectionListener);
|
||||
|
||||
if (image != null && !image.isDisposed()) {
|
||||
menuItem.setImage(image);
|
||||
}
|
||||
}
|
||||
|
||||
private
|
||||
void handle() {
|
||||
SystemTrayMenuAction cb = this.callback;
|
||||
if (cb != null) {
|
||||
cb.onClick(systemTray, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setText(final String newText) {
|
||||
this.text = newText;
|
||||
menuItem.setText(newText);
|
||||
}
|
||||
|
||||
private
|
||||
void setImage_(final String imagePath) {
|
||||
if (imagePath == null) {
|
||||
menuItem.setImage(null);
|
||||
image = null;
|
||||
}
|
||||
else {
|
||||
image = new Image(parent.getShell().getDisplay(), imagePath);
|
||||
menuItem.setImage(image);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setImage(final String imagePath) {
|
||||
if (imagePath == null) {
|
||||
setImage_(null);
|
||||
}
|
||||
else {
|
||||
setImage_(ImageUtil.iconPath(imagePath));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setImage(final URL imageUrl) {
|
||||
if (imageUrl == null) {
|
||||
setImage_(null);
|
||||
}
|
||||
else {
|
||||
setImage_(ImageUtil.iconPath(imageUrl));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setImage(final String cacheName, final InputStream imageStream) {
|
||||
if (imageStream == null) {
|
||||
setImage_(null);
|
||||
}
|
||||
else {
|
||||
setImage_(ImageUtil.iconPath(cacheName, imageStream));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public
|
||||
void setImage(final InputStream imageStream) {
|
||||
if (imageStream == null) {
|
||||
setImage_(null);
|
||||
}
|
||||
else {
|
||||
setImage_(ImageUtil.iconPathNoCache(imageStream));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setCallback(final SystemTrayMenuAction callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void remove() {
|
||||
if (image != null) {
|
||||
image.dispose();
|
||||
}
|
||||
menuItem.dispose();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* Copyright 2016 dorkbox, llc
|
||||
*
|
||||
* 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 dorkbox.systemTray.swt;
|
||||
|
||||
import dorkbox.systemTray.ImageUtil;
|
||||
import dorkbox.systemTray.MenuEntry;
|
||||
import dorkbox.systemTray.SystemTrayMenuAction;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
import org.eclipse.swt.widgets.Event;
|
||||
import org.eclipse.swt.widgets.Listener;
|
||||
import org.eclipse.swt.widgets.Menu;
|
||||
import org.eclipse.swt.widgets.MenuItem;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.swt.widgets.TrayItem;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Class for handling all system tray interaction, via SWING
|
||||
*/
|
||||
public
|
||||
class SwtSystemTray extends dorkbox.systemTray.SystemTray {
|
||||
// volatile SwingSystemTrayMenuPopup menu;
|
||||
volatile MenuItem connectionStatusItem;
|
||||
//
|
||||
// volatile SystemTray tray;
|
||||
// volatile TrayIcon trayIcon;
|
||||
|
||||
private final Display display;
|
||||
private final Shell shell;
|
||||
private final TrayItem tray;
|
||||
|
||||
volatile boolean isActive = false;
|
||||
private final Menu menu;
|
||||
|
||||
/**
|
||||
* Creates a new system tray handler class.
|
||||
*/
|
||||
public
|
||||
SwtSystemTray() {
|
||||
super();
|
||||
|
||||
display = Display.getCurrent();
|
||||
shell = display.getShells()[0];
|
||||
|
||||
tray = new TrayItem(display.getSystemTray(), SWT.NONE);
|
||||
menu = new Menu(shell, SWT.POP_UP);
|
||||
|
||||
tray.addListener(SWT.MenuDetect, new Listener() {
|
||||
public void handleEvent(Event event) {
|
||||
menu.setVisible(true);
|
||||
}
|
||||
});
|
||||
tray.addListener(SWT.Selection, new Listener() {
|
||||
public void handleEvent(Event event) {
|
||||
menu.setVisible(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public
|
||||
void shutdown() {
|
||||
synchronized (this) {
|
||||
for (MenuEntry menuEntry : menuEntries) {
|
||||
menuEntry.remove();
|
||||
}
|
||||
menuEntries.clear();
|
||||
|
||||
connectionStatusItem = null;
|
||||
|
||||
tray.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setStatus(final String infoString) {
|
||||
synchronized (this) {
|
||||
if (connectionStatusItem == null && infoString != null && !infoString.isEmpty()) {
|
||||
deleteMenu();
|
||||
|
||||
connectionStatusItem = new MenuItem(menu, SWT.PUSH);
|
||||
connectionStatusItem.setText(infoString);
|
||||
connectionStatusItem.setEnabled(false);
|
||||
|
||||
createMenu();
|
||||
}
|
||||
else {
|
||||
if (infoString == null || infoString.isEmpty()) {
|
||||
// deletes the status entry only
|
||||
connectionStatusItem.dispose();
|
||||
connectionStatusItem = null;
|
||||
}
|
||||
else {
|
||||
connectionStatusItem.setText(infoString);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the contents of the menu, and unreferences everything in it.
|
||||
*/
|
||||
private void deleteMenu() {
|
||||
// have to remove status from menu
|
||||
if (connectionStatusItem != null) {
|
||||
connectionStatusItem.dispose();
|
||||
}
|
||||
|
||||
synchronized (menuEntries) {
|
||||
// have to remove all other menu entries
|
||||
for (int i = 0; i < menuEntries.size(); i++) {
|
||||
SwtMenuEntry menuEntry__ = (SwtMenuEntry) menuEntries.get(i);
|
||||
menuEntry__.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* recreates the menu items
|
||||
*/
|
||||
private void createMenu() {
|
||||
synchronized (menuEntries) {
|
||||
// now add back other menu entries
|
||||
final SwtMenuEntry[] swtMenuEntries = menuEntries.toArray(new SwtMenuEntry[0]);
|
||||
menuEntries.clear();
|
||||
|
||||
for (int i = 0; i < swtMenuEntries.length; i++) {
|
||||
SwtMenuEntry menuEntry__ = swtMenuEntries[i];
|
||||
addMenuEntry_(menuEntry__.getText(), menuEntry__.imagePath, menuEntry__.callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected
|
||||
void setIcon_(final String iconPath) {
|
||||
tray.setImage(new Image(display, iconPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* Will add a new menu entry, or update one if it already exists
|
||||
*/
|
||||
private
|
||||
void addMenuEntry_(final String menuText, final String imagePath, final SystemTrayMenuAction callback) {
|
||||
if (menuText == null) {
|
||||
throw new NullPointerException("Menu text cannot be null");
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
synchronized (menuEntries) {
|
||||
MenuEntry menuEntry = getMenuEntry(menuText);
|
||||
|
||||
if (menuEntry != null) {
|
||||
throw new IllegalArgumentException("Menu entry already exists for given label '" + menuText + "'");
|
||||
}
|
||||
else {
|
||||
final Image image;
|
||||
if (imagePath != null) {
|
||||
image = new Image(display, imagePath);
|
||||
} else {
|
||||
image = null;
|
||||
}
|
||||
|
||||
menuEntry = new SwtMenuEntry(menu, menuText, imagePath, image, callback, this);
|
||||
menuEntries.add(menuEntry);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void addMenuEntry(String menuText, final String imagePath, final SystemTrayMenuAction callback) {
|
||||
if (imagePath == null) {
|
||||
addMenuEntry_(menuText, null, callback);
|
||||
}
|
||||
else {
|
||||
addMenuEntry_(menuText, ImageUtil.iconPath(imagePath), callback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void addMenuEntry(final String menuText, final URL imageUrl, final SystemTrayMenuAction callback) {
|
||||
if (imageUrl == null) {
|
||||
addMenuEntry_(menuText, null, callback);
|
||||
}
|
||||
else {
|
||||
addMenuEntry_(menuText, ImageUtil.iconPath(imageUrl), callback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void addMenuEntry(final String menuText, final String cacheName, final InputStream imageStream, final SystemTrayMenuAction callback) {
|
||||
if (imageStream == null) {
|
||||
addMenuEntry_(menuText, null, callback);
|
||||
}
|
||||
else {
|
||||
addMenuEntry_(menuText, ImageUtil.iconPath(cacheName, imageStream), callback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public
|
||||
void addMenuEntry(final String menuText, final InputStream imageStream, final SystemTrayMenuAction callback) {
|
||||
if (imageStream == null) {
|
||||
addMenuEntry_(menuText, null, callback);
|
||||
}
|
||||
else {
|
||||
addMenuEntry_(menuText, ImageUtil.iconPathNoCache(imageStream), callback);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,7 +24,6 @@ import org.eclipse.swt.widgets.Display;
|
|||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
|
@ -42,12 +41,6 @@ class TestTraySwt {
|
|||
|
||||
public static
|
||||
void main(String[] args) {
|
||||
// ONLY if manually loading JNA jars.
|
||||
//
|
||||
// Not necessary if using the official JNA downloaded from https://github.com/twall/jna AND THAT JAR is on the classpath
|
||||
//
|
||||
System.load(new File("../../resources/Dependencies/jna/linux_64/libjna.so").getAbsolutePath()); //64bit linux library
|
||||
|
||||
new TestTraySwt();
|
||||
}
|
||||
|
||||
|
@ -58,14 +51,12 @@ class TestTraySwt {
|
|||
public
|
||||
TestTraySwt() {
|
||||
Display display = new Display ();
|
||||
Shell shell = new Shell(display);
|
||||
final Shell shell = new Shell(display);
|
||||
|
||||
Text helloWorldTest = new Text(shell, SWT.NONE);
|
||||
helloWorldTest.setText("Hello World SWT");
|
||||
helloWorldTest.setText("Hello World SWT ................. ");
|
||||
helloWorldTest.pack();
|
||||
|
||||
shell.pack();
|
||||
shell.open ();
|
||||
|
||||
this.systemTray = SystemTray.getSystemTray();
|
||||
if (systemTray == null) {
|
||||
|
@ -111,13 +102,22 @@ class TestTraySwt {
|
|||
public
|
||||
void onClick(final SystemTray systemTray, final MenuEntry menuEntry) {
|
||||
systemTray.shutdown();
|
||||
shell.close(); // close down SWT shell
|
||||
//System.exit(0); not necessary if all non-daemon threads have stopped.
|
||||
}
|
||||
});
|
||||
|
||||
while (!shell.isDisposed ()) {
|
||||
if (!display.readAndDispatch ()) display.sleep ();
|
||||
|
||||
|
||||
shell.pack();
|
||||
shell.open();
|
||||
|
||||
while (!shell.isDisposed()) {
|
||||
if (!display.readAndDispatch()) {
|
||||
display.sleep();
|
||||
}
|
||||
}
|
||||
display.dispose ();
|
||||
|
||||
display.dispose();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue