JAL-3048 jalview.utils.dialogrunner.DialogRunner allows sequences of runnable methods...
[jalview.git] / src / jalview / util / dialogrunner / DialogRunner.java
diff --git a/src/jalview/util/dialogrunner/DialogRunner.java b/src/jalview/util/dialogrunner/DialogRunner.java
new file mode 100644 (file)
index 0000000..fc1a73d
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.util.dialogrunner;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * daft gymnastics to allow Dialogs to extend from a Swing class and use this
+ * class to implement chained Response run() definition and execution.
+ * 
+ * There is probably a better way of doing this.
+ * 
+ * @author jprocter
+ *
+ * @param <T>
+ *          the actual dialog that will be shown - which will also initiate the
+ *          response chain.
+ */
+public class DialogRunner<T extends DialogRunnerI> implements DialogRunnerI
+{
+
+  private Map<Response, RunResponse> callbacks = new java.util.HashMap<>();
+
+  public T dialog;
+
+  public DialogRunner(T ourDialog)
+  {
+    dialog = ourDialog;
+  }
+
+  /**
+   * clear all 'was ran' flags so responses can be called again, and firstRun will
+   * trigger response execution
+   */
+  public void resetResponses()
+  {
+    for (RunResponse response : callbacks.values())
+    {
+      response.reset();
+    }
+    responses.clear();
+    firstRunWasCalled = false;
+  }
+
+  @Override
+  public T response(RunResponse action)
+  {
+    callbacks.put(action.ourTrigger, action);
+    return dialog;
+  }
+
+  /**
+   * handle a response
+   * 
+   * @param responseCode
+   */
+  public void run(int responseCode)
+  {
+    run(new Response(responseCode));
+  }
+
+  public void run(String responseString)
+  {
+    run(new Response(responseString));
+  }
+
+  public void run(Object responseObj)
+  {
+    run(new Response(responseObj));
+  }
+
+  /**
+   * start of response handling.
+   * 
+   * @param responseCode
+   */
+  public void firstRun(int responseCode)
+  {
+    doFirstRun(new Response(responseCode));
+  }
+
+  public void firstRun(String responseString)
+  {
+    doFirstRun(new Response(responseString));
+  }
+
+  public void firstRun(Object responseObj)
+  {
+    doFirstRun(new Response(responseObj));
+  }
+
+
+  boolean firstRunWasCalled = false;
+
+  private void doFirstRun(Response response)
+  {
+    if (firstRunWasCalled)
+    {
+      return;
+    }
+    firstRunWasCalled = true;
+    run(response);
+  }
+
+  private void run(Response response)
+  {
+    responses.add(response);
+    RunResponse action = callbacks.get(response);
+    if (action == null)
+    {
+      System.err.println("Doing nothing for " + response);
+      return;
+    }
+    if (action.wasRun)
+    {
+      System.err
+              .println("IMPLEMENTATION ERROR: Cycle in DialogRunner ! for "
+                      + action);
+    }
+    System.err.println("Executing action for " + response);
+    action.wasRun = true;
+    action.run();
+    if (action.returned != null)
+    {
+      run(action.returned);
+    }
+  }
+
+  List<Response> responses = new ArrayList<>();
+
+}