diff --git a/addon/progressbar.png b/addon/progressbar.png new file mode 100644 index 000000000..7e588ee3a Binary files /dev/null and b/addon/progressbar.png differ diff --git a/source/net/yacy/gui/Tray.java b/source/net/yacy/gui/Tray.java index 93f24193e..8dfefeb38 100644 --- a/source/net/yacy/gui/Tray.java +++ b/source/net/yacy/gui/Tray.java @@ -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��t attendre jusqu'�� YaCy est d��marr��."; - 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��t attendre jusqu'�� YaCy est d��marr��."; + 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��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; }