feat(ui): add multi-resolution tray and application branding assets

This commit is contained in:
Claudecio Martins
2026-10-20 20:16:07 -03:00
parent 66f3172bfb
commit 6ba1a6a77f
18 changed files with 72 additions and 1 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 873 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

@@ -282,6 +282,59 @@ public final class AssetManager {
return getImageOrDefault("app-logo", width, height, fallbackSupplier); return getImageOrDefault("app-logo", width, height, fallbackSupplier);
} }
private static final int[] ICON_SIZES = {16, 24, 32, 48, 64, 128, 256};
/**
* Retorna a lista de imagens multi-resolução do ícone da aplicação
* para configuração do Stage JavaFX principal (16, 24, 32, 48, 64, 128, 256 px).
*/
public static List<Image> getApplicationIcons() {
List<Image> icons = new ArrayList<>();
for (int size : ICON_SIZES) {
String path = "/assets/images/app-icon-" + size + ".png";
InputStream in = AssetManager.class.getResourceAsStream(path);
if (in != null) {
try (in) {
icons.add(new Image(in));
} catch (Exception e) {
logger.debug("Falha ao carregar ícone {}: {}", path, e.getMessage());
}
} else {
InputStream fallback = AssetManager.class.getResourceAsStream("/assets/images/app-icon.png");
if (fallback != null) {
try (fallback) {
icons.add(new Image(fallback, size, size, true, true));
} catch (Exception ignored) {
}
}
}
}
return icons;
}
/**
* Carrega a imagem da bandeja do sistema nativa (AWT TrayIcon) em alta fidelidade.
*/
public static java.awt.Image getTrayIconImage() {
String[] preferredPaths = {
"/assets/images/app-icon-32.png",
"/assets/images/app-icon-16.png",
"/assets/images/app-icon.png"
};
for (String path : preferredPaths) {
InputStream in = AssetManager.class.getResourceAsStream(path);
if (in != null) {
try (in) {
return javax.imageio.ImageIO.read(in);
} catch (Exception e) {
logger.debug("Falha ao ler recurso AWT {}: {}", path, e.getMessage());
}
}
}
return null;
}
private static String cleanBaseName(String name) { private static String cleanBaseName(String name) {
String clean = name; String clean = name;
int dotIdx = clean.lastIndexOf('.'); int dotIdx = clean.lastIndexOf('.');
@@ -189,9 +189,15 @@ public class SystemTrayManager {
} }
/** /**
* Gera dinamicamente um ícone vetorial de 32x32 com o padrão de cores CyberCore (#38bdf8). * Obtém o ícone oficial da marca CyberCore em alta resolução para a bandeja do sistema,
* com fallback vetorial dinâmico caso o recurso não esteja disponível.
*/ */
private Image createTrayIconImage() { private Image createTrayIconImage() {
Image trayAsset = br.com.cybercore.signer.ui.assets.AssetManager.getTrayIconImage();
if (trayAsset != null) {
return trayAsset;
}
int size = 32; int size = 32;
BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB); BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics(); Graphics2D g = image.createGraphics();
@@ -155,6 +155,7 @@ public final class MainAppView {
ThemeManager.addListener(theme -> updateThemeToggleButton()); ThemeManager.addListener(theme -> updateThemeToggleButton());
stage.setTitle(CyberCoreUiConstants.APP_NAME); stage.setTitle(CyberCoreUiConstants.APP_NAME);
stage.getIcons().addAll(br.com.cybercore.signer.ui.assets.AssetManager.getApplicationIcons());
stage.setScene(scene); stage.setScene(scene);
if (Boolean.getBoolean("cybercore.diag.plain-stage")) { if (Boolean.getBoolean("cybercore.diag.plain-stage")) {
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 665 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 873 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

@@ -104,4 +104,15 @@ class AssetManagerTest {
AssetManager.setExternalOverridesEnabled(null); AssetManager.setExternalOverridesEnabled(null);
} }
} }
@Test
@DisplayName("Deve fornecer ícones multi-resolução da aplicação e imagem para a bandeja nativa")
void shouldProvideMultiResolutionIconsAndTrayImage() {
java.util.List<javafx.scene.image.Image> icons = AssetManager.getApplicationIcons();
assertThat(icons).isNotEmpty();
assertThat(icons.size()).isGreaterThanOrEqualTo(5);
java.awt.Image trayImage = AssetManager.getTrayIconImage();
assertThat(trayImage).isNotNull();
}
} }