|
|
|
@ -28,14 +28,20 @@
|
|
|
|
|
package net.yacy.gui;
|
|
|
|
|
|
|
|
|
|
import java.awt.Image;
|
|
|
|
|
import java.awt.image.BufferedImage;
|
|
|
|
|
import java.awt.Color;
|
|
|
|
|
import java.awt.Font;
|
|
|
|
|
import java.awt.Graphics2D;
|
|
|
|
|
import java.awt.MenuItem;
|
|
|
|
|
import java.awt.PopupMenu;
|
|
|
|
|
import java.awt.SystemTray;
|
|
|
|
|
import java.awt.Toolkit;
|
|
|
|
|
import java.awt.TrayIcon;
|
|
|
|
|
import java.awt.event.ActionEvent;
|
|
|
|
|
import java.awt.event.ActionListener;
|
|
|
|
|
import java.io.File;
|
|
|
|
|
import java.lang.reflect.Method;
|
|
|
|
|
|
|
|
|
|
import javax.imageio.ImageIO;
|
|
|
|
|
|
|
|
|
|
import net.yacy.gui.framework.Browser;
|
|
|
|
|
import net.yacy.kelondro.util.OS;
|
|
|
|
@ -43,7 +49,6 @@ import net.yacy.search.Switchboard;
|
|
|
|
|
import net.yacy.search.SwitchboardConstants;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public final class Tray {
|
|
|
|
|
private Switchboard sb;
|
|
|
|
|
|
|
|
|
@ -57,6 +62,8 @@ public final class Tray {
|
|
|
|
|
private boolean isShown = false;
|
|
|
|
|
private boolean appIsReady = false;
|
|
|
|
|
private boolean menuEnabled = true;
|
|
|
|
|
private Image trayIcon = null;
|
|
|
|
|
private BufferedImage[] progressIcons = null;
|
|
|
|
|
|
|
|
|
|
public Tray(final Switchboard sb_par) {
|
|
|
|
|
sb = sb_par;
|
|
|
|
@ -65,38 +72,98 @@ public final class Tray {
|
|
|
|
|
try {
|
|
|
|
|
final boolean trayIconEnabled = sb.getConfigBool(SwitchboardConstants.TRAY_ICON_ENABLED, false);
|
|
|
|
|
final boolean trayIconForced = sb.getConfigBool(SwitchboardConstants.TRAY_ICON_FORCED, false);
|
|
|
|
|
if (trayIconEnabled && (OS.isWindows || trayIconForced)) {
|
|
|
|
|
System.setProperty("java.awt.headless", "false"); // we have to switch off headless mode, else all will fail
|
|
|
|
|
|
|
|
|
|
if(SystemTray.isSupported()) {
|
|
|
|
|
final String iconPath = sb.getAppPath().toString() + "/addon/YaCy_TrayIcon.png".replace("/", File.separator);
|
|
|
|
|
ActionListener al = new ActionListener() {
|
|
|
|
|
@Override
|
|
|
|
|
if (trayIconEnabled && (OS.isWindows || OS.isMacArchitecture || trayIconForced)) {
|
|
|
|
|
System.setProperty("java.awt.headless", "false"); // we have to switch off headless mode, else all will fail
|
|
|
|
|
if (SystemTray.isSupported()) {
|
|
|
|
|
final String iconPath = sb.getAppPath().toString() + "/addon/YaCy_TrayIcon.png".replace("/", File.separator);
|
|
|
|
|
final String progressPath = sb.getAppPath().toString() + "/addon/progressbar.png".replace("/", File.separator);
|
|
|
|
|
ActionListener al = new ActionListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void actionPerformed(final ActionEvent e) {
|
|
|
|
|
doubleClickAction();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
final Image i = Toolkit.getDefaultToolkit().getImage(iconPath);
|
|
|
|
|
final PopupMenu menu = (menuEnabled) ? getPopupMenu() : null;
|
|
|
|
|
ti = new TrayIcon(i, trayLabel, menu);
|
|
|
|
|
ti.setImageAutoSize(true);
|
|
|
|
|
ti.addActionListener(al);
|
|
|
|
|
SystemTray.getSystemTray().add(ti);
|
|
|
|
|
isShown = true;
|
|
|
|
|
} else {
|
|
|
|
|
System.setProperty("java.awt.headless", "true");
|
|
|
|
|
}
|
|
|
|
|
doubleClickAction();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
this.trayIcon = ImageIO.read(new File(iconPath)); // 128x128
|
|
|
|
|
Image progress_raw = ImageIO.read(new File(progressPath)); // 280x56
|
|
|
|
|
BufferedImage progress = new BufferedImage(280, 56, BufferedImage.TYPE_INT_ARGB);
|
|
|
|
|
Graphics2D progressg = progress.createGraphics();
|
|
|
|
|
progressg.drawImage(progress_raw, 0, 0, null);
|
|
|
|
|
progressg.dispose();
|
|
|
|
|
this.progressIcons = new BufferedImage[4];
|
|
|
|
|
Font font = new Font(Font.SANS_SERIF, Font.PLAIN, 30);
|
|
|
|
|
for (int i = 0; i < 4; i++) {
|
|
|
|
|
this.progressIcons[i] = new BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB);
|
|
|
|
|
Graphics2D h = this.progressIcons[i].createGraphics();
|
|
|
|
|
h.setBackground(Color.BLACK);
|
|
|
|
|
h.clearRect(0, 0, 128, 128);
|
|
|
|
|
h.drawImage(this.trayIcon, 0, 0, 128, 128 - progress.getHeight(), null);
|
|
|
|
|
h.drawImage(progress.getSubimage(i * 7, 0, 128, progress.getHeight() / 2), 0, 128 - progress.getHeight() / 2, null);
|
|
|
|
|
h.setColor(Color.WHITE);
|
|
|
|
|
h.setFont(font);
|
|
|
|
|
h.drawString("booting...", 2, 128 - progress.getHeight() + 24);
|
|
|
|
|
h.dispose();
|
|
|
|
|
}
|
|
|
|
|
final PopupMenu menu = (menuEnabled) ? getPopupMenu() : null;
|
|
|
|
|
ti = new TrayIcon(this.trayIcon, trayLabel, menu);
|
|
|
|
|
if (OS.isMacArchitecture) setDockIcon(trayIcon);
|
|
|
|
|
ti.setImageAutoSize(true);
|
|
|
|
|
ti.addActionListener(al);
|
|
|
|
|
SystemTray.getSystemTray().add(ti);
|
|
|
|
|
isShown = true;
|
|
|
|
|
ti.setToolTip(startupMessage());
|
|
|
|
|
new TrayAnimation().start();
|
|
|
|
|
} else {
|
|
|
|
|
System.setProperty("java.awt.headless", "true");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (final Exception e) {
|
|
|
|
|
System.setProperty("java.awt.headless", "true");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class TrayAnimation extends Thread {
|
|
|
|
|
int ic = 0;
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
while (!Tray.this.appIsReady) {
|
|
|
|
|
Tray.this.ti.setImage(Tray.this.progressIcons[ic]);
|
|
|
|
|
if (OS.isMacArchitecture) setDockIcon(Tray.this.progressIcons[ic]);
|
|
|
|
|
ic++; if (ic >= 4) ic = 0;
|
|
|
|
|
try {Thread.sleep(80);} catch (InterruptedException e) {break;}
|
|
|
|
|
}
|
|
|
|
|
ti.setImage(Tray.this.trayIcon);
|
|
|
|
|
ti.setToolTip(readyMessage());
|
|
|
|
|
if (OS.isMacArchitecture) setDockIcon(trayIcon);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void setDockIcon(Image icon) {
|
|
|
|
|
try {
|
|
|
|
|
Class<?> applicationClass = Class.forName("com.apple.eawt.Application");
|
|
|
|
|
Method applicationGetApplication = applicationClass.getMethod("getApplication");
|
|
|
|
|
Object applicationInstance = applicationGetApplication.invoke(null);
|
|
|
|
|
Method setDockIconImage = applicationClass.getMethod("setDockIconImage", Class.forName("java.awt.Image"));
|
|
|
|
|
setDockIconImage.invoke(applicationInstance, icon);
|
|
|
|
|
} catch (Throwable e) {}
|
|
|
|
|
// same as: Application.getApplication().setDockIconImage(i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private MenuItem menuItemHeadline;
|
|
|
|
|
private MenuItem menuItemSearch;
|
|
|
|
|
private MenuItem menuItemAdministration;
|
|
|
|
|
private MenuItem menuItemTerminate;
|
|
|
|
|
/**
|
|
|
|
|
* set all functions available
|
|
|
|
|
*/
|
|
|
|
|
public void setReady() {
|
|
|
|
|
appIsReady = true;
|
|
|
|
|
ti.setImage(this.trayIcon);
|
|
|
|
|
if (OS.isMacArchitecture) setDockIcon(trayIcon);
|
|
|
|
|
ti.setToolTip(readyMessage());
|
|
|
|
|
this.menuItemHeadline.setLabel(readyMessage());
|
|
|
|
|
this.menuItemSearch.setEnabled(true);
|
|
|
|
|
this.menuItemAdministration.setEnabled(true);
|
|
|
|
|
this.menuItemTerminate.setEnabled(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void remove() {
|
|
|
|
@ -107,21 +174,28 @@ public final class Tray {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void doubleClickAction() {
|
|
|
|
|
if (!appIsReady) {
|
|
|
|
|
String label;
|
|
|
|
|
if (deutsch)
|
|
|
|
|
label = "Bitte warten bis YaCy gestartet ist.";
|
|
|
|
|
else if (french)
|
|
|
|
|
label = "S'il vous pla<6C><61>t attendre jusqu'<27><> YaCy est d<><64>marr<72><72>.";
|
|
|
|
|
else
|
|
|
|
|
label = "Please wait until YaCy is started.";
|
|
|
|
|
//ti.displayMessage("YaCy",label);
|
|
|
|
|
ti.displayMessage("YaCy", label, TrayIcon.MessageType.INFO);
|
|
|
|
|
} else {
|
|
|
|
|
openBrowserPage("");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
private String startupMessage() {
|
|
|
|
|
if (deutsch)
|
|
|
|
|
return "YaCy startet, bitte warten...";
|
|
|
|
|
else if (french)
|
|
|
|
|
return "S'il vous pla<6C><61>t attendre jusqu'<27><> YaCy est d<><64>marr<72><72>.";
|
|
|
|
|
else
|
|
|
|
|
return "YaCy is starting, please wait...";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private String readyMessage() {
|
|
|
|
|
if (deutsch) return "YaCy laeuft unter http://localhost:" + sb.getConfig("port", "8090");
|
|
|
|
|
return "YaCy is running at http://localhost:" + sb.getConfig("port", "8090");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void doubleClickAction() {
|
|
|
|
|
if (!appIsReady) {
|
|
|
|
|
String label = startupMessage();
|
|
|
|
|
ti.displayMessage("YaCy", label, TrayIcon.MessageType.INFO);
|
|
|
|
|
} else {
|
|
|
|
|
openBrowserPage("");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
*
|
|
|
|
@ -137,8 +211,16 @@ public final class Tray {
|
|
|
|
|
String label;
|
|
|
|
|
|
|
|
|
|
PopupMenu menu = new PopupMenu();
|
|
|
|
|
MenuItem menuItem;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Headline
|
|
|
|
|
this.menuItemHeadline = new MenuItem(startupMessage());
|
|
|
|
|
this.menuItemHeadline.setEnabled(false);
|
|
|
|
|
//this.menuItemHeadline.setFont(this.menuItemHeadline.getFont().deriveFont(Font.BOLD)); // does not work because getFont() returns null;
|
|
|
|
|
menu.add(this.menuItemHeadline);
|
|
|
|
|
|
|
|
|
|
// Separator
|
|
|
|
|
menu.addSeparator();
|
|
|
|
|
|
|
|
|
|
// YaCy Search
|
|
|
|
|
if (deutsch)
|
|
|
|
|
label = "YaCy Suche";
|
|
|
|
@ -146,48 +228,33 @@ public final class Tray {
|
|
|
|
|
label = "YaCy Recherche";
|
|
|
|
|
else
|
|
|
|
|
label = "YaCy Search";
|
|
|
|
|
menuItem = new MenuItem(label);
|
|
|
|
|
menuItem.addActionListener(new ActionListener() {
|
|
|
|
|
this.menuItemSearch = new MenuItem(label);
|
|
|
|
|
this.menuItemSearch.setEnabled(false);
|
|
|
|
|
this.menuItemSearch.addActionListener(new ActionListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void actionPerformed(final ActionEvent e) {
|
|
|
|
|
openBrowserPage("");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
menu.add(menuItem);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* no prominent compare since google can not be displayed in a frame anymore
|
|
|
|
|
// Compare YaCy
|
|
|
|
|
if (deutsch)
|
|
|
|
|
label = "Vergleichs-Suche";
|
|
|
|
|
else if (french)
|
|
|
|
|
label = "Comparer YaCy";
|
|
|
|
|
else
|
|
|
|
|
label = "Compare YaCy";
|
|
|
|
|
menuItem = new MenuItem(label);
|
|
|
|
|
menuItem.addActionListener(new ActionListener() {
|
|
|
|
|
public void actionPerformed(final ActionEvent e) {
|
|
|
|
|
openBrowser("compare_yacy.html");
|
|
|
|
|
openBrowserPage("index.html");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
menu.add(menuItem);
|
|
|
|
|
*/
|
|
|
|
|
menu.add(this.menuItemSearch);
|
|
|
|
|
|
|
|
|
|
// Peer Administration
|
|
|
|
|
if (deutsch)
|
|
|
|
|
label = "Peer Administration";
|
|
|
|
|
label = "Administration";
|
|
|
|
|
else if (french)
|
|
|
|
|
label = "Peer Administration";
|
|
|
|
|
label = "Administration";
|
|
|
|
|
else
|
|
|
|
|
label = "Peer Administration";
|
|
|
|
|
menuItem = new MenuItem(label);
|
|
|
|
|
menuItem.addActionListener(new ActionListener() {
|
|
|
|
|
label = "Administration";
|
|
|
|
|
this.menuItemAdministration = new MenuItem(label);
|
|
|
|
|
this.menuItemAdministration.setEnabled(false);
|
|
|
|
|
this.menuItemAdministration.addActionListener(new ActionListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void actionPerformed(final ActionEvent e) {
|
|
|
|
|
openBrowserPage("Status.html");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
menu.add(menuItem);
|
|
|
|
|
menu.add(this.menuItemAdministration);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Separator
|
|
|
|
|
menu.addSeparator();
|
|
|
|
@ -199,14 +266,15 @@ public final class Tray {
|
|
|
|
|
label = "Arr<72><72>t YaCy";
|
|
|
|
|
else
|
|
|
|
|
label = "Shutdown YaCy";
|
|
|
|
|
menuItem = new MenuItem(label);
|
|
|
|
|
menuItem.addActionListener(new ActionListener() {
|
|
|
|
|
this.menuItemTerminate = new MenuItem(label);
|
|
|
|
|
this.menuItemTerminate.setEnabled(false);
|
|
|
|
|
this.menuItemTerminate.addActionListener(new ActionListener() {
|
|
|
|
|
@Override
|
|
|
|
|
public void actionPerformed(final ActionEvent e) {
|
|
|
|
|
sb.terminate("shutdown from tray");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
menu.add(menuItem);
|
|
|
|
|
menu.add(this.menuItemTerminate);
|
|
|
|
|
return menu;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|