From 21dcb477dc573b8c01c9edd44368aa877cd38b84 Mon Sep 17 00:00:00 2001 From: huangyuhui Date: Tue, 9 Feb 2016 22:28:36 +0800 Subject: [PATCH] for darkyoooooo's advice --- .../launcher/core/asset/IAssetsHandler.java | 2 +- .../core/asset/MinecraftAssetService.java | 78 +++++++++ .../launcher/core/auth/IAuthenticator.java | 10 +- .../core/launch/AbstractMinecraftLoader.java | 12 +- .../core/launch/DefaultGameLauncher.java | 2 +- .../launcher/core/launch/MinecraftLoader.java | 97 ++--------- .../setting/DefaultMinecraftService.java | 4 +- .../launcher/ui/GameSettingsPanel.java | 9 +- .../launcher/ui/LaunchingUIDaemon.java | 111 ++++++++++++ .../hellominecraft/launcher/ui/MainFrame.java | 158 +++++++++--------- .../launcher/ui/MainPagePanel.form | 1 + .../launcher/ui/MainPagePanel.java | 108 ++---------- .../launcher/ui/modpack/ModpackWizard.java | 2 + .../hellominecraft/lookandfeel/Theme.java | 6 + 14 files changed, 334 insertions(+), 266 deletions(-) create mode 100644 HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/LaunchingUIDaemon.java diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/asset/IAssetsHandler.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/asset/IAssetsHandler.java index 8644cf8f1..cdee384f5 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/asset/IAssetsHandler.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/asset/IAssetsHandler.java @@ -118,7 +118,7 @@ public abstract class IAssetsHandler { IOUtils.closeQuietly(fis); if (contents.get(i).geteTag().equals(sha)) { hasDownloaded++; - HMCLog.log("File " + assetsLocalNames.get(i) + " has downloaded successfully, skipped downloading."); + HMCLog.log("File " + assetsLocalNames.get(i) + " has been downloaded successfully, skipped download."); if (ppl != null) ppl.setProgress(this, hasDownloaded, max); continue; diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/asset/MinecraftAssetService.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/asset/MinecraftAssetService.java index bbc08bcc7..26f6283c9 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/asset/MinecraftAssetService.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/asset/MinecraftAssetService.java @@ -20,11 +20,15 @@ package org.jackhuang.hellominecraft.launcher.core.asset; import com.google.gson.JsonSyntaxException; import java.io.File; import java.io.IOException; +import java.util.Map; import org.jackhuang.hellominecraft.util.C; import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftAssetService; +import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftProvider; import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService; import org.jackhuang.hellominecraft.launcher.core.version.AssetIndexDownloadInfo; import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion; +import org.jackhuang.hellominecraft.util.MessageBox; +import org.jackhuang.hellominecraft.util.func.Function; import org.jackhuang.hellominecraft.util.logging.HMCLog; import org.jackhuang.hellominecraft.util.tasks.Task; import org.jackhuang.hellominecraft.util.tasks.TaskWindow; @@ -116,4 +120,78 @@ public class MinecraftAssetService extends IMinecraftAssetService { throw new IOException("Assets file format malformed.", e); } } + + private boolean checkAssetsExistance(AssetIndexDownloadInfo assetIndex) { + File assetsDir = getAssets(); + File indexDir = new File(assetsDir, "indexes"); + File objectDir = new File(assetsDir, "objects"); + File indexFile = new File(indexDir, assetIndex.getId() + ".json"); + + if (!assetsDir.exists() && !indexFile.isFile()) + return false; + + try { + AssetsIndex index = (AssetsIndex) C.GSON.fromJson(FileUtils.readFileToString(indexFile, "UTF-8"), AssetsIndex.class); + + if (index == null) + return false; + for (Map.Entry entry : index.getFileMap().entrySet()) + if (!new File(new File(objectDir, ((AssetsObject) entry.getValue()).getHash().substring(0, 2)), ((AssetsObject) entry.getValue()).getHash()).exists()) + return false; + return true; + } catch (IOException | JsonSyntaxException e) { + return false; + } + } + + private File reconstructAssets(AssetIndexDownloadInfo assetIndex) { + File assetsDir = getAssets(); + File indexDir = new File(assetsDir, "indexes"); + File objectDir = new File(assetsDir, "objects"); + String assetVersion = assetIndex.getId(); + File indexFile = new File(indexDir, assetVersion + ".json"); + File virtualRoot = new File(new File(assetsDir, "virtual"), assetVersion); + + if (!indexFile.isFile()) { + HMCLog.warn("No assets index file " + virtualRoot + "; can't reconstruct assets"); + return assetsDir; + } + + try { + AssetsIndex index = (AssetsIndex) C.GSON.fromJson(FileUtils.readFileToString(indexFile, "UTF-8"), AssetsIndex.class); + + if (index == null) + return assetsDir; + if (index.isVirtual()) { + int cnt = 0; + HMCLog.log("Reconstructing virtual assets folder at " + virtualRoot); + int tot = index.getFileMap().entrySet().size(); + for (Map.Entry entry : index.getFileMap().entrySet()) { + File target = new File(virtualRoot, (String) entry.getKey()); + File original = new File(new File(objectDir, ((AssetsObject) entry.getValue()).getHash().substring(0, 2)), ((AssetsObject) entry.getValue()).getHash()); + if (original.exists()) { + cnt++; + if (!target.isFile()) + FileUtils.copyFile(original, target, false); + } + } + // If the scale new format existent file is lower then 0.1, use the old format. + if (cnt * 10 < tot) + return assetsDir; + } + } catch (IOException | JsonSyntaxException e) { + HMCLog.warn("Failed to create virutal assets.", e); + } + + return virtualRoot; + } + + public final Function ASSET_PROVIDER_IMPL = t -> { + if (!checkAssetsExistance(t.getAssetsIndex())) + if (MessageBox.Show(C.i18n("assets.no_assets"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) { + IAssetsHandler.ASSETS_HANDLER.getList(t, MinecraftAssetService.this).run(); + TaskWindow.factory().append(IAssetsHandler.ASSETS_HANDLER.getDownloadTask(service.getDownloadType().getProvider())).create(); + } + return reconstructAssets(t.getAssetsIndex()).getAbsolutePath(); + }; } diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/auth/IAuthenticator.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/auth/IAuthenticator.java index 677082ca7..f9ad57bc3 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/auth/IAuthenticator.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/auth/IAuthenticator.java @@ -36,7 +36,7 @@ public abstract class IAuthenticator { PluginManager.plugin().onRegisterAuthenticators(LOGINS::add); } - protected String clientToken, username; + protected String clientToken, username, password; public IAuthenticator(String clientToken) { this.clientToken = clientToken; @@ -106,4 +106,12 @@ public abstract class IAuthenticator { public void setUserName(String s) { username = s; } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } } diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/launch/AbstractMinecraftLoader.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/launch/AbstractMinecraftLoader.java index 867f0dad2..0083dbbef 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/launch/AbstractMinecraftLoader.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/launch/AbstractMinecraftLoader.java @@ -17,18 +17,12 @@ */ package org.jackhuang.hellominecraft.launcher.core.launch; -import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService; -import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftLoader; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.jackhuang.hellominecraft.util.C; import org.jackhuang.hellominecraft.util.logging.HMCLog; -import org.jackhuang.hellominecraft.launcher.Launcher; -import org.jackhuang.hellominecraft.launcher.core.GameException; -import org.jackhuang.hellominecraft.launcher.core.auth.UserProfileProvider; -import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion; import org.jackhuang.hellominecraft.util.system.JdkVersion; import org.jackhuang.hellominecraft.util.MathUtils; import org.jackhuang.hellominecraft.util.MessageBox; @@ -36,6 +30,12 @@ import org.jackhuang.hellominecraft.util.system.OS; import org.jackhuang.hellominecraft.util.system.Platform; import org.jackhuang.hellominecraft.util.StrUtils; import org.jackhuang.hellominecraft.util.Utils; +import org.jackhuang.hellominecraft.launcher.Launcher; +import org.jackhuang.hellominecraft.launcher.core.GameException; +import org.jackhuang.hellominecraft.launcher.core.auth.UserProfileProvider; +import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion; +import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService; +import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftLoader; /** * diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/launch/DefaultGameLauncher.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/launch/DefaultGameLauncher.java index 2b3eacd60..f301a3af4 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/launch/DefaultGameLauncher.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/launch/DefaultGameLauncher.java @@ -57,7 +57,7 @@ public class DefaultGameLauncher extends GameLauncher { try { Compressor.unzip(value.decompressFiles[i], value.getDecompressTo(), value.extractRules[i]::allow, false); } catch (IOException ex) { - HMCLog.err("Unable to decompress library file: " + value.decompressFiles[i] + " to " + value.getDecompressTo(), ex); + HMCLog.err("Unable to decompress library: " + value.decompressFiles[i] + " to " + value.getDecompressTo(), ex); } return true; }); diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/launch/MinecraftLoader.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/launch/MinecraftLoader.java index 8cc41a6fb..4d4ac1203 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/launch/MinecraftLoader.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/core/launch/MinecraftLoader.java @@ -17,26 +17,19 @@ */ package org.jackhuang.hellominecraft.launcher.core.launch; -import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService; -import com.google.gson.JsonSyntaxException; import java.io.File; import java.io.IOException; import java.util.List; -import java.util.Map; -import org.jackhuang.hellominecraft.util.C; +import org.jackhuang.hellominecraft.util.StrUtils; +import org.jackhuang.hellominecraft.util.func.Function; import org.jackhuang.hellominecraft.util.logging.HMCLog; +import org.jackhuang.hellominecraft.util.system.IOUtils; +import org.jackhuang.hellominecraft.util.system.OS; import org.jackhuang.hellominecraft.launcher.core.GameException; import org.jackhuang.hellominecraft.launcher.core.auth.UserProfileProvider; -import org.jackhuang.hellominecraft.util.system.IOUtils; -import org.jackhuang.hellominecraft.launcher.core.asset.AssetsIndex; -import org.jackhuang.hellominecraft.launcher.core.asset.AssetsObject; -import org.jackhuang.hellominecraft.launcher.core.asset.IAssetsHandler; -import org.jackhuang.hellominecraft.util.system.OS; import org.jackhuang.hellominecraft.launcher.core.version.MinecraftLibrary; -import org.jackhuang.hellominecraft.util.tasks.TaskWindow; -import org.jackhuang.hellominecraft.util.system.FileUtils; -import org.jackhuang.hellominecraft.util.MessageBox; -import org.jackhuang.hellominecraft.util.StrUtils; +import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion; +import org.jackhuang.hellominecraft.launcher.core.service.IMinecraftService; /** * @@ -68,13 +61,7 @@ public class MinecraftLoader extends AbstractMinecraftLoader { String[] splitted = StrUtils.tokenize(version.minecraftArguments); - if (!checkAssetsExist()) - if (MessageBox.Show(C.i18n("assets.no_assets"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) { - IAssetsHandler.ASSETS_HANDLER.getList(version, service.asset()).run(); - TaskWindow.factory().append(IAssetsHandler.ASSETS_HANDLER.getDownloadTask(service.getDownloadType().getProvider())).create(); - } - - String game_assets = reconstructAssets().getAbsolutePath(); + String game_assets = assetProvider.apply(version); for (String t : splitted) { t = t.replace("${auth_player_name}", lr.getUserName()); @@ -113,68 +100,16 @@ public class MinecraftLoader extends AbstractMinecraftLoader { } } - private boolean checkAssetsExist() { - File assetsDir = new File(service.baseDirectory(), "assets"); - File indexDir = new File(assetsDir, "indexes"); - File objectDir = new File(assetsDir, "objects"); - File indexFile = new File(indexDir, version.getAssetsIndex().getId() + ".json"); + private final Function DEFAULT_ASSET_PROVIDER = t -> { + return new File(service.baseDirectory(), "assets").getAbsolutePath(); + }; - if (!assetsDir.exists() && !indexFile.isFile()) - return false; + private Function assetProvider = DEFAULT_ASSET_PROVIDER; - try { - AssetsIndex index = (AssetsIndex) C.GSON.fromJson(FileUtils.readFileToString(indexFile, "UTF-8"), AssetsIndex.class); - - if (index == null) - return false; - for (Map.Entry entry : index.getFileMap().entrySet()) - if (!new File(new File(objectDir, ((AssetsObject) entry.getValue()).getHash().substring(0, 2)), ((AssetsObject) entry.getValue()).getHash()).exists()) - return false; - return true; - } catch (IOException | JsonSyntaxException e) { - return false; - } - } - - private File reconstructAssets() { - File assetsDir = new File(service.baseDirectory(), "assets"); - File indexDir = new File(assetsDir, "indexes"); - File objectDir = new File(assetsDir, "objects"); - String assetVersion = version.getAssetsIndex().getId(); - File indexFile = new File(indexDir, assetVersion + ".json"); - File virtualRoot = new File(new File(assetsDir, "virtual"), assetVersion); - - if (!indexFile.isFile()) { - HMCLog.warn("No assets index file " + virtualRoot + "; can't reconstruct assets"); - return assetsDir; - } - - try { - AssetsIndex index = (AssetsIndex) C.GSON.fromJson(FileUtils.readFileToString(indexFile, "UTF-8"), AssetsIndex.class); - - if (index == null) - return assetsDir; - if (index.isVirtual()) { - int cnt = 0; - HMCLog.log("Reconstructing virtual assets folder at " + virtualRoot); - int tot = index.getFileMap().entrySet().size(); - for (Map.Entry entry : index.getFileMap().entrySet()) { - File target = new File(virtualRoot, (String) entry.getKey()); - File original = new File(new File(objectDir, ((AssetsObject) entry.getValue()).getHash().substring(0, 2)), ((AssetsObject) entry.getValue()).getHash()); - if (original.exists()) { - cnt++; - if (!target.isFile()) - FileUtils.copyFile(original, target, false); - } - } - // If the scale new format existent file is lower then 0.1, use the old format. - if (cnt * 10 < tot) - return assetsDir; - } - } catch (IOException | JsonSyntaxException e) { - HMCLog.warn("Failed to create virutal assets.", e); - } - - return virtualRoot; + public void setAssetProvider(Function assetProvider) { + if (assetProvider == null) + this.assetProvider = DEFAULT_ASSET_PROVIDER; + else + this.assetProvider = assetProvider; } } diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/DefaultMinecraftService.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/DefaultMinecraftService.java index 454ff890e..edb671b65 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/DefaultMinecraftService.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/setting/DefaultMinecraftService.java @@ -147,7 +147,9 @@ public class DefaultMinecraftService extends IMinecraftService { @Override public IMinecraftLoader launch(LaunchOptions options, UserProfileProvider p) throws GameException { - return new MinecraftLoader(options, this, p); + MinecraftLoader l = new MinecraftLoader(options, this, p); + l.setAssetProvider(mas.ASSET_PROVIDER_IMPL); + return l; } public Profile getProfile() { diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/GameSettingsPanel.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/GameSettingsPanel.java index c3b0236c6..1a316843b 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/GameSettingsPanel.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/GameSettingsPanel.java @@ -84,6 +84,11 @@ public final class GameSettingsPanel extends AnimatedPanel implements DropTarget setBackground(Color.white); setOpaque(true); + MainFrame.INSTANCE.actions.put("showGameDownloads", () -> { + MainFrame.INSTANCE.selectTab("game"); + showGameDownloads(); + }); + for (int i = 0; i < InstallerType.values().length; i++) installerPanels[i] = new InstallerPanel(this, InstallerType.values()[i]); pnlGameDownloads = new GameDownloadPanel(this); @@ -1122,7 +1127,7 @@ public final class GameSettingsPanel extends AnimatedPanel implements DropTarget private void btnTestGameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnTestGameActionPerformed LogWindow.INSTANCE.setVisible(true); - MainFrame.INSTANCE.mainPanel.runGame(); + MainFrame.INSTANCE.daemon.runGame(getProfile()); }//GEN-LAST:event_btnTestGameActionPerformed private void btnShowLogActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnShowLogActionPerformed @@ -1130,7 +1135,7 @@ public final class GameSettingsPanel extends AnimatedPanel implements DropTarget }//GEN-LAST:event_btnShowLogActionPerformed private void btnMakeLaunchScriptActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnMakeLaunchScriptActionPerformed - MainFrame.INSTANCE.mainPanel.makeLaunchScript(); + MainFrame.INSTANCE.daemon.makeLaunchScript(getProfile()); }//GEN-LAST:event_btnMakeLaunchScriptActionPerformed private void btnIncludeMinecraftActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnIncludeMinecraftActionPerformed diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/LaunchingUIDaemon.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/LaunchingUIDaemon.java new file mode 100644 index 000000000..f57595785 --- /dev/null +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/LaunchingUIDaemon.java @@ -0,0 +1,111 @@ +/* + * Hello Minecraft! Launcher. + * Copyright (C) 2013 huangyuhui + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see {http://www.gnu.org/licenses/}. + */ +package org.jackhuang.hellominecraft.launcher.ui; + +import java.io.IOException; +import java.util.List; +import javax.swing.JOptionPane; +import org.jackhuang.hellominecraft.launcher.core.LauncherVisibility; +import org.jackhuang.hellominecraft.launcher.core.launch.GameLauncher; +import org.jackhuang.hellominecraft.launcher.setting.Profile; +import org.jackhuang.hellominecraft.launcher.setting.Settings; +import org.jackhuang.hellominecraft.util.C; +import org.jackhuang.hellominecraft.util.Event; +import org.jackhuang.hellominecraft.util.MessageBox; +import org.jackhuang.hellominecraft.util.logging.HMCLog; +import org.jackhuang.hellominecraft.util.system.JavaProcessMonitor; +import org.jackhuang.hellominecraft.util.ui.LogWindow; + +/** + * + * @author huangyuhui + */ +public class LaunchingUIDaemon { + + Runnable customizedSuccessEvent = null; + + void runGame(Profile profile) { + MainFrame.INSTANCE.showMessage(C.i18n("ui.message.launching")); + profile.launcher().genLaunchCode(value -> { + value.successEvent.register(LAUNCH_FINISHER); + value.successEvent.register(customizedSuccessEvent); + }, MainFrame.INSTANCE::failed, Settings.getInstance().getAuthenticator().getPassword()); + } + + void makeLaunchScript(Profile profile) { + MainFrame.INSTANCE.showMessage(C.i18n("ui.message.launching")); + profile.launcher().genLaunchCode(value -> { + value.successEvent.register(LAUNCH_SCRIPT_FINISHER); + value.successEvent.register(customizedSuccessEvent); + }, MainFrame.INSTANCE::failed, Settings.getInstance().getAuthenticator().getPassword()); + } + + private static final Event> LAUNCH_FINISHER = (sender, str) -> { + final GameLauncher obj = (GameLauncher) sender; + obj.launchEvent.register(p -> { + if ((LauncherVisibility) obj.getTag() == LauncherVisibility.CLOSE && !LogWindow.INSTANCE.isVisible()) { + HMCLog.log("Without the option of keeping the launcher visible, this application will exit and will NOT catch game logs, but you can turn on \"Debug Mode\"."); + System.exit(0); + } else if ((LauncherVisibility) obj.getTag() == LauncherVisibility.KEEP) + MainFrame.INSTANCE.closeMessage(); + else { + if (LogWindow.INSTANCE.isVisible()) + LogWindow.INSTANCE.setExit(() -> true); + MainFrame.INSTANCE.dispose(); + } + JavaProcessMonitor jpm = new JavaProcessMonitor(p); + jpm.applicationExitedAbnormallyEvent.register(t -> { + HMCLog.err("The game exited abnormally, exit code: " + t); + MessageBox.Show(C.i18n("launch.exited_abnormally") + ", exit code: " + t); + }); + jpm.jvmLaunchFailedEvent.register(t -> { + HMCLog.err("Cannot create jvm, exit code: " + t); + MessageBox.Show(C.i18n("launch.cannot_create_jvm") + ", exit code: " + t); + }); + jpm.stoppedEvent.register(() -> { + if ((LauncherVisibility) obj.getTag() != LauncherVisibility.KEEP && !LogWindow.INSTANCE.isVisible()) { + HMCLog.log("Without the option of keeping the launcher visible, this application will exit and will NOT catch game logs, but you can turn on \"Debug Mode\"."); + System.exit(0); + } + }); + jpm.start(); + }); + try { + obj.launch(str); + } catch (IOException e) { + MainFrame.INSTANCE.failed(C.i18n("launch.failed_creating_process") + "\n" + e.getMessage()); + HMCLog.err("Failed to launch when creating a new process.", e); + } + return true; + }; + + private static final Event> LAUNCH_SCRIPT_FINISHER = (sender, str) -> { + boolean flag = false; + try { + String s = JOptionPane.showInputDialog(C.i18n("mainwindow.enter_script_name")); + if (s != null) + MessageBox.Show(C.i18n("mainwindow.make_launch_succeed") + " " + ((GameLauncher) sender).makeLauncher(s, str).getAbsolutePath()); + flag = true; + } catch (IOException ex) { + MessageBox.Show(C.i18n("mainwindow.make_launch_script_failed")); + HMCLog.err("Failed to create script file.", ex); + } + MainFrame.INSTANCE.closeMessage(); + return flag; + }; +} diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainFrame.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainFrame.java index 5ef38a79a..3e02b3ce1 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainFrame.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainFrame.java @@ -32,6 +32,9 @@ import java.awt.event.MouseListener; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.awt.image.BufferedImage; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; @@ -47,6 +50,7 @@ import org.jackhuang.hellominecraft.launcher.setting.Settings; import org.jackhuang.hellominecraft.launcher.core.auth.IAuthenticator; import org.jackhuang.hellominecraft.lookandfeel.GraphicsUtils; import org.jackhuang.hellominecraft.lookandfeel.Theme; +import org.jackhuang.hellominecraft.util.MessageBox; import org.jackhuang.hellominecraft.util.StrUtils; import org.jackhuang.hellominecraft.util.Utils; import org.jackhuang.hellominecraft.util.ui.DropShadowBorder; @@ -61,17 +65,10 @@ public final class MainFrame extends DraggableFrame { public static final MainFrame INSTANCE = new MainFrame(); - HeaderTab mainTab, gameTab, launcherTab; TintablePanel centralPanel; - JPanel header; - MainPagePanel mainPanel; - GameSettingsPanel gamePanel; - LauncherSettingsPanel launcherPanel; + JPanel header, infoSwap, realPanel; CardLayout infoLayout; - JPanel infoSwap; - JPanel mainPanelWrapper, launcherPanelWrapper, gamePanelWrapper; JLabel backgroundLabel, windowTitle; - JPanel realPanel; DropShadowBorder border; boolean enableShadow; String defaultTitle; @@ -95,7 +92,6 @@ public final class MainFrame extends DraggableFrame { setDefaultCloseOperation(3); setTitle(Main.makeTitle()); initComponents(); - selectTab("main"); loadBackground(); setLocationRelativeTo(null); @@ -150,6 +146,8 @@ public final class MainFrame extends DraggableFrame { ((JPanel) getContentPane()).setOpaque(true); Settings.getInstance().themeChangedEvent.register(this::reloadColor); + + SwingUtilities.invokeLater(() -> selectTab("main")); } private void initComponents() { @@ -176,31 +174,9 @@ public final class MainFrame extends DraggableFrame { header.add(Box.createRigidArea(new Dimension(8, 0))); - ActionListener tabListener = e -> MainFrame.this.selectTab(e.getActionCommand()); - - this.mainTab = new HeaderTab(C.i18n("launcher.title.main")); - this.mainTab.setForeground(BasicColors.COLOR_WHITE_TEXT); - this.mainTab.setBackground(borderColorDarker); - this.mainTab.setActionCommand("main"); - this.mainTab.addActionListener(tabListener); - header.add(this.mainTab); - - this.gameTab = new HeaderTab(C.i18n("launcher.title.game")); - this.gameTab.setForeground(BasicColors.COLOR_WHITE_TEXT); - this.gameTab.setBackground(borderColorDarker); - this.gameTab.setIsActive(true); - this.gameTab.setHorizontalTextPosition(10); - this.gameTab.addActionListener(tabListener); - this.gameTab.setActionCommand("game"); - header.add(this.gameTab); - - this.launcherTab = new HeaderTab(C.i18n("launcher.title.launcher")); - this.launcherTab.setForeground(BasicColors.COLOR_WHITE_TEXT); - this.launcherTab.setBackground(borderColorDarker); - this.launcherTab.setLayout(null); - this.launcherTab.addActionListener(tabListener); - this.launcherTab.setActionCommand("launcher"); - header.add(this.launcherTab); + initializeTab(MainPagePanel.class, "main"); + initializeTab(GameSettingsPanel.class, "game"); + initializeTab(LauncherSettingsPanel.class, "launcher"); header.add(Box.createHorizontalGlue()); @@ -253,15 +229,13 @@ public final class MainFrame extends DraggableFrame { this.infoSwap.setLayout(infoLayout); this.infoSwap.setOpaque(false); - mainPanelWrapper = new JPanel(); - mainPanelWrapper.setLayout(new GridLayout()); - this.infoSwap.add(mainPanelWrapper, "main"); - gamePanelWrapper = new JPanel(); - gamePanelWrapper.setLayout(new GridLayout()); - this.infoSwap.add(gamePanelWrapper, "game"); - launcherPanelWrapper = new JPanel(); - launcherPanelWrapper.setLayout(new GridLayout()); - this.infoSwap.add(launcherPanelWrapper, "launcher"); + tabWrapper = new JPanel[tabHeader.size()]; + tabContent = new AnimatedPanel[tabHeader.size()]; + for (int i = 0; i < tabHeader.size(); i++) { + tabWrapper[i] = new JPanel(); + tabWrapper[i].setLayout(new GridLayout()); + infoSwap.add(tabWrapper[i], tabHeader.get(i).getActionCommand()); + } truePanel.add(this.infoSwap, "Center"); centralPanel.setLayout(null); @@ -274,40 +248,48 @@ public final class MainFrame extends DraggableFrame { add(realPanel); } - public void selectTab(String tabName) { - boolean a = mainTab.isActive(), b = gameTab.isActive(), c = launcherTab.isActive(); - this.mainTab.setIsActive(false); - this.gameTab.setIsActive(false); - this.launcherTab.setIsActive(false); + private final ActionListener tabListener = e -> MainFrame.this.selectTab(e.getActionCommand()); - if (tabName.equalsIgnoreCase("main")) { - if (mainPanel == null) { - mainPanel = new MainPagePanel(); - mainPanelWrapper.add(mainPanel); - } - this.mainTab.setIsActive(true); - this.mainPanel.onSelected(); - if (!a) - mainPanel.animate(); - } else if (tabName.equalsIgnoreCase("game")) { - if (gamePanel == null) { - gamePanel = new GameSettingsPanel(); - gamePanelWrapper.add(gamePanel); - } - this.gameTab.setIsActive(true); - this.gamePanel.onSelected(); - if (!b) - gamePanel.animate(); - } else if (tabName.equalsIgnoreCase("launcher")) { - if (launcherPanel == null) { - launcherPanel = new LauncherSettingsPanel(); - launcherPanelWrapper.add(launcherPanel); - } - this.launcherTab.setIsActive(true); - if (!c) - launcherPanel.animate(); + private void initializeTab(Class c, String cmd) { + HeaderTab tab = new HeaderTab(C.i18n("launcher.title." + cmd)); + tab.setActionCommand(cmd); + tab.setForeground(BasicColors.COLOR_WHITE_TEXT); + tab.setBackground(borderColorDarker); + tab.setLayout(null); + tab.addActionListener(tabListener); + header.add(tab); + tabHeader.add(tab); + tabClasses.add(c); + } + + private List tabHeader = new ArrayList<>(); + private List> tabClasses = new ArrayList<>(); + private JPanel tabWrapper[]; + private AnimatedPanel tabContent[]; + + public void selectTab(String tabName) { + boolean[] activation = new boolean[tabHeader.size()]; + for (int i = 0; i < tabHeader.size(); i++) { + activation[i] = tabHeader.get(i).isActive(); + tabHeader.get(i).setIsActive(false); } + for (int i = 0; i < tabHeader.size(); i++) + if (tabName.equalsIgnoreCase(tabHeader.get(i).getActionCommand())) { + if (tabContent[i] == null) { + try { + tabContent[i] = tabClasses.get(i).newInstance(); + } catch (Exception mustnothappen) { + throw new InternalError(mustnothappen); + } + tabWrapper[i].add(tabContent[i]); + } + tabHeader.get(i).setIsActive(true); + tabContent[i].onSelected(); + if (!activation[i]) + tabContent[i].animate(); + } + this.infoLayout.show(this.infoSwap, tabName); } @@ -322,7 +304,7 @@ public final class MainFrame extends DraggableFrame { ImageIcon background; public void loadBackground() { - background = Utils.searchBackgroundImage(Main.getIcon("background.jpg"), Settings.getInstance().getBgpath(), 800, 480); + background = Utils.searchBackgroundImage(Main.getIcon(Settings.getInstance().getTheme().settings.get("Customized.MainFrame.background_image")), Settings.getInstance().getBgpath(), 800, 480); if (background != null) if (backgroundLabel == null) { backgroundLabel = new JLabel(background); @@ -331,7 +313,7 @@ public final class MainFrame extends DraggableFrame { } else backgroundLabel.setIcon(background); else - HMCLog.warn("No Background Image, the background will be empty!"); + HMCLog.warn("No background image here! The background will be empty!"); } public JPanel getTitleBar() { @@ -354,9 +336,8 @@ public final class MainFrame extends DraggableFrame { borderColor = BasicColors.COLOR_RED; borderColorDarker = BasicColors.COLOR_RED_DARKER; header.setBackground(borderColor); - mainTab.setBackground(borderColorDarker); - gameTab.setBackground(borderColorDarker); - launcherTab.setBackground(borderColorDarker); + for (HeaderTab tab : tabHeader) + tab.setBackground(borderColorDarker); if (border != null) border.setColor(borderColor); repaint(); @@ -386,9 +367,8 @@ public final class MainFrame extends DraggableFrame { if (border != null) border.setColor(borderColor); header.setBackground(borderColor); - mainTab.setBackground(borderColorDarker); - gameTab.setBackground(borderColorDarker); - launcherTab.setBackground(borderColorDarker); + for (HeaderTab tab : tabHeader) + tab.setBackground(borderColorDarker); repaint(); } @@ -458,4 +438,18 @@ public final class MainFrame extends DraggableFrame { } } + public void failed(String s) { + if (s != null) + MessageBox.Show(s); + closeMessage(); + } + + LaunchingUIDaemon daemon = new LaunchingUIDaemon(); + + HashMap actions = new HashMap<>(); + + void invokeAction(String name) { + if (actions.containsKey(name)) + actions.get(name).run(); + } } diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainPagePanel.form b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainPagePanel.form index ddea6032e..5cb5ec6f5 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainPagePanel.form +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainPagePanel.form @@ -213,6 +213,7 @@ + diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainPagePanel.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainPagePanel.java index dae7c7eb3..dd76a2b7a 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainPagePanel.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/MainPagePanel.java @@ -22,21 +22,16 @@ import java.awt.Dimension; import java.awt.Font; import java.awt.event.ItemEvent; import java.awt.event.KeyEvent; -import java.io.IOException; -import java.util.List; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import javax.swing.filechooser.FileNameExtensionFilter; import org.jackhuang.hellominecraft.util.C; -import org.jackhuang.hellominecraft.util.logging.HMCLog; import org.jackhuang.hellominecraft.launcher.core.auth.IAuthenticator; import org.jackhuang.hellominecraft.launcher.setting.Profile; import org.jackhuang.hellominecraft.util.MessageBox; import org.jackhuang.hellominecraft.util.StrUtils; import org.jackhuang.hellominecraft.launcher.core.version.MinecraftVersion; -import org.jackhuang.hellominecraft.launcher.core.launch.GameLauncher; -import org.jackhuang.hellominecraft.launcher.core.LauncherVisibility; import org.jackhuang.hellominecraft.launcher.setting.Settings; import org.jackhuang.hellominecraft.launcher.core.mod.ModpackManager; import org.jackhuang.hellominecraft.launcher.ui.modpack.ModpackWizard; @@ -44,9 +39,7 @@ import org.jackhuang.hellominecraft.lookandfeel.GraphicsUtils; import org.jackhuang.hellominecraft.util.Event; import org.jackhuang.hellominecraft.lookandfeel.comp.ConstomButton; import org.jackhuang.hellominecraft.util.system.FileUtils; -import org.jackhuang.hellominecraft.util.system.JavaProcessMonitor; import org.jackhuang.hellominecraft.util.tasks.TaskWindow; -import org.jackhuang.hellominecraft.util.ui.LogWindow; import org.jackhuang.hellominecraft.util.ui.wizard.api.WizardDisplayer; /** @@ -73,7 +66,7 @@ public class MainPagePanel extends AnimatedPanel { btnRun.setText(C.i18n("ui.button.run")); btnRun.setFont(newFont); - btnRun.addActionListener(e -> runGame()); + btnRun.addActionListener(e -> MainFrame.INSTANCE.daemon.runGame(getProfile())); this.add(pnlButtons); pnlButtons.setBounds(0, 0, w, h); @@ -86,6 +79,8 @@ public class MainPagePanel extends AnimatedPanel { Settings.getInstance().authChangedEvent.register(onAuthChanged); + MainFrame.INSTANCE.daemon.customizedSuccessEvent = this::prepareAuths; + prepareAuths(); } @@ -166,6 +161,11 @@ public class MainPagePanel extends AnimatedPanel { jLabel9.setText(C.i18n("ui.label.password")); // NOI18N + txtPassword.addCaretListener(new javax.swing.event.CaretListener() { + public void caretUpdate(javax.swing.event.CaretEvent evt) { + txtPasswordCaretUpdate(evt); + } + }); txtPassword.addFocusListener(new java.awt.event.FocusAdapter() { public void focusGained(java.awt.event.FocusEvent evt) { txtPasswordFocusGained(evt); @@ -332,7 +332,7 @@ public class MainPagePanel extends AnimatedPanel { }//GEN-LAST:event_txtPasswordFocusGained private void txtPasswordActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtPasswordActionPerformed - runGame(); + MainFrame.INSTANCE.daemon.runGame(getProfile()); }//GEN-LAST:event_txtPasswordActionPerformed private void btnLogoutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnLogoutActionPerformed @@ -352,7 +352,7 @@ public class MainPagePanel extends AnimatedPanel { IAuthenticator l = Settings.getInstance().getAuthenticator(); l.setUserName(txtPlayerName.getText()); if (!l.hasPassword()) - runGame(); + MainFrame.INSTANCE.daemon.runGame(getProfile()); else if (!l.isLoggedIn()) txtPassword.requestFocus(); } @@ -360,7 +360,7 @@ public class MainPagePanel extends AnimatedPanel { private void txtPasswordKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtPasswordKeyPressed if (evt.getKeyCode() == KeyEvent.VK_ENTER) - runGame(); + MainFrame.INSTANCE.daemon.runGame(getProfile()); }//GEN-LAST:event_txtPasswordKeyPressed private void btnImportModpackActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnImportModpackActionPerformed @@ -383,6 +383,10 @@ public class MainPagePanel extends AnimatedPanel { WizardDisplayer.showWizard(new ModpackWizard(getProfile().service()).createWizard()); }//GEN-LAST:event_btnExportModpackActionPerformed + private void txtPasswordCaretUpdate(javax.swing.event.CaretEvent evt) {//GEN-FIRST:event_txtPasswordCaretUpdate + Settings.getInstance().getAuthenticator().setPassword(txtPassword.getText()); + }//GEN-LAST:event_txtPasswordCaretUpdate + // private void prepareAuths() { preparingAuth = true; @@ -414,10 +418,8 @@ public class MainPagePanel extends AnimatedPanel { if (getProfile().service().version().getVersions().isEmpty()) { if (!showedNoVersion) SwingUtilities.invokeLater(() -> { - if (MessageBox.Show(C.i18n("mainwindow.no_version"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) { - MainFrame.INSTANCE.selectTab("game"); - MainFrame.INSTANCE.gamePanel.showGameDownloads(); - } + if (MessageBox.Show(C.i18n("mainwindow.no_version"), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) + MainFrame.INSTANCE.invokeAction("showGameDownloads"); showedNoVersion = true; }); } else { @@ -459,82 +461,6 @@ public class MainPagePanel extends AnimatedPanel { private static final int DEFAULT_WIDTH = 800, DEFAULT_HEIGHT = 480; // - void runGame() { - MainFrame.INSTANCE.showMessage(C.i18n("ui.message.launching")); - getProfile().launcher().genLaunchCode(value -> { - value.successEvent.register(launchFinisher); - value.successEvent.register(this::prepareAuths); - }, this::failed, txtPassword.getText()); - } - - void makeLaunchScript() { - MainFrame.INSTANCE.showMessage(C.i18n("ui.message.launching")); - getProfile().launcher().genLaunchCode(value -> { - value.successEvent.register(launchScriptFinisher); - value.successEvent.register(this::prepareAuths); - }, this::failed, txtPassword.getText()); - } - - private void failed(String s) { - if (s != null) - MessageBox.Show(s); - MainFrame.INSTANCE.closeMessage(); - } - - final Event> launchFinisher = (sender, str) -> { - final GameLauncher obj = (GameLauncher) sender; - obj.launchEvent.register(p -> { - if ((LauncherVisibility) obj.getTag() == LauncherVisibility.CLOSE && !LogWindow.INSTANCE.isVisible()) { - HMCLog.log("Without the option of keeping the launcher visible, this application will exit and will NOT catch game logs, but you can turn on \"Debug Mode\"."); - System.exit(0); - } else if ((LauncherVisibility) obj.getTag() == LauncherVisibility.KEEP) - MainFrame.INSTANCE.closeMessage(); - else { - if (LogWindow.INSTANCE.isVisible()) - LogWindow.INSTANCE.setExit(() -> true); - MainFrame.INSTANCE.dispose(); - } - JavaProcessMonitor jpm = new JavaProcessMonitor(p); - jpm.applicationExitedAbnormallyEvent.register(t -> { - HMCLog.err("The game exited abnormally, exit code: " + t); - MessageBox.Show(C.i18n("launch.exited_abnormally") + ", exit code: " + t); - }); - jpm.jvmLaunchFailedEvent.register(t -> { - HMCLog.err("Cannot create jvm, exit code: " + t); - MessageBox.Show(C.i18n("launch.cannot_create_jvm") + ", exit code: " + t); - }); - jpm.stoppedEvent.register(() -> { - if ((LauncherVisibility) obj.getTag() != LauncherVisibility.KEEP && !LogWindow.INSTANCE.isVisible()) { - HMCLog.log("Without the option of keeping the launcher visible, this application will exit and will NOT catch game logs, but you can turn on \"Debug Mode\"."); - System.exit(0); - } - }); - jpm.start(); - }); - try { - obj.launch(str); - } catch (IOException e) { - failed(C.i18n("launch.failed_creating_process") + "\n" + e.getMessage()); - HMCLog.err("Failed to launch when creating a new process.", e); - } - return true; - }; - - final Event> launchScriptFinisher = (sender, str) -> { - boolean flag = false; - try { - String s = JOptionPane.showInputDialog(C.i18n("mainwindow.enter_script_name")); - if (s != null) - MessageBox.Show(C.i18n("mainwindow.make_launch_succeed") + " " + ((GameLauncher) sender).makeLauncher(s, str).getAbsolutePath()); - flag = true; - } catch (IOException ex) { - MessageBox.Show(C.i18n("mainwindow.make_launch_script_failed")); - HMCLog.err("Failed to create script file.", ex); - } - MainFrame.INSTANCE.closeMessage(); - return flag; - }; - public Profile getProfile() { return Settings.getProfile((String) cboProfiles.getSelectedItem()); } diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/modpack/ModpackWizard.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/modpack/ModpackWizard.java index 59781e2ee..df1c4695a 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/modpack/ModpackWizard.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/ui/modpack/ModpackWizard.java @@ -48,6 +48,8 @@ import org.jackhuang.hellominecraft.util.ui.wizard.spi.WizardPanelProvider; public class ModpackWizard extends WizardBranchController { static void process(CheckBoxTreeNode node, String basePath, List list) { + if (node == null) + return; if (node.isSelected()) { if (basePath.length() > "minecraft/".length()) list.add(basePath.substring("minecraft/".length())); diff --git a/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/Theme.java b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/Theme.java index 6d712b6f5..d89898f9b 100755 --- a/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/Theme.java +++ b/MetroLookAndFeel/src/main/java/org/jackhuang/hellominecraft/lookandfeel/Theme.java @@ -32,6 +32,7 @@ public enum Theme { put("Customized.ComboBox.selected_background", "#A0D8F0"); put("Customized.MainFrame.background", "#106CA3"); put("Customized.MainFrame.selected_background", "#0C5E91"); + put("Customized.MainFrame.background_image", "background.jpg"); } }), GREEN(C.i18n("color.green"), new HashMap() { @@ -40,6 +41,7 @@ public enum Theme { put("Customized.ComboBox.selected_background", "#1ABC9C"); put("Customized.MainFrame.background", "#1ABC9C"); put("Customized.MainFrame.selected_background", "#16A085"); + put("Customized.MainFrame.background_image", "background.jpg"); } }), PURPLE(C.i18n("color.purple"), new HashMap() { @@ -48,6 +50,7 @@ public enum Theme { put("Customized.ComboBox.selected_background", "#9B59B6"); put("Customized.MainFrame.background", "#9B59B6"); put("Customized.MainFrame.selected_background", "#8E44AD"); + put("Customized.MainFrame.background_image", "background.jpg"); } }), DARKER_BLUE(C.i18n("color.dark_blue"), new HashMap() { @@ -56,6 +59,7 @@ public enum Theme { put("Customized.ComboBox.selected_background", "#34495E"); put("Customized.MainFrame.background", "#34495E"); put("Customized.MainFrame.selected_background", "#2C3E50"); + put("Customized.MainFrame.background_image", "background.jpg"); } }), ORANGE(C.i18n("color.orange"), new HashMap() { @@ -64,6 +68,7 @@ public enum Theme { put("Customized.ComboBox.selected_background", "#F39C12"); put("Customized.MainFrame.background", "#E67E22"); put("Customized.MainFrame.selected_background", "#D35400"); + put("Customized.MainFrame.background_image", "background.jpg"); } }), RED(C.i18n("color.red"), new HashMap() { @@ -72,6 +77,7 @@ public enum Theme { put("Customized.ComboBox.selected_background", "#E74C3C"); put("Customized.MainFrame.background", "#E74C3C"); put("Customized.MainFrame.selected_background", "#C0392B"); + put("Customized.MainFrame.background_image", "background.jpg"); } });