From 7892229a2cee7ccbe5afd017e5fe1d5ffd7aa82c Mon Sep 17 00:00:00 2001 From: Rudi Date: Mon, 14 Sep 2026 13:01:41 +0000 Subject: [PATCH] Add icon --- artwork/j3270_icon.svg | 146 ++++++++++++++++++ artwork/lib3270j.svg | 146 ++++++++++++++++++ .../java/haus/nightmare/j3270/J3270App.java | 1 + .../j3270/ft/FileTransferDialog.java | 2 + .../java/haus/nightmare/j3270/ui/AppIcon.java | 138 +++++++++++++++++ .../nightmare/j3270/ui/ConnectDialog.java | 1 + .../j3270/ui/FieldInspectorDialog.java | 1 + .../haus/nightmare/j3270/ui/FindDialog.java | 1 + .../j3270/ui/HostDirectoryDialog.java | 1 + .../j3270/ui/PrinterSessionDialog.java | 1 + .../haus/nightmare/j3270/ui/ScriptDialog.java | 1 + .../nightmare/j3270/ui/SettingsDialog.java | 1 + .../j3270/ui/UntrustedCertificateDialog.java | 1 + j3270/src/main/resources/icons/j3270_icon.svg | 146 ++++++++++++++++++ j3270/src/main/resources/icons/lib3270j.png | Bin 0 -> 5174 bytes j3270/src/main/resources/icons/lib3270j.svg | 146 ++++++++++++++++++ .../src/main/resources/icons/lib3270j_128.png | Bin 0 -> 2315 bytes .../src/main/resources/icons/lib3270j_16.png | Bin 0 -> 220 bytes .../src/main/resources/icons/lib3270j_24.png | Bin 0 -> 311 bytes .../src/main/resources/icons/lib3270j_256.png | Bin 0 -> 5174 bytes .../src/main/resources/icons/lib3270j_32.png | Bin 0 -> 452 bytes .../src/main/resources/icons/lib3270j_48.png | Bin 0 -> 714 bytes .../src/main/resources/icons/lib3270j_512.png | Bin 0 -> 11826 bytes .../src/main/resources/icons/lib3270j_64.png | Bin 0 -> 1024 bytes .../main/resources/icons/lib3270j_wide.png | Bin 0 -> 6173 bytes .../haus/nightmare/j3270/AppIconTest.java | 57 +++++++ 26 files changed, 790 insertions(+) create mode 100644 artwork/j3270_icon.svg create mode 100644 artwork/lib3270j.svg create mode 100644 j3270/src/main/java/haus/nightmare/j3270/ui/AppIcon.java create mode 100644 j3270/src/main/resources/icons/j3270_icon.svg create mode 100644 j3270/src/main/resources/icons/lib3270j.png create mode 100644 j3270/src/main/resources/icons/lib3270j.svg create mode 100644 j3270/src/main/resources/icons/lib3270j_128.png create mode 100644 j3270/src/main/resources/icons/lib3270j_16.png create mode 100644 j3270/src/main/resources/icons/lib3270j_24.png create mode 100644 j3270/src/main/resources/icons/lib3270j_256.png create mode 100644 j3270/src/main/resources/icons/lib3270j_32.png create mode 100644 j3270/src/main/resources/icons/lib3270j_48.png create mode 100644 j3270/src/main/resources/icons/lib3270j_512.png create mode 100644 j3270/src/main/resources/icons/lib3270j_64.png create mode 100644 j3270/src/main/resources/icons/lib3270j_wide.png create mode 100644 j3270/src/test/java/haus/nightmare/j3270/AppIconTest.java diff --git a/artwork/j3270_icon.svg b/artwork/j3270_icon.svg new file mode 100644 index 0000000..a332e3a --- /dev/null +++ b/artwork/j3270_icon.svg @@ -0,0 +1,146 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/artwork/lib3270j.svg b/artwork/lib3270j.svg new file mode 100644 index 0000000..6aa51a3 --- /dev/null +++ b/artwork/lib3270j.svg @@ -0,0 +1,146 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/j3270/src/main/java/haus/nightmare/j3270/J3270App.java b/j3270/src/main/java/haus/nightmare/j3270/J3270App.java index 16ef191..9f474c7 100644 --- a/j3270/src/main/java/haus/nightmare/j3270/J3270App.java +++ b/j3270/src/main/java/haus/nightmare/j3270/J3270App.java @@ -60,6 +60,7 @@ public class J3270App extends JFrame implements ConnectionListener, ScreenUpdate super("j3270 — Java TN3270 Terminal Emulator"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBackground(Color.BLACK); + AppIcon.applyTo(this); buildUI(); buildMenuBar(); diff --git a/j3270/src/main/java/haus/nightmare/j3270/ft/FileTransferDialog.java b/j3270/src/main/java/haus/nightmare/j3270/ft/FileTransferDialog.java index 529889d..8416355 100644 --- a/j3270/src/main/java/haus/nightmare/j3270/ft/FileTransferDialog.java +++ b/j3270/src/main/java/haus/nightmare/j3270/ft/FileTransferDialog.java @@ -1,5 +1,6 @@ package haus.nightmare.j3270.ft; +import haus.nightmare.j3270.ui.AppIcon; import haus.nightmare.j3270.ui.HostDirectoryDialog; import haus.nightmare.j3270.ui.ThemeManager; import haus.nightmare.lib3270j.ft.FTConfig; @@ -92,6 +93,7 @@ public class FileTransferDialog extends JDialog { super(owner, "File Transfer (IND$FILE)", false); this.owner = owner; this.coordinator = coordinator; + AppIcon.applyTo(this); buildUI(); pack(); diff --git a/j3270/src/main/java/haus/nightmare/j3270/ui/AppIcon.java b/j3270/src/main/java/haus/nightmare/j3270/ui/AppIcon.java new file mode 100644 index 0000000..29495a0 --- /dev/null +++ b/j3270/src/main/java/haus/nightmare/j3270/ui/AppIcon.java @@ -0,0 +1,138 @@ +package haus.nightmare.j3270.ui; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Utility for loading and applying application window and taskbar icons. + * Loads multi-resolution lib3270j icons from resources. + */ +public final class AppIcon { + + private static final Logger log = Logger.getLogger(AppIcon.class.getName()); + + private static final int[] ICON_SIZES = {16, 24, 32, 48, 64, 128, 256, 512}; + private static List cachedIcons = null; + private static Image defaultIcon = null; + + private AppIcon() {} + + /** + * Retrieves the list of available application icon images in various resolutions. + * + * @return an unmodifiable list of Image objects, or empty list if none could be loaded. + */ + public static synchronized List getAppIcons() { + if (cachedIcons == null) { + loadIcons(); + } + return cachedIcons; + } + + /** + * Retrieves the default application icon image (256x256 or best available). + * + * @return the default Image, or null if no icon is available. + */ + public static synchronized Image getDefaultIcon() { + if (cachedIcons == null) { + loadIcons(); + } + return defaultIcon; + } + + /** + * Applies the application icons to a target Window (JFrame, JDialog, etc.) + * and updates the desktop Taskbar icon if supported. + * + * @param window the Window to set icon images for. + */ + public static void applyTo(Window window) { + if (GraphicsEnvironment.isHeadless()) { + return; + } + + List icons = getAppIcons(); + if (icons.isEmpty()) { + return; + } + + if (window != null) { + window.setIconImages(icons); + } + + // Apply to OS Taskbar / Dock if supported (Java 9+) + try { + if (Taskbar.isTaskbarSupported()) { + Taskbar taskbar = Taskbar.getTaskbar(); + if (taskbar.isSupported(Taskbar.Feature.ICON_IMAGE)) { + Image bestIcon = defaultIcon != null ? defaultIcon : icons.get(icons.size() - 1); + taskbar.setIconImage(bestIcon); + } + } + } catch (Throwable t) { + log.log(Level.FINE, "Taskbar icon could not be set: {0}", t.getMessage()); + } + } + + private static void loadIcons() { + List icons = new ArrayList<>(); + + for (int size : ICON_SIZES) { + String path = "/icons/lib3270j_" + size + ".png"; + Image img = loadImage(path); + if (img != null) { + icons.add(img); + } + } + + if (icons.isEmpty()) { + Image img = loadImage("/icons/lib3270j.png"); + if (img != null) { + icons.add(img); + } + } + + if (!icons.isEmpty()) { + for (Image img : icons) { + if (img.getWidth(null) == 256) { + defaultIcon = img; + break; + } + } + if (defaultIcon == null) { + defaultIcon = icons.get(icons.size() - 1); + } + } + + cachedIcons = Collections.unmodifiableList(icons); + } + + private static Image loadImage(String resourcePath) { + try { + URL url = AppIcon.class.getResource(resourcePath); + if (url != null) { + BufferedImage img = ImageIO.read(url); + if (img != null) { + return img; + } + } + try (InputStream in = AppIcon.class.getResourceAsStream(resourcePath)) { + if (in != null) { + return ImageIO.read(in); + } + } + } catch (Exception e) { + log.log(Level.FINE, "Failed to load icon from " + resourcePath, e); + } + return null; + } +} diff --git a/j3270/src/main/java/haus/nightmare/j3270/ui/ConnectDialog.java b/j3270/src/main/java/haus/nightmare/j3270/ui/ConnectDialog.java index e3a385c..8e687db 100644 --- a/j3270/src/main/java/haus/nightmare/j3270/ui/ConnectDialog.java +++ b/j3270/src/main/java/haus/nightmare/j3270/ui/ConnectDialog.java @@ -31,6 +31,7 @@ public class ConnectDialog extends JDialog { public ConnectDialog(Frame parent) { super(parent, "Connect to Host", true); + AppIcon.applyTo(this); buildUI(); pack(); setLocationRelativeTo(parent); diff --git a/j3270/src/main/java/haus/nightmare/j3270/ui/FieldInspectorDialog.java b/j3270/src/main/java/haus/nightmare/j3270/ui/FieldInspectorDialog.java index 4de1862..0c6c795 100644 --- a/j3270/src/main/java/haus/nightmare/j3270/ui/FieldInspectorDialog.java +++ b/j3270/src/main/java/haus/nightmare/j3270/ui/FieldInspectorDialog.java @@ -32,6 +32,7 @@ public class FieldInspectorDialog extends JDialog implements ScreenUpdateListene super(parent, "3270 Presentation Space Field Inspector", false); this.client = client; this.terminalPanel = terminalPanel; + AppIcon.applyTo(this); buildUI(); setSize(850, 420); diff --git a/j3270/src/main/java/haus/nightmare/j3270/ui/FindDialog.java b/j3270/src/main/java/haus/nightmare/j3270/ui/FindDialog.java index 0668f33..7c5f572 100644 --- a/j3270/src/main/java/haus/nightmare/j3270/ui/FindDialog.java +++ b/j3270/src/main/java/haus/nightmare/j3270/ui/FindDialog.java @@ -32,6 +32,7 @@ public class FindDialog extends JDialog { super(parent, "Find on Screen", false); this.client = client; this.terminalPanel = terminalPanel; + AppIcon.applyTo(this); buildUI(); pack(); diff --git a/j3270/src/main/java/haus/nightmare/j3270/ui/HostDirectoryDialog.java b/j3270/src/main/java/haus/nightmare/j3270/ui/HostDirectoryDialog.java index 2f462d0..73b0e67 100644 --- a/j3270/src/main/java/haus/nightmare/j3270/ui/HostDirectoryDialog.java +++ b/j3270/src/main/java/haus/nightmare/j3270/ui/HostDirectoryDialog.java @@ -40,6 +40,7 @@ public class HostDirectoryDialog extends JDialog { super(parent, "Host Catalog & Directory Browser", true); this.client = client; this.initialHostType = hostType; + AppIcon.applyTo(this); buildUI(initialQuery); setSize(700, 420); diff --git a/j3270/src/main/java/haus/nightmare/j3270/ui/PrinterSessionDialog.java b/j3270/src/main/java/haus/nightmare/j3270/ui/PrinterSessionDialog.java index 8180ed5..f026540 100644 --- a/j3270/src/main/java/haus/nightmare/j3270/ui/PrinterSessionDialog.java +++ b/j3270/src/main/java/haus/nightmare/j3270/ui/PrinterSessionDialog.java @@ -48,6 +48,7 @@ public class PrinterSessionDialog extends JDialog implements PrintSessionListene public PrinterSessionDialog(Frame parent, String defaultHost, int defaultPort, boolean defaultTls) { super(parent, "IBM 3287 Printer Session Manager", false); this.parent = parent; + AppIcon.applyTo(this); config = new PrinterConfig(defaultHost, defaultPort); config.setUseTls(defaultTls); diff --git a/j3270/src/main/java/haus/nightmare/j3270/ui/ScriptDialog.java b/j3270/src/main/java/haus/nightmare/j3270/ui/ScriptDialog.java index ac95f63..a23edab 100644 --- a/j3270/src/main/java/haus/nightmare/j3270/ui/ScriptDialog.java +++ b/j3270/src/main/java/haus/nightmare/j3270/ui/ScriptDialog.java @@ -25,6 +25,7 @@ public class ScriptDialog extends JDialog { super(parent, "Run Keystrokes / ECL Script", false); this.client = client; this.terminalPanel = terminalPanel; + AppIcon.applyTo(this); buildUI(); setSize(600, 480); diff --git a/j3270/src/main/java/haus/nightmare/j3270/ui/SettingsDialog.java b/j3270/src/main/java/haus/nightmare/j3270/ui/SettingsDialog.java index 852acfd..0cefcb3 100644 --- a/j3270/src/main/java/haus/nightmare/j3270/ui/SettingsDialog.java +++ b/j3270/src/main/java/haus/nightmare/j3270/ui/SettingsDialog.java @@ -62,6 +62,7 @@ public class SettingsDialog extends JDialog { public SettingsDialog(J3270App parent) { super(parent, "Settings", true); this.parentApp = parent; + AppIcon.applyTo(this); initComponents(); setSize(600, 520); diff --git a/j3270/src/main/java/haus/nightmare/j3270/ui/UntrustedCertificateDialog.java b/j3270/src/main/java/haus/nightmare/j3270/ui/UntrustedCertificateDialog.java index 5f909ca..15a17b8 100644 --- a/j3270/src/main/java/haus/nightmare/j3270/ui/UntrustedCertificateDialog.java +++ b/j3270/src/main/java/haus/nightmare/j3270/ui/UntrustedCertificateDialog.java @@ -17,6 +17,7 @@ public class UntrustedCertificateDialog extends JDialog { public UntrustedCertificateDialog(Frame parent, String host, int port, X509Certificate[] chain, CertificateException exception) { super(parent, "Untrusted SSL/TLS Certificate", true); + AppIcon.applyTo(this); buildUI(host, port, chain, exception); pack(); setLocationRelativeTo(parent); diff --git a/j3270/src/main/resources/icons/j3270_icon.svg b/j3270/src/main/resources/icons/j3270_icon.svg new file mode 100644 index 0000000..a332e3a --- /dev/null +++ b/j3270/src/main/resources/icons/j3270_icon.svg @@ -0,0 +1,146 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/j3270/src/main/resources/icons/lib3270j.png b/j3270/src/main/resources/icons/lib3270j.png new file mode 100644 index 0000000000000000000000000000000000000000..c0cd2c563f189b83089ff71052811b00fac9f13f GIT binary patch literal 5174 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 + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/j3270/src/main/resources/icons/lib3270j_128.png b/j3270/src/main/resources/icons/lib3270j_128.png new file mode 100644 index 0000000000000000000000000000000000000000..86966398c55bb6a8bca63e8b2a03483dd24599f6 GIT binary patch literal 2315 zcmaKu2|p7I0LEu-W*e4!j#oyZLY8B$a?HJHawJA9hD;bSnwc{qBso&bQL-pRs5vU3 zB^gnR6e=^fq?Wh$3%tMQ_dNgSBmA>5ZVplsN)iA7K*|wq>+zS=|0)LjyDolP6@MWT z<=k!CMP zkr(Bp6-e_uHO)S_b=P`3b>$b`YX17q%9z*PPdgT_CoO~2>CmHM8vipX$2Uag`*w4= z1JKVppN3P~lV3A2-TKI0E8zE0l3_`+RN|H;G$=M8qb4L5Rc(ZmfyPRHa>m5jI|FID zpyxf19bGh#77nL;IWFvI4b4kM1ZZC@q~ftNireodh<~4t_yzU_-e!T2kex^i)63so=iRz~85H0_Oim5s6;KhZk_mV+j|D4vcXdd#l7rUyvyYuk2tGba|V~Q*D2PME>ab>SNqKI;(AsxmF1e2(OO#iL3 zK}9s6%4|VhkmXNgMAeS@1o*Dbw#9E#?^m1Qz{IJ(>yT~r^x~kLM(-mJRzYVfOrl7) z3Z2}&HPSOpDV2+Y?>qs+P4F$D=4S$KOnHhxa6xmnYuIh$x2W`eoFEyr&W#&XTI$yu zCBX7e2T8hFc}iCRqG07Vn1_mq3>uA4Y{ENgTNDn6{o@ES?Gs#n6CmcPVQ$rb}z zy8~q;#Vf`Mb+Hzs`%f+G>|qpR40Es(?OTdf0&W#i>qt`ZEuMR_`O^JWUs+ck;K+{` zR%sw}@{)K5EyrF-GaJQPmGnDQzx%O-d4ZBR5(-eur=}R?V3*f;2gr(T8Ny8?3r;=L zr_ziCJaKpGoqdQd>+Af(3%^DuTxPwnQH59z z#JuL*s;$QOxscmx(K0i)nk5q?hB;0}g*t5hy@&1IF)C;v<+9*wtM~7f=jP~%tiqgL zS@))3agDNT&cyv%TE)c$758+Cuf~@+12?dE<6+T61b*r;fi(V1%Q&S4Rl`t7GzZSwJ`!N{3wFumvx}uYhs5^;< zM#+o)O_dpLnJU||l}B3OP#!;v^JeM%uXIV6{AUt=0wvMrJuuuKyaw`|;tH`x6lpMT zf%V5%SRzYjj_BpG8C@D%_sCs@e(%t6VBoAoISIM`2(%&ziwS0`|0Kbo61-rwc#$(ldYl{F$%;m`guStG>8pFbH63~Y{C6BOim?2V z5p%!#SKV^_?52n%Fz$)5h1i#)$ga#M%MVKf^|_0F6_%Avhuo@o5(zT`atG}_qdPF3 z!}GlOS;DL8#=OU7n&gROGI)TlU+_7+b)maX>;0qn-GLuH5hc2TRMk95v9+#! zbF<_6N=jLIT9&Fs+3O3Y(bW#JeKUJea^ro5X$R(a#V*I69}4Oroc=Okxd`EC41k0& z5|R`XO0vA5Ik3Y?DM!2%P}7voidt6E7asi0K+$EOf~cne zOCbg$LIL2h-G)w(S`Rouwk+4@8Qz&HHE#p^4RQdzC#oH0s_LZro~}(z3sfoto8pCM z3@dI2Tp-`{vJCG1wbF1sl+zh*eTjN#fF99A1$xaykz&*nXVX5DB>n(yu84mS^LWTF z0LTV2gVDe}FcS0pw$M~=K+>Vs9)T=+4La^-f;7`Qg0qqZ~u7gf$`DxYXo;Q*#deE z70P6r%HwQoqOB#Jlv}D>st?NqIVf_|vZZ?ib0r%F#rB9EzT-y(f9#h2KQ;I(4kC@a Zf)(QjA#UgV8voi2z|qdlmT?qM`xguPIQ0Mk literal 0 HcmV?d00001 diff --git a/j3270/src/main/resources/icons/lib3270j_16.png b/j3270/src/main/resources/icons/lib3270j_16.png new file mode 100644 index 0000000000000000000000000000000000000000..49b1f9b41bb85b9d4b88af73a6758332b2e24034 GIT binary patch literal 220 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61SBU+%rFB|Y)RhkE)4%caKYZ?lYt@=JzX3_ zG$uan-^+JMLBx%p)v2qqu;6|5mz%$(YMb)WqyPW_ literal 0 HcmV?d00001 diff --git a/j3270/src/main/resources/icons/lib3270j_24.png b/j3270/src/main/resources/icons/lib3270j_24.png new file mode 100644 index 0000000000000000000000000000000000000000..3234f7d111749dd6e397666db663ba0f9f811126 GIT binary patch literal 311 zcmV-70m%M|P)P&%#O&{G-U$_y9)Z>-#L;=yh#sETvIWS!%tY zAquIK*b9?-ZgzKO=gZ8u3wQn_&1^BQQ)z+t6CoGkY$pntDbop)kZ{B(ArXi+?HRKL zi;~I^p7KMnqkzD}8!%8PiJUW+NC&5+qF`NnfHC9qKtK05r#MKS#~fa$nwU->=v8EphxSArpM~I<@u@QXe7E znkcI1$l?2?4)9vYN$A4{^hr>ZDl_8zr~O0^O!$D^<$HH-m?HqBGcy={=YIeI002ov JPDHLkV1oL4hSLB5 literal 0 HcmV?d00001 diff --git a/j3270/src/main/resources/icons/lib3270j_256.png b/j3270/src/main/resources/icons/lib3270j_256.png new file mode 100644 index 0000000000000000000000000000000000000000..c0cd2c563f189b83089ff71052811b00fac9f13f GIT binary patch literal 5174 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 literal 0 HcmV?d00001 diff --git a/j3270/src/main/resources/icons/lib3270j_64.png b/j3270/src/main/resources/icons/lib3270j_64.png new file mode 100644 index 0000000000000000000000000000000000000000..3567d8e5ebf5bf6489def906299ad33bc9e26569 GIT binary patch literal 1024 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 z icons = AppIcon.getAppIcons(); + assertNotNull(icons, "Icons list must not be null"); + assertFalse(icons.isEmpty(), "At least one icon image must be loaded"); + + // Verify standard sizes are present + int[] expectedSizes = {16, 24, 32, 48, 64, 128, 256, 512}; + for (int expectedSize : expectedSizes) { + boolean found = icons.stream().anyMatch(img -> img.getWidth(null) == expectedSize && img.getHeight(null) == expectedSize); + assertTrue(found, "Expected icon of size " + expectedSize + "x" + expectedSize + " was not found"); + } + } + + @Test + public void testDefaultIcon() { + Image defaultIcon = AppIcon.getDefaultIcon(); + assertNotNull(defaultIcon, "Default icon must not be null"); + assertEquals(256, defaultIcon.getWidth(null), "Default icon width should be 256"); + assertEquals(256, defaultIcon.getHeight(null), "Default icon height should be 256"); + } + + @Test + public void testApplyToInHeadless() { + // Must execute without exception even in headless environment + assertDoesNotThrow(() -> AppIcon.applyTo(null)); + + if (!GraphicsEnvironment.isHeadless()) { + JFrame frame = new JFrame(); + assertDoesNotThrow(() -> AppIcon.applyTo(frame)); + frame.dispose(); + } + } + + @Test + public void testSvgResourcesExist() { + URL svgUrl = getClass().getResource("/icons/lib3270j.svg"); + assertNotNull(svgUrl, "lib3270j.svg must exist in /icons/"); + + URL iconSvgUrl = getClass().getResource("/icons/j3270_icon.svg"); + assertNotNull(iconSvgUrl, "j3270_icon.svg must exist in /icons/"); + } +}