From 40b3977c219380dd2f702a51020afbf868314b6c Mon Sep 17 00:00:00 2001 From: orbiter Date: Sun, 7 Sep 2014 12:04:35 +0200 Subject: [PATCH] added an animation of the tray icon during the boot phase of YaCy. Additionally, there is a tooltip and a new headline at the tray menu which states the current booting status. --- addon/progressbar.png | Bin 0 -> 4513 bytes source/net/yacy/gui/Tray.java | 208 ++++++++++++++++++++++------------ 2 files changed, 138 insertions(+), 70 deletions(-) create mode 100644 addon/progressbar.png diff --git a/addon/progressbar.png b/addon/progressbar.png new file mode 100644 index 0000000000000000000000000000000000000000..7e588ee3a2d3d8d1609b9f8819425ac5a6f40b97 GIT binary patch literal 4513 zcmV;S5nk?zP)L_BCi=@}JD&i%?{WCH7Yz*@pg0&-0E$SM&%z9CF?V4fISh`P8 z|IamVHd^s|@#*sBCXeE~kJVmx$J7viu4}nT#4jVh=J**Ve--h)##|+hcrQTmnVNf~ z!uiQJ7VA^*Al`|%YWRhzP`+r*lqR@sa(T`^s)n3vx;KhFgBKCss?$P|=OaLsW^=4x zhx{6hi)zV+ON`xsmg3L#>3I8=9NTb3f!hwJM>{ z)UK+QWxX9ld>D=;G@xL^4DLEuumLitkcSMu9dJ=o0|QKyP}EYC7>TE04rT3m<$%L+ z#F!1N*O@g&Y0u#i?t~nhbQ6W_$LAm^l0#&ejDSquByW+!B#Y7!a&XhO9E;Cl-P!c> zJ~YrP;~j&{xt>N}6z{Bi($KGe^!FBP`;nY!E1!4=z{3u-m;>?puP*(tEAp{IF1&lQ z>*^9rJgL8_+o|=`3ht|^wTO}WJ++3vRY+rQW{}Z5K1Ps-7t0`C!)1JY&~X0)d3KDq zC1TAw*Ar=2C+G*Ihb1`MA4!$pls}af&#WAp5TdRx^pO}k!GFr|#NTY5>#N-s#SNX5vX)GZB3W6~bf?A|=L zc)WNm2AsgX)z$W~IIn_Q15O1MctM9PIJ0g3Lu=AYhDc%C)DE**ZZX81m=)6?i+jZp zaY!6zxRsx{2X!O3=eA6p{+J4Aj1{kQAecHftIT>K(0M?8dfI0f?WpaXagEu!FYi;7 z*X1;Rs;FGB^uc~vGfg>Ad9q7A>MqdgAh7QszoH+g!S^k(^Lixn-v&7J7v5PnBH45U z;A;<{`?W~chj-$$p8;Grpf}uw@Xk*pegW`m`}gsGT^YQaZZ(?^@V@H!1YqOiX7iur zW^?09^uGph$@~{t0C9Nkf;f=?001F$MObuGZ)S9NVRB^vM{;3sXlY|ZZ*F#Fa&%>K zASg+0bY*NQcZd2J000d@NklMFPbQ4^&Bsy%ahxxB_-p{>^_B}W@ zcR3?_9{4aTvt+K}x9-Tcu+j7jHDf*QBhU+xQ!(RP>=0iF`l;;icV|Fr=GIR8AGJBJ zNf^vE(|d6Me8~zM$Ad58!kPr{L!=}&46a!e8f|$SqxVvTm%?c8M%T_>c4y85pQqsc z(H;F765wqa^rondmet?DAW_yPfnk zoK+IuFe>}{!Hv%Sd79t}8?C~o_X4WCg8GTz%eV~hW2Ch81_-aHWi0d#fOjAx`$6r@ z755QPd9(Gm&qN&IMK%nEH`3#BWAG|(HQf`GM;lGcR`jBIH22sP0*~^I=Pa5>3mV3Q zuK?vG!zKnVG#Xlo%4sMaBic3fU;)^dL>7n5E=YMJJz#!fcv9F@$}{mID6ej+`AMs| zrnzo<&JJk7iy~n&j>0RBj4(X00CZqfJ=6;-FROH}@lF?%^M)yGTF48LV=GTulm6X- zCx6epV+>CW#pZuu&p8wx)sT?#RwIN2g=db4InVx{j*Or;+R7@MZTu5}w`o)l_qyHC zMl-zo?MT7my@ckc{1X#_r=&b#qiIvhI)~6|(|?mHLmA%tNO2g2S3=5LjffR&%j;ON zIqLX50eG3ka}B@C1xt9#tiI6;<~)MuTk4Ptmd`q2la%+gRnB>9rbf>5QMCyaEUOwh zkE%^$MS{0&v@A!d%aqmxlt=J{jaCH<$sBFct8O*@D=1IFGs>@CN8z2A3_$S0W!)$| z3Y#rps{l9tDr^GqUdIZXk;dQg!#HgI)rk}=3=dOYZuKp{6gF+;m0yLGr{IZe8vkj+ zdn3c699A5K!)9z)&UrRG-#E6WgYrBI9+LA02_Ba7YNq{?@;K*xGRv=A#|oB2{_)Ac zGpS&qocA$Y+I|CkAt-P`@K&M}4DsVJK5{!ucvd=o1aGGCZwOvh5}y2FIi$P?GCcEB zSfimnHNo(tjb?alFuZ_jsAYH&>fUhWA@C^I7Br&ph|z)k60E#CK%cj1vhv`AX=)YZ z(~w=|$!q3Q*nB1z7hG+2!PRCHRBdwDgsV+zDhwp&y^Z0A-8Q4|`B~YX8Q-FGltl## zDQ}<;h4<4mDG#YO%P+z3PE7=#WAHlAqbv@a2)uVuRn~*8!muH>3Z%SO@j@R6ZhERCa=PgTNbDQB61;w&{ z2VScTFS;EHzKj>tgJCm;(O!O5cKHkfkCk_=4=gSi-a`Q1x(yGV=LG=e8I<$l==kPn za8y>F4X*`N9(_7}2U&S9V+9QpsPa-7xl$f1N$@tAA1e=TsQr(C@y)vFIR}q#8pZ=J z0C*oFC2@QLFe**}IBYKC%Co3kBJ~6C;`yg_;H5IM`6aTvs@fFu)2{O5O(EqqKWdY6 z-nz!%l*1-8zOh>cENlkGIBbgWR-%VrZN7-p>xdRC2QhM~+1pIh5;VS1gHsG%EyEK| z>(%(idjUSm;@KN;8ba{!*;{ZdB<8#=qh&b;hfRy&Adg~D@S7rNH54`}=S6k=CSuOB;RVoYli*Ri0)FiS^!s@p7R6dr?9glEiJ#K z-$ZNn_5>K;X!%VVe}Lb_7!@rG95&y?;IPT?Oa$Ju*8Jm$@~m&lbB0Izc`(1E-{cn< z-tnmb;x}2-Fx?V7WcC(%uQNCW{3g2RkY!y%tUSjwL_5RqPU2znTKKb5*!;%mAbuM> zzS)5X_)Y4jcyJ2&P2ky^|0d$G4Cz=F=r?7{f~`Cqc$CY9jb`QP0~ce4*t9$OZ4s!eo!gI1dsy^eCVN${Sw!cDqGNRXVD!YK8D zLE=5k*_+)ebioq<(6X?q88!iU^wLn!2G^uS!0?>Irh-Sw1<654<$W@pFRvWHXfIVt zn{e1<<;i}Nj~ejM!RbmA_gE^w31nG-r``z_HiZz!1iJC$+p+-qO^R^833!P7N(bKAL27}-f`wWsYN$|nJ=g4cxWk%h8QFdl&w1Eya(aTA zQ0NdDhZn^BChv460CD*o(w=(5gHy|UZXmoaspJd6Ys;%e;Z^qbhXHtL8SSAeZwlu; z(6Z18hfTZM6vsF3H7pCoV72*1quMO%9#Ua5{VsFZRLX;^&C0(1q_&*HrUN7Vf?>g_ zi6AgIC3xDiH*tKUp*#z;=>=cnev^dv{D9o&5xmE3xsdX#B)ko&VAHb2q{n*cmovuUv-_or#cHGxf`4hB)4@lofx zaLZ`RvJ^JAwJZyX(pKmYnf)dxyoC3{fLO3ZsbG0T%5&c6J@ESb#e#+5Ep=p<&q!;E z%4-;h;Qb$$7RB+6=IjlF7te=hZ`@EL1q;CwRI@l)7@TZO9YeYX43c}?F^r&1oWpH9ky z{U-2@)1=c&v@E=h9Sx!d3ux2h!6`lgxMV9&g7*+qo@Fb~9vTSn?&9zg>G-L^>C1R@ zTPj#qBPFdcJfzRFEer5bR$0f8Xcppv<+(=KWO&jcGQ)cShfTLq-lklzFg))pKHNU| z{sa3>kg2!cy*Fs;&B~K6Eq;TC`ArTR9_2j$gZ3Oe=MD7P^Kj=ieT$vh9#nZYqwo2l z=a4+U!S8y9fxF&%gHwxVZ;0PSclPG!H?h}jy4R6Yjl!!Q?2Q1*YrNBylKN)J#JoA-AnO0N!7nN_k+|Okw0o_aGfS z3WFMclPDH8-{|;Fx(5wu_QvCzr>%K-*t{xFy&2y9_FPsTQm`yk5B2gNE{08lR|bd8 z?-(WTKNL1Y7xme1V&eZr26XR@uM6wIgZw7i@PN}0QeG7Xk8+-ZCl)LXzjrHmnDP!{ z=pI#dBUS zHom!s!lRsL!;=b@Q2p&QnI%ZrWaSY&_GUW15b5tfBqsn`vo~n!tuZ*g0QgO8ct69l zw?5f#!UYQ-B4hAKd83f>>Th>v7C~V%BXhp)*GnQi`p`7@AMBi`QEkHRX81p+DLXS5 zUXzOpf|pkZ`%U^~zezG|Rv@P#mK%ikmBMCsW(k(_GUsb&FLS9WrndLdgZOQlR2gdc zO^~pud>n-^JnzK;xmDOQ{P5J9Hk#pW$eZF@?8vD=2B!;@pK8W>4oq=Y|ktOPgq#ZGQ2&E{s#a6|NjF3)(hADJI0O300000NkvXXu0mjf?qtGX literal 0 HcmV?d00001 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; }