diff --git a/.travis.yml b/.travis.yml index 4b6cbcf3b..af71cd894 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,7 @@ install: echo "skip 'gradle assemble' step" script: gradle build --continue before_cache: - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock -cache: - directories: - - "$HOME/.gradle/caches/" - - "$HOME/.gradle/wrapper/" +#cache: +# directories: +# - "$HOME/.gradle/caches/" +# - "$HOME/.gradle/wrapper/" diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/MojangDownloadProvider.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/MojangDownloadProvider.java index 6882922dd..815bbe4c9 100755 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/MojangDownloadProvider.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/download/MojangDownloadProvider.java @@ -64,7 +64,7 @@ public class MojangDownloadProvider extends IDownloadProvider { @Override public String getAssetsDownloadURL() { - return "https://resources.download.minecraft.net/"; + return "http://resources.download.minecraft.net/"; } @Override diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/mod/MinecraftModService.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/mod/MinecraftModService.java index 4235cc6d7..68812bbbb 100755 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/mod/MinecraftModService.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/mod/MinecraftModService.java @@ -94,17 +94,23 @@ public class MinecraftModService extends IMinecraftModService { } @Override - public void removeMod(String id, Object[] rows) { + public boolean removeMod(String id, Object[] rows) { if (rows.length == 0) - return; + return true; + boolean flag = true; for (Object r : rows) if (r instanceof ModInfo) { - if (!((ModInfo) r).location.delete()) + if (!((ModInfo) r).location.delete()) { HMCLog.warn("Failed to delete mod" + r); + flag = false; + } } else if (r instanceof Number) - if (!getMods(id).get(((Number) r).intValue()).location.delete()) + if (!getMods(id).get(((Number) r).intValue()).location.delete()) { HMCLog.warn("Failed to delete mod " + r + ", maybe not a file?"); + flag = false; + } recacheMods(id); + return flag; } public String[] checkMd5s(String id) throws IOException { diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/service/IMinecraftModService.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/service/IMinecraftModService.java index d11d84b78..46297f208 100755 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/service/IMinecraftModService.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/service/IMinecraftModService.java @@ -37,5 +37,5 @@ public abstract class IMinecraftModService extends IMinecraftBasicService { public abstract boolean addMod(String id, File f); - public abstract void removeMod(String id, Object[] mods); + public abstract boolean removeMod(String id, Object[] mods); } diff --git a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/version/MinecraftVersionManager.java b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/version/MinecraftVersionManager.java index 35c26cc6b..1401e903b 100755 --- a/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/version/MinecraftVersionManager.java +++ b/HMCL/src/core/java/org/jackhuang/hellominecraft/launcher/core/version/MinecraftVersionManager.java @@ -113,16 +113,16 @@ public class MinecraftVersionManager extends IMinecraftProvider { try { mcVersion = C.GSON.fromJson(FileUtils.read(jsonFile), MinecraftVersion.class); if (mcVersion == null) - throw new GameException("Wrong json format, got null."); - } catch (JsonSyntaxException | IOException | GameException e) { + throw new JsonSyntaxException("Wrong json format, got null."); + } catch (JsonSyntaxException | IOException e) { HMCLog.warn("Found wrong format json, try to fix it.", e); if (MessageBox.show(C.i18n("launcher.versions_json_not_formatted", id), MessageBox.YES_NO_OPTION) == MessageBox.YES_OPTION) { service.download().downloadMinecraftVersionJson(id); try { mcVersion = C.GSON.fromJson(FileUtils.read(jsonFile), MinecraftVersion.class); if (mcVersion == null) - throw new GameException("Wrong json format, got null."); - } catch (IOException | GameException | JsonSyntaxException ex) { + throw new JsonSyntaxException("Wrong json format, got null."); + } catch (IOException | JsonSyntaxException ex) { HMCLog.warn("Ignoring: " + dir + ", the json of this Minecraft is malformed.", ex); continue; } diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Main.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Main.java index 05868d6e3..64d063637 100644 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Main.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/Main.java @@ -129,7 +129,7 @@ public final class Main implements Runnable { try { File file = new File("hmcl.log"); if (!file.exists() && !file.createNewFile()) - HMCLog.warn("Failed to create log file " + file); + LOGGER.log(Level.WARNING, "Failed to create log file {0}", file); Configuration.DEFAULT.appenders.add(new ConsoleAppender("File", new DefaultLayout(), true, new FileOutputStream(file), true)); } catch (IOException ex) { LOGGER.log(Level.SEVERE, "Failed to add log appender File because an error occurred while creating or opening hmcl.log", ex); @@ -144,9 +144,6 @@ public final class Main implements Runnable { Locale.setDefault(sl.self); } - LogWindow.INSTANCE.clean(); - LogWindow.INSTANCE.setTerminateGame(GameLauncher.PROCESS_MANAGER::stopAllProcesses); - try { LOOK_AND_FEEL = new HelloMinecraftLookAndFeel(Settings.getInstance().getTheme().settings); UIManager.setLookAndFeel(LOOK_AND_FEEL); @@ -154,6 +151,9 @@ public final class Main implements Runnable { } catch (ParseException | UnsupportedLookAndFeelException ex) { HMCLog.warn("Failed to set look and feel...", ex); } + + LogWindow.INSTANCE.clean(); + LogWindow.INSTANCE.setTerminateGame(GameLauncher.PROCESS_MANAGER::stopAllProcesses); Settings.UPDATE_CHECKER.outOfDateEvent.register(IUpgrader.NOW_UPGRADER); Settings.UPDATE_CHECKER.process(false).reg(t -> Main.invokeUpdate()).execute(); diff --git a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/util/CrashReporter.java b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/util/CrashReporter.java index ad799fc2e..5de58ced4 100755 --- a/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/util/CrashReporter.java +++ b/HMCL/src/main/java/org/jackhuang/hellominecraft/launcher/util/CrashReporter.java @@ -132,7 +132,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler { private static final HashSet THROWABLE_SET = new HashSet<>(); void reportToServer(final String text, String stacktrace) { - if (THROWABLE_SET.contains(stacktrace) || stacktrace.contains("Font")) + if (THROWABLE_SET.contains(stacktrace) || stacktrace.contains("Font") || stacktrace.contains("InternalError")) return; THROWABLE_SET.add(stacktrace); Thread t = new Thread(() -> { diff --git a/HMCLaF/src/main/java/org/jackhuang/hellominecraft/lookandfeel/Theme.java b/HMCLaF/src/main/java/org/jackhuang/hellominecraft/lookandfeel/Theme.java index d89898f9b..554105d49 100755 --- a/HMCLaF/src/main/java/org/jackhuang/hellominecraft/lookandfeel/Theme.java +++ b/HMCLaF/src/main/java/org/jackhuang/hellominecraft/lookandfeel/Theme.java @@ -19,6 +19,7 @@ package org.jackhuang.hellominecraft.lookandfeel; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import org.jackhuang.hellominecraft.util.C; /** @@ -85,9 +86,7 @@ public enum Theme { public final Map settings; private Theme(String localizedName, Map settings) { - if (settings == null) - throw new NullPointerException("Theme settings map should not be null."); this.localizedName = localizedName; - this.settings = settings; + this.settings = Objects.requireNonNull(settings, "Theme settings map may not be null."); } } diff --git a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/AbstractSwingWorker.java b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/AbstractSwingWorker.java index 666a0b6ce..e666477e7 100644 --- a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/AbstractSwingWorker.java +++ b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/AbstractSwingWorker.java @@ -48,14 +48,12 @@ public abstract class AbstractSwingWorker extends SwingWorker { } public AbstractSwingWorker reg(Consumer c) { - Objects.requireNonNull(c); - processListeners.add(c); + processListeners.add(Objects.requireNonNull(c)); return this; } public AbstractSwingWorker regDone(Runnable c) { - Objects.requireNonNull(c); - doneListeners.add(c); + doneListeners.add(Objects.requireNonNull(c)); return this; } diff --git a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/system/FileUtils.java b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/system/FileUtils.java index 82737d591..b7043186d 100755 --- a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/system/FileUtils.java +++ b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/system/FileUtils.java @@ -28,6 +28,7 @@ import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.List; +import java.util.Objects; import org.jackhuang.hellominecraft.util.logging.HMCLog; /** @@ -121,8 +122,7 @@ public final class FileUtils { public static boolean isSymlink(File file) throws IOException { - if (file == null) - throw new NullPointerException("File must not be null"); + Objects.requireNonNull(file, "File must not be null"); if (File.separatorChar == '\\') return false; File fileInCanonicalDir; @@ -143,10 +143,8 @@ public final class FileUtils { public static void copyDirectory(File srcDir, File destDir, FileFilter filter) throws IOException { - if (srcDir == null) - throw new NullPointerException("Source must not be null"); - if (destDir == null) - throw new NullPointerException("Destination must not be null"); + Objects.requireNonNull(srcDir, "Source must not be null"); + Objects.requireNonNull(destDir, "Destination must not be null"); if (!srcDir.exists()) throw new FileNotFoundException("Source '" + srcDir + "' does not exist"); if (!srcDir.isDirectory()) @@ -230,10 +228,8 @@ public final class FileUtils { public static void copyFile(File srcFile, File destFile) throws IOException { - if (srcFile == null) - throw new NullPointerException("Source must not be null"); - if (destFile == null) - throw new NullPointerException("Destination must not be null"); + Objects.requireNonNull(srcFile, "Source must not be null"); + Objects.requireNonNull(destFile, "Destination must not be null"); if (!srcFile.exists()) throw new FileNotFoundException("Source '" + srcFile + "' does not exist"); if (srcFile.isDirectory()) diff --git a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/LogWindowOutputStream.java b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/LogWindowOutputStream.java index 5aa3b97c5..b108254b8 100755 --- a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/LogWindowOutputStream.java +++ b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/LogWindowOutputStream.java @@ -36,10 +36,8 @@ public class LogWindowOutputStream extends OutputStream { private final Level sas; public LogWindowOutputStream(LogWindow logWindow, Level l) { - Objects.requireNonNull(logWindow); - Objects.requireNonNull(l); - txt = logWindow; - sas = l; + txt = Objects.requireNonNull(logWindow); + sas = Objects.requireNonNull(l); } @Override diff --git a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/BranchingWizard.java b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/BranchingWizard.java index a224f2b18..ffeaedd8b 100644 --- a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/BranchingWizard.java +++ b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/BranchingWizard.java @@ -19,6 +19,7 @@ package org.jackhuang.hellominecraft.util.ui.wizard.spi; import javax.swing.*; import java.util.Arrays; import java.util.Map; +import java.util.Objects; /** * A Wizard with indeterminate branches. The actual branch decision-making is @@ -105,8 +106,7 @@ final class BranchingWizard extends AbstractWizard { if (activeWizard == wizard) return; - if (wizard == null) - throw new NullPointerException("Can't set current wizard to null"); + Objects.requireNonNull(wizard, "Can't set current wizard to null"); if ((activeWizard != null) && (wl != null)) activeWizard.removeWizardObserver(wl); @@ -260,15 +260,10 @@ final class BranchingWizard extends AbstractWizard { @Override public final JComponent navigatingTo(String id, Map settings) { - if (id == null) - throw new NullPointerException(); - currStep = id; + currStep = Objects.requireNonNull(id); wizardData = settings; - WizardImplementation impl = ownerOf(id); - if (impl == null) - throw new NullPointerException("No owning WizardImplementation for" - + " id " + id); + WizardImplementation impl = Objects.requireNonNull(ownerOf(id), "No owning WizardImplementation for id " + id); setCurrent(impl); return activeWizard.navigatingTo(id, settings); diff --git a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/SimpleWizardInfo.java b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/SimpleWizardInfo.java index 8738385d7..cc38e7a10 100644 --- a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/SimpleWizardInfo.java +++ b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/SimpleWizardInfo.java @@ -25,6 +25,7 @@ import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.HashSet; import java.util.Map; +import java.util.Objects; import javax.swing.BorderFactory; import javax.swing.JComponent; import javax.swing.JScrollPane; @@ -59,12 +60,8 @@ public final class SimpleWizardInfo implements WizardControllerImplementation { * and descriptions. */ protected SimpleWizardInfo(String title, String[] steps, String[] descriptions, WizardPanelProvider provider) { - if (steps == null) - throw new NullPointerException("Null steps"); - if (descriptions == null) - throw new NullPointerException("Null descriptions"); - this.steps = steps; - this.descriptions = descriptions; + this.steps = Objects.requireNonNull(steps, "Null steps"); + this.descriptions = Objects.requireNonNull(descriptions, "Null descriptions"); if (new HashSet(Arrays.asList(steps)).size() < steps.length) throw new IllegalArgumentException("Duplicate ID: " + Arrays.asList(steps)); if (descriptions.length != steps.length) @@ -132,16 +129,6 @@ public final class SimpleWizardInfo implements WizardControllerImplementation { * gathered data. */ protected Object finish(Map settings) throws WizardException { - //XXX fixme -// assert canFinish(); - - // SKNUTSON: the "canFinish" behavior is not working - // instead, panels must implement the WizardPanel interface - // and have allowFinish return false -// if ( ! canFinish()) -// { -// throw new RuntimeException ("Can't finish right now"); -// } return provider.finish(settings); } diff --git a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/Summary.java b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/Summary.java index 9b31872a5..089b2b3c3 100644 --- a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/Summary.java +++ b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/Summary.java @@ -20,10 +20,13 @@ package org.jackhuang.hellominecraft.util.ui.wizard.spi; import java.awt.Component; import java.awt.Font; +import java.util.Objects; import javax.swing.JList; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.UIManager; +import org.jackhuang.hellominecraft.util.ArrayUtils; +import org.jackhuang.hellominecraft.util.StrUtils; /** * Object which may be returned from @@ -56,9 +59,7 @@ public class Summary { public Summary(String text, Object result) { //XXX this is creating components off the AWT thread - needs to change //to use invokeAndWait where appropriate - if (text == null) - throw new NullPointerException("Text is null"); - if (text.trim().length() == 0) + if (StrUtils.isBlank(text)) throw new IllegalArgumentException("Text is empty or all whitespace"); this.result = result; JTextArea jta = new JTextArea(); @@ -85,9 +86,7 @@ public class Summary { * @return the requested Summary object */ public Summary(String[] items, Object result) { - if (items == null) - throw new NullPointerException("Items array null"); - if (items.length == 0) + if (ArrayUtils.isEmpty(items)) throw new IllegalArgumentException("Items array empty"); this.result = result; JList list = new JList(items); @@ -108,9 +107,7 @@ public class Summary { */ public Summary(Component comp, Object result) { this.result = result; - this.comp = comp; - if (comp == null) - throw new NullPointerException("Null component"); + this.comp = Objects.requireNonNull(comp, "Null component"); } /** diff --git a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/Util.java b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/Util.java index bd6fbfd69..fc70c92a5 100644 --- a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/Util.java +++ b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/Util.java @@ -10,6 +10,7 @@ import java.lang.reflect.Modifier; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.HashSet; +import java.util.Objects; import java.util.Set; /** @@ -71,10 +72,8 @@ final class Util { try { Method m = clazz.getDeclaredMethod("getStep", new Class[]{}); // assert m.getReturnType() == String.class; - result = (String) m.invoke(clazz, (Object[]) null); - if (result == null) - throw new NullPointerException("getStep may not return null"); - } catch (IllegalAccessException | IllegalArgumentException | NoSuchMethodException | NullPointerException | SecurityException | InvocationTargetException ex) { + result = Objects.requireNonNull((String) m.invoke(clazz, (Object[]) null), "getStep may not return null"); + } catch (Exception ex) { //do nothing } return result == null ? clazz.getName() : result; @@ -85,16 +84,13 @@ final class Util { * class object passed */ static String[] getSteps(Class[] pages) { - if (pages == null) - throw new NullPointerException("Null array of classes"); + Objects.requireNonNull(pages, "Null array of classes"); String[] result = new String[pages.length]; Set used = new HashSet(pages.length); for (int i = 0; i < pages.length; i++) { - if (pages[i] == null) - throw new NullPointerException("Null at " + i + " in array " - + "of panel classes"); + Objects.requireNonNull(pages[i], "Null at " + i + " in array of panel classes"); if (!WizardPage.class.isAssignableFrom(pages[i])) throw new IllegalArgumentException(pages[i] diff --git a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/Wizard.java b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/Wizard.java index 7f4e76e8d..8cde77bac 100644 --- a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/Wizard.java +++ b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/Wizard.java @@ -15,6 +15,7 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Objects; import javax.swing.Action; import javax.swing.JComponent; import org.jackhuang.hellominecraft.util.ui.wizard.api.WizardDisplayer; @@ -121,9 +122,7 @@ public final class Wizard { * Creates a new instance of Wizard */ Wizard(WizardImplementation impl) { - this.impl = impl; - if (impl == null) - throw new NullPointerException(); + this.impl = Objects.requireNonNull(impl); } /** @@ -321,6 +320,7 @@ public final class Wizard { private class ImplL implements WizardObserver { + @Override public void stepsChanged(Wizard wizard) { WizardObserver[] l = (WizardObserver[]) listeners.toArray( new WizardObserver[listeners.size()]); @@ -328,6 +328,7 @@ public final class Wizard { l1.stepsChanged(Wizard.this); } + @Override public void navigabilityChanged(Wizard wizard) { WizardObserver[] l = (WizardObserver[]) listeners.toArray( new WizardObserver[listeners.size()]); @@ -335,6 +336,7 @@ public final class Wizard { l1.navigabilityChanged(Wizard.this); } + @Override public void selectionChanged(Wizard wizard) { WizardObserver[] l = (WizardObserver[]) listeners.toArray( new WizardObserver[listeners.size()]); @@ -343,10 +345,12 @@ public final class Wizard { } } + @Override public int hashCode() { return impl.hashCode() * 17; } + @Override public boolean equals(Object o) { if (o == this) return true; diff --git a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/WizardBranchController.java b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/WizardBranchController.java index ebc1598a9..25bb2e010 100644 --- a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/WizardBranchController.java +++ b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/WizardBranchController.java @@ -16,6 +16,7 @@ enclosed by brackets [] replaced by your own identifying information: package org.jackhuang.hellominecraft.util.ui.wizard.spi; import java.util.Map; +import java.util.Objects; /** * Extend this class to create wizards which have branch points in them - @@ -93,9 +94,7 @@ public abstract class WizardBranchController { * for the initial panes of the wizard. */ WizardBranchController(SimpleWizardInfo base) { - if (base == null) - throw new NullPointerException("No base"); - this.base = base; + this.base = Objects.requireNonNull(base, "No base"); } /** diff --git a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/WizardPage.java b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/WizardPage.java index 529f74c09..8ee85f0cc 100644 --- a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/WizardPage.java +++ b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/WizardPage.java @@ -165,10 +165,6 @@ public class WizardPage extends JPanel implements WizardPanel { throw new IllegalStateException("CustomComponentListener " + "will never be called if the autoListen parameter is " + "false"); -// if (getClass() == WizardPage.class && stepId == null || -// description == null) { -// throw new NullPointerException ("Step or ID is null"); -// } setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); //XXX } @@ -339,6 +335,7 @@ public class WizardPage extends JPanel implements WizardPanel { this.page = page; //Slightly smaller footprint a nested, not inner class } + @Override public void userInputReceived(Component c, Object event) { if (!page.ccl.accept(c)) return; @@ -362,6 +359,7 @@ public class WizardPage extends JPanel implements WizardPanel { return description; } + @Override public void addNotify() { super.addNotify(); if (!listening) @@ -376,14 +374,17 @@ public class WizardPage extends JPanel implements WizardPanel { } } + @Override public WizardPanelNavResult allowBack(String stepName, Map settings, Wizard wizard) { return WizardPanelNavResult.PROCEED; } + @Override public WizardPanelNavResult allowFinish(String stepName, Map settings, Wizard wizard) { return WizardPanelNavResult.PROCEED; } + @Override public WizardPanelNavResult allowNext(String stepName, Map settings, Wizard wizard) { return WizardPanelNavResult.PROCEED; } @@ -830,7 +831,7 @@ public class WizardPage extends JPanel implements WizardPanel { } static WizardPanelProvider createWizardPanelProvider(WizardPage page) { - return new WPP(new WizardPage[]{page}, WizardResultProducer.NO_OP); + return new WPP(new WizardPage[] { page }, WizardResultProducer.NO_OP); } static WizardPanelProvider createWizardPanelProvider(WizardPage[] page) { @@ -879,6 +880,7 @@ public class WizardPage extends JPanel implements WizardPanel { this.finish = finish; } + @Override protected JComponent createPanel(WizardController controller, String id, Map wizardData) { int idx = indexOfStep(id); @@ -907,14 +909,17 @@ public class WizardPage extends JPanel implements WizardPanel { return null; } + @Override protected Object finish(Map settings) throws WizardException { return finish.finish(settings); } + @Override public boolean cancel(Map settings) { return finish.cancel(settings); } + @Override public String getLongDescription(String stepId) { for (WizardPage wizardPage : pages) if (stepId.equals(wizardPage.getID())) @@ -974,6 +979,7 @@ public class WizardPage extends JPanel implements WizardPanel { this.finish = finish; } + @Override protected JComponent createPanel(WizardController controller, String id, Map wizardData) { int idx = indexOfStep(id); @@ -995,18 +1001,22 @@ public class WizardPage extends JPanel implements WizardPanel { } } + @Override protected Object finish(Map settings) throws WizardException { return finish.finish(settings); } + @Override public boolean cancel(Map settings) { return finish.cancel(settings); } + @Override public String toString() { return super.toString() + " for " + finish; } + @Override public String getLongDescription(String stepId) { int idx = indexOfStep(stepId); if (idx != -1) @@ -1027,10 +1037,12 @@ public class WizardPage extends JPanel implements WizardPanel { private int canFinish = -1; private Boolean busy = null; + @Override public void setProblem(String value) { this.problem = value; } + @Override public void setForwardNavigationMode(int value) { switch (value) { case WizardController.MODE_CAN_CONTINUE: @@ -1044,6 +1056,7 @@ public class WizardPage extends JPanel implements WizardPanel { canFinish = value; } + @Override public void setBusy(boolean busy) { this.busy = busy ? Boolean.TRUE : Boolean.FALSE; } @@ -1106,14 +1119,17 @@ public class WizardPage extends JPanel implements WizardPanel { * A no-op WizardResultProducer that returns null. */ WizardResultProducer NO_OP = new WizardResultProducer() { + @Override public Object finish(Map wizardData) { return wizardData; } + @Override public boolean cancel(Map settings) { return true; } + @Override public String toString() { return "NO_OP WizardResultProducer"; } diff --git a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/WizardPanelProvider.java b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/WizardPanelProvider.java index 88dd4e8b5..f7eb231af 100644 --- a/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/WizardPanelProvider.java +++ b/HMCUtils/src/main/java/org/jackhuang/hellominecraft/util/ui/wizard/spi/WizardPanelProvider.java @@ -8,44 +8,44 @@ and include the License file at http://www.netbeans.org/cddl.txt. If applicable, add the following below the CDDL Header, with the fields enclosed by brackets [] replaced by your own identifying information: "Portions Copyrighted [year] [name of copyright owner]" */ -/* + /* * PanelProvider.java * * Created on March 5, 2005, 7:25 PM */ - package org.jackhuang.hellominecraft.util.ui.wizard.spi; import java.util.Arrays; import java.util.HashSet; import java.util.Map; +import java.util.Objects; import javax.swing.JComponent; /** * (Note: WizardPage offers somewhat simpler functionality for - * creating a wizard than does WizardPanelProvider; the only advantage of - * WizardPanelProvider is that it does not require one to - * subclass a panel component). + * creating a wizard than does WizardPanelProvider; the only advantage of + * WizardPanelProvider is that it does not require one to subclass + * a panel component). *

