Java tutorial
/******************************************************************************* * Copyright 2014 Rafael Garcia Moreno. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package com.bladecoder.engineeditor.ui; import java.io.File; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.util.Arrays; import java.util.Properties; import org.apache.commons.io.FileUtils; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.Stage; import com.badlogic.gdx.scenes.scene2d.ui.SelectBox; import com.badlogic.gdx.scenes.scene2d.ui.Skin; import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener; import com.badlogicgames.packr.Packr; import com.badlogicgames.packr.Packr.Platform; import com.bladecoder.engine.actions.Param.Type; import com.bladecoder.engine.util.Config; import com.bladecoder.engineeditor.Ctx; import com.bladecoder.engineeditor.ui.components.EditDialog; import com.bladecoder.engineeditor.ui.components.FileInputPanel; import com.bladecoder.engineeditor.ui.components.InputPanel; import com.bladecoder.engineeditor.ui.components.InputPanelFactory; import com.bladecoder.engineeditor.utils.Message; import com.bladecoder.engineeditor.utils.RunProccess; import com.badlogic.gdx.scenes.scene2d.ui.TextField; public class PackageDialog extends EditDialog { private static final String ARCH_PROP = "package.arch"; private static final String DIR_PROP = "package.dir"; private static final String DESKTOP_LAUNCHER = "org/bladecoder/engine/desktop/DesktopLauncher"; private static final String INFO = "Package the Adventure for distribution"; private static final String[] ARCHS = { "desktop", "android", "ios", "html" }; private static final String[] TYPES = { "Bundle JRE", "Runnable jar" }; private static final String[] OSS = { "all", "windows", "linux64", "linux32", "macOSX" }; private InputPanel arch; private InputPanel dir; private InputPanel type; private InputPanel os; private InputPanel linux64JRE; private InputPanel linux32JRE; private InputPanel winJRE; private InputPanel osxJRE; private InputPanel version; private InputPanel icon; private InputPanel androidVersionCode; private InputPanel androidSDK; private InputPanel androidKeyStore; private InputPanel androidKeyAlias; private InputPanel androidKeyStorePassword; private InputPanel androidKeyAliasPassword; private InputPanel[] options = new InputPanel[12]; @SuppressWarnings("unchecked") public PackageDialog(Skin skin) { super("PACKAGE ADVENTURE", skin); arch = InputPanelFactory.createInputPanel(skin, "Architecture", "Select the target Architecture for the game", ARCHS, true); dir = new FileInputPanel(skin, "Output Directory", "Select the output directory to put the package", FileInputPanel.DialogType.DIRECTORY); type = InputPanelFactory.createInputPanel(skin, "Type", "Select the package type", TYPES, true); os = InputPanelFactory.createInputPanel(skin, "OS", "Select the OS of the package", OSS, true); linux64JRE = new FileInputPanel(skin, "JRE.Linux64", "Select the 64 bits Linux JRE Location to bundle. Must be a ZIP file", FileInputPanel.DialogType.OPEN_FILE); linux32JRE = new FileInputPanel(skin, "JRE.Linux32", "Select the 32 bits Linux JRE Location to bundle. Must be a ZIP file", FileInputPanel.DialogType.OPEN_FILE); winJRE = new FileInputPanel(skin, "JRE.Windows", "Select the Windows JRE Location to bundle. Must be a ZIP file", FileInputPanel.DialogType.OPEN_FILE); osxJRE = new FileInputPanel(skin, "JRE.OSX", "Select the OSX JRE Location to bundle. Must be a ZIP file", FileInputPanel.DialogType.OPEN_FILE); version = InputPanelFactory.createInputPanel(skin, "Version", "Select the package version", true); icon = new FileInputPanel(skin, "Icon", "The icon for the .exe file", FileInputPanel.DialogType.OPEN_FILE); androidVersionCode = InputPanelFactory.createInputPanel(skin, "Version Code", "An integer that identify the version.", Type.INTEGER, true); androidSDK = new FileInputPanel(skin, "SDK", "Select the Android SDK Location. If empty, the ANDROID_HOME variable will be used.", FileInputPanel.DialogType.DIRECTORY, false); androidKeyStore = new FileInputPanel(skin, "KeyStore", "Select the Key Store Location", FileInputPanel.DialogType.OPEN_FILE); androidKeyAlias = InputPanelFactory.createInputPanel(skin, "KeyAlias", "Select the Key Alias Location", true); androidKeyStorePassword = InputPanelFactory.createInputPanel(skin, "KeyStorePasswd", "Key Store Password", true); androidKeyAliasPassword = InputPanelFactory.createInputPanel(skin, "KeyAliasPasswd", "Key Alias Password", true); options[0] = type; options[1] = os; options[2] = linux64JRE; options[3] = linux32JRE; options[4] = winJRE; options[5] = osxJRE; options[6] = version; options[7] = icon; options[8] = androidVersionCode; options[9] = androidSDK; options[10] = androidKeyStore; options[11] = androidKeyAlias; addInputPanel(arch); addInputPanel(dir); for (InputPanel i : options) { addInputPanel(i); } addInputPanel(androidKeyStorePassword); addInputPanel(androidKeyAliasPassword); ((TextField) androidKeyStorePassword.getField()).setPasswordMode(true); ((TextField) androidKeyStorePassword.getField()).setPasswordCharacter('*'); ((TextField) androidKeyAliasPassword.getField()).setPasswordMode(true); ((TextField) androidKeyAliasPassword.getField()).setPasswordCharacter('*'); dir.setMandatory(true); arch.setText(Ctx.project.getEditorConfig().getProperty(ARCH_PROP, ARCHS[0])); dir.setText(Ctx.project.getEditorConfig().getProperty(DIR_PROP, "")); for (InputPanel i : options) { String prop = Ctx.project.getEditorConfig().getProperty("package." + i.getTitle()); if (prop != null && !prop.isEmpty()) i.setText(prop); } version.setText(Ctx.project.getProjectConfig().getProperty(Config.VERSION_PROP, version.getText())); // TODO Set version code based in version // androidVersionCode.setText(genVersionCode(version.getText())); setInfo(INFO); ((SelectBox<String>) (arch.getField())).addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { archChanged(); } }); ((SelectBox<String>) (type.getField())).addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { typeChanged(); } }); ((SelectBox<String>) (os.getField())).addListener(new ChangeListener() { @Override public void changed(ChangeEvent event, Actor actor) { osChanged(); } }); archChanged(); } @Override protected void ok() { new Thread(new Runnable() { Stage stage = getStage(); @Override public void run() { Message.showMsg(stage, "Generating package...", true); String msg; try { msg = packageAdv(); } catch (Exception e) { msg = "Error Generating package\n\n" + e.getMessage(); } Ctx.project.getEditorConfig().setProperty(ARCH_PROP, arch.getText()); Ctx.project.getEditorConfig().setProperty(DIR_PROP, dir.getText()); for (InputPanel i : options) { if (i.getText() != null) Ctx.project.getEditorConfig().setProperty("package." + i.getTitle(), i.getText()); } Message.hideMsg(); if (msg != null) Message.showMsgDialog(stage, "Result", msg); } }).start(); } private String packageAdv() throws IOException { String msg = "Package generated SUCCESSFULLY"; String projectName = getAppName(); if (projectName == null) Ctx.project.getProjectDir().getName(); String versionParam = "-Pversion=" + version.getText() + " "; Ctx.project.getProjectConfig().setProperty(Config.VERSION_PROP, version.getText()); if (arch.getText().equals("desktop")) { String jarDir = Ctx.project.getProjectDir().getAbsolutePath() + "/desktop/build/libs/"; String jarName = projectName + "-desktop-" + version.getText() + ".jar"; msg = genDesktopJar(projectName, versionParam, jarDir, jarName); if (type.getText().equals(TYPES[0])) { // BUNDLE JRE if (os.getText().equals("linux64")) { packr(Platform.linux64, linux64JRE.getText(), projectName, jarDir + jarName, DESKTOP_LAUNCHER, dir.getText()); } else if (os.getText().equals("linux32")) { packr(Platform.linux32, linux32JRE.getText(), projectName, jarDir + jarName, DESKTOP_LAUNCHER, dir.getText()); } else if (os.getText().equals("windows")) { packr(Platform.windows, winJRE.getText(), projectName, jarDir + jarName, DESKTOP_LAUNCHER, dir.getText()); } else if (os.getText().equals("macOSX")) { packr(Platform.mac, osxJRE.getText(), projectName, jarDir + jarName, DESKTOP_LAUNCHER, dir.getText()); } else if (os.getText().equals("all")) { packr(Platform.linux64, linux64JRE.getText(), projectName, jarDir + jarName, DESKTOP_LAUNCHER, dir.getText()); packr(Platform.linux32, linux32JRE.getText(), projectName, jarDir + jarName, DESKTOP_LAUNCHER, dir.getText()); packr(Platform.windows, winJRE.getText(), projectName, jarDir + jarName, DESKTOP_LAUNCHER, dir.getText()); packr(Platform.mac, osxJRE.getText(), projectName, jarDir + jarName, DESKTOP_LAUNCHER, dir.getText()); } } } else if (arch.getText().equals("android")) { String params = versionParam + "-PversionCode=" + androidVersionCode.getText() + " " + "-Pkeystore=" + androidKeyStore.getText() + " " + "-PstorePassword=" + androidKeyStorePassword.getText() + " " + "-Palias=" + androidKeyAlias.getText() + " " + "-PkeyPassword=" + androidKeyAliasPassword.getText() + " "; // UPDATE 'local.properties' with the android SDK location. if (androidSDK.getText() != null && !androidSDK.getText().trim().isEmpty()) { String sdk = androidSDK.getText(); Properties p = new Properties(); p.setProperty("sdk.dir", sdk); p.store(new FileOutputStream( new File(Ctx.project.getProjectDir().getAbsolutePath(), "local.properties")), null); } if (RunProccess.runGradle(Ctx.project.getProjectDir(), params + "android:assembleRelease")) { String apk = Ctx.project.getProjectDir().getAbsolutePath() + "/android/build/outputs/apk/android-release.apk"; File f = new File(apk); // FileUtils.copyFileToDirectory(f, new File(dir.getText())); FileUtils.copyFile(f, new File(dir.getText(), projectName + "-" + version.getText() + ".apk")); } else { msg = "Error Generating package"; } } else if (arch.getText().equals("ios")) { if (RunProccess.runGradle(Ctx.project.getProjectDir(), "ios:createIPA")) { FileUtils.copyDirectory( new File(Ctx.project.getProjectDir().getAbsolutePath() + "/ios/build/robovm/"), new File(dir.getText())); } else { msg = "Error Generating package"; } } else if (arch.getText().equals("html")) { if (RunProccess.runGradle(Ctx.project.getProjectDir(), "html:dist")) { FileUtils.copyDirectory( new File(Ctx.project.getProjectDir().getAbsolutePath() + "/html/build/dist"), new File(dir.getText())); } else { msg = "Error Generating package"; } } return msg; } private void archChanged() { for (InputPanel ip : options) { setVisible(ip, false); } setVisible(androidKeyStorePassword, false); setVisible(androidKeyAliasPassword, false); setVisible(version, true); String a = arch.getText(); if (a.equals("desktop")) { setVisible(type, true); typeChanged(); } else if (a.equals("android")) { setVisible(androidVersionCode, true); setVisible(androidSDK, true); setVisible(androidKeyStore, true); setVisible(androidKeyAlias, true); setVisible(androidKeyStorePassword, true); setVisible(androidKeyAliasPassword, true); } else if (a.equals("html")) { Message.showMsgDialog(getStage(), "Not Supported", "HTML export is not supported yet."); } } private void typeChanged() { if (type.getText().equals(TYPES[0])) { setVisible(os, true); } else { setVisible(os, false); setVisible(icon, false); } osChanged(); } private void osChanged() { if (os.isVisible() && (os.getText().equals("windows") || os.getText().equals("all"))) { setVisible(icon, true); setVisible(winJRE, true); } else { setVisible(icon, false); setVisible(winJRE, false); } if (os.isVisible() && (os.getText().equals("linux32") || os.getText().equals("all"))) { setVisible(linux32JRE, true); } else { setVisible(linux32JRE, false); } if (os.isVisible() && (os.getText().equals("linux64") || os.getText().equals("all"))) { setVisible(linux64JRE, true); } else { setVisible(linux64JRE, false); } if (os.isVisible() && (os.getText().equals("macOSX") || os.getText().equals("all"))) { setVisible(osxJRE, true); } else { setVisible(osxJRE, false); } } @Override protected boolean validateFields() { boolean ok = true; if (!dir.validateField()) ok = false; for (InputPanel i : options) { if (i.isVisible() && !i.validateField()) ok = false; } if (androidKeyStorePassword.isVisible() && !androidKeyStorePassword.validateField()) ok = false; if (androidKeyAliasPassword.isVisible() && !androidKeyAliasPassword.validateField()) ok = false; // if (icon.isVisible() && !icon.getText().endsWith(".ico")) { // icon.setError(true); // ok = false; // } if (linux32JRE.isVisible() && (!new File(linux32JRE.getText()).exists() || !linux32JRE.getText().toLowerCase().endsWith(".zip"))) { linux32JRE.setError(true); ok = false; } if (linux64JRE.isVisible() && (!new File(linux64JRE.getText()).exists() || !linux64JRE.getText().toLowerCase().endsWith(".zip"))) { linux64JRE.setError(true); ok = false; } if (winJRE.isVisible() && (!new File(winJRE.getText()).exists() || !winJRE.getText().toLowerCase().endsWith(".zip"))) { winJRE.setError(true); ok = false; } if (osxJRE.isVisible() && (!new File(osxJRE.getText()).exists() || !osxJRE.getText().toLowerCase().endsWith(".zip"))) { osxJRE.setError(true); ok = false; } return ok; } private String genDesktopJar(String projectName, String versionParam, String jarDir, String jarName) throws IOException { String msg = null; if (RunProccess.runGradle(Ctx.project.getProjectDir(), versionParam + "desktop:dist")) { File f = new File(jarDir + jarName); FileUtils.copyFileToDirectory(f, new File(dir.getText())); new File(jarDir, jarName).setExecutable(true); new File(dir.getText(), jarName).setExecutable(true); } else { msg = "Error Generating package"; } return msg; } private void packr(Platform platform, String jdk, String exe, String jar, String mainClass, String outDir) throws IOException { String suffix = null; ; switch (platform) { case linux32: suffix = "lin32"; break; case linux64: suffix = "lin64"; break; case mac: suffix = "mac"; break; case windows: suffix = "win"; break; } Packr.Config config = new Packr.Config(); config.platform = platform; config.jdk = jdk; config.executable = exe; config.jar = jar; config.mainClass = mainClass; config.vmArgs = Arrays.asList("-Xmx1G"); config.minimizeJre = new String[] { "jre/lib/rt/com/sun/corba", "jre/lib/rt/com/sun/jndi" }; config.outDir = outDir + "/" + exe + "-" + suffix; new Packr().pack(config); } /** * @return The appName from the file gradle.properties from the game */ private String getAppName() { Properties prop = new Properties(); try { prop.load(new FileReader(Ctx.project.getProjectDir().getAbsolutePath() + "/gradle.properties")); return prop.getProperty("appName"); } catch (IOException e) { Message.showMsg(getStage(), "Error reading file 'gradle.properties' from the game.", 3); } return null; } }