diff options
author | Josiah Gaskin <josiahgaskin@google.com> | 2014-09-18 12:29:14 -0700 |
---|---|---|
committer | Josiah Gaskin <josiahgaskin@google.com> | 2014-09-22 11:07:43 -0700 |
commit | 2738ab790f79408aa80970dfef94cd03c95f32c7 (patch) | |
tree | 875e6c0e5c4306e9e9cd2de04306a566e6e23680 | |
parent | d574df173252b036e649c4a6e8e83892ad2d4d9b (diff) | |
download | idea-2738ab790f79408aa80970dfef94cd03c95f32c7.tar.gz |
Add Navigation to Named Steps to Dynamic Wizard Infrastructure
This change allows wizards to "jump" between steps/paths by
navigating to steps of a given name.
Change-Id: I6238b79529b9430f76e87a9be3ee2e85ce535a68
7 files changed, 148 insertions, 3 deletions
diff --git a/android/src/com/android/tools/idea/wizard/AndroidStudioWizardPath.java b/android/src/com/android/tools/idea/wizard/AndroidStudioWizardPath.java index 96b6e209e50..d3b0f833b40 100644 --- a/android/src/com/android/tools/idea/wizard/AndroidStudioWizardPath.java +++ b/android/src/com/android/tools/idea/wizard/AndroidStudioWizardPath.java @@ -16,6 +16,8 @@ package com.android.tools.idea.wizard; import com.intellij.ide.wizard.Step; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Interface for the wizard paths @@ -75,6 +77,18 @@ public interface AndroidStudioWizardPath { boolean canGoNext(); /** + * Returns true if the path contains a step with the given name. + */ + boolean containsStep(@NotNull String stepName, boolean visibleOnly); + + /** + * Set the current step to the step with the given name if it exists. + * If the step does not exist or is not visible (and visibleOnly is true) + * then this is a no-op. + */ + void navigateToNamedStep(@NotNull String stepName, boolean visibleOnly); + + /** * Determine whether this path is visible as part of the wizard flow. * Subclasses which implement branching must override this function. * @@ -93,6 +107,11 @@ public interface AndroidStudioWizardPath { void attachToWizard(DynamicWizard dynamicWizard); /** + * Get the wizard that this path is currently attached to + */ + @Nullable DynamicWizard getWizard(); + + /** * Determine whether this path is optional or required. * Optional paths should be added to the wizard flow AFTER all required paths. * Once all remaining paths in the wizard are optional, the wizard's finish button diff --git a/android/src/com/android/tools/idea/wizard/ChooseModuleTypeStep.java b/android/src/com/android/tools/idea/wizard/ChooseModuleTypeStep.java index ce7c3fbdf56..596aa75a849 100644 --- a/android/src/com/android/tools/idea/wizard/ChooseModuleTypeStep.java +++ b/android/src/com/android/tools/idea/wizard/ChooseModuleTypeStep.java @@ -71,7 +71,7 @@ public class ChooseModuleTypeStep extends DynamicWizardStepWithHeaderAndDescript @Nullable @Contract("null->null") - private static Image iconToImage(@Nullable Icon icon) { + public static Image iconToImage(@Nullable Icon icon) { if (icon == null) { return null; } diff --git a/android/src/com/android/tools/idea/wizard/DynamicWizard.java b/android/src/com/android/tools/idea/wizard/DynamicWizard.java index c9189790adb..4ab50714631 100644 --- a/android/src/com/android/tools/idea/wizard/DynamicWizard.java +++ b/android/src/com/android/tools/idea/wizard/DynamicWizard.java @@ -216,13 +216,13 @@ public abstract class DynamicWizard implements ScopedStateStore.ScopedStoreListe */ protected final void addPath(@NotNull AndroidStudioWizardPath path) { myPaths.add(path); + path.attachToWizard(this); // If this is the first visible path, select it if (myCurrentPath == null && path.isPathVisible()) { myCurrentPath = path; } // Rebuild the iterator to avoid concurrent modification exceptions - myPathListIterator = new PathIterator(myPaths); - path.attachToWizard(this); + myPathListIterator = new PathIterator(myPaths, myCurrentPath); } /** @@ -457,6 +457,40 @@ public abstract class DynamicWizard implements ScopedStateStore.ScopedStoreListe myHost.setTitle(title); } + /** + * Returns true if a step with the given name exists in this wizard's current configuration. + * If visibleOnly is set to true, only visible steps (that are part of visible paths) will + * be considered. + */ + public boolean containsStep(@NotNull String stepName, boolean visibleOnly) { + for (AndroidStudioWizardPath path : myPaths) { + if (visibleOnly && !path.isPathVisible()) { + continue; + } + if (path.containsStep(stepName, visibleOnly)) { + return true; + } + } + return false; + } + + /** + * Navigates this wizard to the step with the given name if it exists. If not, this function + * is a no-op. If the requireVisible parameter is set to true, then only currently visible steps (which + * are part of currently visible paths) will be considered. + */ + public void navigateToNamedStep(@NotNull String stepName, boolean requireVisible) { + for (AndroidStudioWizardPath path : myPaths) { + if ((!requireVisible || path.isPathVisible()) && path.containsStep(stepName, requireVisible)) { + myCurrentPath = path; + myPathListIterator.myCurrentIndex = myPathListIterator.myList.indexOf(myCurrentPath); + myCurrentPath.navigateToNamedStep(stepName, requireVisible); + showStep(myCurrentPath.getCurrentStep()); + return; + } + } + } + protected static class PathIterator { private int myCurrentIndex; @@ -467,6 +501,14 @@ public abstract class DynamicWizard implements ScopedStateStore.ScopedStoreListe myCurrentIndex = 0; } + public PathIterator(ArrayList<AndroidStudioWizardPath> list, AndroidStudioWizardPath currentLocation) { + this(list); + int index = myList.indexOf(currentLocation); + if (currentLocation != null && index != -1) { + myCurrentIndex = index; + } + } + /** * @return a copy of this iterator */ diff --git a/android/src/com/android/tools/idea/wizard/DynamicWizardPath.java b/android/src/com/android/tools/idea/wizard/DynamicWizardPath.java index f9f663cfad2..7e3eb458def 100644 --- a/android/src/com/android/tools/idea/wizard/DynamicWizardPath.java +++ b/android/src/com/android/tools/idea/wizard/DynamicWizardPath.java @@ -86,6 +86,12 @@ public abstract class DynamicWizardPath implements ScopedStateStore.ScopedStoreL init(); } + @Nullable + @Override + public DynamicWizard getWizard() { + return myWizard; + } + /** * Set up this path. Addition of steps and other instantiations should be done here. */ @@ -398,4 +404,34 @@ public abstract class DynamicWizardPath implements ScopedStateStore.ScopedStoreL getCurrentStep().invokeUpdate(null); } } + + @Override + public boolean containsStep(@NotNull String stepName, boolean visibleOnly) { + for (DynamicWizardStep step : mySteps) { + if (visibleOnly && !step.isStepVisible()) { + continue; + } + if (stepName.equals(step.getStepName())) { + return true; + } + } + return false; + } + + @Override + public void navigateToNamedStep(@NotNull String stepName, boolean requireVisible) { + for (DynamicWizardStep step : mySteps) { + if (requireVisible && !step.isStepVisible()) { + continue; + } + if (stepName.equals(step.getStepName())) { + myCurrentStep = step; + myCurrentStepIndex = mySteps.indexOf(step); + myCurrentStep.onEnterStep(); + myCurrentStep.invokeUpdate(null); + invokeUpdate(null); + return; + } + } + } } diff --git a/android/src/com/android/tools/idea/wizard/DynamicWizardStep.java b/android/src/com/android/tools/idea/wizard/DynamicWizardStep.java index 7f6b8fc81c1..46e05672313 100644 --- a/android/src/com/android/tools/idea/wizard/DynamicWizardStep.java +++ b/android/src/com/android/tools/idea/wizard/DynamicWizardStep.java @@ -115,6 +115,14 @@ public abstract class DynamicWizardStep extends ScopedDataBinder implements Step return myPath != null ? myPath.getModule() : null; } + @Nullable + protected final DynamicWizard getWizard() { + if (myPath != null) { + return myPath.getWizard(); + } + return null; + } + /** * Optionally add an icon to the left side of the screen. * @return An icon to be displayed on the left side of the wizard. diff --git a/android/src/com/android/tools/idea/wizard/LegacyPathWrapper.java b/android/src/com/android/tools/idea/wizard/LegacyPathWrapper.java index 2071b80927f..00c96678b77 100644 --- a/android/src/com/android/tools/idea/wizard/LegacyPathWrapper.java +++ b/android/src/com/android/tools/idea/wizard/LegacyPathWrapper.java @@ -106,6 +106,27 @@ public class LegacyPathWrapper implements NewModuleDynamicPath { } @Override + public boolean containsStep(@NotNull String stepName, boolean visibleOnly) { + for (ModuleWizardStep step : mySteps) { + if (stepName.equals(step.getName())) { + return true; + } + } + return false; + } + + @Override + public void navigateToNamedStep(@NotNull String stepName, boolean requireVisible) { + for (ModuleWizardStep step : mySteps) { + if (stepName.equals(step.getName())) { + myCurrentStep = mySteps.indexOf(step); + updateWizard(); + return; + } + } + } + + @Override public boolean isPathVisible() { ModuleTemplate moduleTemplate = myWizard.getState().get(WizardConstants.SELECTED_MODULE_TYPE_KEY); return moduleTemplate != null && Iterables.contains(myTypes, moduleTemplate); @@ -127,6 +148,12 @@ public class LegacyPathWrapper implements NewModuleDynamicPath { myWizard = dynamicWizard; } + @Nullable + @Override + public DynamicWizard getWizard() { + return myWizard; + } + @Override public boolean isPathRequired() { return true; diff --git a/android/src/com/android/tools/idea/wizard/SingleStepPath.java b/android/src/com/android/tools/idea/wizard/SingleStepPath.java index 5f6161881a6..c9fac0e88a9 100644 --- a/android/src/com/android/tools/idea/wizard/SingleStepPath.java +++ b/android/src/com/android/tools/idea/wizard/SingleStepPath.java @@ -47,4 +47,17 @@ public class SingleStepPath extends DynamicWizardPath { public boolean performFinishingActions() { return true; } + + @Override + public boolean validate() { + return myStep.validate(); + } + + @Override + public boolean containsStep(@NotNull String stepName, boolean visibleOnly) { + if (visibleOnly && !isPathVisible()) { + return false; + } + return stepName.equals(myStep.getStepName()); + } } |