diff --git a/src/main/java/net/rptools/maptool/client/MapTool.java b/src/main/java/net/rptools/maptool/client/MapTool.java index 55fb505a48..91b47bd0ec 100644 --- a/src/main/java/net/rptools/maptool/client/MapTool.java +++ b/src/main/java/net/rptools/maptool/client/MapTool.java @@ -29,6 +29,7 @@ import java.awt.Graphics2D; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; +import java.awt.SecondaryLoop; import java.awt.Toolkit; import java.awt.Transparency; import java.awt.event.WindowAdapter; @@ -42,6 +43,7 @@ import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.util.*; +import javafx.application.Platform; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.imageio.ImageIO; @@ -1472,6 +1474,15 @@ public static String getLoggerFileName() { return "NOT_CONFIGURED"; } + private static void initJavaFX() { + var eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue(); + SecondaryLoop secondaryLoop = eventQueue.createSecondaryLoop(); + Platform.startup(secondaryLoop::exit); + secondaryLoop.enter(); + + Platform.setImplicitExit(false); // necessary to use JavaFX later + } + public static void main(String[] args) { log.info("********************************************************************************"); log.info("** **"); @@ -1609,7 +1620,10 @@ public static void main(String[] args) { // System properties System.setProperty("swing.aatext", "true"); - final SplashScreen splash = new SplashScreen((isDevelopment()) ? getVersion() : getVersion()); + initJavaFX(); + + final SplashScreen splash = new SplashScreen(getVersion()); + splash.setVisible(true); try { ThemeSupport.loadTheme(); @@ -1721,7 +1735,8 @@ public static void main(String[] args) { EventQueue.invokeLater( () -> { clientFrame.setVisible(true); - splash.hideSplashScreen(); + splash.setVisible(false); + splash.dispose(); EventQueue.invokeLater(MapTool::postInitialize); }); }); diff --git a/src/main/java/net/rptools/maptool/client/swing/SplashScreen.java b/src/main/java/net/rptools/maptool/client/swing/SplashScreen.java index 5f4859fdcc..ad40237805 100644 --- a/src/main/java/net/rptools/maptool/client/swing/SplashScreen.java +++ b/src/main/java/net/rptools/maptool/client/swing/SplashScreen.java @@ -15,31 +15,58 @@ package net.rptools.maptool.client.swing; import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridBagLayout; +import java.awt.Image; +import java.awt.RenderingHints; import java.awt.Toolkit; +import java.awt.image.BufferedImage; +import java.io.InputStream; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import javafx.application.Platform; -import javafx.embed.swing.JFXPanel; import javafx.embed.swing.SwingFXUtils; import javafx.scene.Group; import javafx.scene.Scene; -import javafx.scene.image.Image; -import javafx.scene.image.ImageView; +import javafx.scene.SnapshotParameters; +import javafx.scene.effect.Effect; +import javafx.scene.effect.Glow; +import javafx.scene.image.WritableImage; import javafx.scene.paint.Color; +import javafx.scene.text.Font; +import javafx.scene.text.Text; +import javafx.stage.Stage; +import javafx.stage.StageStyle; import javax.swing.JFrame; -import net.rptools.maptool.util.CreateVersionedInstallSplash; +import javax.swing.JPanel; +import net.rptools.maptool.client.ui.theme.Images; +import net.rptools.maptool.client.ui.theme.RessourceManager; +import org.javatuples.Pair; public class SplashScreen extends JFrame { + private static final String FONT_RESOURCE = "/net/rptools/maptool/client/fonts/Horta.ttf"; - private static int imgWidth = 490; - private static int imgHeight = 290; + private static final int imgWidth = 490; + private static final int imgHeight = 290; + private static final int versionTextX = 48; + private static final int versionTextY = 37; - public SplashScreen(final String versionText) { - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - final JFXPanel fxPanel = new JFXPanel(); + public SplashScreen(String versionText) { + versionText = Character.isDigit(versionText.charAt(0)) ? "v" + versionText : versionText; setUndecorated(true); setType(Type.UTILITY); - add(fxPanel); + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + int w = imgWidth; + int h = imgHeight; + int x = (screenSize.width - w) / 2; + int y = (screenSize.height - h) / 2; + setBounds(x, y, imgWidth, imgHeight); + + setLocationRelativeTo(null); + setLayout(new GridBagLayout()); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); try { @@ -50,41 +77,81 @@ public SplashScreen(final String versionText) { setBackground(new java.awt.Color(0, 0, 0)); } - Platform.setImplicitExit(false); // necessary to use JavaFX later - Platform.runLater( - () -> { - initFX(fxPanel, versionText); - int w = imgWidth; - int h = imgHeight; - int x = (screenSize.width - w) / 2; - int y = (screenSize.height - h) / 2; - setBounds(x, y, imgWidth, imgHeight); - setVisible(true); + var image = createLaunchSplash("Launching... " + versionText); + + setContentPane( + new JPanel() { + @Override + protected void paintComponent(Graphics g) { + g.drawImage(image, 0, 0, imgWidth, imgHeight, null); + } }); } - private static void initFX(JFXPanel fxPanel, String versionText) { - // This method is invoked on the JavaFX thread - Group root = new Group(); - Scene scene = new Scene(root, Color.TRANSPARENT); + private static BufferedImage createLaunchSplash(String versionText) { + Image splashIcon = RessourceManager.getImage(Images.MAPTOOL_SPLASH); + final Color versionColor = Color.rgb(3, 78, 149, 1); // Color.rgb(27, 85, 139, 1) + + InputStream is = SplashScreen.class.getResourceAsStream(FONT_RESOURCE); + var versionFont = Font.loadFont(is, 28); + + BufferedImage buffImage = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_ARGB); + Graphics2D g2d = buffImage.createGraphics(); + RenderingHints rh = + new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + rh.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); + + g2d.setRenderingHints(rh); + g2d.drawImage(splashIcon, 0, 0, null); + + var future = + CompletableFuture.supplyAsync( + () -> { + // Adding glow twice to make it more pronounced... + var glowingText = textToImage(versionText, Color.WHITESMOKE, versionFont, true); + var regularText = textToImage(versionText, versionColor, versionFont, false); + return new Pair<>(glowingText, regularText); + }, + Platform::runLater); - if (Character.isDigit(versionText.charAt(0))) { - versionText = "v" + versionText; + try { + var result = future.get(); + // Adding glow twice to make it more pronounced... + g2d.drawImage(result.getValue0(), versionTextX, versionTextY, null); + g2d.drawImage(result.getValue0(), versionTextX, versionTextY, null); + g2d.drawImage(result.getValue1(), versionTextX, versionTextY, null); + + } catch (InterruptedException | ExecutionException e) { + // Oh no... we can't show the version. Oh, well. } - Image splashImage = - SwingFXUtils.toFXImage( - CreateVersionedInstallSplash.createLaunchSplash("Launching... " + versionText), null); - ImageView splashView = new ImageView(splashImage); - imgWidth = (int) splashImage.getWidth(); - imgHeight = (int) splashImage.getHeight(); - root.getChildren().add(splashView); + g2d.dispose(); - fxPanel.setScene(scene); + return buffImage; } - public void hideSplashScreen() { - setVisible(false); - dispose(); + private static BufferedImage textToImage( + String text, Color fontColor, Font versionFont, boolean addGlow) { + Text versionText = new Text(0, 0, text); + versionText.setFill(fontColor); + versionText.setFont(versionFont); + + if (addGlow) { + Effect glow = new Glow(1.0); + versionText.setEffect(glow); + } + + Stage stage = new Stage(StageStyle.TRANSPARENT); + Group root = new Group(); + Scene scene = new Scene(root); + SnapshotParameters sp = new SnapshotParameters(); + + sp.setFill(Color.TRANSPARENT); + stage.setScene(scene); + root.getChildren().add(versionText); + + WritableImage img = root.snapshot(sp, null); + + return SwingFXUtils.fromFXImage(img, null); } } diff --git a/src/main/java/net/rptools/maptool/util/CreateVersionedInstallSplash.java b/src/main/java/net/rptools/maptool/util/CreateVersionedInstallSplash.java deleted file mode 100644 index 25f6688333..0000000000 --- a/src/main/java/net/rptools/maptool/util/CreateVersionedInstallSplash.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * This software Copyright by the RPTools.net development team, and - * licensed under the Affero GPL Version 3 or, at your option, any later - * version. - * - * MapTool Source Code is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public - * License * along with this source Code. If not, please visit - * and specifically the Affero license - * text at . - */ -package net.rptools.maptool.util; - -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import javafx.application.Application; -import javafx.embed.swing.SwingFXUtils; -import javafx.scene.Group; -import javafx.scene.Scene; -import javafx.scene.SnapshotParameters; -import javafx.scene.effect.Effect; -import javafx.scene.effect.Glow; -import javafx.scene.image.WritableImage; -import javafx.scene.paint.Color; -import javafx.scene.text.Font; -import javafx.scene.text.Text; -import javafx.stage.Stage; -import javafx.stage.StageStyle; -import javax.imageio.ImageIO; -import javax.swing.ImageIcon; -import net.rptools.maptool.client.swing.SplashScreen; -import net.rptools.maptool.client.ui.theme.Images; -import net.rptools.maptool.client.ui.theme.RessourceManager; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.CommandLineParser; -import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; - -public class CreateVersionedInstallSplash extends Application { - private static String resourceImage = null; - private static String webOutputPath; - private static String versionText = "Dev-Build"; - private static final String FONT_RESOURCE = "/net/rptools/maptool/client/fonts/Horta.ttf"; - private static Font versionFont; - - public static void main(String[] args) { - Options cmdOptions = new Options(); - cmdOptions.addOption("s", "source", true, "Source image to add version string to."); - cmdOptions.addOption("o", "output", true, "Output /path/image to write to."); - cmdOptions.addOption("v", "version", true, "Version text to add to image."); - cmdOptions.addOption("w", "web_output", true, "Output path for upload to web server"); - - // Parameters that can be overridden via command line options... - resourceImage = getCommandLineOption(cmdOptions, "source", resourceImage, args); - versionText = getCommandLineOption(cmdOptions, "version", versionText, args); - webOutputPath = getCommandLineOption(cmdOptions, "web_output", null, args); - - Application.launch(args); - } - - @Override - public void start(Stage primaryStage) { - BufferedImage webImage = createLaunchSplash("v" + versionText); - - try { - System.out.println("Version: " + versionText); - System.out.println("Source: " + resourceImage); - - if (webOutputPath != null) { - System.out.println("Web Output: " + webOutputPath); - updateWebVersion(versionText); - ImageIO.write(webImage, "png", new File(webOutputPath + "/MapTool-splash.png")); - } - - } catch (IOException e) { - System.err.println("Error: " + e.getMessage()); - } - - System.exit(0); - } - - private static void updateWebVersion(String versionText) throws IOException { - File releaseDir = new File(webOutputPath); - if (!releaseDir.mkdirs()) - System.out.println("Error: Unable to create directory path [" + releaseDir + "]"); - - FileWriter fstream = new FileWriter(webOutputPath + "/MapTool-version.js"); - BufferedWriter out = new BufferedWriter(fstream); - out.write("var mtVersion = \"" + versionText + "\";"); - out.close(); - } - - public static BufferedImage createLaunchSplash(String versionText) { - Image splashIcon = RessourceManager.getImage(Images.MAPTOOL_SPLASH); - if (resourceImage != null) { - splashIcon = - new ImageIcon(SplashScreen.class.getClassLoader().getResource(resourceImage)).getImage(); - } - final Color versionColor = Color.rgb(3, 78, 149, 1); // Color.rgb(27, 85, 139, 1) - - final int imgWidth = 490; - final int imgHeight = 290; - final int versionTextX = 48; - final int versionTextY = 37; - - InputStream is = SplashScreen.class.getResourceAsStream(FONT_RESOURCE); - versionFont = Font.loadFont(is, 28); - - BufferedImage buffImage = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_ARGB); - Graphics2D g2d = buffImage.createGraphics(); - RenderingHints rh = - new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - rh.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); - - g2d.setRenderingHints(rh); - g2d.drawImage(splashIcon, 0, 0, null); - - // Adding glow twice to make it more pronounced... - g2d.drawImage( - textToImage(versionText, Color.WHITESMOKE, 28, true), versionTextX, versionTextY, null); - g2d.drawImage( - textToImage(versionText, Color.WHITESMOKE, 28, true), versionTextX, versionTextY, null); - g2d.drawImage( - textToImage(versionText, versionColor, 28, false), versionTextX, versionTextY, null); - g2d.dispose(); - - return buffImage; - } - - private static BufferedImage textToImage( - String text, Color fontColor, int fontSize, boolean addGlow) { - Text versionText = new Text(0, 0, text); - versionText.setFill(fontColor); - versionText.setFont(versionFont); - - if (addGlow) { - Effect glow = new Glow(1.0); - versionText.setEffect(glow); - } - - Stage stage = new Stage(StageStyle.TRANSPARENT); - Group root = new Group(); - Scene scene = new Scene(root); - SnapshotParameters sp = new SnapshotParameters(); - - sp.setFill(Color.TRANSPARENT); - stage.setScene(scene); - root.getChildren().add(versionText); - - WritableImage img = root.snapshot(sp, null); - - return SwingFXUtils.fromFXImage(img, null); - } - - private static String getCommandLineOption( - Options options, String searchValue, String defaultValue, String[] args) { - CommandLineParser parser = new DefaultParser(); - - try { - CommandLine cmd = parser.parse(options, args); - - if (cmd.hasOption(searchValue)) { - return cmd.getOptionValue(searchValue); - } - } catch (ParseException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - return defaultValue; - } -}