Fixed handshake failed connecting with minecraft asset site

This commit is contained in:
huangyuhui 2017-01-26 15:07:57 +08:00
parent 574532f10c
commit 627e632120
19 changed files with 225 additions and 245 deletions

View File

@ -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/"

View File

@ -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

View File

@ -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 {

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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();

View File

@ -132,7 +132,7 @@ public class CrashReporter implements Thread.UncaughtExceptionHandler {
private static final HashSet<String> 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(() -> {

View File

@ -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<String, String> settings;
private Theme(String localizedName, Map<String, String> 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.");
}
}

View File

@ -48,14 +48,12 @@ public abstract class AbstractSwingWorker<T> extends SwingWorker<Void, T> {
}
public AbstractSwingWorker reg(Consumer<T> 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;
}

View File

@ -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())

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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 <code>Summary</code> 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");
}
/**

View File

@ -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]

View File

@ -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;

View File

@ -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");
}
/**

View File

@ -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";
}

View File

@ -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: <code>WizardPage</code> offers somewhat simpler functionality for
* creating a wizard than does WizardPanelProvider; the only advantage of
* <code>WizardPanelProvider</code> is that it does not require one to
* subclass a panel component).
* creating a wizard than does WizardPanelProvider; the only advantage of
* <code>WizardPanelProvider</code> is that it does not require one to subclass
* a panel component).
* <p>
* A simple interface for providing a fixed set of panels for a wizard.
* To use, simply implement <code>createPanel()</code> to create the
* appropriate UI component for a given step (a unique String ID - one of the ones passed
* in the constructor in the <code>steps</code> array), and implement
* A simple interface for providing a fixed set of panels for a wizard. To use,
* simply implement <code>createPanel()</code> to create the appropriate UI
* component for a given step (a unique String ID - one of the ones passed in
* the constructor in the <code>steps</code> array), and implement
* <code>finish()</code> to do whatever should be done when the wizard is
* finished.
* <p>
* To control whether the Next/Finish buttons are enabled, components
* created in <code>createPanel()</code> should call methods on the <code>
* WizardController</code> 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
* <code>createPanel()</code> should call methods on the <code>
* WizardController</code> passed. The created panels should listen on the UI
* components they create, updating the settings Map when the user changes their
* input.
* <p>
* Super-simple one-pane wizard example - if the checkbox is checked, the user
* can continue:
* <pre>
* public class MyProvider extends WizardPanelProvider {
* public MyProvider() {
* <font color="gray">//here we pass a localized title for the wizard,
* <font color="gray">//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</font>
* 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) {
* <font color="gray">//Typically you want to write the result of some user
* <font color="gray">//Typically you want to write the result of some user
* //action into the settings map as soon as they do it </font>
* 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 {
* <font color="gray">//if we had some interesting information (Strings a user put in a
* <font color="gray">//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</font>
* 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 <code>WizardBranchController</code>, 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 <code>WizardBranchController</code>, 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 <code>steps</code> parameter
* 1:1 with the unique IDs passed as the <code>steps</code> 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 <code>steps</code> parameter are unique IDs of
* panels, which will be passed to <code>createPanel</code> to create
* panels for various steps in the wizard, as the user navigates it.
* The <code>descriptions</code> parameter is a set of localized descriptions
* Create a WizardPanelProvider with the provided title, steps and
* descriptions. The <code>steps</code> parameter are unique IDs of panels,
* which will be passed to <code>createPanel</code> to create panels for
* various steps in the wizard, as the user navigates it. The
* <code>descriptions</code> 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 <code>WizardBranchController</code>.
* one step to it. Mainly useful for initial steps in a
* <code>WizardBranchController</code>.
*
* @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 <i>once</i> 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
* <code>setProblem()</code> and <code>setCanFinish()</code> 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 <i>once</i> 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 <code>setProblem()</code> and
* <code>setCanFinish()</code> 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.
* <p>
* If an instance of <code>Summary</code> is returned from this method, the
* UI shall display it on a final page and disable all navigation buttons
* except the Close/Cancel button.
* <p>
* If an instance of <code>DeferredWizardResult</code> is returned from this
* method, the UI shall display some sort of progress bar while the result
* is computed in the background. If that <code>DeferredWizardResult</code>
* method, the UI shall display some sort of progress bar while the result
* is computed in the background. If that <code>DeferredWizardResult</code>
* produces a <code>Summary</code> object, that summary shall be displayed
* as described above.
* <p>
* 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
* <code>setProblem(null)</code> and <code>setCanFinish(true)</code> have
* been called on the <code>WizardController</code> passed to
* <code>createPanel()</code>.
* @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 <code>DeferredWizardResult</code>
* or <code>Summary</code> 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
* <code>setProblem(null)</code> and <code>setCanFinish(true)</code> have
* been called on the <code>WizardController</code> passed to
* <code>createPanel()</code>.
* @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 <code>DeferredWizardResult</code> or
* <code>Summary</code> 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.
* <p>
* 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.
* <p>
* This method will <i>not</i> be called when a panel is first instantiated -
* <code>createPanel()</code> is expected to set validity and canFinish
* This method will <i>not</i> be called when a panel is first instantiated
* - <code>createPanel()</code> is expected to set validity and canFinish
* appropriately.
* <p>
* The settings Map passed to this method will always be the same
* Settings map instance that was passed to <code>createPanel()</code>
* when the panel was created.
* The settings Map passed to this method will always be the same Settings
* map instance that was passed to <code>createPanel()</code> when the panel
* was created.
* <p>
* If you are implementing WizardPanelProvider and some of the pages are
* <code>WizardPage</code>s, you should call the super implementation if
* you override this method.
* <code>WizardPage</code>s, 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;
}