- * A simple interface for providing a fixed set of panels for a wizard. - * To use, simply implement createPanel() to create the - * appropriate UI component for a given step (a unique String ID - one of the ones passed - * in the constructor in the steps array), and implement + * A simple interface for providing a fixed set of panels for a wizard. To use, + * simply implement createPanel() to create the appropriate UI + * component for a given step (a unique String ID - one of the ones passed in + * the constructor in the steps array), and implement * finish() to do whatever should be done when the wizard is * finished. *

- * To control whether the Next/Finish buttons are enabled, components - * created in createPanel() should call methods on the - * WizardController passed. The created panels should listen on the - * UI components they create, updating the settings Map when the user changes - * their input. + * To control whether the Next/Finish buttons are enabled, components created in + * createPanel() should call methods on the + * WizardController passed. The created panels should listen on the UI + * components they create, updating the settings Map when the user changes their + * input. *

* Super-simple one-pane wizard example - if the checkbox is checked, the user * can continue: *

  * public class MyProvider extends WizardPanelProvider {
  *    public MyProvider() {
- *       //here we pass a localized title for the wizard, 
+ *       //here we pass a localized title for the wizard,
  *       //the ID of the one step it will have, and a localized description
  *       //the wizard can show for that one step
  *       super ("Click the box", "click", "Click the checkbox");
@@ -57,7 +57,7 @@ import javax.swing.JComponent;
  *       final JCheckBox result = new JCheckBox();
  *       result.addActionListener (new ActionListener() {
  *          public void actionPerformed (ActionEvent ae) {
- *             //Typically you want to write the result of some user 
+ *             //Typically you want to write the result of some user
  *             //action into the settings map as soon as they do it 
  *             settings.put ("boxSelected", result.isSelected() ? Boolean.TRUE : Boolean.FALSE);
  *             if (result.isSelected()) {
@@ -72,7 +72,7 @@ import javax.swing.JComponent;
  *    }
  *
  *    protected Object finish (Map settings) throws WizardException {
- *       //if we had some interesting information (Strings a user put in a 
+ *       //if we had some interesting information (Strings a user put in a
  *       //text field or something, we'd generate some interesting object or
  *       //create some files or something here
  *       return null;
@@ -83,240 +83,229 @@ import javax.swing.JComponent;
  * @author Tim Boudreau
  */
 public abstract class WizardPanelProvider {
+
     final String title;
     final String[] descriptions;
     final String[] steps;
     final String[] knownProblems;
-    
+
     /**
-     * Create a WizardPanelProvider.  The passed array of steps and descriptions
+     * Create a WizardPanelProvider. The passed array of steps and descriptions
      * will be used as IDs and localized descriptions of the various steps in
-     * the wizard.  Use this constructor (which passes not title) for sub-wizards
-     * used in a WizardBranchController, where the first pane 
-     * will determine the title, and the titles of the sub-wizards will never be 
+     * the wizard. Use this constructor (which passes not title) for sub-wizards
+     * used in a WizardBranchController, where the first pane will
+     * determine the title, and the titles of the sub-wizards will never be
      * shown.
-     * @param steps A set of unique IDs identifying each step of this wizard.  Each
-     *   ID must occur only once in the array of steps.
-     *   
+     *
+     * @param steps A set of unique IDs identifying each step of this wizard.
+     * Each ID must occur only once in the array of steps.
+     *
      * @param descriptions A set of human-readable descriptions corresponding
-     *  1:1 with the unique IDs passed as the steps parameter
+     * 1:1 with the unique IDs passed as the steps parameter
      */
-    protected WizardPanelProvider (String[] steps, String[] descriptions) {
-        this (null, steps, descriptions);
+    protected WizardPanelProvider(String[] steps, String[] descriptions) {
+        this(null, steps, descriptions);
     }
-    
+
     /**
-     * Create a WizardPanelProvider with the provided title, steps and 
-     * descriptions.  The steps parameter are unique IDs of 
-     * panels, which will be passed to createPanel to create
-     * panels for various steps in the wizard, as the user navigates it.
-     * The descriptions parameter is a set of localized descriptions
+     * Create a WizardPanelProvider with the provided title, steps and
+     * descriptions. The steps parameter are unique IDs of panels,
+     * which will be passed to createPanel to create panels for
+     * various steps in the wizard, as the user navigates it. The
+     * descriptions parameter is a set of localized descriptions
      * that can appear in the Wizard to describe each step.
+     *
      * @param title A human readable title for the wizard dialog
-     * @param steps An array of unique IDs for the various panels of this 
-     *  wizard
+     * @param steps An array of unique IDs for the various panels of this wizard
      * @param descriptions An array of descriptions corresponding 1:1 with the
-     *  unique IDs.  These must be human readable, localized strings.
+     * unique IDs. These must be human readable, localized strings.
      */
-    protected WizardPanelProvider (String title, String[] steps, String[] descriptions) {
+    protected WizardPanelProvider(String title, String[] steps, String[] descriptions) {
         this.title = title;
         this.steps = steps;
         this.descriptions = descriptions;
         knownProblems = new String[steps.length];
-        if (steps.length != descriptions.length) {
-            throw new IllegalArgumentException ("Length of steps and" +
-                    " descriptions arrays do not match");
-        }
+        if (steps.length != descriptions.length)
+            throw new IllegalArgumentException("Length of steps and"
+                    + " descriptions arrays do not match");
         // assert validData (steps, descriptions) == null : validData (steps, descriptions);
-        String v = validData (steps, descriptions);
+        String v = validData(steps, descriptions);
         if (v != null)
-        {
-            throw new RuntimeException (v);
-        }
+            throw new RuntimeException(v);
     }
-    
-    
-    private String validData (String[] steps, String[] descriptions) {
-        if (steps.length != descriptions.length) {
-            return steps.length + " steps but " + descriptions.length + 
-                    " descriptions";
+
+    private String validData(String[] steps, String[] descriptions) {
+        if (steps.length != descriptions.length)
+            return steps.length + " steps but " + descriptions.length
+                    + " descriptions";
+        for (int i = 0; i < steps.length; i++) {
+            Objects.requireNonNull(steps[i], "Step id " + i + " is null");
+            Objects.requireNonNull(descriptions[i], "Description " + i + " is null");
         }
-        for (int i=0; i < steps.length; i++) {
-            if (steps[i] == null) {
-                throw new NullPointerException ("Step id " + i + " is null");
-            }
-            if (descriptions[i] == null) {
-                throw new NullPointerException ("Description " + i + " is null");
-            }
-        }
-        if (new HashSet(Arrays.asList(steps)).size() != steps.length) {
+        if (new HashSet(Arrays.asList(steps)).size() != steps.length)
             return "Duplicate step ids: " + Arrays.asList(steps);
-        }
         return null;
     }
-    
+
     /**
      * Convenience constructor to create a WizardPanelProvider which has only
-     * one step to it.  Mainly useful for initial steps in a WizardBranchController.
+     * one step to it. Mainly useful for initial steps in a
+     * WizardBranchController.
+     *
      * @param title A human readable title for the wizard dialog
      * @param singleStep The unique ID of the only step this wizard has
      * @param singleDescription The human-readable description of what the user
-     *  should do in the one step of this one-step wizard or sub-wizard
+     * should do in the one step of this one-step wizard or sub-wizard
      */
-    protected WizardPanelProvider (String title, String singleStep, String singleDescription) {
-        this (title, new String[] {singleStep}, new String[] {singleDescription});
+    protected WizardPanelProvider(String title, String singleStep, String singleDescription) {
+        this(title, new String[] { singleStep }, new String[] { singleDescription });
     }
-    
+
     /**
-     * Create a panel that represents a named step in the wizard.
-     * This method will be called exactly once in the life of 
-     * a wizard.  The panel should retain the passed settings Map, and
-     * add/remove values from it as the user enters information, calling
-     * setProblem() and setCanFinish() as
-     * appropriate in response to user input.
-     * 
-     * @param controller - the object which controls whether the
-     *  Next/Finish buttons in the wizard are enabled, and what instructions
-     *  are displayed to the user if they are not
-     * @param id The name of the step, one of the array of steps passed in
-     *  the constructor
-     * @param settings A Map containing settings from earlier steps in
-     *   the wizard.  It is safe to retain a reference to this map and put
-     *   values in it as the user manipulates the UI;  the reference should
-     *   be refreshed whenever this method is called again.
-     * @return A JComponent that should be displayed in the center of the
-     *  wizard
+     * Create a panel that represents a named step in the wizard. This method
+     * will be called exactly once in the life of a wizard. The panel
+     * should retain the passed settings Map, and add/remove values from it as
+     * the user enters information, calling setProblem() and
+     * setCanFinish() as appropriate in response to user input.
+     *
+     * @param controller - the object which controls whether the Next/Finish
+     * buttons in the wizard are enabled, and what instructions are displayed to
+     * the user if they are not
+     * @param id The name of the step, one of the array of steps passed in the
+     * constructor
+     * @param settings A Map containing settings from earlier steps in the
+     * wizard. It is safe to retain a reference to this map and put values in it
+     * as the user manipulates the UI; the reference should be refreshed
+     * whenever this method is called again.
+     * @return A JComponent that should be displayed in the center of the wizard
      */
-    protected abstract JComponent createPanel (WizardController controller, String id, Map settings);
-    
+    protected abstract JComponent createPanel(WizardController controller, String id, Map settings);
+
     /**
-     * Instantiate whatever object (if any) the wizard creates from its
-     * gathered data.  The default implementation is a no-op that returns
-     * null.
+     * Instantiate whatever object (if any) the wizard creates from its gathered
+     * data. The default implementation is a no-op that returns null.
      * 

* If an instance of Summary is returned from this method, the * UI shall display it on a final page and disable all navigation buttons * except the Close/Cancel button. *

* If an instance of DeferredWizardResult is returned from this - * method, the UI shall display some sort of progress bar while the result - * is computed in the background. If that DeferredWizardResult + * method, the UI shall display some sort of progress bar while the result + * is computed in the background. If that DeferredWizardResult * produces a Summary object, that summary shall be displayed * as described above. *

* The default implementation returns the settings map it is passed. * - * @param settings The settings map, now fully populated with all settings needed - * to complete the wizard (this method will only be called if - * setProblem(null) and setCanFinish(true) have - * been called on the WizardController passed to - * createPanel(). - * @return an object composed based on what the user entered in the wizard - - * somethingmeaningful to whatever code invoked the wizard, or null. Note - * special handling if an instance of DeferredWizardResult - * or Summary is returned from this method. + * @param settings The settings map, now fully populated with all settings + * needed to complete the wizard (this method will only be called if + * setProblem(null) and setCanFinish(true) have + * been called on the WizardController passed to + * createPanel(). + * @return an object composed based on what the user entered in the wizard - + * somethingmeaningful to whatever code invoked the wizard, or null. Note + * special handling if an instance of DeferredWizardResult or + * Summary is returned from this method. */ - protected Object finish (Map settings) throws WizardException { + protected Object finish(Map settings) throws WizardException { return settings; } /** * The method provides a chance to call setProblem() or setCanFinish() when - * the user re-navigates to a panel they've already seen - in the case - * that the user pressed the Previous button and then the Next button. + * the user re-navigates to a panel they've already seen - in the case that + * the user pressed the Previous button and then the Next button. *

* The default implementation does nothing, which is sufficient for most - * cases. - * If whether this panel is valid or not could - * have changed because of changed data from a previous panel, or it - * displays data entered on previous panes which may have changed, - * you may want to override this method to ensure validity and canFinish - * are set correctly, and that the components have the correct text. + * cases. If whether this panel is valid or not could have changed because + * of changed data from a previous panel, or it displays data entered on + * previous panes which may have changed, you may want to override this + * method to ensure validity and canFinish are set correctly, and that the + * components have the correct text. *

- * This method will not be called when a panel is first instantiated - - * createPanel() is expected to set validity and canFinish + * This method will not be called when a panel is first instantiated + * - createPanel() is expected to set validity and canFinish * appropriately. *

- * The settings Map passed to this method will always be the same - * Settings map instance that was passed to createPanel() - * when the panel was created. + * The settings Map passed to this method will always be the same Settings + * map instance that was passed to createPanel() when the panel + * was created. *

* If you are implementing WizardPanelProvider and some of the pages are - * WizardPages, you should call the super implementation if - * you override this method. + * WizardPages, you should call the super implementation if you + * override this method. */ - protected void recycleExistingPanel (String id, WizardController controller, Map wizardData, JComponent panel) { + protected void recycleExistingPanel(String id, WizardController controller, Map wizardData, JComponent panel) { //do nothing } - void recycle (String id, WizardController controller, Map wizardData, JComponent panel) { + void recycle(String id, WizardController controller, Map wizardData, JComponent panel) { if (panel instanceof WizardPage) { WizardPage page = (WizardPage) panel; page.setController(controller); page.setWizardDataMap(wizardData); page.recycle(); } - recycleExistingPanel (id, controller, wizardData, panel); + recycleExistingPanel(id, controller, wizardData, panel); } - + private Wizard wizard; + /** - * Create a Wizard for this PanelProvider. The instance created by this + * Create a Wizard for this PanelProvider. The instance created by this * method is cached and the same instance will be returned on subsequent * calls. */ public final Wizard createWizard() { - if (wizard == null) { - wizard = new Wizard (new SimpleWizard (this)); - } + if (wizard == null) + wizard = new Wizard(new SimpleWizard(this)); return wizard; } - + /** - * This method can optionally be overridden to provide a longer - * description of a step to be shown in the top of its panel. - * The default implementation returns null, indicating that the - * short description should be used. - * + * This method can optionally be overridden to provide a longer description + * of a step to be shown in the top of its panel. The default implementation + * returns null, indicating that the short description should be used. + * * @param stepId a unique id for one step of the wizard - * @return An alternate description for use in the top of the wizard - * page when this page is the current one, or null - */ - public String getLongDescription (String stepId) { + * @return An alternate description for use in the top of the wizard page + * when this page is the current one, or null + */ + public String getLongDescription(String stepId) { return null; } - + /** - * Convenience method to get the index into the array of steps passed to - * the constructor of a specific step id. + * Convenience method to get the index into the array of steps passed to the + * constructor of a specific step id. */ - protected final int indexOfStep (String id) { + protected final int indexOfStep(String id) { return Arrays.asList(steps).indexOf(id); } - - void setKnownProblem (String problem, int idx) { + + void setKnownProblem(String problem, int idx) { //Record a problem message so we can put it back if the user does //prev and then next - if (idx >= 0) { //setProblem() can be called during initialization + if (idx >= 0) //setProblem() can be called during initialization knownProblems[idx] = problem; - } } - + String getKnownProblem(int idx) { return knownProblems[idx]; } /** - * Called if the user invokes cancel. The default impl returns - * true. - * @return false to abort cancellation (almost all implementations will - * want to return true - this is really only applicable in cases such - * as an OS installer or such). + * Called if the user invokes cancel. The default impl returns true. + * + * @return false to abort cancellation (almost all implementations will want + * to return true - this is really only applicable in cases such as an OS + * installer or such). */ public boolean cancel(Map settings) { return true; } - + + @Override public String toString() { return super.toString() + " with wizard " + wizard; }