/* * Copyright (c) 1998-2017 by Richard A. Wilkes. All rights reserved. * * This Source Code Form is subject to the terms of the Mozilla Public * License, version 2.0. If a copy of the MPL was not distributed with * this file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This Source Code Form is "Incompatible With Secondary Licenses", as * defined by the Mozilla Public License, version 2.0. */ package com.trollworks.gcs.character; import com.trollworks.gcs.common.TemporaryFile; import com.trollworks.gcs.preferences.OutputPreferences; import com.trollworks.gcs.services.HttpMethodType; import com.trollworks.gcs.services.NotImplementedException; import com.trollworks.gcs.services.WebServiceClient; import com.trollworks.toolkit.annotation.Localize; import com.trollworks.toolkit.io.Log; import com.trollworks.toolkit.io.xml.XMLWriter; import com.trollworks.toolkit.ui.image.StdImage; import com.trollworks.toolkit.ui.menu.Command; import com.trollworks.toolkit.ui.widget.WindowUtils; import com.trollworks.toolkit.utility.Localization; import java.awt.Color; import java.awt.Desktop; import java.awt.Font; import java.awt.KeyboardFocusManager; import java.io.ByteArrayOutputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Files; import java.text.MessageFormat; import java.util.Scanner; import java.util.UUID; import javax.swing.JEditorPane; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; /** Provides export to GURPS Calculator. */ public class GURPSCalculator { @Localize("Replace") private static String OPTION_REPLACE; @Localize("Create New") private static String OPTION_CREATE_NEW; @Localize("Cancel") private static String OPTION_CANCEL; @Localize("Character Exists") private static String TITLE_CHARACTER_EXISTS; @Localize("This character already exists in GURPS Calculator.\nWould you like to replace it?\n\nIf you choose 'Create New', you should save your\ncharacter afterwards.") private static String TEXT_CHARACTER_EXISTS; @Localize("Success") private static String SUCCESS_TITLE; @Localize("Export to GURPS Calculator was successful.") private static String SUCCESS_MESSAGE; @Localize("There was an error exporting to GURPS Calculator. Please try again later.") private static String ERROR_MESSAGE; @Localize("You need to set a valid GURPS Calculator Key in sheet preferences.<br><a href='%s'>Click here</a> for more information.") private static String KEY_MISSING_MESSAGE; @Localize("Unable to open {0}") protected static String UNABLE_TO_OPEN_URL; static { Localization.initialize(); } public static void export(CharacterSheet sheet) { if (sheet != null) { GURPSCharacter character = sheet.getCharacter(); WebServiceClient client = new WebServiceClient(OutputPreferences.BASE_GURPS_CALCULATOR_URL); try { if (showExistsDialogIfNecessary(client, character)) { try (TemporaryFile templateFile = new TemporaryFile("gcalcTemplate", ".html")) { //$NON-NLS-1$ //$NON-NLS-2$ try (PrintWriter out = new PrintWriter(templateFile)) { out.print(client.sendRequest(HttpMethodType.GET, "api/GetOutputTemplate")); //$NON-NLS-1$ } try (TemporaryFile outputFile = new TemporaryFile("gcalcOutput", ".html")) { //$NON-NLS-1$ //$NON-NLS-2$ if (new TextTemplate(sheet).export(outputFile, templateFile)) { String result = null; try (Scanner scanner = new Scanner(outputFile)) { result = scanner.useDelimiter("\\A").next(); //$NON-NLS-1$ } catch (FileNotFoundException exception) { Log.error(exception); } UUID id = character.getId(); String key = OutputPreferences.getGurpsCalculatorKey(); String path = String.format("api/SaveCharacter/%s/%s", id, key); //$NON-NLS-1$ result = client.sendRequest(HttpMethodType.POST, path, null, result); if (!result.isEmpty()) { throw new IOException("Bad response from the web server for template write"); //$NON-NLS-1$ } try (TemporaryFile image = new TemporaryFile("gcalcImage", ".png")) { //$NON-NLS-1$ //$NON-NLS-2$ StdImage.writePNG(image, character.getDescription().getPortrait().getRetina(), 150); path = String.format("api/SaveCharacterImage/%s/%s", id, key); //$NON-NLS-1$ result = client.sendRequest(HttpMethodType.POST, path, Files.readAllBytes(image.toPath())); if (!result.isEmpty()) { throw new IOException("Bad response from the web server for image write"); //$NON-NLS-1$ } } try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { try (XMLWriter w = new XMLWriter(out)) { character.save(w, true, false); } path = String.format("api/SaveCharacterRawFileGCS/%s/%s", id, key); //$NON-NLS-1$ result = client.sendRequest(HttpMethodType.POST, path, out.toByteArray()); if (!result.isEmpty()) { throw new IOException("Bad response from the web server for GCS file write"); //$NON-NLS-1$ } } showResult(true); } else { showResult(false); } } } } } catch (Exception exception) { Log.error(exception); showResult(false); } } } private static boolean showExistsDialogIfNecessary(WebServiceClient client, GURPSCharacter character) throws MalformedURLException, IOException, NotImplementedException { if (client.sendRequest(HttpMethodType.GET, String.format("api/GetCharacterExists/%s/%s", character.getId(), OutputPreferences.getGurpsCalculatorKey())).equals("true")) { //$NON-NLS-1$ //$NON-NLS-2$ switch (JOptionPane.showOptionDialog(KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner(), TEXT_CHARACTER_EXISTS, TITLE_CHARACTER_EXISTS, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new Object[] { OPTION_REPLACE, OPTION_CREATE_NEW, OPTION_CANCEL }, OPTION_CANCEL)) { case 1: character.generateNewId(); character.setModified(true); break; case 2: return false; default: break; } } return true; } private static void showResult(boolean success) { String message = success ? SUCCESS_MESSAGE : ERROR_MESSAGE; String key = OutputPreferences.getGurpsCalculatorKey(); if (key == null || !key.matches("[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89ab][0-9a-fA-F]{3}-[0-9a-fA-F]{12}")) { //$NON-NLS-1$ message = String.format(KEY_MISSING_MESSAGE, OutputPreferences.GURPS_CALCULATOR_URL); } JLabel styleLabel = new JLabel(); Font font = styleLabel.getFont(); Color color = styleLabel.getBackground(); StringBuilder buffer = new StringBuilder(); buffer.append("<html><body style='font-family:"); //$NON-NLS-1$ buffer.append(font.getFamily()); buffer.append(";font-weight:"); //$NON-NLS-1$ buffer.append(font.isBold() ? "bold" : "normal"); //$NON-NLS-1$ //$NON-NLS-2$ buffer.append(";font-size:"); //$NON-NLS-1$ buffer.append(font.getSize()); buffer.append("pt;background-color: rgb("); //$NON-NLS-1$ buffer.append(color.getRed()); buffer.append(","); //$NON-NLS-1$ buffer.append(color.getGreen()); buffer.append(","); //$NON-NLS-1$ buffer.append(color.getBlue()); buffer.append(");'>"); //$NON-NLS-1$ buffer.append(message); buffer.append("</body></html>"); //$NON-NLS-1$ JEditorPane messagePane = new JEditorPane("text/html", buffer.toString()); //$NON-NLS-1$ messagePane.setEditable(false); messagePane.setBorder(null); messagePane.addHyperlinkListener(new HyperlinkListener() { @Override public void hyperlinkUpdate(HyperlinkEvent event) { if (Desktop.isDesktopSupported() && event.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) { URL url = event.getURL(); try { Desktop.getDesktop().browse(url.toURI()); } catch (IOException | URISyntaxException exception) { WindowUtils.showError(null, MessageFormat.format(UNABLE_TO_OPEN_URL, url.toExternalForm())); } } } }); JOptionPane.showMessageDialog(Command.getFocusOwner(), messagePane, success ? SUCCESS_TITLE : WindowUtils.ERROR, success ? JOptionPane.INFORMATION_MESSAGE : JOptionPane.ERROR_MESSAGE); } }