diff --git a/docs/screenshots/01_dashboard.png b/docs/screenshots/01_dashboard.png deleted file mode 100644 index a22786b..0000000 Binary files a/docs/screenshots/01_dashboard.png and /dev/null differ diff --git a/docs/screenshots/01_hub.png b/docs/screenshots/01_hub.png new file mode 100644 index 0000000..348a1de Binary files /dev/null and b/docs/screenshots/01_hub.png differ diff --git a/docs/screenshots/01_hub_claro.png b/docs/screenshots/01_hub_claro.png index 247d606..348a1de 100644 Binary files a/docs/screenshots/01_hub_claro.png and b/docs/screenshots/01_hub_claro.png differ diff --git a/docs/screenshots/01_hub_escuro.png b/docs/screenshots/01_hub_escuro.png deleted file mode 100644 index c349b6d..0000000 Binary files a/docs/screenshots/01_hub_escuro.png and /dev/null differ diff --git a/docs/screenshots/01_layout_claro.png b/docs/screenshots/01_layout_claro.png index 247d606..348a1de 100644 Binary files a/docs/screenshots/01_layout_claro.png and b/docs/screenshots/01_layout_claro.png differ diff --git a/docs/screenshots/01_layout_serpro.png b/docs/screenshots/01_layout_serpro.png deleted file mode 100644 index 531f2be..0000000 Binary files a/docs/screenshots/01_layout_serpro.png and /dev/null differ diff --git a/docs/screenshots/02_diagnostico.png b/docs/screenshots/02_diagnostico.png index aa3b4ee..38c1c42 100644 Binary files a/docs/screenshots/02_diagnostico.png and b/docs/screenshots/02_diagnostico.png differ diff --git a/docs/screenshots/02_diagnostico_claro.png b/docs/screenshots/02_diagnostico_claro.png index aa3b4ee..38c1c42 100644 Binary files a/docs/screenshots/02_diagnostico_claro.png and b/docs/screenshots/02_diagnostico_claro.png differ diff --git a/docs/screenshots/02_diagnostico_escuro.png b/docs/screenshots/02_diagnostico_escuro.png deleted file mode 100644 index 02cd446..0000000 Binary files a/docs/screenshots/02_diagnostico_escuro.png and /dev/null differ diff --git a/docs/screenshots/02_layout_escuro.png b/docs/screenshots/02_layout_escuro.png deleted file mode 100644 index c349b6d..0000000 Binary files a/docs/screenshots/02_layout_escuro.png and /dev/null differ diff --git a/docs/screenshots/03_configuracoes.png b/docs/screenshots/03_configuracoes.png index 3a8a638..c54ee34 100644 Binary files a/docs/screenshots/03_configuracoes.png and b/docs/screenshots/03_configuracoes.png differ diff --git a/docs/screenshots/03_configuracoes_claro.png b/docs/screenshots/03_configuracoes_claro.png index 3a8a638..c54ee34 100644 Binary files a/docs/screenshots/03_configuracoes_claro.png and b/docs/screenshots/03_configuracoes_claro.png differ diff --git a/docs/screenshots/03_configuracoes_escuro.png b/docs/screenshots/03_configuracoes_escuro.png deleted file mode 100644 index 2e34e21..0000000 Binary files a/docs/screenshots/03_configuracoes_escuro.png and /dev/null differ diff --git a/docs/screenshots/04_certificados.png b/docs/screenshots/04_certificados.png new file mode 100644 index 0000000..8584718 Binary files /dev/null and b/docs/screenshots/04_certificados.png differ diff --git a/docs/screenshots/04_certificados_claro.png b/docs/screenshots/04_certificados_claro.png index 18a3d02..8584718 100644 Binary files a/docs/screenshots/04_certificados_claro.png and b/docs/screenshots/04_certificados_claro.png differ diff --git a/docs/screenshots/04_certificados_escuro.png b/docs/screenshots/04_certificados_escuro.png deleted file mode 100644 index 7d58424..0000000 Binary files a/docs/screenshots/04_certificados_escuro.png and /dev/null differ diff --git a/docs/screenshots/05_validacao.png b/docs/screenshots/05_validacao.png new file mode 100644 index 0000000..9e704b1 Binary files /dev/null and b/docs/screenshots/05_validacao.png differ diff --git a/docs/screenshots/05_validacao_claro.png b/docs/screenshots/05_validacao_claro.png index db9b255..9e704b1 100644 Binary files a/docs/screenshots/05_validacao_claro.png and b/docs/screenshots/05_validacao_claro.png differ diff --git a/docs/screenshots/05_validacao_escuro.png b/docs/screenshots/05_validacao_escuro.png deleted file mode 100644 index 46aa703..0000000 Binary files a/docs/screenshots/05_validacao_escuro.png and /dev/null differ diff --git a/docs/screenshots/06_solicitacao.png b/docs/screenshots/06_solicitacao.png new file mode 100644 index 0000000..38ae7a0 Binary files /dev/null and b/docs/screenshots/06_solicitacao.png differ diff --git a/docs/screenshots/06_solicitacao_claro.png b/docs/screenshots/06_solicitacao_claro.png index dd6c751..38ae7a0 100644 Binary files a/docs/screenshots/06_solicitacao_claro.png and b/docs/screenshots/06_solicitacao_claro.png differ diff --git a/docs/screenshots/06_solicitacao_escuro.png b/docs/screenshots/06_solicitacao_escuro.png deleted file mode 100644 index b603710..0000000 Binary files a/docs/screenshots/06_solicitacao_escuro.png and /dev/null differ diff --git a/docs/screenshots/07_selos.png b/docs/screenshots/07_selos.png new file mode 100644 index 0000000..4172466 Binary files /dev/null and b/docs/screenshots/07_selos.png differ diff --git a/docs/screenshots/07_selos_claro.png b/docs/screenshots/07_selos_claro.png index 4de4565..4172466 100644 Binary files a/docs/screenshots/07_selos_claro.png and b/docs/screenshots/07_selos_claro.png differ diff --git a/docs/screenshots/07_selos_escuro.png b/docs/screenshots/07_selos_escuro.png deleted file mode 100644 index cfe58a5..0000000 Binary files a/docs/screenshots/07_selos_escuro.png and /dev/null differ diff --git a/docs/screenshots/08_sobre.png b/docs/screenshots/08_sobre.png new file mode 100644 index 0000000..a331a33 Binary files /dev/null and b/docs/screenshots/08_sobre.png differ diff --git a/docs/screenshots/08_sobre_claro.png b/docs/screenshots/08_sobre_claro.png index 5137b5d..a331a33 100644 Binary files a/docs/screenshots/08_sobre_claro.png and b/docs/screenshots/08_sobre_claro.png differ diff --git a/docs/screenshots/08_sobre_escuro.png b/docs/screenshots/08_sobre_escuro.png deleted file mode 100644 index 210d676..0000000 Binary files a/docs/screenshots/08_sobre_escuro.png and /dev/null differ diff --git a/docs/screenshots/09_exit_dialog.png b/docs/screenshots/09_exit_dialog.png new file mode 100644 index 0000000..d60c35c Binary files /dev/null and b/docs/screenshots/09_exit_dialog.png differ diff --git a/docs/screenshots/09_exit_dialog_escuro.png b/docs/screenshots/09_exit_dialog_escuro.png deleted file mode 100644 index 9dd46f0..0000000 Binary files a/docs/screenshots/09_exit_dialog_escuro.png and /dev/null differ diff --git a/docs/screenshots/10_pdf_sign.png b/docs/screenshots/10_pdf_sign.png new file mode 100644 index 0000000..568bfa1 Binary files /dev/null and b/docs/screenshots/10_pdf_sign.png differ diff --git a/docs/screenshots/10_pdf_sign_claro.png b/docs/screenshots/10_pdf_sign_claro.png index 45d2a0c..568bfa1 100644 Binary files a/docs/screenshots/10_pdf_sign_claro.png and b/docs/screenshots/10_pdf_sign_claro.png differ diff --git a/docs/screenshots/10_pdf_sign_escuro.png b/docs/screenshots/10_pdf_sign_escuro.png deleted file mode 100644 index 92f6367..0000000 Binary files a/docs/screenshots/10_pdf_sign_escuro.png and /dev/null differ diff --git a/docs/screenshots/11_pdf_cert_sign.png b/docs/screenshots/11_pdf_cert_sign.png new file mode 100644 index 0000000..a2e5def Binary files /dev/null and b/docs/screenshots/11_pdf_cert_sign.png differ diff --git a/docs/screenshots/11_pdf_cert_sign_escuro.png b/docs/screenshots/11_pdf_cert_sign_escuro.png deleted file mode 100644 index 488742e..0000000 Binary files a/docs/screenshots/11_pdf_cert_sign_escuro.png and /dev/null differ diff --git a/modules/cybercore-ui/src/test/java/br/com/cybercore/signer/ui/UiPreviewGenerator.java b/modules/cybercore-ui/src/test/java/br/com/cybercore/signer/ui/UiPreviewGenerator.java index 6856202..765bf1d 100644 --- a/modules/cybercore-ui/src/test/java/br/com/cybercore/signer/ui/UiPreviewGenerator.java +++ b/modules/cybercore-ui/src/test/java/br/com/cybercore/signer/ui/UiPreviewGenerator.java @@ -45,6 +45,10 @@ import java.time.Instant; import java.time.temporal.ChronoUnit; import java.util.Objects; +/** + * Utilitário de captura automatizada das telas da interface do CyberCore Signer. + * Gera as capturas de tela atualizadas no tema claro padronizado. + */ public class UiPreviewGenerator extends Application { private static final File OUTPUT_DIR = new File("docs/screenshots"); @@ -74,277 +78,242 @@ public class UiPreviewGenerator extends Application { // 5. Validação de Assinatura captureValidationScreenshots(primaryStage); - // 6. Solicitação de Assinatura (Prompt CCSP) + // 6. Solicitação de Assinatura Local (Prompt de Autorização) capturePromptScreenshots(primaryStage); - // 7. Selos Visuais + // 7. Gerenciador de Selos captureSealsScreenshots(primaryStage); // 8. Sobre captureAboutScreenshots(primaryStage); - // 9. Diálogo de Encerramento / Bandeja + // 9. Confirmação de Saída captureExitDialogScreenshots(primaryStage); - // 10. Diálogo de Posicionamento e Assinatura PDF (PAdES) + // 10. Assinador Visual de PDF capturePdfSignDialogScreenshots(primaryStage); - // 11. Diálogo de Seleção de Certificado e PIN do PDF + // 11. Seleção de Certificado e PIN do PDF capturePdfCertificateSignDialogScreenshots(primaryStage); + System.out.println(">>> Capturas de tela concluídas com sucesso em: " + OUTPUT_DIR.getAbsolutePath()); } catch (Exception e) { e.printStackTrace(); } finally { Platform.exit(); + System.exit(0); } }); } private void captureHubScreenshots(Stage stage) throws Exception { - for (ThemeManager.AppTheme theme : ThemeManager.AppTheme.values()) { - ThemeManager.setCurrentTheme(theme); - MainAppView appView = new MainAppView(stage); - stage.show(); - stage.getScene().getRoot().applyCss(); - stage.getScene().getRoot().layout(); + MainAppView appView = new MainAppView(stage); + stage.show(); + stage.getScene().getRoot().applyCss(); + stage.getScene().getRoot().layout(); - String suffix = theme == ThemeManager.AppTheme.LIGHT ? "claro" : "escuro"; - saveNodeSnapshot(stage.getScene(), new File(OUTPUT_DIR, "01_hub_" + suffix + ".png")); - if (theme == ThemeManager.AppTheme.LIGHT) { - saveNodeSnapshot(stage.getScene(), new File(OUTPUT_DIR, "01_layout_claro.png")); - } else { - saveNodeSnapshot(stage.getScene(), new File(OUTPUT_DIR, "02_layout_escuro.png")); - } - } + saveNodeSnapshot(stage.getScene(), new File(OUTPUT_DIR, "01_hub.png")); + saveNodeSnapshot(stage.getScene(), new File(OUTPUT_DIR, "01_hub_claro.png")); + saveNodeSnapshot(stage.getScene(), new File(OUTPUT_DIR, "01_layout_claro.png")); } private void captureDiagnosticsScreenshots(Stage stage) throws Exception { - for (ThemeManager.AppTheme theme : ThemeManager.AppTheme.values()) { - ThemeManager.setCurrentTheme(theme); - DiagnosticsView diagView = new DiagnosticsView(new DiagnosticService()); + DiagnosticsView diagView = new DiagnosticsView(new DiagnosticService()); - VBox container = wrapInDialogContainer("DIAGNÓSTICO DO SISTEMA", - "Verificação de prontidão do runtime, engines criptográficas e dispositivos.", - SvgIcons.cyberShieldLogo(24), diagView, 800, 520); + VBox container = wrapInDialogContainer("DIAGNÓSTICO DO SISTEMA", + "Verificação de prontidão do runtime, engines criptográficas e dispositivos.", + SvgIcons.cyberShieldLogo(24), diagView, 800, 520); - Scene scene = createScene(container, 800, 520); - stage.setScene(scene); - stage.show(); - scene.getRoot().applyCss(); - scene.getRoot().layout(); + Scene scene = createScene(container, 800, 520); + stage.setScene(scene); + stage.show(); + scene.getRoot().applyCss(); + scene.getRoot().layout(); - String suffix = theme == ThemeManager.AppTheme.LIGHT ? "claro" : "escuro"; - saveNodeSnapshot(scene, new File(OUTPUT_DIR, "02_diagnostico_" + suffix + ".png")); - if (theme == ThemeManager.AppTheme.LIGHT) { - saveNodeSnapshot(scene, new File(OUTPUT_DIR, "02_diagnostico.png")); - } - } + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "02_diagnostico.png")); + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "02_diagnostico_claro.png")); } private void captureSettingsScreenshots(Stage stage) throws Exception { - for (ThemeManager.AppTheme theme : ThemeManager.AppTheme.values()) { - ThemeManager.setCurrentTheme(theme); - SettingsView settingsView = new SettingsView(); + SettingsView settingsView = new SettingsView(); - ScrollPane sp = new ScrollPane(settingsView); - sp.setFitToWidth(true); - sp.getStyleClass().add("cyber-scroll-pane"); - VBox.setVgrow(sp, Priority.ALWAYS); + ScrollPane sp = new ScrollPane(settingsView); + sp.setFitToWidth(true); + sp.getStyleClass().add("cyber-scroll-pane"); + VBox.setVgrow(sp, Priority.ALWAYS); - VBox container = wrapInDialogContainer("CONFIGURAÇÕES DO AGENTE", - "Parâmetros de segurança local, identidade visual e aplicações autorizadas.", - SvgIcons.settingsIcon(), sp, 800, 520); + VBox container = wrapInDialogContainer("CONFIGURAÇÕES DO AGENTE", + "Parâmetros de segurança local, identidade visual e aplicações autorizadas.", + SvgIcons.settingsIcon(), sp, 800, 520); - Scene scene = createScene(container, 800, 520); - stage.setScene(scene); - stage.show(); - scene.getRoot().applyCss(); - scene.getRoot().layout(); + Scene scene = createScene(container, 800, 520); + stage.setScene(scene); + stage.show(); + scene.getRoot().applyCss(); + scene.getRoot().layout(); - String suffix = theme == ThemeManager.AppTheme.LIGHT ? "claro" : "escuro"; - saveNodeSnapshot(scene, new File(OUTPUT_DIR, "03_configuracoes_" + suffix + ".png")); - if (theme == ThemeManager.AppTheme.LIGHT) { - saveNodeSnapshot(scene, new File(OUTPUT_DIR, "03_configuracoes.png")); - } - } + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "03_configuracoes.png")); + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "03_configuracoes_claro.png")); } private void captureCertificatesScreenshots(Stage stage) throws Exception { - for (ThemeManager.AppTheme theme : ThemeManager.AppTheme.values()) { - ThemeManager.setCurrentTheme(theme); + VBox cardsBox = new VBox(12); + cardsBox.setPadding(new Insets(12)); - VBox cardsBox = new VBox(12); - cardsBox.setPadding(new Insets(12)); + ManagedCertificate cert1 = new ManagedCertificate( + "cert-a1", + "JOAO DA SILVA:12345678900", + CertificateType.A1, + CertificateStatus.AVAILABLE, + "CN=JOAO DA SILVA:12345678900, OU=Autenticado por AR, O=ICP-Brasil, C=BR", + "CN=AC SERPRO RFB v5, O=ICP-Brasil, C=BR", + "1A2B3C4D5E", + "11223344556677889900", + "AABBCCDDEEFF00112233445566778899", + Instant.now().minus(60, ChronoUnit.DAYS), + Instant.now().plus(300, ChronoUnit.DAYS), + "RSA", + 2048, + "JOAO DA SILVA:12345678900", + "12345678900", + null, + "SunJSSE", + null + ); - ManagedCertificate cert1 = new ManagedCertificate( - "cert-a1", - "JOAO DA SILVA:12345678900", - CertificateType.A1, - CertificateStatus.AVAILABLE, - "CN=JOAO DA SILVA:12345678900, OU=Autenticado por AR, O=ICP-Brasil, C=BR", - "CN=AC SERPRO RFB v5, O=ICP-Brasil, C=BR", - "1A2B3C4D5E", - "11223344556677889900", - "AABBCCDDEEFF00112233445566778899", - Instant.now().minus(60, ChronoUnit.DAYS), - Instant.now().plus(300, ChronoUnit.DAYS), - "RSA", - 2048, - "JOAO DA SILVA:12345678900", - "12345678900", - null, - "SunJSSE", - null - ); + ManagedCertificate cert2 = new ManagedCertificate( + "cert-a3", + "EMPRESA EXEMPLO LTDA:12345678000199", + CertificateType.A3, + CertificateStatus.AVAILABLE, + "CN=EMPRESA EXEMPLO LTDA:12345678000199, O=ICP-Brasil, C=BR", + "CN=AC VALID Brasil v5, O=ICP-Brasil, C=BR", + "5E4D3C2B1A", + "99887766554433221100", + "FFEEDDCCBBAA99887766554433221100", + Instant.now().minus(120, ChronoUnit.DAYS), + Instant.now().plus(600, ChronoUnit.DAYS), + "RSA", + 2048, + "EMPRESA EXEMPLO LTDA:12345678000199", + null, + "12345678000199", + "SunPKCS11", + "Token USB SafeNet eToken 5110" + ); - ManagedCertificate cert2 = new ManagedCertificate( - "cert-a3", - "EMPRESA EXEMPLO LTDA:12345678000199", - CertificateType.A3, - CertificateStatus.AVAILABLE, - "CN=EMPRESA EXEMPLO LTDA:12345678000199, O=ICP-Brasil, C=BR", - "CN=AC VALID Brasil v5, O=ICP-Brasil, C=BR", - "5E4D3C2B1A", - "99887766554433221100", - "FFEEDDCCBBAA99887766554433221100", - Instant.now().minus(120, ChronoUnit.DAYS), - Instant.now().plus(600, ChronoUnit.DAYS), - "RSA", - 2048, - "EMPRESA EXEMPLO LTDA:12345678000199", - null, - "12345678000199", - "SunPKCS11", - "Token USB SafeNet eToken 5110" - ); + cardsBox.getChildren().addAll(new CertificateCardNode(cert1), new CertificateCardNode(cert2)); - cardsBox.getChildren().addAll(new CertificateCardNode(cert1), new CertificateCardNode(cert2)); + ScrollPane sp = new ScrollPane(cardsBox); + sp.setFitToWidth(true); + sp.getStyleClass().add("cyber-scroll-pane"); + VBox.setVgrow(sp, Priority.ALWAYS); - ScrollPane sp = new ScrollPane(cardsBox); - sp.setFitToWidth(true); - sp.getStyleClass().add("cyber-scroll-pane"); - VBox.setVgrow(sp, Priority.ALWAYS); + VBox container = wrapInDialogContainer("CERTIFICADOS DIGITAIS & ARQUIVOS SEGUROS", + "Certificados ICP-Brasil disponíveis para assinatura local no dispositivo.", + SvgIcons.certificatesIcon(), sp, 760, 520); - VBox container = wrapInDialogContainer("CERTIFICADOS DIGITAIS & ARQUIVOS SEGUROS", - "Certificados ICP-Brasil disponíveis para assinatura local no dispositivo.", - SvgIcons.certificatesIcon(), sp, 760, 520); + Scene scene = createScene(container, 760, 520); + stage.setScene(scene); + stage.show(); + scene.getRoot().applyCss(); + scene.getRoot().layout(); - Scene scene = createScene(container, 760, 520); - stage.setScene(scene); - stage.show(); - scene.getRoot().applyCss(); - scene.getRoot().layout(); - - String suffix = theme == ThemeManager.AppTheme.LIGHT ? "claro" : "escuro"; - saveNodeSnapshot(scene, new File(OUTPUT_DIR, "04_certificados_" + suffix + ".png")); - } + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "04_certificados.png")); + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "04_certificados_claro.png")); } private void captureValidationScreenshots(Stage stage) throws Exception { - for (ThemeManager.AppTheme theme : ThemeManager.AppTheme.values()) { - ThemeManager.setCurrentTheme(theme); - SignatureValidationDialog dlg = new SignatureValidationDialog(null); - // Captura layout do diálogo - Scene scene = createValidationSampleScene(stage); - stage.setScene(scene); - stage.show(); - scene.getRoot().applyCss(); - scene.getRoot().layout(); + SignatureValidationDialog dlg = new SignatureValidationDialog(null); + Scene scene = createValidationSampleScene(stage); + stage.setScene(scene); + stage.show(); + scene.getRoot().applyCss(); + scene.getRoot().layout(); - String suffix = theme == ThemeManager.AppTheme.LIGHT ? "claro" : "escuro"; - saveNodeSnapshot(scene, new File(OUTPUT_DIR, "05_validacao_" + suffix + ".png")); - } + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "05_validacao.png")); + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "05_validacao_claro.png")); } private void capturePromptScreenshots(Stage stage) throws Exception { - for (ThemeManager.AppTheme theme : ThemeManager.AppTheme.values()) { - ThemeManager.setCurrentTheme(theme); + ManagedCertificate cert = new ManagedCertificate( + "cert-a1", + "MARIA OLIVEIRA:98765432100", + CertificateType.A1, + CertificateStatus.AVAILABLE, + "CN=MARIA OLIVEIRA:98765432100, O=ICP-Brasil, C=BR", + "CN=AC CERTISIGN Multipla v5, O=ICP-Brasil, C=BR", + "3F4E5D", + "11223344", + "AABBCCDD", + Instant.now().minus(30, ChronoUnit.DAYS), + Instant.now().plus(330, ChronoUnit.DAYS), + "RSA", + 2048, + "MARIA OLIVEIRA:98765432100", + "98765432100", + null, + "SunJSSE", + null + ); - ManagedCertificate cert = new ManagedCertificate( - "cert-a1", - "MARIA OLIVEIRA:98765432100", - CertificateType.A1, - CertificateStatus.AVAILABLE, - "CN=MARIA OLIVEIRA:98765432100, O=ICP-Brasil, C=BR", - "CN=AC CERTISIGN Multipla v5, O=ICP-Brasil, C=BR", - "3F4E5D", - "11223344", - "AABBCCDD", - Instant.now().minus(30, ChronoUnit.DAYS), - Instant.now().plus(330, ChronoUnit.DAYS), - "RSA", - 2048, - "MARIA OLIVEIRA:98765432100", - "98765432100", - null, - "SunJSSE", - null - ); + SigningContext ctx = new SigningContext( + "req-9876-uuid", + "app-contratos-web", + new byte[32], + "SHA256withRSA", + null, + Instant.now().plusSeconds(120) + ); - SigningContext ctx = new SigningContext( - "req-9876-uuid", - "app-contratos-web", - new byte[32], - "SHA256withRSA", - null, - Instant.now().plusSeconds(120) - ); + SignaturePromptDialog dlg = new SignaturePromptDialog( + stage, + "Portal de Assinaturas Web", + "https://assinador.empresa.com.br", + cert, + ctx, + "Contrato_Prestacao_Servicos_2026.pdf", + "PDF", + false + ); - SignaturePromptDialog dlg = new SignaturePromptDialog( - stage, - "Portal de Assinaturas Web", - "https://assinador.empresa.com.br", - cert, - ctx, - "Contrato_Prestacao_Servicos_2026.pdf", - "PDF", - false - ); + Scene scene = createPromptSampleScene(cert, ctx); + stage.setScene(scene); + stage.show(); + scene.getRoot().applyCss(); + scene.getRoot().layout(); - Scene scene = createPromptSampleScene(cert, ctx); - stage.setScene(scene); - stage.show(); - scene.getRoot().applyCss(); - scene.getRoot().layout(); - - String suffix = theme == ThemeManager.AppTheme.LIGHT ? "claro" : "escuro"; - saveNodeSnapshot(scene, new File(OUTPUT_DIR, "06_solicitacao_" + suffix + ".png")); - } + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "06_solicitacao.png")); + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "06_solicitacao_claro.png")); } private void captureSealsScreenshots(Stage stage) throws Exception { - for (ThemeManager.AppTheme theme : ThemeManager.AppTheme.values()) { - ThemeManager.setCurrentTheme(theme); - SealManagementDialog dlg = new SealManagementDialog(stage); - Scene scene = createSealsSampleScene(); - stage.setScene(scene); - stage.show(); - scene.getRoot().applyCss(); - scene.getRoot().layout(); + SealManagementDialog dlg = new SealManagementDialog(stage); + Scene scene = createSealsSampleScene(); + stage.setScene(scene); + stage.show(); + scene.getRoot().applyCss(); + scene.getRoot().layout(); - String suffix = theme == ThemeManager.AppTheme.LIGHT ? "claro" : "escuro"; - saveNodeSnapshot(scene, new File(OUTPUT_DIR, "07_selos_" + suffix + ".png")); - } + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "07_selos.png")); + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "07_selos_claro.png")); } private void captureAboutScreenshots(Stage stage) throws Exception { - for (ThemeManager.AppTheme theme : ThemeManager.AppTheme.values()) { - ThemeManager.setCurrentTheme(theme); - AboutView aboutView = new AboutView(); + AboutView aboutView = new AboutView(); - VBox container = wrapInDialogContainer("SOBRE O ASSINADOR", - "Agente de assinatura digital ICP-Brasil com segurança criptográfica em nível de hardware.", - SvgIcons.aboutIcon(), aboutView, 620, 480); + VBox container = wrapInDialogContainer("SOBRE O ASSINADOR", + "Agente de assinatura digital ICP-Brasil com segurança criptográfica em nível de hardware.", + SvgIcons.aboutIcon(), aboutView, 620, 480); - Scene scene = createScene(container, 620, 480); - stage.setScene(scene); - stage.show(); - scene.getRoot().applyCss(); - scene.getRoot().layout(); + Scene scene = createScene(container, 620, 480); + stage.setScene(scene); + stage.show(); + scene.getRoot().applyCss(); + scene.getRoot().layout(); - String suffix = theme == ThemeManager.AppTheme.LIGHT ? "claro" : "escuro"; - saveNodeSnapshot(scene, new File(OUTPUT_DIR, "08_sobre_" + suffix + ".png")); - } + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "08_sobre.png")); + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "08_sobre_claro.png")); } private Scene createScene(VBox root, double w, double h) { @@ -358,105 +327,140 @@ public class UiPreviewGenerator extends Application { private VBox wrapInDialogContainer(String title, String subtitle, Node icon, Node content, double w, double h) { VBox container = new VBox(16); - container.getStyleClass().addAll("dialog-container", "cyber-root"); - container.setPadding(new Insets(20)); + container.getStyleClass().add("dialog-container"); + container.setPadding(new Insets(24)); HBox header = new HBox(12); header.setAlignment(Pos.CENTER_LEFT); VBox titleBox = new VBox(2); - Label titleLbl = new Label(title); - titleLbl.getStyleClass().add("dialog-header-title"); - Label subLbl = new Label(subtitle); - subLbl.getStyleClass().add("dialog-header-subtitle"); - titleBox.getChildren().addAll(titleLbl, subLbl); + Label lblTitle = new Label(title); + lblTitle.getStyleClass().addAll("dialog-header-title", "text-bold"); + + Label lblSub = new Label(subtitle); + lblSub.getStyleClass().add("dialog-subtitle"); + titleBox.getChildren().addAll(lblTitle, lblSub); header.getChildren().addAll(icon, titleBox); - VBox contentBox = new VBox(content); - VBox.setVgrow(contentBox, Priority.ALWAYS); - - container.getChildren().addAll(header, contentBox); + container.getChildren().addAll(header, content); return container; } private Scene createValidationSampleScene(Stage stage) { VBox root = new VBox(16); - root.setPadding(new Insets(20)); - root.getStyleClass().addAll("dialog-container", "cyber-root"); + root.getStyleClass().add("dialog-container"); + root.setPadding(new Insets(24)); HBox header = new HBox(12); header.setAlignment(Pos.CENTER_LEFT); - header.getChildren().addAll( - SvgIcons.validateIcon(), - new Label("VALIDAÇÃO DE ASSINATURA DIGITAL") - ); - VBox box = new VBox(12); - box.getStyleClass().add("dialog-box"); - box.getChildren().addAll( - new Label("Arquivo: Contrato_Prestacao_Servicos_Assinado.pdf"), - new Label("Status: Assinatura Válida e Íntegra"), - new Label("Assinado por: JOAO DA SILVA (CPF ***.123.456-**)"), - new Label("Autoridade Certificadora: AC SERPRO RFB v5 (ICP-Brasil)") - ); + VBox titleBox = new VBox(2); + Label title = new Label("VALIDAÇÃO DE DOCUMENTO ASSINADO"); + title.getStyleClass().addAll("dialog-header-title", "text-bold"); + Label sub = new Label("Verificação criptográfica de conformidade de assinaturas PAdES, CAdES e XMLDSig."); + sub.getStyleClass().add("dialog-subtitle"); + titleBox.getChildren().addAll(title, sub); + header.getChildren().addAll(SvgIcons.validateIcon(), titleBox); - root.getChildren().addAll(header, box); + VBox resultBox = new VBox(12); + resultBox.getStyleClass().add("content-card"); + resultBox.setPadding(new Insets(16)); + + Label docTitle = new Label("Documento: Relatorio_Financeiro_2026.pdf (Conforme ICP-Brasil)"); + docTitle.getStyleClass().add("text-bold"); + + Label statusLbl = new Label("✓ 1 Assinatura Digital VÁLIDA detectada"); + statusLbl.getStyleClass().addAll("status-badge", "status-badge-success", "text-bold"); + + VBox signerCard = new VBox(6); + signerCard.getStyleClass().add("certificate-card"); + signerCard.setPadding(new Insets(12)); + + Label signerName = new Label("Assinante: CARLOS EDUARDO SANTOS:55443322100"); + signerName.getStyleClass().add("text-bold"); + Label signerAc = new Label("Autoridade Certificadora: AC SERPRO RFB v5"); + signerAc.getStyleClass().add("text-muted"); + Label signerDate = new Label("Data/Hora: 20/10/2026 15:42:10 (Carimbo do Tempo Validado)"); + signerDate.getStyleClass().add("text-muted"); + + signerCard.getChildren().addAll(signerName, signerAc, signerDate); + resultBox.getChildren().addAll(docTitle, statusLbl, signerCard); + + root.getChildren().addAll(header, resultBox); return createScene(root, 720, 480); } private Scene createPromptSampleScene(ManagedCertificate cert, SigningContext ctx) { VBox root = new VBox(16); - root.setPadding(new Insets(22)); - root.getStyleClass().addAll("dialog-container", "cyber-root"); + root.getStyleClass().add("dialog-container"); + root.setPadding(new Insets(24)); HBox header = new HBox(12); header.setAlignment(Pos.CENTER_LEFT); - header.getChildren().addAll( - SvgIcons.cyberShieldLogo(24), - new Label("SOLICITAÇÃO DE ASSINATURA DIGITAL") - ); - VBox box = new VBox(10); - box.getStyleClass().add("dialog-box"); - box.getChildren().addAll( - new Label("Aplicação Solicitante: Portal de Assinaturas Web"), - new Label("Origem: https://assinador.empresa.com.br"), - new Label("Documento: Contrato_Prestacao_Servicos_2026.pdf"), - new Label("Algoritmo: " + ctx.algorithm()), - new Label("Certificado: " + cert.commonName() + " [" + cert.type().getCode() + "]") - ); + VBox titleBox = new VBox(2); + Label title = new Label("SOLICITAÇÃO DE ASSINATURA DIGITAL"); + title.getStyleClass().addAll("dialog-header-title", "text-bold"); + Label sub = new Label("Uma aplicação web autorizada requer sua confirmação para assinar um documento."); + sub.getStyleClass().add("dialog-subtitle"); + titleBox.getChildren().addAll(title, sub); + header.getChildren().addAll(SvgIcons.cyberShieldLogo(24), titleBox); - HBox actions = new HBox(12); - actions.setAlignment(Pos.CENTER_RIGHT); - Button btnReject = new Button("Recusar"); - btnReject.getStyleClass().add("btn-secondary"); - Button btnApprove = new Button("Autorizar Assinatura"); - btnApprove.getStyleClass().add("btn-primary"); - actions.getChildren().addAll(btnReject, btnApprove); + VBox box = new VBox(14); + box.getStyleClass().add("content-card"); + box.setPadding(new Insets(16)); - root.getChildren().addAll(header, box, actions); - return createScene(root, 620, 440); + Label appLbl = new Label("Aplicação Solicitante: Portal de Assinaturas Web (https://assinador.empresa.com.br)"); + appLbl.getStyleClass().add("text-bold"); + + Label docLbl = new Label("Documento: Contrato_Prestacao_Servicos_2026.pdf (Hash SHA-256)"); + docLbl.getStyleClass().add("text-muted"); + + VBox certNode = new VBox(6); + certNode.getStyleClass().add("certificate-card"); + certNode.setPadding(new Insets(12)); + Label certTitle = new Label("Certificado Digital Selecionado:"); + certTitle.getStyleClass().addAll("text-bold", "text-muted"); + Label certSubject = new Label(cert.commonName()); + certSubject.getStyleClass().add("text-bold"); + Label certEmissor = new Label("Emissor: " + cert.issuerDn()); + certEmissor.getStyleClass().add("text-muted"); + certNode.getChildren().addAll(certTitle, certSubject, certEmissor); + + HBox btnBar = new HBox(12); + btnBar.setAlignment(Pos.CENTER_RIGHT); + Button btnRecusar = new Button("Recusar"); + btnRecusar.getStyleClass().addAll("btn-ghost"); + Button btnConfirmar = new Button("Autorizar e Assinar"); + btnConfirmar.getStyleClass().addAll("btn-primary"); + btnBar.getChildren().addAll(btnRecusar, btnConfirmar); + + box.getChildren().addAll(appLbl, docLbl, certNode, btnBar); + root.getChildren().addAll(header, box); + return createScene(root, 700, 480); } private Scene createSealsSampleScene() { VBox root = new VBox(16); - root.setPadding(new Insets(20)); - root.getStyleClass().addAll("dialog-container", "cyber-root"); + root.getStyleClass().add("dialog-container"); + root.setPadding(new Insets(24)); HBox header = new HBox(12); header.setAlignment(Pos.CENTER_LEFT); - header.getChildren().addAll( - SvgIcons.sealIcon(), - new Label("GERENCIAMENTO DE SELOS VISUAIS") - ); - VBox box = new VBox(10); - box.getStyleClass().add("dialog-box"); + VBox titleBox = new VBox(2); + Label title = new Label("TEMAS E SELOS VISUAIS PAdES"); + title.getStyleClass().addAll("dialog-header-title", "text-bold"); + Label sub = new Label("Personalize a aparência dos carimbos visuais de assinatura digital em PDFs."); + sub.getStyleClass().add("dialog-subtitle"); + titleBox.getChildren().addAll(title, sub); + header.getChildren().addAll(SvgIcons.sealIcon(), titleBox); + + HBox box = new HBox(16); box.getChildren().addAll( - new Label("Selo Ativo: Padrão ICP-Brasil Institucional"), - new Label("Dimensões: 200 x 60 mm • Posição: Canto inferior direito"), - new Label("Elementos: Carimbo de Tempo + Brasão + Dados do Titular") + new Label("Visualização de Selos Padronizados ICP-Brasil"), + br.com.cybercore.signer.ui.components.Icons.sealIcpBrasil() ); root.getChildren().addAll(header, box); @@ -464,32 +468,26 @@ public class UiPreviewGenerator extends Application { } private void captureExitDialogScreenshots(Stage stage) throws Exception { - for (ThemeManager.AppTheme theme : ThemeManager.AppTheme.values()) { - ThemeManager.setCurrentTheme(theme); - ExitConfirmationDialog dialog = new ExitConfirmationDialog(null); - Scene scene = dialog.getStage().getScene(); - scene.getRoot().applyCss(); - scene.getRoot().layout(); + ExitConfirmationDialog dialog = new ExitConfirmationDialog(null); + Scene scene = dialog.getStage().getScene(); + scene.getRoot().applyCss(); + scene.getRoot().layout(); - String suffix = theme == ThemeManager.AppTheme.LIGHT ? "claro" : "escuro"; - saveNodeSnapshot(scene, new File(OUTPUT_DIR, "09_exit_dialog_" + suffix + ".png")); - } + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "09_exit_dialog.png")); + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "09_exit_dialog_claro.png")); } private void capturePdfSignDialogScreenshots(Stage stage) throws Exception { File samplePdf = getOrCreateSamplePdf(); CertificateManager certManager = CertificateManager.createDefault(); - for (ThemeManager.AppTheme theme : ThemeManager.AppTheme.values()) { - ThemeManager.setCurrentTheme(theme); - PdfSignDialog dialog = new PdfSignDialog(null, certManager, samplePdf); - Scene scene = dialog.getStage().getScene(); - scene.getRoot().applyCss(); - scene.getRoot().layout(); + PdfSignDialog dialog = new PdfSignDialog(null, certManager, samplePdf); + Scene scene = dialog.getStage().getScene(); + scene.getRoot().applyCss(); + scene.getRoot().layout(); - String suffix = theme == ThemeManager.AppTheme.LIGHT ? "claro" : "escuro"; - saveNodeSnapshot(scene, new File(OUTPUT_DIR, "10_pdf_sign_" + suffix + ".png")); - } + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "10_pdf_sign.png")); + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "10_pdf_sign_claro.png")); } private void capturePdfCertificateSignDialogScreenshots(Stage stage) throws Exception { @@ -514,23 +512,20 @@ public class UiPreviewGenerator extends Application { ); br.com.cybercore.signer.core.pdf.PdfSigningService pdfSigningService = new br.com.cybercore.signer.core.pdf.PdfSigningService(certManager); - for (ThemeManager.AppTheme theme : ThemeManager.AppTheme.values()) { - ThemeManager.setCurrentTheme(theme); - PdfCertificateSignDialog dialog = new PdfCertificateSignDialog( - null, - certManager, - pdfSigningService, - samplePdf, - config, - "Selo Padrão ICP-Brasil (Canto Inferior Direito)" - ); - Scene scene = dialog.getStage().getScene(); - scene.getRoot().applyCss(); - scene.getRoot().layout(); + PdfCertificateSignDialog dialog = new PdfCertificateSignDialog( + null, + certManager, + pdfSigningService, + samplePdf, + config, + "Selo Padrão ICP-Brasil (Canto Inferior Direito)" + ); + Scene scene = dialog.getStage().getScene(); + scene.getRoot().applyCss(); + scene.getRoot().layout(); - String suffix = theme == ThemeManager.AppTheme.LIGHT ? "claro" : "escuro"; - saveNodeSnapshot(scene, new File(OUTPUT_DIR, "11_pdf_cert_sign_" + suffix + ".png")); - } + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "11_pdf_cert_sign.png")); + saveNodeSnapshot(scene, new File(OUTPUT_DIR, "11_pdf_cert_sign_claro.png")); } private static File getOrCreateSamplePdf() throws Exception { @@ -539,17 +534,17 @@ public class UiPreviewGenerator extends Application { if (pdf.getParentFile() != null) { pdf.getParentFile().mkdirs(); } - try (org.apache.pdfbox.pdmodel.PDDocument doc = new org.apache.pdfbox.pdmodel.PDDocument()) { + try (org.apache.pdfbox.pdmodel.PDDocument document = new org.apache.pdfbox.pdmodel.PDDocument()) { org.apache.pdfbox.pdmodel.PDPage page = new org.apache.pdfbox.pdmodel.PDPage(); - doc.addPage(page); - try (org.apache.pdfbox.pdmodel.PDPageContentStream stream = new org.apache.pdfbox.pdmodel.PDPageContentStream(doc, page)) { - stream.beginText(); - stream.setFont(new org.apache.pdfbox.pdmodel.font.PDType1Font(org.apache.pdfbox.pdmodel.font.Standard14Fonts.FontName.HELVETICA_BOLD), 16); - stream.newLineAtOffset(50, 700); - stream.showText("CyberCore Signer — Documento PDF de Demonstração"); - stream.endText(); + document.addPage(page); + try (org.apache.pdfbox.pdmodel.PDPageContentStream cs = new org.apache.pdfbox.pdmodel.PDPageContentStream(document, page)) { + cs.beginText(); + cs.setFont(new org.apache.pdfbox.pdmodel.font.PDType1Font(org.apache.pdfbox.pdmodel.font.Standard14Fonts.FontName.HELVETICA_BOLD), 16); + cs.newLineAtOffset(50, 700); + cs.showText("CyberCore Signer - Documento de Teste de Assinatura"); + cs.endText(); } - doc.save(pdf); + document.save(pdf); } } return pdf; @@ -557,15 +552,16 @@ public class UiPreviewGenerator extends Application { private static void saveNodeSnapshot(Scene scene, File targetFile) throws Exception { WritableImage image = scene.snapshot(null); - int w = (int) image.getWidth(); - int h = (int) image.getHeight(); - BufferedImage bufferedImage = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); + int width = (int) image.getWidth(); + int height = (int) image.getHeight(); + BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); PixelReader reader = image.getPixelReader(); - for (int y = 0; y < h; y++) { - for (int x = 0; x < w; x++) { + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { bufferedImage.setRGB(x, y, reader.getArgb(x, y)); } } ImageIO.write(bufferedImage, "png", targetFile); + System.out.println("Screenshot gerada: " + targetFile.getName()); } } diff --git a/modules/cybercore-ui/src/test/java/br/com/cybercore/signer/ui/assets/AssetManagerTest.java b/modules/cybercore-ui/src/test/java/br/com/cybercore/signer/ui/assets/AssetManagerTest.java index 534909c..c5f7cb7 100644 --- a/modules/cybercore-ui/src/test/java/br/com/cybercore/signer/ui/assets/AssetManagerTest.java +++ b/modules/cybercore-ui/src/test/java/br/com/cybercore/signer/ui/assets/AssetManagerTest.java @@ -33,7 +33,7 @@ class AssetManagerTest { String[] iconNames = { "pdf", "xml", "file", "batch", "attached", "co-sign", "timestamp", "ltv", "validate", "validate-timestamp", "exit", - "logs", "settings", "tutorial", "cert", "about", "sun", "moon", + "logs", "settings", "tutorial", "cert", "about", "shield", "seal", "seal-icp-brasil", "check", "error", "star", "close", "arrow-right", "zoom-in", "zoom-out", "zoom-fit", "refresh" }; @@ -56,17 +56,10 @@ class AssetManagerTest { } @Test - @DisplayName("Deve repintar dinamicamente elementos currentColor ao mudar o tema") - void shouldRepaintCurrentColorDynamicallyOnThemeChange() { + @DisplayName("Deve carregar ícones SVG com cor dinâmica sem lançar exceções") + void shouldRenderDynamicSvgIcons() { Node iconNode = br.com.cybercore.signer.ui.components.Icons.settings(24); assertThat(iconNode).isInstanceOf(javafx.scene.layout.Pane.class); - - // Alterna o tema e garante que não lança erro - br.com.cybercore.signer.ui.theme.ThemeManager.setCurrentTheme(br.com.cybercore.signer.ui.theme.ThemeManager.AppTheme.DARK); - assertThat(br.com.cybercore.signer.ui.theme.ThemeManager.isDark()).isTrue(); - - br.com.cybercore.signer.ui.theme.ThemeManager.setCurrentTheme(br.com.cybercore.signer.ui.theme.ThemeManager.AppTheme.LIGHT); - assertThat(br.com.cybercore.signer.ui.theme.ThemeManager.isDark()).isFalse(); } @Test